1 /* s12z-dis.c -- Freescale S12Z disassembly
2 Copyright (C) 2018-2019 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. */
23 #include "bfd_stdint.h"
27 #include "opcode/s12z.h"
32 #include "disassemble.h"
36 struct mem_read_abstraction
38 struct mem_read_abstraction_base base;
40 struct disassemble_info* info;
44 advance (struct mem_read_abstraction_base *b)
46 struct mem_read_abstraction *mra = (struct mem_read_abstraction *) b;
51 posn (struct mem_read_abstraction_base *b)
53 struct mem_read_abstraction *mra = (struct mem_read_abstraction *) b;
58 abstract_read_memory (struct mem_read_abstraction_base *b,
60 size_t n, bfd_byte *bytes)
62 struct mem_read_abstraction *mra = (struct mem_read_abstraction *) b;
65 (*mra->info->read_memory_func) (mra->memaddr + offset,
70 (*mra->info->memory_error_func) (status, mra->memaddr, mra->info);
76 /* Start of disassembly file. */
77 const struct reg registers[S12Z_N_REGISTERS] =
99 static const char *mnemonics[] =
104 "tbne", "tbeq", "tbpl", "tbmi", "tbgt", "tble",
105 "dbne", "dbeq", "dbpl", "dbmi", "dbgt", "dble",
200 operand_separator (struct disassemble_info *info)
202 if ((info->flags & 0x2))
203 (*info->fprintf_func) (info->stream, ",");
205 (*info->fprintf_func) (info->stream, " ");
210 /* Render the symbol name whose value is ADDR + BASE or the adddress itself if
211 there is no symbol. If BASE is non zero, then the a PC relative adddress is
212 assumend (ie BASE is the value in the PC. */
214 decode_possible_symbol (bfd_vma addr, bfd_vma base,
215 struct disassemble_info *info, bool relative)
217 const char *fmt = relative ? "*%+" BFD_VMA_FMT "d" : "%" BFD_VMA_FMT "d";
218 if (!info->symbol_at_address_func (addr + base, info))
220 (*info->fprintf_func) (info->stream, fmt, addr);
226 for (j = 0; j < info->symtab_size; ++j)
228 sym = info->symtab[j];
229 if (bfd_asymbol_value (sym) == addr + base)
234 if (j < info->symtab_size)
235 (*info->fprintf_func) (info->stream, "%s", bfd_asymbol_name (sym));
237 (*info->fprintf_func) (info->stream, fmt, addr);
242 /* Emit the disassembled text for OPR */
244 opr_emit_disassembly (const struct operand *opr,
245 struct disassemble_info *info)
247 operand_separator (info);
251 case OPND_CL_IMMEDIATE:
252 (*info->fprintf_func) (info->stream, "#%d",
253 ((struct immediate_operand *) opr)->value);
255 case OPND_CL_REGISTER:
257 int r = ((struct register_operand*) opr)->reg;
258 (*info->fprintf_func) (info->stream, "%s", registers[r].name);
261 case OPND_CL_REGISTER_ALL16:
262 (*info->fprintf_func) (info->stream, "%s", "ALL16b");
264 case OPND_CL_REGISTER_ALL:
265 (*info->fprintf_func) (info->stream, "%s", "ALL");
267 case OPND_CL_BIT_FIELD:
268 (*info->fprintf_func) (info->stream, "#%d:%d",
269 ((struct bitfield_operand*)opr)->width,
270 ((struct bitfield_operand*)opr)->offset);
272 case OPND_CL_SIMPLE_MEMORY:
274 struct simple_memory_operand *mo =
275 (struct simple_memory_operand *) opr;
276 decode_possible_symbol (mo->addr, mo->base, info, mo->relative);
282 struct memory_operand *mo = (struct memory_operand *) opr;
283 (*info->fprintf_func) (info->stream, "%c", mo->indirect ? '[' : '(');
286 assert (mo->mutation == OPND_RM_NONE || mo->n_regs == 1);
287 switch (mo->mutation)
289 case OPND_RM_PRE_DEC:
292 case OPND_RM_PRE_INC:
295 case OPND_RM_POST_DEC:
298 case OPND_RM_POST_INC:
304 (*info->fprintf_func) (info->stream, (mo->n_regs == 0) ? "%d" : "%d,", mo->base_offset);
309 (*info->fprintf_func) (info->stream, fmt,
310 registers[mo->regs[0]].name);
313 if (mo->n_regs > used_reg)
315 (*info->fprintf_func) (info->stream, ",%s",
316 registers[mo->regs[used_reg]].name);
319 (*info->fprintf_func) (info->stream, "%c",
320 mo->indirect ? ']' : ')');
326 static const char shift_size_table[] = {
331 print_insn_s12z (bfd_vma memaddr, struct disassemble_info* info)
334 enum operator operator = OP_INVALID;
337 /* The longest instruction in S12Z can have 6 operands.
338 (Most have 3 or less. Only PSH and PUL have so many. */
339 struct operand *operands[6];
341 struct mem_read_abstraction mra;
342 mra.base.read = (void *) abstract_read_memory ;
343 mra.base.advance = advance ;
344 mra.base.posn = posn;
345 mra.memaddr = memaddr;
350 decode_s12z (&operator, &osize, &n_operands, operands,
351 (struct mem_read_abstraction_base *) &mra);
353 (info->fprintf_func) (info->stream, "%s", mnemonics[(long)operator]);
355 /* Ship out size sufficies for those instructions which
360 for (o = 0; o < n_operands; ++o)
362 if (operands[o] && operands[o]->osize != -1)
366 (*mra.info->fprintf_func) (mra.info->stream, "%c", '.');
369 (*mra.info->fprintf_func) (mra.info->stream, "%c",
370 shift_size_table[operands[o]->osize]);
376 (*mra.info->fprintf_func) (mra.info->stream, ".%c",
377 shift_size_table[osize]);
381 /* Ship out the operands. */
382 for (o = 0; o < n_operands; ++o)
385 opr_emit_disassembly (operands[o], mra.info);