summaryrefslogtreecommitdiffstats
path: root/contrib/binutils
diff options
context:
space:
mode:
authorandrew <andrew@FreeBSD.org>2013-03-18 08:22:35 +0000
committerandrew <andrew@FreeBSD.org>2013-03-18 08:22:35 +0000
commit7479840eb88c237a735d25cf9f01cc3a07cef955 (patch)
tree97c9127fff01109b536ae1fc308839756ae906e0 /contrib/binutils
parente0722a1284e9361c5be0754fbb14d19b7e6335ae (diff)
downloadFreeBSD-src-7479840eb88c237a735d25cf9f01cc3a07cef955.zip
FreeBSD-src-7479840eb88c237a735d25cf9f01cc3a07cef955.tar.gz
Add support for the vmsr and vmrs instructions. This supports the system
level version of the instructions. When used in userland the hardware only allows us to read/write FPSCR.
Diffstat (limited to 'contrib/binutils')
-rw-r--r--contrib/binutils/gas/config/tc-arm.c66
1 files changed, 66 insertions, 0 deletions
diff --git a/contrib/binutils/gas/config/tc-arm.c b/contrib/binutils/gas/config/tc-arm.c
index 83e5433..c8f3149 100644
--- a/contrib/binutils/gas/config/tc-arm.c
+++ b/contrib/binutils/gas/config/tc-arm.c
@@ -651,6 +651,7 @@ struct asm_opcode
#define BAD_ARGS _("bad arguments to instruction")
#define BAD_PC _("r15 not allowed here")
+#define BAD_SP _("r13 not allowed here")
#define BAD_COND _("instruction cannot be conditional")
#define BAD_OVERLAP _("registers may not be the same")
#define BAD_HIREG _("lo register required")
@@ -659,6 +660,7 @@ struct asm_opcode
#define BAD_BRANCH _("branch must be last instruction in IT block")
#define BAD_NOT_IT _("instruction not allowed in IT block")
#define BAD_FPU _("selected FPU does not support instruction")
+#define BAD_VMRS _("APSR_nzcv may only be used with fpscr")
static struct hash_control *arm_ops_hsh;
static struct hash_control *arm_cond_hsh;
@@ -7095,6 +7097,68 @@ do_vfp_nsyn_msr (void)
return SUCCESS;
}
+static int
+do_vfp_vmrs (void)
+{
+ int rt;
+
+ /* The destination register can be r0-r14 or APSR_nzcv */
+ if (inst.operands[0].reg > 14)
+ {
+ inst.error = BAD_PC;
+ return FAIL;
+ }
+
+ /* If the destination is r13 and not in ARM mode then unprefictable */
+ if (thumb_mode && inst.operands[0].reg == REG_SP)
+ {
+ inst.error = BAD_SP;
+ return FAIL;
+ }
+
+ /* If the destination is APSR_nzcv */
+ if (inst.operands[0].isvec && inst.operands[1].reg != 1)
+ {
+ inst.error = BAD_VMRS;
+ return FAIL;
+ }
+
+ if (inst.operands[0].isvec)
+ rt = 15;
+ else
+ rt = inst.operands[0].reg;
+
+ /* Or in the registers to use */
+ inst.instruction |= rt << 12;
+ inst.instruction |= inst.operands[1].reg << 16;
+
+ return SUCCESS;
+}
+
+static int
+do_vfp_vmsr (void)
+{
+ /* The destination register can be r0-r14 or APSR_nzcv */
+ if (inst.operands[1].reg > 14)
+ {
+ inst.error = BAD_PC;
+ return FAIL;
+ }
+
+ /* If the destination is r13 and not in ARM mode then unprefictable */
+ if (thumb_mode && inst.operands[0].reg == REG_SP)
+ {
+ inst.error = BAD_SP;
+ return FAIL;
+ }
+
+ /* Or in the registers to use */
+ inst.instruction |= inst.operands[1].reg << 12;
+ inst.instruction |= inst.operands[0].reg << 16;
+
+ return SUCCESS;
+}
+
static void
do_mrs (void)
{
@@ -15726,6 +15790,8 @@ static const struct asm_opcode insns[] =
cCE(ftouizs, ebc0ac0, 2, (RVS, RVS), vfp_sp_monadic),
cCE(fmrx, ef00a10, 2, (RR, RVC), rd_rn),
cCE(fmxr, ee00a10, 2, (RVC, RR), rn_rd),
+ cCE(vmrs, ef00a10, 2, (APSR_RR, RVC), vfp_vmrs),
+ cCE(vmsr, ee00a10, 2, (RVC, RR), vfp_vmsr),
/* Memory operations. */
cCE(flds, d100a00, 2, (RVS, ADDRGLDC), vfp_sp_ldst),
OpenPOWER on IntegriCloud