Author: andrew
Date: Mon Mar 18 08:22:35 2013
New Revision: 248460
URL: http://svnweb.freebsd.org/changeset/base/248460

Log:
  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.

Modified:
  head/contrib/binutils/gas/config/tc-arm.c

Modified: head/contrib/binutils/gas/config/tc-arm.c
==============================================================================
--- head/contrib/binutils/gas/config/tc-arm.c   Mon Mar 18 07:41:08 2013        
(r248459)
+++ head/contrib/binutils/gas/config/tc-arm.c   Mon Mar 18 08:22:35 2013        
(r248460)
@@ -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),
_______________________________________________
svn-src-head@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to