00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include <stdio.h>
00021 #include <ctype.h>
00022 #include <string.h>
00023 #include <sys/types.h>
00024
00025 #include "dis-asm.h"
00026 #include "opintl.h"
00027 #include "libiberty.h"
00028
00029 #define DASM_SECTION
00030 #include "opcode/msp430.h"
00031 #undef DASM_SECTION
00032
00033
00034 static unsigned short msp430dis_opcode
00035 PARAMS ((bfd_vma, disassemble_info *));
00036 int print_insn_msp430
00037 PARAMS ((bfd_vma, disassemble_info *));
00038 int msp430_nooperands
00039 PARAMS ((struct msp430_opcode_s *, bfd_vma, unsigned short, char *, int *));
00040 int msp430_singleoperand
00041 PARAMS ((disassemble_info *, struct msp430_opcode_s *, bfd_vma, unsigned short,
00042 char *, char *, int *));
00043 int msp430_doubleoperand
00044 PARAMS ((disassemble_info *, struct msp430_opcode_s *, bfd_vma, unsigned short,
00045 char *, char *, char *, char *, int *));
00046 int msp430_branchinstr
00047 PARAMS ((disassemble_info *, struct msp430_opcode_s *, bfd_vma, unsigned short,
00048 char *, char *, int *));
00049
00050 #define PS(x) (0xffff & (x))
00051
00052 static unsigned short
00053 msp430dis_opcode (addr, info)
00054 bfd_vma addr;
00055 disassemble_info *info;
00056 {
00057 bfd_byte buffer[2];
00058 int status;
00059
00060 status = info->read_memory_func (addr, buffer, 2, info);
00061 if (status != 0)
00062 {
00063 info->memory_error_func (status, addr, info);
00064 return -1;
00065 }
00066 return bfd_getl16 (buffer);
00067 }
00068
00069 int
00070 print_insn_msp430 (addr, info)
00071 bfd_vma addr;
00072 disassemble_info *info;
00073 {
00074 void *stream = info->stream;
00075 fprintf_ftype prin = info->fprintf_func;
00076 struct msp430_opcode_s *opcode;
00077 char op1[32], op2[32], comm1[64], comm2[64];
00078 int cmd_len = 0;
00079 unsigned short insn;
00080 int cycles = 0;
00081 char *bc = "";
00082 char dinfo[32];
00083
00084 insn = msp430dis_opcode (addr, info);
00085 sprintf (dinfo, "0x%04x", insn);
00086
00087 if (((int) addr & 0xffff) > 0xffdf)
00088 {
00089 (*prin) (stream, "interrupt service routine at 0x%04x", 0xffff & insn);
00090 return 2;
00091 }
00092
00093 *comm1 = 0;
00094 *comm2 = 0;
00095
00096 for (opcode = msp430_opcodes; opcode->name; opcode++)
00097 {
00098 if ((insn & opcode->bin_mask) == opcode->bin_opcode
00099 && opcode->bin_opcode != 0x9300)
00100 {
00101 *op1 = 0;
00102 *op2 = 0;
00103 *comm1 = 0;
00104 *comm2 = 0;
00105
00106
00107 if (opcode->insn_opnumb == 3 && (insn & 0x000f) == 0
00108 && (0x0080 & insn) == 0)
00109 {
00110 cmd_len =
00111 msp430_branchinstr (info, opcode, addr, insn, op1, comm1,
00112 &cycles);
00113 if (cmd_len)
00114 break;
00115 }
00116
00117 switch (opcode->insn_opnumb)
00118 {
00119 case 0:
00120 cmd_len = msp430_nooperands (opcode, addr, insn, comm1, &cycles);
00121 break;
00122 case 2:
00123 cmd_len =
00124 msp430_doubleoperand (info, opcode, addr, insn, op1, op2,
00125 comm1, comm2, &cycles);
00126 if (insn & BYTE_OPERATION)
00127 bc = ".b";
00128 break;
00129 case 1:
00130 cmd_len =
00131 msp430_singleoperand (info, opcode, addr, insn, op1, comm1,
00132 &cycles);
00133 if (insn & BYTE_OPERATION && opcode->fmt != 3)
00134 bc = ".b";
00135 break;
00136 default:
00137 break;
00138 }
00139 }
00140
00141 if (cmd_len)
00142 break;
00143 }
00144
00145 dinfo[5] = 0;
00146
00147 if (cmd_len < 1)
00148 {
00149
00150 (*prin) (stream, ".word 0x%04x; ????", PS (insn));
00151 return 2;
00152 }
00153
00154 (*prin) (stream, "%s%s", opcode->name, bc);
00155
00156 if (*op1)
00157 (*prin) (stream, "\t%s", op1);
00158 if (*op2)
00159 (*prin) (stream, ",");
00160
00161 if (strlen (op1) < 7)
00162 (*prin) (stream, "\t");
00163 if (!strlen (op1))
00164 (*prin) (stream, "\t");
00165
00166 if (*op2)
00167 (*prin) (stream, "%s", op2);
00168 if (strlen (op2) < 8)
00169 (*prin) (stream, "\t");
00170
00171 if (*comm1 || *comm2)
00172 (*prin) (stream, ";");
00173 else if (cycles)
00174 {
00175 if (*op2)
00176 (*prin) (stream, ";");
00177 else
00178 {
00179 if (strlen (op1) < 7)
00180 (*prin) (stream, ";");
00181 else
00182 (*prin) (stream, "\t;");
00183 }
00184 }
00185 if (*comm1)
00186 (*prin) (stream, "%s", comm1);
00187 if (*comm1 && *comm2)
00188 (*prin) (stream, ",");
00189 if (*comm2)
00190 (*prin) (stream, " %s", comm2);
00191 return cmd_len;
00192 }
00193
00194 int
00195 msp430_nooperands (opcode, addr, insn, comm, cycles)
00196 struct msp430_opcode_s *opcode;
00197 bfd_vma addr ATTRIBUTE_UNUSED;
00198 unsigned short insn ATTRIBUTE_UNUSED;
00199 char *comm;
00200 int *cycles;
00201 {
00202
00203 if (insn == 0x43b2)
00204 return 0;
00205 if (insn == opcode->bin_opcode)
00206 return 2;
00207
00208 if (opcode->fmt == 0)
00209 {
00210 if ((insn & 0x0f00) != 3 || (insn & 0x0f00) != 2)
00211 return 0;
00212
00213 strcpy (comm, "emulated...");
00214 *cycles = 1;
00215 }
00216 else
00217 {
00218 strcpy (comm, "return from interupt");
00219 *cycles = 5;
00220 }
00221
00222 return 2;
00223 }
00224
00225
00226 int
00227 msp430_singleoperand (info, opcode, addr, insn, op, comm, cycles)
00228 disassemble_info *info;
00229 struct msp430_opcode_s *opcode;
00230 bfd_vma addr;
00231 unsigned short insn;
00232 char *op;
00233 char *comm;
00234 int *cycles;
00235 {
00236 int regs = 0, regd = 0;
00237 int ad = 0, as = 0;
00238 int where = 0;
00239 int cmd_len = 2;
00240 short dst = 0;
00241
00242 regd = insn & 0x0f;
00243 regs = (insn & 0x0f00) >> 8;
00244 as = (insn & 0x0030) >> 4;
00245 ad = (insn & 0x0080) >> 7;
00246
00247 switch (opcode->fmt)
00248 {
00249 case 0:
00250 if (regs != 2 && regs != 3 && regs != 1)
00251 return 0;
00252
00253
00254 if (opcode->bin_opcode == 0x4300 && (ad || as))
00255 return 0;
00256
00257
00258 if ((opcode->bin_opcode & 0xff00) == 0x5300 && as == 3)
00259 return 0;
00260
00261 if (ad == 0)
00262 {
00263 *cycles = 1;
00264
00265
00266 if (regd == 0)
00267 {
00268 *cycles += 1;
00269 sprintf (op, "r0");
00270 }
00271 else if (regd == 1)
00272 sprintf (op, "r1");
00273
00274 else if (regd == 2)
00275 sprintf (op, "r2");
00276
00277 else
00278 sprintf (op, "r%d", regd);
00279 }
00280 else
00281 {
00282 if (regd == 0)
00283 {
00284
00285 dst = msp430dis_opcode (addr + 2, info);
00286 cmd_len += 2;
00287 *cycles = 4;
00288 sprintf (op, "0x%04x", dst);
00289 sprintf (comm, "PC rel. abs addr 0x%04x",
00290 PS ((short) (addr + 2) + dst));
00291 }
00292 else if (regd == 2)
00293 {
00294
00295 dst = msp430dis_opcode (addr + 2, info);
00296 cmd_len += 2;
00297 *cycles = 4;
00298 sprintf (op, "&0x%04x", PS (dst));
00299 }
00300 else
00301 {
00302 dst = msp430dis_opcode (addr + 2, info);
00303 cmd_len += 2;
00304 *cycles = 4;
00305 sprintf (op, "%d(r%d)", dst, regd);
00306 }
00307 }
00308 break;
00309
00310 case 2:
00311
00312 if (as == 0)
00313 {
00314 if (regd == 3)
00315 {
00316
00317 sprintf (op, "#0");
00318 sprintf (comm, "r3 As==00");
00319 }
00320 else
00321 {
00322
00323 sprintf (op, "r%d", regd);
00324 }
00325 *cycles = 1;
00326 }
00327 else if (as == 2)
00328 {
00329 *cycles = 1;
00330 if (regd == 2)
00331 {
00332 sprintf (op, "#4");
00333 sprintf (comm, "r2 As==10");
00334 }
00335 else if (regd == 3)
00336 {
00337 sprintf (op, "#2");
00338 sprintf (comm, "r3 As==10");
00339 }
00340 else
00341 {
00342 *cycles = 3;
00343
00344 sprintf (op, "@r%d", regd);
00345 }
00346 }
00347 else if (as == 3)
00348 {
00349 *cycles = 1;
00350 if (regd == 2)
00351 {
00352 sprintf (op, "#8");
00353 sprintf (comm, "r2 As==11");
00354 }
00355 else if (regd == 3)
00356 {
00357 sprintf (op, "#-1");
00358 sprintf (comm, "r3 As==11");
00359 }
00360 else if (regd == 0)
00361 {
00362 *cycles = 3;
00363
00364 dst = msp430dis_opcode (addr + 2, info);
00365 cmd_len += 2;
00366 sprintf (op, "#%d", dst);
00367 sprintf (comm, "#0x%04x", PS (dst));
00368 }
00369 else
00370 {
00371 *cycles = 3;
00372 sprintf (op, "@r%d+", regd);
00373 }
00374 }
00375 else if (as == 1)
00376 {
00377 *cycles = 4;
00378 if (regd == 0)
00379 {
00380
00381 dst = msp430dis_opcode (addr + 2, info);
00382 cmd_len += 2;
00383 sprintf (op, "0x%04x", PS (dst));
00384 sprintf (comm, "PC rel. 0x%04x",
00385 PS ((short) addr + 2 + dst));
00386 }
00387 else if (regd == 2)
00388 {
00389
00390 dst = msp430dis_opcode (addr + 2, info);
00391 cmd_len += 2;
00392 sprintf (op, "&0x%04x", PS (dst));
00393 }
00394 else if (regd == 3)
00395 {
00396 *cycles = 1;
00397 sprintf (op, "#1");
00398 sprintf (comm, "r3 As==01");
00399 }
00400 else
00401 {
00402
00403 dst = msp430dis_opcode (addr + 2, info);
00404 cmd_len += 2;
00405 sprintf (op, "%d(r%d)", dst, regd);
00406 }
00407 }
00408 break;
00409
00410 case 3:
00411 where = insn & 0x03ff;
00412 if (where & 0x200)
00413 where |= ~0x03ff;
00414 if (where > 512 || where < -511)
00415 return 0;
00416
00417 where *= 2;
00418 sprintf (op, "$%+-8d", where + 2);
00419 sprintf (comm, "abs 0x%x", PS ((short) (addr) + 2 + where));
00420 *cycles = 2;
00421 return 2;
00422 break;
00423 default:
00424 cmd_len = 0;
00425 }
00426
00427 return cmd_len;
00428 }
00429
00430 int
00431 msp430_doubleoperand (info, opcode, addr, insn, op1, op2, comm1, comm2, cycles)
00432 disassemble_info *info;
00433 struct msp430_opcode_s *opcode;
00434 bfd_vma addr;
00435 unsigned short insn;
00436 char *op1, *op2;
00437 char *comm1, *comm2;
00438 int *cycles;
00439 {
00440 int regs = 0, regd = 0;
00441 int ad = 0, as = 0;
00442 int cmd_len = 2;
00443 short dst = 0;
00444
00445 regd = insn & 0x0f;
00446 regs = (insn & 0x0f00) >> 8;
00447 as = (insn & 0x0030) >> 4;
00448 ad = (insn & 0x0080) >> 7;
00449
00450 if (opcode->fmt == 0)
00451 {
00452
00453
00454
00455
00456
00457
00458
00459
00460
00461
00462 if (regd != regs || as != ad)
00463 return 0;
00464
00465 if (ad == 0)
00466 {
00467
00468 if (regd == 3)
00469 {
00470 strcpy (comm1, "Illegal as emulation instr");
00471 return -1;
00472 }
00473
00474 sprintf (op1, "r%d", regd);
00475 *cycles = 1;
00476 }
00477 else
00478 {
00479 if (regd == 0)
00480 {
00481
00482 dst = msp430dis_opcode (addr + 2, info);
00483 cmd_len += 4;
00484 *cycles = 6;
00485 sprintf (op1, "0x%04x", PS (dst));
00486 sprintf (comm1, "PC rel. 0x%04x",
00487 PS ((short) addr + 2 + dst));
00488
00489 }
00490 else if (regd == 2)
00491 {
00492
00493 dst = msp430dis_opcode (addr + 2, info);
00494
00495
00496 if (dst != msp430dis_opcode (addr + 4, info))
00497 return 0;
00498 cmd_len += 4;
00499 *cycles = 6;
00500 sprintf (op1, "&0x%04x", PS (dst));
00501 }
00502 else
00503 {
00504
00505 dst = msp430dis_opcode (addr + 2, info);
00506 cmd_len += 4;
00507 *cycles = 6;
00508 sprintf (op1, "%d(r%d)", dst, regd);
00509 }
00510 }
00511
00512 *op2 = 0;
00513 *comm2 = 0;
00514 return cmd_len;
00515 }
00516
00517
00518 if (ad == 0 && regd == 3)
00519 {
00520
00521 strcpy (comm1, "Illegal as 2-op instr");
00522 return -1;
00523 }
00524
00525
00526 if (as == 0)
00527 {
00528 *cycles = 1;
00529 if (regs == 3)
00530 {
00531
00532 sprintf (op1, "#0");
00533 sprintf (comm1, "r3 As==00");
00534 }
00535 else
00536 {
00537
00538 sprintf (op1, "r%d", regs);
00539 }
00540 }
00541 else if (as == 2)
00542 {
00543 *cycles = 1;
00544
00545 if (regs == 2)
00546 {
00547 sprintf (op1, "#4");
00548 sprintf (comm1, "r2 As==10");
00549 }
00550 else if (regs == 3)
00551 {
00552 sprintf (op1, "#2");
00553 sprintf (comm1, "r3 As==10");
00554 }
00555 else
00556 {
00557 *cycles = 2;
00558
00559
00560 sprintf (op1, "@r%d", regs);
00561 }
00562 if (!regs)
00563 *cycles = 3;
00564 }
00565 else if (as == 3)
00566 {
00567 if (regs == 2)
00568 {
00569 sprintf (op1, "#8");
00570 sprintf (comm1, "r2 As==11");
00571 *cycles = 1;
00572 }
00573 else if (regs == 3)
00574 {
00575 sprintf (op1, "#-1");
00576 sprintf (comm1, "r3 As==11");
00577 *cycles = 1;
00578 }
00579 else if (regs == 0)
00580 {
00581 *cycles = 3;
00582
00583 dst = msp430dis_opcode (addr + 2, info);
00584 cmd_len += 2;
00585 sprintf (op1, "#%d", dst);
00586 sprintf (comm1, "#0x%04x", PS (dst));
00587 }
00588 else
00589 {
00590 *cycles = 2;
00591 sprintf (op1, "@r%d+", regs);
00592 }
00593 }
00594 else if (as == 1)
00595 {
00596 if (regs == 0)
00597 {
00598 *cycles = 4;
00599
00600 dst = msp430dis_opcode (addr + 2, info);
00601 cmd_len += 2;
00602 sprintf (op1, "0x%04x", PS (dst));
00603 sprintf (comm1, "PC rel. 0x%04x",
00604 PS ((short) addr + 2 + dst));
00605 }
00606 else if (regs == 2)
00607 {
00608 *cycles = 2;
00609
00610 dst = msp430dis_opcode (addr + 2, info);
00611 cmd_len += 2;
00612 sprintf (op1, "&0x%04x", PS (dst));
00613 sprintf (comm1, "0x%04x", PS (dst));
00614 }
00615 else if (regs == 3)
00616 {
00617 *cycles = 1;
00618 sprintf (op1, "#1");
00619 sprintf (comm1, "r3 As==01");
00620 }
00621 else
00622 {
00623 *cycles = 3;
00624
00625 dst = msp430dis_opcode (addr + 2, info);
00626 cmd_len += 2;
00627 sprintf (op1, "%d(r%d)", dst, regs);
00628 }
00629 }
00630
00631
00632
00633 if (ad == 0)
00634 {
00635
00636 if (regd == 0)
00637 {
00638 *cycles += 1;
00639 sprintf (op2, "r0");
00640 }
00641 else if (regd == 1)
00642 sprintf (op2, "r1");
00643
00644 else if (regd == 2)
00645 sprintf (op2, "r2");
00646
00647 else
00648 sprintf (op2, "r%d", regd);
00649 }
00650 else
00651 {
00652 * cycles += 3;
00653
00654 if (regd == 0)
00655 {
00656
00657 *cycles += 1;
00658 dst = msp430dis_opcode (addr + cmd_len, info);
00659 sprintf (op2, "0x%04x", PS (dst));
00660 sprintf (comm2, "PC rel. 0x%04x",
00661 PS ((short) addr + cmd_len + dst));
00662 cmd_len += 2;
00663 }
00664 else if (regd == 2)
00665 {
00666
00667 dst = msp430dis_opcode (addr + cmd_len, info);
00668 cmd_len += 2;
00669 sprintf (op2, "&0x%04x", PS (dst));
00670 }
00671 else
00672 {
00673 dst = msp430dis_opcode (addr + cmd_len, info);
00674 cmd_len += 2;
00675 sprintf (op2, "%d(r%d)", dst, regd);
00676 }
00677 }
00678
00679 return cmd_len;
00680 }
00681
00682
00683 int
00684 msp430_branchinstr (info, opcode, addr, insn, op1, comm1, cycles)
00685 disassemble_info *info;
00686 struct msp430_opcode_s *opcode ATTRIBUTE_UNUSED;
00687 bfd_vma addr ATTRIBUTE_UNUSED;
00688 unsigned short insn;
00689 char *op1;
00690 char *comm1;
00691 int *cycles;
00692 {
00693 int regs = 0, regd = 0;
00694 int ad = 0, as = 0;
00695 int cmd_len = 2;
00696 short dst = 0;
00697
00698 regd = insn & 0x0f;
00699 regs = (insn & 0x0f00) >> 8;
00700 as = (insn & 0x0030) >> 4;
00701 ad = (insn & 0x0080) >> 7;
00702
00703 if (regd != 0)
00704 return 0;
00705
00706
00707 if (as == 0)
00708 {
00709
00710 if (regs == 3)
00711 {
00712 *cycles = 1;
00713 sprintf (op1, "#0");
00714 sprintf (comm1, "r3 As==00");
00715 }
00716 else
00717 {
00718
00719 *cycles = 1;
00720 sprintf (op1, "r%d", regs);
00721 }
00722 }
00723 else if (as == 2)
00724 {
00725 if (regs == 2)
00726 {
00727 *cycles = 2;
00728 sprintf (op1, "#4");
00729 sprintf (comm1, "r2 As==10");
00730 }
00731 else if (regs == 3)
00732 {
00733 *cycles = 1;
00734 sprintf (op1, "#2");
00735 sprintf (comm1, "r3 As==10");
00736 }
00737 else
00738 {
00739
00740 *cycles = 2;
00741 sprintf (op1, "@r%d", regs);
00742 }
00743 }
00744 else if (as == 3)
00745 {
00746 if (regs == 2)
00747 {
00748 *cycles = 1;
00749 sprintf (op1, "#8");
00750 sprintf (comm1, "r2 As==11");
00751 }
00752 else if (regs == 3)
00753 {
00754 *cycles = 1;
00755 sprintf (op1, "#-1");
00756 sprintf (comm1, "r3 As==11");
00757 }
00758 else if (regs == 0)
00759 {
00760
00761 *cycles = 3;
00762 dst = msp430dis_opcode (addr + 2, info);
00763 cmd_len += 2;
00764 sprintf (op1, "#0x%04x", PS (dst));
00765 }
00766 else
00767 {
00768 *cycles = 2;
00769 sprintf (op1, "@r%d+", regs);
00770 }
00771 }
00772 else if (as == 1)
00773 {
00774 * cycles = 3;
00775
00776 if (regs == 0)
00777 {
00778
00779 dst = msp430dis_opcode (addr + 2, info);
00780 cmd_len += 2;
00781 (*cycles)++;
00782 sprintf (op1, "0x%04x", PS (dst));
00783 sprintf (comm1, "PC rel. 0x%04x",
00784 PS ((short) addr + 2 + dst));
00785 }
00786 else if (regs == 2)
00787 {
00788
00789 dst = msp430dis_opcode (addr + 2, info);
00790 cmd_len += 2;
00791 sprintf (op1, "&0x%04x", PS (dst));
00792 }
00793 else if (regs == 3)
00794 {
00795 (*cycles)--;
00796 sprintf (op1, "#1");
00797 sprintf (comm1, "r3 As==01");
00798 }
00799 else
00800 {
00801
00802 dst = msp430dis_opcode (addr + 2, info);
00803 cmd_len += 2;
00804 sprintf (op1, "%d(r%d)", dst, regs);
00805 }
00806 }
00807
00808 return cmd_len;
00809 }