This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
[PATCH ARM 6/6]: Architectural Extensions - Virtualization Extensions
- From: Matthew Gretton-Dann <matthew dot gretton-dann at arm dot com>
- To: binutils at sourceware dot org
- Cc: Richard Earnshaw <Richard dot Earnshaw at arm dot com>
- Date: Thu, 23 Sep 2010 10:24:29 +0100
- Subject: [PATCH ARM 6/6]: Architectural Extensions - Virtualization Extensions
- References: <1285232920.17086.138.camel@e102319-lin.cambridge.arm.com>
All,
The attached patch adds support for the Virtualization Extensions to
v7-A under the 'virt' extension.
The main features of this patch are to add support for the HVC and ERET
instructions, and to also add support for the new special registers
which MRS and MSR accept. Also note that the 'virt' extension implies
the 'idiv' extension.
Proposed ChangeLogs:
bfd/ChangeLog:
* bfd-in2.h (BFD_RELOC_ARM_HVC): Add.
gas/ChangeLog:
2010-09-22 Matthew Gretton-Dann <matthew.gretton-dann@arm.com>
* config/tc-arm.c (arm_ext_virt): Add.
(arm_reg_type): Add REG_TYPE_RNB for banked registers.
(reg_entry): Allow registers to be larger than a byte.
(reg_alias): Fix type warning.
(parse_operands): Parse banked registers when appropriate.
(do_mrs): Add support for Virtualization Extensions.
(do_hvc): Add.
(do_t_mrs): Add support for Virtualization Extensions.
(do_t_msr): Likewise.
(do_t_hvc): Add.
(SPLRBANK): Likewise.
(reg_names): Add banked registers.
(insns): Add support for Virtualization Extensions.
(md_apply_fixup): Likewise.
(arm_cpus): -mcpu=cortex-a15 implies the Virtualization
Extensions.
(arm_extensions): Add 'virt' extension.
(aeabi_set_public_attributes): Add support for Virtualization
Extensions.
doc/c-arm.texi: Document 'virt' extension.
gas/testsuite/ChangeLog:
2010-09-22 Matthew Gretton-Dann <matthew.gretton-dann@arm.com>
* gas/arm/armv7-a+virt.d: New test.
* gas/arm/armv7-a+virt.s: Likewise.
* gas/arm/attr-march-all.d: Update for Virtualization
Extensions.
* gas/arm/attr-march-armv7-a+sec+virt.d: New test.
* gas/arm/attr-march-armv7-a+virt.d: Likewise.
include/opcode/ChangeLog:
2010-09-22 Matthew Gretton-Dann <matthew.gretton-dann@arm.com>
* arm.h (ARM_EXT_VIRT): Add.
(ARM_ARCH_V7A_IDIV_MP_SEC): Rename...
(ARM_ARCH_V7A_IDIV_MP_SEC_VIRT): ...to this and include
Virtualization Extensions.
opcodes/ChangeLog:
2010-09-22 Matthew Gretton-Dann <matthew.gretton-dann@arm.com>
arm-dis.c (arm_opcodes): Add Virtualiztion Extensions support.
(thumb32_opcodes): Likewise.
(banked_regname): Add.
(print_insn_arm): Add Virtualization Extensions support.
(print_insn_thumb32): Likewise.
Thanks,
Matt
--
Matthew Gretton-Dann
Principal Engineer - PDSW Tools
ARM Ltd
diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h
index 0e7b337..4bd47ca 100644
--- a/bfd/bfd-in2.h
+++ b/bfd/bfd-in2.h
@@ -3166,6 +3166,7 @@ pc-relative or some form of GOT-indirect relocation. */
BFD_RELOC_ARM_T32_ADD_PC12,
BFD_RELOC_ARM_SHIFT_IMM,
BFD_RELOC_ARM_SMC,
+ BFD_RELOC_ARM_HVC,
BFD_RELOC_ARM_SWI,
BFD_RELOC_ARM_MULTI,
BFD_RELOC_ARM_CP_OFF_IMM,
diff --git a/gas/config/tc-arm.c b/gas/config/tc-arm.c
index 886d92f..0e0b894 100644
--- a/gas/config/tc-arm.c
+++ b/gas/config/tc-arm.c
@@ -201,6 +201,7 @@ static const arm_feature_set arm_ext_mp = ARM_FEATURE (ARM_EXT_MP, 0);
static const arm_feature_set arm_ext_sec = ARM_FEATURE (ARM_EXT_SEC, 0);
static const arm_feature_set arm_ext_os = ARM_FEATURE (ARM_EXT_OS, 0);
static const arm_feature_set arm_ext_adiv = ARM_FEATURE (ARM_EXT_ADIV, 0);
+static const arm_feature_set arm_ext_virt = ARM_FEATURE (ARM_EXT_VIRT, 0);
static const arm_feature_set arm_arch_any = ARM_ANY;
static const arm_feature_set arm_arch_full = ARM_FEATURE (-1, -1);
@@ -506,6 +507,7 @@ enum arm_reg_type
REG_TYPE_MMXWC,
REG_TYPE_MMXWCG,
REG_TYPE_XSCALE,
+ REG_TYPE_RNB,
};
/* Structure for a hash table entry for a register.
@@ -515,7 +517,7 @@ enum arm_reg_type
struct reg_entry
{
const char * name;
- unsigned char number;
+ unsigned int number;
unsigned char type;
unsigned char builtin;
struct neon_typed_alias * neon;
@@ -2062,7 +2064,7 @@ parse_reloc (char **str)
/* Directives: register aliases. */
static struct reg_entry *
-insert_reg_alias (char *str, int number, int type)
+insert_reg_alias (char *str, unsigned number, int type)
{
struct reg_entry *new_reg;
const char *name;
@@ -6380,9 +6382,18 @@ parse_operands (char *str, const unsigned int *pattern, bfd_boolean thumb)
break;
case OP_RVC_PSR:
- po_reg_or_goto (REG_TYPE_VFC, try_psr);
+ po_reg_or_goto (REG_TYPE_VFC, try_banked_reg);
inst.operands[i].isvec = 1; /* Mark VFP control reg as vector. */
break;
+ try_banked_reg:
+ po_reg_or_goto (REG_TYPE_RNB, try_psr);
+ if (!ARM_CPU_HAS_FEATURE (cpu_variant, arm_ext_virt))
+ {
+ inst.error = _("Banked registers are not available with this "
+ "architecture.");
+ goto failure;
+ }
+ break;
try_psr:
val = parse_psr (&str);
break;
@@ -7851,16 +7862,30 @@ do_vmsr (void)
static void
do_mrs (void)
{
+ unsigned br;
+
if (do_vfp_nsyn_mrs () == SUCCESS)
return;
- /* mrs only accepts CPSR/SPSR/CPSR_all/SPSR_all. */
- constraint ((inst.operands[1].imm & (PSR_c|PSR_x|PSR_s|PSR_f))
- != (PSR_c|PSR_f),
- _("'CPSR' or 'SPSR' expected"));
constraint (inst.operands[0].reg == REG_PC, BAD_PC);
inst.instruction |= inst.operands[0].reg << 12;
- inst.instruction |= (inst.operands[1].imm & SPSR_BIT);
+
+ if (inst.operands[1].isreg)
+ {
+ br = inst.operands[1].reg;
+ if (((br & 0x200) == 0) && ((br & 0xf0000) != 0xf000))
+ as_bad (_("bad register for mrs"));
+ }
+ else
+ {
+ /* mrs only accepts CPSR/SPSR/CPSR_all/SPSR_all. */
+ constraint ((inst.operands[1].imm & (PSR_c|PSR_x|PSR_s|PSR_f))
+ != (PSR_c|PSR_f),
+ _("'CPSR' or 'SPSR' expected"));
+ br = (15<<16) | (inst.operands[1].imm & SPSR_BIT);
+ }
+
+ inst.instruction |= br;
}
/* Two possible forms:
@@ -8122,6 +8147,13 @@ do_smc (void)
}
static void
+do_hvc (void)
+{
+ inst.reloc.type = BFD_RELOC_ARM_HVC;
+ inst.reloc.pc_rel = 0;
+}
+
+static void
do_swi (void)
{
inst.reloc.type = BFD_RELOC_ARM_SWI;
@@ -10734,34 +10766,47 @@ static void
do_t_mrs (void)
{
unsigned Rd;
- int flags;
if (do_vfp_nsyn_mrs () == SUCCESS)
return;
- flags = inst.operands[1].imm & (PSR_c|PSR_x|PSR_s|PSR_f|SPSR_BIT);
- if (flags == 0)
+ Rd = inst.operands[0].reg;
+ reject_bad_reg (Rd);
+ inst.instruction |= Rd << 8;
+
+ if (inst.operands[1].isreg)
{
- constraint (!ARM_CPU_HAS_FEATURE (cpu_variant, arm_ext_m),
- _("selected processor does not support "
- "requested special purpose register"));
+ unsigned br = inst.operands[1].reg;
+ if (((br & 0x200) == 0) && ((br & 0xf000) != 0xf000))
+ as_bad (_("bad register for mrs"));
+
+ inst.instruction |= br & (0xf << 16);
+ inst.instruction |= (br & 0x300) >> 4;
+ inst.instruction |= (br & SPSR_BIT) >> 2;
}
else
{
- constraint (!ARM_CPU_HAS_FEATURE (cpu_variant, arm_ext_v1),
- _("selected processor does not support "
- "requested special purpose register"));
- /* mrs only accepts CPSR/SPSR/CPSR_all/SPSR_all. */
- constraint ((flags & ~SPSR_BIT) != (PSR_c|PSR_f),
- _("'CPSR' or 'SPSR' expected"));
- }
-
- Rd = inst.operands[0].reg;
- reject_bad_reg (Rd);
+ int flags = inst.operands[1].imm & (PSR_c|PSR_x|PSR_s|PSR_f|SPSR_BIT);
+ if (flags == 0)
+ {
+ constraint (!ARM_CPU_HAS_FEATURE (cpu_variant, arm_ext_m),
+ _("selected processor does not support "
+ "requested special purpose register"));
+ }
+ else
+ {
+ constraint (!ARM_CPU_HAS_FEATURE (cpu_variant, arm_ext_v1),
+ _("selected processor does not support "
+ "requested special purpose register"));
+ /* mrs only accepts CPSR/SPSR/CPSR_all/SPSR_all. */
+ constraint ((flags & ~SPSR_BIT) != (PSR_c|PSR_f),
+ _("'CPSR' or 'SPSR' expected"));
+ }
- inst.instruction |= Rd << 8;
- inst.instruction |= (flags & SPSR_BIT) >> 2;
- inst.instruction |= inst.operands[1].imm & 0xff;
+ inst.instruction |= (flags & SPSR_BIT) >> 2;
+ inst.instruction |= inst.operands[1].imm & 0xff;
+ inst.instruction |= 0xf0000;
+ }
}
static void
@@ -10775,7 +10820,12 @@ do_t_msr (void)
constraint (!inst.operands[1].isreg,
_("Thumb encoding does not support an immediate here"));
- flags = inst.operands[0].imm;
+
+ if (inst.operands[0].isreg)
+ flags = (int)(inst.operands[0].reg);
+ else
+ flags = inst.operands[0].imm;
+
if (flags & ~0xff)
{
constraint (!ARM_CPU_HAS_FEATURE (cpu_variant, arm_ext_v1),
@@ -10794,7 +10844,8 @@ do_t_msr (void)
reject_bad_reg (Rn);
inst.instruction |= (flags & SPSR_BIT) >> 2;
- inst.instruction |= (flags & ~SPSR_BIT) >> 8;
+ inst.instruction |= (flags & 0xf0000) >> 8;
+ inst.instruction |= (flags & 0x300) >> 4;
inst.instruction |= (flags & 0xff);
inst.instruction |= Rn << 16;
}
@@ -11390,6 +11441,15 @@ do_t_smc (void)
}
static void
+do_t_hvc (void)
+{
+ unsigned int value = inst.reloc.exp.X_add_number;
+ inst.reloc.type = BFD_RELOC_UNUSED;
+ inst.instruction |= (value & 0x0fff);
+ inst.instruction |= (value & 0xf000) << 4;
+}
+
+static void
do_t_ssat_usat (int bias)
{
unsigned Rd, Rn;
@@ -16185,6 +16245,13 @@ arm_canonicalize_symbol_name (char * name)
REGNUM2(p, 4,t), REGNUM2(p, 5,t), REGNUM2(p, 6,t), REGNUM2(p, 7,t), \
REGNUM2(p, 8,t), REGNUM2(p, 9,t), REGNUM2(p,10,t), REGNUM2(p,11,t), \
REGNUM2(p,12,t), REGNUM2(p,13,t), REGNUM2(p,14,t), REGNUM2(p,15,t)
+#define SPLRBANK(base,bank,t) \
+ REGDEF(lr_##bank, 768|((base+0)<<16), t), \
+ REGDEF(sp_##bank, 768|((base+1)<<16), t), \
+ REGDEF(spsr_##bank, 768|(base<<16)|SPSR_BIT, t), \
+ REGDEF(LR_##bank, 768|((base+0)<<16), t), \
+ REGDEF(SP_##bank, 768|((base+1)<<16), t), \
+ REGDEF(SPSR_##bank, 768|(base<<16)|SPSR_BIT, t)
static const struct reg_entry reg_names[] =
{
@@ -16215,6 +16282,34 @@ static const struct reg_entry reg_names[] =
REGSET(c, CN), REGSET(C, CN),
REGSET(cr, CN), REGSET(CR, CN),
+ /* ARM banked registers. */
+ REGDEF(R8_usr,512|(0<<16),RNB), REGDEF(r8_usr,512|(0<<16),RNB),
+ REGDEF(R9_usr,512|(1<<16),RNB), REGDEF(r9_usr,512|(1<<16),RNB),
+ REGDEF(R10_usr,512|(2<<16),RNB), REGDEF(r10_usr,512|(2<<16),RNB),
+ REGDEF(R11_usr,512|(3<<16),RNB), REGDEF(r11_usr,512|(3<<16),RNB),
+ REGDEF(R12_usr,512|(4<<16),RNB), REGDEF(r12_usr,512|(4<<16),RNB),
+ REGDEF(SP_usr,512|(5<<16),RNB), REGDEF(sp_usr,512|(5<<16),RNB),
+ REGDEF(LR_usr,512|(6<<16),RNB), REGDEF(lr_usr,512|(6<<16),RNB),
+
+ REGDEF(R8_fiq,512|(8<<16),RNB), REGDEF(r8_fiq,512|(8<<16),RNB),
+ REGDEF(R9_fiq,512|(9<<16),RNB), REGDEF(r9_fiq,512|(9<<16),RNB),
+ REGDEF(R10_fiq,512|(10<<16),RNB), REGDEF(r10_fiq,512|(10<<16),RNB),
+ REGDEF(R11_fiq,512|(11<<16),RNB), REGDEF(r11_fiq,512|(11<<16),RNB),
+ REGDEF(R12_fiq,512|(12<<16),RNB), REGDEF(r12_fiq,512|(12<<16),RNB),
+ REGDEF(SP_fiq,512|(13<<16),RNB), REGDEF(SP_fiq,512|(13<<16),RNB),
+ REGDEF(LR_fiq,512|(14<<16),RNB), REGDEF(lr_fiq,512|(14<<16),RNB),
+ REGDEF(SPSR_fiq,512|(14<<16)|SPSR_BIT,RNB), REGDEF(spsr_fiq,512|(14<<16)|SPSR_BIT,RNB),
+
+ SPLRBANK(0,IRQ,RNB), SPLRBANK(0,irq,RNB),
+ SPLRBANK(2,SVC,RNB), SPLRBANK(2,svc,RNB),
+ SPLRBANK(4,ABT,RNB), SPLRBANK(4,abt,RNB),
+ SPLRBANK(6,UND,RNB), SPLRBANK(6,und,RNB),
+ SPLRBANK(12,MON,RNB), SPLRBANK(12,mon,RNB),
+ REGDEF(elr_hyp,768|(14<<16),RNB), REGDEF(ELR_hyp,768|(14<<16),RNB),
+ REGDEF(sp_hyp,768|(15<<16),RNB), REGDEF(SP_hyp,768|(15<<16),RNB),
+ REGDEF(spsr_hyp,768|(14<<16)|SPSR_BIT,RNB),
+ REGDEF(SPSR_hyp,768|(14<<16)|SPSR_BIT,RNB),
+
/* FPA registers. */
REGNUM(f,0,FN), REGNUM(f,1,FN), REGNUM(f,2,FN), REGNUM(f,3,FN),
REGNUM(f,4,FN), REGNUM(f,5,FN), REGNUM(f,6,FN), REGNUM(f,7, FN),
@@ -16800,7 +16895,7 @@ static const struct asm_opcode insns[] =
#undef THUMB_VARIANT
#define THUMB_VARIANT & arm_ext_msr
- TCE("mrs", 10f0000, f3ef8000, 2, (APSR_RR, RVC_PSR), mrs, t_mrs),
+ TCE("mrs", 1000000, f3e08000, 2, (APSR_RR, RVC_PSR), mrs, t_mrs),
TCE("msr", 120f000, f3808000, 2, (RVC_PSR, RR_EXi), msr, t_msr),
#undef ARM_VARIANT
@@ -17088,6 +17183,14 @@ static const struct asm_opcode insns[] =
TCE("smc", 1600070, f7f08000, 1, (EXPi), smc, t_smc),
+#undef ARM_VARIANT
+#define ARM_VARIANT & arm_ext_virt
+#undef THUMB_VARIANT
+#define THUMB_VARIANT & arm_ext_virt
+
+ TCE("hvc", 1400070, f7e08000, 1, (EXPi), hvc, t_hvc),
+ TCE("eret", 160006e, f3de8f00, 0, (), noargs, noargs),
+
#undef ARM_VARIANT
#define ARM_VARIANT & arm_ext_v6t2
#undef THUMB_VARIANT
@@ -20389,6 +20492,15 @@ md_apply_fix (fixS * fixP,
md_number_to_chars (buf, newval, INSN_SIZE);
break;
+ case BFD_RELOC_ARM_HVC:
+ if (((unsigned long) value) > 0xffff)
+ as_bad_where (fixP->fx_file, fixP->fx_line,
+ _("invalid hvc expression"));
+ newval = md_chars_to_number (buf, INSN_SIZE);
+ newval |= (value & 0xf) | ((value & 0xfff0) << 4);
+ md_number_to_chars (buf, newval, INSN_SIZE);
+ break;
+
case BFD_RELOC_ARM_SWI:
if (fixP->tc_fix_data != 0)
{
@@ -22430,7 +22542,7 @@ static const struct arm_cpu_option_table arm_cpus[] =
ARM_FEATURE (0, FPU_VFP_V3
| FPU_NEON_EXT_V1),
"Cortex-A9"},
- {"cortex-a15", ARM_ARCH_V7A_IDIV_MP_SEC,
+ {"cortex-a15", ARM_ARCH_V7A_IDIV_MP_SEC_VIRT,
FPU_ARCH_NEON_VFP_V4,
"Cortex-A15"},
{"cortex-r4", ARM_ARCH_V7R, FPU_NONE, "Cortex-R4"},
@@ -22529,6 +22641,8 @@ static const struct arm_option_extension_value_table arm_extensions[] =
ARM_FEATURE (ARM_EXT_V6M, 0)},
{"sec", ARM_FEATURE (ARM_EXT_SEC, 0),
ARM_FEATURE (ARM_EXT_V6K | ARM_EXT_V7A, 0)},
+ {"virt", ARM_FEATURE (ARM_EXT_VIRT | ARM_EXT_ADIV | ARM_EXT_DIV, 0),
+ ARM_FEATURE (ARM_EXT_V7A, 0)},
{"xscale", ARM_FEATURE (0, ARM_CEXT_XSCALE), ARM_ANY},
{NULL, ARM_ARCH_NONE, ARM_ARCH_NONE}
};
@@ -23084,6 +23198,7 @@ static void
aeabi_set_public_attributes (void)
{
int arch;
+ int virt_sec = 0;
arm_feature_set flags;
arm_feature_set tmp;
const cpu_arch_ver_table *p;
@@ -23214,7 +23329,11 @@ aeabi_set_public_attributes (void)
/* Tag Virtualization_use. */
if (ARM_CPU_HAS_FEATURE (flags, arm_ext_sec))
- aeabi_set_attribute_int (Tag_Virtualization_use, 1);
+ virt_sec |= 1;
+ if (ARM_CPU_HAS_FEATURE (flags, arm_ext_virt))
+ virt_sec |= 2;
+ if (virt_sec != 0)
+ aeabi_set_attribute_int (Tag_Virtualization_use, virt_sec);
}
/* Add the default contents for the .ARM.attributes section. */
diff --git a/gas/doc/c-arm.texi b/gas/doc/c-arm.texi
index 2a5c351..d3cccf4 100644
--- a/gas/doc/c-arm.texi
+++ b/gas/doc/c-arm.texi
@@ -156,6 +156,8 @@ The following extensions are currently supported:
@code{mp} (Multiprocessing Extensions for v7-A and v7-R architectures),
@code{os} (Operating System for v6M architecture),
@code{sec} (Security Extensions for v6K and v7-A architectures),
+@code{virt} (Virtualization Extensions for v7-A architecture, implies
+@code{idiv}),
and
@code{xscale}.
diff --git a/gas/testsuite/gas/arm/armv7-a+virt.d b/gas/testsuite/gas/arm/armv7-a+virt.d
new file mode 100644
index 0000000..1e3224c
--- /dev/null
+++ b/gas/testsuite/gas/arm/armv7-a+virt.d
@@ -0,0 +1,145 @@
+# name: ARMv7-a+virt Instructions
+# as: -march=armv7-a+virt
+# objdump: -dr --prefix-addresses --show-raw-insn
+
+.*: +file format .*arm.*
+
+Disassembly of section .text:
+0[0-9a-f]+ <[^>]+> e1400070 hvc 0
+0[0-9a-f]+ <[^>]+> e14fff7f hvc 65535 ; 0xffff
+0[0-9a-f]+ <[^>]+> e160006e eret
+0[0-9a-f]+ <[^>]+> e1001200 mrs r1, R8_usr
+0[0-9a-f]+ <[^>]+> e1011200 mrs r1, R9_usr
+0[0-9a-f]+ <[^>]+> e1021200 mrs r1, R10_usr
+0[0-9a-f]+ <[^>]+> e1031200 mrs r1, R11_usr
+0[0-9a-f]+ <[^>]+> e1041200 mrs r1, R12_usr
+0[0-9a-f]+ <[^>]+> e1051200 mrs r1, SP_usr
+0[0-9a-f]+ <[^>]+> e1061200 mrs r1, LR_usr
+0[0-9a-f]+ <[^>]+> e1081200 mrs r1, R8_fiq
+0[0-9a-f]+ <[^>]+> e1091200 mrs r1, R9_fiq
+0[0-9a-f]+ <[^>]+> e10a1200 mrs r1, R10_fiq
+0[0-9a-f]+ <[^>]+> e10b1200 mrs r1, R11_fiq
+0[0-9a-f]+ <[^>]+> e10c1200 mrs r1, R12_fiq
+0[0-9a-f]+ <[^>]+> e10d1200 mrs r1, SP_fiq
+0[0-9a-f]+ <[^>]+> e10e1200 mrs r1, LR_fiq
+0[0-9a-f]+ <[^>]+> e14e1200 mrs r1, SPSR_fiq
+0[0-9a-f]+ <[^>]+> e1011300 mrs r1, SP_irq
+0[0-9a-f]+ <[^>]+> e1001300 mrs r1, LR_irq
+0[0-9a-f]+ <[^>]+> e1401300 mrs r1, SPSR_irq
+0[0-9a-f]+ <[^>]+> e1031300 mrs r1, SP_svc
+0[0-9a-f]+ <[^>]+> e1021300 mrs r1, LR_svc
+0[0-9a-f]+ <[^>]+> e1421300 mrs r1, SPSR_svc
+0[0-9a-f]+ <[^>]+> e1051300 mrs r1, SP_abt
+0[0-9a-f]+ <[^>]+> e1041300 mrs r1, LR_abt
+0[0-9a-f]+ <[^>]+> e1441300 mrs r1, SPSR_abt
+0[0-9a-f]+ <[^>]+> e1071300 mrs r1, SP_und
+0[0-9a-f]+ <[^>]+> e1061300 mrs r1, LR_und
+0[0-9a-f]+ <[^>]+> e1461300 mrs r1, SPSR_und
+0[0-9a-f]+ <[^>]+> e10d1300 mrs r1, SP_mon
+0[0-9a-f]+ <[^>]+> e10c1300 mrs r1, LR_mon
+0[0-9a-f]+ <[^>]+> e14c1300 mrs r1, SPSR_mon
+0[0-9a-f]+ <[^>]+> e10f1300 mrs r1, SP_hyp
+0[0-9a-f]+ <[^>]+> e10e1300 mrs r1, ELR_hyp
+0[0-9a-f]+ <[^>]+> e14e1300 mrs r1, SPSR_hyp
+0[0-9a-f]+ <[^>]+> e120f201 msr R8_usr, r1
+0[0-9a-f]+ <[^>]+> e121f201 msr R9_usr, r1
+0[0-9a-f]+ <[^>]+> e122f201 msr R10_usr, r1
+0[0-9a-f]+ <[^>]+> e123f201 msr R11_usr, r1
+0[0-9a-f]+ <[^>]+> e124f201 msr R12_usr, r1
+0[0-9a-f]+ <[^>]+> e125f201 msr SP_usr, r1
+0[0-9a-f]+ <[^>]+> e126f201 msr LR_usr, r1
+0[0-9a-f]+ <[^>]+> e128f201 msr R8_fiq, r1
+0[0-9a-f]+ <[^>]+> e129f201 msr R9_fiq, r1
+0[0-9a-f]+ <[^>]+> e12af201 msr R10_fiq, r1
+0[0-9a-f]+ <[^>]+> e12bf201 msr R11_fiq, r1
+0[0-9a-f]+ <[^>]+> e12cf201 msr R12_fiq, r1
+0[0-9a-f]+ <[^>]+> e12df201 msr SP_fiq, r1
+0[0-9a-f]+ <[^>]+> e12ef201 msr LR_fiq, r1
+0[0-9a-f]+ <[^>]+> e16ef201 msr SPSR_fiq, r1
+0[0-9a-f]+ <[^>]+> e121f301 msr SP_irq, r1
+0[0-9a-f]+ <[^>]+> e120f301 msr LR_irq, r1
+0[0-9a-f]+ <[^>]+> e160f301 msr SPSR_irq, r1
+0[0-9a-f]+ <[^>]+> e123f301 msr SP_svc, r1
+0[0-9a-f]+ <[^>]+> e122f301 msr LR_svc, r1
+0[0-9a-f]+ <[^>]+> e162f301 msr SPSR_svc, r1
+0[0-9a-f]+ <[^>]+> e125f301 msr SP_abt, r1
+0[0-9a-f]+ <[^>]+> e124f301 msr LR_abt, r1
+0[0-9a-f]+ <[^>]+> e164f301 msr SPSR_abt, r1
+0[0-9a-f]+ <[^>]+> e127f301 msr SP_und, r1
+0[0-9a-f]+ <[^>]+> e126f301 msr LR_und, r1
+0[0-9a-f]+ <[^>]+> e166f301 msr SPSR_und, r1
+0[0-9a-f]+ <[^>]+> e12df301 msr SP_mon, r1
+0[0-9a-f]+ <[^>]+> e12cf301 msr LR_mon, r1
+0[0-9a-f]+ <[^>]+> e16cf301 msr SPSR_mon, r1
+0[0-9a-f]+ <[^>]+> e12ff301 msr SP_hyp, r1
+0[0-9a-f]+ <[^>]+> e12ef301 msr ELR_hyp, r1
+0[0-9a-f]+ <[^>]+> e16ef301 msr SPSR_hyp, r1
+0[0-9a-f]+ <[^>]+> f7e0 8000 hvc #0
+0[0-9a-f]+ <[^>]+> f7ef 8fff hvc #65535 ; 0xffff
+0[0-9a-f]+ <[^>]+> f3de 8f00 subs pc, lr, #0
+0[0-9a-f]+ <[^>]+> f3e0 8120 mrs r1, R8_usr
+0[0-9a-f]+ <[^>]+> f3e1 8120 mrs r1, R9_usr
+0[0-9a-f]+ <[^>]+> f3e2 8120 mrs r1, R10_usr
+0[0-9a-f]+ <[^>]+> f3e3 8120 mrs r1, R11_usr
+0[0-9a-f]+ <[^>]+> f3e4 8120 mrs r1, R12_usr
+0[0-9a-f]+ <[^>]+> f3e5 8120 mrs r1, SP_usr
+0[0-9a-f]+ <[^>]+> f3e6 8120 mrs r1, LR_usr
+0[0-9a-f]+ <[^>]+> f3e8 8120 mrs r1, R8_fiq
+0[0-9a-f]+ <[^>]+> f3e9 8120 mrs r1, R9_fiq
+0[0-9a-f]+ <[^>]+> f3ea 8120 mrs r1, R10_fiq
+0[0-9a-f]+ <[^>]+> f3eb 8120 mrs r1, R11_fiq
+0[0-9a-f]+ <[^>]+> f3ec 8120 mrs r1, R12_fiq
+0[0-9a-f]+ <[^>]+> f3ed 8120 mrs r1, SP_fiq
+0[0-9a-f]+ <[^>]+> f3ee 8120 mrs r1, LR_fiq
+0[0-9a-f]+ <[^>]+> f3fe 8120 mrs r1, SPSR_fiq
+0[0-9a-f]+ <[^>]+> f3e1 8130 mrs r1, SP_irq
+0[0-9a-f]+ <[^>]+> f3e0 8130 mrs r1, LR_irq
+0[0-9a-f]+ <[^>]+> f3f0 8130 mrs r1, SPSR_irq
+0[0-9a-f]+ <[^>]+> f3e3 8130 mrs r1, SP_svc
+0[0-9a-f]+ <[^>]+> f3e2 8130 mrs r1, LR_svc
+0[0-9a-f]+ <[^>]+> f3f2 8130 mrs r1, SPSR_svc
+0[0-9a-f]+ <[^>]+> f3e5 8130 mrs r1, SP_abt
+0[0-9a-f]+ <[^>]+> f3e4 8130 mrs r1, LR_abt
+0[0-9a-f]+ <[^>]+> f3f4 8130 mrs r1, SPSR_abt
+0[0-9a-f]+ <[^>]+> f3e7 8130 mrs r1, SP_und
+0[0-9a-f]+ <[^>]+> f3e6 8130 mrs r1, LR_und
+0[0-9a-f]+ <[^>]+> f3f6 8130 mrs r1, SPSR_und
+0[0-9a-f]+ <[^>]+> f3ed 8130 mrs r1, SP_mon
+0[0-9a-f]+ <[^>]+> f3ec 8130 mrs r1, LR_mon
+0[0-9a-f]+ <[^>]+> f3fc 8130 mrs r1, SPSR_mon
+0[0-9a-f]+ <[^>]+> f3ef 8130 mrs r1, SP_hyp
+0[0-9a-f]+ <[^>]+> f3ee 8130 mrs r1, ELR_hyp
+0[0-9a-f]+ <[^>]+> f3fe 8130 mrs r1, SPSR_hyp
+0[0-9a-f]+ <[^>]+> f381 8020 msr R8_usr, r1
+0[0-9a-f]+ <[^>]+> f381 8120 msr R9_usr, r1
+0[0-9a-f]+ <[^>]+> f381 8220 msr R10_usr, r1
+0[0-9a-f]+ <[^>]+> f381 8320 msr R11_usr, r1
+0[0-9a-f]+ <[^>]+> f381 8420 msr R12_usr, r1
+0[0-9a-f]+ <[^>]+> f381 8520 msr SP_usr, r1
+0[0-9a-f]+ <[^>]+> f381 8620 msr LR_usr, r1
+0[0-9a-f]+ <[^>]+> f381 8820 msr R8_fiq, r1
+0[0-9a-f]+ <[^>]+> f381 8920 msr R9_fiq, r1
+0[0-9a-f]+ <[^>]+> f381 8a20 msr R10_fiq, r1
+0[0-9a-f]+ <[^>]+> f381 8b20 msr R11_fiq, r1
+0[0-9a-f]+ <[^>]+> f381 8c20 msr R12_fiq, r1
+0[0-9a-f]+ <[^>]+> f381 8d20 msr SP_fiq, r1
+0[0-9a-f]+ <[^>]+> f381 8e20 msr LR_fiq, r1
+0[0-9a-f]+ <[^>]+> f391 8e20 msr SPSR_fiq, r1
+0[0-9a-f]+ <[^>]+> f381 8130 msr SP_irq, r1
+0[0-9a-f]+ <[^>]+> f381 8030 msr LR_irq, r1
+0[0-9a-f]+ <[^>]+> f391 8030 msr SPSR_irq, r1
+0[0-9a-f]+ <[^>]+> f381 8330 msr SP_svc, r1
+0[0-9a-f]+ <[^>]+> f381 8230 msr LR_svc, r1
+0[0-9a-f]+ <[^>]+> f391 8230 msr SPSR_svc, r1
+0[0-9a-f]+ <[^>]+> f381 8530 msr SP_abt, r1
+0[0-9a-f]+ <[^>]+> f381 8430 msr LR_abt, r1
+0[0-9a-f]+ <[^>]+> f391 8430 msr SPSR_abt, r1
+0[0-9a-f]+ <[^>]+> f381 8730 msr SP_und, r1
+0[0-9a-f]+ <[^>]+> f381 8630 msr LR_und, r1
+0[0-9a-f]+ <[^>]+> f391 8630 msr SPSR_und, r1
+0[0-9a-f]+ <[^>]+> f381 8d30 msr SP_mon, r1
+0[0-9a-f]+ <[^>]+> f381 8c30 msr LR_mon, r1
+0[0-9a-f]+ <[^>]+> f391 8c30 msr SPSR_mon, r1
+0[0-9a-f]+ <[^>]+> f381 8f30 msr SP_hyp, r1
+0[0-9a-f]+ <[^>]+> f381 8e30 msr ELR_hyp, r1
+0[0-9a-f]+ <[^>]+> f391 8e30 msr SPSR_hyp, r1
diff --git a/gas/testsuite/gas/arm/armv7-a+virt.s b/gas/testsuite/gas/arm/armv7-a+virt.s
new file mode 100644
index 0000000..354b8bc
--- /dev/null
+++ b/gas/testsuite/gas/arm/armv7-a+virt.s
@@ -0,0 +1,146 @@
+ .text
+ .syntax unified
+ .arm
+foo:
+ hvc 0x0000
+ hvc 0xffff
+ eret
+ mrs r1, R8_usr
+ mrs r1, R9_usr
+ mrs r1, R10_usr
+ mrs r1, R11_usr
+ mrs r1, R12_usr
+ mrs r1, SP_usr
+ mrs r1, LR_usr
+ mrs r1, R8_fiq
+ mrs r1, R9_fiq
+ mrs r1, R10_fiq
+ mrs r1, R11_fiq
+ mrs r1, R12_fiq
+ mrs r1, SP_fiq
+ mrs r1, LR_fiq
+ mrs r1, SPSR_fiq
+ mrs r1, SP_irq
+ mrs r1, LR_irq
+ mrs r1, SPSR_irq
+ mrs r1, SP_svc
+ mrs r1, LR_svc
+ mrs r1, SPSR_svc
+ mrs r1, SP_abt
+ mrs r1, LR_abt
+ mrs r1, SPSR_abt
+ mrs r1, SP_und
+ mrs r1, LR_und
+ mrs r1, SPSR_und
+ mrs r1, SP_mon
+ mrs r1, LR_mon
+ mrs r1, SPSR_mon
+ mrs r1, SP_hyp
+ mrs r1, ELR_hyp
+ mrs r1, SPSR_hyp
+ msr R8_usr, r1
+ msr R9_usr, r1
+ msr R10_usr, r1
+ msr R11_usr, r1
+ msr R12_usr, r1
+ msr SP_usr, r1
+ msr LR_usr, r1
+ msr R8_fiq, r1
+ msr R9_fiq, r1
+ msr R10_fiq, r1
+ msr R11_fiq, r1
+ msr R12_fiq, r1
+ msr SP_fiq, r1
+ msr LR_fiq, r1
+ msr SPSR_fiq, r1
+ msr SP_irq, r1
+ msr LR_irq, r1
+ msr SPSR_irq, r1
+ msr SP_svc, r1
+ msr LR_svc, r1
+ msr SPSR_svc, r1
+ msr SP_abt, r1
+ msr LR_abt, r1
+ msr SPSR_abt, r1
+ msr SP_und, r1
+ msr LR_und, r1
+ msr SPSR_und, r1
+ msr SP_mon, r1
+ msr LR_mon, r1
+ msr SPSR_mon, r1
+ msr SP_hyp, r1
+ msr ELR_hyp, r1
+ msr SPSR_hyp, r1
+
+ .thumb
+bar:
+ hvc 0x0000
+ hvc 0xffff
+ eret
+ mrs r1, R8_usr
+ mrs r1, R9_usr
+ mrs r1, R10_usr
+ mrs r1, R11_usr
+ mrs r1, R12_usr
+ mrs r1, SP_usr
+ mrs r1, LR_usr
+ mrs r1, R8_fiq
+ mrs r1, R9_fiq
+ mrs r1, R10_fiq
+ mrs r1, R11_fiq
+ mrs r1, R12_fiq
+ mrs r1, SP_fiq
+ mrs r1, LR_fiq
+ mrs r1, SPSR_fiq
+ mrs r1, SP_irq
+ mrs r1, LR_irq
+ mrs r1, SPSR_irq
+ mrs r1, SP_svc
+ mrs r1, LR_svc
+ mrs r1, SPSR_svc
+ mrs r1, SP_abt
+ mrs r1, LR_abt
+ mrs r1, SPSR_abt
+ mrs r1, SP_und
+ mrs r1, LR_und
+ mrs r1, SPSR_und
+ mrs r1, SP_mon
+ mrs r1, LR_mon
+ mrs r1, SPSR_mon
+ mrs r1, SP_hyp
+ mrs r1, ELR_hyp
+ mrs r1, SPSR_hyp
+ msr R8_usr, r1
+ msr R9_usr, r1
+ msr R10_usr, r1
+ msr R11_usr, r1
+ msr R12_usr, r1
+ msr SP_usr, r1
+ msr LR_usr, r1
+ msr R8_fiq, r1
+ msr R9_fiq, r1
+ msr R10_fiq, r1
+ msr R11_fiq, r1
+ msr R12_fiq, r1
+ msr SP_fiq, r1
+ msr LR_fiq, r1
+ msr SPSR_fiq, r1
+ msr SP_irq, r1
+ msr LR_irq, r1
+ msr SPSR_irq, r1
+ msr SP_svc, r1
+ msr LR_svc, r1
+ msr SPSR_svc, r1
+ msr SP_abt, r1
+ msr LR_abt, r1
+ msr SPSR_abt, r1
+ msr SP_und, r1
+ msr LR_und, r1
+ msr SPSR_und, r1
+ msr SP_mon, r1
+ msr LR_mon, r1
+ msr SPSR_mon, r1
+ msr SP_hyp, r1
+ msr ELR_hyp, r1
+ msr SPSR_hyp, r1
+
diff --git a/gas/testsuite/gas/arm/attr-march-all.d b/gas/testsuite/gas/arm/attr-march-all.d
index a976d04..e56f317 100644
--- a/gas/testsuite/gas/arm/attr-march-all.d
+++ b/gas/testsuite/gas/arm/attr-march-all.d
@@ -14,4 +14,4 @@ File Attributes
Tag_THUMB_ISA_use: Thumb-2
Tag_MPextension_use: Allowed
Tag_DIV_use: Allowed in v7-A with integer division extension
- Tag_Virtualization_use: TrustZone
+ Tag_Virtualization_use: TrustZone and Virtualization Extensions
diff --git a/gas/testsuite/gas/arm/attr-march-armv7-a+sec+virt.d b/gas/testsuite/gas/arm/attr-march-armv7-a+sec+virt.d
new file mode 100644
index 0000000..c51e093
--- /dev/null
+++ b/gas/testsuite/gas/arm/attr-march-armv7-a+sec+virt.d
@@ -0,0 +1,16 @@
+# name: attributes for -march=armv7-a+sec+virt
+# source: blank.s
+# as: -march=armv7-a+sec+virt
+# readelf: -A
+# This test is only valid on EABI based ports.
+# target: *-*-*eabi
+
+Attribute Section: aeabi
+File Attributes
+ Tag_CPU_name: "7-A"
+ Tag_CPU_arch: v7
+ Tag_CPU_arch_profile: Application
+ Tag_ARM_ISA_use: Yes
+ Tag_THUMB_ISA_use: Thumb-2
+ Tag_DIV_use: Allowed in v7-A with integer division extension
+ Tag_Virtualization_use: TrustZone and Virtualization Extensions
diff --git a/gas/testsuite/gas/arm/attr-march-armv7-a+virt.d b/gas/testsuite/gas/arm/attr-march-armv7-a+virt.d
new file mode 100644
index 0000000..9329bc1
--- /dev/null
+++ b/gas/testsuite/gas/arm/attr-march-armv7-a+virt.d
@@ -0,0 +1,16 @@
+# name: attributes for -march=armv7-a+virt
+# source: blank.s
+# as: -march=armv7-a+virt
+# readelf: -A
+# This test is only valid on EABI based ports.
+# target: *-*-*eabi
+
+Attribute Section: aeabi
+File Attributes
+ Tag_CPU_name: "7-A"
+ Tag_CPU_arch: v7
+ Tag_CPU_arch_profile: Application
+ Tag_ARM_ISA_use: Yes
+ Tag_THUMB_ISA_use: Thumb-2
+ Tag_DIV_use: Allowed in v7-A with integer division extension
+ Tag_Virtualization_use: Virtualization Extensions
diff --git a/include/opcode/arm.h b/include/opcode/arm.h
index 58cace8..0bfd302 100644
--- a/include/opcode/arm.h
+++ b/include/opcode/arm.h
@@ -54,6 +54,7 @@
#define ARM_EXT_OS 0x20000000 /* OS Extensions. */
#define ARM_EXT_ADIV 0x40000000 /* Integer divide extensions in ARM
state. */
+#define ARM_EXT_VIRT 0x80000000 /* Virtualization extensions. */
/* Co-processor space extensions. */
#define ARM_CEXT_XSCALE 0x00000001 /* Allow MIA etc. */
@@ -222,10 +223,11 @@
#define ARM_ARCH_V7A_MP_SEC \
ARM_FEATURE (ARM_AEXT_V7A | ARM_EXT_MP | ARM_EXT_SEC, \
0)
-/* v7-a+idiv+mp+sec. */
-#define ARM_ARCH_V7A_IDIV_MP_SEC \
+/* v7-a+idiv+mp+sec+virt. */
+#define ARM_ARCH_V7A_IDIV_MP_SEC_VIRT \
ARM_FEATURE (ARM_AEXT_V7A | ARM_EXT_MP | ARM_EXT_SEC \
- | ARM_EXT_DIV | ARM_EXT_ADIV, 0)
+ | ARM_EXT_DIV | ARM_EXT_ADIV \
+ | ARM_EXT_VIRT, 0)
/* There are too many feature bits to fit in a single word, so use a
structure. For simplicity we put all core features in one word and
diff --git a/opcodes/arm-dis.c b/opcodes/arm-dis.c
index 005c957..e506abd 100644
--- a/opcodes/arm-dis.c
+++ b/opcodes/arm-dis.c
@@ -816,7 +816,8 @@ static const struct opcode32 neon_opcodes[] =
%e print arm SMI operand (bits 0..7,8..19).
%E print the LSB and WIDTH fields of a BFI or BFC instruction.
- %V print the 16-bit immediate field of a MOVT or MOVW instruction. */
+ %V print the 16-bit immediate field of a MOVT or MOVW instruction.
+ %R print the SPSR/CPSR or banked register of an MRS. */
static const struct opcode32 arm_opcodes[] =
{
@@ -829,6 +830,10 @@ static const struct opcode32 arm_opcodes[] =
{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"},
+ /* Virtualization Extension instructions. */
+ {ARM_EXT_VIRT, 0x0160006e, 0x0fffffff, "eret%c"},
+ {ARM_EXT_VIRT, 0x01400070, 0x0ff000f0, "hvc%c\t%e"},
+
/* Integer Divide Extension instructions. */
{ARM_EXT_ADIV, 0x0710f010, 0x0ff0f0f0, "sdiv%c\t%16-19r, %0-3r, %8-11r"},
{ARM_EXT_ADIV, 0x0730f010, 0x0ff0f0f0, "udiv%c\t%16-19r, %0-3r, %8-11r"},
@@ -1091,8 +1096,9 @@ static const struct opcode32 arm_opcodes[] =
{ARM_EXT_V1, 0x00e00000, 0x0fe00010, "rsc%20's%c\t%12-15r, %16-19r, %o"},
{ARM_EXT_V1, 0x00e00010, 0x0fe00090, "rsc%20's%c\t%12-15R, %16-19R, %o"},
- {ARM_EXT_V3, 0x0120f000, 0x0db0f000, "msr%c\t%22?SCPSR%C, %o"},
- {ARM_EXT_V3, 0x010f0000, 0x0fbf0fff, "mrs%c\t%12-15R, %22?SCPSR"},
+ {ARM_EXT_VIRT, 0x0120f200, 0x0fb0f200, "msr%c\t%C, %0-3r"},
+ {ARM_EXT_V3, 0x0120f000, 0x0db0f000, "msr%c\t%C, %o"},
+ {ARM_EXT_V3, 0x01000000, 0x0fb00cff, "mrs%c\t%12-15R, %R"},
{ARM_EXT_V1, 0x03000000, 0x0fe00000, "tst%p%c\t%16-19r, %o"},
{ARM_EXT_V1, 0x01000000, 0x0fe00010, "tst%p%c\t%16-19r, %o"},
@@ -1103,7 +1109,6 @@ static const struct opcode32 arm_opcodes[] =
{ARM_EXT_V1, 0x01200010, 0x0fe00090, "teq%p%c\t%16-19R, %o"},
{ARM_EXT_V1, 0x03400000, 0x0fe00000, "cmp%p%c\t%16-19r, %o"},
- {ARM_EXT_V3, 0x01400000, 0x0ff00010, "mrs%c\t%12-15R, %22?SCPSR"},
{ARM_EXT_V1, 0x01400000, 0x0fe00010, "cmp%p%c\t%16-19r, %o"},
{ARM_EXT_V1, 0x01400010, 0x0fe00090, "cmp%p%c\t%16-19R, %o"},
@@ -1313,6 +1318,7 @@ static const struct opcode16 thumb_opcodes[] =
%M print a modified 12-bit immediate (same location)
%J print a 16-bit immediate from hw1[3:0,10],hw2[14:12,7:0]
%K print a 16-bit immediate from hw2[3:0],hw1[3:0],hw2[11:4]
+ %H print a 16-bit immediate from hw2[3:0],hw1[11:0]
%S print a possibly-shifted Rm
%a print the address of a plain load/store
@@ -1360,6 +1366,10 @@ static const struct opcode32 thumb32_opcodes[] =
{ARM_EXT_DIV, 0xfb90f0f0, 0xfff0f0f0, "sdiv%c\t%8-11r, %16-19r, %0-3r"},
{ARM_EXT_DIV, 0xfbb0f0f0, 0xfff0f0f0, "udiv%c\t%8-11r, %16-19r, %0-3r"},
+ /* Virtualization Extension instructions. */
+ {ARM_EXT_VIRT, 0xf7e08000, 0xfff0f000, "hvc%c\t%V"},
+ /* We skip ERET as that is SUBS pc, lr, #0. */
+
/* MP Extension instructions. */
{ARM_EXT_MP, 0xf830f000, 0xff70f000, "pldw%c\t%a"},
@@ -1380,7 +1390,7 @@ static const struct opcode32 thumb32_opcodes[] =
{ARM_EXT_V6T2, 0xf3c08f00, 0xfff0ffff, "bxj%c\t%16-19r%x"},
{ARM_EXT_V6T2, 0xe810c000, 0xffd0ffff, "rfedb%c\t%16-19r%21'!"},
{ARM_EXT_V6T2, 0xe990c000, 0xffd0ffff, "rfeia%c\t%16-19r%21'!"},
- {ARM_EXT_V6T2, 0xf3ef8000, 0xffeff000, "mrs%c\t%8-11r, %D"},
+ {ARM_EXT_V6T2, 0xf3e08000, 0xffe0f000, "mrs%c\t%8-11r, %D"},
{ARM_EXT_V6T2, 0xf3af8100, 0xffffffe0, "cps\t#%0-4d%X"},
{ARM_EXT_V6T2, 0xe8d0f000, 0xfff0fff0, "tbb%c\t[%16-19r, %0-3r]%x"},
{ARM_EXT_V6T2, 0xe8d0f010, 0xfff0fff0, "tbh%c\t[%16-19r, %0-3r, lsl #1]%x"},
@@ -2862,6 +2872,52 @@ print_insn_neon (struct disassemble_info *info, long given, bfd_boolean thumb)
return FALSE;
}
+/* Return the name of a v7A special register. */
+
+static const char *
+banked_regname (unsigned reg)
+{
+ switch (reg)
+ {
+ case 15: return "CPSR";
+ case 32: return "R8_usr";
+ case 33: return "R9_usr";
+ case 34: return "R10_usr";
+ case 35: return "R11_usr";
+ case 36: return "R12_usr";
+ case 37: return "SP_usr";
+ case 38: return "LR_usr";
+ case 40: return "R8_fiq";
+ case 41: return "R9_fiq";
+ case 42: return "R10_fiq";
+ case 43: return "R11_fiq";
+ case 44: return "R12_fiq";
+ case 45: return "SP_fiq";
+ case 46: return "LR_fiq";
+ case 48: return "LR_irq";
+ case 49: return "SP_irq";
+ case 50: return "LR_svc";
+ case 51: return "SP_svc";
+ case 52: return "LR_abt";
+ case 53: return "SP_abt";
+ case 54: return "LR_und";
+ case 55: return "SP_und";
+ case 60: return "LR_mon";
+ case 61: return "SP_mon";
+ case 62: return "ELR_hyp";
+ case 63: return "SP_hyp";
+ case 79: return "SPSR";
+ case 110: return "SPSR_fiq";
+ case 112: return "SPSR_irq";
+ case 114: return "SPSR_svc";
+ case 116: return "SPSR_abt";
+ case 118: return "SPSR_und";
+ case 124: return "SPSR_mon";
+ case 126: return "SPSR_hyp";
+ default: return NULL;
+ }
+}
+
/* Print one ARM instruction from PC on INFO->STREAM. */
static void
@@ -3156,15 +3212,31 @@ print_insn_arm (bfd_vma pc, struct disassemble_info *info, long given)
break;
case 'C':
- func (stream, "_");
- if (given & 0x80000)
- func (stream, "f");
- if (given & 0x40000)
- func (stream, "s");
- if (given & 0x20000)
- func (stream, "x");
- if (given & 0x10000)
- func (stream, "c");
+ if ((given & 0x02000200) == 0x200)
+ {
+ const char * name;
+ unsigned sysm = (given & 0x004f0000) >> 16;
+ sysm |= (given & 0x300) >> 4;
+ name = banked_regname (sysm);
+
+ if (name != NULL)
+ func (stream, "%s", name);
+ else
+ func (stream, "(UNDEF: %lu)", sysm);
+ }
+ else
+ {
+ func (stream, "%cPSR_",
+ (given & 0x00400000) ? 'S' : 'C');
+ if (given & 0x80000)
+ func (stream, "f");
+ if (given & 0x40000)
+ func (stream, "s");
+ if (given & 0x20000)
+ func (stream, "x");
+ if (given & 0x10000)
+ func (stream, "c");
+ }
break;
case 'U':
@@ -3302,6 +3374,21 @@ print_insn_arm (bfd_vma pc, struct disassemble_info *info, long given)
}
break;
+ case 'R':
+ /* Get the PSR/banked register name. */
+ {
+ const char * name;
+ unsigned sysm = (given & 0x004f0000) >> 16;
+ sysm |= (given & 0x300) >> 4;
+ name = banked_regname (sysm);
+
+ if (name != NULL)
+ func (stream, "%s", name);
+ else
+ func (stream, "(UNDEF: %lu)", sysm);
+ }
+ break;
+
case 'V':
/* 16-bit unsigned immediate from a MOVT or MOVW
instruction, encoded in bits 0:11 and 15:19. */
@@ -3746,6 +3833,17 @@ print_insn_thumb32 (bfd_vma pc, struct disassemble_info *info, long given)
}
break;
+ case 'V':
+ {
+ unsigned int imm = 0;
+
+ imm |= (given & 0x00000fffu);
+ imm |= (given & 0x000f0000u) >> 4;
+ func (stream, "#%u", imm);
+ value_in_comment = imm;
+ }
+ break;
+
case 'S':
{
unsigned int reg = (given & 0x0000000fu);
@@ -4070,6 +4168,18 @@ print_insn_thumb32 (bfd_vma pc, struct disassemble_info *info, long given)
if (given & 0x100)
func (stream, "c");
}
+ else if ((given & 0x20) == 0x20)
+ {
+ char const* name;
+ unsigned sysm = (given & 0xf00) >> 8;
+ sysm |= (given & 0x30);
+ sysm |= (given & 0x00100000) >> 14;
+ name = banked_regname (sysm);
+ if (name != NULL)
+ func (stream, "%s", name);
+ else
+ func (stream, "(UNDEF: %lu)", sysm);
+ }
else
{
func (stream, psr_name (given & 0xff));
@@ -4077,8 +4187,19 @@ print_insn_thumb32 (bfd_vma pc, struct disassemble_info *info, long given)
break;
case 'D':
- if ((given & 0xff) == 0)
- func (stream, "%cPSR", (given & 0x100000) ? 'S' : 'C');
+ if (((given & 0xff) == 0)
+ || ((given & 0x20) == 0x20))
+ {
+ char const* name;
+ unsigned sm = (given & 0xf0000) >> 16;
+ sm |= (given & 0x30);
+ sm |= (given & 0x00100000) >> 14;
+ name = banked_regname (sm);
+ if (name != NULL)
+ func (stream, "%s", name);
+ else
+ func (stream, "(UNDEF: %lu)", sm);
+ }
else
func (stream, psr_name (given & 0xff));
break;