X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=opcodes%2Fmsp430-dis.c;h=c057c9bde7ec1eb2a1338c943be8884d448e0a53;hb=e950b3453948830c5ce9c2f70d114d0b38a4b4ac;hp=1284bbe44fe7793bd810fc4178080c1f678cc16a;hpb=4b95cf5c0c75d6efc1b2f96af72317aecca079f1;p=deliverable%2Fbinutils-gdb.git diff --git a/opcodes/msp430-dis.c b/opcodes/msp430-dis.c index 1284bbe44f..c057c9bde7 100644 --- a/opcodes/msp430-dis.c +++ b/opcodes/msp430-dis.c @@ -1,8 +1,8 @@ /* Disassemble MSP430 instructions. - Copyright (C) 2002-2014 Free Software Foundation, Inc. + Copyright (C) 2002-2016 Free Software Foundation, Inc. Contributed by Dmitry Diky - + This file is part of the GNU opcodes library. This library is free software; you can redistribute it and/or modify @@ -24,6 +24,7 @@ #include #include #include +#include #include "dis-asm.h" #include "opintl.h" @@ -36,19 +37,80 @@ #define PS(x) (0xffff & (x)) -static unsigned short -msp430dis_opcode (bfd_vma addr, disassemble_info *info) +static bfd_boolean +msp430dis_read_two_bytes (bfd_vma addr, + disassemble_info * info, + bfd_byte * buffer, + char * comm) { - bfd_byte buffer[2]; int status; status = info->read_memory_func (addr, buffer, 2, info); - if (status != 0) + if (status == 0) + return TRUE; + + /* PR 20150: A status of EIO means that there were no more bytes left + to read in the current section. This can happen when disassembling + interrupt vectors for example. Avoid cluttering the output with + unhelpful error messages in this case. */ + if (status == EIO) + { + if (comm) + sprintf (comm, _("Warning: disassembly unreliable - not enough bytes available")); + } + else { info->memory_error_func (status, addr, info); - return -1; + if (comm) + sprintf (comm, _("Error: read from memory failed")); + } + + return FALSE; +} + +static bfd_boolean +msp430dis_opcode_unsigned (bfd_vma addr, + disassemble_info * info, + unsigned short * return_val, + char * comm) +{ + bfd_byte buffer[2]; + + if (msp430dis_read_two_bytes (addr, info, buffer, comm)) + { + * return_val = bfd_getl16 (buffer); + return TRUE; + } + else + { + * return_val = 0; + return FALSE; + } +} + +static bfd_boolean +msp430dis_opcode_signed (bfd_vma addr, + disassemble_info * info, + signed int * return_val, + char * comm) +{ + bfd_byte buffer[2]; + + if (msp430dis_read_two_bytes (addr, info, buffer, comm)) + { + int status; + + status = bfd_getl_signed_16 (buffer); + if (status & 0x8000) + status |= -1U << 16; + * return_val = status; + return TRUE; + } + else + { + * return_val = 0; + return FALSE; } - return bfd_getl16 (buffer); } static int @@ -66,7 +128,7 @@ msp430_nooperands (struct msp430_opcode_s *opcode, if (opcode->fmt == 0) { - if ((insn & 0x0f00) != 3 || (insn & 0x0f00) != 2) + if ((insn & 0x0f00) != 0x0300 || (insn & 0x0f00) != 0x0200) return 0; strcpy (comm, "emulated..."); @@ -193,47 +255,51 @@ msp430_singleoperand (disassemble_info *info, if (regd == 0) { /* PC relative. */ - dst = msp430dis_opcode (addr + 2, info); - cmd_len += 2; - *cycles = 4; - sprintf (op, "0x%04x", dst); - sprintf (comm, "PC rel. abs addr 0x%04x", - PS ((short) (addr + 2) + dst)); - if (extended_dst) + if (msp430dis_opcode_signed (addr + 2, info, &dst, comm)) { - dst |= extended_dst << 16; - sprintf (op, "0x%05x", dst); - sprintf (comm, "PC rel. abs addr 0x%05lx", - (long)((addr + 2 + dst) & 0xfffff)); + cmd_len += 2; + *cycles = 4; + sprintf (op, "0x%04x", dst); + sprintf (comm, "PC rel. abs addr 0x%04x", + PS ((short) (addr + 2) + dst)); + if (extended_dst) + { + dst |= extended_dst << 16; + sprintf (op, "0x%05x", dst); + sprintf (comm, "PC rel. abs addr 0x%05lx", + (long)((addr + 2 + dst) & 0xfffff)); + } } } else if (regd == 2) { /* Absolute. */ - dst = msp430dis_opcode (addr + 2, info); - cmd_len += 2; - *cycles = 4; - sprintf (op, "&0x%04x", PS (dst)); - if (extended_dst) + if (msp430dis_opcode_signed (addr + 2, info, &dst, comm)) { - dst |= extended_dst << 16; - sprintf (op, "&0x%05x", dst & 0xfffff); + cmd_len += 2; + *cycles = 4; + sprintf (op, "&0x%04x", PS (dst)); + if (extended_dst) + { + dst |= extended_dst << 16; + sprintf (op, "&0x%05x", dst & 0xfffff); + } } } else { - dst = msp430dis_opcode (addr + 2, info); - cmd_len += 2; - *cycles = 4; - if (extended_dst) + if (msp430dis_opcode_signed (addr + 2, info, &dst, comm)) { - dst |= extended_dst << 16; - if (dst & 0x80000) - dst |= -1 << 20; + cmd_len += 2; + *cycles = 4; + if (extended_dst) + { + dst |= extended_dst << 16; + if (dst & 0x80000) + dst |= -1U << 20; + } + sprintf (op, "%d(r%d)", dst, regd); } - else if (dst & 0x8000) - dst |= -1 << 16; - sprintf (op, "%d(r%d)", dst, regd); } } break; @@ -264,19 +330,21 @@ msp430_singleoperand (disassemble_info *info, { *cycles = 3; /* absolute. @pc+ */ - dst = msp430dis_opcode (addr + 2, info); - cmd_len += 2; - sprintf (op, "#%d", dst); - if (dst > 9 || dst < 0) - sprintf (comm, "#0x%04x", PS (dst)); - if (extended_dst) + if (msp430dis_opcode_signed (addr + 2, info, &dst, comm)) { - dst |= extended_dst << 16; - if (dst & 0x80000) - dst |= -1 << 20; + cmd_len += 2; sprintf (op, "#%d", dst); if (dst > 9 || dst < 0) - sprintf (comm, "#0x%05x", dst); + sprintf (comm, "#0x%04x", PS (dst)); + if (extended_dst) + { + dst |= extended_dst << 16; + if (dst & 0x80000) + dst |= -1U << 20; + sprintf (op, "#%d", dst); + if (dst > 9 || dst < 0) + sprintf (comm, "#0x%05x", dst); + } } } else @@ -288,29 +356,33 @@ msp430_singleoperand (disassemble_info *info, if (regd == 0) { /* PC relative. */ - dst = msp430dis_opcode (addr + 2, info); - cmd_len += 2; - sprintf (op, "0x%04x", PS (dst)); - sprintf (comm, "PC rel. 0x%04x", - PS ((short) addr + 2 + dst)); - if (extended_dst) + if (msp430dis_opcode_signed (addr + 2, info, &dst, comm)) { - dst |= extended_dst << 16; - sprintf (op, "0x%05x", dst & 0xffff); - sprintf (comm, "PC rel. 0x%05lx", - (long)((addr + 2 + dst) & 0xfffff)); + cmd_len += 2; + sprintf (op, "0x%04x", PS (dst)); + sprintf (comm, "PC rel. 0x%04x", + PS ((short) addr + 2 + dst)); + if (extended_dst) + { + dst |= extended_dst << 16; + sprintf (op, "0x%05x", dst & 0xffff); + sprintf (comm, "PC rel. 0x%05lx", + (long)((addr + 2 + dst) & 0xfffff)); + } } } else if (regd == 2) { /* Absolute. */ - dst = msp430dis_opcode (addr + 2, info); - cmd_len += 2; - sprintf (op, "&0x%04x", PS (dst)); - if (extended_dst) + if (msp430dis_opcode_signed (addr + 2, info, &dst, comm)) { - dst |= extended_dst << 16; - sprintf (op, "&0x%05x", dst & 0xfffff); + cmd_len += 2; + sprintf (op, "&0x%04x", PS (dst)); + if (extended_dst) + { + dst |= extended_dst << 16; + sprintf (op, "&0x%05x", dst & 0xfffff); + } } } else if (regd == 3) @@ -322,19 +394,19 @@ msp430_singleoperand (disassemble_info *info, else { /* Indexed. */ - dst = msp430dis_opcode (addr + 2, info); - cmd_len += 2; - if (extended_dst) + if (msp430dis_opcode_signed (addr + 2, info, &dst, comm)) { - dst |= extended_dst << 16; - if (dst & 0x80000) - dst |= -1 << 20; + cmd_len += 2; + if (extended_dst) + { + dst |= extended_dst << 16; + if (dst & 0x80000) + dst |= -1U << 20; + } + sprintf (op, "%d(r%d)", dst, regd); + if (dst > 9 || dst < 0) + sprintf (comm, "%05x", dst); } - else if (dst & 0x8000) - dst |= -1 << 16; - sprintf (op, "%d(r%d)", dst, regd); - if (dst > 9 || dst < 0) - sprintf (comm, "%05x", dst); } } break; @@ -352,6 +424,7 @@ msp430_singleoperand (disassemble_info *info, *cycles = 2; return 2; break; + default: cmd_len = 0; } @@ -397,7 +470,7 @@ msp430_doubleoperand (disassemble_info *info, Rm Register, x(Rm) Indexed, 0xXXXX Relative, - &0xXXXX Absolute + &0xXXXX Absolute emulated_ins dst basic_ins dst, dst. */ @@ -409,7 +482,7 @@ msp430_doubleoperand (disassemble_info *info, /* Register mode. */ if (regd == 3) { - strcpy (comm1, _("Illegal as emulation instr")); + strcpy (comm1, _("Warning: illegal as emulation instr")); return -1; } @@ -421,56 +494,65 @@ msp430_doubleoperand (disassemble_info *info, if (regd == 0) { /* PC relative, Symbolic. */ - dst = msp430dis_opcode (addr + 2, info); - cmd_len += 4; - *cycles = 6; - sprintf (op1, "0x%04x", PS (dst)); - sprintf (comm1, "PC rel. 0x%04x", - PS ((short) addr + 2 + dst)); - if (extended_dst) + if (msp430dis_opcode_signed (addr + 2, info, &dst, comm1)) { - dst |= extended_dst << 16; - if (dst & 0x80000) - dst |= -1 << 20; - sprintf (op1, "0x%05x", dst & 0xfffff); - sprintf (comm1, "PC rel. 0x%05lx", - (long)((addr + 2 + dst) & 0xfffff)); + cmd_len += 4; + *cycles = 6; + sprintf (op1, "0x%04x", PS (dst)); + sprintf (comm1, "PC rel. 0x%04x", + PS ((short) addr + 2 + dst)); + if (extension_word) + { + dst |= extended_dst << 16; + if (dst & 0x80000) + dst |= -1U << 20; + sprintf (op1, "0x%05x", dst & 0xfffff); + sprintf (comm1, "PC rel. 0x%05lx", + (long)((addr + 2 + dst) & 0xfffff)); + } } } else if (regd == 2) { /* Absolute. */ - dst = msp430dis_opcode (addr + 2, info); - /* If the 'src' field is not the same as the dst - then this is not an rla instruction. */ - if (dst != msp430dis_opcode (addr + 4, info)) - return 0; - cmd_len += 4; - *cycles = 6; - sprintf (op1, "&0x%04x", PS (dst)); - if (extended_dst) + if (msp430dis_opcode_signed (addr + 2, info, &dst, comm1)) { - dst |= extended_dst << 16; - sprintf (op1, "&0x%05x", dst & 0xfffff); + int src; + + /* If the 'src' field is not the same as the dst + then this is not an rla instruction. */ + if (msp430dis_opcode_signed (addr + 4, info, &src, comm2)) + { + if (src != dst) + return 0; + } + cmd_len += 4; + *cycles = 6; + sprintf (op1, "&0x%04x", PS (dst)); + if (extension_word) + { + dst |= extended_dst << 16; + sprintf (op1, "&0x%05x", dst & 0xfffff); + } } } else { /* Indexed. */ - dst = msp430dis_opcode (addr + 2, info); - if (extended_dst) + if (msp430dis_opcode_signed (addr + 2, info, &dst, comm1)) { - dst |= extended_dst << 16; - if (dst & 0x80000) - dst |= -1 << 20; + if (extension_word) + { + dst |= extended_dst << 16; + if (dst & 0x80000) + dst |= -1U << 20; + } + cmd_len += 4; + *cycles = 6; + sprintf (op1, "%d(r%d)", dst, regd); + if (dst > 9 || dst < -9) + sprintf (comm1, "#0x%05x", dst); } - else if (dst & 0x8000) - dst |= -1 << 16; - cmd_len += 4; - *cycles = 6; - sprintf (op1, "%d(r%d)", dst, regd); - if (dst > 9 || dst < -9) - sprintf (comm1, "#0x%05x", dst); } } @@ -484,7 +566,7 @@ msp430_doubleoperand (disassemble_info *info, if (ad == 0 && regd == 3) { /* R2/R3 are illegal as dest: may be data section. */ - strcpy (comm1, _("Illegal as 2-op instr")); + strcpy (comm1, _("Warning: illegal as 2-op instr")); return -1; } @@ -514,19 +596,22 @@ msp430_doubleoperand (disassemble_info *info, { *cycles = 3; /* Absolute. @pc+. */ - dst = msp430dis_opcode (addr + 2, info); - cmd_len += 2; - sprintf (op1, "#%d", dst); - if (dst > 9 || dst < 0) - sprintf (comm1, "#0x%04x", PS (dst)); - if (extended_src) + if (msp430dis_opcode_signed (addr + 2, info, &dst, comm1)) { - dst |= extended_src << 16; - if (dst & 0x80000) - dst |= -1 << 20; + cmd_len += 2; sprintf (op1, "#%d", dst); if (dst > 9 || dst < 0) - sprintf (comm1, "0x%05x", dst & 0xfffff); + sprintf (comm1, "#0x%04x", PS (dst)); + if (extension_word) + { + dst &= 0xffff; + dst |= extended_src << 16; + if (dst & 0x80000) + dst |= -1U << 20; + sprintf (op1, "#%d", dst); + if (dst > 9 || dst < 0) + sprintf (comm1, "0x%05x", dst & 0xfffff); + } } } else @@ -538,34 +623,40 @@ msp430_doubleoperand (disassemble_info *info, { *cycles = 4; /* PC relative. */ - dst = msp430dis_opcode (addr + 2, info); - cmd_len += 2; - sprintf (op1, "0x%04x", PS (dst)); - sprintf (comm1, "PC rel. 0x%04x", - PS ((short) addr + 2 + dst)); - if (extended_src) + if (msp430dis_opcode_signed (addr + 2, info, &dst, comm1)) { - dst |= extended_src << 16; - if (dst & 0x80000) - dst |= -1 << 20; - sprintf (op1, "0x%05x", dst & 0xfffff); - sprintf (comm1, "PC rel. 0x%05lx", - (long) ((addr + 2 + dst) & 0xfffff)); + cmd_len += 2; + sprintf (op1, "0x%04x", PS (dst)); + sprintf (comm1, "PC rel. 0x%04x", + PS ((short) addr + 2 + dst)); + if (extension_word) + { + dst &= 0xffff; + dst |= extended_src << 16; + if (dst & 0x80000) + dst |= -1U << 20; + sprintf (op1, "0x%05x", dst & 0xfffff); + sprintf (comm1, "PC rel. 0x%05lx", + (long) ((addr + 2 + dst) & 0xfffff)); + } } } else if (regs == 2) { *cycles = 2; /* Absolute. */ - dst = msp430dis_opcode (addr + 2, info); - cmd_len += 2; - sprintf (op1, "&0x%04x", PS (dst)); - sprintf (comm1, "0x%04x", PS (dst)); - if (extended_src) + if (msp430dis_opcode_signed (addr + 2, info, &dst, comm1)) { - dst |= extended_src << 16; - sprintf (op1, "&0x%05x", dst & 0xfffff); - * comm1 = 0; + cmd_len += 2; + sprintf (op1, "&0x%04x", PS (dst)); + sprintf (comm1, "0x%04x", PS (dst)); + if (extension_word) + { + dst &= 0xffff; + dst |= extended_src << 16; + sprintf (op1, "&0x%05x", dst & 0xfffff); + * comm1 = 0; + } } } else if (regs == 3) @@ -578,19 +669,20 @@ msp430_doubleoperand (disassemble_info *info, { *cycles = 3; /* Indexed. */ - dst = msp430dis_opcode (addr + 2, info); - cmd_len += 2; - if (extended_src) + if (msp430dis_opcode_signed (addr + 2, info, &dst, comm1)) { - dst |= extended_src << 16; - if (dst & 0x80000) - dst |= -1 << 20; + cmd_len += 2; + if (extension_word) + { + dst &= 0xffff; + dst |= extended_src << 16; + if (dst & 0x80000) + dst |= -1U << 20; + } + sprintf (op1, "%d(r%d)", dst, regs); + if (dst > 9 || dst < -9) + sprintf (comm1, "0x%05x", dst); } - else if (dst & 0x8000) - dst |= -1 << 16; - sprintf (op1, "%d(r%d)", dst, regs); - if (dst > 9 || dst < -9) - sprintf (comm1, "0x%05x", dst); } } @@ -621,50 +713,54 @@ msp430_doubleoperand (disassemble_info *info, { /* PC relative. */ *cycles += 1; - dst = msp430dis_opcode (addr + cmd_len, info); - sprintf (op2, "0x%04x", PS (dst)); - sprintf (comm2, "PC rel. 0x%04x", - PS ((short) addr + cmd_len + dst)); - if (extended_dst) + if (msp430dis_opcode_signed (addr + cmd_len, info, &dst, comm2)) { - dst |= extended_dst << 16; - if (dst & 0x80000) - dst |= -1 << 20; - sprintf (op2, "0x%05x", dst & 0xfffff); - sprintf (comm2, "PC rel. 0x%05lx", - (long)((addr + cmd_len + dst) & 0xfffff)); + sprintf (op2, "0x%04x", PS (dst)); + sprintf (comm2, "PC rel. 0x%04x", + PS ((short) addr + cmd_len + dst)); + if (extension_word) + { + dst |= extended_dst << 16; + if (dst & 0x80000) + dst |= -1U << 20; + sprintf (op2, "0x%05x", dst & 0xfffff); + sprintf (comm2, "PC rel. 0x%05lx", + (long)((addr + cmd_len + dst) & 0xfffff)); + } } cmd_len += 2; } else if (regd == 2) { /* Absolute. */ - dst = msp430dis_opcode (addr + cmd_len, info); - cmd_len += 2; - sprintf (op2, "&0x%04x", PS (dst)); - if (extended_dst) + if (msp430dis_opcode_signed (addr + cmd_len, info, &dst, comm2)) { - dst |= extended_dst << 16; - sprintf (op2, "&0x%05x", dst & 0xfffff); + cmd_len += 2; + sprintf (op2, "&0x%04x", PS (dst)); + if (extension_word) + { + dst |= extended_dst << 16; + sprintf (op2, "&0x%05x", dst & 0xfffff); + } } } else { - dst = msp430dis_opcode (addr + cmd_len, info); - cmd_len += 2; - if (dst & 0x8000) - dst |= -1 << 16; - if (dst > 9 || dst < 0) - sprintf (comm2, "0x%04x", PS (dst)); - if (extended_dst) + if (msp430dis_opcode_signed (addr + cmd_len, info, &dst, comm2)) { - dst |= extended_dst << 16; - if (dst & 0x80000) - dst |= -1 << 20; + cmd_len += 2; if (dst > 9 || dst < 0) - sprintf (comm2, "0x%05x", dst & 0xfffff); + sprintf (comm2, "0x%04x", PS (dst)); + if (extension_word) + { + dst |= extended_dst << 16; + if (dst & 0x80000) + dst |= -1U << 20; + if (dst > 9 || dst < 0) + sprintf (comm2, "0x%05x", dst & 0xfffff); + } + sprintf (op2, "%d(r%d)", dst, regd); } - sprintf (op2, "%d(r%d)", dst, regd); } } @@ -683,7 +779,8 @@ msp430_branchinstr (disassemble_info *info, int regs = 0, regd = 0; int as = 0; int cmd_len = 2; - short dst = 0; + int dst = 0; + unsigned short udst = 0; regd = insn & 0x0f; regs = (insn & 0x0f00) >> 8; @@ -719,9 +816,11 @@ msp430_branchinstr (disassemble_info *info, { /* Absolute. @pc+ */ *cycles = 3; - dst = msp430dis_opcode (addr + 2, info); - cmd_len += 2; - sprintf (op1, "#0x%04x", PS (dst)); + if (msp430dis_opcode_unsigned (addr + 2, info, &udst, comm1)) + { + cmd_len += 2; + sprintf (op1, "#0x%04x", PS (udst)); + } } else * cycles = print_as3_reg_name (regs, op1, comm1, 1, 1, 2); @@ -733,19 +832,23 @@ msp430_branchinstr (disassemble_info *info, if (regs == 0) { /* PC relative. */ - dst = msp430dis_opcode (addr + 2, info); - cmd_len += 2; - (*cycles)++; - sprintf (op1, "0x%04x", PS (dst)); - sprintf (comm1, "PC rel. 0x%04x", - PS ((short) addr + 2 + dst)); + if (msp430dis_opcode_signed (addr + 2, info, &dst, comm1)) + { + cmd_len += 2; + (*cycles)++; + sprintf (op1, "0x%04x", PS (dst)); + sprintf (comm1, "PC rel. 0x%04x", + PS ((short) addr + 2 + dst)); + } } else if (regs == 2) { /* Absolute. */ - dst = msp430dis_opcode (addr + 2, info); - cmd_len += 2; - sprintf (op1, "&0x%04x", PS (dst)); + if (msp430dis_opcode_unsigned (addr + 2, info, &udst, comm1)) + { + cmd_len += 2; + sprintf (op1, "&0x%04x", PS (udst)); + } } else if (regs == 3) { @@ -756,11 +859,11 @@ msp430_branchinstr (disassemble_info *info, else { /* Indexed. */ - dst = msp430dis_opcode (addr + 2, info); - cmd_len += 2; - if (dst & 0x8000) - dst |= -1 << 16; - sprintf (op1, "%d(r%d)", dst, regs); + if (msp430dis_opcode_signed (addr + 2, info, &dst, comm1)) + { + cmd_len += 2; + sprintf (op1, "%d(r%d)", dst, regs); + } } } @@ -780,7 +883,7 @@ msp430x_calla_instr (disassemble_info * info, int am = (insn & 0xf0) >> 4; int cmd_len = 2; unsigned short udst = 0; - short dst = 0; + int dst = 0; switch (am) { @@ -791,13 +894,15 @@ msp430x_calla_instr (disassemble_info * info, case 5: /* CALLA x(Rdst) */ *cycles = 3; - dst = msp430dis_opcode (addr + 2, info); - cmd_len += 2; - sprintf (op1, "%d(r%d)", dst, reg); - if (reg == 0) - sprintf (comm1, "PC rel. 0x%05lx", (long) (addr + 2 + dst)); - else - sprintf (comm1, "0x%05x", dst); + if (msp430dis_opcode_signed (addr + 2, info, &dst, comm1)) + { + cmd_len += 2; + sprintf (op1, "%d(r%d)", dst, reg); + if (reg == 0) + sprintf (comm1, "PC rel. 0x%05lx", (long) (addr + 2 + dst)); + else + sprintf (comm1, "0x%05x", dst); + } break; case 6: /* CALLA @Rdst */ @@ -811,32 +916,38 @@ msp430x_calla_instr (disassemble_info * info, break; case 8: /* CALLA &abs20 */ - udst = msp430dis_opcode (addr + 2, info); - cmd_len += 2; - *cycles = 4; - sprintf (op1, "&%d", (ureg << 16) + udst); - sprintf (comm1, "0x%05x", (ureg << 16) + udst); + if (msp430dis_opcode_unsigned (addr + 2, info, &udst, comm1)) + { + cmd_len += 2; + *cycles = 4; + sprintf (op1, "&%d", (ureg << 16) + udst); + sprintf (comm1, "0x%05x", (ureg << 16) + udst); + } break; case 9: /* CALLA pcrel-sym */ - dst = msp430dis_opcode (addr + 2, info); - cmd_len += 2; - *cycles = 4; - sprintf (op1, "%d(PC)", (reg << 16) + dst); - sprintf (comm1, "PC rel. 0x%05lx", - (long) (addr + 2 + dst + (reg << 16))); + if (msp430dis_opcode_signed (addr + 2, info, &dst, comm1)) + { + cmd_len += 2; + *cycles = 4; + sprintf (op1, "%d(PC)", (reg << 16) + dst); + sprintf (comm1, "PC rel. 0x%05lx", + (long) (addr + 2 + dst + (reg << 16))); + } break; case 11: /* CALLA #imm20 */ - udst = msp430dis_opcode (addr + 2, info); - cmd_len += 2; - *cycles = 4; - sprintf (op1, "#%d", (ureg << 16) + udst); - sprintf (comm1, "0x%05x", (ureg << 16) + udst); + if (msp430dis_opcode_unsigned (addr + 2, info, &udst, comm1)) + { + cmd_len += 2; + *cycles = 4; + sprintf (op1, "#%d", (ureg << 16) + udst); + sprintf (comm1, "0x%05x", (ureg << 16) + udst); + } break; default: - strcpy (comm1, _("unrecognised CALLA addressing mode")); + strcpy (comm1, _("Warning: unrecognised CALLA addressing mode")); return -1; } @@ -855,9 +966,9 @@ print_insn_msp430 (bfd_vma addr, disassemble_info *info) int cycles = 0; char *bc = ""; unsigned short extension_word = 0; + unsigned short bits; - insn = msp430dis_opcode (addr, info); - if (insn == (unsigned short) -1) + if (! msp430dis_opcode_unsigned (addr, info, &insn, NULL)) { prin (stream, ".word 0xffff; ????"); return 2; @@ -877,8 +988,7 @@ print_insn_msp430 (bfd_vma addr, disassemble_info *info) { extension_word = insn; addr += 2; - insn = msp430dis_opcode (addr, info); - if (insn == (unsigned short) -1) + if (! msp430dis_opcode_unsigned (addr, info, &insn, NULL)) { prin (stream, ".word 0x%04x, 0xffff; ????", extension_word); @@ -936,7 +1046,7 @@ print_insn_msp430 (bfd_vma addr, disassemble_info *info) sprintf (comm1, "20-bit words"); bc =".a"; } - + cycles = 2; /*FIXME*/ cmd_len = 2; break; @@ -963,10 +1073,13 @@ print_insn_msp430 (bfd_vma addr, disassemble_info *info) else { n <<= 16; - n |= msp430dis_opcode (addr + 2, info); - sprintf (op1, "#%d", n); - if (n > 9 || n < 0) - sprintf (comm1, "0x%05x", n); + if (msp430dis_opcode_unsigned (addr + 2, info, &bits, comm1)) + { + n |= bits; + sprintf (op1, "#%d", n); + if (n > 9 || n < 0) + sprintf (comm1, "0x%05x", n); + } cmd_len = 4; } sprintf (op2, "r%d", reg); @@ -984,7 +1097,7 @@ print_insn_msp430 (bfd_vma addr, disassemble_info *info) if (strcmp (opcode->name, "bra") != 0) sprintf (op2, "r%d", reg); break; - + case 1: /* MOVA @Rsrc+, Rdst */ cmd_len = 2; if (strcmp (opcode->name, "reta") != 0) @@ -994,77 +1107,86 @@ print_insn_msp430 (bfd_vma addr, disassemble_info *info) sprintf (op2, "r%d", reg); } break; - + case 2: /* MOVA &abs20, Rdst */ cmd_len = 4; n <<= 16; - n |= msp430dis_opcode (addr + 2, info); - sprintf (op1, "&%d", n); - if (n > 9 || n < 0) - sprintf (comm1, "0x%05x", n); - if (strcmp (opcode->name, "bra") != 0) - sprintf (op2, "r%d", reg); + if (msp430dis_opcode_unsigned (addr + 2, info, &bits, comm1)) + { + n |= bits; + sprintf (op1, "&%d", n); + if (n > 9 || n < 0) + sprintf (comm1, "0x%05x", n); + if (strcmp (opcode->name, "bra") != 0) + sprintf (op2, "r%d", reg); + } break; - + case 3: /* MOVA x(Rsrc), Rdst */ cmd_len = 4; if (strcmp (opcode->name, "bra") != 0) sprintf (op2, "r%d", reg); reg = n; - n = msp430dis_opcode (addr + 2, info); - if (n & 0x8000) - n |= -1 << 16; - sprintf (op1, "%d(r%d)", n, reg); - if (n > 9 || n < 0) + if (msp430dis_opcode_signed (addr + 2, info, &n, comm1)) { - if (reg == 0) - sprintf (comm1, "PC rel. 0x%05lx", - (long) (addr + 2 + n)); - else - sprintf (comm1, "0x%05x", n); + sprintf (op1, "%d(r%d)", n, reg); + if (n > 9 || n < 0) + { + if (reg == 0) + sprintf (comm1, "PC rel. 0x%05lx", + (long) (addr + 2 + n)); + else + sprintf (comm1, "0x%05x", n); + } } break; case 6: /* MOVA Rsrc, &abs20 */ cmd_len = 4; reg <<= 16; - reg |= msp430dis_opcode (addr + 2, info); - sprintf (op1, "r%d", n); - sprintf (op2, "&%d", reg); - if (reg > 9 || reg < 0) - sprintf (comm2, "0x%05x", reg); + if (msp430dis_opcode_unsigned (addr + 2, info, &bits, comm2)) + { + reg |= bits; + sprintf (op1, "r%d", n); + sprintf (op2, "&%d", reg); + if (reg > 9 || reg < 0) + sprintf (comm2, "0x%05x", reg); + } break; case 7: /* MOVA Rsrc, x(Rdst) */ cmd_len = 4; sprintf (op1, "r%d", n); - n = msp430dis_opcode (addr + 2, info); - if (n & 0x8000) - n |= -1 << 16; - sprintf (op2, "%d(r%d)", n, reg); - if (n > 9 || n < 0) + if (msp430dis_opcode_signed (addr + 2, info, &n, comm2)) { - if (reg == 0) - sprintf (comm2, "PC rel. 0x%05lx", - (long) (addr + 2 + n)); - else - sprintf (comm2, "0x%05x", n); + sprintf (op2, "%d(r%d)", n, reg); + if (n > 9 || n < 0) + { + if (reg == 0) + sprintf (comm2, "PC rel. 0x%05lx", + (long) (addr + 2 + n)); + else + sprintf (comm2, "0x%05x", n); + } } break; - + case 8: /* MOVA #imm20, Rdst */ cmd_len = 4; n <<= 16; - n |= msp430dis_opcode (addr + 2, info); - if (n & 0x80000) - n |= -1 << 20; - sprintf (op1, "#%d", n); - if (n > 9 || n < 0) - sprintf (comm1, "0x%05x", n); - if (strcmp (opcode->name, "bra") != 0) - sprintf (op2, "r%d", reg); + if (msp430dis_opcode_unsigned (addr + 2, info, &bits, comm1)) + { + n |= bits; + if (n & 0x80000) + n |= -1U << 20; + sprintf (op1, "#%d", n); + if (n > 9 || n < 0) + sprintf (comm1, "0x%05x", n); + if (strcmp (opcode->name, "bra") != 0) + sprintf (op2, "r%d", reg); + } break; - + case 12: /* MOVA Rsrc, Rdst */ cmd_len = 2; sprintf (op1, "r%d", n); @@ -1102,15 +1224,15 @@ print_insn_msp430 (bfd_vma addr, disassemble_info *info) } else if (extension_word) { - if (extension_word & (1 << 6)) + if (extension_word & BYTE_OPERATION) bc = ".w"; else { bc = ".?"; - sprintf (comm2, _("Reserved use of A/L and B/W bits detected")); + sprintf (comm2, _("Warning: reserved use of A/L and B/W bits detected")); } } - + break; case 1: cmd_len += @@ -1124,7 +1246,7 @@ print_insn_msp430 (bfd_vma addr, disassemble_info *info) if (insn & BYTE_OPERATION) { bc = ".?"; - sprintf (comm2, _("Reserved use of A/L and B/W bits detected")); + sprintf (comm2, _("Warning: reserved use of A/L and B/W bits detected")); } else if (extension_word & BYTE_OPERATION) bc = ".w"; @@ -1145,7 +1267,7 @@ print_insn_msp430 (bfd_vma addr, disassemble_info *info) else { bc = ".?"; - sprintf (comm2, _("Reserved use of A/L and B/W bits detected")); + sprintf (comm2, _("Warning: reserved use of A/L and B/W bits detected")); } } break; @@ -1181,7 +1303,12 @@ print_insn_msp430 (bfd_vma addr, disassemble_info *info) prin (stream, "rpt #%d { ", (extension_word & 0xf) + 1); } - if (extension_word && opcode->name[strlen (opcode->name) - 1] != 'x') + /* Special case: RRC with an extension word and the ZC bit set is actually RRU. */ + if (extension_word + && (extension_word & IGNORE_CARRY_BIT) + && strcmp (opcode->name, "rrc") == 0) + (*prin) (stream, "rrux%s", bc); + else if (extension_word && opcode->name[strlen (opcode->name) - 1] != 'x') (*prin) (stream, "%sx%s", opcode->name, bc); else (*prin) (stream, "%s%s", opcode->name, bc);