[binutils, ARM, 16/16] Add support to VLDR and VSTR of system registers
authorAndre Vieira <andre.simoesdiasvieira@arm.com>
Mon, 15 Apr 2019 11:23:24 +0000 (12:23 +0100)
committerAndre Vieira <andre.simoesdiasvieira@arm.com>
Mon, 15 Apr 2019 11:32:01 +0000 (12:32 +0100)
GNU as' Arm backend assumes each mnemonic has a single entry in the instruction table but VLDR (system register) and VSTR (system register) are different instructions than VLDR and VSTR. It is thus necessary to add some form of demultiplexing in the parser. It starts by creating a new operand type OP_VLDR which indicate that the operand is either the existing OP_RVSD operand or a system register. The function parse_operands () then tries these two cases in order, calling the new parse_sys_vldr_vstr for the second case.

Since the encoding function is specified in the instruction table entry, it also need to have some sort of demultiplexing. This is done in do_vldr_vstr which either calls the existing do_neon_ldr_str () or calls the new do_t_vldr_vstr_sysreg ().

A new internal relocation is needed as well since the offset has a shorter range than in other Thumb coprocessor instructions. Disassembly also requires special care since VSTR (system register) reuse the STC encoding with the coprocessor number 15. Armv8.1-M Mainline ARM manual states that coprocessor 8, 14 and 15 are reserved for floating-point and MVE instructions a feature bit check is added if the coprocessor number is one of this value and we are trying to match a coprocessor instruction (eg. STC) to forbid the match.

ChangeLog entries are as follows:

*** bfd/ChangeLog ***

2019-04-15  Thomas Preud'homme  <thomas.preudhomme@arm.com>

* reloc.c (BFD_RELOC_ARM_T32_VLDR_VSTR_OFF_IMM): New internal
relocation.
* bfd-in2.h: Regenerate.
* libbfd.h: Likewise.

*** gas/ChangeLog ***

2019-04-15  Thomas Preud'homme  <thomas.preudhomme@arm.com>

* config/tc-arm.c (parse_sys_vldr_vstr): New function.
(OP_VLDR): New enum operand_parse_code enumerator.
(parse_operands): Add logic for OP_VLDR.
(do_t_vldr_vstr_sysreg): New function.
(do_vldr_vstr): Likewise.
(insns): Guard VLDR and VSTR by arm_ext_v4t for Thumb mode.
(md_apply_fix): Add bound check for VLDR and VSTR co-processor offset.
Add masking logic for BFD_RELOC_ARM_T32_VLDR_VSTR_OFF_IMM relocation.
* testsuite/gas/arm/archv8m_1m-cmse-main-bad.s: Add examples of bad
uses of VLDR and VSTR.
* testsuite/gas/arm/archv8m_1m-cmse-main-bad.l: Add error messages for
above bad uses.
* testsuite/gas/arm/archv8m_1m-cmse-main.s: Add examples of VLDR and
VSTR valid uses.
* testsuite/gas/arm/archv8m_1m-cmse-main.d: Add disassembly for the
above examples.

*** opcodes/ChangeLog ***

2019-04-15  Thomas Preud'homme  <thomas.preudhomme@arm.com>

* arm-dis.c (coprocessor_opcodes): Document new %J and %K format
specifier.  Add entries for VLDR and VSTR of system registers.
(print_insn_coprocessor): Forbid coprocessor numbers 8, 14 and 15 in
coprocessor instructions on Armv8.1-M Mainline targets.  Add handling
of %J and %K format specifier.

12 files changed:
bfd/ChangeLog
bfd/bfd-in2.h
bfd/libbfd.h
bfd/reloc.c
gas/ChangeLog
gas/config/tc-arm.c
gas/testsuite/gas/arm/archv8m_1m-cmse-main-bad.l
gas/testsuite/gas/arm/archv8m_1m-cmse-main-bad.s
gas/testsuite/gas/arm/archv8m_1m-cmse-main.d
gas/testsuite/gas/arm/archv8m_1m-cmse-main.s
opcodes/ChangeLog
opcodes/arm-dis.c

index 7876f516895a5de384f01da79dabdd2a82a16d8f..834b84f75f9b4b295c775f7069b2ce68369f062e 100644 (file)
@@ -1,3 +1,10 @@
+2019-04-15  Thomas Preud'homme  <thomas.preudhomme@arm.com>
+
+       * reloc.c (BFD_RELOC_ARM_T32_VLDR_VSTR_OFF_IMM): New internal
+       relocation.
+       * bfd-in2.h: Regenerate.
+       * libbfd.h: Likewise.
+
 2019-04-15  Sudakshina Das  <sudi.das@arm.com>
 
        * reloc.c (BFD_RELOC_ARM_THUMB_LOOP12): New.
index 540b9f71c181841ea782c63d87d0d5271c864966..13af0beade1ee1521be7db8307e5fa2e025594b2 100644 (file)
@@ -3722,6 +3722,7 @@ pc-relative or some form of GOT-indirect relocation.  */
   BFD_RELOC_ARM_CP_OFF_IMM_S2,
   BFD_RELOC_ARM_T32_CP_OFF_IMM,
   BFD_RELOC_ARM_T32_CP_OFF_IMM_S2,
+  BFD_RELOC_ARM_T32_VLDR_VSTR_OFF_IMM,
   BFD_RELOC_ARM_ADR_IMM,
   BFD_RELOC_ARM_LDR_IMM,
   BFD_RELOC_ARM_LITERAL,
index f64a8f3892ad3aff5c4570f0281875bce35846a6..b51df73179fd1d3185f904466fd995f113a22835 100644 (file)
@@ -1634,6 +1634,7 @@ static const char *const bfd_reloc_code_real_names[] = { "@@uninitialized@@",
   "BFD_RELOC_ARM_CP_OFF_IMM_S2",
   "BFD_RELOC_ARM_T32_CP_OFF_IMM",
   "BFD_RELOC_ARM_T32_CP_OFF_IMM_S2",
+  "BFD_RELOC_ARM_T32_VLDR_VSTR_OFF_IMM",
   "BFD_RELOC_ARM_ADR_IMM",
   "BFD_RELOC_ARM_LDR_IMM",
   "BFD_RELOC_ARM_LITERAL",
index e6ba9e265027a6c34a8ad183dd5825a9af9c1f82..9615279833228cff4cb7f4cd77e930b2ad7cf4ab 100644 (file)
@@ -3292,6 +3292,8 @@ ENUMX
   BFD_RELOC_ARM_T32_CP_OFF_IMM
 ENUMX
   BFD_RELOC_ARM_T32_CP_OFF_IMM_S2
+ENUMX
+  BFD_RELOC_ARM_T32_VLDR_VSTR_OFF_IMM
 ENUMX
   BFD_RELOC_ARM_ADR_IMM
 ENUMX
index d669d00b9cfe849a81a84b91da2e765d4da2ff81..7eb172c96bac8416f6f8b226dabae05d94d5e22e 100644 (file)
@@ -1,3 +1,22 @@
+2019-04-15  Thomas Preud'homme  <thomas.preudhomme@arm.com>
+
+       * config/tc-arm.c (parse_sys_vldr_vstr): New function.
+       (OP_VLDR): New enum operand_parse_code enumerator.
+       (parse_operands): Add logic for OP_VLDR.
+       (do_t_vldr_vstr_sysreg): New function.
+       (do_vldr_vstr): Likewise.
+       (insns): Guard VLDR and VSTR by arm_ext_v4t for Thumb mode.
+       (md_apply_fix): Add bound check for VLDR and VSTR co-processor offset.
+       Add masking logic for BFD_RELOC_ARM_T32_VLDR_VSTR_OFF_IMM relocation.
+       * testsuite/gas/arm/archv8m_1m-cmse-main-bad.s: Add examples of bad
+       uses of VLDR and VSTR.
+       * testsuite/gas/arm/archv8m_1m-cmse-main-bad.l: Add error messages for
+       above bad uses.
+       * testsuite/gas/arm/archv8m_1m-cmse-main.s: Add examples of VLDR and
+       VSTR valid uses.
+       * testsuite/gas/arm/archv8m_1m-cmse-main.d: Add disassembly for the
+       above examples.
+
 2019-04-15  Thomas Preud'homme  <thomas.preudhomme@arm.com>
 
        * config/tc-arm.c (arm_typed_reg_parse): Fix typo in comment.
index b5dc3eb212ea414e86c8620160496d8f1ee508b6..20a2dee1aaa1660fbda62d8aa8d9551d929352b5 100644 (file)
@@ -6128,6 +6128,39 @@ check_suffix:
   return FAIL;
 }
 
+static int
+parse_sys_vldr_vstr (char **str)
+{
+  unsigned i;
+  int val = FAIL;
+  struct {
+    const char *name;
+    int regl;
+    int regh;
+  } sysregs[] = {
+    {"FPSCR",          0x1, 0x0},
+    {"FPSCR_nzcvqc",   0x2, 0x0},
+    {"VPR",            0x4, 0x1},
+    {"P0",             0x5, 0x1},
+    {"FPCXTNS",                0x6, 0x1},
+    {"FPCXTS",         0x7, 0x1}
+  };
+  char *op_end = strchr (*str, ',');
+  size_t op_strlen = op_end - *str;
+
+  for (i = 0; i < sizeof (sysregs) / sizeof (sysregs[0]); i++)
+    {
+      if (!strncmp (*str, sysregs[i].name, op_strlen))
+       {
+         val = sysregs[i].regl | (sysregs[i].regh << 3);
+         *str = op_end;
+         break;
+       }
+    }
+
+  return val;
+}
+
 /* Parse the flags argument to CPSI[ED].  Returns FAIL on error, or a
    value suitable for splatting into the AIF field of the instruction. */
 
@@ -6652,6 +6685,7 @@ enum operand_parse_code
   OP_RNDQ_Ibig,        /* Neon D or Q reg, or big immediate for logic and VMVN.  */
   OP_RNDQ_I63b, /* Neon D or Q reg, or immediate for shift.  */
   OP_RIWR_I32z, /* iWMMXt wR register, or immediate 0 .. 32 for iWMMXt2.  */
+  OP_VLDR,     /* VLDR operand.  */
 
   OP_I0,        /* immediate zero */
   OP_I7,       /* immediate value 0 .. 7 */
@@ -7225,6 +7259,13 @@ parse_operands (char *str, const unsigned int *pattern, bfd_boolean thumb)
          val = parse_psr (&str, op_parse_code == OP_wPSR);
          break;
 
+       case OP_VLDR:
+         po_reg_or_goto (REG_TYPE_VFSD, try_sysreg);
+         break;
+       try_sysreg:
+         val = parse_sys_vldr_vstr (&str);
+         break;
+
        case OP_APSR_RR:
          po_reg_or_goto (REG_TYPE_RN, try_apsr);
          break;
@@ -7401,6 +7442,10 @@ parse_operands (char *str, const unsigned int *pattern, bfd_boolean thumb)
            inst.error = BAD_PC;
          break;
 
+       case OP_VLDR:
+         if (inst.operands[i].isreg)
+           break;
+       /* fall through.  */
        case OP_CPSF:
        case OP_ENDI:
        case OP_oROR:
@@ -17397,6 +17442,55 @@ do_neon_ldr_str (void)
     }
 }
 
+static void
+do_t_vldr_vstr_sysreg (void)
+{
+  int fp_vldr_bitno = 20, sysreg_vldr_bitno = 20;
+  bfd_boolean is_vldr = ((inst.instruction & (1 << fp_vldr_bitno)) != 0);
+
+  /* Use of PC is UNPREDICTABLE.  */
+  if (inst.operands[1].reg == REG_PC)
+    inst.error = _("Use of PC here is UNPREDICTABLE");
+
+  if (inst.operands[1].immisreg)
+    inst.error = _("instruction does not accept register index");
+
+  if (!inst.operands[1].isreg)
+    inst.error = _("instruction does not accept PC-relative addressing");
+
+  if (abs (inst.operands[1].imm) >= (1 << 7))
+    inst.error = _("immediate value out of range");
+
+  inst.instruction = 0xec000f80;
+  if (is_vldr)
+    inst.instruction |= 1 << sysreg_vldr_bitno;
+  encode_arm_cp_address (1, TRUE, FALSE, BFD_RELOC_ARM_T32_VLDR_VSTR_OFF_IMM);
+  inst.instruction |= (inst.operands[0].imm & 0x7) << 13;
+  inst.instruction |= (inst.operands[0].imm & 0x8) << 19;
+}
+
+static void
+do_vldr_vstr (void)
+{
+  bfd_boolean sysreg_op = !inst.operands[0].isreg;
+
+  /* VLDR/VSTR (System Register).  */
+  if (sysreg_op)
+    {
+      if (!mark_feature_used (&arm_ext_v8_1m_main))
+       as_bad (_("Instruction not permitted on this architecture"));
+
+      do_t_vldr_vstr_sysreg ();
+    }
+  /* VLDR/VSTR.  */
+  else
+    {
+      if (!mark_feature_used (&fpu_vfp_ext_v1xd))
+       as_bad (_("Instruction not permitted on this architecture"));
+      do_neon_ldr_str ();
+    }
+}
+
 /* "interleave" version also handles non-interleaving register VLD1/VST1
    instructions.  */
 
@@ -21284,8 +21378,6 @@ static const struct asm_opcode insns[] =
  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(vldr,      d100b00, 2, (RVSD, ADDRGLDC), neon_ldr_str),
- NCE(vstr,      d000b00, 2, (RVSD, ADDRGLDC), neon_ldr_str),
 
  nCEF(vcvt,     _vcvt,   3, (RNSDQ, RNSDQ, oI32z), neon_cvt),
  nCEF(vcvtr,    _vcvt,   2, (RNSDQ, RNSDQ), neon_cvtr),
@@ -21297,6 +21389,15 @@ static const struct asm_opcode insns[] =
  NCE(vmov,      0,       1, (VMOV), neon_mov),
  NCE(vmovq,     0,       1, (VMOV), neon_mov),
 
+#undef  THUMB_VARIANT
+/* Could be either VLDR/VSTR or VLDR/VSTR (system register) which are guarded
+   by different feature bits.  Since we are setting the Thumb guard, we can
+   require Thumb-1 which makes it a nop guard and set the right feature bit in
+   do_vldr_vstr ().  */
+#define THUMB_VARIANT  & arm_ext_v4t
+ NCE(vldr,      d100b00, 2, (VLDR, ADDRGLDC), vldr_vstr),
+ NCE(vstr,      d000b00, 2, (VLDR, ADDRGLDC), vldr_vstr),
+
 #undef  ARM_VARIANT
 #define ARM_VARIANT    & arm_ext_fp16
 #undef  THUMB_VARIANT
@@ -24548,6 +24649,7 @@ md_apply_fix (fixS *    fixP,
 
     case BFD_RELOC_ARM_CP_OFF_IMM:
     case BFD_RELOC_ARM_T32_CP_OFF_IMM:
+    case BFD_RELOC_ARM_T32_VLDR_VSTR_OFF_IMM:
       if (fixP->fx_r_type == BFD_RELOC_ARM_CP_OFF_IMM)
        newval = md_chars_to_number (buf, INSN_SIZE);
       else
@@ -24561,6 +24663,12 @@ md_apply_fix (fixS *   fixP,
            as_bad_where (fixP->fx_file, fixP->fx_line,
                          _("co-processor offset out of range"));
        }
+      else if ((newval & 0xfe001f80) == 0xec000f80)
+       {
+         if (value < -511 || value > 512 || (value & 3))
+           as_bad_where (fixP->fx_file, fixP->fx_line,
+                         _("co-processor offset out of range"));
+       }
       else if (value < -1023 || value > 1023 || (value & 3))
        as_bad_where (fixP->fx_file, fixP->fx_line,
                      _("co-processor offset out of range"));
@@ -24574,10 +24682,18 @@ md_apply_fix (fixS *  fixP,
       else
        newval = get_thumb32_insn (buf);
       if (value == 0)
-       newval &= 0xffffff00;
+       {
+         if (fixP->fx_r_type == BFD_RELOC_ARM_T32_VLDR_VSTR_OFF_IMM)
+           newval &= 0xffffff80;
+         else
+           newval &= 0xffffff00;
+       }
       else
        {
-         newval &= 0xff7fff00;
+         if (fixP->fx_r_type == BFD_RELOC_ARM_T32_VLDR_VSTR_OFF_IMM)
+           newval &= 0xff7fff80;
+         else
+           newval &= 0xff7fff00;
          if ((newval & 0x0f200f00) == 0x0d000900)
            {
              /* This is a fp16 vstr/vldr.
index b64937d27f2af469daac5e3feb9167dccde0a986..979982dd9f3bc2059ea059db37dd655c4140b8f5 100644 (file)
@@ -6,3 +6,11 @@
 [^:]*:11: Error: VPR expected last -- `vscclrm {s0}'
 [^:]*:12: Error: VFP single precision register or VPR expected -- `vscclrm {s1,d1,VPR}'
 [^:]*:13: Error: VFP single precision register expected -- `vscclrm {s1-d1,VPR}'
+[^:]*:15: Error: syntax error -- `vldr APSR,\[r2\]'
+[^:]*:20: Error: syntax error -- `vstr APSR,\[r2\]'
+[^:]*:16: Error: co-processor offset out of range
+[^:]*:17: Error: co-processor offset out of range
+[^:]*:18: Error: co-processor offset out of range
+[^:]*:21: Error: co-processor offset out of range
+[^:]*:22: Error: co-processor offset out of range
+[^:]*:23: Error: co-processor offset out of range
index f4baefe73f84a0c93a9ab992b80a9f0b3644d051..894e8b2b8f03cef09bfe33dcf238af68fb07f95d 100644 (file)
@@ -11,3 +11,13 @@ vscclrm {} @ Rejects empty list
 vscclrm {s0} @ Rejects list without VPR
 vscclrm {s1, d1, VPR} @ Reject mix of single and double-precision VFP registers
 vscclrm {s1-d1, VPR} @ Likewise when using a range
+
+vldr APSR, [r2] @ Rejects incorrect system register
+vldr FPSCR, [r2, #2] @ Rejects invalid immediate for offset variant
+vldr FPSCR, [r2, #2]! @ Likewise for pre-index variant
+vldr FPSCR, [r2], #2 @ Likewise for post-index variant
+
+vstr APSR, [r2] @ Rejects incorrect system register
+vstr FPSCR, [r2, #2] @ Rejects invalid immediate for offset variant
+vstr FPSCR, [r2, #2]! @ Likewise for pre-index variant
+vstr FPSCR, [r2], #2 @ Likewise for post-index variant
index 866adc9cb0db7a8c0f6061c3829ac07f3d5233f3..1ed543a04e8602a0c6dfed28c0ec6ae455722af0 100644 (file)
@@ -20,4 +20,38 @@ Disassembly of section .text:
 0+.* <[^>]*> ec9f 0b20         vscclrm {d0-d15, VPR}
 0+.* <[^>]*> bf18              it      ne
 0+.* <[^>]*> ecdf 1a01         vscclrmne       {s3, VPR}
+0+.* <[^>]*> ed92 2f80         vldr    FPSCR, \[r2\]
+0+.* <[^>]*> ed92 2f82         vldr    FPSCR, \[r2, #8\]
+0+.* <[^>]*> ed92 2f82         vldr    FPSCR, \[r2, #8\]
+0+.* <[^>]*> ed12 2f82         vldr    FPSCR, \[r2, #-8\]
+0+.* <[^>]*> edb2 2f82         vldr    FPSCR, \[r2, #8\]!
+0+.* <[^>]*> edb2 2f82         vldr    FPSCR, \[r2, #8\]!
+0+.* <[^>]*> ed32 2f82         vldr    FPSCR, \[r2, #-8\]!
+0+.* <[^>]*> ecb2 2f82         vldr    FPSCR, \[r2\], #8
+0+.* <[^>]*> ecb2 2f82         vldr    FPSCR, \[r2\], #8
+0+.* <[^>]*> ec32 2f82         vldr    FPSCR, \[r2\], #-8
+0+.* <[^>]*> ed93 4f80         vldr    FPSCR_nzcvqc, \[r3\]
+0+.* <[^>]*> edd3 8f80         vldr    VPR, \[r3\]
+0+.* <[^>]*> edd3 af80         vldr    P0, \[r3\]
+0+.* <[^>]*> edd3 cf80         vldr    FPCXTNS, \[r3\]
+0+.* <[^>]*> edd3 ef80         vldr    FPCXTS, \[r3\]
+0+.* <[^>]*> bfa8              it      ge
+0+.* <[^>]*> edd3 ef80         vldrge  FPCXTS, \[r3\]
+0+.* <[^>]*> ed82 2f80         vstr    FPSCR, \[r2\]
+0+.* <[^>]*> ed82 2f82         vstr    FPSCR, \[r2, #8\]
+0+.* <[^>]*> ed82 2f82         vstr    FPSCR, \[r2, #8\]
+0+.* <[^>]*> ed02 2f82         vstr    FPSCR, \[r2, #-8\]
+0+.* <[^>]*> eda2 2f82         vstr    FPSCR, \[r2, #8\]!
+0+.* <[^>]*> eda2 2f82         vstr    FPSCR, \[r2, #8\]!
+0+.* <[^>]*> ed22 2f82         vstr    FPSCR, \[r2, #-8\]!
+0+.* <[^>]*> eca2 2f82         vstr    FPSCR, \[r2\], #8
+0+.* <[^>]*> eca2 2f82         vstr    FPSCR, \[r2\], #8
+0+.* <[^>]*> ec22 2f82         vstr    FPSCR, \[r2\], #-8
+0+.* <[^>]*> ed83 4f80         vstr    FPSCR_nzcvqc, \[r3\]
+0+.* <[^>]*> edc3 8f80         vstr    VPR, \[r3\]
+0+.* <[^>]*> edc3 af80         vstr    P0, \[r3\]
+0+.* <[^>]*> edc3 cf80         vstr    FPCXTNS, \[r3\]
+0+.* <[^>]*> edc3 ef80         vstr    FPCXTS, \[r3\]
+0+.* <[^>]*> bfa8              it      ge
+0+.* <[^>]*> edc3 ef80         vstrge  FPCXTS, \[r3\]
 #...
index f4df2dbb2f7666c4c762a9b62463d809ba91577e..9a20e1e4fe7ab1e497d83da13f288f1efcfc6a0c 100644 (file)
@@ -18,3 +18,37 @@ vscclrm {s0-s31, VPR} @ Accept all single-precision VFP registers and VPR
                      @ together
 vscclrm {d0-d15, VPR} @ Likewise for double-precision VFP registers
 vscclrmne {s3, VPR} @ Accepts conditional execution
+
+vldr FPSCR, [r2] @ Accepts offset variant without immediate
+vldr FPSCR, [r2, #8] @ Likewise but with immediate without sign
+vldr FPSCR, [r2, #+8] @ Likewise but with positive sign
+vldr FPSCR, [r2, #-8] @ Likewise but with negative sign
+vldr FPSCR, [r2, #8]! @ Accepts pre-index variant with immediate without sign
+vldr FPSCR, [r2, #+8]! @ Likewise but with positive sign
+vldr FPSCR, [r2, #-8]! @ Likewise but with negative sign
+vldr FPSCR, [r2], #8 @ Accepts post-index variant with immediate without sign
+vldr FPSCR, [r2], #+8 @ Likewise but with positive sign
+vldr FPSCR, [r2], #-8 @ Likewise but with negative sign
+vldr FPSCR_nzcvqc, [r3] @ Accepts FPSCR_nzcvqc system register
+vldr VPR, [r3] @ Accepts VPR system register
+vldr P0,  [r3] @ Accepts P0 system register
+vldr FPCXTNS, [r3] @ Accepts FPCXTNS system register
+vldr FPCXTS, [r3] @ Accepts FPCXTS system register
+vldrge FPCXTS, [r3] @ Accepts conditional execution
+
+vstr FPSCR, [r2] @ Accepts offset variant without immediate
+vstr FPSCR, [r2, #8] @ Likewise but with immediate without sign
+vstr FPSCR, [r2, #+8] @ Likewise but with positive sign
+vstr FPSCR, [r2, #-8] @ Likewise but with negative sign
+vstr FPSCR, [r2, #8]! @ Accepts pre-index variant with immediate without sign
+vstr FPSCR, [r2, #+8]! @ Likewise but with positive sign
+vstr FPSCR, [r2, #-8]! @ Likewise but with negative sign
+vstr FPSCR, [r2], #8 @ Accepts post-index variant with immediate without sign
+vstr FPSCR, [r2], #+8 @ Likewise but with positive sign
+vstr FPSCR, [r2], #-8 @ Likewise but with negative sign
+vstr FPSCR_nzcvqc, [r3] @ Accepts FPSCR_nzcvqc system register
+vstr VPR, [r3] @ Accepts VPR system register
+vstr P0,  [r3] @ Accepts P0 system register
+vstr FPCXTNS, [r3] @ Accepts FPCXTNS system register
+vstr FPCXTS, [r3] @ Accepts FPCXTS system register
+vstrge FPCXTS, [r3] @ Accepts conditional execution
index 7b330c7d099b9c1735b8f5502b0d57fea68c1eae..05d211b644546dc63ca2601a76cfc7afbe87cb1c 100644 (file)
@@ -1,3 +1,11 @@
+2019-04-15  Thomas Preud'homme  <thomas.preudhomme@arm.com>
+
+       * arm-dis.c (coprocessor_opcodes): Document new %J and %K format
+       specifier.  Add entries for VLDR and VSTR of system registers.
+       (print_insn_coprocessor): Forbid coprocessor numbers 8, 14 and 15 in
+       coprocessor instructions on Armv8.1-M Mainline targets.  Add handling
+       of %J and %K format specifier.
+
 2019-04-15  Thomas Preud'homme  <thomas.preudhomme@arm.com>
 
        * arm-dis.c (coprocessor_opcodes): Document new %C format control code.
index ea053a32fd0a710616981d99814c77911f3f145b..c2a8a5f324b020e0a65bce45a02c46e321c4dd4c 100644 (file)
@@ -111,6 +111,8 @@ struct opcode16
    %B                  print vstm/vldm register list
    %C                  print vscclrm register list
    %I                   print cirrus signed shift immediate: bits 0..3|4..6
+   %J                  print register for VLDR instruction
+   %K                  print address for VLDR instruction
    %F                  print the COUNT field of a LFM/SFM instruction.
    %P                  print floating point precision in arithmetic insn
    %Q                  print floating point precision in ldf/stf insn
@@ -471,6 +473,10 @@ static const struct sopcode32 coprocessor_opcodes[] =
     0x0d000a00, 0x0f300f00, "vstr%c\t%y1, %A"},
   {ANY, ARM_FEATURE_COPROC (FPU_VFP_EXT_V1xD),
     0x0d100a00, 0x0f300f00, "vldr%c\t%y1, %A"},
+  {ANY, ARM_FEATURE_COPROC (ARM_EXT2_V8_1M_MAIN),
+    0xec100f80, 0xfe101f80, "vldr%c\t%J, %K"},
+  {ANY, ARM_FEATURE_COPROC (ARM_EXT2_V8_1M_MAIN),
+    0xec000f80, 0xfe101f80, "vstr%c\t%J, %K"},
 
   {ANY, ARM_FEATURE_COPROC (FPU_VFP_EXT_V1xD),
     0x0d200b01, 0x0fb00f01, "fstmdbx%c\t%16-19r!, %z3\t;@ Deprecated"},
@@ -3462,6 +3468,8 @@ print_insn_coprocessor (bfd_vma pc,
   int cp_num;
   struct arm_private_data *private_data = info->private_data;
   arm_feature_set allowed_arches = ARM_ARCH_NONE;
+  arm_feature_set arm_ext_v8_1m_main =
+    ARM_FEATURE_CORE_HIGH (ARM_EXT2_V8_1M_MAIN);
 
   allowed_arches = private_data->features;
 
@@ -3557,23 +3565,34 @@ print_insn_coprocessor (bfd_vma pc,
          /* Floating-point instructions.  */
          if (cp_num == 9 || cp_num == 10 || cp_num == 11)
            continue;
+
+         /* Armv8.1-M Mainline FP & MVE instructions.  */
+         if (ARM_CPU_HAS_FEATURE (arm_ext_v8_1m_main, allowed_arches)
+             && !ARM_CPU_IS_ANY (allowed_arches)
+             && (cp_num == 8 || cp_num == 14 || cp_num == 15))
+           continue;
        }
 
       for (c = insn->assembler; *c; c++)
        {
          if (*c == '%')
            {
-             switch (*++c)
+             const char mod = *++c;
+             switch (mod)
                {
                case '%':
                  func (stream, "%%");
                  break;
 
                case 'A':
+               case 'K':
                  {
                    int rn = (given >> 16) & 0xf;
                    bfd_vma offset = given & 0xff;
 
+                   if (mod == 'K')
+                     offset = given & 0x7f;
+
                    func (stream, "[%s", arm_regnames [(given >> 16) & 0xf]);
 
                    if (PRE_BIT_SET || WRITEBACK_BIT_SET)
@@ -3705,6 +3724,37 @@ print_insn_coprocessor (bfd_vma pc,
 
                  break;
 
+               case 'J':
+                 {
+                   int regno = ((given >> 19) & 0x8) | ((given >> 13) & 0x7);
+
+                   switch (regno)
+                     {
+                     case 0x1:
+                       func (stream, "FPSCR");
+                       break;
+                     case 0x2:
+                       func (stream, "FPSCR_nzcvqc");
+                       break;
+                     case 0xc:
+                       func (stream, "VPR");
+                       break;
+                     case 0xd:
+                       func (stream, "P0");
+                       break;
+                     case 0xe:
+                       func (stream, "FPCXTNS");
+                       break;
+                     case 0xf:
+                       func (stream, "FPCXTS");
+                       break;
+                     default:
+                       func (stream, "<invalid reg %d>", regno);
+                       break;
+                     }
+                 }
+                 break;
+
                case 'F':
                  switch (given & 0x00408000)
                    {