Home | History | Annotate | Line # | Download | only in opcodes
      1      1.1  christos /* Disassembler code for Renesas RX.
      2  1.1.1.9  christos    Copyright (C) 2008-2024 Free Software Foundation, Inc.
      3      1.1  christos    Contributed by Red Hat.
      4      1.1  christos    Written by DJ Delorie.
      5      1.1  christos 
      6      1.1  christos    This file is part of the GNU opcodes library.
      7      1.1  christos 
      8      1.1  christos    This library is free software; you can redistribute it and/or modify
      9      1.1  christos    it under the terms of the GNU General Public License as published by
     10      1.1  christos    the Free Software Foundation; either version 3, or (at your option)
     11      1.1  christos    any later version.
     12      1.1  christos 
     13      1.1  christos    It is distributed in the hope that it will be useful, but WITHOUT
     14      1.1  christos    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
     15      1.1  christos    or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
     16      1.1  christos    License for more details.
     17      1.1  christos 
     18      1.1  christos    You should have received a copy of the GNU General Public License
     19      1.1  christos    along with this program; if not, write to the Free Software
     20      1.1  christos    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
     21      1.1  christos    MA 02110-1301, USA.  */
     22      1.1  christos 
     23  1.1.1.2  christos #include "sysdep.h"
     24      1.1  christos #include <stdio.h>
     25      1.1  christos 
     26      1.1  christos #include "bfd.h"
     27      1.1  christos #include "dis-asm.h"
     28      1.1  christos #include "opcode/rx.h"
     29  1.1.1.7  christos #include "libiberty.h"
     30  1.1.1.7  christos #include "opintl.h"
     31      1.1  christos 
     32  1.1.1.5  christos #include <setjmp.h>
     33  1.1.1.5  christos 
     34      1.1  christos typedef struct
     35      1.1  christos {
     36      1.1  christos   bfd_vma pc;
     37      1.1  christos   disassemble_info * dis;
     38      1.1  christos } RX_Data;
     39      1.1  christos 
     40  1.1.1.5  christos struct private
     41  1.1.1.5  christos {
     42  1.1.1.5  christos   OPCODES_SIGJMP_BUF bailout;
     43  1.1.1.5  christos };
     44  1.1.1.5  christos 
     45      1.1  christos static int
     46      1.1  christos rx_get_byte (void * vdata)
     47      1.1  christos {
     48      1.1  christos   bfd_byte buf[1];
     49      1.1  christos   RX_Data *rx_data = (RX_Data *) vdata;
     50  1.1.1.5  christos   int status;
     51  1.1.1.5  christos 
     52  1.1.1.5  christos   status = rx_data->dis->read_memory_func (rx_data->pc,
     53  1.1.1.5  christos 					   buf,
     54  1.1.1.5  christos 					   1,
     55  1.1.1.5  christos 					   rx_data->dis);
     56  1.1.1.5  christos   if (status != 0)
     57  1.1.1.5  christos     {
     58  1.1.1.5  christos       struct private *priv = (struct private *) rx_data->dis->private_data;
     59      1.1  christos 
     60  1.1.1.5  christos       rx_data->dis->memory_error_func (status, rx_data->pc,
     61  1.1.1.5  christos 				       rx_data->dis);
     62  1.1.1.5  christos        OPCODES_SIGLONGJMP (priv->bailout, 1);
     63  1.1.1.5  christos     }
     64      1.1  christos 
     65      1.1  christos   rx_data->pc ++;
     66      1.1  christos   return buf[0];
     67      1.1  christos }
     68      1.1  christos 
     69  1.1.1.4  christos static char const * size_names[RX_MAX_SIZE] =
     70      1.1  christos {
     71  1.1.1.6  christos   "", ".b", ".ub", ".b", ".w", ".uw", ".w", ".a", ".l", "", "<error>"
     72      1.1  christos };
     73      1.1  christos 
     74  1.1.1.4  christos static char const * opsize_names[RX_MAX_SIZE] =
     75      1.1  christos {
     76  1.1.1.6  christos   "", ".b", ".b", ".b", ".w", ".w", ".w", ".a", ".l", ".d", "<error>"
     77      1.1  christos };
     78      1.1  christos 
     79      1.1  christos static char const * register_names[] =
     80      1.1  christos {
     81  1.1.1.7  christos   /* General registers.  */
     82      1.1  christos   "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
     83      1.1  christos   "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
     84  1.1.1.7  christos   /* Control registers.  */
     85  1.1.1.4  christos   "psw", "pc", "usp", "fpsw", NULL, NULL, NULL, NULL,
     86  1.1.1.4  christos   "bpsw", "bpc", "isp", "fintv", "intb", "extb", NULL, NULL,
     87  1.1.1.4  christos   "a0", "a1", NULL, NULL, NULL, NULL, NULL, NULL,
     88  1.1.1.8  christos   NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
     89      1.1  christos };
     90      1.1  christos 
     91      1.1  christos static char const * condition_names[] =
     92      1.1  christos {
     93  1.1.1.7  christos   /* Condition codes.  */
     94      1.1  christos   "eq", "ne", "c", "nc", "gtu", "leu", "pz", "n",
     95  1.1.1.4  christos   "ge", "lt", "gt", "le", "o", "no", "<invalid>", "<invalid>"
     96      1.1  christos };
     97      1.1  christos 
     98      1.1  christos static const char * flag_names[] =
     99      1.1  christos {
    100      1.1  christos   "c", "z", "s", "o", "", "", "", "",
    101      1.1  christos   "", "", "", "", "", "", "", "",
    102  1.1.1.8  christos   "i", "u", "", "", "", "", "", "",
    103  1.1.1.8  christos   "", "", "", "", "", "", "", ""
    104      1.1  christos };
    105      1.1  christos 
    106  1.1.1.6  christos static const char * double_register_names[] =
    107  1.1.1.6  christos {
    108  1.1.1.6  christos   "dr0", "dr1", "dr2", "dr3", "dr4", "dr5", "dr6", "dr7",
    109  1.1.1.8  christos   "dr8", "dr9", "dr10", "dr11", "dr12", "dr13", "dr14", "dr15"
    110  1.1.1.6  christos };
    111  1.1.1.6  christos 
    112  1.1.1.6  christos static const char * double_register_high_names[] =
    113  1.1.1.6  christos {
    114  1.1.1.6  christos   "drh0", "drh1", "drh2", "drh3", "drh4", "drh5", "drh6", "drh7",
    115  1.1.1.8  christos   "drh8", "drh9", "drh10", "drh11", "drh12", "drh13", "drh14", "drh15"
    116  1.1.1.6  christos };
    117  1.1.1.6  christos 
    118  1.1.1.6  christos static const char * double_register_low_names[] =
    119  1.1.1.6  christos {
    120  1.1.1.6  christos   "drl0", "drl1", "drl2", "drl3", "drl4", "drl5", "drl6", "drl7",
    121  1.1.1.8  christos   "drl8", "drl9", "drl10", "drl11", "drl12", "drl13", "drl14", "drl15"
    122  1.1.1.6  christos };
    123  1.1.1.6  christos 
    124  1.1.1.6  christos static const char * double_control_register_names[] =
    125  1.1.1.6  christos {
    126  1.1.1.8  christos   "dpsw", "dcmr", "decnt", "depc"
    127  1.1.1.6  christos };
    128  1.1.1.6  christos 
    129  1.1.1.6  christos static const char * double_condition_names[] =
    130  1.1.1.6  christos {
    131  1.1.1.8  christos   "", "un", "eq", "", "lt", "", "le"
    132  1.1.1.6  christos };
    133  1.1.1.6  christos 
    134  1.1.1.7  christos static inline const char *
    135  1.1.1.7  christos get_register_name (unsigned int reg)
    136  1.1.1.7  christos {
    137  1.1.1.7  christos   if (reg < ARRAY_SIZE (register_names))
    138  1.1.1.7  christos     return register_names[reg];
    139  1.1.1.7  christos   return _("<invalid register number>");
    140  1.1.1.7  christos }
    141  1.1.1.7  christos 
    142  1.1.1.7  christos static inline const char *
    143  1.1.1.7  christos get_condition_name (unsigned int cond)
    144  1.1.1.7  christos {
    145  1.1.1.7  christos   if (cond < ARRAY_SIZE (condition_names))
    146  1.1.1.7  christos     return condition_names[cond];
    147  1.1.1.7  christos   return _("<invalid condition code>");
    148  1.1.1.7  christos }
    149  1.1.1.7  christos 
    150  1.1.1.7  christos static inline const char *
    151  1.1.1.7  christos get_flag_name (unsigned int flag)
    152  1.1.1.7  christos {
    153  1.1.1.7  christos   if (flag < ARRAY_SIZE (flag_names))
    154  1.1.1.7  christos     return flag_names[flag];
    155  1.1.1.7  christos   return _("<invalid flag>");
    156  1.1.1.7  christos }
    157  1.1.1.7  christos 
    158  1.1.1.7  christos static inline const char *
    159  1.1.1.7  christos get_double_register_name (unsigned int reg)
    160  1.1.1.7  christos {
    161  1.1.1.7  christos   if (reg < ARRAY_SIZE (double_register_names))
    162  1.1.1.7  christos     return double_register_names[reg];
    163  1.1.1.7  christos   return _("<invalid register number>");
    164  1.1.1.7  christos }
    165  1.1.1.7  christos 
    166  1.1.1.7  christos static inline const char *
    167  1.1.1.7  christos get_double_register_high_name (unsigned int reg)
    168  1.1.1.7  christos {
    169  1.1.1.7  christos   if (reg < ARRAY_SIZE (double_register_high_names))
    170  1.1.1.7  christos     return double_register_high_names[reg];
    171  1.1.1.7  christos   return _("<invalid register number>");
    172  1.1.1.7  christos }
    173  1.1.1.7  christos 
    174  1.1.1.7  christos static inline const char *
    175  1.1.1.7  christos get_double_register_low_name (unsigned int reg)
    176  1.1.1.7  christos {
    177  1.1.1.7  christos   if (reg < ARRAY_SIZE (double_register_low_names))
    178  1.1.1.7  christos     return double_register_low_names[reg];
    179  1.1.1.7  christos   return _("<invalid register number>");
    180  1.1.1.7  christos }
    181  1.1.1.7  christos 
    182  1.1.1.7  christos static inline const char *
    183  1.1.1.7  christos get_double_control_register_name (unsigned int reg)
    184  1.1.1.7  christos {
    185  1.1.1.7  christos   if (reg < ARRAY_SIZE (double_control_register_names))
    186  1.1.1.7  christos     return double_control_register_names[reg];
    187  1.1.1.7  christos   return _("<invalid register number>");
    188  1.1.1.7  christos }
    189  1.1.1.7  christos 
    190  1.1.1.7  christos static inline const char *
    191  1.1.1.7  christos get_double_condition_name (unsigned int cond)
    192  1.1.1.7  christos {
    193  1.1.1.7  christos   if (cond < ARRAY_SIZE (double_condition_names))
    194  1.1.1.7  christos     return double_condition_names[cond];
    195  1.1.1.7  christos   return _("<invalid condition code>");
    196  1.1.1.7  christos }
    197  1.1.1.7  christos 
    198  1.1.1.7  christos static inline const char *
    199  1.1.1.7  christos get_opsize_name (unsigned int opsize)
    200  1.1.1.7  christos {
    201  1.1.1.7  christos   if (opsize < ARRAY_SIZE (opsize_names))
    202  1.1.1.7  christos     return opsize_names[opsize];
    203  1.1.1.7  christos   return _("<invalid opsize>");
    204  1.1.1.7  christos }
    205  1.1.1.7  christos 
    206  1.1.1.7  christos static inline const char *
    207  1.1.1.7  christos get_size_name (unsigned int size)
    208  1.1.1.7  christos {
    209  1.1.1.7  christos   if (size < ARRAY_SIZE (size_names))
    210  1.1.1.7  christos     return size_names[size];
    211  1.1.1.7  christos   return _("<invalid size>");
    212  1.1.1.7  christos }
    213  1.1.1.7  christos 
    214  1.1.1.7  christos 
    215      1.1  christos int
    216      1.1  christos print_insn_rx (bfd_vma addr, disassemble_info * dis)
    217      1.1  christos {
    218      1.1  christos   int rv;
    219      1.1  christos   RX_Data rx_data;
    220      1.1  christos   RX_Opcode_Decoded opcode;
    221      1.1  christos   const char * s;
    222  1.1.1.5  christos   struct private priv;
    223      1.1  christos 
    224  1.1.1.8  christos   dis->private_data = &priv;
    225      1.1  christos   rx_data.pc = addr;
    226      1.1  christos   rx_data.dis = dis;
    227      1.1  christos 
    228  1.1.1.5  christos   if (OPCODES_SIGSETJMP (priv.bailout) != 0)
    229  1.1.1.5  christos     {
    230  1.1.1.5  christos       /* Error return.  */
    231  1.1.1.5  christos       return -1;
    232  1.1.1.5  christos     }
    233  1.1.1.5  christos 
    234      1.1  christos   rv = rx_decode_opcode (addr, &opcode, rx_get_byte, &rx_data);
    235      1.1  christos 
    236      1.1  christos   dis->bytes_per_line = 10;
    237      1.1  christos 
    238      1.1  christos #define PR (dis->fprintf_func)
    239      1.1  christos #define PS (dis->stream)
    240      1.1  christos #define PC(c) PR (PS, "%c", c)
    241      1.1  christos 
    242  1.1.1.4  christos   /* Detect illegal instructions.  */
    243  1.1.1.4  christos   if (opcode.op[0].size == RX_Bad_Size
    244  1.1.1.4  christos       || register_names [opcode.op[0].reg] == NULL
    245  1.1.1.4  christos       || register_names [opcode.op[1].reg] == NULL
    246  1.1.1.4  christos       || register_names [opcode.op[2].reg] == NULL)
    247  1.1.1.4  christos     {
    248  1.1.1.4  christos       bfd_byte buf[10];
    249  1.1.1.4  christos       int i;
    250  1.1.1.4  christos 
    251  1.1.1.4  christos       PR (PS, ".byte ");
    252  1.1.1.4  christos       rx_data.dis->read_memory_func (rx_data.pc - rv, buf, rv, rx_data.dis);
    253  1.1.1.4  christos 
    254  1.1.1.4  christos       for (i = 0 ; i < rv; i++)
    255  1.1.1.4  christos 	PR (PS, "0x%02x ", buf[i]);
    256  1.1.1.4  christos       return rv;
    257  1.1.1.4  christos     }
    258  1.1.1.4  christos 
    259      1.1  christos   for (s = opcode.syntax; *s; s++)
    260      1.1  christos     {
    261      1.1  christos       if (*s != '%')
    262      1.1  christos 	{
    263      1.1  christos 	  PC (*s);
    264      1.1  christos 	}
    265      1.1  christos       else
    266      1.1  christos 	{
    267      1.1  christos 	  RX_Opcode_Operand * oper;
    268      1.1  christos 	  int do_size = 0;
    269      1.1  christos 	  int do_hex = 0;
    270      1.1  christos 	  int do_addr = 0;
    271      1.1  christos 
    272      1.1  christos 	  s ++;
    273      1.1  christos 
    274      1.1  christos 	  if (*s == 'S')
    275      1.1  christos 	    {
    276      1.1  christos 	      do_size = 1;
    277      1.1  christos 	      s++;
    278      1.1  christos 	    }
    279      1.1  christos 	  if (*s == 'x')
    280      1.1  christos 	    {
    281      1.1  christos 	      do_hex = 1;
    282      1.1  christos 	      s++;
    283      1.1  christos 	    }
    284      1.1  christos 	  if (*s == 'a')
    285      1.1  christos 	    {
    286      1.1  christos 	      do_addr = 1;
    287      1.1  christos 	      s++;
    288      1.1  christos 	    }
    289      1.1  christos 
    290      1.1  christos 	  switch (*s)
    291      1.1  christos 	    {
    292      1.1  christos 	    case '%':
    293      1.1  christos 	      PC ('%');
    294      1.1  christos 	      break;
    295      1.1  christos 
    296      1.1  christos 	    case 's':
    297  1.1.1.7  christos 	      PR (PS, "%s", get_opsize_name (opcode.size));
    298      1.1  christos 	      break;
    299      1.1  christos 
    300  1.1.1.6  christos 	    case 'b':
    301  1.1.1.6  christos 	      s ++;
    302  1.1.1.7  christos 	      if (*s == 'f')
    303  1.1.1.7  christos 		{
    304  1.1.1.7  christos 		  int imm = opcode.op[2].addend;
    305  1.1.1.7  christos 		  int slsb, dlsb, width;
    306  1.1.1.7  christos 
    307  1.1.1.7  christos 		  dlsb = (imm >> 5) & 0x1f;
    308  1.1.1.7  christos 		  slsb = (imm & 0x1f);
    309  1.1.1.7  christos 		  slsb = (slsb >= 0x10?(slsb ^ 0x1f) + 1:slsb);
    310  1.1.1.7  christos 		  slsb = dlsb - slsb;
    311  1.1.1.7  christos 		  slsb = (slsb < 0?-slsb:slsb);
    312  1.1.1.7  christos 		  width = ((imm >> 10) & 0x1f) - dlsb;
    313  1.1.1.7  christos 		  PR (PS, "#%d, #%d, #%d, %s, %s",
    314  1.1.1.7  christos 		      slsb, dlsb, width,
    315  1.1.1.7  christos 		      get_register_name (opcode.op[1].reg),
    316  1.1.1.7  christos 		      get_register_name (opcode.op[0].reg));
    317  1.1.1.7  christos 		}
    318  1.1.1.6  christos 	      break;
    319      1.1  christos 	    case '0':
    320      1.1  christos 	    case '1':
    321      1.1  christos 	    case '2':
    322  1.1.1.7  christos 	      oper = opcode.op + (*s - '0');
    323      1.1  christos 	      if (do_size)
    324      1.1  christos 		{
    325  1.1.1.4  christos 		  if (oper->type == RX_Operand_Indirect || oper->type == RX_Operand_Zero_Indirect)
    326  1.1.1.7  christos 		    PR (PS, "%s", get_size_name (oper->size));
    327      1.1  christos 		}
    328      1.1  christos 	      else
    329      1.1  christos 		switch (oper->type)
    330      1.1  christos 		  {
    331      1.1  christos 		  case RX_Operand_Immediate:
    332      1.1  christos 		    if (do_addr)
    333      1.1  christos 		      dis->print_address_func (oper->addend, dis);
    334      1.1  christos 		    else if (do_hex
    335      1.1  christos 			     || oper->addend > 999
    336      1.1  christos 			     || oper->addend < -999)
    337      1.1  christos 		      PR (PS, "%#x", oper->addend);
    338      1.1  christos 		    else
    339      1.1  christos 		      PR (PS, "%d", oper->addend);
    340      1.1  christos 		    break;
    341      1.1  christos 		  case RX_Operand_Register:
    342      1.1  christos 		  case RX_Operand_TwoReg:
    343  1.1.1.7  christos 		    PR (PS, "%s", get_register_name (oper->reg));
    344      1.1  christos 		    break;
    345      1.1  christos 		  case RX_Operand_Indirect:
    346  1.1.1.7  christos 		    PR (PS, "%d[%s]", oper->addend, get_register_name (oper->reg));
    347  1.1.1.4  christos 		    break;
    348  1.1.1.4  christos 		  case RX_Operand_Zero_Indirect:
    349  1.1.1.7  christos 		    PR (PS, "[%s]", get_register_name (oper->reg));
    350      1.1  christos 		    break;
    351      1.1  christos 		  case RX_Operand_Postinc:
    352  1.1.1.7  christos 		    PR (PS, "[%s+]", get_register_name (oper->reg));
    353      1.1  christos 		    break;
    354      1.1  christos 		  case RX_Operand_Predec:
    355  1.1.1.7  christos 		    PR (PS, "[-%s]", get_register_name (oper->reg));
    356      1.1  christos 		    break;
    357      1.1  christos 		  case RX_Operand_Condition:
    358  1.1.1.7  christos 		    PR (PS, "%s", get_condition_name (oper->reg));
    359      1.1  christos 		    break;
    360      1.1  christos 		  case RX_Operand_Flag:
    361  1.1.1.7  christos 		    PR (PS, "%s", get_flag_name (oper->reg));
    362      1.1  christos 		    break;
    363  1.1.1.6  christos 		  case RX_Operand_DoubleReg:
    364  1.1.1.7  christos 		    PR (PS, "%s", get_double_register_name (oper->reg));
    365  1.1.1.6  christos 		    break;
    366  1.1.1.6  christos 		  case RX_Operand_DoubleRegH:
    367  1.1.1.7  christos 		    PR (PS, "%s", get_double_register_high_name (oper->reg));
    368  1.1.1.6  christos 		    break;
    369  1.1.1.6  christos 		  case RX_Operand_DoubleRegL:
    370  1.1.1.7  christos 		    PR (PS, "%s", get_double_register_low_name (oper->reg));
    371  1.1.1.6  christos 		    break;
    372  1.1.1.6  christos 		  case RX_Operand_DoubleCReg:
    373  1.1.1.7  christos 		    PR (PS, "%s", get_double_control_register_name (oper->reg));
    374  1.1.1.6  christos 		    break;
    375  1.1.1.6  christos 		  case RX_Operand_DoubleCond:
    376  1.1.1.7  christos 		    PR (PS, "%s", get_double_condition_name (oper->reg));
    377  1.1.1.6  christos 		    break;
    378      1.1  christos 		  default:
    379      1.1  christos 		    PR (PS, "[???]");
    380      1.1  christos 		    break;
    381      1.1  christos 		  }
    382      1.1  christos 	    }
    383      1.1  christos 	}
    384      1.1  christos     }
    385      1.1  christos 
    386      1.1  christos   return rv;
    387      1.1  christos }
    388