%c print condition code (always bits 28-31 in ARM mode)
%q print shifter argument
- %u print condition code (unconditional in ARM mode)
+ %u print condition code (unconditional in ARM mode,
+ UNPREDICTABLE if not AL in Thumb)
%A print address for ldc/stc/ldf/stf instruction
%B print vstm/vldm register list
%I print cirrus signed shift immediate: bits 0..3|4..6
%Q print floating point precision in ldf/stf insn
%R print floating point rounding mode
+ %<bitfield>c print as a condition code (for vsel)
%<bitfield>r print as an ARM register
%<bitfield>R as %<>r but r15 is UNPREDICTABLE
%<bitfield>ru as %<>r but each u register must be unique.
{FPU_VFP_EXT_FMA, 0x0e900a00, 0x0fb00f50, "vfnms%c.f32\t%y1, %y2, %y0"},
{FPU_VFP_EXT_FMA, 0x0e900b00, 0x0fb00f50, "vfnms%c.f64\t%z1, %z2, %z0"},
+ /* FP v5. */
+ {FPU_VFP_EXT_ARMV8, 0xfe000a00, 0xff800f00, "vsel%20-21c%u.f32\t%y1, %y2, %y0"},
+ {FPU_VFP_EXT_ARMV8, 0xfe000b00, 0xff800f00, "vsel%20-21c%u.f64\t%z1, %z2, %z0"},
+ {FPU_VFP_EXT_ARMV8, 0xfe800a00, 0xffb00f40, "vmaxnm%u.f32\t%y1, %y2, %y0"},
+ {FPU_VFP_EXT_ARMV8, 0xfe800b00, 0xffb00f40, "vmaxnm%u.f64\t%z1, %z2, %z0"},
+ {FPU_VFP_EXT_ARMV8, 0xfe800a40, 0xffb00f40, "vminnm%u.f32\t%y1, %y2, %y0"},
+ {FPU_VFP_EXT_ARMV8, 0xfe800b40, 0xffb00f40, "vminnm%u.f64\t%z1, %z2, %z0"},
+ {FPU_VFP_EXT_ARMV8, 0xfebc0a40, 0xffbc0f50, "vcvt%16-17?mpna%u.%7?su32.f32\t%y1, %y0"},
+ {FPU_VFP_EXT_ARMV8, 0xfebc0b40, 0xffbc0f50, "vcvt%16-17?mpna%u.%7?su32.f64\t%y1, %z0"},
+ {FPU_VFP_EXT_ARMV8, 0x0eb60a40, 0x0fbe0f50, "vrint%7,16??xzr%c.f32.f32\t%y1, %y0"},
+ {FPU_VFP_EXT_ARMV8, 0x0eb60b40, 0x0fbe0f50, "vrint%7,16??xzr%c.f64.f64\t%z1, %z0"},
+ {FPU_VFP_EXT_ARMV8, 0xfeb80a40, 0xffbc0f50, "vrint%16-17?mpna%u.f32.f32\t%y1, %y0"},
+ {FPU_VFP_EXT_ARMV8, 0xfeb80b40, 0xffbc0f50, "vrint%16-17?mpna%u.f64.f64\t%z1, %z0"},
+
/* Generic coprocessor instructions. */
{ 0, SENTINEL_GENERIC_START, 0, "" },
{ARM_EXT_V5E, 0x0c400000, 0x0ff00000, "mcrr%c\t%8-11d, %4-7d, %12-15R, %16-19r, cr%0-3d"},
%% %
%c print condition code
+ %u print condition code (unconditional in ARM mode,
+ UNPREDICTABLE if not AL in Thumb)
%A print v{st,ld}[1234] operands
%B print v{st,ld}[1234] any one operands
%C print v{st,ld}[1234] single->all operands
{FPU_NEON_EXT_FMA, 0xf2200c10, 0xffa00f10, "vfms%c.f%20U0\t%12-15,22R, %16-19,7R, %0-3,5R"},
/* Two registers, miscellaneous. */
+ {FPU_NEON_EXT_ARMV8, 0xf3ba0400, 0xffbf0c10, "vrint%7-9?p?m?zaxn%u.f32.f32\t%12-15,22R, %0-3,5R"},
+ {FPU_NEON_EXT_ARMV8, 0xf3bb0000, 0xffbf0c10, "vcvt%8-9?mpna%u.%7?us32.f32\t%12-15,22R, %0-3,5R"},
{FPU_NEON_EXT_V1, 0xf2880a10, 0xfebf0fd0, "vmovl%c.%24?us8\t%12-15,22Q, %0-3,5D"},
{FPU_NEON_EXT_V1, 0xf2900a10, 0xfebf0fd0, "vmovl%c.%24?us16\t%12-15,22Q, %0-3,5D"},
{FPU_NEON_EXT_V1, 0xf2a00a10, 0xfebf0fd0, "vmovl%c.%24?us32\t%12-15,22Q, %0-3,5D"},
{FPU_NEON_EXT_V1, 0xf3b30600, 0xffb30e10, "vcvt%c.%7-8?usff%18-19Sa.%7-8?ffus%18-19Sa\t%12-15,22R, %0-3,5R"},
/* Three registers of the same length. */
+ {FPU_NEON_EXT_ARMV8, 0xf3000f10, 0xffa00f10, "vmaxnm%u.f%20U0\t%12-15,22R, %16-19,7R, %0-3,5R"},
+ {FPU_NEON_EXT_ARMV8, 0xf3200f10, 0xffa00f10, "vminnm%u.f%20U0\t%12-15,22R, %16-19,7R, %0-3,5R"},
{FPU_NEON_EXT_V1, 0xf2000110, 0xffb00f10, "vand%c\t%12-15,22R, %16-19,7R, %0-3,5R"},
{FPU_NEON_EXT_V1, 0xf2100110, 0xffb00f10, "vbic%c\t%12-15,22R, %16-19,7R, %0-3,5R"},
{FPU_NEON_EXT_V1, 0xf2200110, 0xffb00f10, "vorr%c\t%12-15,22R, %16-19,7R, %0-3,5R"},
%P print address for pli instruction.
%<bitfield>r print as an ARM register
+ %<bitfield>T print as an ARM register + 1
%<bitfield>R as %r but r15 is UNPREDICTABLE
%<bitfield>{r|R}u as %{r|R} but if matches the other %u field then is UNPREDICTABLE
%<bitfield>{r|R}U as %{r|R} but if matches the other %U field then is UNPREDICTABLE
{ARM_EXT_V3M, 0x00800090, 0x0fa000f0, "%22?sumull%20's%c\t%12-15Ru, %16-19Ru, %0-3R, %8-11R"},
{ARM_EXT_V3M, 0x00a00090, 0x0fa000f0, "%22?sumlal%20's%c\t%12-15Ru, %16-19Ru, %0-3R, %8-11R"},
+ /* V8 instructions. */
+ {ARM_EXT_V8, 0x0320f005, 0x0fffffff, "sevl"},
+ {ARM_EXT_V8, 0xe1000070, 0xfff000f0, "hlt\t0x%16-19X%12-15X%8-11X%0-3X"},
+ {ARM_EXT_V8, 0x01800e90, 0x0ff00ff0, "strlex%c\t%12-15r, %0-3r, [%16-19R]"},
+ {ARM_EXT_V8, 0x01900e9f, 0x0ff00fff, "ldraex%c\t%12-15r, [%16-19R]"},
+ {ARM_EXT_V8, 0x01a00e90, 0x0ff00ff0, "strlexd%c\t%12-15r, %0-3r, %0-3T, [%16-19R]"},
+ {ARM_EXT_V8, 0x01b00e9f, 0x0ff00fff, "ldraexd%c\t%12-15r, %12-15T, [%16-19R]"},
+ {ARM_EXT_V8, 0x01c00e90, 0x0ff00ff0, "strlexb%c\t%12-15r, %0-3r, [%16-19R]"},
+ {ARM_EXT_V8, 0x01d00e9f, 0x0ff00fff, "ldraexb%c\t%12-15r, [%16-19R]"},
+ {ARM_EXT_V8, 0x01e00e90, 0x0ff00ff0, "strlexh%c\t%12-15r, %0-3r, [%16-19R]"},
+ {ARM_EXT_V8, 0x01f00e9f, 0x0ff00fff, "ldraexh%c\t%12-15r, [%16-19R]"},
+ {ARM_EXT_V8, 0x0180fc90, 0x0ff0fff0, "strl%c\t%0-3r, [%16-19R]"},
+ {ARM_EXT_V8, 0x01900c9f, 0x0ff00fff, "ldra%c\t%12-15r, [%16-19R]"},
+ {ARM_EXT_V8, 0x01c0fc90, 0x0ff0fff0, "strlb%c\t%0-3r, [%16-19R]"},
+ {ARM_EXT_V8, 0x01d00c9f, 0x0ff00fff, "ldrab%c\t%12-15r, [%16-19R]"},
+ {ARM_EXT_V8, 0x01e0fc90, 0x0ff0fff0, "strlh%c\t%0-3r, [%16-19R]"},
+ {ARM_EXT_V8, 0x01f00c9f, 0x0ff00fff, "ldraexh%c\t%12-15r, [%16-19R]"},
+
/* Virtualization Extension instructions. */
{ARM_EXT_VIRT, 0x0160006e, 0x0fffffff, "eret%c"},
{ARM_EXT_VIRT, 0x01400070, 0x0ff000f0, "hvc%c\t%e"},
/* V7 instructions. */
{ARM_EXT_V7, 0xf450f000, 0xfd70f000, "pli\t%P"},
{ARM_EXT_V7, 0x0320f0f0, 0x0ffffff0, "dbg%c\t#%0-3d"},
+ {ARM_EXT_V8, 0xf57ff051, 0xfffffff3, "dmb\t%U"},
+ {ARM_EXT_V8, 0xf57ff041, 0xfffffff3, "dsb\t%U"},
{ARM_EXT_V7, 0xf57ff050, 0xfffffff0, "dmb\t%U"},
{ARM_EXT_V7, 0xf57ff040, 0xfffffff0, "dsb\t%U"},
{ARM_EXT_V7, 0xf57ff060, 0xfffffff0, "isb\t%U"},
{
/* Thumb instructions. */
+ /* ARM V8 instructions. */
+ {ARM_EXT_V8, 0xbf50, 0xffff, "sevl%c"},
+ {ARM_EXT_V8, 0xba80, 0xffc0, "hlt\t%0-5x"},
+
/* ARM V6K no-argument instructions. */
{ARM_EXT_V6K, 0xbf00, 0xffff, "nop%c"},
{ARM_EXT_V6K, 0xbf10, 0xffff, "yield%c"},
makes heavy use of special-case bit patterns. */
static const struct opcode32 thumb32_opcodes[] =
{
+ /* V8 instructions. */
+ {ARM_EXT_V8, 0xf3af8005, 0xffffffff, "sevl%c.w"},
+ {ARM_EXT_V8, 0xf78f8000, 0xfffffffc, "dcps%0-1d"},
+ {ARM_EXT_V8, 0xe8c00f8f, 0xfff00fff, "strlb%c\t%12-15r, [%16-19R]"},
+ {ARM_EXT_V8, 0xe8c00f9f, 0xfff00fff, "strlh%c\t%12-15r, [%16-19R]"},
+ {ARM_EXT_V8, 0xe8c00faf, 0xfff00fff, "strl%c\t%12-15r, [%16-19R]"},
+ {ARM_EXT_V8, 0xe8c00fc0, 0xfff00ff0, "strlexb%c\t%0-3r, %12-15r, [%16-19R]"},
+ {ARM_EXT_V8, 0xe8c00fd0, 0xfff00ff0, "strlexh%c\t%0-3r, %12-15r, [%16-19R]"},
+ {ARM_EXT_V8, 0xe8c00fe0, 0xfff00ff0, "strlex%c\t%0-3r, %12-15r, [%16-19R]"},
+ {ARM_EXT_V8, 0xe8c000f0, 0xfff000f0, "strlexd%c\t%0-3r, %12-15r, %8-11r, [%16-19R]"},
+ {ARM_EXT_V8, 0xe8d00f8f, 0xfff00fff, "ldrab%c\t%12-15r, [%16-19R]"},
+ {ARM_EXT_V8, 0xe8d00f9f, 0xfff00fff, "ldrah%c\t%12-15r, [%16-19R]"},
+ {ARM_EXT_V8, 0xe8d00faf, 0xfff00fff, "ldra%c\t%12-15r, [%16-19R]"},
+ {ARM_EXT_V8, 0xe8d00fcf, 0xfff00fff, "ldraexb%c\t%12-15r, [%16-19R]"},
+ {ARM_EXT_V8, 0xe8d00fdf, 0xfff00fff, "ldraexh%c\t%12-15r, [%16-19R]"},
+ {ARM_EXT_V8, 0xe8d00fef, 0xfff00fff, "ldraex%c\t%12-15r, [%16-19R]"},
+ {ARM_EXT_V8, 0xe8d000ff, 0xfff000ff, "ldraexd%c\t%12-15r, %8-11r, [%16-19R]"},
+
/* V7 instructions. */
{ARM_EXT_V7, 0xf910f000, 0xff70f000, "pli%c\t%a"},
{ARM_EXT_V7, 0xf3af80f0, 0xfffffff0, "dbg%c\t#%0-3d"},
+ {ARM_EXT_V8, 0xf3bf8f51, 0xfffffff3, "dmb%c\t%U"},
+ {ARM_EXT_V8, 0xf3bf8f41, 0xfffffff3, "dsb%c\t%U"},
{ARM_EXT_V7, 0xf3bf8f50, 0xfffffff0, "dmb%c\t%U"},
{ARM_EXT_V7, 0xf3bf8f40, 0xfffffff0, "dsb%c\t%U"},
{ARM_EXT_V7, 0xf3bf8f60, 0xfffffff0, "isb%c\t%U"},
/* The address of the insn for which the IT state is valid. */
static bfd_vma ifthen_address;
#define IFTHEN_COND ((ifthen_state >> 4) & 0xf)
+/* Indicates that the current Conditional state is unconditional or outside
+ an IT block. */
+#define COND_UNCOND 16
\f
/* Functions. */
if (ifthen_state)
cond = IFTHEN_COND;
else
- cond = 16;
+ cond = COND_UNCOND;
}
else
{
if ((given & 0xf0000000) == 0xf0000000)
{
mask |= 0xf0000000;
- cond = 16;
+ cond = COND_UNCOND;
}
else
{
cond = (given >> 28) & 0xf;
if (cond == 0xe)
- cond = 16;
+ cond = COND_UNCOND;
}
}
}
break;
+ case 'u':
+ if (cond != COND_UNCOND)
+ is_unpredictable = TRUE;
+
+ /* Fall through. */
case 'c':
func (stream, "%s", arm_conditional[cond]);
break;
func (stream, "0x%lx", (value & 0xffffffffUL));
break;
+ case 'c':
+ switch (value)
+ {
+ case 0:
+ func (stream, "eq");
+ break;
+
+ case 1:
+ func (stream, "vs");
+ break;
+
+ case 2:
+ func (stream, "ge");
+ break;
+
+ case 3:
+ func (stream, "gt");
+ break;
+
+ default:
+ func (stream, "??");
+ break;
+ }
+ break;
+
case '`':
c++;
if (value == 0)
if ((given & insn->mask) == insn->value)
{
signed long value_in_comment = 0;
+ bfd_boolean is_unpredictable = FALSE;
const char *c;
for (c = insn->assembler; *c; c++)
func (stream, "%%");
break;
+ case 'u':
+ if (thumb && ifthen_state)
+ is_unpredictable = TRUE;
+
+ /* Fall through. */
case 'c':
if (thumb && ifthen_state)
func (stream, "%s", arm_conditional[IFTHEN_COND]);
func (stream, "{d%d-d%d}", regno, regno + num);
}
break;
-
+
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
if (value_in_comment > 32 || value_in_comment < -16)
func (stream, "\t; 0x%lx", value_in_comment);
+ if (is_unpredictable)
+ func (stream, UNPREDICTABLE_INSTRUCTION);
+
return TRUE;
}
}
}
}
+/* Return the name of the DMB/DSB option. */
+static const char *
+data_barrier_option (unsigned option)
+{
+ switch (option & 0xf)
+ {
+ case 0xf: return "sy";
+ case 0xe: return "st";
+ case 0xd: return "ld";
+ case 0xb: return "ish";
+ case 0xa: return "ishst";
+ case 0x9: return "ishld";
+ case 0x7: return "un";
+ case 0x6: return "unst";
+ case 0x5: return "nshld";
+ case 0x3: return "osh";
+ case 0x2: return "oshst";
+ case 0x1: return "oshld";
+ default: return NULL;
+ }
+}
+
/* Print one ARM instruction from PC on INFO->STREAM. */
static void
}
else
{
- switch (given & 0xf)
- {
- case 0xf: func (stream, "sy"); break;
- case 0x7: func (stream, "un"); break;
- case 0xe: func (stream, "st"); break;
- case 0x6: func (stream, "unst"); break;
- case 0xb: func (stream, "ish"); break;
- case 0xa: func (stream, "ishst"); break;
- case 0x3: func (stream, "osh"); break;
- case 0x2: func (stream, "oshst"); break;
- default:
+ const char * opt = data_barrier_option (given & 0xf);
+ if (opt != NULL)
+ func (stream, "%s", opt);
+ else
func (stream, "#%d", (int) given & 0xf);
- break;
- }
}
break;
is_unpredictable = TRUE;
/* Fall through. */
case 'r':
+ case 'T':
+ /* We want register + 1 when decoding T. */
+ if (*c == 'T')
+ ++value;
+
if (c[1] == 'u')
{
/* Eat the 'u' character. */
}
else
{
- switch (given & 0xf)
- {
- case 0xf: func (stream, "sy"); break;
- case 0x7: func (stream, "un"); break;
- case 0xe: func (stream, "st"); break;
- case 0x6: func (stream, "unst"); break;
- case 0xb: func (stream, "ish"); break;
- case 0xa: func (stream, "ishst"); break;
- case 0x3: func (stream, "osh"); break;
- case 0x2: func (stream, "oshst"); break;
- default:
- func (stream, "#%d", (int) given & 0xf);
- break;
- }
+ const char * opt = data_barrier_option (given & 0xf);
+ if (opt != NULL)
+ func (stream, "%s", opt);
+ else
+ func (stream, "#%d", (int) given & 0xf);
}
break;