Implement Read/Write constraints on system registers on AArch64
authorTamar Christina <tamar.christina@arm.com>
Tue, 15 May 2018 15:37:20 +0000 (16:37 +0100)
committerTamar Christina <tamar.christina@arm.com>
Tue, 15 May 2018 16:17:36 +0000 (17:17 +0100)
This patch adds constraints for read and write only system registers with the
msr and mrs instructions.  The code will treat having both flags set and none
set as the same.  These flags add constraints that must be matched up. e.g. a
system register with a READ only flag set, can only be used with mrs.  If The
constraint fails a warning is emitted.

Examples of the warnings generated:

test.s: Assembler messages:
test.s:5: Warning: specified register cannot be written to at operand 1 -- `msr dbgdtrrx_el0,x3'
test.s:7: Warning: specified register cannot be read from at operand 2 -- `mrs x3,dbgdtrtx_el0'
test.s:8: Warning: specified register cannot be written to at operand 1 -- `msr midr_el1,x3'

and disassembly notes:

0000000000000000 <main>:
   0: d5130503  msr dbgdtrtx_el0, x3
   4: d5130503  msr dbgdtrtx_el0, x3
   8: d5330503  mrs x3, dbgdtrrx_el0
   c: d5330503  mrs x3, dbgdtrrx_el0
  10: d5180003  msr midr_el1, x3 ; note: writing to a read-only register.

Note that because dbgdtrrx_el0 and dbgdtrtx_el0 have the same encoding, during
disassembly the constraints are use to disambiguate between the two.  An exact
constraint match is always prefered over partial ones if available.

As always the warnings can be suppressed with -w and also be made errors using
warnings as errors.

binutils/

PR binutils/21446
* doc/binutils.texi (-M): Document AArch64 options.

gas/

PR binutils/21446
* testsuite/gas/aarch64/illegal-sysreg-2.s: Fix pmbidr_el1 test.
* testsuite/gas/aarch64/illegal-sysreg-2.l: Likewise.
* testsuite/gas/aarch64/illegal-sysreg-2.d: Likewise.
* testsuite/gas/aarch64/sysreg-diagnostic.s: New.
* testsuite/gas/aarch64/sysreg-diagnostic.l: New.
* testsuite/gas/aarch64/sysreg-diagnostic.d: New.

include/

PR binutils/21446
* opcode/aarch64.h (F_SYS_READ, F_SYS_WRITE): New.

opcodes/

PR binutils/21446
* aarch64-asm.c (opintl.h): Include.
(aarch64_ins_sysreg): Enforce read/write constraints.
* aarch64-dis.c (aarch64_ext_sysreg): Likewise.
* aarch64-opc.h (F_DEPRECATED, F_ARCHEXT, F_HASXT): Moved here.
(F_REG_READ, F_REG_WRITE): New.
* aarch64-opc.c (aarch64_print_operand): Generate notes for
AARCH64_OPND_SYSREG.
(F_DEPRECATED, F_ARCHEXT, F_HASXT): Move to aarch64-opc.h.
(aarch64_sys_regs): Add constraints to currentel, midr_el1, ctr_el0,
mpidr_el1, revidr_el1, aidr_el1, dczid_el0, id_dfr0_el1, id_pfr0_el1,
id_pfr1_el1, id_afr0_el1, id_mmfr0_el1, id_mmfr1_el1, id_mmfr2_el1,
id_mmfr3_el1, id_mmfr4_el1, id_isar0_el1, id_isar1_el1, id_isar2_el1,
id_isar3_el1, id_isar4_el1, id_isar5_el1, mvfr0_el1, mvfr1_el1,
mvfr2_el1, ccsidr_el1, id_aa64pfr0_el1, id_aa64pfr1_el1,
id_aa64dfr0_el1, id_aa64dfr1_el1, id_aa64isar0_el1, id_aa64isar1_el1,
id_aa64mmfr0_el1, id_aa64mmfr1_el1, id_aa64mmfr2_el1, id_aa64afr0_el1,
id_aa64afr0_el1, id_aa64afr1_el1, id_aa64zfr0_el1, clidr_el1,
csselr_el1, vsesr_el2, erridr_el1, erxfr_el1, rvbar_el1, rvbar_el2,
rvbar_el3, isr_el1, tpidrro_el0, cntfrq_el0, cntpct_el0, cntvct_el0,
mdccsr_el0, dbgdtrrx_el0, dbgdtrtx_el0, osdtrrx_el1, osdtrtx_el1,
mdrar_el1, oslar_el1, oslsr_el1, dbgauthstatus_el1, pmbidr_el1,
pmsidr_el1, pmswinc_el0, pmceid0_el0, pmceid1_el0.
* aarch64-tbl.h (aarch64_opcode_table): Add constraints to
msr (F_SYS_WRITE), mrs (F_SYS_READ).

16 files changed:
binutils/ChangeLog
gas/ChangeLog
gas/testsuite/gas/aarch64/illegal-sysreg-2.l
gas/testsuite/gas/aarch64/sysreg-2.d
gas/testsuite/gas/aarch64/sysreg-2.s
gas/testsuite/gas/aarch64/sysreg-diagnostic.d [new file with mode: 0644]
gas/testsuite/gas/aarch64/sysreg-diagnostic.l [new file with mode: 0644]
gas/testsuite/gas/aarch64/sysreg-diagnostic.s [new file with mode: 0644]
include/ChangeLog
include/opcode/aarch64.h
opcodes/ChangeLog
opcodes/aarch64-asm.c
opcodes/aarch64-dis.c
opcodes/aarch64-opc.c
opcodes/aarch64-opc.h
opcodes/aarch64-tbl.h

index 8f139a5ecaa09fe41b43ac4c52351882597c8a41..3d90103aba02c42a2835879214ba296de5bfd58c 100644 (file)
@@ -1,3 +1,8 @@
+2018-05-15  Tamar Christina  <tamar.christina@arm.com>
+
+       PR binutils/21446
+       * doc/binutils.texi (-M): Document AArch64 options.
+
 2018-05-15  Tamar Christina  <tamar.christina@arm.com>
 
        PR binutils/21446
index 84bba4b0da3e64ae20f81996e14fe1609293614c..a89ffe16db5327854244e17d253e93b983e8445a 100644 (file)
@@ -1,3 +1,13 @@
+2018-05-15  Tamar Christina  <tamar.christina@arm.com>
+
+       PR binutils/21446
+       * testsuite/gas/aarch64/illegal-sysreg-2.s: Fix pmbidr_el1 test.
+       * testsuite/gas/aarch64/illegal-sysreg-2.l: Likewise.
+       * testsuite/gas/aarch64/illegal-sysreg-2.d: Likewise.
+       * testsuite/gas/aarch64/sysreg-diagnostic.s: New.
+       * testsuite/gas/aarch64/sysreg-diagnostic.l: New.
+       * testsuite/gas/aarch64/sysreg-diagnostic.d: New.
+
 2018-05-15  Tamar Christina  <tamar.christina@arm.com>
 
        PR binutils/21446
index f05961120bdb13a18541ababada669925e8b1ca6..120405660305c1994b0cd1e1221c8d9351e57087 100644 (file)
@@ -27,8 +27,6 @@
 [^:]*:[0-9]+: Error: selected processor does not support system register name 'pmbptr_el1'
 [^:]*:[0-9]+: Error: selected processor does not support system register name 'pmbsr_el1'
 [^:]*:[0-9]+: Error: selected processor does not support system register name 'pmbsr_el1'
-[^:]*:[0-9]+: Error: selected processor does not support system register name 'pmbidr_el1'
-[^:]*:[0-9]+: Error: selected processor does not support system register name 'pmbidr_el1'
 [^:]*:[0-9]+: Error: selected processor does not support system register name 'pmscr_el1'
 [^:]*:[0-9]+: Error: selected processor does not support system register name 'pmscr_el1'
 [^:]*:[0-9]+: Error: selected processor does not support system register name 'pmsicr_el1'
index a0539db148925a55653e2c9cc63ff14804d628ea..097f27292739b810e7b6840d096e3fad9901f1cd 100644 (file)
@@ -38,8 +38,6 @@ Disassembly of section .text:
   [0-9a-f]+:   d5389a27        mrs     x7, pmbptr_el1
   [0-9a-f]+:   d5189a67        msr     pmbsr_el1, x7
   [0-9a-f]+:   d5389a67        mrs     x7, pmbsr_el1
-  [0-9a-f]+:   d5189ae7        msr     pmbidr_el1, x7
-  [0-9a-f]+:   d5389ae7        mrs     x7, pmbidr_el1
   [0-9a-f]+:   d5189907        msr     pmscr_el1, x7
   [0-9a-f]+:   d5389907        mrs     x7, pmscr_el1
   [0-9a-f]+:   d5189947        msr     pmsicr_el1, x7
index 2f6ea7066e2bbf307dda7bccda29c5dbfd0b236f..57eb08f33521076314260b68f3e322280d9ff93b 100644 (file)
@@ -44,7 +44,7 @@
 
        /* Statistical profiling.  */
 
-       .irp reg, pmblimitr_el1, pmbptr_el1, pmbsr_el1 pmbidr_el1
+       .irp reg, pmblimitr_el1, pmbptr_el1, pmbsr_el1
        rw_sys_reg sys_reg=\reg xreg=x7 r=1 w=1
        .endr
 
diff --git a/gas/testsuite/gas/aarch64/sysreg-diagnostic.d b/gas/testsuite/gas/aarch64/sysreg-diagnostic.d
new file mode 100644 (file)
index 0000000..2f52f36
--- /dev/null
@@ -0,0 +1,14 @@
+#objdump: -dr -M notes
+#as: -march=armv8-a
+#error-output: sysreg-diagnostic.l
+
+.*:     file format .*
+
+Disassembly of section \.text:
+
+.* <.*>:
+.*:    d5130503        msr     dbgdtrtx_el0, x3
+.*:    d5130503        msr     dbgdtrtx_el0, x3
+.*:    d5330503        mrs     x3, dbgdtrrx_el0
+.*:    d5330503        mrs     x3, dbgdtrrx_el0
+.*:    d5180003        msr     midr_el1, x3    ; note: writing to a read-only register\.
diff --git a/gas/testsuite/gas/aarch64/sysreg-diagnostic.l b/gas/testsuite/gas/aarch64/sysreg-diagnostic.l
new file mode 100644 (file)
index 0000000..4566652
--- /dev/null
@@ -0,0 +1,4 @@
+.*: Assembler messages:
+.*:3: Warning: specified register cannot be written to at operand 1 -- `msr dbgdtrrx_el0,x3'
+.*:5: Warning: specified register cannot be read from at operand 2 -- `mrs x3,dbgdtrtx_el0'
+.*:6: Warning: specified register cannot be written to at operand 1 -- `msr midr_el1,x3'
diff --git a/gas/testsuite/gas/aarch64/sysreg-diagnostic.s b/gas/testsuite/gas/aarch64/sysreg-diagnostic.s
new file mode 100644 (file)
index 0000000..5f68fe6
--- /dev/null
@@ -0,0 +1,6 @@
+.text
+       msr     dbgdtrtx_el0, x3
+       msr     dbgdtrrx_el0, x3
+       mrs     x3, dbgdtrrx_el0
+       mrs     x3, dbgdtrtx_el0
+       msr     midr_el1, x3
index f9868a2ef6c997a4e96edc63e93c1de98d60f15d..fe9cad661430982df9cd732b6362f36f160e21eb 100644 (file)
@@ -1,3 +1,8 @@
+2018-05-15  Tamar Christina  <tamar.christina@arm.com>
+
+       PR binutils/21446
+       * opcode/aarch64.h (F_SYS_READ, F_SYS_WRITE): New.
+
 2018-05-15  Tamar Christina  <tamar.christina@arm.com>
 
        PR binutils/21446
index 1c0013e70629a0154a77337f7c20fe9de845ebc8..dc16fe4a02a6de5721f84ee1f556bd488ac8517b 100644 (file)
@@ -765,7 +765,11 @@ extern aarch64_opcode aarch64_opcode_table[];
 #define F_LSE_SZ (1 << 27)
 /* Require an exact qualifier match, even for NIL qualifiers.  */
 #define F_STRICT (1ULL << 28)
-/* Next bit is 29.  */
+/* This system instruction is used to read system registers.  */
+#define F_SYS_READ (1ULL << 29)
+/* This system instruction is used to write system registers.  */
+#define F_SYS_WRITE (1ULL << 30)
+/* Next bit is 31.  */
 
 static inline bfd_boolean
 alias_opcode_p (const aarch64_opcode *opcode)
index a9656a355a5146e2432f68491c3fefa379e2b537..6baa67ed036caad9c46302f04630f836bdf9f2f1 100644 (file)
@@ -1,3 +1,31 @@
+2018-05-15  Tamar Christina  <tamar.christina@arm.com>
+
+       PR binutils/21446
+       * aarch64-asm.c (opintl.h): Include.
+       (aarch64_ins_sysreg): Enforce read/write constraints.
+       * aarch64-dis.c (aarch64_ext_sysreg): Likewise.
+       * aarch64-opc.h (F_DEPRECATED, F_ARCHEXT, F_HASXT): Moved here.
+       (F_REG_READ, F_REG_WRITE): New.
+       * aarch64-opc.c (aarch64_print_operand): Generate notes for
+       AARCH64_OPND_SYSREG.
+       (F_DEPRECATED, F_ARCHEXT, F_HASXT): Move to aarch64-opc.h.
+       (aarch64_sys_regs): Add constraints to currentel, midr_el1, ctr_el0,
+       mpidr_el1, revidr_el1, aidr_el1, dczid_el0, id_dfr0_el1, id_pfr0_el1,
+       id_pfr1_el1, id_afr0_el1, id_mmfr0_el1, id_mmfr1_el1, id_mmfr2_el1,
+       id_mmfr3_el1, id_mmfr4_el1, id_isar0_el1, id_isar1_el1, id_isar2_el1,
+       id_isar3_el1, id_isar4_el1, id_isar5_el1, mvfr0_el1, mvfr1_el1,
+       mvfr2_el1, ccsidr_el1, id_aa64pfr0_el1, id_aa64pfr1_el1,
+       id_aa64dfr0_el1, id_aa64dfr1_el1, id_aa64isar0_el1, id_aa64isar1_el1,
+       id_aa64mmfr0_el1, id_aa64mmfr1_el1, id_aa64mmfr2_el1, id_aa64afr0_el1,
+       id_aa64afr0_el1, id_aa64afr1_el1, id_aa64zfr0_el1, clidr_el1,
+       csselr_el1, vsesr_el2, erridr_el1, erxfr_el1, rvbar_el1, rvbar_el2,
+       rvbar_el3, isr_el1, tpidrro_el0, cntfrq_el0, cntpct_el0, cntvct_el0,
+       mdccsr_el0, dbgdtrrx_el0, dbgdtrtx_el0, osdtrrx_el1, osdtrtx_el1,
+       mdrar_el1, oslar_el1, oslsr_el1, dbgauthstatus_el1, pmbidr_el1,
+       pmsidr_el1, pmswinc_el0, pmceid0_el0, pmceid1_el0.
+       * aarch64-tbl.h (aarch64_opcode_table): Add constraints to
+       msr (F_SYS_WRITE), mrs (F_SYS_READ).
+
 2018-05-15  Tamar Christina  <tamar.christina@arm.com>
 
        PR binutils/21446
index 67c9b6e5d904b5c7adfa14276837fd2c4a5a09d7..06d428bf193d0720770f6324bfc92c54416321ee 100644 (file)
@@ -22,6 +22,7 @@
 #include <stdarg.h>
 #include "libiberty.h"
 #include "aarch64-asm.h"
+#include "opintl.h"
 
 /* Utilities.  */
 
@@ -785,6 +786,36 @@ aarch64_ins_sysreg (const aarch64_operand *self ATTRIBUTE_UNUSED,
                    const aarch64_inst *inst,
                    aarch64_operand_error *detail ATTRIBUTE_UNUSED)
 {
+   /* If a system instruction check if we have any restrictions on which
+      registers it can use.  */
+   if (inst->opcode->iclass == ic_system)
+     {
+        uint64_t opcode_flags
+         = inst->opcode->flags & (F_SYS_READ | F_SYS_WRITE);
+       uint32_t sysreg_flags
+         = info->sysreg.flags & (F_REG_READ | F_REG_WRITE);
+
+        /* Check to see if it's read-only, else check if it's write only.
+          if it's both or unspecified don't care.  */
+       if (opcode_flags == F_SYS_READ
+           && sysreg_flags
+           && sysreg_flags != F_REG_READ)
+         {
+               detail->kind = AARCH64_OPDE_SYNTAX_ERROR;
+               detail->error = _("specified register cannot be read from");
+               detail->index = info->idx;
+               detail->non_fatal = TRUE;
+         }
+       else if (opcode_flags == F_SYS_WRITE
+                && sysreg_flags
+                && sysreg_flags != F_REG_WRITE)
+         {
+               detail->kind = AARCH64_OPDE_SYNTAX_ERROR;
+               detail->error = _("specified register cannot be written to");
+               detail->index = info->idx;
+               detail->non_fatal = TRUE;
+         }
+     }
   /* op0:op1:CRn:CRm:op2 */
   insert_fields (code, info->sysreg.value, inst->opcode->mask, 5,
                 FLD_op2, FLD_CRm, FLD_CRn, FLD_op1, FLD_op0);
index ae53e49201a2aad5285ca9c44a01eafb8c950380..b9c15594c01030edc0493c69c5bfcb00fc134507 100644 (file)
@@ -1179,7 +1179,22 @@ aarch64_ext_sysreg (const aarch64_operand *self ATTRIBUTE_UNUSED,
   /* op0:op1:CRn:CRm:op2 */
   info->sysreg.value = extract_fields (code, 0, 5, FLD_op0, FLD_op1, FLD_CRn,
                                       FLD_CRm, FLD_op2);
-  return 1;
+  info->sysreg.flags = 0;
+
+  /* If a system instruction, check which restrictions should be on the register
+     value during decoding, these will be enforced then.  */
+  if (inst->opcode->iclass == ic_system)
+    {
+      /* Check to see if it's read-only, else check if it's write only.
+        if it's both or unspecified don't care.  */
+      if ((inst->opcode->flags & (F_SYS_READ | F_SYS_WRITE)) == F_SYS_READ)
+       info->sysreg.flags = F_REG_READ;
+      else if ((inst->opcode->flags & (F_SYS_READ | F_SYS_WRITE))
+              == F_SYS_WRITE)
+       info->sysreg.flags = F_REG_WRITE;
+    }
+
+  return TRUE;
 }
 
 /* Decode the PSTATE field operand for e.g. MSR <pstatefield>, #<imm>.  */
index 9d7f941184594131feec5abca8d7ffbec0b1f793..365cf15ce9f037fc09820f9425515628bf96b91b 100644 (file)
@@ -3556,11 +3556,38 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
 
     case AARCH64_OPND_SYSREG:
       for (i = 0; aarch64_sys_regs[i].name; ++i)
-       if (aarch64_sys_regs[i].value == opnd->sysreg.value
-           && ! aarch64_sys_reg_deprecated_p (&aarch64_sys_regs[i]))
-         break;
-      if (aarch64_sys_regs[i].name)
-       snprintf (buf, size, "%s", aarch64_sys_regs[i].name);
+       {
+         bfd_boolean exact_match
+           = (aarch64_sys_regs[i].flags & opnd->sysreg.flags)
+              == opnd->sysreg.flags;
+
+         /* Try and find an exact match, But if that fails, return the first
+            partial match that was found.  */
+         if (aarch64_sys_regs[i].value == opnd->sysreg.value
+             && ! aarch64_sys_reg_deprecated_p (&aarch64_sys_regs[i])
+             && (name == NULL || exact_match))
+           {
+             name = aarch64_sys_regs[i].name;
+             if (exact_match)
+               {
+                 if (notes)
+                   *notes = NULL;
+                 break;
+               }
+
+             /* If we didn't match exactly, that means the presense of a flag
+                indicates what we didn't want for this instruction.  e.g. If
+                F_REG_READ is there, that means we were looking for a write
+                register.  See aarch64_ext_sysreg.  */
+             if (aarch64_sys_regs[i].flags & F_REG_WRITE)
+               *notes = _("reading from a write-only register.");
+             else if (aarch64_sys_regs[i].flags & F_REG_READ)
+               *notes = _("writing to a read-only register.");
+           }
+       }
+
+      if (name)
+       snprintf (buf, size, "%s", name);
       else
        {
          /* Implementation defined system register.  */
@@ -3638,26 +3665,8 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
 #define C14 14
 #define C15 15
 
-#ifdef F_DEPRECATED
-#undef F_DEPRECATED
-#endif
-#define F_DEPRECATED   0x1     /* Deprecated system register.  */
-
-#ifdef F_ARCHEXT
-#undef F_ARCHEXT
-#endif
-#define F_ARCHEXT      0x2     /* Architecture dependent system register.  */
-
-#ifdef F_HASXT
-#undef F_HASXT
-#endif
-#define F_HASXT                0x4     /* System instruction register <Xt>
-                                  operand.  */
-
-
-/* TODO there are two more issues need to be resolved
-   1. handle read-only and write-only system registers
-   2. handle cpu-implementation-defined system registers.  */
+/* TODO there is one more issues need to be resolved
+   1. handle cpu-implementation-defined system registers.  */
 const aarch64_sys_reg aarch64_sys_regs [] =
 {
   { "spsr_el1",         CPEN_(0,C0,0), 0 }, /* = spsr_svc */
@@ -3667,7 +3676,7 @@ const aarch64_sys_reg aarch64_sys_regs [] =
   { "sp_el0",           CPEN_(0,C1,0), 0 },
   { "spsel",            CPEN_(0,C2,0), 0 },
   { "daif",             CPEN_(3,C2,1), 0 },
-  { "currentel",        CPEN_(0,C2,2), 0 }, /* RO */
+  { "currentel",        CPEN_(0,C2,2), F_REG_READ }, /* RO */
   { "pan",             CPEN_(0,C2,3),  F_ARCHEXT },
   { "uao",             CPEN_ (0, C2, 4), F_ARCHEXT },
   { "nzcv",             CPEN_(3,C2,0), 0 },
@@ -3687,45 +3696,45 @@ const aarch64_sys_reg aarch64_sys_regs [] =
   { "sp_el2",           CPEN_(6,C1,0), 0 },
   { "spsr_svc",         CPEN_(0,C0,0), F_DEPRECATED }, /* = spsr_el1 */
   { "spsr_hyp",         CPEN_(4,C0,0), F_DEPRECATED }, /* = spsr_el2 */
-  { "midr_el1",         CPENC(3,0,C0,C0,0),    0 }, /* RO */
-  { "ctr_el0",          CPENC(3,3,C0,C0,1),    0 }, /* RO */
-  { "mpidr_el1",        CPENC(3,0,C0,C0,5),    0 }, /* RO */
-  { "revidr_el1",       CPENC(3,0,C0,C0,6),    0 }, /* RO */
-  { "aidr_el1",         CPENC(3,1,C0,C0,7),    0 }, /* RO */
-  { "dczid_el0",        CPENC(3,3,C0,C0,7),    0 }, /* RO */
-  { "id_dfr0_el1",      CPENC(3,0,C0,C1,2),    0 }, /* RO */
-  { "id_pfr0_el1",      CPENC(3,0,C0,C1,0),    0 }, /* RO */
-  { "id_pfr1_el1",      CPENC(3,0,C0,C1,1),    0 }, /* RO */
-  { "id_afr0_el1",      CPENC(3,0,C0,C1,3),    0 }, /* RO */
-  { "id_mmfr0_el1",     CPENC(3,0,C0,C1,4),    0 }, /* RO */
-  { "id_mmfr1_el1",     CPENC(3,0,C0,C1,5),    0 }, /* RO */
-  { "id_mmfr2_el1",     CPENC(3,0,C0,C1,6),    0 }, /* RO */
-  { "id_mmfr3_el1",     CPENC(3,0,C0,C1,7),    0 }, /* RO */
-  { "id_mmfr4_el1",     CPENC(3,0,C0,C2,6),    0 }, /* RO */
-  { "id_isar0_el1",     CPENC(3,0,C0,C2,0),    0 }, /* RO */
-  { "id_isar1_el1",     CPENC(3,0,C0,C2,1),    0 }, /* RO */
-  { "id_isar2_el1",     CPENC(3,0,C0,C2,2),    0 }, /* RO */
-  { "id_isar3_el1",     CPENC(3,0,C0,C2,3),    0 }, /* RO */
-  { "id_isar4_el1",     CPENC(3,0,C0,C2,4),    0 }, /* RO */
-  { "id_isar5_el1",     CPENC(3,0,C0,C2,5),    0 }, /* RO */
-  { "mvfr0_el1",        CPENC(3,0,C0,C3,0),    0 }, /* RO */
-  { "mvfr1_el1",        CPENC(3,0,C0,C3,1),    0 }, /* RO */
-  { "mvfr2_el1",        CPENC(3,0,C0,C3,2),    0 }, /* RO */
-  { "ccsidr_el1",       CPENC(3,1,C0,C0,0),    0 }, /* RO */
-  { "id_aa64pfr0_el1",  CPENC(3,0,C0,C4,0),    0 }, /* RO */
-  { "id_aa64pfr1_el1",  CPENC(3,0,C0,C4,1),    0 }, /* RO */
-  { "id_aa64dfr0_el1",  CPENC(3,0,C0,C5,0),    0 }, /* RO */
-  { "id_aa64dfr1_el1",  CPENC(3,0,C0,C5,1),    0 }, /* RO */
-  { "id_aa64isar0_el1", CPENC(3,0,C0,C6,0),    0 }, /* RO */
-  { "id_aa64isar1_el1", CPENC(3,0,C0,C6,1),    0 }, /* RO */
-  { "id_aa64mmfr0_el1", CPENC(3,0,C0,C7,0),    0 }, /* RO */
-  { "id_aa64mmfr1_el1", CPENC(3,0,C0,C7,1),    0 }, /* RO */
-  { "id_aa64mmfr2_el1", CPENC (3, 0, C0, C7, 2), F_ARCHEXT }, /* RO */
-  { "id_aa64afr0_el1",  CPENC(3,0,C0,C5,4),    0 }, /* RO */
-  { "id_aa64afr1_el1",  CPENC(3,0,C0,C5,5),    0 }, /* RO */
-  { "id_aa64zfr0_el1",  CPENC (3, 0, C0, C4, 4), F_ARCHEXT }, /* RO */
-  { "clidr_el1",        CPENC(3,1,C0,C0,1),    0 }, /* RO */
-  { "csselr_el1",       CPENC(3,2,C0,C0,0),    0 }, /* RO */
+  { "midr_el1",         CPENC(3,0,C0,C0,0),    F_REG_READ }, /* RO */
+  { "ctr_el0",          CPENC(3,3,C0,C0,1),    F_REG_READ }, /* RO */
+  { "mpidr_el1",        CPENC(3,0,C0,C0,5),    F_REG_READ }, /* RO */
+  { "revidr_el1",       CPENC(3,0,C0,C0,6),    F_REG_READ }, /* RO */
+  { "aidr_el1",         CPENC(3,1,C0,C0,7),    F_REG_READ }, /* RO */
+  { "dczid_el0",        CPENC(3,3,C0,C0,7),    F_REG_READ }, /* RO */
+  { "id_dfr0_el1",      CPENC(3,0,C0,C1,2),    F_REG_READ }, /* RO */
+  { "id_pfr0_el1",      CPENC(3,0,C0,C1,0),    F_REG_READ }, /* RO */
+  { "id_pfr1_el1",      CPENC(3,0,C0,C1,1),    F_REG_READ }, /* RO */
+  { "id_afr0_el1",      CPENC(3,0,C0,C1,3),    F_REG_READ }, /* RO */
+  { "id_mmfr0_el1",     CPENC(3,0,C0,C1,4),    F_REG_READ }, /* RO */
+  { "id_mmfr1_el1",     CPENC(3,0,C0,C1,5),    F_REG_READ }, /* RO */
+  { "id_mmfr2_el1",     CPENC(3,0,C0,C1,6),    F_REG_READ }, /* RO */
+  { "id_mmfr3_el1",     CPENC(3,0,C0,C1,7),    F_REG_READ }, /* RO */
+  { "id_mmfr4_el1",     CPENC(3,0,C0,C2,6),    F_REG_READ }, /* RO */
+  { "id_isar0_el1",     CPENC(3,0,C0,C2,0),    F_REG_READ }, /* RO */
+  { "id_isar1_el1",     CPENC(3,0,C0,C2,1),    F_REG_READ }, /* RO */
+  { "id_isar2_el1",     CPENC(3,0,C0,C2,2),    F_REG_READ }, /* RO */
+  { "id_isar3_el1",     CPENC(3,0,C0,C2,3),    F_REG_READ }, /* RO */
+  { "id_isar4_el1",     CPENC(3,0,C0,C2,4),    F_REG_READ }, /* RO */
+  { "id_isar5_el1",     CPENC(3,0,C0,C2,5),    F_REG_READ }, /* RO */
+  { "mvfr0_el1",        CPENC(3,0,C0,C3,0),    F_REG_READ }, /* RO */
+  { "mvfr1_el1",        CPENC(3,0,C0,C3,1),    F_REG_READ }, /* RO */
+  { "mvfr2_el1",        CPENC(3,0,C0,C3,2),    F_REG_READ }, /* RO */
+  { "ccsidr_el1",       CPENC(3,1,C0,C0,0),    F_REG_READ }, /* RO */
+  { "id_aa64pfr0_el1",  CPENC(3,0,C0,C4,0),    F_REG_READ }, /* RO */
+  { "id_aa64pfr1_el1",  CPENC(3,0,C0,C4,1),    F_REG_READ }, /* RO */
+  { "id_aa64dfr0_el1",  CPENC(3,0,C0,C5,0),    F_REG_READ }, /* RO */
+  { "id_aa64dfr1_el1",  CPENC(3,0,C0,C5,1),    F_REG_READ }, /* RO */
+  { "id_aa64isar0_el1", CPENC(3,0,C0,C6,0),    F_REG_READ }, /* RO */
+  { "id_aa64isar1_el1", CPENC(3,0,C0,C6,1),    F_REG_READ }, /* RO */
+  { "id_aa64mmfr0_el1", CPENC(3,0,C0,C7,0),    F_REG_READ }, /* RO */
+  { "id_aa64mmfr1_el1", CPENC(3,0,C0,C7,1),    F_REG_READ }, /* RO */
+  { "id_aa64mmfr2_el1", CPENC (3, 0, C0, C7, 2), F_ARCHEXT | F_REG_READ }, /* RO */
+  { "id_aa64afr0_el1",  CPENC(3,0,C0,C5,4),    F_REG_READ }, /* RO */
+  { "id_aa64afr1_el1",  CPENC(3,0,C0,C5,5),    F_REG_READ }, /* RO */
+  { "id_aa64zfr0_el1",  CPENC (3, 0, C0, C4, 4), F_ARCHEXT | F_REG_READ }, /* RO */
+  { "clidr_el1",        CPENC(3,1,C0,C0,1),    F_REG_READ }, /* RO */
+  { "csselr_el1",       CPENC(3,2,C0,C0,0),    F_REG_READ }, /* RO */
   { "vpidr_el2",        CPENC(3,4,C0,C0,0),    0 },
   { "vmpidr_el2",       CPENC(3,4,C0,C0,5),    0 },
   { "sctlr_el1",        CPENC(3,0,C1,C0,0),    0 },
@@ -3785,11 +3794,11 @@ const aarch64_sys_reg aarch64_sys_regs [] =
   { "esr_el2",          CPENC(3,4,C5,C2,0),    0 },
   { "esr_el3",          CPENC(3,6,C5,C2,0),    0 },
   { "esr_el12",                CPENC (3, 5, C5, C2, 0), F_ARCHEXT },
-  { "vsesr_el2",       CPENC (3, 4, C5, C2, 3), F_ARCHEXT }, /* RO */
+  { "vsesr_el2",       CPENC (3, 4, C5, C2, 3), F_ARCHEXT | F_REG_READ }, /* RO */
   { "fpexc32_el2",      CPENC(3,4,C5,C3,0),    0 },
-  { "erridr_el1",      CPENC (3, 0, C5, C3, 0), F_ARCHEXT }, /* RO */
+  { "erridr_el1",      CPENC (3, 0, C5, C3, 0), F_ARCHEXT | F_REG_READ }, /* RO */
   { "errselr_el1",     CPENC (3, 0, C5, C3, 1), F_ARCHEXT },
-  { "erxfr_el1",       CPENC (3, 0, C5, C4, 0), F_ARCHEXT }, /* RO */
+  { "erxfr_el1",       CPENC (3, 0, C5, C4, 0), F_ARCHEXT | F_REG_READ }, /* RO */
   { "erxctlr_el1",     CPENC (3, 0, C5, C4, 1), F_ARCHEXT },
   { "erxstatus_el1",   CPENC (3, 0, C5, C4, 2), F_ARCHEXT },
   { "erxaddr_el1",     CPENC (3, 0, C5, C4, 3), F_ARCHEXT },
@@ -3813,27 +3822,27 @@ const aarch64_sys_reg aarch64_sys_regs [] =
   { "vbar_el2",         CPENC(3,4,C12,C0,0),   0 },
   { "vbar_el3",         CPENC(3,6,C12,C0,0),   0 },
   { "vbar_el12",       CPENC (3, 5, C12, C0, 0), F_ARCHEXT },
-  { "rvbar_el1",        CPENC(3,0,C12,C0,1),   0 }, /* RO */
-  { "rvbar_el2",        CPENC(3,4,C12,C0,1),   0 }, /* RO */
-  { "rvbar_el3",        CPENC(3,6,C12,C0,1),   0 }, /* RO */
+  { "rvbar_el1",        CPENC(3,0,C12,C0,1),   F_REG_READ }, /* RO */
+  { "rvbar_el2",        CPENC(3,4,C12,C0,1),   F_REG_READ }, /* RO */
+  { "rvbar_el3",        CPENC(3,6,C12,C0,1),   F_REG_READ }, /* RO */
   { "rmr_el1",          CPENC(3,0,C12,C0,2),   0 },
   { "rmr_el2",          CPENC(3,4,C12,C0,2),   0 },
   { "rmr_el3",          CPENC(3,6,C12,C0,2),   0 },
-  { "isr_el1",          CPENC(3,0,C12,C1,0),   0 }, /* RO */
+  { "isr_el1",          CPENC(3,0,C12,C1,0),   F_REG_READ }, /* RO */
   { "disr_el1",                CPENC (3, 0, C12, C1, 1), F_ARCHEXT },
   { "vdisr_el2",       CPENC (3, 4, C12, C1, 1), F_ARCHEXT },
   { "contextidr_el1",   CPENC(3,0,C13,C0,1),   0 },
   { "contextidr_el2",  CPENC (3, 4, C13, C0, 1), F_ARCHEXT },
   { "contextidr_el12", CPENC (3, 5, C13, C0, 1), F_ARCHEXT },
   { "tpidr_el0",        CPENC(3,3,C13,C0,2),   0 },
-  { "tpidrro_el0",      CPENC(3,3,C13,C0,3),   0 }, /* RO */
+  { "tpidrro_el0",      CPENC(3,3,C13,C0,3),   0 }, /* RW */
   { "tpidr_el1",        CPENC(3,0,C13,C0,4),   0 },
   { "tpidr_el2",        CPENC(3,4,C13,C0,2),   0 },
   { "tpidr_el3",        CPENC(3,6,C13,C0,2),   0 },
   { "teecr32_el1",      CPENC(2,2,C0, C0,0),   0 }, /* See section 3.9.7.1 */
-  { "cntfrq_el0",       CPENC(3,3,C14,C0,0),   0 }, /* RO */
-  { "cntpct_el0",       CPENC(3,3,C14,C0,1),   0 }, /* RO */
-  { "cntvct_el0",       CPENC(3,3,C14,C0,2),   0 }, /* RO */
+  { "cntfrq_el0",       CPENC(3,3,C14,C0,0),   0 }, /* RW */
+  { "cntpct_el0",       CPENC(3,3,C14,C0,1),   F_REG_READ }, /* RO */
+  { "cntvct_el0",       CPENC(3,3,C14,C0,2),   F_REG_READ }, /* RO */
   { "cntvoff_el2",      CPENC(3,4,C14,C0,3),   0 },
   { "cntkctl_el1",      CPENC(3,0,C14,C1,0),   0 },
   { "cntkctl_el12",    CPENC (3, 5, C14, C1, 0), F_ARCHEXT },
@@ -3864,13 +3873,13 @@ const aarch64_sys_reg aarch64_sys_regs [] =
   { "teehbr32_el1",     CPENC(2,2,C1,C0,0),    0 },
   { "sder32_el3",       CPENC(3,6,C1,C1,1),    0 },
   { "mdscr_el1",         CPENC(2,0,C0, C2, 2), 0 },
-  { "mdccsr_el0",        CPENC(2,3,C0, C1, 0), 0 },  /* r */
+  { "mdccsr_el0",        CPENC(2,3,C0, C1, 0), F_REG_READ  },  /* r */
   { "mdccint_el1",       CPENC(2,0,C0, C2, 0), 0 },
   { "dbgdtr_el0",        CPENC(2,3,C0, C4, 0), 0 },
-  { "dbgdtrrx_el0",      CPENC(2,3,C0, C5, 0), 0 },  /* r */
-  { "dbgdtrtx_el0",      CPENC(2,3,C0, C5, 0), 0 },  /* w */
-  { "osdtrrx_el1",       CPENC(2,0,C0, C0, 2), 0 },  /* r */
-  { "osdtrtx_el1",       CPENC(2,0,C0, C3, 2), 0 },  /* w */
+  { "dbgdtrrx_el0",      CPENC(2,3,C0, C5, 0), F_REG_READ  },  /* r */
+  { "dbgdtrtx_el0",      CPENC(2,3,C0, C5, 0), F_REG_WRITE },  /* w */
+  { "osdtrrx_el1",       CPENC(2,0,C0, C0, 2), F_REG_READ  },  /* r */
+  { "osdtrtx_el1",       CPENC(2,0,C0, C3, 2), F_REG_WRITE },  /* w */
   { "oseccr_el1",        CPENC(2,0,C0, C6, 2), 0 },
   { "dbgvcr32_el2",      CPENC(2,4,C0, C7, 0), 0 },
   { "dbgbvr0_el1",       CPENC(2,0,C0, C0, 4), 0 },
@@ -3937,35 +3946,35 @@ const aarch64_sys_reg aarch64_sys_regs [] =
   { "dbgwcr13_el1",      CPENC(2,0,C0, C13,7), 0 },
   { "dbgwcr14_el1",      CPENC(2,0,C0, C14,7), 0 },
   { "dbgwcr15_el1",      CPENC(2,0,C0, C15,7), 0 },
-  { "mdrar_el1",         CPENC(2,0,C1, C0, 0), 0 },  /* r */
-  { "oslar_el1",         CPENC(2,0,C1, C0, 4), 0 },  /* w */
-  { "oslsr_el1",         CPENC(2,0,C1, C1, 4), 0 },  /* r */
+  { "mdrar_el1",         CPENC(2,0,C1, C0, 0), F_REG_READ  },  /* r */
+  { "oslar_el1",         CPENC(2,0,C1, C0, 4), F_REG_WRITE },  /* w */
+  { "oslsr_el1",         CPENC(2,0,C1, C1, 4), F_REG_READ  },  /* r */
   { "osdlr_el1",         CPENC(2,0,C1, C3, 4), 0 },
   { "dbgprcr_el1",       CPENC(2,0,C1, C4, 4), 0 },
   { "dbgclaimset_el1",   CPENC(2,0,C7, C8, 6), 0 },
   { "dbgclaimclr_el1",   CPENC(2,0,C7, C9, 6), 0 },
-  { "dbgauthstatus_el1", CPENC(2,0,C7, C14,6), 0 },  /* r */
+  { "dbgauthstatus_el1", CPENC(2,0,C7, C14,6), F_REG_READ  },  /* r */
   { "pmblimitr_el1",    CPENC (3, 0, C9, C10, 0), F_ARCHEXT },  /* rw */
   { "pmbptr_el1",       CPENC (3, 0, C9, C10, 1), F_ARCHEXT },  /* rw */
   { "pmbsr_el1",        CPENC (3, 0, C9, C10, 3), F_ARCHEXT },  /* rw */
-  { "pmbidr_el1",       CPENC (3, 0, C9, C10, 7), F_ARCHEXT },  /* ro */
+  { "pmbidr_el1",       CPENC (3, 0, C9, C10, 7), F_ARCHEXT | F_REG_READ },  /* ro */
   { "pmscr_el1",        CPENC (3, 0, C9, C9, 0),  F_ARCHEXT },  /* rw */
   { "pmsicr_el1",       CPENC (3, 0, C9, C9, 2),  F_ARCHEXT },  /* rw */
   { "pmsirr_el1",       CPENC (3, 0, C9, C9, 3),  F_ARCHEXT },  /* rw */
   { "pmsfcr_el1",       CPENC (3, 0, C9, C9, 4),  F_ARCHEXT },  /* rw */
   { "pmsevfr_el1",      CPENC (3, 0, C9, C9, 5),  F_ARCHEXT },  /* rw */
   { "pmslatfr_el1",     CPENC (3, 0, C9, C9, 6),  F_ARCHEXT },  /* rw */
-  { "pmsidr_el1",       CPENC (3, 0, C9, C9, 7),  F_ARCHEXT },  /* ro */
+  { "pmsidr_el1",       CPENC (3, 0, C9, C9, 7),  F_ARCHEXT | F_REG_READ },  /* ro */
   { "pmscr_el2",        CPENC (3, 4, C9, C9, 0),  F_ARCHEXT },  /* rw */
   { "pmscr_el12",       CPENC (3, 5, C9, C9, 0),  F_ARCHEXT },  /* rw */
   { "pmcr_el0",          CPENC(3,3,C9,C12, 0), 0 },
   { "pmcntenset_el0",    CPENC(3,3,C9,C12, 1), 0 },
   { "pmcntenclr_el0",    CPENC(3,3,C9,C12, 2), 0 },
   { "pmovsclr_el0",      CPENC(3,3,C9,C12, 3), 0 },
-  { "pmswinc_el0",       CPENC(3,3,C9,C12, 4), 0 },  /* w */
+  { "pmswinc_el0",       CPENC(3,3,C9,C12, 4), F_REG_WRITE },  /* w */
   { "pmselr_el0",        CPENC(3,3,C9,C12, 5), 0 },
-  { "pmceid0_el0",       CPENC(3,3,C9,C12, 6), 0 },  /* r */
-  { "pmceid1_el0",       CPENC(3,3,C9,C12, 7), 0 },  /* r */
+  { "pmceid0_el0",       CPENC(3,3,C9,C12, 6), F_REG_READ  },  /* r */
+  { "pmceid1_el0",       CPENC(3,3,C9,C12, 7), F_REG_READ  },  /* r */
   { "pmccntr_el0",       CPENC(3,3,C9,C13, 0), 0 },
   { "pmxevtyper_el0",    CPENC(3,3,C9,C13, 1), 0 },
   { "pmxevcntr_el0",     CPENC(3,3,C9,C13, 2), 0 },
index 81d045eded8447c85b7b2acd3f760fd79346ea54..f741deac3f9a8975ad59b69e23b4c2d99491aa85 100644 (file)
@@ -196,6 +196,26 @@ extern const aarch64_operand aarch64_operands[];
 #define OPD_F_OD_LSB           5
 #define OPD_F_NO_ZR            0x00000100      /* ZR index not allowed.  */
 
+/* Register flags.  */
+
+#undef F_DEPRECATED
+#define F_DEPRECATED   (1 << 0)  /* Deprecated system register.  */
+
+#undef F_ARCHEXT
+#define F_ARCHEXT      (1 << 1)  /* Architecture dependent system register.  */
+
+#undef F_HASXT
+#define F_HASXT                (1 << 2)  /* System instruction register <Xt>
+                                    operand.  */
+
+#undef F_REG_READ
+#define F_REG_READ     (1 << 3)  /* Register can only be used to read values
+                                    out of.  */
+
+#undef F_REG_WRITE
+#define F_REG_WRITE    (1 << 4)  /* Register can only be written to but not
+                                    read from.  */
+
 static inline bfd_boolean
 operand_has_inserter (const aarch64_operand *operand)
 {
index 36afdd1bc34b3eeb780e0becf14a41a83987b621..1e1b2e4ffe68a8a791342c4b6eae485fcef32f71 100644 (file)
@@ -3452,7 +3452,7 @@ struct aarch64_opcode aarch64_opcode_table[] =
   CORE_INSN ("adr",  0x10000000, 0x9f000000, pcreladdr, 0, OP2 (Rd, ADDR_PCREL21), QL_ADRP, 0),
   CORE_INSN ("adrp", 0x90000000, 0x9f000000, pcreladdr, 0, OP2 (Rd, ADDR_ADRP), QL_ADRP, 0),
   /* System.  */
-  CORE_INSN ("msr", 0xd500401f, 0xfff8f01f, ic_system, 0, OP2 (PSTATEFIELD, UIMM4), {}, 0),
+  CORE_INSN ("msr", 0xd500401f, 0xfff8f01f, ic_system, 0, OP2 (PSTATEFIELD, UIMM4), {}, F_SYS_WRITE),
   CORE_INSN ("hint",0xd503201f, 0xfffff01f, ic_system, 0, OP1 (UIMM7), {}, F_HAS_ALIAS),
   CORE_INSN ("nop", 0xd503201f, 0xffffffff, ic_system, 0, OP0 (), {}, F_ALIAS),
   CORE_INSN ("csdb",0xd503229f, 0xffffffff, ic_system, 0, OP0 (), {}, F_ALIAS),
@@ -3477,9 +3477,9 @@ struct aarch64_opcode aarch64_opcode_table[] =
   CORE_INSN ("dc",  0xd5080000, 0xfff80000, ic_system, 0, OP2 (SYSREG_DC, Rt), QL_SRC_X, F_ALIAS),
   CORE_INSN ("ic",  0xd5080000, 0xfff80000, ic_system, 0, OP2 (SYSREG_IC, Rt_SYS), QL_SRC_X, F_ALIAS | F_OPD1_OPT | F_DEFAULT (0x1F)),
   CORE_INSN ("tlbi",0xd5080000, 0xfff80000, ic_system, 0, OP2 (SYSREG_TLBI, Rt_SYS), QL_SRC_X, F_ALIAS | F_OPD1_OPT | F_DEFAULT (0x1F)),
-  CORE_INSN ("msr", 0xd5000000, 0xffe00000, ic_system, 0, OP2 (SYSREG, Rt), QL_SRC_X, 0),
+  CORE_INSN ("msr", 0xd5000000, 0xffe00000, ic_system, 0, OP2 (SYSREG, Rt), QL_SRC_X, F_SYS_WRITE),
   CORE_INSN ("sysl",0xd5280000, 0xfff80000, ic_system, 0, OP5 (Rt, UIMM3_OP1, CRn, CRm, UIMM3_OP2), QL_SYSL, 0),
-  CORE_INSN ("mrs", 0xd5200000, 0xffe00000, ic_system, 0, OP2 (Rt, SYSREG), QL_DST_X, 0),
+  CORE_INSN ("mrs", 0xd5200000, 0xffe00000, ic_system, 0, OP2 (Rt, SYSREG), QL_DST_X, F_SYS_READ),
   V8_3_INSN ("paciaz",  0xd503231f, 0xffffffff, ic_system, OP0 (), {}, F_ALIAS),
   V8_3_INSN ("paciasp", 0xd503233f, 0xffffffff, ic_system, OP0 (), {}, F_ALIAS),
   V8_3_INSN ("pacibz",  0xd503235f, 0xffffffff, ic_system, OP0 (), {}, F_ALIAS),