00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "sysdep.h"
00025 #include "dis-asm.h"
00026 #include "floatformat.h"
00027 #include "libiberty.h"
00028 #include "opintl.h"
00029
00030 #include "opcode/m68k.h"
00031
00032
00033
00034 static int
00035 fetch_data PARAMS ((struct disassemble_info *, bfd_byte *));
00036
00037 static void
00038 dummy_print_address PARAMS ((bfd_vma, struct disassemble_info *));
00039
00040 static int
00041 fetch_arg PARAMS ((unsigned char *, int, int, disassemble_info *));
00042
00043 static void
00044 print_base PARAMS ((int, bfd_vma, disassemble_info *));
00045
00046 static unsigned char *
00047 print_indexed PARAMS ((int, unsigned char *, bfd_vma, disassemble_info *));
00048
00049 static int
00050 print_insn_arg PARAMS ((const char *, unsigned char *, unsigned char *,
00051 bfd_vma, disassemble_info *));
00052
00053 static bfd_boolean m68k_valid_ea (char code, int val);
00054
00055 const char * const fpcr_names[] =
00056 {
00057 "", "%fpiar", "%fpsr", "%fpiar/%fpsr", "%fpcr",
00058 "%fpiar/%fpcr", "%fpsr/%fpcr", "%fpiar/%fpsr/%fpcr"
00059 };
00060
00061 static char *const reg_names[] =
00062 {
00063 "%d0", "%d1", "%d2", "%d3", "%d4", "%d5", "%d6", "%d7",
00064 "%a0", "%a1", "%a2", "%a3", "%a4", "%a5", "%fp", "%sp",
00065 "%ps", "%pc"
00066 };
00067
00068
00069
00070 static char *const reg_half_names[] =
00071 {
00072 "%d0", "%d1", "%d2", "%d3", "%d4", "%d5", "%d6", "%d7",
00073 "%a0", "%a1", "%a2", "%a3", "%a4", "%a5", "%a6", "%a7",
00074 "%ps", "%pc"
00075 };
00076
00077
00078 #if __STDC__ == 1
00079 #define COERCE_SIGNED_CHAR(ch) ((signed char) (ch))
00080 #else
00081 #define COERCE_SIGNED_CHAR(ch) ((int) (((ch) ^ 0x80) & 0xFF) - 128)
00082 #endif
00083
00084
00085 #define NEXTBYTE(p) (p += 2, FETCH_DATA (info, p), COERCE_SIGNED_CHAR(p[-1]))
00086
00087
00088 #define COERCE16(x) ((int) (((x) ^ 0x8000) - 0x8000))
00089 #define NEXTWORD(p) \
00090 (p += 2, FETCH_DATA (info, p), \
00091 COERCE16 ((p[-2] << 8) + p[-1]))
00092
00093
00094 #define COERCE32(x) ((bfd_signed_vma) ((x) ^ 0x80000000) - 0x80000000)
00095 #define NEXTLONG(p) \
00096 (p += 4, FETCH_DATA (info, p), \
00097 (COERCE32 ((((((p[-4] << 8) + p[-3]) << 8) + p[-2]) << 8) + p[-1])))
00098
00099
00100 #define NEXTULONG(p) \
00101 (p += 4, FETCH_DATA (info, p), \
00102 (unsigned int) ((((((p[-4] << 8) + p[-3]) << 8) + p[-2]) << 8) + p[-1]))
00103
00104
00105 #define NEXTSINGLE(val, p) \
00106 (p += 4, FETCH_DATA (info, p), \
00107 floatformat_to_double (&floatformat_ieee_single_big, (char *) p - 4, &val))
00108
00109
00110 #define NEXTDOUBLE(val, p) \
00111 (p += 8, FETCH_DATA (info, p), \
00112 floatformat_to_double (&floatformat_ieee_double_big, (char *) p - 8, &val))
00113
00114
00115 #define NEXTEXTEND(val, p) \
00116 (p += 12, FETCH_DATA (info, p), \
00117 floatformat_to_double (&floatformat_m68881_ext, (char *) p - 12, &val))
00118
00119
00120
00121
00122
00123 #define NEXTPACKED(p) \
00124 (p += 12, FETCH_DATA (info, p), 0.0)
00125
00126
00127 #define MAXLEN 22
00128
00129 #include <setjmp.h>
00130
00131 struct private {
00132
00133 bfd_byte *max_fetched;
00134 bfd_byte the_buffer[MAXLEN];
00135 bfd_vma insn_start;
00136 jmp_buf bailout;
00137 };
00138
00139
00140
00141
00142 #define FETCH_DATA(info, addr) \
00143 ((addr) <= ((struct private *) (info->private_data))->max_fetched \
00144 ? 1 : fetch_data ((info), (addr)))
00145
00146 static int
00147 fetch_data (info, addr)
00148 struct disassemble_info *info;
00149 bfd_byte *addr;
00150 {
00151 int status;
00152 struct private *priv = (struct private *)info->private_data;
00153 bfd_vma start = priv->insn_start + (priv->max_fetched - priv->the_buffer);
00154
00155 status = (*info->read_memory_func) (start,
00156 priv->max_fetched,
00157 addr - priv->max_fetched,
00158 info);
00159 if (status != 0)
00160 {
00161 (*info->memory_error_func) (status, start, info);
00162 longjmp (priv->bailout, 1);
00163 }
00164 else
00165 priv->max_fetched = addr;
00166 return 1;
00167 }
00168
00169
00170 static int
00171 #ifdef __STDC__
00172 dummy_printer (FILE *file ATTRIBUTE_UNUSED,
00173 const char *format ATTRIBUTE_UNUSED, ...)
00174 #else
00175 dummy_printer (file)
00176 FILE *file ATTRIBUTE_UNUSED;
00177 #endif
00178 {
00179 return 0;
00180 }
00181
00182 static void
00183 dummy_print_address (vma, info)
00184 bfd_vma vma ATTRIBUTE_UNUSED;
00185 struct disassemble_info *info ATTRIBUTE_UNUSED;
00186 {
00187 }
00188
00189
00190
00191
00192 static int
00193 match_insn_m68k (bfd_vma memaddr, disassemble_info * info,
00194 const struct m68k_opcode * best, struct private * priv)
00195 {
00196 unsigned char *save_p;
00197 unsigned char *p;
00198 const char *d;
00199
00200 bfd_byte *buffer = priv->the_buffer;
00201 fprintf_ftype save_printer = info->fprintf_func;
00202 void (* save_print_address) (bfd_vma, struct disassemble_info *)
00203 = info->print_address_func;
00204
00205
00206
00207 p = buffer + 2;
00208
00209
00210
00211
00212
00213 for (d = best->args; *d; d += 2)
00214 {
00215
00216
00217 if (d[0] == '#')
00218 {
00219 if (d[1] == 'l' && p - buffer < 6)
00220 p = buffer + 6;
00221 else if (p - buffer < 4 && d[1] != 'C' && d[1] != '8')
00222 p = buffer + 4;
00223 }
00224
00225 if ((d[0] == 'L' || d[0] == 'l') && d[1] == 'w' && p - buffer < 4)
00226 p = buffer + 4;
00227
00228 switch (d[1])
00229 {
00230 case '1':
00231 case '2':
00232 case '3':
00233 case '7':
00234 case '8':
00235 case '9':
00236 case 'i':
00237 if (p - buffer < 4)
00238 p = buffer + 4;
00239 break;
00240 case '4':
00241 case '5':
00242 case '6':
00243 if (p - buffer < 6)
00244 p = buffer + 6;
00245 break;
00246 default:
00247 break;
00248 }
00249 }
00250
00251
00252
00253 if (p - buffer < 4 && (best->match & 0xFFFF) != 0)
00254 p = buffer + 4;
00255
00256
00257
00258 if (p - buffer < 6
00259 && (best->match & 0xffff) == 0xffff
00260 && best->args[0] == '#'
00261 && best->args[1] == 'w')
00262 {
00263
00264
00265
00266
00267 p = buffer + 6;
00268 FETCH_DATA (info, p);
00269 buffer[2] = buffer[4];
00270 buffer[3] = buffer[5];
00271 }
00272
00273 FETCH_DATA (info, p);
00274
00275 d = best->args;
00276
00277 save_p = p;
00278 info->print_address_func = dummy_print_address;
00279 info->fprintf_func = (fprintf_ftype) dummy_printer;
00280
00281
00282
00283 for (; *d; d += 2)
00284 {
00285 int eaten = print_insn_arg (d, buffer, p, memaddr + (p - buffer), info);
00286
00287 if (eaten >= 0)
00288 p += eaten;
00289 else if (eaten == -1)
00290 {
00291 info->fprintf_func = save_printer;
00292 info->print_address_func = save_print_address;
00293 return 0;
00294 }
00295 else
00296 {
00297 info->fprintf_func (info->stream,
00298
00299 _("<internal error in opcode table: %s %s>\n"),
00300 best->name, best->args);
00301 info->fprintf_func = save_printer;
00302 info->print_address_func = save_print_address;
00303 return 2;
00304 }
00305 }
00306
00307 p = save_p;
00308 info->fprintf_func = save_printer;
00309 info->print_address_func = save_print_address;
00310
00311 d = best->args;
00312
00313 info->fprintf_func (info->stream, "%s", best->name);
00314
00315 if (*d)
00316 info->fprintf_func (info->stream, " ");
00317
00318 while (*d)
00319 {
00320 p += print_insn_arg (d, buffer, p, memaddr + (p - buffer), info);
00321 d += 2;
00322
00323 if (*d && *(d - 2) != 'I' && *d != 'k')
00324 info->fprintf_func (info->stream, ",");
00325 }
00326
00327 return p - buffer;
00328 }
00329
00330
00331
00332
00333 int
00334 print_insn_m68k (memaddr, info)
00335 bfd_vma memaddr;
00336 disassemble_info *info;
00337 {
00338 int i;
00339 const char *d;
00340 unsigned int arch_mask;
00341 struct private priv;
00342 bfd_byte *buffer = priv.the_buffer;
00343 int major_opcode;
00344 static int numopcodes[16];
00345 static const struct m68k_opcode **opcodes[16];
00346 int val;
00347
00348 if (!opcodes[0])
00349 {
00350
00351
00352 const struct m68k_opcode **opc_pointer[16];
00353
00354
00355 for (i = 0; i < m68k_numopcodes; i++)
00356 numopcodes[(m68k_opcodes[i].opcode >> 28) & 15]++;
00357
00358
00359
00360 opc_pointer[0] = xmalloc (sizeof (struct m68k_opcode *)
00361 * m68k_numopcodes);
00362 opcodes[0] = opc_pointer[0];
00363
00364 for (i = 1; i < 16; i++)
00365 {
00366 opc_pointer[i] = opc_pointer[i - 1] + numopcodes[i - 1];
00367 opcodes[i] = opc_pointer[i];
00368 }
00369
00370 for (i = 0; i < m68k_numopcodes; i++)
00371 *opc_pointer[(m68k_opcodes[i].opcode >> 28) & 15]++ = &m68k_opcodes[i];
00372 }
00373
00374 info->private_data = (PTR) &priv;
00375
00376
00377 info->bytes_per_chunk = 2;
00378 info->bytes_per_line = 6;
00379 info->display_endian = BFD_ENDIAN_BIG;
00380 priv.max_fetched = priv.the_buffer;
00381 priv.insn_start = memaddr;
00382
00383 if (setjmp (priv.bailout) != 0)
00384
00385 return -1;
00386
00387 switch (info->mach)
00388 {
00389 default:
00390 case 0:
00391 arch_mask = (unsigned int) -1;
00392 break;
00393 case bfd_mach_m68000:
00394 arch_mask = m68000|m68881|m68851;
00395 break;
00396 case bfd_mach_m68008:
00397 arch_mask = m68008|m68881|m68851;
00398 break;
00399 case bfd_mach_m68010:
00400 arch_mask = m68010|m68881|m68851;
00401 break;
00402 case bfd_mach_m68020:
00403 arch_mask = m68020|m68881|m68851;
00404 break;
00405 case bfd_mach_m68030:
00406 arch_mask = m68030|m68881|m68851;
00407 break;
00408 case bfd_mach_m68040:
00409 arch_mask = m68040|m68881|m68851;
00410 break;
00411 case bfd_mach_m68060:
00412 arch_mask = m68060|m68881|m68851;
00413 break;
00414 case bfd_mach_mcf5200:
00415 arch_mask = mcfisa_a;
00416 break;
00417 case bfd_mach_mcf521x:
00418 case bfd_mach_mcf528x:
00419 arch_mask = mcfisa_a|mcfhwdiv|mcfisa_aa|mcfusp|mcfemac;
00420 break;
00421 case bfd_mach_mcf5206e:
00422 arch_mask = mcfisa_a|mcfhwdiv|mcfmac;
00423 break;
00424 case bfd_mach_mcf5249:
00425 arch_mask = mcfisa_a|mcfhwdiv|mcfemac;
00426 break;
00427 case bfd_mach_mcf5307:
00428 arch_mask = mcfisa_a|mcfhwdiv|mcfmac;
00429 break;
00430 case bfd_mach_mcf5407:
00431 arch_mask = mcfisa_a|mcfhwdiv|mcfisa_b|mcfmac;
00432 break;
00433 case bfd_mach_mcf547x:
00434 case bfd_mach_mcf548x:
00435 case bfd_mach_mcfv4e:
00436 arch_mask = mcfisa_a|mcfhwdiv|mcfisa_b|mcfusp|cfloat|mcfemac;
00437 break;
00438 }
00439
00440 FETCH_DATA (info, buffer + 2);
00441 major_opcode = (buffer[0] >> 4) & 15;
00442
00443 for (i = 0; i < numopcodes[major_opcode]; i++)
00444 {
00445 const struct m68k_opcode *opc = opcodes[major_opcode][i];
00446 unsigned long opcode = opc->opcode;
00447 unsigned long match = opc->match;
00448
00449 if (((0xff & buffer[0] & (match >> 24)) == (0xff & (opcode >> 24)))
00450 && ((0xff & buffer[1] & (match >> 16)) == (0xff & (opcode >> 16)))
00451
00452 && (((0xffff & match) == 0)
00453 ||
00454 (FETCH_DATA (info, buffer + 4)
00455 && ((0xff & buffer[2] & (match >> 8)) == (0xff & (opcode >> 8)))
00456 && ((0xff & buffer[3] & match) == (0xff & opcode)))
00457 )
00458 && (opc->arch & arch_mask) != 0)
00459 {
00460
00461
00462
00463 for (d = opc->args; *d; d += 2)
00464 if (d[1] == 'D')
00465 break;
00466
00467
00468
00469
00470 if (*d == '\0')
00471 for (d = opc->args; *d; d += 2)
00472 if (d[1] == 't')
00473 break;
00474
00475
00476
00477 if (*d == '\0')
00478 {
00479 for (d = opc->args; *d; d += 2)
00480 {
00481 if (d[0] == 's' && d[1] == '8')
00482 {
00483 val = fetch_arg (buffer, d[1], 3, info);
00484 if ((val & (val - 1)) != 0)
00485 break;
00486 }
00487 }
00488 }
00489
00490 if (*d == '\0')
00491 if ((val = match_insn_m68k (memaddr, info, opc, & priv)))
00492 return val;
00493 }
00494 }
00495
00496
00497 info->fprintf_func (info->stream, "0%o", (buffer[0] << 8) + buffer[1]);
00498 return 2;
00499 }
00500
00501
00502
00503
00504
00505 static int
00506 print_insn_arg (d, buffer, p0, addr, info)
00507 const char *d;
00508 unsigned char *buffer;
00509 unsigned char *p0;
00510 bfd_vma addr;
00511 disassemble_info *info;
00512 {
00513 int val = 0;
00514 int place = d[1];
00515 unsigned char *p = p0;
00516 int regno;
00517 const char *regname;
00518 unsigned char *p1;
00519 double flval;
00520 int flt_p;
00521 bfd_signed_vma disp;
00522 unsigned int uval;
00523
00524 switch (*d)
00525 {
00526 case 'c':
00527 {
00528 static char *const cacheFieldName[] = { "nc", "dc", "ic", "bc" };
00529 val = fetch_arg (buffer, place, 2, info);
00530 (*info->fprintf_func) (info->stream, cacheFieldName[val]);
00531 break;
00532 }
00533
00534 case 'a':
00535 {
00536 (*info->fprintf_func)
00537 (info->stream,
00538 "%s@",
00539 reg_names[fetch_arg (buffer, place, 3, info) + 8]);
00540 break;
00541 }
00542
00543 case '_':
00544 {
00545 uval = NEXTULONG (p);
00546 (*info->print_address_func) (uval, info);
00547 break;
00548 }
00549
00550 case 'C':
00551 (*info->fprintf_func) (info->stream, "%%ccr");
00552 break;
00553
00554 case 'S':
00555 (*info->fprintf_func) (info->stream, "%%sr");
00556 break;
00557
00558 case 'U':
00559 (*info->fprintf_func) (info->stream, "%%usp");
00560 break;
00561
00562 case 'E':
00563 (*info->fprintf_func) (info->stream, "%%acc");
00564 break;
00565
00566 case 'G':
00567 (*info->fprintf_func) (info->stream, "%%macsr");
00568 break;
00569
00570 case 'H':
00571 (*info->fprintf_func) (info->stream, "%%mask");
00572 break;
00573
00574 case 'J':
00575 {
00576
00577
00578
00579 static const struct { char *name; int value; } names[]
00580 = {{"%sfc", 0x000}, {"%dfc", 0x001}, {"%cacr", 0x002},
00581 {"%tc", 0x003}, {"%itt0",0x004}, {"%itt1", 0x005},
00582 {"%dtt0",0x006}, {"%dtt1",0x007}, {"%buscr",0x008},
00583 {"%usp", 0x800}, {"%vbr", 0x801}, {"%caar", 0x802},
00584 {"%msp", 0x803}, {"%isp", 0x804},
00585 {"%flashbar", 0xc04}, {"%rambar", 0xc05},
00586
00587
00588 {"%mmusr",0x805},
00589
00590 {"%urp", 0x806}, {"%srp", 0x807}, {"%pcr", 0x808}};
00591
00592 val = fetch_arg (buffer, place, 12, info);
00593 for (regno = sizeof names / sizeof names[0] - 1; regno >= 0; regno--)
00594 if (names[regno].value == val)
00595 {
00596 (*info->fprintf_func) (info->stream, "%s", names[regno].name);
00597 break;
00598 }
00599 if (regno < 0)
00600 (*info->fprintf_func) (info->stream, "%d", val);
00601 }
00602 break;
00603
00604 case 'Q':
00605 val = fetch_arg (buffer, place, 3, info);
00606
00607 if (val == 0 && d[1] != 's')
00608 val = 8;
00609 (*info->fprintf_func) (info->stream, "#%d", val);
00610 break;
00611
00612 case 'x':
00613 val = fetch_arg (buffer, place, 3, info);
00614
00615 if (val == 0)
00616 val = -1;
00617 (*info->fprintf_func) (info->stream, "#%d", val);
00618 break;
00619
00620 case 'M':
00621 if (place == 'h')
00622 {
00623 static char *const scalefactor_name[] = { "<<", ">>" };
00624 val = fetch_arg (buffer, place, 1, info);
00625 (*info->fprintf_func) (info->stream, scalefactor_name[val]);
00626 }
00627 else
00628 {
00629 val = fetch_arg (buffer, place, 8, info);
00630 if (val & 0x80)
00631 val = val - 0x100;
00632 (*info->fprintf_func) (info->stream, "#%d", val);
00633 }
00634 break;
00635
00636 case 'T':
00637 val = fetch_arg (buffer, place, 4, info);
00638 (*info->fprintf_func) (info->stream, "#%d", val);
00639 break;
00640
00641 case 'D':
00642 (*info->fprintf_func) (info->stream, "%s",
00643 reg_names[fetch_arg (buffer, place, 3, info)]);
00644 break;
00645
00646 case 'A':
00647 (*info->fprintf_func)
00648 (info->stream, "%s",
00649 reg_names[fetch_arg (buffer, place, 3, info) + 010]);
00650 break;
00651
00652 case 'R':
00653 (*info->fprintf_func)
00654 (info->stream, "%s",
00655 reg_names[fetch_arg (buffer, place, 4, info)]);
00656 break;
00657
00658 case 'r':
00659 regno = fetch_arg (buffer, place, 4, info);
00660 if (regno > 7)
00661 (*info->fprintf_func) (info->stream, "%s@", reg_names[regno]);
00662 else
00663 (*info->fprintf_func) (info->stream, "@(%s)", reg_names[regno]);
00664 break;
00665
00666 case 'F':
00667 (*info->fprintf_func)
00668 (info->stream, "%%fp%d",
00669 fetch_arg (buffer, place, 3, info));
00670 break;
00671
00672 case 'O':
00673 val = fetch_arg (buffer, place, 6, info);
00674 if (val & 0x20)
00675 (*info->fprintf_func) (info->stream, "%s", reg_names[val & 7]);
00676 else
00677 (*info->fprintf_func) (info->stream, "%d", val);
00678 break;
00679
00680 case '+':
00681 (*info->fprintf_func)
00682 (info->stream, "%s@+",
00683 reg_names[fetch_arg (buffer, place, 3, info) + 8]);
00684 break;
00685
00686 case '-':
00687 (*info->fprintf_func)
00688 (info->stream, "%s@-",
00689 reg_names[fetch_arg (buffer, place, 3, info) + 8]);
00690 break;
00691
00692 case 'k':
00693 if (place == 'k')
00694 (*info->fprintf_func)
00695 (info->stream, "{%s}",
00696 reg_names[fetch_arg (buffer, place, 3, info)]);
00697 else if (place == 'C')
00698 {
00699 val = fetch_arg (buffer, place, 7, info);
00700 if (val > 63)
00701 val -= 128;
00702 (*info->fprintf_func) (info->stream, "{#%d}", val);
00703 }
00704 else
00705 return -2;
00706 break;
00707
00708 case '#':
00709 case '^':
00710 p1 = buffer + (*d == '#' ? 2 : 4);
00711 if (place == 's')
00712 val = fetch_arg (buffer, place, 4, info);
00713 else if (place == 'C')
00714 val = fetch_arg (buffer, place, 7, info);
00715 else if (place == '8')
00716 val = fetch_arg (buffer, place, 3, info);
00717 else if (place == '3')
00718 val = fetch_arg (buffer, place, 8, info);
00719 else if (place == 'b')
00720 val = NEXTBYTE (p1);
00721 else if (place == 'w' || place == 'W')
00722 val = NEXTWORD (p1);
00723 else if (place == 'l')
00724 val = NEXTLONG (p1);
00725 else
00726 return -2;
00727 (*info->fprintf_func) (info->stream, "#%d", val);
00728 break;
00729
00730 case 'B':
00731 if (place == 'b')
00732 disp = NEXTBYTE (p);
00733 else if (place == 'B')
00734 disp = COERCE_SIGNED_CHAR (buffer[1]);
00735 else if (place == 'w' || place == 'W')
00736 disp = NEXTWORD (p);
00737 else if (place == 'l' || place == 'L' || place == 'C')
00738 disp = NEXTLONG (p);
00739 else if (place == 'g')
00740 {
00741 disp = NEXTBYTE (buffer);
00742 if (disp == 0)
00743 disp = NEXTWORD (p);
00744 else if (disp == -1)
00745 disp = NEXTLONG (p);
00746 }
00747 else if (place == 'c')
00748 {
00749 if (buffer[1] & 0x40)
00750 disp = NEXTLONG (p);
00751 else
00752 disp = NEXTWORD (p);
00753 }
00754 else
00755 return -2;
00756
00757 (*info->print_address_func) (addr + disp, info);
00758 break;
00759
00760 case 'd':
00761 val = NEXTWORD (p);
00762 (*info->fprintf_func)
00763 (info->stream, "%s@(%d)",
00764 reg_names[fetch_arg (buffer, place, 3, info) + 8], val);
00765 break;
00766
00767 case 's':
00768 (*info->fprintf_func) (info->stream, "%s",
00769 fpcr_names[fetch_arg (buffer, place, 3, info)]);
00770 break;
00771
00772 case 'e':
00773 val = fetch_arg(buffer, place, 2, info);
00774 (*info->fprintf_func) (info->stream, "%%acc%d", val);
00775 break;
00776
00777 case 'g':
00778 val = fetch_arg(buffer, place, 1, info);
00779 (*info->fprintf_func) (info->stream, "%%accext%s", val==0 ? "01" : "23");
00780 break;
00781
00782 case 'i':
00783 val = fetch_arg(buffer, place, 2, info);
00784 if (val == 1)
00785 (*info->fprintf_func) (info->stream, "<<");
00786 else if (val == 3)
00787 (*info->fprintf_func) (info->stream, ">>");
00788 else
00789 return -1;
00790 break;
00791
00792 case 'I':
00793
00794 val = fetch_arg (buffer, 'd', 3, info);
00795
00796 if (val != 1)
00797 (*info->fprintf_func) (info->stream, "(cpid=%d) ", val);
00798 break;
00799
00800 case '4':
00801 case '*':
00802 case '~':
00803 case '%':
00804 case ';':
00805 case '@':
00806 case '!':
00807 case '$':
00808 case '?':
00809 case '/':
00810 case '&':
00811 case '|':
00812 case '<':
00813 case '>':
00814 case 'm':
00815 case 'n':
00816 case 'o':
00817 case 'p':
00818 case 'q':
00819 case 'v':
00820 case 'b':
00821 case 'w':
00822 case 'y':
00823 case 'z':
00824 if (place == 'd')
00825 {
00826 val = fetch_arg (buffer, 'x', 6, info);
00827 val = ((val & 7) << 3) + ((val >> 3) & 7);
00828 }
00829 else
00830 val = fetch_arg (buffer, 's', 6, info);
00831
00832
00833 if (!m68k_valid_ea (*d, val))
00834 return -1;
00835
00836
00837 regno = (val & 7) + 8;
00838 regname = reg_names[regno];
00839 switch (val >> 3)
00840 {
00841 case 0:
00842 (*info->fprintf_func) (info->stream, "%s", reg_names[val]);
00843 break;
00844
00845 case 1:
00846 (*info->fprintf_func) (info->stream, "%s", regname);
00847 break;
00848
00849 case 2:
00850 (*info->fprintf_func) (info->stream, "%s@", regname);
00851 break;
00852
00853 case 3:
00854 (*info->fprintf_func) (info->stream, "%s@+", regname);
00855 break;
00856
00857 case 4:
00858 (*info->fprintf_func) (info->stream, "%s@-", regname);
00859 break;
00860
00861 case 5:
00862 val = NEXTWORD (p);
00863 (*info->fprintf_func) (info->stream, "%s@(%d)", regname, val);
00864 break;
00865
00866 case 6:
00867 p = print_indexed (regno, p, addr, info);
00868 break;
00869
00870 case 7:
00871 switch (val & 7)
00872 {
00873 case 0:
00874 val = NEXTWORD (p);
00875 (*info->print_address_func) (val, info);
00876 break;
00877
00878 case 1:
00879 uval = NEXTULONG (p);
00880 (*info->print_address_func) (uval, info);
00881 break;
00882
00883 case 2:
00884 val = NEXTWORD (p);
00885 (*info->fprintf_func) (info->stream, "%%pc@(");
00886 (*info->print_address_func) (addr + val, info);
00887 (*info->fprintf_func) (info->stream, ")");
00888 break;
00889
00890 case 3:
00891 p = print_indexed (-1, p, addr, info);
00892 break;
00893
00894 case 4:
00895 flt_p = 1;
00896 switch (place)
00897 {
00898 case 'b':
00899 val = NEXTBYTE (p);
00900 flt_p = 0;
00901 break;
00902
00903 case 'w':
00904 val = NEXTWORD (p);
00905 flt_p = 0;
00906 break;
00907
00908 case 'l':
00909 val = NEXTLONG (p);
00910 flt_p = 0;
00911 break;
00912
00913 case 'f':
00914 NEXTSINGLE (flval, p);
00915 break;
00916
00917 case 'F':
00918 NEXTDOUBLE (flval, p);
00919 break;
00920
00921 case 'x':
00922 NEXTEXTEND (flval, p);
00923 break;
00924
00925 case 'p':
00926 flval = NEXTPACKED (p);
00927 break;
00928
00929 default:
00930 return -1;
00931 }
00932 if (flt_p)
00933 (*info->fprintf_func) (info->stream, "#%g", flval);
00934 else
00935 (*info->fprintf_func) (info->stream, "#%d", val);
00936 break;
00937
00938 default:
00939 return -1;
00940 }
00941 }
00942
00943
00944
00945
00946 if (place == '/')
00947 {
00948 val = fetch_arg (buffer, place, 1, info);
00949 if (val)
00950 info->fprintf_func (info->stream, "&");
00951 }
00952 break;
00953
00954 case 'L':
00955 case 'l':
00956 if (place == 'w')
00957 {
00958 char doneany;
00959 p1 = buffer + 2;
00960 val = NEXTWORD (p1);
00961
00962
00963 p = p1 > p ? p1 : p;
00964 if (val == 0)
00965 {
00966 (*info->fprintf_func) (info->stream, "#0");
00967 break;
00968 }
00969 if (*d == 'l')
00970 {
00971 register int newval = 0;
00972 for (regno = 0; regno < 16; ++regno)
00973 if (val & (0x8000 >> regno))
00974 newval |= 1 << regno;
00975 val = newval;
00976 }
00977 val &= 0xffff;
00978 doneany = 0;
00979 for (regno = 0; regno < 16; ++regno)
00980 if (val & (1 << regno))
00981 {
00982 int first_regno;
00983 if (doneany)
00984 (*info->fprintf_func) (info->stream, "/");
00985 doneany = 1;
00986 (*info->fprintf_func) (info->stream, "%s", reg_names[regno]);
00987 first_regno = regno;
00988 while (val & (1 << (regno + 1)))
00989 ++regno;
00990 if (regno > first_regno)
00991 (*info->fprintf_func) (info->stream, "-%s",
00992 reg_names[regno]);
00993 }
00994 }
00995 else if (place == '3')
00996 {
00997
00998 char doneany;
00999 val = fetch_arg (buffer, place, 8, info);
01000 if (val == 0)
01001 {
01002 (*info->fprintf_func) (info->stream, "#0");
01003 break;
01004 }
01005 if (*d == 'l')
01006 {
01007 register int newval = 0;
01008 for (regno = 0; regno < 8; ++regno)
01009 if (val & (0x80 >> regno))
01010 newval |= 1 << regno;
01011 val = newval;
01012 }
01013 val &= 0xff;
01014 doneany = 0;
01015 for (regno = 0; regno < 8; ++regno)
01016 if (val & (1 << regno))
01017 {
01018 int first_regno;
01019 if (doneany)
01020 (*info->fprintf_func) (info->stream, "/");
01021 doneany = 1;
01022 (*info->fprintf_func) (info->stream, "%%fp%d", regno);
01023 first_regno = regno;
01024 while (val & (1 << (regno + 1)))
01025 ++regno;
01026 if (regno > first_regno)
01027 (*info->fprintf_func) (info->stream, "-%%fp%d", regno);
01028 }
01029 }
01030 else if (place == '8')
01031 {
01032
01033 (*info->fprintf_func) (info->stream, "%s",
01034 fpcr_names[fetch_arg (buffer, place, 3,
01035 info)]);
01036 }
01037 else
01038 return -2;
01039 break;
01040
01041 case 'X':
01042 place = '8';
01043 case 'Y':
01044 case 'Z':
01045 case 'W':
01046 case '0':
01047 case '1':
01048 case '2':
01049 case '3':
01050 {
01051 int val = fetch_arg (buffer, place, 5, info);
01052 char *name = 0;
01053 switch (val)
01054 {
01055 case 2: name = "%tt0"; break;
01056 case 3: name = "%tt1"; break;
01057 case 0x10: name = "%tc"; break;
01058 case 0x11: name = "%drp"; break;
01059 case 0x12: name = "%srp"; break;
01060 case 0x13: name = "%crp"; break;
01061 case 0x14: name = "%cal"; break;
01062 case 0x15: name = "%val"; break;
01063 case 0x16: name = "%scc"; break;
01064 case 0x17: name = "%ac"; break;
01065 case 0x18: name = "%psr"; break;
01066 case 0x19: name = "%pcsr"; break;
01067 case 0x1c:
01068 case 0x1d:
01069 {
01070 int break_reg = ((buffer[3] >> 2) & 7);
01071 (*info->fprintf_func)
01072 (info->stream, val == 0x1c ? "%%bad%d" : "%%bac%d",
01073 break_reg);
01074 }
01075 break;
01076 default:
01077 (*info->fprintf_func) (info->stream, "<mmu register %d>", val);
01078 }
01079 if (name)
01080 (*info->fprintf_func) (info->stream, "%s", name);
01081 }
01082 break;
01083
01084 case 'f':
01085 {
01086 int fc = fetch_arg (buffer, place, 5, info);
01087 if (fc == 1)
01088 (*info->fprintf_func) (info->stream, "%%dfc");
01089 else if (fc == 0)
01090 (*info->fprintf_func) (info->stream, "%%sfc");
01091 else
01092
01093 (*info->fprintf_func) (info->stream, _("<function code %d>"), fc);
01094 }
01095 break;
01096
01097 case 'V':
01098 (*info->fprintf_func) (info->stream, "%%val");
01099 break;
01100
01101 case 't':
01102 {
01103 int level = fetch_arg (buffer, place, 3, info);
01104 (*info->fprintf_func) (info->stream, "%d", level);
01105 }
01106 break;
01107
01108 case 'u':
01109 {
01110 short is_upper = 0;
01111 int reg = fetch_arg (buffer, place, 5, info);
01112
01113 if (reg & 0x10)
01114 {
01115 is_upper = 1;
01116 reg &= 0xf;
01117 }
01118 (*info->fprintf_func) (info->stream, "%s%s",
01119 reg_half_names[reg],
01120 is_upper ? "u" : "l");
01121 }
01122 break;
01123
01124 default:
01125 return -2;
01126 }
01127
01128 return p - p0;
01129 }
01130
01131
01132
01133
01134
01135
01136
01137
01138 static bfd_boolean
01139 m68k_valid_ea (char code, int val)
01140 {
01141 int mode, mask;
01142 #define M(n0,n1,n2,n3,n4,n5,n6,n70,n71,n72,n73,n74) \
01143 (n0 | n1 << 1 | n2 << 2 | n3 << 3 | n4 << 4 | n5 << 5 | n6 << 6 \
01144 | n70 << 7 | n71 << 8 | n72 << 9 | n73 << 10 | n74 << 11)
01145
01146 switch (code)
01147 {
01148 case '*':
01149 mask = M (1,1,1,1,1,1,1,1,1,1,1,1);
01150 break;
01151 case '~':
01152 mask = M (0,0,1,1,1,1,1,1,1,0,0,0);
01153 break;
01154 case '%':
01155 mask = M (1,1,1,1,1,1,1,1,1,0,0,0);
01156 break;
01157 case ';':
01158 mask = M (1,0,1,1,1,1,1,1,1,1,1,1);
01159 break;
01160 case '@':
01161 mask = M (1,0,1,1,1,1,1,1,1,1,1,0);
01162 break;
01163 case '!':
01164 mask = M (0,0,1,0,0,1,1,1,1,1,1,0);
01165 break;
01166 case '&':
01167 mask = M (0,0,1,0,0,1,1,1,1,0,0,0);
01168 break;
01169 case '$':
01170 mask = M (1,0,1,1,1,1,1,1,1,0,0,0);
01171 break;
01172 case '?':
01173 mask = M (1,0,1,0,0,1,1,1,1,0,0,0);
01174 break;
01175 case '/':
01176 mask = M (1,0,1,0,0,1,1,1,1,1,1,0);
01177 break;
01178 case '|':
01179 mask = M (0,0,1,0,0,1,1,1,1,1,1,0);
01180 break;
01181 case '>':
01182 mask = M (0,0,1,0,1,1,1,1,1,0,0,0);
01183 break;
01184 case '<':
01185 mask = M (0,0,1,1,0,1,1,1,1,1,1,0);
01186 break;
01187 case 'm':
01188 mask = M (1,1,1,1,1,0,0,0,0,0,0,0);
01189 break;
01190 case 'n':
01191 mask = M (0,0,0,0,0,1,0,0,0,1,0,0);
01192 break;
01193 case 'o':
01194 mask = M (0,0,0,0,0,0,1,1,1,0,1,1);
01195 break;
01196 case 'p':
01197 mask = M (1,1,1,1,1,1,0,0,0,0,0,0);
01198 break;
01199 case 'q':
01200 mask = M (1,0,1,1,1,1,0,0,0,0,0,0);
01201 break;
01202 case 'v':
01203 mask = M (1,0,1,1,1,1,0,1,1,0,0,0);
01204 break;
01205 case 'b':
01206 mask = M (1,0,1,1,1,1,0,0,0,1,0,0);
01207 break;
01208 case 'w':
01209 mask = M (0,0,1,1,1,1,0,0,0,1,0,0);
01210 break;
01211 case 'y':
01212 mask = M (0,0,1,0,0,1,0,0,0,0,0,0);
01213 break;
01214 case 'z':
01215 mask = M (0,0,1,0,0,1,0,0,0,1,0,0);
01216 break;
01217 case '4':
01218 mask = M (0,0,1,1,1,1,0,0,0,0,0,0);
01219 break;
01220 default:
01221 abort ();
01222 }
01223 #undef M
01224
01225 mode = (val >> 3) & 7;
01226 if (mode == 7)
01227 mode += val & 7;
01228 return (mask & (1 << mode)) != 0;
01229 }
01230
01231
01232
01233
01234
01235
01236 static int
01237 fetch_arg (buffer, code, bits, info)
01238 unsigned char *buffer;
01239 int code;
01240 int bits;
01241 disassemble_info *info;
01242 {
01243 int val = 0;
01244
01245 switch (code)
01246 {
01247 case '/':
01248 val = buffer[3] >> 5;
01249 break;
01250
01251 case 'G':
01252 val = ((buffer[3] >> 3) & 0x2) | ((~buffer[1] >> 7) & 0x1);
01253 break;
01254
01255 case 'H':
01256 val = ((buffer[3] >> 3) & 0x2) | ((buffer[1] >> 7) & 0x1);
01257 break;
01258
01259 case ']':
01260 val = buffer[0] >> 2;
01261 break;
01262
01263 case 'I':
01264 val = buffer[2] >> 1;
01265 break;
01266
01267 case 'F':
01268 val = buffer[0] >> 1;
01269 break;
01270
01271 case 'f':
01272 val = buffer[1];
01273 break;
01274
01275 case 's':
01276 val = buffer[1];
01277 break;
01278
01279 case 'd':
01280 val = (buffer[0] << 8) + buffer[1];
01281 val >>= 9;
01282 break;
01283
01284 case 'x':
01285 val = (buffer[0] << 8) + buffer[1];
01286 val >>= 6;
01287 break;
01288
01289 case 'k':
01290 FETCH_DATA (info, buffer + 3);
01291 val = (buffer[3] >> 4);
01292 break;
01293
01294 case 'C':
01295 FETCH_DATA (info, buffer + 3);
01296 val = buffer[3];
01297 break;
01298
01299 case '1':
01300 FETCH_DATA (info, buffer + 3);
01301 val = (buffer[2] << 8) + buffer[3];
01302 val >>= 12;
01303 break;
01304
01305 case '2':
01306 FETCH_DATA (info, buffer + 3);
01307 val = (buffer[2] << 8) + buffer[3];
01308 val >>= 6;
01309 break;
01310
01311 case '3':
01312 case 'j':
01313 FETCH_DATA (info, buffer + 3);
01314 val = (buffer[2] << 8) + buffer[3];
01315 break;
01316
01317 case '4':
01318 FETCH_DATA (info, buffer + 5);
01319 val = (buffer[4] << 8) + buffer[5];
01320 val >>= 12;
01321 break;
01322
01323 case '5':
01324 FETCH_DATA (info, buffer + 5);
01325 val = (buffer[4] << 8) + buffer[5];
01326 val >>= 6;
01327 break;
01328
01329 case '6':
01330 FETCH_DATA (info, buffer + 5);
01331 val = (buffer[4] << 8) + buffer[5];
01332 break;
01333
01334 case '7':
01335 FETCH_DATA (info, buffer + 3);
01336 val = (buffer[2] << 8) + buffer[3];
01337 val >>= 7;
01338 break;
01339
01340 case '8':
01341 FETCH_DATA (info, buffer + 3);
01342 val = (buffer[2] << 8) + buffer[3];
01343 val >>= 10;
01344 break;
01345
01346 case '9':
01347 FETCH_DATA (info, buffer + 3);
01348 val = (buffer[2] << 8) + buffer[3];
01349 val >>= 5;
01350 break;
01351
01352 case 'e':
01353 val = (buffer[1] >> 6);
01354 break;
01355
01356 case 'm':
01357 val = (buffer[1] & 0x40 ? 0x8 : 0)
01358 | ((buffer[0] >> 1) & 0x7)
01359 | (buffer[3] & 0x80 ? 0x10 : 0);
01360 break;
01361
01362 case 'n':
01363 val = (buffer[1] & 0x40 ? 0x8 : 0) | ((buffer[0] >> 1) & 0x7);
01364 break;
01365
01366 case 'o':
01367 val = (buffer[2] >> 4) | (buffer[3] & 0x80 ? 0x10 : 0);
01368 break;
01369
01370 case 'M':
01371 val = (buffer[1] & 0xf) | (buffer[3] & 0x40 ? 0x10 : 0);
01372 break;
01373
01374 case 'N':
01375 val = (buffer[3] & 0xf) | (buffer[3] & 0x40 ? 0x10 : 0);
01376 break;
01377
01378 case 'h':
01379 val = buffer[2] >> 2;
01380 break;
01381
01382 default:
01383 abort ();
01384 }
01385
01386 switch (bits)
01387 {
01388 case 1:
01389 return val & 1;
01390 case 2:
01391 return val & 3;
01392 case 3:
01393 return val & 7;
01394 case 4:
01395 return val & 017;
01396 case 5:
01397 return val & 037;
01398 case 6:
01399 return val & 077;
01400 case 7:
01401 return val & 0177;
01402 case 8:
01403 return val & 0377;
01404 case 12:
01405 return val & 07777;
01406 default:
01407 abort ();
01408 }
01409 }
01410
01411
01412
01413
01414
01415 static unsigned char *
01416 print_indexed (basereg, p, addr, info)
01417 int basereg;
01418 unsigned char *p;
01419 bfd_vma addr;
01420 disassemble_info *info;
01421 {
01422 int word;
01423 static char *const scales[] = { "", ":2", ":4", ":8" };
01424 bfd_vma base_disp;
01425 bfd_vma outer_disp;
01426 char buf[40];
01427 char vmabuf[50];
01428
01429 word = NEXTWORD (p);
01430
01431
01432
01433 sprintf (buf, "%s:%c%s",
01434 reg_names[(word >> 12) & 0xf],
01435 (word & 0x800) ? 'l' : 'w',
01436 scales[(word >> 9) & 3]);
01437
01438
01439
01440 if ((word & 0x100) == 0)
01441 {
01442 base_disp = word & 0xff;
01443 if ((base_disp & 0x80) != 0)
01444 base_disp -= 0x100;
01445 if (basereg == -1)
01446 base_disp += addr;
01447 print_base (basereg, base_disp, info);
01448 (*info->fprintf_func) (info->stream, ",%s)", buf);
01449 return p;
01450 }
01451
01452
01453
01454
01455 if (word & 0200)
01456 {
01457 if (basereg == -1)
01458 basereg = -3;
01459 else
01460 basereg = -2;
01461 }
01462 if (word & 0100)
01463 buf[0] = '\0';
01464 base_disp = 0;
01465 switch ((word >> 4) & 3)
01466 {
01467 case 2:
01468 base_disp = NEXTWORD (p);
01469 break;
01470 case 3:
01471 base_disp = NEXTLONG (p);
01472 }
01473 if (basereg == -1)
01474 base_disp += addr;
01475
01476
01477
01478 if ((word & 7) == 0)
01479 {
01480 print_base (basereg, base_disp, info);
01481 if (buf[0] != '\0')
01482 (*info->fprintf_func) (info->stream, ",%s", buf);
01483 (*info->fprintf_func) (info->stream, ")");
01484 return p;
01485 }
01486
01487
01488
01489 outer_disp = 0;
01490 switch (word & 3)
01491 {
01492 case 2:
01493 outer_disp = NEXTWORD (p);
01494 break;
01495 case 3:
01496 outer_disp = NEXTLONG (p);
01497 }
01498
01499 print_base (basereg, base_disp, info);
01500 if ((word & 4) == 0 && buf[0] != '\0')
01501 {
01502 (*info->fprintf_func) (info->stream, ",%s", buf);
01503 buf[0] = '\0';
01504 }
01505 sprintf_vma (vmabuf, outer_disp);
01506 (*info->fprintf_func) (info->stream, ")@(%s", vmabuf);
01507 if (buf[0] != '\0')
01508 (*info->fprintf_func) (info->stream, ",%s", buf);
01509 (*info->fprintf_func) (info->stream, ")");
01510
01511 return p;
01512 }
01513
01514
01515
01516
01517 static void
01518 print_base (regno, disp, info)
01519 int regno;
01520 bfd_vma disp;
01521 disassemble_info *info;
01522 {
01523 if (regno == -1)
01524 {
01525 (*info->fprintf_func) (info->stream, "%%pc@(");
01526 (*info->print_address_func) (disp, info);
01527 }
01528 else
01529 {
01530 char buf[50];
01531
01532 if (regno == -2)
01533 (*info->fprintf_func) (info->stream, "@(");
01534 else if (regno == -3)
01535 (*info->fprintf_func) (info->stream, "%%zpc@(");
01536 else
01537 (*info->fprintf_func) (info->stream, "%s@(", reg_names[regno]);
01538
01539 sprintf_vma (buf, disp);
01540 (*info->fprintf_func) (info->stream, "%s", buf);
01541 }
01542 }