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