[PATCH 1/9] aarch64: Extend aarch64_field to support constants

Alice Carlotti alice.carlotti@arm.com
Wed Oct 8 00:38:20 GMT 2025


Many instructions have constraints on the range of registers they can
use.  This means that some bits in the register number are fixed, and
therefore aren't mapped to a field in the instruction encoding.
Currently we use various adhoc rules to handle these fixed bits, but
this doesn't handle all cases and we often have to write new code to
support new combinations of permitted registers.

This patch allows these constant bits to instead be specified in the
same structure used to represent instruction fields.  Uses of the new
constant fields will be introduced in subsequent patches.


diff --git a/opcodes/aarch64-opc.c b/opcodes/aarch64-opc.c
index 4b173201e92bc7fd5c6d4e306e1f8fb332b0e041..b0ee3c9d3633075377ca3c14feccc124d0a94ba4 100644
--- a/opcodes/aarch64-opc.c
+++ b/opcodes/aarch64-opc.c
@@ -226,6 +226,8 @@ aarch64_select_operand_for_sizeq_field_coding (const aarch64_opcode *opcode)
 const aarch64_field aarch64_fields[] =
 {
     {  0,  0 },	/* NIL.  */
+    { 32,  1 },	/* CONST_0.  */
+    { 33,  1 },	/* CONST_1.  */
     {  8,  4 },	/* CRm: in the system instructions.  */
     { 10,  2 }, /* CRm_dsb_nxs: 2-bit imm. encoded in CRm<3:2>.  */
     { 12,  4 },	/* CRn: in the system instructions.  */
diff --git a/opcodes/aarch64-opc.h b/opcodes/aarch64-opc.h
index 4182c9d5f678beac3a240e08c9842e8620a32bb6..4d2d928c1d8d39b9489e073fc9141c154b38e3a3 100644
--- a/opcodes/aarch64-opc.h
+++ b/opcodes/aarch64-opc.h
@@ -30,6 +30,8 @@
 enum aarch64_field_kind
 {
   FLD_NIL,
+  FLD_CONST_0,
+  FLD_CONST_1,
   FLD_CRm,
   FLD_CRm_dsb_nxs,
   FLD_CRn,
@@ -242,7 +244,10 @@ enum aarch64_field_kind
   FLD_ZA5_4,
 };
 
-/* Field description.  */
+/* Field description.
+   If lsb < 32, then this represents a field in an instruction encoding.
+   If lsb >= 32, then this represents a constant value of width <= 5,
+   stored as lsb = (value | 32).  */
 struct aarch64_field
 {
   int lsb;
@@ -497,8 +502,14 @@ insert_field_2 (const aarch64_field *field, aarch64_insn *code,
 		aarch64_insn value, aarch64_insn mask)
 {
   assert (field->width < 32 && field->width >= 1 && field->lsb >= 0
-	  && field->lsb + field->width <= 32);
+	  && (field->lsb >= 32 || (field->lsb + field->width <= 32)));
   value &= gen_mask (field->width);
+  if (field->lsb >= 32)
+    {
+      /* Value is constant.  */
+      assert (value == (field->lsb & 31));
+      return;
+    }
   value <<= field->lsb;
   /* In some opcodes, field can be part of the base opcode, e.g. the size
      field in FADD.  The following helps avoid corrupt the base opcode.  */
@@ -514,6 +525,10 @@ extract_field_2 (const aarch64_field *field, aarch64_insn code,
 		 aarch64_insn mask)
 {
   aarch64_insn value;
+  /* Check for constant field.  */
+  if (field->lsb >= 32)
+    return field->lsb & 31;
+
   /* Clear any bit that is a part of the base opcode.  */
   code &= ~mask;
   value = (code >> field->lsb) & gen_mask (field->width);


More information about the Binutils mailing list