X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=opcodes%2Fbfin-dis.c;h=a510db1e764b0c19bbdce2e919eb6f0f86e36a2d;hb=0b7691fd6ec26dfb326e9c35cf4c5b157d3998df;hp=d74fa58e93e6240bd8ec48e7b663becb87bd018b;hpb=086134ec0edd4a54682c435552c8ae20f65fbb23;p=deliverable%2Fbinutils-gdb.git diff --git a/opcodes/bfin-dis.c b/opcodes/bfin-dis.c index d74fa58e93..a510db1e76 100644 --- a/opcodes/bfin-dis.c +++ b/opcodes/bfin-dis.c @@ -1,5 +1,5 @@ /* Disassemble ADI Blackfin Instructions. - Copyright 2005, 2007 Free Software Foundation, Inc. + Copyright 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. This file is part of libopcodes. @@ -53,6 +53,9 @@ typedef long TIword; typedef unsigned int bu32; +static char comment = 0; +static char parallel = 0; + typedef enum { c_0, c_1, c_4, c_2, c_uimm2, c_uimm3, c_imm3, c_pcrel4, @@ -62,20 +65,20 @@ typedef enum c_uimm16s4d, c_uimm16, c_pcrel24, c_uimm32, c_imm32, c_huimm32, c_huimm32e, } const_forms_t; -static struct +static const struct { - char *name; - int nbits; - char reloc; - char issigned; - char pcrel; - char scale; - char offset; - char negative; - char positive; - char decimal; - char leading; - char exact; + const char *name; + const int nbits; + const char reloc; + const char issigned; + const char pcrel; + const char scale; + const char offset; + const char negative; + const char positive; + const char decimal; + const char leading; + const char exact; } constant_formats[] = { { "0", 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0}, @@ -123,14 +126,8 @@ static struct { "huimm32e", 32, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1}, }; -int _print_insn_bfin (bfd_vma pc, disassemble_info * outf); -int print_insn_bfin (bfd_vma pc, disassemble_info * outf); - -static char comment = 0; -static char parallel = 0; - -static char * -fmtconst (const_forms_t cf, TIword x, bfd_vma pc, disassemble_info * outf) +static const char * +fmtconst (const_forms_t cf, TIword x, bfd_vma pc, disassemble_info *outf) { static char buf[60]; @@ -148,7 +145,7 @@ fmtconst (const_forms_t cf, TIword x, bfd_vma pc, disassemble_info * outf) } else { - sprintf (buf, "%lx", x); + sprintf (buf, "%lx", (unsigned long) x); return buf; } } @@ -186,7 +183,7 @@ fmtconst (const_forms_t cf, TIword x, bfd_vma pc, disassemble_info * outf) if (constant_formats[cf].issigned && x < 0) sprintf (buf, "-0x%x", abs (x)); else - sprintf (buf, "0x%lx", x); + sprintf (buf, "0x%lx", (unsigned long) x); } return buf; @@ -245,6 +242,7 @@ enum machine_registers REG_BL0, REG_BL1, REG_BL2, REG_BL3, REG_LL0, REG_LL1, REG_LL2, REG_LL3, REG_IH0, REG_IH1, REG_IH2, REG_IH3, REG_MH0, REG_MH1, REG_MH2, REG_MH3, REG_BH0, REG_BH1, REG_BH2, REG_BH3, REG_LH0, REG_LH1, REG_LH2, REG_LH3, + REG_AC0_COPY, REG_V_COPY, REG_RND_MOD, REG_LASTREG, }; @@ -257,7 +255,7 @@ enum reg_class LIM_REG_CLASSES }; -static char *reg_names[] = +static const char *reg_names[] = { "R0.L", "R1.L", "R2.L", "R3.L", "R4.L", "R5.L", "R6.L", "R7.L", "R0.H", "R1.H", "R2.H", "R3.H", "R4.H", "R5.H", "R6.H", "R7.H", @@ -280,6 +278,7 @@ static char *reg_names[] = "B0.L", "B1.L", "B2.L", "B3.L", "L0.L", "L1.L", "L2.L", "L3.L", "I0.H", "I1.H", "I2.H", "I3.H", "M0.H", "M1.H", "M2.H", "M3.H", "B0.H", "B1.H", "B2.H", "B3.H", "L0.H", "L1.H", "L2.H", "L3.H", + "AC0_COPY", "V_COPY", "RND_MOD", "LASTREG", 0 }; @@ -317,7 +316,6 @@ static enum machine_registers decode_dregs_byte[] = }; #define dregs_byte(x) REGNAME (decode_dregs_byte[(x) & 7]) -#define dregs_pair(x) REGNAME (decode_dregs_pair[(x) & 7]) /* P(0..5) SP FP. */ static enum machine_registers decode_pregs[] = @@ -394,7 +392,7 @@ static enum machine_registers decode_regs_hi[] = { REG_RH0, REG_RH1, REG_RH2, REG_RH3, REG_RH4, REG_RH5, REG_RH6, REG_RH7, REG_PH0, REG_PH1, REG_PH2, REG_PH3, REG_PH4, REG_PH5, REG_SHP, REG_FHP, - REG_IH0, REG_IH1, REG_IH2, REG_IH3, REG_MH0, REG_MH1, REG_LH2, REG_MH3, + REG_IH0, REG_IH1, REG_IH2, REG_IH3, REG_MH0, REG_MH1, REG_MH2, REG_MH3, REG_BH0, REG_BH1, REG_BH2, REG_BH3, REG_LH0, REG_LH1, REG_LH2, REG_LH3, }; @@ -402,15 +400,17 @@ static enum machine_registers decode_regs_hi[] = static enum machine_registers decode_statbits[] = { - REG_AZ, REG_AN, REG_LASTREG, REG_LASTREG, REG_LASTREG, REG_LASTREG, REG_AQ, REG_LASTREG, - REG_LASTREG, REG_LASTREG, REG_LASTREG, REG_LASTREG, REG_AC0, REG_AC1, REG_LASTREG, REG_LASTREG, - REG_AV0, REG_AV0S, REG_AV1, REG_AV1S, REG_LASTREG, REG_LASTREG, REG_LASTREG, REG_LASTREG, - REG_V, REG_VS, REG_LASTREG, REG_LASTREG, REG_LASTREG, REG_LASTREG, REG_LASTREG, REG_LASTREG, + REG_AZ, REG_AN, REG_AC0_COPY, REG_V_COPY, + REG_LASTREG, REG_LASTREG, REG_AQ, REG_LASTREG, + REG_RND_MOD, REG_LASTREG, REG_LASTREG, REG_LASTREG, + REG_AC0, REG_AC1, REG_LASTREG, REG_LASTREG, + REG_AV0, REG_AV0S, REG_AV1, REG_AV1S, + REG_LASTREG, REG_LASTREG, REG_LASTREG, REG_LASTREG, + REG_V, REG_VS, REG_LASTREG, REG_LASTREG, + REG_LASTREG, REG_LASTREG, REG_LASTREG, REG_LASTREG, }; -#define statbits(x) REGNAME (decode_statbits[(x) & 31]) -#define ignore_bits(x) REGNAME (decode_ignore_bits[(x) & 7]) -#define ccstat(x) REGNAME (decode_ccstat[(x) & 0]) +#define statbits(x) REGNAME (decode_statbits[(x) & 31]) /* LC0 LC1. */ static enum machine_registers decode_counters[] = @@ -432,9 +432,23 @@ static enum machine_registers decode_allregs[] = REG_A0x, REG_A0w, REG_A1x, REG_A1w, REG_GP, REG_LASTREG, REG_ASTAT, REG_RETS, REG_LASTREG, REG_LASTREG, REG_LASTREG, REG_LASTREG, REG_LASTREG, REG_LASTREG, REG_LASTREG, REG_LASTREG, REG_LC0, REG_LT0, REG_LB0, REG_LC1, REG_LT1, REG_LB1, REG_CYCLES, REG_CYCLES2, - REG_USP, REG_SEQSTAT, REG_SYSCFG, REG_RETI, REG_RETX, REG_RETN, REG_RETE, REG_EMUDAT, REG_LASTREG, + REG_USP, REG_SEQSTAT, REG_SYSCFG, REG_RETI, REG_RETX, REG_RETN, REG_RETE, REG_EMUDAT, + REG_LASTREG, }; +#define IS_DREG(g,r) ((g) == 0 && (r) < 8) +#define IS_PREG(g,r) ((g) == 1 && (r) < 8) +#define IS_AREG(g,r) ((g) == 4 && (r) >= 0 && (r) < 4) +#define IS_GENREG(g,r) ((((g) == 0 || (g) == 1) && (r) < 8) || IS_AREG (g, r)) +#define IS_DAGREG(g,r) (((g) == 2 || (g) == 3) && (r) < 8) +#define IS_SYSREG(g,r) \ + (((g) == 4 && ((r) == 6 || (r) == 7)) || (g) == 6 || (g) == 7) +#define IS_RESERVEDREG(g,r) \ + (((r) > 7) || ((g) == 4 && ((r) == 4 || (r) == 5)) || (g) == 5) + +#define allreg(r,g) (!IS_RESERVEDREG (g, r)) +#define mostreg(r,g) (!(IS_DREG (g, r) || IS_PREG (g, r) || IS_RESERVEDREG (g, r))) + #define allregs(x,i) REGNAME (decode_allregs[((i) << 3) | x]) #define uimm16s4(x) fmtconst (c_uimm16s4, x, 0, outf) #define uimm16s4d(x) fmtconst (c_uimm16s4d, x, 0, outf) @@ -481,7 +495,7 @@ static enum machine_registers decode_allregs[] = /* (arch.pm)arch_disassembler_functions. */ #ifndef OUTS -#define OUTS(p, txt) ((p) ? (((txt)[0]) ? (p->fprintf_func)(p->stream, txt) :0) :0) +#define OUTS(p, txt) ((p) ? (((txt)[0]) ? (p->fprintf_func)(p->stream, "%s", txt) :0) :0) #endif static void @@ -554,7 +568,7 @@ aligndir (int r0, disassemble_info *outf) static int decode_multfunc (int h0, int h1, int src0, int src1, disassemble_info * outf) { - char *s0, *s1; + const char *s0, *s1; if (h0) s0 = dregs_hi (src0); @@ -575,8 +589,8 @@ decode_multfunc (int h0, int h1, int src0, int src1, disassemble_info * outf) static int decode_macfunc (int which, int op, int h0, int h1, int src0, int src1, disassemble_info * outf) { - char *a; - char *sop = ""; + const char *a; + const char *sop = ""; if (which) a = "A1"; @@ -764,35 +778,35 @@ decode_ProgCtrl_0 (TIword iw0, disassemble_info *outf) OUTS (outf, "SSYNC"); else if (prgfunc == 2 && poprnd == 5) OUTS (outf, "EMUEXCPT"); - else if (prgfunc == 3) + else if (prgfunc == 3 && IS_DREG (0, poprnd)) { OUTS (outf, "CLI "); OUTS (outf, dregs (poprnd)); } - else if (prgfunc == 4) + else if (prgfunc == 4 && IS_DREG (0, poprnd)) { OUTS (outf, "STI "); OUTS (outf, dregs (poprnd)); } - else if (prgfunc == 5) + else if (prgfunc == 5 && IS_PREG (1, poprnd)) { OUTS (outf, "JUMP ("); OUTS (outf, pregs (poprnd)); OUTS (outf, ")"); } - else if (prgfunc == 6) + else if (prgfunc == 6 && IS_PREG (1, poprnd)) { OUTS (outf, "CALL ("); OUTS (outf, pregs (poprnd)); OUTS (outf, ")"); } - else if (prgfunc == 7) + else if (prgfunc == 7 && IS_PREG (1, poprnd)) { OUTS (outf, "CALL (PC + "); OUTS (outf, pregs (poprnd)); OUTS (outf, ")"); } - else if (prgfunc == 8) + else if (prgfunc == 8 && IS_PREG (1, poprnd)) { OUTS (outf, "JUMP (PC + "); OUTS (outf, pregs (poprnd)); @@ -808,7 +822,7 @@ decode_ProgCtrl_0 (TIword iw0, disassemble_info *outf) OUTS (outf, "EXCPT "); OUTS (outf, uimm4 (poprnd)); } - else if (prgfunc == 11) + else if (prgfunc == 11 && IS_PREG (1, poprnd)) { OUTS (outf, "TESTSET ("); OUTS (outf, pregs (poprnd)); @@ -894,12 +908,12 @@ decode_PushPopReg_0 (TIword iw0, disassemble_info *outf) int grp = ((iw0 >> PushPopReg_grp_bits) & PushPopReg_grp_mask); int reg = ((iw0 >> PushPopReg_reg_bits) & PushPopReg_reg_mask); - if (W == 0) + if (W == 0 && mostreg (reg, grp)) { OUTS (outf, allregs (reg, grp)); OUTS (outf, " = [SP++]"); } - else if (W == 1) + else if (W == 1 && allreg (reg, grp)) { OUTS (outf, "[--SP] = "); OUTS (outf, allregs (reg, grp)); @@ -1194,7 +1208,7 @@ decode_CC2dreg_0 (TIword iw0, disassemble_info *outf) OUTS (outf, "CC = "); OUTS (outf, dregs (reg)); } - else if (op == 3) + else if (op == 3 && reg == 0) OUTS (outf, "CC = !CC"); else return 0; @@ -1213,44 +1227,57 @@ decode_CC2stat_0 (TIword iw0, disassemble_info *outf) int op = ((iw0 >> CC2stat_op_bits) & CC2stat_op_mask); int cbit = ((iw0 >> CC2stat_cbit_bits) & CC2stat_cbit_mask); + const char *bitname = statbits (cbit); + if (decode_statbits[cbit] == REG_LASTREG) + { + /* All ASTAT bits except CC may be operated on in hardware, but may + not have a dedicated insn, so still decode "valid" insns. */ + static char bitnames[64]; + if (cbit != 5) + sprintf (bitnames, "ASTAT[%i /* unused bit */]", cbit); + else + strcpy (bitnames, "CC /* ... Illegal register ... */"); + bitname = bitnames; + } + if (op == 0 && D == 0) { OUTS (outf, "CC = "); - OUTS (outf, statbits (cbit)); + OUTS (outf, bitname); } else if (op == 1 && D == 0) { OUTS (outf, "CC |= "); - OUTS (outf, statbits (cbit)); + OUTS (outf, bitname); } else if (op == 2 && D == 0) { OUTS (outf, "CC &= "); - OUTS (outf, statbits (cbit)); + OUTS (outf, bitname); } else if (op == 3 && D == 0) { OUTS (outf, "CC ^= "); - OUTS (outf, statbits (cbit)); + OUTS (outf, bitname); } else if (op == 0 && D == 1) { - OUTS (outf, statbits (cbit)); + OUTS (outf, bitname); OUTS (outf, " = CC"); } else if (op == 1 && D == 1) { - OUTS (outf, statbits (cbit)); + OUTS (outf, bitname); OUTS (outf, " |= CC"); } else if (op == 2 && D == 1) { - OUTS (outf, statbits (cbit)); + OUTS (outf, bitname); OUTS (outf, " &= CC"); } else if (op == 3 && D == 1) { - OUTS (outf, statbits (cbit)); + OUTS (outf, bitname); OUTS (outf, " ^= CC"); } else @@ -1324,6 +1351,19 @@ decode_REGMV_0 (TIword iw0, disassemble_info *outf) int src = ((iw0 >> RegMv_src_bits) & RegMv_src_mask); int dst = ((iw0 >> RegMv_dst_bits) & RegMv_dst_mask); + if (!((IS_GENREG (gd, dst) && IS_GENREG (gs, src)) + || (IS_GENREG (gd, dst) && IS_DAGREG (gs, src)) + || (IS_DAGREG (gd, dst) && IS_GENREG (gs, src)) + || (IS_DAGREG (gd, dst) && IS_DAGREG (gs, src)) + || (IS_GENREG (gd, dst) && gs == 7 && src == 0) + || (gd == 7 && dst == 0 && IS_GENREG (gs, src)) + || (IS_DREG (gd, dst) && IS_SYSREG (gs, src)) + || (IS_PREG (gd, dst) && IS_SYSREG (gs, src)) + || (IS_SYSREG (gd, dst) && IS_DREG (gs, src)) + || (IS_SYSREG (gd, dst) && IS_PREG (gs, src)) + || (IS_SYSREG (gd, dst) && gs == 7 && src == 0))) + return 0; + OUTS (outf, allregs (dst, gd)); OUTS (outf, " = "); OUTS (outf, allregs (src, gs)); @@ -4038,7 +4078,7 @@ decode_dsp32shift_0 (TIword iw0, TIword iw1, disassemble_info *outf) else if (sop == 2 && sopcde == 2) { OUTS (outf, dregs (dst0)); - OUTS (outf, " = SHIFT "); + OUTS (outf, " = LSHIFT "); OUTS (outf, dregs (src1)); OUTS (outf, " BY "); OUTS (outf, dregs_lo (src0)); @@ -4054,7 +4094,7 @@ decode_dsp32shift_0 (TIword iw0, TIword iw1, disassemble_info *outf) else if (sop == 2 && sopcde == 1) { OUTS (outf, dregs (dst0)); - OUTS (outf, " = SHIFT "); + OUTS (outf, " = LSHIFT "); OUTS (outf, dregs (src1)); OUTS (outf, " BY "); OUTS (outf, dregs_lo (src0)); @@ -4421,7 +4461,7 @@ decode_dsp32shiftimm_0 (TIword iw0, TIword iw1, disassemble_info *outf) OUTS (outf, dregs (src1)); OUTS (outf, " >>> "); OUTS (outf, imm5 (-immag)); - OUTS (outf, " (V)"); + OUTS (outf, " (V, S)"); } else if (sop == 2 && sopcde == 1 && bit8 == 1) { @@ -4534,12 +4574,12 @@ decode_pseudoDEBUG_0 (TIword iw0, disassemble_info *outf) else if (grp == 0 && fn == 2) { - OUTS (outf, "OUTC"); + OUTS (outf, "OUTC "); OUTS (outf, dregs (reg)); } else if (fn == 0) { - OUTS (outf, "DBG"); + OUTS (outf, "DBG "); OUTS (outf, allregs (reg, grp)); } else if (fn == 1) @@ -4553,22 +4593,38 @@ decode_pseudoDEBUG_0 (TIword iw0, disassemble_info *outf) return 2; } +static int +decode_pseudoOChar_0 (TIword iw0, disassemble_info *outf) +{ + /* psedoOChar + +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ + | 1 | 1 | 1 | 1 | 1 | 0 | 0 | 1 |.ch............................| + +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */ + int ch = ((iw0 >> PseudoChr_ch_bits) & PseudoChr_ch_mask); + + OUTS (outf, "OUTC "); + OUTS (outf, uimm8 (ch)); + + return 2; +} + static int decode_pseudodbg_assert_0 (TIword iw0, TIword iw1, disassemble_info *outf) { /* pseudodbg_assert +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ - | 1 | 1 | 1 | 1 | 0 | - | - | - | - | - |.dbgop.....|.regtest...| + | 1 | 1 | 1 | 1 | 0 | - | - | - | dbgop |.grp.......|.regtest...| |.expected......................................................| +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */ int expected = ((iw1 >> PseudoDbg_Assert_expected_bits) & PseudoDbg_Assert_expected_mask); int dbgop = ((iw0 >> (PseudoDbg_Assert_dbgop_bits - 16)) & PseudoDbg_Assert_dbgop_mask); + int grp = ((iw0 >> (PseudoDbg_Assert_grp_bits - 16)) & PseudoDbg_Assert_grp_mask); int regtest = ((iw0 >> (PseudoDbg_Assert_regtest_bits - 16)) & PseudoDbg_Assert_regtest_mask); if (dbgop == 0) { OUTS (outf, "DBGA ("); - OUTS (outf, dregs_lo (regtest)); + OUTS (outf, regs_lo (regtest, grp)); OUTS (outf, ", "); OUTS (outf, uimm16 (expected)); OUTS (outf, ")"); @@ -4576,7 +4632,7 @@ decode_pseudodbg_assert_0 (TIword iw0, TIword iw1, disassemble_info *outf) else if (dbgop == 1) { OUTS (outf, "DBGA ("); - OUTS (outf, dregs_hi (regtest)); + OUTS (outf, regs_hi (regtest, grp)); OUTS (outf, ", "); OUTS (outf, uimm16 (expected)); OUTS (outf, ")"); @@ -4584,7 +4640,7 @@ decode_pseudodbg_assert_0 (TIword iw0, TIword iw1, disassemble_info *outf) else if (dbgop == 2) { OUTS (outf, "DBGAL ("); - OUTS (outf, dregs (regtest)); + OUTS (outf, allregs (regtest, grp)); OUTS (outf, ", "); OUTS (outf, uimm16 (expected)); OUTS (outf, ")"); @@ -4592,7 +4648,7 @@ decode_pseudodbg_assert_0 (TIword iw0, TIword iw1, disassemble_info *outf) else if (dbgop == 3) { OUTS (outf, "DBGAH ("); - OUTS (outf, dregs (regtest)); + OUTS (outf, allregs (regtest, grp)); OUTS (outf, ", "); OUTS (outf, uimm16 (expected)); OUTS (outf, ")"); @@ -4602,7 +4658,7 @@ decode_pseudodbg_assert_0 (TIword iw0, TIword iw1, disassemble_info *outf) return 4; } -int +static int _print_insn_bfin (bfd_vma pc, disassemble_info *outf) { bfd_byte buf[4]; @@ -4612,7 +4668,11 @@ _print_insn_bfin (bfd_vma pc, disassemble_info *outf) int rv = 0; status = (*outf->read_memory_func) (pc & ~0x1, buf, 2, outf); + /* FIXME */ + (void) status; status = (*outf->read_memory_func) ((pc + 2) & ~0x1, buf + 2, 2, outf); + /* FIXME */ + (void) status; iw0 = bfd_getl16 (buf); iw1 = bfd_getl16 (buf + 2); @@ -4692,11 +4752,9 @@ _print_insn_bfin (bfd_vma pc, disassemble_info *outf) rv = decode_dsp32shiftimm_0 (iw0, iw1, outf); else if ((iw0 & 0xff00) == 0xf800) rv = decode_pseudoDEBUG_0 (iw0, outf); -#if 0 else if ((iw0 & 0xFF00) == 0xF900) - rv = decode_pseudoOChar_0 (iw0, iw1, pc, outf); -#endif - else if ((iw0 & 0xFFC0) == 0xf000 && (iw1 & 0x0000) == 0x0000) + rv = decode_pseudoOChar_0 (iw0, outf); + else if ((iw0 & 0xFF00) == 0xf000 && (iw1 & 0x0000) == 0x0000) rv = decode_pseudodbg_assert_0 (iw0, iw1, outf); return rv; @@ -4712,6 +4770,8 @@ print_insn_bfin (bfd_vma pc, disassemble_info *outf) int count = 0; status = (*outf->read_memory_func) (pc & ~0x01, buf, 2, outf); + /* FIXME */ + (void) status; iw0 = bfd_getl16 (buf); count += _print_insn_bfin (pc, outf);