Home | History | Annotate | Download | only in opcodes
      1 /* Disassembler code for Renesas RL78.
      2    Copyright (C) 2011-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/rl78.h"
     29 
     30 #define DEBUG_SEMANTICS 0
     31 
     32 typedef struct
     33 {
     34   bfd_vma pc;
     35   disassemble_info * dis;
     36 } RL78_Data;
     37 
     38 static int
     39 rl78_get_byte (void * vdata)
     40 {
     41   bfd_byte buf[1];
     42   RL78_Data *rl78_data = (RL78_Data *) vdata;
     43 
     44   rl78_data->dis->read_memory_func (rl78_data->pc,
     45 				  buf,
     46 				  1,
     47 				  rl78_data->dis);
     48 
     49   rl78_data->pc ++;
     50   return buf[0];
     51 }
     52 
     53 static char const *
     54 register_names[] =
     55 {
     56   "",
     57   "x", "a", "c", "b", "e", "d", "l", "h",
     58   "ax", "bc", "de", "hl",
     59   "sp", "psw", "cs", "es", "pmc", "mem"
     60 };
     61 
     62 static char const *
     63 condition_names[] =
     64 {
     65   "t", "f", "c", "nc", "h", "nh", "z", "nz"
     66 };
     67 
     68 static int
     69 indirect_type (int t)
     70 {
     71   switch (t)
     72     {
     73     case RL78_Operand_Indirect:
     74     case RL78_Operand_BitIndirect:
     75     case RL78_Operand_PostInc:
     76     case RL78_Operand_PreDec:
     77       return 1;
     78     default:
     79       return 0;
     80     }
     81 }
     82 
     83 int
     84 print_insn_rl78 (bfd_vma addr, disassemble_info * dis)
     85 {
     86   int rv;
     87   RL78_Data rl78_data;
     88   RL78_Opcode_Decoded opcode;
     89   const char * s;
     90 #if DEBUG_SEMANTICS
     91   static char buf[200];
     92 #endif
     93 
     94   rl78_data.pc = addr;
     95   rl78_data.dis = dis;
     96 
     97   rv = rl78_decode_opcode (addr, &opcode, rl78_get_byte, &rl78_data);
     98 
     99   dis->bytes_per_line = 10;
    100 
    101 #define PR (dis->fprintf_func)
    102 #define PS (dis->stream)
    103 #define PC(c) PR (PS, "%c", c)
    104 
    105   s = opcode.syntax;
    106 
    107 #if DEBUG_SEMANTICS
    108 
    109   switch (opcode.id)
    110     {
    111     case RLO_unknown: s = "uknown"; break;
    112     case RLO_add: s = "add: %e0%0 += %e1%1"; break;
    113     case RLO_addc: s = "addc: %e0%0 += %e1%1 + CY"; break;
    114     case RLO_and: s = "and: %e0%0 &= %e1%1"; break;
    115     case RLO_branch: s = "branch: pc = %e0%0"; break;
    116     case RLO_branch_cond: s = "branch_cond: pc = %e0%0 if %c1 / %e1%1"; break;
    117     case RLO_branch_cond_clear: s = "branch_cond_clear: pc = %e0%0 if %c1 / %e1%1, %e1%1 = 0"; break;
    118     case RLO_call: s = "call: pc = %e1%0"; break;
    119     case RLO_cmp: s = "cmp: %e0%0 - %e1%1"; break;
    120     case RLO_mov: s = "mov: %e0%0 = %e1%1"; break;
    121     case RLO_or: s = "or: %e0%0 |= %e1%1"; break;
    122     case RLO_rol: s = "rol: %e0%0 <<= %e1%1"; break;
    123     case RLO_rolc: s = "rol: %e0%0 <<= %e1%1,CY"; break;
    124     case RLO_ror: s = "ror: %e0%0 >>= %e1%1"; break;
    125     case RLO_rorc: s = "ror: %e0%0 >>= %e1%1,CY"; break;
    126     case RLO_sar: s = "sar: %e0%0 >>= %e1%1 signed"; break;
    127     case RLO_sel: s = "sel: rb = %1"; break;
    128     case RLO_shr: s = "shr: %e0%0 >>= %e1%1 unsigned"; break;
    129     case RLO_shl: s = "shl: %e0%0 <<= %e1%1"; break;
    130     case RLO_skip: s = "skip: if %c1"; break;
    131     case RLO_sub: s = "sub: %e0%0 -= %e1%1"; break;
    132     case RLO_subc: s = "subc: %e0%0 -= %e1%1 - CY"; break;
    133     case RLO_xch: s = "xch: %e0%0 <-> %e1%1"; break;
    134     case RLO_xor: s = "xor: %e0%0 ^= %e1%1"; break;
    135     }
    136 
    137   sprintf(buf, "%s%%W%%f\t\033[32m%s\033[0m", s, opcode.syntax);
    138   s = buf;
    139 
    140 #endif
    141 
    142   for (; *s; s++)
    143     {
    144       if (*s != '%')
    145 	{
    146 	  PC (*s);
    147 	}
    148       else
    149 	{
    150 	  RL78_Opcode_Operand * oper;
    151 	  int do_hex = 0;
    152 	  int do_addr = 0;
    153 	  int do_es = 0;
    154 	  int do_sfr = 0;
    155 	  int do_cond = 0;
    156 	  int do_bang = 0;
    157 
    158 	  while (1)
    159 	    {
    160 	      s ++;
    161 	      switch (*s)
    162 		{
    163 		case 'x':
    164 		  do_hex = 1;
    165 		  break;
    166 		case '!':
    167 		  do_bang = 1;
    168 		  break;
    169 		case 'e':
    170 		  do_es = 1;
    171 		  break;
    172 		case 'a':
    173 		  do_addr = 1;
    174 		  break;
    175 		case 's':
    176 		  do_sfr = 1;
    177 		  break;
    178 		case 'c':
    179 		  do_cond = 1;
    180 		  break;
    181 		default:
    182 		  goto no_more_modifiers;
    183 		}
    184 	    }
    185 	no_more_modifiers:;
    186 
    187 	  switch (*s)
    188 	    {
    189 	    case '%':
    190 	      PC ('%');
    191 	      break;
    192 
    193 #if DEBUG_SEMANTICS
    194 
    195 	    case 'W':
    196 	      if (opcode.size == RL78_Word)
    197 		PR (PS, " \033[33mW\033[0m");
    198 	      break;
    199 
    200 	    case 'f':
    201 	      if (opcode.flags)
    202 		{
    203 		  char *comma = "";
    204 		  PR (PS, "  \033[35m");
    205 
    206 		  if (opcode.flags & RL78_PSW_Z)
    207 		    { PR (PS, "Z"); comma = ","; }
    208 		  if (opcode.flags & RL78_PSW_AC)
    209 		    { PR (PS, "%sAC", comma); comma = ","; }
    210 		  if (opcode.flags & RL78_PSW_CY)
    211 		    { PR (PS, "%sCY", comma); comma = ","; }
    212 		  PR (PS, "\033[0m");
    213 		}
    214 	      break;
    215 
    216 #endif
    217 
    218 	    case '0':
    219 	    case '1':
    220 	      oper = *s == '0' ? &opcode.op[0] : &opcode.op[1];
    221 	    if (do_es)
    222 	      {
    223 		if (oper->use_es && indirect_type (oper->type))
    224 		  PR (PS, "es:");
    225 	      }
    226 
    227 	    if (do_bang)
    228 	      PC ('!');
    229 
    230 	    if (do_cond)
    231 	      {
    232 		PR (PS, "%s", condition_names[oper->condition]);
    233 		break;
    234 	      }
    235 
    236 	    switch (oper->type)
    237 	      {
    238 	      case RL78_Operand_Immediate:
    239 		if (do_addr)
    240 		  dis->print_address_func (oper->addend, dis);
    241 		else if (do_hex
    242 			 || oper->addend > 999
    243 			 || oper->addend < -999)
    244 		  PR (PS, "%#x", oper->addend);
    245 		else
    246 		  PR (PS, "%d", oper->addend);
    247 		break;
    248 
    249 	      case RL78_Operand_Register:
    250 		PR (PS, "%s", register_names[oper->reg]);
    251 		break;
    252 
    253 	      case RL78_Operand_Bit:
    254 		PR (PS, "%s.%d", register_names[oper->reg], oper->bit_number);
    255 		break;
    256 
    257 	      case RL78_Operand_Indirect:
    258 	      case RL78_Operand_BitIndirect:
    259 		switch (oper->reg)
    260 		  {
    261 		  case RL78_Reg_None:
    262 		    if (oper->addend == 0xffffa && do_sfr && opcode.size == RL78_Byte)
    263 		      PR (PS, "psw");
    264 		    else if (oper->addend == 0xffff8 && do_sfr && opcode.size == RL78_Word)
    265 		      PR (PS, "sp");
    266 		    else if (oper->addend >= 0xffe20)
    267 		      PR (PS, "%#x", oper->addend);
    268 		    else
    269 		      {
    270 			int faddr = oper->addend;
    271 			if (do_es && ! oper->use_es)
    272 			  faddr += 0xf0000;
    273 			dis->print_address_func (faddr, dis);
    274 		      }
    275 		    break;
    276 
    277 		  case RL78_Reg_B:
    278 		  case RL78_Reg_C:
    279 		  case RL78_Reg_BC:
    280 		    PR (PS, "%d[%s]", oper->addend, register_names[oper->reg]);
    281 		    break;
    282 
    283 		  default:
    284 		    PR (PS, "[%s", register_names[oper->reg]);
    285 		    if (oper->reg2 != RL78_Reg_None)
    286 		      PR (PS, "+%s", register_names[oper->reg2]);
    287 		    if (oper->addend)
    288 		      PR (PS, "+%d", oper->addend);
    289 		    PC (']');
    290 		    break;
    291 
    292 		  }
    293 		if (oper->type == RL78_Operand_BitIndirect)
    294 		  PR (PS, ".%d", oper->bit_number);
    295 		break;
    296 
    297 #if DEBUG_SEMANTICS
    298 		/* Shouldn't happen - push and pop don't print
    299 		   [SP] directly.  But we *do* use them for
    300 		   semantic debugging.  */
    301 	      case RL78_Operand_PostInc:
    302 		PR (PS, "[%s++]", register_names[oper->reg]);
    303 		break;
    304 	      case RL78_Operand_PreDec:
    305 		PR (PS, "[--%s]", register_names[oper->reg]);
    306 		break;
    307 #endif
    308 
    309 	      default:
    310 		/* If we ever print this, that means the
    311 		   programmer tried to print an operand with a
    312 		   type we don't expect.  Print the line and
    313 		   operand number from rl78-decode.opc for
    314 		   them.  */
    315 		PR (PS, "???%d.%d", opcode.lineno, *s - '0');
    316 		break;
    317 	      }
    318 	    }
    319 	}
    320     }
    321 
    322 #if DEBUG_SEMANTICS
    323 
    324   PR (PS, "\t\033[34m(line %d)\033[0m", opcode.lineno);
    325 
    326 #endif
    327 
    328   return rv;
    329 }
    330