Home | History | Annotate | Download | only in opcodes
      1 /* Disassemble h8500 instructions.
      2    Copyright (C) 1993-2014 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 
     24 #define DISASSEMBLER_TABLE
     25 #define DEFINE_TABLE
     26 
     27 #include "h8500-opc.h"
     28 #include "dis-asm.h"
     29 #include "opintl.h"
     30 
     31 /* Maximum length of an instruction.  */
     32 #define MAXLEN 8
     33 
     34 #include <setjmp.h>
     35 
     36 struct private
     37 {
     38   /* Points to first byte not fetched.  */
     39   bfd_byte *max_fetched;
     40   bfd_byte the_buffer[MAXLEN];
     41   bfd_vma insn_start;
     42   OPCODES_SIGJMP_BUF bailout;
     43 };
     44 
     45 /* Make sure that bytes from INFO->PRIVATE_DATA->BUFFER (inclusive)
     46    to ADDR (exclusive) are valid.  Returns 1 for success, longjmps
     47    on error.  */
     48 #define FETCH_DATA(info, addr) \
     49   ((addr) <= ((struct private *)(info->private_data))->max_fetched \
     50    ? 1 : fetch_data ((info), (addr)))
     51 
     52 static int
     53 fetch_data (struct disassemble_info *info, bfd_byte *addr)
     54 {
     55   int status;
     56   struct private *priv = (struct private *) info->private_data;
     57   bfd_vma start = priv->insn_start + (priv->max_fetched - priv->the_buffer);
     58 
     59   status = (*info->read_memory_func) (start,
     60 				      priv->max_fetched,
     61 				      addr - priv->max_fetched,
     62 				      info);
     63   if (status != 0)
     64     {
     65       (*info->memory_error_func) (status, start, info);
     66       OPCODES_SIGLONGJMP (priv->bailout, 1);
     67     }
     68   else
     69     priv->max_fetched = addr;
     70   return 1;
     71 }
     72 
     73 static char *crname[] = { "sr", "ccr", "*", "br", "ep", "dp", "*", "tp" };
     74 
     75 int
     76 print_insn_h8500 (bfd_vma addr, disassemble_info *info)
     77 {
     78   const h8500_opcode_info *opcode;
     79   void *stream = info->stream;
     80   fprintf_ftype func = info->fprintf_func;
     81   struct private priv;
     82   bfd_byte *buffer = priv.the_buffer;
     83 
     84   info->private_data = (PTR) & priv;
     85   priv.max_fetched = priv.the_buffer;
     86   priv.insn_start = addr;
     87   if (OPCODES_SIGSETJMP (priv.bailout) != 0)
     88     /* Error return.  */
     89     return -1;
     90 
     91   /* Run down the table to find the one which matches.  */
     92   for (opcode = h8500_table; opcode->name; opcode++)
     93     {
     94       int byte;
     95       int rn = 0;
     96       int rd = 0;
     97       int rs = 0;
     98       int disp = 0;
     99       int abs_val = 0;
    100       int imm = 0;
    101       int pcrel = 0;
    102       int qim = 0;
    103       int i;
    104       int cr = 0;
    105 
    106       for (byte = 0; byte < opcode->length; byte++)
    107 	{
    108 	  FETCH_DATA (info, buffer + byte + 1);
    109 	  if ((buffer[byte] & opcode->bytes[byte].mask)
    110 	      != (opcode->bytes[byte].contents))
    111 	    goto next;
    112 
    113 	  else
    114 	    {
    115 	      /* Extract any info parts.  */
    116 	      switch (opcode->bytes[byte].insert)
    117 		{
    118 		case 0:
    119 		case FP:
    120 		  break;
    121 		default:
    122 		  /* xgettext:c-format */
    123 		  func (stream, _("can't cope with insert %d\n"),
    124 			opcode->bytes[byte].insert);
    125 		  break;
    126 		case RN:
    127 		  rn = buffer[byte] & 0x7;
    128 		  break;
    129 		case RS:
    130 		  rs = buffer[byte] & 0x7;
    131 		  break;
    132 		case CRB:
    133 		  cr = buffer[byte] & 0x7;
    134 		  if (cr == 0)
    135 		    goto next;
    136 		  break;
    137 		case CRW:
    138 		  cr = buffer[byte] & 0x7;
    139 		  if (cr != 0)
    140 		    goto next;
    141 		  break;
    142 		case DISP16:
    143 		  FETCH_DATA (info, buffer + byte + 2);
    144 		  disp = (buffer[byte] << 8) | (buffer[byte + 1]);
    145 		  break;
    146 		case FPIND_D8:
    147 		case DISP8:
    148 		  disp = ((char) (buffer[byte]));
    149 		  break;
    150 		case RD:
    151 		case RDIND:
    152 		  rd = buffer[byte] & 0x7;
    153 		  break;
    154 		case ABS24:
    155 		  FETCH_DATA (info, buffer + byte + 3);
    156 		  abs_val =
    157 		    (buffer[byte] << 16)
    158 		    | (buffer[byte + 1] << 8)
    159 		    | (buffer[byte + 2]);
    160 		  break;
    161 		case ABS16:
    162 		  FETCH_DATA (info, buffer + byte + 2);
    163 		  abs_val = (buffer[byte] << 8) | (buffer[byte + 1]);
    164 		  break;
    165 		case ABS8:
    166 		  abs_val = (buffer[byte]);
    167 		  break;
    168 		case IMM16:
    169 		  FETCH_DATA (info, buffer + byte + 2);
    170 		  imm = (buffer[byte] << 8) | (buffer[byte + 1]);
    171 		  break;
    172 		case IMM4:
    173 		  imm = (buffer[byte]) & 0xf;
    174 		  break;
    175 		case IMM8:
    176 		case RLIST:
    177 		  imm = (buffer[byte]);
    178 		  break;
    179 		case PCREL16:
    180 		  FETCH_DATA (info, buffer + byte + 2);
    181 		  pcrel = (buffer[byte] << 8) | (buffer[byte + 1]);
    182 		  break;
    183 		case PCREL8:
    184 		  pcrel = (buffer[byte]);
    185 		  break;
    186 		case QIM:
    187 		  switch (buffer[byte] & 0x7)
    188 		    {
    189 		    case 0:
    190 		      qim = 1;
    191 		      break;
    192 		    case 1:
    193 		      qim = 2;
    194 		      break;
    195 		    case 4:
    196 		      qim = -1;
    197 		      break;
    198 		    case 5:
    199 		      qim = -2;
    200 		      break;
    201 		    }
    202 		  break;
    203 
    204 		}
    205 	    }
    206 	}
    207       /* We get here when all the masks have passed so we can output
    208 	 the operands.  */
    209       FETCH_DATA (info, buffer + opcode->length);
    210       (func) (stream, "%s\t", opcode->name);
    211       for (i = 0; i < opcode->nargs; i++)
    212 	{
    213 	  if (i)
    214 	    (func) (stream, ",");
    215 	  switch (opcode->arg_type[i])
    216 	    {
    217 	    case FP:
    218 	      func (stream, "fp");
    219 	      break;
    220 	    case RNIND_D16:
    221 	      func (stream, "@(0x%x:16,r%d)", disp, rn);
    222 	      break;
    223 	    case RNIND_D8:
    224 	      func (stream, "@(0x%x:8 (%d),r%d)", disp & 0xff, disp, rn);
    225 	      break;
    226 	    case RDIND_D16:
    227 	      func (stream, "@(0x%x:16,r%d)", disp, rd);
    228 	      break;
    229 	    case RDIND_D8:
    230 	      func (stream, "@(0x%x:8 (%d), r%d)", disp & 0xff, disp, rd);
    231 	      break;
    232 	    case FPIND_D8:
    233 	      func (stream, "@(0x%x:8 (%d), fp)", disp & 0xff, disp);
    234 	      break;
    235 	    case CRB:
    236 	    case CRW:
    237 	      func (stream, "%s", crname[cr]);
    238 	      break;
    239 	    case RN:
    240 	      func (stream, "r%d", rn);
    241 	      break;
    242 	    case RD:
    243 	      func (stream, "r%d", rd);
    244 	      break;
    245 	    case RS:
    246 	      func (stream, "r%d", rs);
    247 	      break;
    248 	    case RNDEC:
    249 	      func (stream, "@-r%d", rn);
    250 	      break;
    251 	    case RNINC:
    252 	      func (stream, "@r%d+", rn);
    253 	      break;
    254 	    case RNIND:
    255 	      func (stream, "@r%d", rn);
    256 	      break;
    257 	    case RDIND:
    258 	      func (stream, "@r%d", rd);
    259 	      break;
    260 	    case SPINC:
    261 	      func (stream, "@sp+");
    262 	      break;
    263 	    case SPDEC:
    264 	      func (stream, "@-sp");
    265 	      break;
    266 	    case ABS24:
    267 	      func (stream, "@0x%0x:24", abs_val);
    268 	      break;
    269 	    case ABS16:
    270 	      func (stream, "@0x%0x:16", abs_val & 0xffff);
    271 	      break;
    272 	    case ABS8:
    273 	      func (stream, "@0x%0x:8", abs_val & 0xff);
    274 	      break;
    275 	    case IMM16:
    276 	      func (stream, "#0x%0x:16", imm & 0xffff);
    277 	      break;
    278 	    case RLIST:
    279 	      {
    280 		int j;
    281 		int nc = 0;
    282 
    283 		func (stream, "(");
    284 		for (j = 0; j < 8; j++)
    285 		  {
    286 		    if (imm & (1 << j))
    287 		      {
    288 			func (stream, "r%d", j);
    289 			if (nc)
    290 			  func (stream, ",");
    291 			nc = 1;
    292 		      }
    293 		  }
    294 		func (stream, ")");
    295 	      }
    296 	      break;
    297 	    case IMM8:
    298 	      func (stream, "#0x%0x:8", imm & 0xff);
    299 	      break;
    300 	    case PCREL16:
    301 	      func (stream, "0x%0x:16",
    302 		    (int)(pcrel + addr + opcode->length) & 0xffff);
    303 	      break;
    304 	    case PCREL8:
    305 	      func (stream, "#0x%0x:8",
    306 		    (int)((char) pcrel + addr + opcode->length) & 0xffff);
    307 	      break;
    308 	    case QIM:
    309 	      func (stream, "#%d:q", qim);
    310 	      break;
    311 	    case IMM4:
    312 	      func (stream, "#%d:4", imm);
    313 	      break;
    314 	    }
    315 	}
    316       return opcode->length;
    317     next:
    318       ;
    319     }
    320 
    321   /* Couldn't understand anything.  */
    322   /* xgettext:c-format */
    323   func (stream, _("%02x\t\t*unknown*"), buffer[0]);
    324   return 1;
    325 }
    326