00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #define DEFINE_TABLE
00024
00025 #include "sysdep.h"
00026 #define h8_opcodes h8ops
00027 #include "opcode/h8300.h"
00028 #include "dis-asm.h"
00029 #include "opintl.h"
00030 #include "libiberty.h"
00031
00032 struct h8_instruction
00033 {
00034 int length;
00035 const struct h8_opcode *opcode;
00036 };
00037
00038 struct h8_instruction *h8_instructions;
00039
00040 static void bfd_h8_disassemble_init PARAMS ((void));
00041 static void print_one_arg PARAMS ((disassemble_info *, bfd_vma, op_type,
00042 int, int, int, int, const char **, int));
00043 static unsigned int bfd_h8_disassemble PARAMS ((bfd_vma,
00044 disassemble_info *,
00045 int));
00046 static void extract_immediate PARAMS ((FILE *,
00047 op_type, int,
00048 unsigned char *,
00049 int *, int *,
00050 const struct h8_opcode *));
00051
00052
00053
00054
00055 static void
00056 bfd_h8_disassemble_init ()
00057 {
00058 unsigned int i;
00059 unsigned int nopcodes;
00060 const struct h8_opcode *p;
00061 struct h8_instruction *pi;
00062
00063 nopcodes = sizeof (h8_opcodes) / sizeof (struct h8_opcode);
00064
00065 h8_instructions = (struct h8_instruction *)
00066 xmalloc (nopcodes * sizeof (struct h8_instruction));
00067
00068 for (p = h8_opcodes, pi = h8_instructions; p->name; p++, pi++)
00069 {
00070 int n1 = 0;
00071 int n2 = 0;
00072
00073 if ((int) p->data.nib[0] < 16)
00074 n1 = (int) p->data.nib[0];
00075 else
00076 n1 = 0;
00077
00078 if ((int) p->data.nib[1] < 16)
00079 n2 = (int) p->data.nib[1];
00080 else
00081 n2 = 0;
00082
00083
00084
00085 for (i = 0; p->data.nib[i] != (op_type) E; i++)
00086 ;
00087
00088 if (i & 1)
00089 {
00090 fprintf (stderr, "Internal error, h8_disassemble_init.\n");
00091 abort ();
00092 }
00093
00094 pi->length = i / 2;
00095 pi->opcode = p;
00096 }
00097
00098
00099 pi->length = 0;
00100 pi->opcode = p;
00101 }
00102
00103 static void
00104 extract_immediate (stream, looking_for, thisnib, data, cst, len, q)
00105 FILE *stream;
00106 op_type looking_for;
00107 int thisnib;
00108 unsigned char *data;
00109 int *cst, *len;
00110 const struct h8_opcode *q;
00111 {
00112 switch (looking_for & SIZE)
00113 {
00114 case L_2:
00115 *len = 2;
00116 *cst = thisnib & 3;
00117
00118
00119 if ((looking_for & MODE) == DISP)
00120 {
00121 if (OP_KIND (q->how) == O_MOVAB ||
00122 OP_KIND (q->how) == O_MOVAW ||
00123 OP_KIND (q->how) == O_MOVAL)
00124 {
00125
00126 switch (q->args.nib[0] & MODE) {
00127 case INDEXB:
00128 default:
00129 break;
00130 case INDEXW:
00131 *cst *= 2;
00132 break;
00133 case INDEXL:
00134 *cst *= 4;
00135 break;
00136 }
00137 }
00138 else
00139 {
00140
00141 switch (OP_SIZE (q->how)) {
00142 default: break;
00143 case SW:
00144 *cst *= 2;
00145 break;
00146 case SL:
00147 *cst *= 4;
00148 break;
00149 }
00150 }
00151 }
00152 break;
00153 case L_8:
00154 *len = 8;
00155 *cst = data[0];
00156 break;
00157 case L_16:
00158 case L_16U:
00159 *len = 16;
00160 *cst = (data[0] << 8) + data [1];
00161 #if 0
00162 if ((looking_for & SIZE) == L_16)
00163 *cst = (short) *cst;
00164 #endif
00165 break;
00166 case L_32:
00167 *len = 32;
00168 *cst = (data[0] << 24) + (data[1] << 16) + (data[2] << 8) + data[3];
00169 break;
00170 default:
00171 *len = 0;
00172 *cst = 0;
00173 fprintf (stream, "DISP bad size\n");
00174 break;
00175 }
00176 }
00177
00178 static const char *regnames[] =
00179 {
00180 "r0h", "r1h", "r2h", "r3h", "r4h", "r5h", "r6h", "r7h",
00181 "r0l", "r1l", "r2l", "r3l", "r4l", "r5l", "r6l", "r7l"
00182 };
00183 static const char *wregnames[] =
00184 {
00185 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
00186 "e0", "e1", "e2", "e3", "e4", "e5", "e6", "e7"
00187 };
00188 static const char *lregnames[] =
00189 {
00190 "er0", "er1", "er2", "er3", "er4", "er5", "er6", "er7",
00191 "er0", "er1", "er2", "er3", "er4", "er5", "er6", "er7"
00192 };
00193 static const char *cregnames[] =
00194 {
00195 "ccr", "exr", "mach", "macl", "", "", "vbr", "sbr"
00196 };
00197
00198 static void
00199 print_one_arg (info, addr, x, cst, cstlen, rdisp_n, rn, pregnames, len)
00200 disassemble_info *info;
00201 bfd_vma addr;
00202 op_type x;
00203 int cst, cstlen, rdisp_n, rn;
00204 const char **pregnames;
00205 int len;
00206 {
00207 void *stream = info->stream;
00208 fprintf_ftype outfn = info->fprintf_func;
00209
00210 if ((x & SIZE) == L_3 ||
00211 (x & SIZE) == L_3NZ)
00212 {
00213 outfn (stream, "#0x%x", (unsigned) cst);
00214 }
00215 else if ((x & MODE) == IMM)
00216 {
00217 outfn (stream, "#0x%x", (unsigned) cst);
00218 }
00219 else if ((x & MODE) == DBIT ||
00220 (x & MODE) == KBIT)
00221 {
00222 outfn (stream, "#%d", (unsigned) cst);
00223 }
00224 else if ((x & MODE) == CONST_2)
00225 outfn (stream, "#2");
00226 else if ((x & MODE) == CONST_4)
00227 outfn (stream, "#4");
00228 else if ((x & MODE) == CONST_8)
00229 outfn (stream, "#8");
00230 else if ((x & MODE) == CONST_16)
00231 outfn (stream, "#16");
00232 else if ((x & MODE) == REG)
00233 {
00234 switch (x & SIZE)
00235 {
00236 case L_8:
00237 outfn (stream, "%s", regnames[rn]);
00238 break;
00239 case L_16:
00240 case L_16U:
00241 outfn (stream, "%s", wregnames[rn]);
00242 break;
00243 case L_P:
00244 case L_32:
00245 outfn (stream, "%s", lregnames[rn]);
00246 break;
00247 }
00248 }
00249 else if ((x & MODE) == LOWREG)
00250 {
00251 switch (x & SIZE)
00252 {
00253 case L_8:
00254
00255 outfn (stream, "%s.b", regnames[rn < 8 ? rn + 8 : rn]);
00256 break;
00257 case L_16:
00258 case L_16U:
00259
00260 outfn (stream, "%s.w", wregnames[rn < 8 ? rn : rn - 8]);
00261 break;
00262 case L_P:
00263 case L_32:
00264 outfn (stream, "%s.l", lregnames[rn]);
00265 break;
00266 }
00267 }
00268 else if ((x & MODE) == POSTINC)
00269 {
00270 outfn (stream, "@%s+", pregnames[rn]);
00271 }
00272 else if ((x & MODE) == POSTDEC)
00273 {
00274 outfn (stream, "@%s-", pregnames[rn]);
00275 }
00276 else if ((x & MODE) == PREINC)
00277 {
00278 outfn (stream, "@+%s", pregnames[rn]);
00279 }
00280 else if ((x & MODE) == PREDEC)
00281 {
00282 outfn (stream, "@-%s", pregnames[rn]);
00283 }
00284 else if ((x & MODE) == IND)
00285 {
00286 outfn (stream, "@%s", pregnames[rn]);
00287 }
00288 else if ((x & MODE) == ABS || (x & ABSJMP))
00289 {
00290 outfn (stream, "@0x%x:%d", (unsigned) cst, cstlen);
00291 }
00292 else if ((x & MODE) == MEMIND)
00293 {
00294 outfn (stream, "@@%d (0x%x)", cst, cst);
00295 }
00296 else if ((x & MODE) == VECIND)
00297 {
00298
00299
00300
00301 int offset = (cst + 0x80) * 4;
00302 outfn (stream, "@@%d (0x%x)", offset, offset);
00303 }
00304 else if ((x & MODE) == PCREL)
00305 {
00306 if ((x & SIZE) == L_16 ||
00307 (x & SIZE) == L_16U)
00308 {
00309 outfn (stream, ".%s%d (0x%x)",
00310 (short) cst > 0 ? "+" : "",
00311 (short) cst,
00312 addr + (short) cst + len);
00313 }
00314 else
00315 {
00316 outfn (stream, ".%s%d (0x%x)",
00317 (char) cst > 0 ? "+" : "",
00318 (char) cst,
00319 addr + (char) cst + len);
00320 }
00321 }
00322 else if ((x & MODE) == DISP)
00323 {
00324 outfn (stream, "@(0x%x:%d,%s)", cst, cstlen,
00325 pregnames[rdisp_n]);
00326 }
00327 else if ((x & MODE) == INDEXB)
00328 {
00329
00330 outfn (stream, "@(0x%x:%d,%s.b)", cst, cstlen,
00331 regnames[rdisp_n < 8 ? rdisp_n + 8 : rdisp_n]);
00332 }
00333 else if ((x & MODE) == INDEXW)
00334 {
00335
00336 outfn (stream, "@(0x%x:%d,%s.w)", cst, cstlen,
00337 wregnames[rdisp_n < 8 ? rdisp_n : rdisp_n - 8]);
00338 }
00339 else if ((x & MODE) == INDEXL)
00340 {
00341 outfn (stream, "@(0x%x:%d,%s.l)", cst, cstlen,
00342 lregnames[rdisp_n]);
00343 }
00344 else if (x & CTRL)
00345 {
00346 outfn (stream, cregnames[rn]);
00347 }
00348 else if ((x & MODE) == CCR)
00349 {
00350 outfn (stream, "ccr");
00351 }
00352 else if ((x & MODE) == EXR)
00353 {
00354 outfn (stream, "exr");
00355 }
00356 else if ((x & MODE) == MACREG)
00357 {
00358 outfn (stream, "mac%c", cst ? 'l' : 'h');
00359 }
00360 else
00361
00362 outfn (stream, _("Hmmmm 0x%x"), x);
00363 }
00364
00365 static unsigned int
00366 bfd_h8_disassemble (addr, info, mach)
00367 bfd_vma addr;
00368 disassemble_info *info;
00369 int mach;
00370 {
00371
00372 int regno[3] = { 0, 0, 0 };
00373 int dispregno[3] = { 0, 0, 0 };
00374 int cst[3] = { 0, 0, 0 };
00375 int cstlen[3] = { 0, 0, 0 };
00376 static bfd_boolean init = 0;
00377 const struct h8_instruction *qi;
00378 char const **pregnames = mach != 0 ? lregnames : wregnames;
00379 int status;
00380 unsigned int l;
00381 unsigned char data[MAX_CODE_NIBBLES];
00382 void *stream = info->stream;
00383 fprintf_ftype outfn = info->fprintf_func;
00384
00385 if (!init)
00386 {
00387 bfd_h8_disassemble_init ();
00388 init = 1;
00389 }
00390
00391 status = info->read_memory_func (addr, data, 2, info);
00392 if (status != 0)
00393 {
00394 info->memory_error_func (status, addr, info);
00395 return -1;
00396 }
00397
00398 for (l = 2; status == 0 && l < sizeof (data) / 2; l += 2)
00399 status = info->read_memory_func (addr + l, data + l, 2, info);
00400
00401
00402 for (qi = h8_instructions; qi->opcode->name; qi++)
00403 {
00404 const struct h8_opcode *q = qi->opcode;
00405 op_type *nib = q->data.nib;
00406 unsigned int len = 0;
00407
00408 while (1)
00409 {
00410 op_type looking_for = *nib;
00411 int thisnib = data[len / 2];
00412 int opnr;
00413
00414 thisnib = (len & 1) ? (thisnib & 0xf) : ((thisnib / 16) & 0xf);
00415 opnr = ((looking_for & OP3) == OP3 ? 2
00416 : (looking_for & DST) == DST ? 1 : 0);
00417
00418 if (looking_for < 16 && looking_for >= 0)
00419 {
00420 if (looking_for != thisnib)
00421 goto fail;
00422 }
00423 else
00424 {
00425 if ((int) looking_for & (int) B31)
00426 {
00427 if (!((thisnib & 0x8) != 0))
00428 goto fail;
00429
00430 looking_for = (op_type) ((int) looking_for & ~(int) B31);
00431 thisnib &= 0x7;
00432 }
00433 else if ((int) looking_for & (int) B30)
00434 {
00435 if (!((thisnib & 0x8) == 0))
00436 goto fail;
00437
00438 looking_for = (op_type) ((int) looking_for & ~(int) B30);
00439 }
00440
00441 if ((int) looking_for & (int) B21)
00442 {
00443 if (!((thisnib & 0x4) != 0))
00444 goto fail;
00445
00446 looking_for = (op_type) ((int) looking_for & ~(int) B21);
00447 thisnib &= 0xb;
00448 }
00449 else if ((int) looking_for & (int) B20)
00450 {
00451 if (!((thisnib & 0x4) == 0))
00452 goto fail;
00453
00454 looking_for = (op_type) ((int) looking_for & ~(int) B20);
00455 }
00456 if ((int) looking_for & (int) B11)
00457 {
00458 if (!((thisnib & 0x2) != 0))
00459 goto fail;
00460
00461 looking_for = (op_type) ((int) looking_for & ~(int) B11);
00462 thisnib &= 0xd;
00463 }
00464 else if ((int) looking_for & (int) B10)
00465 {
00466 if (!((thisnib & 0x2) == 0))
00467 goto fail;
00468
00469 looking_for = (op_type) ((int) looking_for & ~(int) B10);
00470 }
00471
00472 if ((int) looking_for & (int) B01)
00473 {
00474 if (!((thisnib & 0x1) != 0))
00475 goto fail;
00476
00477 looking_for = (op_type) ((int) looking_for & ~(int) B01);
00478 thisnib &= 0xe;
00479 }
00480 else if ((int) looking_for & (int) B00)
00481 {
00482 if (!((thisnib & 0x1) == 0))
00483 goto fail;
00484
00485 looking_for = (op_type) ((int) looking_for & ~(int) B00);
00486 }
00487
00488 if (looking_for & IGNORE)
00489 {
00490
00491 if (thisnib != 0)
00492 goto fail;
00493 }
00494 else if ((looking_for & MODE) == DATA)
00495 {
00496 ;
00497 }
00498 else if ((looking_for & MODE) == DBIT)
00499 {
00500
00501
00502
00503 if ((looking_for & 7) != (thisnib & 7))
00504 goto fail;
00505
00506 cst[opnr] = (thisnib & 0x8) ? 2 : 1;
00507 }
00508 else if ((looking_for & MODE) == DISP ||
00509 (looking_for & MODE) == ABS ||
00510 (looking_for & MODE) == PCREL ||
00511 (looking_for & MODE) == INDEXB ||
00512 (looking_for & MODE) == INDEXW ||
00513 (looking_for & MODE) == INDEXL)
00514 {
00515 extract_immediate (stream, looking_for, thisnib,
00516 data + len / 2, cst + opnr,
00517 cstlen + opnr, q);
00518
00519 if (q->how == O (O_BRAS, SB))
00520 cst[opnr] -= 1;
00521 }
00522 else if ((looking_for & MODE) == REG ||
00523 (looking_for & MODE) == LOWREG ||
00524 (looking_for & MODE) == IND ||
00525 (looking_for & MODE) == PREINC ||
00526 (looking_for & MODE) == POSTINC ||
00527 (looking_for & MODE) == PREDEC ||
00528 (looking_for & MODE) == POSTDEC)
00529 {
00530 regno[opnr] = thisnib;
00531 }
00532 else if (looking_for & CTRL)
00533 {
00534 thisnib &= 7;
00535 if (((looking_for & MODE) == CCR && (thisnib != C_CCR)) ||
00536 ((looking_for & MODE) == EXR && (thisnib != C_EXR)) ||
00537 ((looking_for & MODE) == MACH && (thisnib != C_MACH)) ||
00538 ((looking_for & MODE) == MACL && (thisnib != C_MACL)) ||
00539 ((looking_for & MODE) == VBR && (thisnib != C_VBR)) ||
00540 ((looking_for & MODE) == SBR && (thisnib != C_SBR)))
00541 goto fail;
00542 if (((looking_for & MODE) == CCR_EXR &&
00543 (thisnib != C_CCR && thisnib != C_EXR)) ||
00544 ((looking_for & MODE) == VBR_SBR &&
00545 (thisnib != C_VBR && thisnib != C_SBR)) ||
00546 ((looking_for & MODE) == MACREG &&
00547 (thisnib != C_MACH && thisnib != C_MACL)))
00548 goto fail;
00549 if (((looking_for & MODE) == CC_EX_VB_SB &&
00550 (thisnib != C_CCR && thisnib != C_EXR &&
00551 thisnib != C_VBR && thisnib != C_SBR)))
00552 goto fail;
00553
00554 regno[opnr] = thisnib;
00555 }
00556 else if ((looking_for & SIZE) == L_5)
00557 {
00558 cst[opnr] = data[len / 2] & 31;
00559 cstlen[opnr] = 5;
00560 }
00561 else if ((looking_for & SIZE) == L_4)
00562 {
00563 cst[opnr] = thisnib;
00564 cstlen[opnr] = 4;
00565 }
00566 else if ((looking_for & SIZE) == L_16 ||
00567 (looking_for & SIZE) == L_16U)
00568 {
00569 cst[opnr] = (data[len / 2]) * 256 + data[(len + 2) / 2];
00570 cstlen[opnr] = 16;
00571 }
00572 else if ((looking_for & MODE) == MEMIND)
00573 {
00574 cst[opnr] = data[1];
00575 }
00576 else if ((looking_for & MODE) == VECIND)
00577 {
00578 cst[opnr] = data[1] & 0x7f;
00579 }
00580 else if ((looking_for & SIZE) == L_32)
00581 {
00582 int i = len / 2;
00583
00584 cst[opnr] = ((data[i] << 24)
00585 | (data[i + 1] << 16)
00586 | (data[i + 2] << 8)
00587 | (data[i + 3]));
00588
00589 cstlen[opnr] = 32;
00590 }
00591 else if ((looking_for & SIZE) == L_24)
00592 {
00593 int i = len / 2;
00594
00595 cst[opnr] =
00596 (data[i] << 16) | (data[i + 1] << 8) | (data[i + 2]);
00597 cstlen[opnr] = 24;
00598 }
00599 else if (looking_for & IGNORE)
00600 {
00601 ;
00602 }
00603 else if (looking_for & DISPREG)
00604 {
00605 dispregno[opnr] = thisnib & 7;
00606 }
00607 else if ((looking_for & MODE) == KBIT)
00608 {
00609 switch (thisnib)
00610 {
00611 case 9:
00612 cst[opnr] = 4;
00613 break;
00614 case 8:
00615 cst[opnr] = 2;
00616 break;
00617 case 0:
00618 cst[opnr] = 1;
00619 break;
00620 default:
00621 goto fail;
00622 }
00623 }
00624 else if ((looking_for & SIZE) == L_8)
00625 {
00626 cstlen[opnr] = 8;
00627 cst[opnr] = data[len / 2];
00628 }
00629 else if ((looking_for & SIZE) == L_3 ||
00630 (looking_for & SIZE) == L_3NZ)
00631 {
00632 cst[opnr] = thisnib & 0x7;
00633 if (cst[opnr] == 0 && (looking_for & SIZE) == L_3NZ)
00634 goto fail;
00635 }
00636 else if ((looking_for & SIZE) == L_2)
00637 {
00638 cstlen[opnr] = 2;
00639 cst[opnr] = thisnib & 0x3;
00640 }
00641 else if ((looking_for & MODE) == MACREG)
00642 {
00643 cst[opnr] = (thisnib == 3);
00644 }
00645 else if (looking_for == (op_type) E)
00646 {
00647 outfn (stream, "%s\t", q->name);
00648
00649
00650 if (strcmp (q->name, "ldm.l") == 0)
00651 {
00652 int count, high;
00653
00654 count = (data[1] / 16) & 0x3;
00655 high = regno[1];
00656
00657 outfn (stream, "@sp+,er%d-er%d", high - count, high);
00658 return qi->length;
00659 }
00660
00661 if (strcmp (q->name, "stm.l") == 0)
00662 {
00663 int count, low;
00664
00665 count = (data[1] / 16) & 0x3;
00666 low = regno[0];
00667
00668 outfn (stream, "er%d-er%d,@-sp", low, low + count);
00669 return qi->length;
00670 }
00671 if (strcmp (q->name, "rte/l") == 0
00672 || strcmp (q->name, "rts/l") == 0)
00673 {
00674 if (regno[0] == 0)
00675 outfn (stream, "er%d", regno[1]);
00676 else
00677 {
00678 outfn (stream, "er%d-er%d", regno[1] - regno[0],
00679 regno[1]);
00680 }
00681 return qi->length;
00682 }
00683 if (strncmp (q->name, "mova", 4) == 0)
00684 {
00685 op_type *args = q->args.nib;
00686
00687 if (args[1] == (op_type) E)
00688 {
00689
00690 print_one_arg (info, addr, args[0], cst[0],
00691 cstlen[0], dispregno[0], regno[0],
00692 pregnames, qi->length);
00693 outfn (stream, ",er%d", dispregno[0]);
00694 }
00695 else
00696 {
00697 outfn (stream, "@(0x%x:%d,", cst[0], cstlen[0]);
00698 print_one_arg (info, addr, args[1], cst[1],
00699 cstlen[1], dispregno[1], regno[1],
00700 pregnames, qi->length);
00701 outfn (stream, ".%c),",
00702 (args[0] & MODE) == INDEXB ? 'b' : 'w');
00703 print_one_arg (info, addr, args[2], cst[2],
00704 cstlen[2], dispregno[2], regno[2],
00705 pregnames, qi->length);
00706 }
00707 return qi->length;
00708 }
00709
00710 {
00711 op_type *args = q->args.nib;
00712 int hadone = 0;
00713 int nargs;
00714
00715
00716
00717
00718
00719 if (strcmp (qi->opcode->name, "adds") == 0
00720 || strcmp (qi->opcode->name, "subs") == 0)
00721 {
00722 outfn (stream, "#%d,%s", cst[0], pregnames[regno[1] & 0x7]);
00723 return qi->length;
00724 }
00725
00726 for (nargs = 0;
00727 nargs < 3 && args[nargs] != (op_type) E;
00728 nargs++)
00729 {
00730 int x = args[nargs];
00731
00732 if (hadone)
00733 outfn (stream, ",");
00734
00735 print_one_arg (info, addr, x,
00736 cst[nargs], cstlen[nargs],
00737 dispregno[nargs], regno[nargs],
00738 pregnames, qi->length);
00739
00740 hadone = 1;
00741 }
00742 }
00743
00744 return qi->length;
00745 }
00746 else
00747
00748 outfn (stream, _("Don't understand 0x%x \n"), looking_for);
00749 }
00750
00751 len++;
00752 nib++;
00753 }
00754
00755 fail:
00756 ;
00757 }
00758
00759
00760 outfn (stream, ".word\tH'%x,H'%x", data[0], data[1]);
00761 return 2;
00762 }
00763
00764 int
00765 print_insn_h8300 (addr, info)
00766 bfd_vma addr;
00767 disassemble_info *info;
00768 {
00769 return bfd_h8_disassemble (addr, info, 0);
00770 }
00771
00772 int
00773 print_insn_h8300h (addr, info)
00774 bfd_vma addr;
00775 disassemble_info *info;
00776 {
00777 return bfd_h8_disassemble (addr, info, 1);
00778 }
00779
00780 int
00781 print_insn_h8300s (addr, info)
00782 bfd_vma addr;
00783 disassemble_info *info;
00784 {
00785 return bfd_h8_disassemble (addr, info, 2);
00786 }