* config/tc-arm.c (parse_vfp_reg_list): Improve register bounds
authorJulian Brown <julian@codesourcery.com>
Fri, 5 May 2006 18:54:44 +0000 (18:54 +0000)
committerJulian Brown <julian@codesourcery.com>
Fri, 5 May 2006 18:54:44 +0000 (18:54 +0000)
checking.
(do_neon_mov): Enable several VMOV variants for VFP. Add suitable
architecture version checks.
(insns): Allow overlapping instructions to be used in VFP mode.

gas/ChangeLog
gas/config/tc-arm.c

index 59ca0f8..76386d7 100644 (file)
@@ -1,3 +1,11 @@
+2006-05-05  Julian Brown  <julian@codesourcery.com>
+
+       * config/tc-arm.c (parse_vfp_reg_list): Improve register bounds
+       checking.
+       (do_neon_mov): Enable several VMOV variants for VFP. Add suitable
+       architecture version checks.
+       (insns): Allow overlapping instructions to be used in VFP mode.
+
 2006-05-05  H.J. Lu  <hongjiu.lu@intel.com>
 
        PR gas/2598
index 243fc1a..47f39a8 100644 (file)
@@ -1553,6 +1553,15 @@ parse_vfp_reg_list (char **str, unsigned int *pbase, enum reg_list_els etype)
     
     case REGLIST_VFP_D:
       regtype = REG_TYPE_VFD;
+      break;
+    
+    case REGLIST_NEON_D:
+      regtype = REG_TYPE_NDQ;
+      break;
+    }
+
+  if (etype != REGLIST_VFP_S)
+    {
       /* VFPv3 allows 32 D registers.  */
       if (ARM_CPU_HAS_FEATURE (cpu_variant, fpu_vfp_ext_v3))
         {
@@ -1566,12 +1575,6 @@ parse_vfp_reg_list (char **str, unsigned int *pbase, enum reg_list_els etype)
         }
       else
         max_regs = 16;
-      break;
-    
-    case REGLIST_NEON_D:
-      regtype = REG_TYPE_NDQ;
-      max_regs = 32;
-      break;
     }
 
   base_reg = max_regs;
@@ -1588,6 +1591,12 @@ parse_vfp_reg_list (char **str, unsigned int *pbase, enum reg_list_els etype)
          return FAIL;
        }
  
+      if (new_base >= max_regs)
+        {
+          first_error (_("register out of range in list"));
+          return FAIL;
+        }
       /* Note: a value of 2 * n is returned for the register Q<n>.  */
       if (regtype == REG_TYPE_NQ)
         {
@@ -1626,6 +1635,12 @@ parse_vfp_reg_list (char **str, unsigned int *pbase, enum reg_list_els etype)
              return FAIL;
            }
 
+          if (high_range >= max_regs)
+            {
+              first_error (_("register out of range in list"));
+              return FAIL;
+            }
+
           if (regtype == REG_TYPE_NQ)
             high_range = high_range + 1;
 
@@ -11303,6 +11318,9 @@ do_neon_dup (void)
    
    All the encoded bits are hardcoded by this function.
    
+   Cases 4, 6 may be used with VFPv1 and above (only 32-bit transfers!).
+   Cases 5, 7 may be used with VFPv2 and above.
+   
    FIXME: Some of the checking may be a bit sloppy (in a couple of cases you
    can specify a type where it doesn't make sense to, and is ignored).
 */
@@ -11313,6 +11331,7 @@ do_neon_mov (void)
   int nargs = inst.operands[0].present + inst.operands[1].present
               + inst.operands[2].present;
   unsigned save_cond = thumb_mode ? 0xe0000000 : inst.instruction & 0xf0000000;
+  const char *vfp_vers = "selected FPU does not support instruction";
 
   switch (nargs)
     {
@@ -11328,6 +11347,10 @@ do_neon_mov (void)
           unsigned x = NEON_SCALAR_INDEX (inst.operands[1].reg);
           unsigned abcdebits = 0;
 
+          constraint (!ARM_CPU_HAS_FEATURE (cpu_variant, fpu_vfp_ext_v1),
+                      _(vfp_vers));
+          constraint (!ARM_CPU_HAS_FEATURE (cpu_variant, fpu_neon_ext_v1)
+                      && et.size != 32, _(vfp_vers));
           constraint (et.type == NT_invtype, _("bad type for scalar"));
           constraint (x >= 64 / et.size, _("scalar index out of range"));
 
@@ -11361,6 +11384,10 @@ do_neon_mov (void)
               unsigned dn = NEON_SCALAR_REG (inst.operands[0].reg);
               unsigned x = NEON_SCALAR_INDEX (inst.operands[0].reg);
 
+              constraint (!ARM_CPU_HAS_FEATURE (cpu_variant, fpu_vfp_ext_v1),
+                          _(vfp_vers));
+              constraint (!ARM_CPU_HAS_FEATURE (cpu_variant, fpu_neon_ext_v1)
+                          && et.size != 32, _(vfp_vers));
               constraint (et.type == NT_invtype, _("bad type for scalar"));
               constraint (x >= 64 / et.size, _("scalar index out of range"));
 
@@ -11411,6 +11438,9 @@ do_neon_mov (void)
     
     case 3:
       /* Cases 5, 7.  */
+      constraint (!ARM_CPU_HAS_FEATURE (cpu_variant, fpu_vfp_ext_v2),
+                  _(vfp_vers));
+
       if (inst.operands[0].regisimm)
         {
           /* Case 5.  */
@@ -14155,7 +14185,16 @@ static const struct asm_opcode insns[] =
  nUF(vcvtq,     vcvt,    3, (RNQ,  RNQ,  oI32b), neon_cvt),
 
   /* One register and an immediate value. All encoding special-cased!  */
+#undef THUMB_VARIANT
+#define THUMB_VARIANT &fpu_vfp_ext_v1
+#undef ARM_VARIANT
+#define ARM_VARIANT &fpu_vfp_ext_v1
  NCE(vmov,      0,       1, (VMOV),             neon_mov),
+
+#undef THUMB_VARIANT
+#define THUMB_VARIANT &fpu_neon_ext_v1
+#undef ARM_VARIANT
+#define ARM_VARIANT &fpu_neon_ext_v1
  NCE(vmovq,     0,       1, (VMOV),             neon_mov),
  nUF(vmvn,      vmvn,    2, (RNDQ, RNDQ_IMVNb), neon_mvn),
  nUF(vmvnq,     vmvn,    2, (RNQ,  RNDQ_IMVNb), neon_mvn),
@@ -14250,9 +14289,9 @@ static const struct asm_opcode insns[] =
  NUF(vtbx,      1b00840, 3, (RND, NRDLST, RND), neon_tbl_tbx),
 
 #undef THUMB_VARIANT
-#define THUMB_VARIANT &fpu_vfp_v3_or_neon_ext
+#define THUMB_VARIANT &fpu_vfp_ext_v1xd
 #undef ARM_VARIANT
-#define ARM_VARIANT &fpu_vfp_v3_or_neon_ext
+#define ARM_VARIANT &fpu_vfp_ext_v1xd
 
   /* Load/store instructions. Available in Neon or VFPv3.  */
  NCE(vldm,      c900b00, 2, (RRw, NRDLST),    neon_ldm_stm),
@@ -14264,6 +14303,11 @@ static const struct asm_opcode insns[] =
  NCE(vldr,      d100b00, 2, (RND, ADDR),      neon_ldr_str),
  NCE(vstr,      d000b00, 2, (RND, ADDR),      neon_ldr_str),
 
+#undef THUMB_VARIANT
+#define THUMB_VARIANT &fpu_vfp_v3_or_neon_ext
+#undef ARM_VARIANT
+#define ARM_VARIANT &fpu_vfp_v3_or_neon_ext
+
   /* Neon element/structure load/store.  */
  nUF(vld1,      vld1,    2, (NSTRLST, ADDR),  neon_ldx_stx),
  nUF(vst1,      vst1,    2, (NSTRLST, ADDR),  neon_ldx_stx),