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