/* 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.
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,
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},
{ "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];
}
else
{
- sprintf (buf, "%lx", x);
+ sprintf (buf, "%lx", (unsigned long) x);
return buf;
}
}
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;
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,
};
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",
"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
};
};
#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[] =
{
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,
};
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[] =
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)
/* (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
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);
static int
decode_macfunc (int which, int op, int h0, int h1, int src0, int src1, disassemble_info * outf)
{
- char *a;
- char *sop = "<unknown op>";
+ const char *a;
+ const char *sop = "<unknown op>";
if (which)
a = "A1";
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));
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));
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));
OUTS (outf, "CC = ");
OUTS (outf, dregs (reg));
}
- else if (op == 3)
+ else if (op == 3 && reg == 0)
OUTS (outf, "CC = !CC");
else
return 0;
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
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));
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));
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));
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)
{
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)
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, ")");
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, ")");
else if (dbgop == 2)
{
OUTS (outf, "DBGAL (");
- OUTS (outf, dregs (regtest));
+ OUTS (outf, allregs (regtest, grp));
OUTS (outf, ", ");
OUTS (outf, uimm16 (expected));
OUTS (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, ")");
return 4;
}
-int
+static int
_print_insn_bfin (bfd_vma pc, disassemble_info *outf)
{
bfd_byte buf[4];
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);
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;
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);