[Patch][gas][arm] Enable VLDM, VSTM, VPUSH, VPOP for MVE

Mihail Ionescu mihail.ionescu@foss.arm.com
Fri Nov 8 17:31:00 GMT 2019


Hi,

Small update. I made a mistake in the code, using the
wrong constraint, for fpu_vfp_ext_v1 instead of fpu_vfp_ext_v1xd
which ended up breaking vldm and vstm for some targets.
The ChangeLog shouldn't need any changes.

Is it ok for trunk?


Regards,
Mihail

###############     Attachment also inlined for ease of reply 
###############


diff --git a/gas/config/tc-arm.c b/gas/config/tc-arm.c
index 
76098e6b1b5cf8c5a7f3a2383dfbe4658cc7b6be..f5bf5802b6a242284ccc21f10adaa8d2a3fb60c1 
100644
--- a/gas/config/tc-arm.c
+++ b/gas/config/tc-arm.c
@@ -16440,36 +16440,6 @@ nsyn_insert_sp (void)
    inst.operands[0].present = 1;
  }

-static void
-do_vfp_nsyn_push (void)
-{
-  nsyn_insert_sp ();
-
-  constraint (inst.operands[1].imm < 1 || inst.operands[1].imm > 16,
-	      _("register list must contain at least 1 and at most 16 "
-		"registers"));
-
-  if (inst.operands[1].issingle)
-    do_vfp_nsyn_opcode ("fstmdbs");
-  else
-    do_vfp_nsyn_opcode ("fstmdbd");
-}
-
-static void
-do_vfp_nsyn_pop (void)
-{
-  nsyn_insert_sp ();
-
-  constraint (inst.operands[1].imm < 1 || inst.operands[1].imm > 16,
-	      _("register list must contain at least 1 and at most 16 "
-		"registers"));
-
-  if (inst.operands[1].issingle)
-    do_vfp_nsyn_opcode ("fldmias");
-  else
-    do_vfp_nsyn_opcode ("fldmiad");
-}
-
  /* Fix up Neon data-processing instructions, ORing in the correct bits for
     ARM mode or Thumb mode and moving the encoded bit 24 to bit 28.  */

@@ -20465,6 +20435,9 @@ do_neon_tbl_tbx (void)
  static void
  do_neon_ldm_stm (void)
  {
+  constraint (!ARM_CPU_HAS_FEATURE (cpu_variant, fpu_vfp_ext_v1xd)
+	      && !ARM_CPU_HAS_FEATURE (cpu_variant, mve_ext),
+	      _(BAD_FPU));
    /* P, U and L bits are part of bitmask.  */
    int is_dbmode = (inst.instruction & (1 << 24)) != 0;
    unsigned offsetbits = inst.operands[1].imm * 2;
@@ -20493,6 +20466,49 @@ do_neon_ldm_stm (void)
  }

  static void
+do_vfp_nsyn_pop (void)
+{
+  nsyn_insert_sp ();
+  if (ARM_CPU_HAS_FEATURE (cpu_variant, mve_ext)) {
+    return do_vfp_nsyn_opcode ("vldm");
+  }
+
+  constraint (!ARM_CPU_HAS_FEATURE (cpu_variant, fpu_vfp_ext_v1xd),
+	      _(BAD_FPU));
+
+  constraint (inst.operands[1].imm < 1 || inst.operands[1].imm > 16,
+	      _("register list must contain at least 1 and at most 16 "
+		"registers"));
+
+  if (inst.operands[1].issingle)
+    do_vfp_nsyn_opcode ("fldmias");
+  else
+    do_vfp_nsyn_opcode ("fldmiad");
+}
+
+static void
+do_vfp_nsyn_push (void)
+{
+  nsyn_insert_sp ();
+  if (ARM_CPU_HAS_FEATURE (cpu_variant, mve_ext)) {
+    return do_vfp_nsyn_opcode ("vstmdb");
+  }
+
+  constraint (!ARM_CPU_HAS_FEATURE (cpu_variant, fpu_vfp_ext_v1xd),
+	      _(BAD_FPU));
+
+  constraint (inst.operands[1].imm < 1 || inst.operands[1].imm > 16,
+	      _("register list must contain at least 1 and at most 16 "
+		"registers"));
+
+  if (inst.operands[1].issingle)
+    do_vfp_nsyn_opcode ("fstmdbs");
+  else
+    do_vfp_nsyn_opcode ("fstmdbd");
+}
+
+
+static void
  do_neon_ldr_str (void)
  {
    int is_ldr = (inst.instruction & (1 << 20)) != 0;
@@ -20572,7 +20588,8 @@ do_vldr_vstr (void)
    /* VLDR/VSTR.  */
    else
      {
-      if (!mark_feature_used (&fpu_vfp_ext_v1xd))
+      if (!mark_feature_used (&fpu_vfp_ext_v1xd)
+	  && !ARM_CPU_HAS_FEATURE (cpu_variant, mve_ext))
  	as_bad (_("Instruction not permitted on this architecture"));
        do_neon_ldr_str ();
      }
@@ -24680,6 +24697,10 @@ static const struct asm_opcode insns[] =
  #define THUMB_VARIANT  & arm_ext_v6t2
   mcCE(vmrs,	ef00a10, 2, (APSR_RR, RVC),   vmrs),
   mcCE(vmsr,	ee00a10, 2, (RVC, RR),        vmsr),
+ mcCE(fldd,	d100b00, 2, (RVD, ADDRGLDC),  vfp_dp_ldst),
+ mcCE(fstd,	d000b00, 2, (RVD, ADDRGLDC),  vfp_dp_ldst),
+ mcCE(flds,	d100a00, 2, (RVS, ADDRGLDC),  vfp_sp_ldst),
+ mcCE(fsts,	d000a00, 2, (RVS, ADDRGLDC),  vfp_sp_ldst),
  #undef THUMB_VARIANT

    /* Moves and type conversions.  */
@@ -24694,8 +24715,6 @@ static const struct asm_opcode insns[] =
   cCE("fmxr",	ee00a10, 2, (RVC, RR),	      rn_rd),

    /* Memory operations.	 */
- cCE("flds",	d100a00, 2, (RVS, ADDRGLDC),  vfp_sp_ldst),
- cCE("fsts",	d000a00, 2, (RVS, ADDRGLDC),  vfp_sp_ldst),
   cCE("fldmias",	c900a00, 2, (RRnpctw, VRSLST),    vfp_sp_ldstmia),
   cCE("fldmfds",	c900a00, 2, (RRnpctw, VRSLST),    vfp_sp_ldstmia),
   cCE("fldmdbs",	d300a00, 2, (RRnpctw, VRSLST),    vfp_sp_ldstmdb),
@@ -24737,8 +24756,6 @@ static const struct asm_opcode insns[] =

   /* Double precision load/store are still present on single precision
      implementations.  */
- cCE("fldd",	d100b00, 2, (RVD, ADDRGLDC),  vfp_dp_ldst),
- cCE("fstd",	d000b00, 2, (RVD, ADDRGLDC),  vfp_dp_ldst),
   cCE("fldmiad",	c900b00, 2, (RRnpctw, VRDLST),    vfp_dp_ldstmia),
   cCE("fldmfdd",	c900b00, 2, (RRnpctw, VRDLST),    vfp_dp_ldstmia),
   cCE("fldmdbd",	d300b00, 2, (RRnpctw, VRDLST),    vfp_dp_ldstmdb),
@@ -24792,6 +24809,19 @@ static const struct asm_opcode insns[] =
  #undef  ARM_VARIANT
  #define ARM_VARIANT    & fpu_vfp_ext_v1xd
  #undef  THUMB_VARIANT
+#define THUMB_VARIANT  & arm_ext_v6t2
+
+ NCE(vldm,      c900b00, 2, (RRnpctw, VRSDLST), neon_ldm_stm),
+ NCE(vldmia,    c900b00, 2, (RRnpctw, VRSDLST), neon_ldm_stm),
+ NCE(vldmdb,    d100b00, 2, (RRnpctw, VRSDLST), neon_ldm_stm),
+ NCE(vstm,      c800b00, 2, (RRnpctw, VRSDLST), neon_ldm_stm),
+ NCE(vstmia,    c800b00, 2, (RRnpctw, VRSDLST), neon_ldm_stm),
+ NCE(vstmdb,    d000b00, 2, (RRnpctw, VRSDLST), neon_ldm_stm),
+
+ NCE(vpop,      0,       1, (VRSDLST),          vfp_nsyn_pop),
+ NCE(vpush,     0,       1, (VRSDLST),          vfp_nsyn_push),
+
+#undef  THUMB_VARIANT
  #define THUMB_VARIANT  & fpu_vfp_ext_v1xd

    /* These mnemonics are unique to VFP.  */
@@ -24800,20 +24830,11 @@ static const struct asm_opcode insns[] =
   nCE(vnmul,     _vnmul,   3, (RVSD, RVSD, RVSD), vfp_nsyn_nmul),
   nCE(vnmla,     _vnmla,   3, (RVSD, RVSD, RVSD), vfp_nsyn_nmul),
   nCE(vnmls,     _vnmls,   3, (RVSD, RVSD, RVSD), vfp_nsyn_nmul),
- NCE(vpush,     0,       1, (VRSDLST),          vfp_nsyn_push),
- NCE(vpop,      0,       1, (VRSDLST),          vfp_nsyn_pop),
   NCE(vcvtz,     0,       2, (RVSD, RVSD),       vfp_nsyn_cvtz),

    /* Mnemonics shared by Neon and VFP.  */
   nCEF(vmls,     _vmls,    3, (RNSDQ, oRNSDQ, RNSDQ_RNSC), 
neon_mac_maybe_scalar),

- NCE(vldm,      c900b00, 2, (RRnpctw, VRSDLST), neon_ldm_stm),
- NCE(vldmia,    c900b00, 2, (RRnpctw, VRSDLST), neon_ldm_stm),
- NCE(vldmdb,    d100b00, 2, (RRnpctw, VRSDLST), neon_ldm_stm),
- NCE(vstm,      c800b00, 2, (RRnpctw, VRSDLST), neon_ldm_stm),
- NCE(vstmia,    c800b00, 2, (RRnpctw, VRSDLST), neon_ldm_stm),
- NCE(vstmdb,    d000b00, 2, (RRnpctw, VRSDLST), neon_ldm_stm),
-
   mnCEF(vcvt,     _vcvt,   3, (RNSDQMQ, RNSDQMQ, oI32z), neon_cvt),
   nCEF(vcvtr,    _vcvt,   2, (RNSDQ, RNSDQ), neon_cvtr),
   MNCEF(vcvtb,	eb20a40, 3, (RVSDMQ, RVSDMQ, oI32b), neon_cvtb),
diff --git a/gas/testsuite/gas/arm/v8_1m-mve.d 
b/gas/testsuite/gas/arm/v8_1m-mve.d
new file mode 100644
index 
0000000000000000000000000000000000000000..4c528de073fdc2a52c5bfbb77c41bdd0c0bc2161
--- /dev/null
+++ b/gas/testsuite/gas/arm/v8_1m-mve.d
@@ -0,0 +1,27 @@
+# name: V8.1-m FP register instructions enabled by +mve
+# as: -march=armv8.1-m.main+mve
+# objdump: -dr --show-raw-insn -marmv8.1-m.main
+
+.*: +file format .*arm.*
+
+
+Disassembly of section .text:
+
+00000000 <\.text>:
+ *[0-9a-f]+:	ec80 0b08 	vstmia	r0, {d0-d3}
+ *[0-9a-f]+:	ecb7 3b04 	vldmia	r7!, {d3-d4}
+ *[0-9a-f]+:	ecbd 0b06 	vpop	{d0-d2}
+ *[0-9a-f]+:	ed2d 0b06 	vpush	{d0-d2}
+ *[0-9a-f]+:	ecbd 2b08 	vpop	{d2-d5}
+ *[0-9a-f]+:	ed2d 1b0c 	vpush	{d1-d6}
+ *[0-9a-f]+:	fe71 0f4d 	vpst
+ *[0-9a-f]+:	fd00 3e01 	vstrwt\.32	q1, \[q0, #-4\]
+ *[0-9a-f]+:	ed82 2f80 	vstr	FPSCR, \[r2\]
+ *[0-9a-f]+:	ed80 0b00 	vstr	d0, \[r0\]
+ *[0-9a-f]+:	ed90 0b00 	vldr	d0, \[r0\]
+ *[0-9a-f]+:	ed80 0a00 	vstr	s0, \[r0\]
+ *[0-9a-f]+:	ed90 0a00 	vldr	s0, \[r0\]
+ *[0-9a-f]+:	ed81 fb00 	vstr	d15, \[r1\]
+ *[0-9a-f]+:	ed91 fb00 	vldr	d15, \[r1\]
+ *[0-9a-f]+:	edc1 fa00 	vstr	s31, \[r1\]
+ *[0-9a-f]+:	edd1 fa00 	vldr	s31, \[r1\]
diff --git a/gas/testsuite/gas/arm/v8_1m-mve.s 
b/gas/testsuite/gas/arm/v8_1m-mve.s
new file mode 100644
index 
0000000000000000000000000000000000000000..cae1f93c1581c4cfc61191f4e4815a20b50378d1
--- /dev/null
+++ b/gas/testsuite/gas/arm/v8_1m-mve.s
@@ -0,0 +1,24 @@
+.syntax unified
+
+vstmia r0,{d0-d3}
+vldmia    r7!, {d3-d4}
+
+vpop {d0-d2}
+vpush {d0-d2}
+vpop {d2-d5}
+vpush {d1-d6}
+
+vpst
+vstrwt.u32 q1, [q0, #-4]
+
+vstr FPSCR, [r2] @ Accepts offset variant without immediate
+
+vstr d0,[r0]
+vldr d0,[r0]
+vstr s0,[r0]
+vldr s0,[r0]
+
+vstr d15,[r1]
+vldr d15,[r1]
+vstr s31,[r1]
+vldr s31,[r1]


On 11/06/2019 11:33 AM, Mihail Ionescu wrote:
> Hi,
> 
> This patch enables a few instructions for Armv8.1-M MVE. Currently VLDM,
> VSTM, VSTR, VLDR, VPUSH and VPOP are enabled only when the Armv8-M
> Floating-point Extension is enabled.  According to the ARMv8.1-M ARM,
> section A.1.4.2[1], they can be enabled by having "Armv8-M Floating-point
> Extension and/or Armv8.1-M MVE".
> 
> [1]https://developer.arm.com/docs/ddi0553/bh/armv81-m-architecture-reference-manual
> 
> gas/ChangeLog:
> 
> 2019-11-06  Mihail Ionescu  <mihail.ionescu@arm.com>
> 
> 	* config/tc-arm.c (do_vfp_nsyn_push): Move in order to enable it for
> 	both fpu_vfp_ext_v1xd and mve_ext and add call to the aliased vstm
> 	instruction for mve_ext.
> 	(do_vfp_nsyn_pop): Move in order to enable it for both
> 	fpu_vfp_ext_v1xd and mve_ext and add call to the aliased vldm
> 	instruction for mve_ext.
> 	(do_neon_ldm_stm): Add fpu_vfp_ext_v1 and mve_ext checks.
> 	(insns): Enable vldm, vldmia, vldmdb, vstm, vstmia, vstmdb, vpop,
> 	vpush, and fldd, fstd, flds, fsts for arm_ext_v6t2 instead
>   	of fpu_vfp_ext_v1xd.
> 	* gas/testsuite/gas/arm/v8_1m-mve.s: New.
> 	* gas/testsuite/gas/arm/v8_1m-mve.d: New.
> 
> Tested on arm-none-eabi.
> 
> 
> Is it ok for trunk?
> 
> 
> Regards,
> Mihail
> 
> 
> ###############     Attachment also inlined for ease of reply    ###############
> 
> 
> diff --git a/gas/config/tc-arm.c b/gas/config/tc-arm.c
> index d835976353b0c0420886736a871a84619d529f89..1c27bd5f392cd5d133a985025bf347328cf4d920 100644
> --- a/gas/config/tc-arm.c
> +++ b/gas/config/tc-arm.c
> @@ -16442,36 +16442,6 @@ nsyn_insert_sp (void)
>     inst.operands[0].present = 1;
>   }
>   
> -static void
> -do_vfp_nsyn_push (void)
> -{
> -  nsyn_insert_sp ();
> -
> -  constraint (inst.operands[1].imm < 1 || inst.operands[1].imm > 16,
> -	      _("register list must contain at least 1 and at most 16 "
> -		"registers"));
> -
> -  if (inst.operands[1].issingle)
> -    do_vfp_nsyn_opcode ("fstmdbs");
> -  else
> -    do_vfp_nsyn_opcode ("fstmdbd");
> -}
> -
> -static void
> -do_vfp_nsyn_pop (void)
> -{
> -  nsyn_insert_sp ();
> -
> -  constraint (inst.operands[1].imm < 1 || inst.operands[1].imm > 16,
> -	      _("register list must contain at least 1 and at most 16 "
> -		"registers"));
> -
> -  if (inst.operands[1].issingle)
> -    do_vfp_nsyn_opcode ("fldmias");
> -  else
> -    do_vfp_nsyn_opcode ("fldmiad");
> -}
> -
>   /* Fix up Neon data-processing instructions, ORing in the correct bits for
>      ARM mode or Thumb mode and moving the encoded bit 24 to bit 28.  */
>   
> @@ -20469,6 +20439,9 @@ do_neon_tbl_tbx (void)
>   static void
>   do_neon_ldm_stm (void)
>   {
> +  constraint (!ARM_CPU_HAS_FEATURE (cpu_variant, fpu_vfp_ext_v1)
> +	      && !ARM_CPU_HAS_FEATURE (cpu_variant, mve_ext),
> +	      _(BAD_FPU));
>     /* P, U and L bits are part of bitmask.  */
>     int is_dbmode = (inst.instruction & (1 << 24)) != 0;
>     unsigned offsetbits = inst.operands[1].imm * 2;
> @@ -20497,6 +20470,49 @@ do_neon_ldm_stm (void)
>   }
>   
>   static void
> +do_vfp_nsyn_pop (void)
> +{
> +  nsyn_insert_sp ();
> +  if (ARM_CPU_HAS_FEATURE (cpu_variant, mve_ext)) {
> +    return do_vfp_nsyn_opcode ("vldm");
> +  }
> +
> +  constraint (!ARM_CPU_HAS_FEATURE (cpu_variant, fpu_vfp_ext_v1xd),
> +	      _(BAD_FPU));
> +
> +  constraint (inst.operands[1].imm < 1 || inst.operands[1].imm > 16,
> +	      _("register list must contain at least 1 and at most 16 "
> +		"registers"));
> +
> +  if (inst.operands[1].issingle)
> +    do_vfp_nsyn_opcode ("fldmias");
> +  else
> +    do_vfp_nsyn_opcode ("fldmiad");
> +}
> +
> +static void
> +do_vfp_nsyn_push (void)
> +{
> +  nsyn_insert_sp ();
> +  if (ARM_CPU_HAS_FEATURE (cpu_variant, mve_ext)) {
> +    return do_vfp_nsyn_opcode ("vstmdb");
> +  }
> +
> +  constraint (!ARM_CPU_HAS_FEATURE (cpu_variant, fpu_vfp_ext_v1xd),
> +	      _(BAD_FPU));
> +
> +  constraint (inst.operands[1].imm < 1 || inst.operands[1].imm > 16,
> +	      _("register list must contain at least 1 and at most 16 "
> +		"registers"));
> +
> +  if (inst.operands[1].issingle)
> +    do_vfp_nsyn_opcode ("fstmdbs");
> +  else
> +    do_vfp_nsyn_opcode ("fstmdbd");
> +}
> +
> +
> +static void
>   do_neon_ldr_str (void)
>   {
>     int is_ldr = (inst.instruction & (1 << 20)) != 0;
> @@ -20576,7 +20592,8 @@ do_vldr_vstr (void)
>     /* VLDR/VSTR.  */
>     else
>       {
> -      if (!mark_feature_used (&fpu_vfp_ext_v1xd))
> +      if (!mark_feature_used (&fpu_vfp_ext_v1xd)
> +	  && !ARM_CPU_HAS_FEATURE (cpu_variant, mve_ext))
>   	as_bad (_("Instruction not permitted on this architecture"));
>         do_neon_ldr_str ();
>       }
> @@ -24684,6 +24701,10 @@ static const struct asm_opcode insns[] =
>   #define THUMB_VARIANT  & arm_ext_v6t2
>    mcCE(vmrs,	ef00a10, 2, (APSR_RR, RVC),   vmrs),
>    mcCE(vmsr,	ee00a10, 2, (RVC, RR),        vmsr),
> + mcCE(fldd,	d100b00, 2, (RVD, ADDRGLDC),  vfp_dp_ldst),
> + mcCE(fstd,	d000b00, 2, (RVD, ADDRGLDC),  vfp_dp_ldst),
> + mcCE(flds,	d100a00, 2, (RVS, ADDRGLDC),  vfp_sp_ldst),
> + mcCE(fsts,	d000a00, 2, (RVS, ADDRGLDC),  vfp_sp_ldst),
>   #undef THUMB_VARIANT
>   
>     /* Moves and type conversions.  */
> @@ -24698,8 +24719,6 @@ static const struct asm_opcode insns[] =
>    cCE("fmxr",	ee00a10, 2, (RVC, RR),	      rn_rd),
>   
>     /* Memory operations.	 */
> - cCE("flds",	d100a00, 2, (RVS, ADDRGLDC),  vfp_sp_ldst),
> - cCE("fsts",	d000a00, 2, (RVS, ADDRGLDC),  vfp_sp_ldst),
>    cCE("fldmias",	c900a00, 2, (RRnpctw, VRSLST),    vfp_sp_ldstmia),
>    cCE("fldmfds",	c900a00, 2, (RRnpctw, VRSLST),    vfp_sp_ldstmia),
>    cCE("fldmdbs",	d300a00, 2, (RRnpctw, VRSLST),    vfp_sp_ldstmdb),
> @@ -24741,8 +24760,6 @@ static const struct asm_opcode insns[] =
>   
>    /* Double precision load/store are still present on single precision
>       implementations.  */
> - cCE("fldd",	d100b00, 2, (RVD, ADDRGLDC),  vfp_dp_ldst),
> - cCE("fstd",	d000b00, 2, (RVD, ADDRGLDC),  vfp_dp_ldst),
>    cCE("fldmiad",	c900b00, 2, (RRnpctw, VRDLST),    vfp_dp_ldstmia),
>    cCE("fldmfdd",	c900b00, 2, (RRnpctw, VRDLST),    vfp_dp_ldstmia),
>    cCE("fldmdbd",	d300b00, 2, (RRnpctw, VRDLST),    vfp_dp_ldstmdb),
> @@ -24796,6 +24813,19 @@ static const struct asm_opcode insns[] =
>   #undef  ARM_VARIANT
>   #define ARM_VARIANT    & fpu_vfp_ext_v1xd
>   #undef  THUMB_VARIANT
> +#define THUMB_VARIANT  & arm_ext_v6t2
> +
> + NCE(vldm,      c900b00, 2, (RRnpctw, VRSDLST), neon_ldm_stm),
> + NCE(vldmia,    c900b00, 2, (RRnpctw, VRSDLST), neon_ldm_stm),
> + NCE(vldmdb,    d100b00, 2, (RRnpctw, VRSDLST), neon_ldm_stm),
> + NCE(vstm,      c800b00, 2, (RRnpctw, VRSDLST), neon_ldm_stm),
> + NCE(vstmia,    c800b00, 2, (RRnpctw, VRSDLST), neon_ldm_stm),
> + NCE(vstmdb,    d000b00, 2, (RRnpctw, VRSDLST), neon_ldm_stm),
> +
> + NCE(vpop,      0,       1, (VRSDLST),          vfp_nsyn_pop),
> + NCE(vpush,     0,       1, (VRSDLST),          vfp_nsyn_push),
> +
> +#undef  THUMB_VARIANT
>   #define THUMB_VARIANT  & fpu_vfp_ext_v1xd
>   
>     /* These mnemonics are unique to VFP.  */
> @@ -24804,20 +24834,11 @@ static const struct asm_opcode insns[] =
>    nCE(vnmul,     _vnmul,   3, (RVSD, RVSD, RVSD), vfp_nsyn_nmul),
>    nCE(vnmla,     _vnmla,   3, (RVSD, RVSD, RVSD), vfp_nsyn_nmul),
>    nCE(vnmls,     _vnmls,   3, (RVSD, RVSD, RVSD), vfp_nsyn_nmul),
> - NCE(vpush,     0,       1, (VRSDLST),          vfp_nsyn_push),
> - NCE(vpop,      0,       1, (VRSDLST),          vfp_nsyn_pop),
>    NCE(vcvtz,     0,       2, (RVSD, RVSD),       vfp_nsyn_cvtz),
>   
>     /* Mnemonics shared by Neon and VFP.  */
>    nCEF(vmls,     _vmls,    3, (RNSDQ, oRNSDQ, RNSDQ_RNSC), neon_mac_maybe_scalar),
>   
> - NCE(vldm,      c900b00, 2, (RRnpctw, VRSDLST), neon_ldm_stm),
> - NCE(vldmia,    c900b00, 2, (RRnpctw, VRSDLST), neon_ldm_stm),
> - NCE(vldmdb,    d100b00, 2, (RRnpctw, VRSDLST), neon_ldm_stm),
> - NCE(vstm,      c800b00, 2, (RRnpctw, VRSDLST), neon_ldm_stm),
> - NCE(vstmia,    c800b00, 2, (RRnpctw, VRSDLST), neon_ldm_stm),
> - NCE(vstmdb,    d000b00, 2, (RRnpctw, VRSDLST), neon_ldm_stm),
> -
>    mnCEF(vcvt,     _vcvt,   3, (RNSDQMQ, RNSDQMQ, oI32z), neon_cvt),
>    nCEF(vcvtr,    _vcvt,   2, (RNSDQ, RNSDQ), neon_cvtr),
>    MNCEF(vcvtb,	eb20a40, 3, (RVSDMQ, RVSDMQ, oI32b), neon_cvtb),
> diff --git a/gas/testsuite/gas/arm/v8_1m-mve.d b/gas/testsuite/gas/arm/v8_1m-mve.d
> new file mode 100644
> index 0000000000000000000000000000000000000000..4c528de073fdc2a52c5bfbb77c41bdd0c0bc2161
> --- /dev/null
> +++ b/gas/testsuite/gas/arm/v8_1m-mve.d
> @@ -0,0 +1,27 @@
> +# name: V8.1-m FP register instructions enabled by +mve
> +# as: -march=armv8.1-m.main+mve
> +# objdump: -dr --show-raw-insn -marmv8.1-m.main
> +
> +.*: +file format .*arm.*
> +
> +
> +Disassembly of section .text:
> +
> +00000000 <\.text>:
> + *[0-9a-f]+:	ec80 0b08 	vstmia	r0, {d0-d3}
> + *[0-9a-f]+:	ecb7 3b04 	vldmia	r7!, {d3-d4}
> + *[0-9a-f]+:	ecbd 0b06 	vpop	{d0-d2}
> + *[0-9a-f]+:	ed2d 0b06 	vpush	{d0-d2}
> + *[0-9a-f]+:	ecbd 2b08 	vpop	{d2-d5}
> + *[0-9a-f]+:	ed2d 1b0c 	vpush	{d1-d6}
> + *[0-9a-f]+:	fe71 0f4d 	vpst
> + *[0-9a-f]+:	fd00 3e01 	vstrwt\.32	q1, \[q0, #-4\]
> + *[0-9a-f]+:	ed82 2f80 	vstr	FPSCR, \[r2\]
> + *[0-9a-f]+:	ed80 0b00 	vstr	d0, \[r0\]
> + *[0-9a-f]+:	ed90 0b00 	vldr	d0, \[r0\]
> + *[0-9a-f]+:	ed80 0a00 	vstr	s0, \[r0\]
> + *[0-9a-f]+:	ed90 0a00 	vldr	s0, \[r0\]
> + *[0-9a-f]+:	ed81 fb00 	vstr	d15, \[r1\]
> + *[0-9a-f]+:	ed91 fb00 	vldr	d15, \[r1\]
> + *[0-9a-f]+:	edc1 fa00 	vstr	s31, \[r1\]
> + *[0-9a-f]+:	edd1 fa00 	vldr	s31, \[r1\]
> diff --git a/gas/testsuite/gas/arm/v8_1m-mve.s b/gas/testsuite/gas/arm/v8_1m-mve.s
> new file mode 100644
> index 0000000000000000000000000000000000000000..cae1f93c1581c4cfc61191f4e4815a20b50378d1
> --- /dev/null
> +++ b/gas/testsuite/gas/arm/v8_1m-mve.s
> @@ -0,0 +1,24 @@
> +.syntax unified
> +
> +vstmia r0,{d0-d3}
> +vldmia    r7!, {d3-d4}
> +
> +vpop {d0-d2}
> +vpush {d0-d2}
> +vpop {d2-d5}
> +vpush {d1-d6}
> +
> +vpst
> +vstrwt.u32 q1, [q0, #-4]
> +
> +vstr FPSCR, [r2] @ Accepts offset variant without immediate
> +
> +vstr d0,[r0]
> +vldr d0,[r0]
> +vstr s0,[r0]
> +vldr s0,[r0]
> +
> +vstr d15,[r1]
> +vldr d15,[r1]
> +vstr s31,[r1]
> +vldr s31,[r1]
> 
-------------- next part --------------
diff --git a/gas/config/tc-arm.c b/gas/config/tc-arm.c
index 76098e6b1b5cf8c5a7f3a2383dfbe4658cc7b6be..f5bf5802b6a242284ccc21f10adaa8d2a3fb60c1 100644
--- a/gas/config/tc-arm.c
+++ b/gas/config/tc-arm.c
@@ -16440,36 +16440,6 @@ nsyn_insert_sp (void)
   inst.operands[0].present = 1;
 }
 
-static void
-do_vfp_nsyn_push (void)
-{
-  nsyn_insert_sp ();
-
-  constraint (inst.operands[1].imm < 1 || inst.operands[1].imm > 16,
-	      _("register list must contain at least 1 and at most 16 "
-		"registers"));
-
-  if (inst.operands[1].issingle)
-    do_vfp_nsyn_opcode ("fstmdbs");
-  else
-    do_vfp_nsyn_opcode ("fstmdbd");
-}
-
-static void
-do_vfp_nsyn_pop (void)
-{
-  nsyn_insert_sp ();
-
-  constraint (inst.operands[1].imm < 1 || inst.operands[1].imm > 16,
-	      _("register list must contain at least 1 and at most 16 "
-		"registers"));
-
-  if (inst.operands[1].issingle)
-    do_vfp_nsyn_opcode ("fldmias");
-  else
-    do_vfp_nsyn_opcode ("fldmiad");
-}
-
 /* Fix up Neon data-processing instructions, ORing in the correct bits for
    ARM mode or Thumb mode and moving the encoded bit 24 to bit 28.  */
 
@@ -20465,6 +20435,9 @@ do_neon_tbl_tbx (void)
 static void
 do_neon_ldm_stm (void)
 {
+  constraint (!ARM_CPU_HAS_FEATURE (cpu_variant, fpu_vfp_ext_v1xd)
+	      && !ARM_CPU_HAS_FEATURE (cpu_variant, mve_ext),
+	      _(BAD_FPU));
   /* P, U and L bits are part of bitmask.  */
   int is_dbmode = (inst.instruction & (1 << 24)) != 0;
   unsigned offsetbits = inst.operands[1].imm * 2;
@@ -20493,6 +20466,49 @@ do_neon_ldm_stm (void)
 }
 
 static void
+do_vfp_nsyn_pop (void)
+{
+  nsyn_insert_sp ();
+  if (ARM_CPU_HAS_FEATURE (cpu_variant, mve_ext)) {
+    return do_vfp_nsyn_opcode ("vldm");
+  }
+
+  constraint (!ARM_CPU_HAS_FEATURE (cpu_variant, fpu_vfp_ext_v1xd),
+	      _(BAD_FPU));
+
+  constraint (inst.operands[1].imm < 1 || inst.operands[1].imm > 16,
+	      _("register list must contain at least 1 and at most 16 "
+		"registers"));
+
+  if (inst.operands[1].issingle)
+    do_vfp_nsyn_opcode ("fldmias");
+  else
+    do_vfp_nsyn_opcode ("fldmiad");
+}
+
+static void
+do_vfp_nsyn_push (void)
+{
+  nsyn_insert_sp ();
+  if (ARM_CPU_HAS_FEATURE (cpu_variant, mve_ext)) {
+    return do_vfp_nsyn_opcode ("vstmdb");
+  }
+
+  constraint (!ARM_CPU_HAS_FEATURE (cpu_variant, fpu_vfp_ext_v1xd),
+	      _(BAD_FPU));
+
+  constraint (inst.operands[1].imm < 1 || inst.operands[1].imm > 16,
+	      _("register list must contain at least 1 and at most 16 "
+		"registers"));
+
+  if (inst.operands[1].issingle)
+    do_vfp_nsyn_opcode ("fstmdbs");
+  else
+    do_vfp_nsyn_opcode ("fstmdbd");
+}
+
+
+static void
 do_neon_ldr_str (void)
 {
   int is_ldr = (inst.instruction & (1 << 20)) != 0;
@@ -20572,7 +20588,8 @@ do_vldr_vstr (void)
   /* VLDR/VSTR.  */
   else
     {
-      if (!mark_feature_used (&fpu_vfp_ext_v1xd))
+      if (!mark_feature_used (&fpu_vfp_ext_v1xd)
+	  && !ARM_CPU_HAS_FEATURE (cpu_variant, mve_ext))
 	as_bad (_("Instruction not permitted on this architecture"));
       do_neon_ldr_str ();
     }
@@ -24680,6 +24697,10 @@ static const struct asm_opcode insns[] =
 #define THUMB_VARIANT  & arm_ext_v6t2
  mcCE(vmrs,	ef00a10, 2, (APSR_RR, RVC),   vmrs),
  mcCE(vmsr,	ee00a10, 2, (RVC, RR),        vmsr),
+ mcCE(fldd,	d100b00, 2, (RVD, ADDRGLDC),  vfp_dp_ldst),
+ mcCE(fstd,	d000b00, 2, (RVD, ADDRGLDC),  vfp_dp_ldst),
+ mcCE(flds,	d100a00, 2, (RVS, ADDRGLDC),  vfp_sp_ldst),
+ mcCE(fsts,	d000a00, 2, (RVS, ADDRGLDC),  vfp_sp_ldst),
 #undef THUMB_VARIANT
 
   /* Moves and type conversions.  */
@@ -24694,8 +24715,6 @@ static const struct asm_opcode insns[] =
  cCE("fmxr",	ee00a10, 2, (RVC, RR),	      rn_rd),
 
   /* Memory operations.	 */
- cCE("flds",	d100a00, 2, (RVS, ADDRGLDC),  vfp_sp_ldst),
- cCE("fsts",	d000a00, 2, (RVS, ADDRGLDC),  vfp_sp_ldst),
  cCE("fldmias",	c900a00, 2, (RRnpctw, VRSLST),    vfp_sp_ldstmia),
  cCE("fldmfds",	c900a00, 2, (RRnpctw, VRSLST),    vfp_sp_ldstmia),
  cCE("fldmdbs",	d300a00, 2, (RRnpctw, VRSLST),    vfp_sp_ldstmdb),
@@ -24737,8 +24756,6 @@ static const struct asm_opcode insns[] =
 
  /* Double precision load/store are still present on single precision
     implementations.  */
- cCE("fldd",	d100b00, 2, (RVD, ADDRGLDC),  vfp_dp_ldst),
- cCE("fstd",	d000b00, 2, (RVD, ADDRGLDC),  vfp_dp_ldst),
  cCE("fldmiad",	c900b00, 2, (RRnpctw, VRDLST),    vfp_dp_ldstmia),
  cCE("fldmfdd",	c900b00, 2, (RRnpctw, VRDLST),    vfp_dp_ldstmia),
  cCE("fldmdbd",	d300b00, 2, (RRnpctw, VRDLST),    vfp_dp_ldstmdb),
@@ -24792,6 +24809,19 @@ static const struct asm_opcode insns[] =
 #undef  ARM_VARIANT
 #define ARM_VARIANT    & fpu_vfp_ext_v1xd
 #undef  THUMB_VARIANT
+#define THUMB_VARIANT  & arm_ext_v6t2
+
+ NCE(vldm,      c900b00, 2, (RRnpctw, VRSDLST), neon_ldm_stm),
+ NCE(vldmia,    c900b00, 2, (RRnpctw, VRSDLST), neon_ldm_stm),
+ NCE(vldmdb,    d100b00, 2, (RRnpctw, VRSDLST), neon_ldm_stm),
+ NCE(vstm,      c800b00, 2, (RRnpctw, VRSDLST), neon_ldm_stm),
+ NCE(vstmia,    c800b00, 2, (RRnpctw, VRSDLST), neon_ldm_stm),
+ NCE(vstmdb,    d000b00, 2, (RRnpctw, VRSDLST), neon_ldm_stm),
+
+ NCE(vpop,      0,       1, (VRSDLST),          vfp_nsyn_pop),
+ NCE(vpush,     0,       1, (VRSDLST),          vfp_nsyn_push),
+
+#undef  THUMB_VARIANT
 #define THUMB_VARIANT  & fpu_vfp_ext_v1xd
 
   /* These mnemonics are unique to VFP.  */
@@ -24800,20 +24830,11 @@ static const struct asm_opcode insns[] =
  nCE(vnmul,     _vnmul,   3, (RVSD, RVSD, RVSD), vfp_nsyn_nmul),
  nCE(vnmla,     _vnmla,   3, (RVSD, RVSD, RVSD), vfp_nsyn_nmul),
  nCE(vnmls,     _vnmls,   3, (RVSD, RVSD, RVSD), vfp_nsyn_nmul),
- NCE(vpush,     0,       1, (VRSDLST),          vfp_nsyn_push),
- NCE(vpop,      0,       1, (VRSDLST),          vfp_nsyn_pop),
  NCE(vcvtz,     0,       2, (RVSD, RVSD),       vfp_nsyn_cvtz),
 
   /* Mnemonics shared by Neon and VFP.  */
  nCEF(vmls,     _vmls,    3, (RNSDQ, oRNSDQ, RNSDQ_RNSC), neon_mac_maybe_scalar),
 
- NCE(vldm,      c900b00, 2, (RRnpctw, VRSDLST), neon_ldm_stm),
- NCE(vldmia,    c900b00, 2, (RRnpctw, VRSDLST), neon_ldm_stm),
- NCE(vldmdb,    d100b00, 2, (RRnpctw, VRSDLST), neon_ldm_stm),
- NCE(vstm,      c800b00, 2, (RRnpctw, VRSDLST), neon_ldm_stm),
- NCE(vstmia,    c800b00, 2, (RRnpctw, VRSDLST), neon_ldm_stm),
- NCE(vstmdb,    d000b00, 2, (RRnpctw, VRSDLST), neon_ldm_stm),
-
  mnCEF(vcvt,     _vcvt,   3, (RNSDQMQ, RNSDQMQ, oI32z), neon_cvt),
  nCEF(vcvtr,    _vcvt,   2, (RNSDQ, RNSDQ), neon_cvtr),
  MNCEF(vcvtb,	eb20a40, 3, (RVSDMQ, RVSDMQ, oI32b), neon_cvtb),
diff --git a/gas/testsuite/gas/arm/v8_1m-mve.d b/gas/testsuite/gas/arm/v8_1m-mve.d
new file mode 100644
index 0000000000000000000000000000000000000000..4c528de073fdc2a52c5bfbb77c41bdd0c0bc2161
--- /dev/null
+++ b/gas/testsuite/gas/arm/v8_1m-mve.d
@@ -0,0 +1,27 @@
+# name: V8.1-m FP register instructions enabled by +mve
+# as: -march=armv8.1-m.main+mve
+# objdump: -dr --show-raw-insn -marmv8.1-m.main
+
+.*: +file format .*arm.*
+
+
+Disassembly of section .text:
+
+00000000 <\.text>:
+ *[0-9a-f]+:	ec80 0b08 	vstmia	r0, {d0-d3}
+ *[0-9a-f]+:	ecb7 3b04 	vldmia	r7!, {d3-d4}
+ *[0-9a-f]+:	ecbd 0b06 	vpop	{d0-d2}
+ *[0-9a-f]+:	ed2d 0b06 	vpush	{d0-d2}
+ *[0-9a-f]+:	ecbd 2b08 	vpop	{d2-d5}
+ *[0-9a-f]+:	ed2d 1b0c 	vpush	{d1-d6}
+ *[0-9a-f]+:	fe71 0f4d 	vpst
+ *[0-9a-f]+:	fd00 3e01 	vstrwt\.32	q1, \[q0, #-4\]
+ *[0-9a-f]+:	ed82 2f80 	vstr	FPSCR, \[r2\]
+ *[0-9a-f]+:	ed80 0b00 	vstr	d0, \[r0\]
+ *[0-9a-f]+:	ed90 0b00 	vldr	d0, \[r0\]
+ *[0-9a-f]+:	ed80 0a00 	vstr	s0, \[r0\]
+ *[0-9a-f]+:	ed90 0a00 	vldr	s0, \[r0\]
+ *[0-9a-f]+:	ed81 fb00 	vstr	d15, \[r1\]
+ *[0-9a-f]+:	ed91 fb00 	vldr	d15, \[r1\]
+ *[0-9a-f]+:	edc1 fa00 	vstr	s31, \[r1\]
+ *[0-9a-f]+:	edd1 fa00 	vldr	s31, \[r1\]
diff --git a/gas/testsuite/gas/arm/v8_1m-mve.s b/gas/testsuite/gas/arm/v8_1m-mve.s
new file mode 100644
index 0000000000000000000000000000000000000000..cae1f93c1581c4cfc61191f4e4815a20b50378d1
--- /dev/null
+++ b/gas/testsuite/gas/arm/v8_1m-mve.s
@@ -0,0 +1,24 @@
+.syntax unified
+
+vstmia r0,{d0-d3}
+vldmia    r7!, {d3-d4}
+
+vpop {d0-d2}
+vpush {d0-d2}
+vpop {d2-d5}
+vpush {d1-d6}
+
+vpst
+vstrwt.u32 q1, [q0, #-4]
+
+vstr FPSCR, [r2] @ Accepts offset variant without immediate
+
+vstr d0,[r0]
+vldr d0,[r0]
+vstr s0,[r0]
+vldr s0,[r0]
+
+vstr d15,[r1]
+vldr d15,[r1]
+vstr s31,[r1]
+vldr s31,[r1]


More information about the Binutils mailing list