1 /* s12z-dis.c -- Freescale S12Z disassembly
2 Copyright (C) 2018-2022 Free Software Foundation, Inc.
4 This file is part of the GNU opcodes library.
6 This library is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3, or (at your option)
11 It is distributed in the hope that it will be useful, but WITHOUT
12 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
14 License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
19 MA 02110-1301, USA. */
27 #include "opcode/s12z.h"
30 #include "disassemble.h"
34 struct mem_read_abstraction
36 struct mem_read_abstraction_base base;
38 struct disassemble_info* info;
42 advance (struct mem_read_abstraction_base *b)
44 struct mem_read_abstraction *mra = (struct mem_read_abstraction *) b;
49 posn (struct mem_read_abstraction_base *b)
51 struct mem_read_abstraction *mra = (struct mem_read_abstraction *) b;
56 abstract_read_memory (struct mem_read_abstraction_base *b,
58 size_t n, bfd_byte *bytes)
60 struct mem_read_abstraction *mra = (struct mem_read_abstraction *) b;
62 int status = (*mra->info->read_memory_func) (mra->memaddr + offset,
65 (*mra->info->memory_error_func) (status, mra->memaddr + offset,
67 return status != 0 ? -1 : 0;
70 /* Start of disassembly file. */
71 const struct reg registers[S12Z_N_REGISTERS] =
93 static const char *mnemonics[] =
98 "tbne", "tbeq", "tbpl", "tbmi", "tbgt", "tble",
99 "dbne", "dbeq", "dbpl", "dbmi", "dbgt", "dble",
194 operand_separator (struct disassemble_info *info)
196 if ((info->flags & 0x2))
197 (*info->fprintf_func) (info->stream, ",");
199 (*info->fprintf_func) (info->stream, " ");
204 /* Render the symbol name whose value is ADDR + BASE or the adddress itself if
205 there is no symbol. If BASE is non zero, then the a PC relative adddress is
206 assumend (ie BASE is the value in the PC. */
208 decode_possible_symbol (bfd_signed_vma addr, bfd_vma base,
209 struct disassemble_info *info, bool relative)
211 const char *fmt = relative ? "*%+" PRId64 : "%" PRId64;
212 asymbol *sym = info->symbol_at_address_func (addr + base, info);
215 (*info->fprintf_func) (info->stream, fmt, (int64_t) addr);
217 (*info->fprintf_func) (info->stream, "%s", bfd_asymbol_name (sym));
221 /* Emit the disassembled text for OPR */
223 opr_emit_disassembly (const struct operand *opr,
224 struct disassemble_info *info)
226 operand_separator (info);
230 case OPND_CL_IMMEDIATE:
231 (*info->fprintf_func) (info->stream, "#%d",
232 ((struct immediate_operand *) opr)->value);
234 case OPND_CL_REGISTER:
236 int r = ((struct register_operand*) opr)->reg;
238 if (r < 0 || r >= S12Z_N_REGISTERS)
239 (*info->fprintf_func) (info->stream, _("<illegal reg num>"));
241 (*info->fprintf_func) (info->stream, "%s", registers[r].name);
244 case OPND_CL_REGISTER_ALL16:
245 (*info->fprintf_func) (info->stream, "%s", "ALL16b");
247 case OPND_CL_REGISTER_ALL:
248 (*info->fprintf_func) (info->stream, "%s", "ALL");
250 case OPND_CL_BIT_FIELD:
251 (*info->fprintf_func) (info->stream, "#%d:%d",
252 ((struct bitfield_operand*)opr)->width,
253 ((struct bitfield_operand*)opr)->offset);
255 case OPND_CL_SIMPLE_MEMORY:
257 struct simple_memory_operand *mo =
258 (struct simple_memory_operand *) opr;
259 decode_possible_symbol (mo->addr, mo->base, info, mo->relative);
265 struct memory_operand *mo = (struct memory_operand *) opr;
266 (*info->fprintf_func) (info->stream, "%c", mo->indirect ? '[' : '(');
269 assert (mo->mutation == OPND_RM_NONE || mo->n_regs == 1);
270 switch (mo->mutation)
272 case OPND_RM_PRE_DEC:
275 case OPND_RM_PRE_INC:
278 case OPND_RM_POST_DEC:
281 case OPND_RM_POST_INC:
287 (*info->fprintf_func) (info->stream, (mo->n_regs == 0) ? "%d" : "%d,", mo->base_offset);
295 if (r < 0 || r >= S12Z_N_REGISTERS)
296 (*info->fprintf_func) (info->stream, fmt, _("<illegal reg num>"));
298 (*info->fprintf_func) (info->stream, fmt, registers[r].name);
302 if (mo->n_regs > used_reg)
304 int r = mo->regs[used_reg];
306 if (r < 0 || r >= S12Z_N_REGISTERS)
307 (*info->fprintf_func) (info->stream, _("<illegal reg num>"));
309 (*info->fprintf_func) (info->stream, ",%s",
313 (*info->fprintf_func) (info->stream, "%c",
314 mo->indirect ? ']' : ')');
320 #define S12Z_N_SIZES 4
321 static const char shift_size_table[S12Z_N_SIZES] =
327 print_insn_s12z (bfd_vma memaddr, struct disassemble_info* info)
330 enum optr operator = OP_INVALID;
333 /* The longest instruction in S12Z can have 6 operands.
334 (Most have 3 or less. Only PSH and PUL have so many. */
335 struct operand *operands[6];
337 struct mem_read_abstraction mra;
338 mra.base.read = (void *) abstract_read_memory ;
339 mra.base.advance = advance ;
340 mra.base.posn = posn;
341 mra.memaddr = memaddr;
346 decode_s12z (&operator, &osize, &n_operands, operands,
347 (struct mem_read_abstraction_base *) &mra);
349 (info->fprintf_func) (info->stream, "%s", mnemonics[(long)operator]);
351 /* Ship out size sufficies for those instructions which
357 for (o = 0; o < n_operands; ++o)
359 if (operands[o] && operands[o]->osize != -1)
363 (*mra.info->fprintf_func) (mra.info->stream, "%c", '.');
367 osize = operands[o]->osize;
369 if (osize < 0 || osize >= S12Z_N_SIZES)
370 (*mra.info->fprintf_func) (mra.info->stream, _("<bad>"));
372 (*mra.info->fprintf_func) (mra.info->stream, "%c",
373 shift_size_table[osize]);
379 if (osize < 0 || osize >= S12Z_N_SIZES)
380 (*mra.info->fprintf_func) (mra.info->stream, _(".<bad>"));
382 (*mra.info->fprintf_func) (mra.info->stream, ".%c",
383 shift_size_table[osize]);
386 /* Ship out the operands. */
387 for (o = 0; o < n_operands; ++o)
390 opr_emit_disassembly (operands[o], mra.info);