[06/12] aarch64: Apply narrowing of allowed immediate values for SYSP

Message ID 20240103011739.2444792-7-victor.donascimento@arm.com
State Unresolved
Headers
Series None |

Checks

Context Check Description
snail/binutils-gdb-check warning Git am fail log

Commit Message

Victor Do Nascimento Jan. 3, 2024, 1:17 a.m. UTC
  While CRn and CRm fields in the SYSP instruction are 4-bit wide and
are thus able to accommodate values in the range 0-15, the
specifications for the SYSP instructions limit their ranges to 8-9 for
CRm and 0-7 in the case of CRn.

This led to the need to signal in some way to the operand parser that
a given operand is under special restrictions regarding its use.  This
is done via the new `F_OPD_NARROW' flag, indicating a narrowing in the
range of operand values for fields in the instruction tagged with the
flag.

The flag is then used in `parse_operands' when the instruction is
assembled, but needs not be taken into consideration during
disassembly.
---
 gas/config/tc-aarch64.c                    | 18 +++++++++++++++++-
 gas/testsuite/gas/aarch64/illegal-sys128.d |  3 +++
 gas/testsuite/gas/aarch64/sysp.d           | 10 ++++++++++
 gas/testsuite/gas/aarch64/sysp.s           |  4 ++++
 include/opcode/aarch64.h                   |  7 ++++++-
 opcodes/aarch64-tbl.h                      |  2 +-
 6 files changed, 41 insertions(+), 3 deletions(-)
 create mode 100644 gas/testsuite/gas/aarch64/illegal-sys128.d
 create mode 100644 gas/testsuite/gas/aarch64/sysp.d
 create mode 100644 gas/testsuite/gas/aarch64/sysp.s
  

Patch

diff --git a/gas/config/tc-aarch64.c b/gas/config/tc-aarch64.c
index 12fb1740635..cc08fd31dd4 100644
--- a/gas/config/tc-aarch64.c
+++ b/gas/config/tc-aarch64.c
@@ -6485,6 +6485,7 @@  parse_operands (char *str, const aarch64_opcode *opcode)
   int i;
   char *backtrack_pos = 0;
   const enum aarch64_opnd *operands = opcode->operands;
+  const uint64_t flags = opcode->flags;
   aarch64_reg_type imm_reg_type;
 
   clear_error ();
@@ -6833,7 +6834,22 @@  parse_operands (char *str, const aarch64_opcode *opcode)
 		goto failure;
 
 	      po_imm_nc_or_fail ();
-	      if (val > 15)
+	      if (flags & F_OPD_NARROW)
+		{
+		  if ((operands[i] == AARCH64_OPND_CRn)
+		      && (val < 8 || val > 9))
+		    {
+		      set_fatal_syntax_error (_(N_ ("C8 - C9 expected")));
+		      goto failure;
+		    }
+		  else if ((operands[i] == AARCH64_OPND_CRm)
+			   && (val > 7))
+		    {
+		      set_fatal_syntax_error (_(N_ ("C0 - C7 expected")));
+		      goto failure;
+		    }
+		}
+	      else if (val > 15)
 		{
 		  set_fatal_syntax_error (_(N_ ("C0 - C15 expected")));
 		  goto failure;
diff --git a/gas/testsuite/gas/aarch64/illegal-sys128.d b/gas/testsuite/gas/aarch64/illegal-sys128.d
new file mode 100644
index 00000000000..891b9347167
--- /dev/null
+++ b/gas/testsuite/gas/aarch64/illegal-sys128.d
@@ -0,0 +1,3 @@ 
+#name: Out-of-bounds SYSP operand tests
+#source: illegal-sys128.s
+#error_output: illegal-sys128.l
diff --git a/gas/testsuite/gas/aarch64/sysp.d b/gas/testsuite/gas/aarch64/sysp.d
new file mode 100644
index 00000000000..80286c19ffd
--- /dev/null
+++ b/gas/testsuite/gas/aarch64/sysp.d
@@ -0,0 +1,10 @@ 
+#objdump: -dr
+
+.*
+
+
+Disassembly of section \.text:
+
+0+ <\.text>:
+[^:]*:	d5488000 	sysp	#0, C8, C0, #0, x0, x1
+[^:]*:	d54e97fa 	sysp	#6, C9, C7, #7, x26, x27
\ No newline at end of file
diff --git a/gas/testsuite/gas/aarch64/sysp.s b/gas/testsuite/gas/aarch64/sysp.s
new file mode 100644
index 00000000000..f50d3ab05a8
--- /dev/null
+++ b/gas/testsuite/gas/aarch64/sysp.s
@@ -0,0 +1,4 @@ 
+	.arch armv9.4-a+d128
+
+	sysp	#0, C8, C0, #0, x0, x1
+	sysp	#6, C9, C7, #7, x26, x27
diff --git a/include/opcode/aarch64.h b/include/opcode/aarch64.h
index c69f85557d0..d170bdf0bde 100644
--- a/include/opcode/aarch64.h
+++ b/include/opcode/aarch64.h
@@ -1224,7 +1224,12 @@  extern const aarch64_opcode aarch64_opcode_table[];
    to be optional, then we also implicitly specify (N+1)th operand to also be
    optional.  */
 #define F_OPD_PAIR_OPT (1ULL << 32)
-/* Next bit is 33.  */
+/* This instruction does not allow the full range of values that the
+   width of fields in the assembler instruction would theoretically
+   allow.  This impacts the constraintts on assembly but yelds no
+   impact on disassembly.  */
+#define F_OPD_NARROW (1ULL << 33)
+/* Next bit is 34.  */
 
 /* Instruction constraints.  */
 /* This instruction has a predication constraint on the instruction at PC+4.  */
diff --git a/opcodes/aarch64-tbl.h b/opcodes/aarch64-tbl.h
index 79830e007d5..98feb56e08a 100644
--- a/opcodes/aarch64-tbl.h
+++ b/opcodes/aarch64-tbl.h
@@ -4201,7 +4201,7 @@  const struct aarch64_opcode aarch64_opcode_table[] =
   GCS_INSN ("gcssttr", 0xd91f1c00, 0xfffffc00, OP2 (Rt, Rn_SP), QL_I2SAMEX, 0),
   CORE_INSN ("gcsb", 0xd503227f, 0xffffffff, ic_system, 0, OP1 (BARRIER_GCSB), {}, F_ALIAS),
   CORE_INSN ("sys", 0xd5080000, 0xfff80000, ic_system, 0, OP5 (UIMM3_OP1, CRn, CRm, UIMM3_OP2, Rt), QL_SYS, F_HAS_ALIAS | F_OPD4_OPT | F_DEFAULT (0x1F)),
-  D128_INSN ("sysp", 0xd5480000, 0xfff80000, OP6 (UIMM3_OP1, CRn, CRm, UIMM3_OP2, Rt, PAIRREG_OR_XZR), QL_SYSP, F_HAS_ALIAS | F_OPD4_OPT | F_OPD_PAIR_OPT | F_DEFAULT (0x1f)),
+  D128_INSN ("sysp", 0xd5480000, 0xfff80000, OP6 (UIMM3_OP1, CRn, CRm, UIMM3_OP2, Rt, PAIRREG_OR_XZR), QL_SYSP, F_HAS_ALIAS | F_OPD_NARROW | F_OPD4_OPT | F_OPD_PAIR_OPT | F_DEFAULT (0x1f)),
   CORE_INSN ("at",  0xd5080000, 0xfff80000, ic_system, 0, OP2 (SYSREG_AT, Rt), QL_SRC_X, F_ALIAS),
   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)),