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