X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=opcodes%2Fmsp430-dis.c;h=9d7edbeb9039e32e698a27a1a42a58b2f8eea3ab;hb=645ea3ea629261e7e66127db1438f64019fd5d08;hp=1b5ffb1ec1229b23cbf8dec88c54a60ba08510e1;hpb=3ab489312135d66f65a23985dd2341340842db1d;p=deliverable%2Fbinutils-gdb.git diff --git a/opcodes/msp430-dis.c b/opcodes/msp430-dis.c index 1b5ffb1ec1..9d7edbeb90 100644 --- a/opcodes/msp430-dis.c +++ b/opcodes/msp430-dis.c @@ -1,21 +1,25 @@ /* Disassemble MSP430 instructions. - Copyright (C) 2002, 2004 Free Software Foundation, Inc. + Copyright (C) 2002, 2004, 2005, 2007, 2009, 2010 + Free Software Foundation, Inc. Contributed by Dmitry Diky - This program is free software; you can redistribute it and/or modify + This file is part of the GNU opcodes library. + + This library is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - + the Free Software Foundation; either version 3, or (at your option) + any later version. + + It is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public + License for more details. + You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, + MA 02110-1301, USA. */ #include #include @@ -31,28 +35,10 @@ #undef DASM_SECTION -static unsigned short msp430dis_opcode - PARAMS ((bfd_vma, disassemble_info *)); -int print_insn_msp430 - PARAMS ((bfd_vma, disassemble_info *)); -int msp430_nooperands - PARAMS ((struct msp430_opcode_s *, bfd_vma, unsigned short, char *, int *)); -int msp430_singleoperand - PARAMS ((disassemble_info *, struct msp430_opcode_s *, bfd_vma, unsigned short, - char *, char *, int *)); -int msp430_doubleoperand - PARAMS ((disassemble_info *, struct msp430_opcode_s *, bfd_vma, unsigned short, - char *, char *, char *, char *, int *)); -int msp430_branchinstr - PARAMS ((disassemble_info *, struct msp430_opcode_s *, bfd_vma, unsigned short, - char *, char *, int *)); - #define PS(x) (0xffff & (x)) static unsigned short -msp430dis_opcode (addr, info) - bfd_vma addr; - disassemble_info *info; +msp430dis_opcode (bfd_vma addr, disassemble_info *info) { bfd_byte buffer[2]; int status; @@ -66,138 +52,12 @@ msp430dis_opcode (addr, info) return bfd_getl16 (buffer); } -int -print_insn_msp430 (addr, info) - bfd_vma addr; - disassemble_info *info; -{ - void *stream = info->stream; - fprintf_ftype prin = info->fprintf_func; - struct msp430_opcode_s *opcode; - char op1[32], op2[32], comm1[64], comm2[64]; - int cmd_len = 0; - unsigned short insn; - int cycles = 0; - char *bc = ""; - char dinfo[32]; /* Debug purposes. */ - - insn = msp430dis_opcode (addr, info); - sprintf (dinfo, "0x%04x", insn); - - if (((int) addr & 0xffff) > 0xffdf) - { - (*prin) (stream, "interrupt service routine at 0x%04x", 0xffff & insn); - return 2; - } - - *comm1 = 0; - *comm2 = 0; - - for (opcode = msp430_opcodes; opcode->name; opcode++) - { - if ((insn & opcode->bin_mask) == opcode->bin_opcode - && opcode->bin_opcode != 0x9300) - { - *op1 = 0; - *op2 = 0; - *comm1 = 0; - *comm2 = 0; - - /* r0 as destination. Ad should be zero. */ - if (opcode->insn_opnumb == 3 && (insn & 0x000f) == 0 - && (0x0080 & insn) == 0) - { - cmd_len = - msp430_branchinstr (info, opcode, addr, insn, op1, comm1, - &cycles); - if (cmd_len) - break; - } - - switch (opcode->insn_opnumb) - { - case 0: - cmd_len = msp430_nooperands (opcode, addr, insn, comm1, &cycles); - break; - case 2: - cmd_len = - msp430_doubleoperand (info, opcode, addr, insn, op1, op2, - comm1, comm2, &cycles); - if (insn & BYTE_OPERATION) - bc = ".b"; - break; - case 1: - cmd_len = - msp430_singleoperand (info, opcode, addr, insn, op1, comm1, - &cycles); - if (insn & BYTE_OPERATION && opcode->fmt != 3) - bc = ".b"; - break; - default: - break; - } - } - - if (cmd_len) - break; - } - - dinfo[5] = 0; - - if (cmd_len < 1) - { - /* Unknown opcode, or invalid combination of operands. */ - (*prin) (stream, ".word 0x%04x; ????", PS (insn)); - return 2; - } - - (*prin) (stream, "%s%s", opcode->name, bc); - - if (*op1) - (*prin) (stream, "\t%s", op1); - if (*op2) - (*prin) (stream, ","); - - if (strlen (op1) < 7) - (*prin) (stream, "\t"); - if (!strlen (op1)) - (*prin) (stream, "\t"); - - if (*op2) - (*prin) (stream, "%s", op2); - if (strlen (op2) < 8) - (*prin) (stream, "\t"); - - if (*comm1 || *comm2) - (*prin) (stream, ";"); - else if (cycles) - { - if (*op2) - (*prin) (stream, ";"); - else - { - if (strlen (op1) < 7) - (*prin) (stream, ";"); - else - (*prin) (stream, "\t;"); - } - } - if (*comm1) - (*prin) (stream, "%s", comm1); - if (*comm1 && *comm2) - (*prin) (stream, ","); - if (*comm2) - (*prin) (stream, " %s", comm2); - return cmd_len; -} - -int -msp430_nooperands (opcode, addr, insn, comm, cycles) - struct msp430_opcode_s *opcode; - bfd_vma addr ATTRIBUTE_UNUSED; - unsigned short insn ATTRIBUTE_UNUSED; - char *comm; - int *cycles; +static int +msp430_nooperands (struct msp430_opcode_s *opcode, + bfd_vma addr ATTRIBUTE_UNUSED, + unsigned short insn ATTRIBUTE_UNUSED, + char *comm, + int *cycles) { /* Pop with constant. */ if (insn == 0x43b2) @@ -222,16 +82,14 @@ msp430_nooperands (opcode, addr, insn, comm, cycles) return 2; } - -int -msp430_singleoperand (info, opcode, addr, insn, op, comm, cycles) - disassemble_info *info; - struct msp430_opcode_s *opcode; - bfd_vma addr; - unsigned short insn; - char *op; - char *comm; - int *cycles; +static int +msp430_singleoperand (disassemble_info *info, + struct msp430_opcode_s *opcode, + bfd_vma addr, + unsigned short insn, + char *op, + char *comm, + int *cycles) { int regs = 0, regd = 0; int ad = 0, as = 0; @@ -277,7 +135,7 @@ msp430_singleoperand (info, opcode, addr, insn, op, comm, cycles) else sprintf (op, "r%d", regd); } - else /* ad == 1 msp430dis_opcode. */ + else /* ad == 1 msp430dis_opcode. */ { if (regd == 0) { @@ -308,7 +166,6 @@ msp430_singleoperand (info, opcode, addr, insn, op, comm, cycles) break; case 2: /* rrc, push, call, swpb, rra, sxt, push, call, reti etc... */ - if (as == 0) { if (regd == 3) @@ -427,15 +284,16 @@ msp430_singleoperand (info, opcode, addr, insn, op, comm, cycles) return cmd_len; } -int -msp430_doubleoperand (info, opcode, addr, insn, op1, op2, comm1, comm2, cycles) - disassemble_info *info; - struct msp430_opcode_s *opcode; - bfd_vma addr; - unsigned short insn; - char *op1, *op2; - char *comm1, *comm2; - int *cycles; +static int +msp430_doubleoperand (disassemble_info *info, + struct msp430_opcode_s *opcode, + bfd_vma addr, + unsigned short insn, + char *op1, + char *op2, + char *comm1, + char *comm2, + int *cycles) { int regs = 0, regd = 0; int ad = 0, as = 0; @@ -467,7 +325,7 @@ msp430_doubleoperand (info, opcode, addr, insn, op1, op2, comm1, comm2, cycles) /* Register mode. */ if (regd == 3) { - strcpy (comm1, "Illegal as emulation instr"); + strcpy (comm1, _("Illegal as emulation instr")); return -1; } @@ -518,7 +376,7 @@ msp430_doubleoperand (info, opcode, addr, insn, op1, op2, comm1, comm2, cycles) if (ad == 0 && regd == 3) { /* R2/R3 are illegal as dest: may be data section. */ - strcpy (comm1, "Illegal as 2-op instr"); + strcpy (comm1, _("Illegal as 2-op instr")); return -1; } @@ -579,7 +437,7 @@ msp430_doubleoperand (info, opcode, addr, insn, op1, op2, comm1, comm2, cycles) else if (regs == 0) { *cycles = 3; - /* Absolute. @pc+ */ + /* Absolute. @pc+. */ dst = msp430dis_opcode (addr + 2, info); cmd_len += 2; sprintf (op1, "#%d", dst); @@ -647,7 +505,7 @@ msp430_doubleoperand (info, opcode, addr, insn, op1, op2, comm1, comm2, cycles) else sprintf (op2, "r%d", regd); } - else /* ad == 1. */ + else /* ad == 1. */ { * cycles += 3; @@ -679,26 +537,23 @@ msp430_doubleoperand (info, opcode, addr, insn, op1, op2, comm1, comm2, cycles) return cmd_len; } - -int -msp430_branchinstr (info, opcode, addr, insn, op1, comm1, cycles) - disassemble_info *info; - struct msp430_opcode_s *opcode ATTRIBUTE_UNUSED; - bfd_vma addr ATTRIBUTE_UNUSED; - unsigned short insn; - char *op1; - char *comm1; - int *cycles; +static int +msp430_branchinstr (disassemble_info *info, + struct msp430_opcode_s *opcode ATTRIBUTE_UNUSED, + bfd_vma addr ATTRIBUTE_UNUSED, + unsigned short insn, + char *op1, + char *comm1, + int *cycles) { int regs = 0, regd = 0; - int ad = 0, as = 0; + int as = 0; int cmd_len = 2; short dst = 0; regd = insn & 0x0f; regs = (insn & 0x0f00) >> 8; as = (insn & 0x0030) >> 4; - ad = (insn & 0x0080) >> 7; if (regd != 0) /* Destination register is not a PC. */ return 0; @@ -807,3 +662,126 @@ msp430_branchinstr (info, opcode, addr, insn, op1, comm1, cycles) return cmd_len; } + +int +print_insn_msp430 (bfd_vma addr, disassemble_info *info) +{ + void *stream = info->stream; + fprintf_ftype prin = info->fprintf_func; + struct msp430_opcode_s *opcode; + char op1[32], op2[32], comm1[64], comm2[64]; + int cmd_len = 0; + unsigned short insn; + int cycles = 0; + char *bc = ""; + char dinfo[32]; /* Debug purposes. */ + + insn = msp430dis_opcode (addr, info); + sprintf (dinfo, "0x%04x", insn); + + if (((int) addr & 0xffff) > 0xffdf) + { + (*prin) (stream, "interrupt service routine at 0x%04x", 0xffff & insn); + return 2; + } + + *comm1 = 0; + *comm2 = 0; + + for (opcode = msp430_opcodes; opcode->name; opcode++) + { + if ((insn & opcode->bin_mask) == opcode->bin_opcode + && opcode->bin_opcode != 0x9300) + { + *op1 = 0; + *op2 = 0; + *comm1 = 0; + *comm2 = 0; + + /* r0 as destination. Ad should be zero. */ + if (opcode->insn_opnumb == 3 && (insn & 0x000f) == 0 + && (0x0080 & insn) == 0) + { + cmd_len = + msp430_branchinstr (info, opcode, addr, insn, op1, comm1, + &cycles); + if (cmd_len) + break; + } + + switch (opcode->insn_opnumb) + { + case 0: + cmd_len = msp430_nooperands (opcode, addr, insn, comm1, &cycles); + break; + case 2: + cmd_len = + msp430_doubleoperand (info, opcode, addr, insn, op1, op2, + comm1, comm2, &cycles); + if (insn & BYTE_OPERATION) + bc = ".b"; + break; + case 1: + cmd_len = + msp430_singleoperand (info, opcode, addr, insn, op1, comm1, + &cycles); + if (insn & BYTE_OPERATION && opcode->fmt != 3) + bc = ".b"; + break; + default: + break; + } + } + + if (cmd_len) + break; + } + + dinfo[5] = 0; + + if (cmd_len < 1) + { + /* Unknown opcode, or invalid combination of operands. */ + (*prin) (stream, ".word 0x%04x; ????", PS (insn)); + return 2; + } + + (*prin) (stream, "%s%s", opcode->name, bc); + + if (*op1) + (*prin) (stream, "\t%s", op1); + if (*op2) + (*prin) (stream, ","); + + if (strlen (op1) < 7) + (*prin) (stream, "\t"); + if (!strlen (op1)) + (*prin) (stream, "\t"); + + if (*op2) + (*prin) (stream, "%s", op2); + if (strlen (op2) < 8) + (*prin) (stream, "\t"); + + if (*comm1 || *comm2) + (*prin) (stream, ";"); + else if (cycles) + { + if (*op2) + (*prin) (stream, ";"); + else + { + if (strlen (op1) < 7) + (*prin) (stream, ";"); + else + (*prin) (stream, "\t;"); + } + } + if (*comm1) + (*prin) (stream, "%s", comm1); + if (*comm1 && *comm2) + (*prin) (stream, ","); + if (*comm2) + (*prin) (stream, " %s", comm2); + return cmd_len; +}