Home | History | Annotate | Line # | Download | only in opcodes
s12z-dis.c revision 1.1.1.2.2.1
      1 /* s12z-dis.c -- Freescale S12Z disassembly
      2    Copyright (C) 2018-2022 Free Software Foundation, Inc.
      3 
      4    This file is part of the GNU opcodes library.
      5 
      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)
      9    any later version.
     10 
     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.
     15 
     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.  */
     20 
     21 #include "sysdep.h"
     22 #include <stdio.h>
     23 #include <stdint.h>
     24 #include <stdbool.h>
     25 #include <assert.h>
     26 
     27 #include "opcode/s12z.h"
     28 #include "bfd.h"
     29 #include "dis-asm.h"
     30 #include "disassemble.h"
     31 #include "s12z-opc.h"
     32 #include "opintl.h"
     33 
     34 struct mem_read_abstraction
     35 {
     36   struct mem_read_abstraction_base base;
     37   bfd_vma memaddr;
     38   struct disassemble_info* info;
     39 };
     40 
     41 static void
     42 advance (struct mem_read_abstraction_base *b)
     43 {
     44   struct mem_read_abstraction *mra = (struct mem_read_abstraction *) b;
     45   mra->memaddr ++;
     46 }
     47 
     48 static bfd_vma
     49 posn (struct mem_read_abstraction_base *b)
     50 {
     51   struct mem_read_abstraction *mra = (struct mem_read_abstraction *) b;
     52   return mra->memaddr;
     53 }
     54 
     55 static int
     56 abstract_read_memory (struct mem_read_abstraction_base *b,
     57 		      int offset,
     58 		      size_t n, bfd_byte *bytes)
     59 {
     60   struct mem_read_abstraction *mra = (struct mem_read_abstraction *) b;
     61 
     62   int status = (*mra->info->read_memory_func) (mra->memaddr + offset,
     63 					       bytes, n, mra->info);
     64   if (status != 0)
     65     (*mra->info->memory_error_func) (status, mra->memaddr + offset,
     66                                      mra->info);
     67   return status != 0 ? -1 : 0;
     68 }
     69 
     70 /* Start of disassembly file.  */
     71 const struct reg registers[S12Z_N_REGISTERS] =
     72   {
     73     {"d2", 2},
     74     {"d3", 2},
     75     {"d4", 2},
     76     {"d5", 2},
     77 
     78     {"d0", 1},
     79     {"d1", 1},
     80 
     81     {"d6", 4},
     82     {"d7", 4},
     83 
     84     {"x", 3},
     85     {"y", 3},
     86     {"s", 3},
     87     {"p", 3},
     88     {"cch", 1},
     89     {"ccl", 1},
     90     {"ccw", 2}
     91   };
     92 
     93 static const char *mnemonics[] =
     94   {
     95     "!!invalid!!",
     96     "psh",
     97     "pul",
     98     "tbne", "tbeq", "tbpl", "tbmi", "tbgt", "tble",
     99     "dbne", "dbeq", "dbpl", "dbmi", "dbgt", "dble",
    100     "sex",
    101     "exg",
    102     "lsl", "lsr",
    103     "asl", "asr",
    104     "rol", "ror",
    105     "bfins", "bfext",
    106 
    107     "trap",
    108 
    109     "ld",
    110     "st",
    111     "cmp",
    112 
    113     "stop",
    114     "wai",
    115     "sys",
    116 
    117     "minu",
    118     "mins",
    119     "maxu",
    120     "maxs",
    121 
    122     "abs",
    123     "adc",
    124     "bit",
    125     "sbc",
    126     "rti",
    127     "clb",
    128     "eor",
    129 
    130     "sat",
    131 
    132     "nop",
    133     "bgnd",
    134     "brclr",
    135     "brset",
    136     "rts",
    137     "lea",
    138     "mov",
    139 
    140     "bra",
    141     "bsr",
    142     "bhi",
    143     "bls",
    144     "bcc",
    145     "bcs",
    146     "bne",
    147     "beq",
    148     "bvc",
    149     "bvs",
    150     "bpl",
    151     "bmi",
    152     "bge",
    153     "blt",
    154     "bgt",
    155     "ble",
    156     "inc",
    157     "clr",
    158     "dec",
    159 
    160     "add",
    161     "sub",
    162     "and",
    163     "or",
    164 
    165     "tfr",
    166     "jmp",
    167     "jsr",
    168     "com",
    169     "andcc",
    170     "neg",
    171     "orcc",
    172     "bclr",
    173     "bset",
    174     "btgl",
    175     "swi",
    176 
    177     "mulu",
    178     "divu",
    179     "modu",
    180     "macu",
    181     "qmulu",
    182 
    183     "muls",
    184     "divs",
    185     "mods",
    186     "macs",
    187     "qmuls",
    188 
    189     NULL
    190   };
    191 
    192 
    193 static void
    194 operand_separator (struct disassemble_info *info)
    195 {
    196   if ((info->flags & 0x2))
    197     (*info->fprintf_func) (info->stream, ",");
    198 
    199   (*info->fprintf_func) (info->stream, " ");
    200 
    201   info->flags |= 0x2;
    202 }
    203 
    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.  */
    207 static void
    208 decode_possible_symbol (bfd_signed_vma addr, bfd_vma base,
    209                         struct disassemble_info *info, bool relative)
    210 {
    211   const char *fmt = relative ? "*%+" PRId64 : "%" PRId64;
    212   asymbol *sym = info->symbol_at_address_func (addr + base, info);
    213 
    214   if (!sym)
    215     (*info->fprintf_func) (info->stream, fmt, (int64_t) addr);
    216   else
    217     (*info->fprintf_func) (info->stream, "%s", bfd_asymbol_name (sym));
    218 }
    219 
    220 
    221 /* Emit the disassembled text for OPR */
    222 static void
    223 opr_emit_disassembly (const struct operand *opr,
    224 		      struct disassemble_info *info)
    225 {
    226   operand_separator (info);
    227 
    228   switch (opr->cl)
    229     {
    230     case OPND_CL_IMMEDIATE:
    231       (*info->fprintf_func) (info->stream, "#%d",
    232 			     ((struct immediate_operand *) opr)->value);
    233       break;
    234     case OPND_CL_REGISTER:
    235       {
    236         int r = ((struct register_operand*) opr)->reg;
    237 
    238 	if (r < 0 || r >= S12Z_N_REGISTERS)
    239 	  (*info->fprintf_func) (info->stream, _("<illegal reg num>"));
    240 	else
    241 	  (*info->fprintf_func) (info->stream, "%s", registers[r].name);
    242       }
    243       break;
    244     case OPND_CL_REGISTER_ALL16:
    245       (*info->fprintf_func) (info->stream, "%s", "ALL16b");
    246       break;
    247     case OPND_CL_REGISTER_ALL:
    248       (*info->fprintf_func) (info->stream, "%s", "ALL");
    249       break;
    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);
    254       break;
    255     case OPND_CL_SIMPLE_MEMORY:
    256       {
    257         struct simple_memory_operand *mo =
    258 	  (struct simple_memory_operand *) opr;
    259 	decode_possible_symbol (mo->addr, mo->base, info, mo->relative);
    260       }
    261       break;
    262     case OPND_CL_MEMORY:
    263       {
    264         int used_reg = 0;
    265         struct memory_operand *mo = (struct memory_operand *) opr;
    266 	(*info->fprintf_func) (info->stream, "%c", mo->indirect ? '[' : '(');
    267 
    268 	const char *fmt;
    269 	assert (mo->mutation == OPND_RM_NONE || mo->n_regs == 1);
    270 	switch (mo->mutation)
    271 	  {
    272 	  case OPND_RM_PRE_DEC:
    273 	    fmt = "-%s";
    274 	    break;
    275 	  case OPND_RM_PRE_INC:
    276 	    fmt = "+%s";
    277 	    break;
    278 	  case OPND_RM_POST_DEC:
    279 	    fmt = "%s-";
    280 	    break;
    281 	  case OPND_RM_POST_INC:
    282 	    fmt = "%s+";
    283 	    break;
    284 	  case OPND_RM_NONE:
    285 	  default:
    286 	    if (mo->n_regs < 2)
    287 	      (*info->fprintf_func) (info->stream, (mo->n_regs == 0) ? "%d" : "%d,", mo->base_offset);
    288 	    fmt = "%s";
    289 	    break;
    290 	  }
    291 	if (mo->n_regs > 0)
    292 	  {
    293 	    int r = mo->regs[0];
    294 
    295 	    if (r < 0 || r >= S12Z_N_REGISTERS)
    296 	      (*info->fprintf_func) (info->stream, fmt, _("<illegal reg num>"));
    297 	    else
    298 	      (*info->fprintf_func) (info->stream, fmt, registers[r].name);
    299 	  }
    300 	used_reg = 1;
    301 
    302         if (mo->n_regs > used_reg)
    303           {
    304 	    int r = mo->regs[used_reg];
    305 
    306 	    if (r < 0 || r >= S12Z_N_REGISTERS)
    307 	      (*info->fprintf_func) (info->stream, _("<illegal reg num>"));
    308 	    else
    309 	      (*info->fprintf_func) (info->stream, ",%s",
    310 				     registers[r].name);
    311           }
    312 
    313 	(*info->fprintf_func) (info->stream, "%c",
    314 			       mo->indirect ? ']' : ')');
    315       }
    316       break;
    317     };
    318 }
    319 
    320 #define S12Z_N_SIZES 4
    321 static const char shift_size_table[S12Z_N_SIZES] =
    322 {
    323   'b', 'w', 'p', 'l'
    324 };
    325 
    326 int
    327 print_insn_s12z (bfd_vma memaddr, struct disassemble_info* info)
    328 {
    329   int o;
    330   enum optr operator = OP_INVALID;
    331   int n_operands = 0;
    332 
    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];
    336 
    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;
    342   mra.info = info;
    343 
    344   short osize = -1;
    345   int n_bytes =
    346     decode_s12z (&operator, &osize, &n_operands, operands,
    347 		 (struct mem_read_abstraction_base *) &mra);
    348 
    349   (info->fprintf_func) (info->stream, "%s", mnemonics[(long)operator]);
    350 
    351   /* Ship out size sufficies for those instructions which
    352      need them.  */
    353   if (osize == -1)
    354     {
    355       bool suffix = false;
    356 
    357       for (o = 0; o < n_operands; ++o)
    358 	{
    359 	  if (operands[o] && operands[o]->osize != -1)
    360 	    {
    361 	      if (!suffix)
    362 		{
    363 		  (*mra.info->fprintf_func) (mra.info->stream, "%c", '.');
    364 		  suffix = true;
    365 		}
    366 
    367 	      osize = operands[o]->osize;
    368 
    369 	      if (osize < 0 || osize >= S12Z_N_SIZES)
    370 		(*mra.info->fprintf_func) (mra.info->stream, _("<bad>"));
    371 	      else
    372 		(*mra.info->fprintf_func) (mra.info->stream, "%c",
    373 					   shift_size_table[osize]);
    374 	    }
    375 	}
    376     }
    377   else
    378     {
    379       if (osize < 0 || osize >= S12Z_N_SIZES)
    380 	(*mra.info->fprintf_func) (mra.info->stream, _(".<bad>"));
    381       else
    382 	(*mra.info->fprintf_func) (mra.info->stream, ".%c",
    383 				   shift_size_table[osize]);
    384     }
    385 
    386   /* Ship out the operands.  */
    387   for (o = 0; o < n_operands; ++o)
    388     {
    389       if (operands[o])
    390 	opr_emit_disassembly (operands[o], mra.info);
    391       free (operands[o]);
    392     }
    393 
    394   return n_bytes;
    395 }
    396