[PATCH 36/57][Arm][GAS] Add support for MVE instructions: wlstp, dlstp, letp and...
authorAndre Vieira <andre.simoesdiasvieira@arm.com>
Thu, 16 May 2019 12:52:51 +0000 (13:52 +0100)
committerAndre Vieira <andre.simoesdiasvieira@arm.com>
Thu, 16 May 2019 15:36:53 +0000 (16:36 +0100)
gas/ChangeLog:
2019-05-16  Andre Vieira  <andre.simoesdiasvieira@arm.com>

* config/tc-arm.c (T16_32_TAB): Add new instructions.
(do_t_loloop): Changed to handle tail predication variants.
(md_apply_fix): Likewise.
(insns): Add entries for MVE mnemonics.
* testsuite/gas/arm/mve-tailpredloop-bad.d: New test.
* testsuite/gas/arm/mve-tailpredloop-bad.l: New test.
* testsuite/gas/arm/mve-tailpredloop-bad.s: New test.
* testsuite/gas/arm/mve-tailpredloop.d: New test.

gas/ChangeLog
gas/config/tc-arm.c
gas/testsuite/gas/arm/mve-tailpredloop-bad.d [new file with mode: 0644]
gas/testsuite/gas/arm/mve-tailpredloop-bad.l [new file with mode: 0644]
gas/testsuite/gas/arm/mve-tailpredloop-bad.s [new file with mode: 0644]

index f7883edf584713f27d9a6d230625d0b1c8b38a1d..e2cab99d797cb2f6971f9c4cd184f43c8206d57c 100644 (file)
@@ -1,3 +1,14 @@
+2019-05-16  Andre Vieira  <andre.simoesdiasvieira@arm.com>
+
+       * config/tc-arm.c (T16_32_TAB): Add new instructions.
+       (do_t_loloop): Changed to handle tail predication variants.
+       (md_apply_fix): Likewise.
+       (insns): Add entries for MVE mnemonics.
+       * testsuite/gas/arm/mve-tailpredloop-bad.d: New test.
+       * testsuite/gas/arm/mve-tailpredloop-bad.l: New test.
+       * testsuite/gas/arm/mve-tailpredloop-bad.s: New test.
+       * testsuite/gas/arm/mve-tailpredloop.d: New test.
+
 2019-05-16  Andre Vieira  <andre.simoesdiasvieira@arm.com>
 
        * config/tc-arm.c (do_mve_vshll): New encoding function.
index ab672c1fdbb03002d66b6989d7971391d0c42ba0..1bc15df1a98184aa139a4bb570c6f5e578bdf3e2 100644 (file)
@@ -11134,9 +11134,11 @@ encode_thumb32_addr_mode (int i, bfd_boolean is_t, bfd_boolean is_d)
   X(_cpy,   4600, ea4f0000),                   \
   X(_dec_sp,80dd, f1ad0d00),                   \
   X(_dls,   0000, f040e001),                   \
+  X(_dlstp, 0000, f000e001),                   \
   X(_eor,   4040, ea800000),                   \
   X(_eors,  4040, ea900000),                   \
   X(_inc_sp,00dd, f10d0d00),                   \
+  X(_lctp,  0000, f00fe001),                   \
   X(_ldmia, c800, e8900000),                   \
   X(_ldr,   6800, f8500000),                   \
   X(_ldrb,  7800, f8100000),                   \
@@ -11147,6 +11149,7 @@ encode_thumb32_addr_mode (int i, bfd_boolean is_t, bfd_boolean is_d)
   X(_ldr_pc2,4800, f85f0000),                  \
   X(_ldr_sp,9800, f85d0000),                   \
   X(_le,    0000, f00fc001),                   \
+  X(_letp,  0000, f01fc001),                   \
   X(_lsl,   0000, fa00f000),                   \
   X(_lsls,  0000, fa10f000),                   \
   X(_lsr,   0800, fa20f000),                   \
@@ -11189,6 +11192,7 @@ encode_thumb32_addr_mode (int i, bfd_boolean is_t, bfd_boolean is_d)
   X(_wfe,   bf20, f3af8002),                   \
   X(_wfi,   bf30, f3af8003),                   \
   X(_wls,   0000, f040c001),                   \
+  X(_wlstp, 0000, f000c001),                   \
   X(_sev,   bf40, f3af8004),                    \
   X(_sevl,  bf50, f3af8005),                   \
   X(_udf,   de00, f7f0a000)
@@ -14114,38 +14118,6 @@ v8_1_loop_reloc (int is_le)
     }
 }
 
-/* To handle the Scalar Low Overhead Loop instructions
-   in Armv8.1-M Mainline.  */
-static void
-do_t_loloop (void)
-{
-  unsigned long insn = inst.instruction;
-
-  set_pred_insn_type (OUTSIDE_PRED_INSN);
-  inst.instruction = THUMB_OP32 (inst.instruction);
-
-  switch (insn)
-    {
-    case T_MNEM_le:
-      /* le <label>.  */
-      if (!inst.operands[0].present)
-       inst.instruction |= 1 << 21;
-
-      v8_1_loop_reloc (TRUE);
-      break;
-
-    case T_MNEM_wls:
-      v8_1_loop_reloc (FALSE);
-      /* Fall through.  */
-    case T_MNEM_dls:
-      constraint (inst.operands[1].isreg != 1, BAD_ARGS);
-      inst.instruction |= (inst.operands[1].reg << 16);
-      break;
-
-    default: abort();
-    }
-}
-
 /* MVE instruction encoder helpers.  */
 #define M_MNEM_vabav   0xee800f01
 #define M_MNEM_vmladav   0xeef00e00
@@ -14444,6 +14416,8 @@ NEON_ENC_TAB
   X(2, (R, S), SINGLE),                        \
   X(2, (F, R), SINGLE),                        \
   X(2, (R, F), SINGLE),                        \
+/* Used for MVE tail predicated loop instructions.  */\
+  X(2, (R, R), QUAD),                  \
 /* Half float shape supported so far.  */\
   X (2, (H, D), MIXED),                        \
   X (2, (D, H), MIXED),                        \
@@ -15985,6 +15959,66 @@ do_mve_vcmul (void)
   inst.is_neon = 1;
 }
 
+/* To handle the Low Overhead Loop instructions
+   in Armv8.1-M Mainline and MVE.  */
+static void
+do_t_loloop (void)
+{
+  unsigned long insn = inst.instruction;
+
+  inst.instruction = THUMB_OP32 (inst.instruction);
+
+  if (insn == T_MNEM_lctp)
+    return;
+
+  set_pred_insn_type (MVE_OUTSIDE_PRED_INSN);
+
+  if (insn == T_MNEM_wlstp || insn == T_MNEM_dlstp)
+    {
+      struct neon_type_el et
+       = neon_check_type (2, NS_RR, N_EQK, N_8 | N_16 | N_32 | N_64 | N_KEY);
+      inst.instruction |= neon_logbits (et.size) << 20;
+      inst.is_neon = 1;
+    }
+
+  switch (insn)
+    {
+    case T_MNEM_letp:
+      constraint (!inst.operands[0].present,
+                 _("expected LR"));
+      /* fall through.  */
+    case T_MNEM_le:
+      /* le <label>.  */
+      if (!inst.operands[0].present)
+       inst.instruction |= 1 << 21;
+
+      v8_1_loop_reloc (TRUE);
+      break;
+
+    case T_MNEM_wls:
+    case T_MNEM_wlstp:
+      v8_1_loop_reloc (FALSE);
+      /* fall through.  */
+    case T_MNEM_dlstp:
+    case T_MNEM_dls:
+      constraint (inst.operands[1].isreg != 1, BAD_ARGS);
+
+      if (insn == T_MNEM_wlstp || insn == T_MNEM_dlstp)
+       constraint (inst.operands[1].reg == REG_PC, BAD_PC);
+      else if (inst.operands[1].reg == REG_PC)
+       as_tsktsk (MVE_BAD_PC);
+      if (inst.operands[1].reg == REG_SP)
+       as_tsktsk (MVE_BAD_SP);
+
+      inst.instruction |= (inst.operands[1].reg << 16);
+      break;
+
+    default:
+      abort ();
+    }
+}
+
+
 static void
 do_vfp_nsyn_cmp (void)
 {
@@ -25240,6 +25274,11 @@ static const struct asm_opcode insns[] =
  mToC("vshllt",            ee201e00,      3, (RMQ, RMQ, I32),      mve_vshll),
  mToC("vshllb",            ee200e00,      3, (RMQ, RMQ, I32),      mve_vshll),
 
+ toU("dlstp",  _dlstp, 2, (LR, RR),      t_loloop),
+ toU("wlstp",  _wlstp, 3, (LR, RR, EXP), t_loloop),
+ toU("letp",   _letp,  2, (LR, EXP),     t_loloop),
+ toU("lctp",   _lctp,  0, (),            t_loloop),
+
 #undef THUMB_VARIANT
 #define THUMB_VARIANT & mve_fp_ext
  mToC("vcmul", ee300e00,   4, (RMQ, RMQ, RMQ, EXPi),             mve_vcmul),
@@ -28641,9 +28680,10 @@ md_apply_fix (fixS *   fixP,
        }
 
       bfd_vma insn = get_thumb32_insn (buf);
-      /* le lr, <label> or le <label> */
+      /* le lr, <label>, le <label> or letp lr, <label> */
       if (((insn & 0xffffffff) == 0xf00fc001)
-         || ((insn & 0xffffffff) == 0xf02fc001))
+         || ((insn & 0xffffffff) == 0xf02fc001)
+         || ((insn & 0xffffffff) == 0xf01fc001))
        value = -value;
 
       if (v8_1_branch_value_check (value, 12, FALSE) == FAIL)
diff --git a/gas/testsuite/gas/arm/mve-tailpredloop-bad.d b/gas/testsuite/gas/arm/mve-tailpredloop-bad.d
new file mode 100644 (file)
index 0000000..53c0abc
--- /dev/null
@@ -0,0 +1,5 @@
+#name: bad MVE WLSTP, DLSTP and LETP instructions
+#as: -march=armv8.1-m.main+mve
+#error_output: mve-tailpredloop-bad.l
+
+.*: +file format .*arm.*
diff --git a/gas/testsuite/gas/arm/mve-tailpredloop-bad.l b/gas/testsuite/gas/arm/mve-tailpredloop-bad.l
new file mode 100644 (file)
index 0000000..5e9209f
--- /dev/null
@@ -0,0 +1,26 @@
+[^:]*: Assembler messages:
+[^:]*:25: Warning: instruction is UNPREDICTABLE in an IT block
+[^:]*:25: Warning: instruction is UNPREDICTABLE in an IT block
+[^:]*:25: Warning: instruction is UNPREDICTABLE in an IT block
+[^:]*:25: Warning: instruction is UNPREDICTABLE in an IT block
+[^:]*:25: Warning: instruction is UNPREDICTABLE in an IT block
+[^:]*:25: Warning: instruction is UNPREDICTABLE in an IT block
+[^:]*:26: Warning: instruction is UNPREDICTABLE in an IT block
+[^:]*:26: Warning: instruction is UNPREDICTABLE in an IT block
+[^:]*:26: Warning: instruction is UNPREDICTABLE in an IT block
+[^:]*:26: Warning: instruction is UNPREDICTABLE in an IT block
+[^:]*:26: Warning: instruction is UNPREDICTABLE in an IT block
+[^:]*:26: Warning: instruction is UNPREDICTABLE in an IT block
+[^:]*:27: Warning: instruction is UNPREDICTABLE in an IT block
+[^:]*:27: Warning: instruction is UNPREDICTABLE in an IT block
+[^:]*:27: Warning: instruction is UNPREDICTABLE in an IT block
+[^:]*:27: Warning: instruction is UNPREDICTABLE in an IT block
+[^:]*:27: Warning: instruction is UNPREDICTABLE in an IT block
+[^:]*:27: Warning: instruction is UNPREDICTABLE in an IT block
+[^:]*:28: Error: r15 not allowed here -- `wlstp.8 lr,pc,.label'
+[^:]*:29: Warning: instruction is UNPREDICTABLE with SP operand
+[^:]*:30: Error: r15 not allowed here -- `dlstp.16 lr,pc'
+[^:]*:31: Warning: instruction is UNPREDICTABLE with SP operand
+[^:]*:33: Error: ARM register expected -- `letp .label_back'
+[^:]*:34: Error: branch out of range or not a multiple of 2
+[^:]*:35: Error: branch out of range or not a multiple of 2
diff --git a/gas/testsuite/gas/arm/mve-tailpredloop-bad.s b/gas/testsuite/gas/arm/mve-tailpredloop-bad.s
new file mode 100644 (file)
index 0000000..929722a
--- /dev/null
@@ -0,0 +1,36 @@
+.macro cond1
+.irp cond, eq, ne, gt, ge, lt, le
+it \cond
+wlstp.8 lr, r0, .label
+.endr
+.endm
+
+.macro cond2
+.irp cond, eq, ne, gt, ge, lt, le
+it \cond
+dlstp.8 lr, r0
+.endr
+.endm
+
+.macro cond3
+.irp cond, eq, ne, gt, ge, lt, le
+it \cond
+letp lr, .label_back
+.endr
+.endm
+
+.label_back:
+.syntax unified
+.thumb
+cond1
+cond2
+cond3
+wlstp.8 lr, pc, .label
+wlstp.8 lr, sp, .label
+dlstp.16 lr, pc
+dlstp.16 lr, sp
+.label:
+letp .label_back
+wlstp.8 lr, r0, .label
+letp lr, .label2
+.label2: