Home | History | Annotate | Download | only in opcodes
      1 /* Disassembler code for Renesas RX.
      2    Copyright (C) 2008-2014 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 
     30 typedef struct
     31 {
     32   bfd_vma pc;
     33   disassemble_info * dis;
     34 } RX_Data;
     35 
     36 static int
     37 rx_get_byte (void * vdata)
     38 {
     39   bfd_byte buf[1];
     40   RX_Data *rx_data = (RX_Data *) vdata;
     41 
     42   rx_data->dis->read_memory_func (rx_data->pc,
     43 				  buf,
     44 				  1,
     45 				  rx_data->dis);
     46 
     47   rx_data->pc ++;
     48   return buf[0];
     49 }
     50 
     51 static char const * size_names[] =
     52 {
     53   "", ".b", ".ub", ".b", ".w", ".uw", ".w", ".a", ".l"
     54 };
     55 
     56 static char const * opsize_names[] =
     57 {
     58   "", ".b", ".b", ".b", ".w", ".w", ".w", ".a", ".l"
     59 };
     60 
     61 static char const * register_names[] =
     62 {
     63   /* general registers */
     64   "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
     65   "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
     66   /* control register */
     67   "psw", "pc", "usp", "fpsw", "", "", "", "wr",
     68   "bpsw", "bpc", "isp", "fintv", "intb", "", "", "",
     69   "pbp", "pben", "", "", "", "", "", "",
     70   "bbpsw", "bbpc", "", "", "", "", "", ""
     71 };
     72 
     73 static char const * condition_names[] =
     74 {
     75   /* condition codes */
     76   "eq", "ne", "c", "nc", "gtu", "leu", "pz", "n",
     77   "ge", "lt", "gt", "le", "o", "no", "always", "never"
     78 };
     79 
     80 static const char * flag_names[] =
     81 {
     82   "c", "z", "s", "o", "", "", "", "",
     83   "", "", "", "", "", "", "", "",
     84   "i", "u", "", "", "", "", "", ""
     85   "", "", "", "", "", "", "", "",
     86 };
     87 
     88 int
     89 print_insn_rx (bfd_vma addr, disassemble_info * dis)
     90 {
     91   int rv;
     92   RX_Data rx_data;
     93   RX_Opcode_Decoded opcode;
     94   const char * s;
     95 
     96   rx_data.pc = addr;
     97   rx_data.dis = dis;
     98 
     99   rv = rx_decode_opcode (addr, &opcode, rx_get_byte, &rx_data);
    100 
    101   dis->bytes_per_line = 10;
    102 
    103 #define PR (dis->fprintf_func)
    104 #define PS (dis->stream)
    105 #define PC(c) PR (PS, "%c", c)
    106 
    107   for (s = opcode.syntax; *s; s++)
    108     {
    109       if (*s != '%')
    110 	{
    111 	  PC (*s);
    112 	}
    113       else
    114 	{
    115 	  RX_Opcode_Operand * oper;
    116 	  int do_size = 0;
    117 	  int do_hex = 0;
    118 	  int do_addr = 0;
    119 
    120 	  s ++;
    121 
    122 	  if (*s == 'S')
    123 	    {
    124 	      do_size = 1;
    125 	      s++;
    126 	    }
    127 	  if (*s == 'x')
    128 	    {
    129 	      do_hex = 1;
    130 	      s++;
    131 	    }
    132 	  if (*s == 'a')
    133 	    {
    134 	      do_addr = 1;
    135 	      s++;
    136 	    }
    137 
    138 	  switch (*s)
    139 	    {
    140 	    case '%':
    141 	      PC ('%');
    142 	      break;
    143 
    144 	    case 's':
    145 	      PR (PS, "%s", opsize_names[opcode.size]);
    146 	      break;
    147 
    148 	    case '0':
    149 	    case '1':
    150 	    case '2':
    151 	      oper = opcode.op + *s - '0';
    152 	      if (do_size)
    153 		{
    154 		  if (oper->type == RX_Operand_Indirect)
    155 		    PR (PS, "%s", size_names[oper->size]);
    156 		}
    157 	      else
    158 		switch (oper->type)
    159 		  {
    160 		  case RX_Operand_Immediate:
    161 		    if (do_addr)
    162 		      dis->print_address_func (oper->addend, dis);
    163 		    else if (do_hex
    164 			     || oper->addend > 999
    165 			     || oper->addend < -999)
    166 		      PR (PS, "%#x", oper->addend);
    167 		    else
    168 		      PR (PS, "%d", oper->addend);
    169 		    break;
    170 		  case RX_Operand_Register:
    171 		  case RX_Operand_TwoReg:
    172 		    PR (PS, "%s", register_names[oper->reg]);
    173 		    break;
    174 		  case RX_Operand_Indirect:
    175 		    if (oper->addend)
    176 		      PR (PS, "%d[%s]", oper->addend, register_names[oper->reg]);
    177 		    else
    178 		      PR (PS, "[%s]", register_names[oper->reg]);
    179 		    break;
    180 		  case RX_Operand_Postinc:
    181 		    PR (PS, "[%s+]", register_names[oper->reg]);
    182 		    break;
    183 		  case RX_Operand_Predec:
    184 		    PR (PS, "[-%s]", register_names[oper->reg]);
    185 		    break;
    186 		  case RX_Operand_Condition:
    187 		    PR (PS, "%s", condition_names[oper->reg]);
    188 		    break;
    189 		  case RX_Operand_Flag:
    190 		    PR (PS, "%s", flag_names[oper->reg]);
    191 		    break;
    192 		  default:
    193 		    PR (PS, "[???]");
    194 		    break;
    195 		  }
    196 	    }
    197 	}
    198     }
    199 
    200   return rv;
    201 }
    202