]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
aarch64: Extend aarch64_field to support constants
authorAlice Carlotti <alice.carlotti@arm.com>
Thu, 2 Oct 2025 17:57:58 +0000 (18:57 +0100)
committerAlice Carlotti <alice.carlotti@arm.com>
Fri, 10 Oct 2025 00:14:06 +0000 (01:14 +0100)
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.

opcodes/aarch64-asm.c
opcodes/aarch64-dis.c
opcodes/aarch64-opc.c
opcodes/aarch64-opc.h

index 75216fd8dc3c4b269dcb123e9896c2d2f0e6debc..fafbc4db375a0fd552b947f31825c1295e119925 100644 (file)
@@ -313,7 +313,7 @@ aarch64_ins_ldst_elemlist (const aarch64_operand *self ATTRIBUTE_UNUSED,
                           const aarch64_inst *inst ATTRIBUTE_UNUSED,
                           aarch64_operand_error *errors ATTRIBUTE_UNUSED)
 {
-  aarch64_field field = {0, 0};
+  aarch64_field field = AARCH64_FIELD_NIL;
   aarch64_insn QSsize = 0;     /* fields Q:S:size.  */
   aarch64_insn opcodeh2 = 0;   /* opcode<2:1> */
 
@@ -459,7 +459,7 @@ aarch64_ins_advsimd_imm_modified (const aarch64_operand *self ATTRIBUTE_UNUSED,
   uint64_t imm = info->imm.value;
   enum aarch64_modifier_kind kind = info->shifter.kind;
   int amount = info->shifter.amount;
-  aarch64_field field = {0, 0};
+  aarch64_field field = AARCH64_FIELD_NIL;
 
   /* a:b:c:d:e:f:g:h */
   if (!info->imm.is_fp && aarch64_get_qualifier_esize (opnd0_qualifier) == 8)
@@ -1833,7 +1833,7 @@ static void
 encode_asimd_fcvt (aarch64_inst *inst)
 {
   aarch64_insn value;
-  aarch64_field field = {0, 0};
+  aarch64_field field = AARCH64_FIELD_NIL;
   enum aarch64_opnd_qualifier qualifier = AARCH64_OPND_QLF_NIL;
 
   switch (inst->opcode->op)
@@ -1865,7 +1865,7 @@ static void
 encode_asisd_fcvtxn (aarch64_inst *inst)
 {
   aarch64_insn val = 1;
-  aarch64_field field = {0, 0};
+  aarch64_field field = AARCH64_FIELD_NIL;
   assert (inst->operands[0].qualifier == AARCH64_OPND_QLF_S_S);
   gen_sub_field (FLD_size, 0, 1, &field);
   insert_field_2 (&field, &inst->value, val, 0);
@@ -1876,7 +1876,7 @@ static void
 encode_fcvt (aarch64_inst *inst)
 {
   aarch64_insn val;
-  const aarch64_field field = {15, 2};
+  const aarch64_field field = AARCH64_FIELD (15, 2);
 
   /* opc dstsize */
   switch (inst->operands[0].qualifier)
@@ -2096,7 +2096,7 @@ do_special_encoding (struct aarch64_inst *inst)
   if (inst->opcode->flags & F_T)
     {
       int num; /* num of consecutive '0's on the right side of imm5<3:0>.  */
-      aarch64_field field = {0, 0};
+      aarch64_field field = AARCH64_FIELD_NIL;
       enum aarch64_opnd_qualifier qualifier;
 
       idx = 0;
@@ -2157,7 +2157,7 @@ do_special_encoding (struct aarch64_inst *inst)
     {
       /* e.g. LDRSB <Wt>, [<Xn|SP>, <R><m>{, <extend> {<amount>}}].  */
       enum aarch64_opnd_qualifier qualifier;
-      aarch64_field field = {0, 0};
+      aarch64_field field = AARCH64_FIELD_NIL;
       assert (aarch64_get_operand_class (inst->opcode->operands[0])
              == AARCH64_OPND_CLASS_INT_REG);
       gen_sub_field (FLD_opc, 0, 1, &field);
index 4a4be31c81300ac16678a7c6c3b12b1d5c585a97..f2683d0b2c131237a5eee5dfa1411df77619944f 100644 (file)
@@ -584,7 +584,7 @@ aarch64_ext_ldst_elemlist (const aarch64_operand *self ATTRIBUTE_UNUSED,
                           const aarch64_inst *inst ATTRIBUTE_UNUSED,
                           aarch64_operand_error *errors ATTRIBUTE_UNUSED)
 {
-  aarch64_field field = {0, 0};
+  aarch64_field field = AARCH64_FIELD_NIL;
   aarch64_insn QSsize;         /* fields Q:S:size.  */
   aarch64_insn opcodeh2;       /* opcode<2:1> */
 
@@ -796,7 +796,7 @@ aarch64_ext_advsimd_imm_modified (const aarch64_operand *self ATTRIBUTE_UNUSED,
 {
   uint64_t imm;
   enum aarch64_opnd_qualifier opnd0_qualifier = inst->operands[0].qualifier;
-  aarch64_field field = {0, 0};
+  aarch64_field field = AARCH64_FIELD_NIL;
 
   assert (info->idx == 1);
 
@@ -2599,7 +2599,7 @@ decode_sizeq (aarch64_inst *inst)
 static int
 decode_asimd_fcvt (aarch64_inst *inst)
 {
-  aarch64_field field = {0, 0};
+  aarch64_field field = AARCH64_FIELD_NIL;
   aarch64_insn value;
   enum aarch64_opnd_qualifier qualifier;
 
@@ -2632,7 +2632,7 @@ decode_asimd_fcvt (aarch64_inst *inst)
 static int
 decode_asisd_fcvtxn (aarch64_inst *inst)
 {
-  aarch64_field field = {0, 0};
+  aarch64_field field = AARCH64_FIELD_NIL;
   gen_sub_field (FLD_size, 0, 1, &field);
   if (!extract_field_2 (&field, inst->value, 0))
     return 0;
@@ -2646,7 +2646,7 @@ decode_fcvt (aarch64_inst *inst)
 {
   enum aarch64_opnd_qualifier qualifier;
   aarch64_insn value;
-  const aarch64_field field = {15, 2};
+  const aarch64_field field = AARCH64_FIELD (15, 2);
 
   /* opc dstsize */
   value = extract_field_2 (&field, inst->value, 0);
@@ -2925,7 +2925,7 @@ do_special_decoding (aarch64_inst *inst)
 
   if (inst->opcode->flags & F_LDS_SIZE)
     {
-      aarch64_field field = {0, 0};
+      aarch64_field field = AARCH64_FIELD_NIL;
       assert (aarch64_get_operand_class (inst->opcode->operands[0])
              == AARCH64_OPND_CLASS_INT_REG);
       gen_sub_field (FLD_opc, 0, 1, &field);
index e01b9f7b09dc8184bc6189ae4bae6dd6e5d06fc5..29321ca79eb72badf132443d1a78da58d626f401 100644 (file)
@@ -225,220 +225,219 @@ aarch64_select_operand_for_sizeq_field_coding (const aarch64_opcode *opcode)
 +   Keep synced with 'enum aarch64_field_kind'.  */
 const aarch64_field aarch64_fields[] =
 {
-    {  0,  0 },        /* NIL.  */
-    {  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.  */
-    { 10,  8 }, /* CSSC_imm8.  */
-    { 11,  1 },        /* H: in advsimd scalar x indexed element instructions.  */
-    { 21,  1 },        /* L: in advsimd scalar x indexed element instructions.  */
-    {  0,  5 },        /* LSE128_Rt: Shared input+output operand register.  */
-    { 16,  5 },        /* LSE128_Rt2: Shared input+output operand register 2.  */
-    { 20,  1 },        /* M: in advsimd scalar x indexed element instructions.  */
-    { 22,  1 },        /* N: in logical (immediate) instructions.  */
-    { 30,  1 },        /* Q: in most AdvSIMD instructions.  */
-    { 10,  5 },        /* Ra: in fp instructions.  */
-    {  0,  5 },        /* Rd: in many integer instructions.  */
-    { 16,  5 },        /* Rm: in ld/st reg offset and some integer inst.  */
-    {  5,  5 },        /* Rn: in many integer instructions.  */
-    { 16,  5 },        /* Rs: in load/store exclusive instructions.  */
-    {  0,  5 },        /* Rt: in load/store instructions.  */
-    { 10,  5 },        /* Rt2: in load/store pair instructions.  */
-    { 12,  1 },        /* S: in load/store reg offset instructions.  */
-    { 12,  2 }, /* SM3_imm2: Indexed element SM3 2 bits index immediate.  */
-    {  1,  3 }, /* SME_Pdx2: predicate register, multiple of 2, [3:1].  */
-    { 13,  3 }, /* SME_Pm: second source scalable predicate register P0-P7.  */
-    {  0,  3 }, /* SME_PNd3: PN0-PN7, bits [2:0].  */
-    {  5,  3 }, /* SME_PNn3: PN0-PN7, bits [7:5].  */
-    { 16,  1 }, /* SME_Q: Q class bit, bit 16.  */
-    { 16,  2 }, /* SME_Rm: index base register W12-W15 [17:16].  */
-    { 13,  2 }, /* SME_Rv: vector select register W12-W15, bits [14:13].  */
-    { 15,  1 }, /* SME_V: (horizontal / vertical tiles), bit 15.  */
-    { 10,  1 }, /* SME_VL_10: VLx2 or VLx4, bit [10].  */
-    { 13,  1 }, /* SME_VL_13: VLx2 or VLx4, bit [13].  */
-    {  0,  1 }, /* SME_ZAda_1b: tile ZA0-ZA1.  */
-    {  0,  2 }, /* SME_ZAda_2b: tile ZA0-ZA3.  */
-    {  0,  3 }, /* SME_ZAda_3b: tile ZA0-ZA7.  */
-    {  1,  4 }, /* SME_Zdn2: Z0-Z31, multiple of 2, bits [4:1].  */
-    {  2,  3 }, /* SME_Zdn4: Z0-Z31, multiple of 4, bits [4:2].  */
-    { 16,  4 }, /* SME_Zm: Z0-Z15, bits [19:16].  */
-    { 17,  4 }, /* SME_Zm2: Z0-Z31, multiple of 2, bits [20:17].  */
-    { 18,  3 }, /* SME_Zm4: Z0-Z31, multiple of 4, bits [20:18].  */
-    {  6,  4 }, /* SME_Zn2: Z0-Z31, multiple of 2, bits [9:6].  */
-    {  7,  3 }, /* SME_Zn4: Z0-Z31, multiple of 4, bits [9:7].  */
-    {  4,  1 }, /* SME_ZtT: upper bit of Zt, bit [4].  */
-    {  0,  3 }, /* SME_Zt3: lower 3 bits of Zt, bits [2:0].  */
-    {  0,  2 }, /* SME_Zt2: lower 2 bits of Zt, bits [1:0].  */
-    { 23,  1 }, /* SME_i1: immediate field, bit 23.  */
-    { 12,  2 }, /* SME_size_12: bits [13:12].  */
-    { 22,  2 }, /* SME_size_22: size<1>, size<0> class field, [23:22].  */
-    { 23,  1 }, /* SME_sz_23: bit [23].  */
-    { 22,  1 }, /* SME_tszh: immediate and qualifier field, bit 22.  */
-    { 18,  3 }, /* SME_tszl: immediate and qualifier field, bits [20:18].  */
-    { 0,   8 }, /* SME_zero_mask: list of up to 8 tile names separated by commas [7:0].  */
-    {  4,  1 }, /* SVE_M_4: Merge/zero select, bit 4.  */
-    { 14,  1 }, /* SVE_M_14: Merge/zero select, bit 14.  */
-    { 16,  1 }, /* SVE_M_16: Merge/zero select, bit 16.  */
-    { 17,  1 }, /* SVE_N: SVE equivalent of N.  */
-    {  0,  4 }, /* SVE_Pd: p0-p15, bits [3,0].  */
-    { 10,  3 }, /* SVE_Pg3: p0-p7, bits [12,10].  */
-    {  5,  4 }, /* SVE_Pg4_5: p0-p15, bits [8,5].  */
-    { 10,  4 }, /* SVE_Pg4_10: p0-p15, bits [13,10].  */
-    { 16,  4 }, /* SVE_Pg4_16: p0-p15, bits [19,16].  */
-    { 16,  4 }, /* SVE_Pm: p0-p15, bits [19,16].  */
-    {  5,  4 }, /* SVE_Pn: p0-p15, bits [8,5].  */
-    {  0,  4 }, /* SVE_Pt: p0-p15, bits [3,0].  */
-    {  5,  5 }, /* SVE_Rm: SVE alternative position for Rm.  */
-    { 16,  5 }, /* SVE_Rn: SVE alternative position for Rn.  */
-    {  0,  5 }, /* SVE_Vd: Scalar SIMD&FP register, bits [4,0].  */
-    {  5,  5 }, /* SVE_Vm: Scalar SIMD&FP register, bits [9,5].  */
-    {  5,  5 }, /* SVE_Vn: Scalar SIMD&FP register, bits [9,5].  */
-    {  5,  5 }, /* SVE_Za_5: SVE vector register, bits [9,5].  */
-    { 16,  5 }, /* SVE_Za_16: SVE vector register, bits [20,16].  */
-    {  0,  5 }, /* SVE_Zd: SVE vector register. bits [4,0].  */
-    {  5,  5 }, /* SVE_Zm_5: SVE vector register, bits [9,5].  */
-    { 16,  5 }, /* SVE_Zm_16: SVE vector register, bits [20,16]. */
-    {  5,  5 }, /* SVE_Zn: SVE vector register, bits [9,5].  */
-    {  0,  5 }, /* SVE_Zt: SVE vector register, bits [4,0].  */
-    {  5,  1 }, /* SVE_i1: single-bit immediate.  */
-    { 23,  1 }, /* SVE_i1_23: single-bit immediate.  */
-    { 22,  2 }, /* SVE_i2: 2-bit index, bits [23,22].  */
-    { 20,  1 }, /* SVE_i2h: high bit of 2bit immediate, bits.  */
-    { 22,  1 }, /* SVE_i3h: high bit of 3-bit immediate.  */
-    { 19,  2 }, /* SVE_i3h2: two high bits of 3bit immediate, bits [20,19].  */
-    { 22,  2 }, /* SVE_i3h3: two high bits of 3bit immediate, bits [22,23].  */
-    { 11,  1 }, /* SVE_i3l: low bit of 3-bit immediate.  */
-    { 12,  1 }, /* SVE_i3l2: low bit of 3-bit immediate, bit 12.  */
-    { 10,  2 }, /* SVE_i4l2: two low bits of 4bit immediate, bits [11,10].  */
-    { 16,  3 }, /* SVE_imm3: 3-bit immediate field.  */
-    { 16,  4 }, /* SVE_imm4: 4-bit immediate field.  */
-    {  5,  5 }, /* SVE_imm5: 5-bit immediate field.  */
-    { 16,  5 }, /* SVE_imm5b: secondary 5-bit immediate field.  */
-    { 16,  6 }, /* SVE_imm6: 6-bit immediate field.  */
-    { 14,  7 }, /* SVE_imm7: 7-bit immediate field.  */
-    {  5,  8 }, /* SVE_imm8: 8-bit immediate field.  */
-    {  5,  9 }, /* SVE_imm9: 9-bit immediate field.  */
-    { 11,  6 }, /* SVE_immr: SVE equivalent of immr.  */
-    {  5,  6 }, /* SVE_imms: SVE equivalent of imms.  */
-    { 10,  2 }, /* SVE_msz: 2-bit shift amount for ADR.  */
-    {  5,  5 }, /* SVE_pattern: vector pattern enumeration.  */
-    {  0,  4 }, /* SVE_prfop: prefetch operation for SVE PRF[BHWD].  */
-    { 16,  1 }, /* SVE_rot1: 1-bit rotation amount.  */
-    { 10,  2 }, /* SVE_rot2: 2-bit rotation amount.  */
-    { 10,  1 }, /* SVE_rot3: 1-bit rotation amount at bit 10.  */
-    { 17,  2 }, /* SVE_size: 2-bit element size, bits [18,17].  */
-    { 22,  1 }, /* SVE_sz: 1-bit element size select.  */
-    { 30,  1 }, /* SVE_sz2: 1-bit element size select.  */
-    { 17,  1 }, /* SVE_sz3: 1-bit element size select.  */
-    { 14,  1 }, /* SVE_sz4: 1-bit element size select.  */
-    { 16,  4 }, /* SVE_tsz: triangular size select.  */
-    { 22,  2 }, /* SVE_tszh: triangular size select high, bits [23,22].  */
-    {  8,  2 }, /* SVE_tszl_8: triangular size select low, bits [9,8].  */
-    { 19,  2 }, /* SVE_tszl_19: triangular size select low, bits [20,19].  */
-    { 14,  1 }, /* SVE_xs_14: UXTW/SXTW select (bit 14).  */
-    { 22,  1 }, /* SVE_xs_22: UXTW/SXTW select (bit 22).  */
-    { 22,  1 },        /* S_imm10: in LDRAA and LDRAB instructions.  */
-    { 16,  3 },        /* abc: a:b:c bits in AdvSIMD modified immediate.  */
-    { 13,  3 },        /* asisdlso_opcode: opcode in advsimd ld/st single element.  */
-    { 19,  5 },        /* b40: in the test bit and branch instructions.  */
-    { 31,  1 },        /* b5: in the test bit and branch instructions.  */
-    { 12,  4 },        /* cmode: in advsimd modified immediate instructions.  */
-    { 12,  4 },        /* cond: condition flags as a source operand.  */
-    {  0,  4 },        /* cond2: condition in truly conditional-executed inst.  */
-    {  5,  5 },        /* defgh: d:e:f:g:h bits in AdvSIMD modified immediate.  */
-    { 21,  2 },        /* hw: in move wide constant instructions.  */
-    {  0,  1 },        /* imm1_0: general immediate in bits [0].  */
-    {  2,  1 },        /* imm1_2: general immediate in bits [2].  */
-    {  3,  1 },        /* imm1_3: general immediate in bits [3].  */
-    {  8,  1 },        /* imm1_8: general immediate in bits [8].  */
-    { 10,  1 },        /* imm1_10: general immediate in bits [10].  */
-    { 14,  1 },        /* imm1_14: general immediate in bits [14].  */
-    { 15,  1 },        /* imm1_15: general immediate in bits [15].  */
-    { 16,  1 },        /* imm1_16: general immediate in bits [16].  */
-    {  0,  2 },        /* imm2_0: general immediate in bits [1:0].  */
-    {  1,  2 },        /* imm2_1: general immediate in bits [2:1].  */
-    {  2,  2 },        /* imm2_2: general immediate in bits [3:2].  */
-    {  8,  2 },        /* imm2_8: general immediate in bits [9:8].  */
-    { 10,  2 }, /* imm2_10: 2-bit immediate, bits [11:10] */
-    { 12,  2 }, /* imm2_12: 2-bit immediate, bits [13:12] */
-    { 13,  2 }, /* imm2_13: 2-bit immediate, bits [14:13] */
-    { 15,  2 }, /* imm2_15: 2-bit immediate, bits [16:15] */
-    { 16,  2 }, /* imm2_16: 2-bit immediate, bits [17:16] */
-    { 19,  2 }, /* imm2_19: 2-bit immediate, bits [20:19] */
-    {  0,  3 },        /* imm3_0: general immediate in bits [2:0].  */
-    {  5,  3 },        /* imm3_5: general immediate in bits [7:5].  */
-    { 10,  3 },        /* imm3_10: in add/sub extended reg instructions.  */
-    { 12,  3 },        /* imm3_12: general immediate in bits [14:12].  */
-    { 14,  3 },        /* imm3_14: general immediate in bits [16:14].  */
-    { 15,  3 },        /* imm3_15: general immediate in bits [17:15].  */
-    { 19,  3 },        /* imm3_19: general immediate in bits [21:19].  */
-    {  0,  4 },        /* imm4_0: in rmif instructions.  */
-    {  5,  4 }, /* imm4_5: in SME instructions.  */
-    { 10,  4 },        /* imm4_10: in adddg/subg instructions.  */
-    { 11,  4 },        /* imm4_11: in advsimd ext and advsimd ins instructions.  */
-    { 14,  4 },        /* imm4_14: general immediate in bits [17:14].  */
-    { 16,  5 },        /* imm5: in conditional compare (immediate) instructions.  */
-    { 10,  6 },        /* imm6_10: in add/sub reg shifted instructions.  */
-    { 15,  6 },        /* imm6_15: in rmif instructions.  */
-    { 15,  7 },        /* imm7: in load/store pair pre/post index instructions.  */
-    { 13,  8 },        /* imm8: in floating-point scalar move immediate inst.  */
-    { 12,  9 },        /* imm9: in load/store pre/post index instructions.  */
-    {  5,  9 },        /* imm9_5: in CB<cc> (immediate).  */
-    { 10, 12 },        /* imm12: in ld/st unsigned imm or add/sub shifted inst.  */
-    {  5, 14 },        /* imm14: in test bit and branch instructions.  */
-    {  0, 16 },        /* imm16_0: in udf instruction. */
-    {  5, 16 },        /* imm16_5: in exception instructions.  */
-    { 17,  1 }, /* imm17_1: in 1 bit element index.  */
-    { 17,  2 }, /* imm17_2: in 2 bits element index.  */
-    {  5, 19 },        /* imm19: e.g. in CBZ.  */
-    {  0, 26 },        /* imm26: in unconditional branch instructions.  */
-    { 16,  3 },        /* immb: in advsimd shift by immediate instructions.  */
-    { 19,  4 },        /* immh: in advsimd shift by immediate instructions.  */
-    {  5, 19 },        /* immhi: e.g. in ADRP.  */
-    { 29,  2 },        /* immlo: e.g. in ADRP.  */
-    { 16,  6 },        /* immr: in bitfield and logical immediate instructions.  */
-    { 10,  6 },        /* imms: in bitfield and logical immediate instructions.  */
-    { 11,  1 },        /* index: in ld/st inst deciding the pre/post-index.  */
-    { 24,  1 },        /* index2: in ld/st pair inst deciding the pre/post-index.  */
-    { 30,  2 },        /* ldst_size: size field in ld/st reg offset inst.  */
-    { 13,  2 },        /* len: in advsimd tbl/tbx instructions.  */
-    { 30,  1 },        /* lse_sz: in LSE extension atomic instructions.  */
-    {  0,  4 },        /* nzcv: flag bit specifier, encoded in the "nzcv" field.  */
-    { 29,  1 },        /* op: in AdvSIMD modified immediate instructions.  */
-    { 19,  2 },        /* op0: in the system instructions.  */
-    { 16,  3 },        /* op1: in the system instructions.  */
-    {  5,  3 },        /* op2: in the system instructions.  */
-    { 22,  2 },        /* opc: in load/store reg offset instructions.  */
-    { 23,  1 },        /* opc1: in load/store reg offset instructions.  */
-    { 12,  4 },        /* opcode: in advsimd load/store instructions.  */
-    { 13,  3 },        /* option: in ld/st reg offset + add/sub extended reg inst.  */
-    { 11,  2 }, /* rotate1: FCMLA immediate rotate.  */
-    { 13,  2 }, /* rotate2: Indexed element FCMLA immediate rotate.  */
-    { 12,  1 }, /* rotate3: FCADD immediate rotate.  */
-    { 10,  6 },        /* scale: in the fixed-point scalar to fp converting inst.  */
-    { 31,  1 },        /* sf: in integer data processing instructions.  */
-    { 22,  2 },        /* shift: in add/sub reg/imm shifted instructions.  */
-    { 22,  2 },        /* size: in most AdvSIMD and floating-point instructions.  */
-    { 22,  1 }, /* sz: 1-bit element size select.  */
-    { 22,  2 },        /* type: floating point type field in fp data inst.  */
-    { 10,  2 },        /* vldst_size: size field in the AdvSIMD load/store inst.  */
-    {  5,  3 }, /* off3: immediate offset used to calculate slice number in a
-                  ZA tile.  */
-    {  5,  2 }, /* off2: immediate offset used to calculate slice number in
-                  a ZA tile.  */
-    {  7,  1 }, /* ZAn_1: name of the 1bit encoded ZA tile.  */
-    {  5,  1 }, /* ol: immediate offset used to calculate slice number in a ZA
-                  tile.  */
-    {  6,  2 }, /* ZAn_2: name of the 2bit encoded ZA tile.  */
-    {  5,  3 }, /* ZAn_3: name of the 3bit encoded ZA tile.  */
-    {  6,  1 }, /* ZAn: name of the bit encoded ZA tile.  */
-    { 12,  4 },        /* opc2: in rcpc3 ld/st inst deciding the pre/post-index.  */
-    { 30,  2 },        /* rcpc3_size: in rcpc3 ld/st, field controls Rt/Rt2 width.  */
-    {  5,  1 },        /* FLD_brbop: used in BRB to mean IALL or INJ.  */
-    {  8,  1 }, /* ZA8_1: name of the 1 bit encoded ZA tile ZA0-ZA1.  */
-    {  7,  2 }, /* ZA7_2: name of the 2 bits encoded ZA tile ZA0-ZA3.  */
-    {  6,  3 }, /* ZA6_3: name of the 3 bits encoded ZA tile ZA0-ZA7.  */
-    {  5,  4 }, /* ZA5_4: name of the 4 bits encoded ZA tile ZA0-ZA15.  */
+    AARCH64_FIELD_NIL, /* NIL.  */
+    AARCH64_FIELD_CONST (0, 1),        /* CONST_0.  */
+    AARCH64_FIELD_CONST (1, 1),        /* CONST_1.  */
+    AARCH64_FIELD ( 8, 4), /* CRm: in the system instructions.  */
+    AARCH64_FIELD (10, 2), /* CRm_dsb_nxs: 2-bit imm. encoded in CRm<3:2>.  */
+    AARCH64_FIELD (12, 4), /* CRn: in the system instructions.  */
+    AARCH64_FIELD (10, 8), /* CSSC_imm8.  */
+    AARCH64_FIELD (11, 1), /* H: in advsimd scalar x indexed element instructions.  */
+    AARCH64_FIELD (21, 1), /* L: in advsimd scalar x indexed element instructions.  */
+    AARCH64_FIELD ( 0, 5), /* LSE128_Rt: Shared input+output operand register.  */
+    AARCH64_FIELD (16, 5), /* LSE128_Rt2: Shared input+output operand register 2.  */
+    AARCH64_FIELD (20, 1), /* M: in advsimd scalar x indexed element instructions.  */
+    AARCH64_FIELD (22, 1), /* N: in logical (immediate) instructions.  */
+    AARCH64_FIELD (30, 1), /* Q: in most AdvSIMD instructions.  */
+    AARCH64_FIELD (10, 5), /* Ra: in fp instructions.  */
+    AARCH64_FIELD ( 0, 5), /* Rd: in many integer instructions.  */
+    AARCH64_FIELD (16, 5), /* Rm: in ld/st reg offset and some integer inst.  */
+    AARCH64_FIELD ( 5, 5), /* Rn: in many integer instructions.  */
+    AARCH64_FIELD (16, 5), /* Rs: in load/store exclusive instructions.  */
+    AARCH64_FIELD ( 0, 5), /* Rt: in load/store instructions.  */
+    AARCH64_FIELD (10, 5), /* Rt2: in load/store pair instructions.  */
+    AARCH64_FIELD (12, 1), /* S: in load/store reg offset instructions.  */
+    AARCH64_FIELD (12, 2), /* SM3_imm2: Indexed element SM3 2 bits index immediate.  */
+    AARCH64_FIELD ( 1, 3), /* SME_Pdx2: predicate register, multiple of 2, [3:1].  */
+    AARCH64_FIELD (13, 3), /* SME_Pm: second source scalable predicate register P0-P7.  */
+    AARCH64_FIELD ( 0, 3), /* SME_PNd3: PN0-PN7, bits [2:0].  */
+    AARCH64_FIELD ( 5, 3), /* SME_PNn3: PN0-PN7, bits [7:5].  */
+    AARCH64_FIELD (16, 1), /* SME_Q: Q class bit, bit 16.  */
+    AARCH64_FIELD (16, 2), /* SME_Rm: index base register W12-W15 [17:16].  */
+    AARCH64_FIELD (13, 2), /* SME_Rv: vector select register W12-W15, bits [14:13].  */
+    AARCH64_FIELD (15, 1), /* SME_V: (horizontal / vertical tiles), bit 15.  */
+    AARCH64_FIELD (10, 1), /* SME_VL_10: VLx2 or VLx4, bit [10].  */
+    AARCH64_FIELD (13, 1), /* SME_VL_13: VLx2 or VLx4, bit [13].  */
+    AARCH64_FIELD ( 0, 1), /* SME_ZAda_1b: tile ZA0-ZA1.  */
+    AARCH64_FIELD ( 0, 2), /* SME_ZAda_2b: tile ZA0-ZA3.  */
+    AARCH64_FIELD ( 0, 3), /* SME_ZAda_3b: tile ZA0-ZA7.  */
+    AARCH64_FIELD ( 1, 4), /* SME_Zdn2: Z0-Z31, multiple of 2, bits [4:1].  */
+    AARCH64_FIELD ( 2, 3), /* SME_Zdn4: Z0-Z31, multiple of 4, bits [4:2].  */
+    AARCH64_FIELD (16, 4), /* SME_Zm: Z0-Z15, bits [19:16].  */
+    AARCH64_FIELD (17, 4), /* SME_Zm2: Z0-Z31, multiple of 2, bits [20:17].  */
+    AARCH64_FIELD (18, 3), /* SME_Zm4: Z0-Z31, multiple of 4, bits [20:18].  */
+    AARCH64_FIELD ( 6, 4), /* SME_Zn2: Z0-Z31, multiple of 2, bits [9:6].  */
+    AARCH64_FIELD ( 7, 3), /* SME_Zn4: Z0-Z31, multiple of 4, bits [9:7].  */
+    AARCH64_FIELD ( 4, 1), /* SME_ZtT: upper bit of Zt, bit [4].  */
+    AARCH64_FIELD ( 0, 3), /* SME_Zt3: lower 3 bits of Zt, bits [2:0].  */
+    AARCH64_FIELD ( 0, 2), /* SME_Zt2: lower 2 bits of Zt, bits [1:0].  */
+    AARCH64_FIELD (23, 1), /* SME_i1: immediate field, bit 23.  */
+    AARCH64_FIELD (12, 2), /* SME_size_12: bits [13:12].  */
+    AARCH64_FIELD (22, 2), /* SME_size_22: size<1>, size<0> class field, [23:22].  */
+    AARCH64_FIELD (23, 1), /* SME_sz_23: bit [23].  */
+    AARCH64_FIELD (22, 1), /* SME_tszh: immediate and qualifier field, bit 22.  */
+    AARCH64_FIELD (18, 3), /* SME_tszl: immediate and qualifier field, bits [20:18].  */
+    AARCH64_FIELD (0,  8), /* SME_zero_mask: list of up to 8 tile names separated by commas [7:0].  */
+    AARCH64_FIELD ( 4, 1), /* SVE_M_4: Merge/zero select, bit 4.  */
+    AARCH64_FIELD (14, 1), /* SVE_M_14: Merge/zero select, bit 14.  */
+    AARCH64_FIELD (16, 1), /* SVE_M_16: Merge/zero select, bit 16.  */
+    AARCH64_FIELD (17, 1), /* SVE_N: SVE equivalent of N.  */
+    AARCH64_FIELD ( 0, 4), /* SVE_Pd: p0-p15, bits [3,0].  */
+    AARCH64_FIELD (10, 3), /* SVE_Pg3: p0-p7, bits [12,10].  */
+    AARCH64_FIELD ( 5, 4), /* SVE_Pg4_5: p0-p15, bits [8,5].  */
+    AARCH64_FIELD (10, 4), /* SVE_Pg4_10: p0-p15, bits [13,10].  */
+    AARCH64_FIELD (16, 4), /* SVE_Pg4_16: p0-p15, bits [19,16].  */
+    AARCH64_FIELD (16, 4), /* SVE_Pm: p0-p15, bits [19,16].  */
+    AARCH64_FIELD ( 5, 4), /* SVE_Pn: p0-p15, bits [8,5].  */
+    AARCH64_FIELD ( 0, 4), /* SVE_Pt: p0-p15, bits [3,0].  */
+    AARCH64_FIELD ( 5, 5), /* SVE_Rm: SVE alternative position for Rm.  */
+    AARCH64_FIELD (16, 5), /* SVE_Rn: SVE alternative position for Rn.  */
+    AARCH64_FIELD ( 0, 5), /* SVE_Vd: Scalar SIMD&FP register, bits [4,0].  */
+    AARCH64_FIELD ( 5, 5), /* SVE_Vm: Scalar SIMD&FP register, bits [9,5].  */
+    AARCH64_FIELD ( 5, 5), /* SVE_Vn: Scalar SIMD&FP register, bits [9,5].  */
+    AARCH64_FIELD ( 5, 5), /* SVE_Za_5: SVE vector register, bits [9,5].  */
+    AARCH64_FIELD (16, 5), /* SVE_Za_16: SVE vector register, bits [20,16].  */
+    AARCH64_FIELD ( 0, 5), /* SVE_Zd: SVE vector register. bits [4,0].  */
+    AARCH64_FIELD ( 5, 5), /* SVE_Zm_5: SVE vector register, bits [9,5].  */
+    AARCH64_FIELD (16, 5), /* SVE_Zm_16: SVE vector register, bits [20,16]. */
+    AARCH64_FIELD ( 5, 5), /* SVE_Zn: SVE vector register, bits [9,5].  */
+    AARCH64_FIELD ( 0, 5), /* SVE_Zt: SVE vector register, bits [4,0].  */
+    AARCH64_FIELD ( 5, 1), /* SVE_i1: single-bit immediate.  */
+    AARCH64_FIELD (23, 1), /* SVE_i1_23: single-bit immediate.  */
+    AARCH64_FIELD (22, 2), /* SVE_i2: 2-bit index, bits [23,22].  */
+    AARCH64_FIELD (20, 1), /* SVE_i2h: high bit of 2bit immediate, bits.  */
+    AARCH64_FIELD (22, 1), /* SVE_i3h: high bit of 3-bit immediate.  */
+    AARCH64_FIELD (19, 2), /* SVE_i3h2: two high bits of 3bit immediate, bits [20,19].  */
+    AARCH64_FIELD (22, 2), /* SVE_i3h3: two high bits of 3bit immediate, bits [22,23].  */
+    AARCH64_FIELD (11, 1), /* SVE_i3l: low bit of 3-bit immediate.  */
+    AARCH64_FIELD (12, 1), /* SVE_i3l2: low bit of 3-bit immediate, bit 12.  */
+    AARCH64_FIELD (10, 2), /* SVE_i4l2: two low bits of 4bit immediate, bits [11,10].  */
+    AARCH64_FIELD (16, 3), /* SVE_imm3: 3-bit immediate field.  */
+    AARCH64_FIELD (16, 4), /* SVE_imm4: 4-bit immediate field.  */
+    AARCH64_FIELD ( 5, 5), /* SVE_imm5: 5-bit immediate field.  */
+    AARCH64_FIELD (16, 5), /* SVE_imm5b: secondary 5-bit immediate field.  */
+    AARCH64_FIELD (16, 6), /* SVE_imm6: 6-bit immediate field.  */
+    AARCH64_FIELD (14, 7), /* SVE_imm7: 7-bit immediate field.  */
+    AARCH64_FIELD ( 5, 8), /* SVE_imm8: 8-bit immediate field.  */
+    AARCH64_FIELD ( 5, 9), /* SVE_imm9: 9-bit immediate field.  */
+    AARCH64_FIELD (11, 6), /* SVE_immr: SVE equivalent of immr.  */
+    AARCH64_FIELD ( 5, 6), /* SVE_imms: SVE equivalent of imms.  */
+    AARCH64_FIELD (10, 2), /* SVE_msz: 2-bit shift amount for ADR.  */
+    AARCH64_FIELD ( 5, 5), /* SVE_pattern: vector pattern enumeration.  */
+    AARCH64_FIELD ( 0, 4), /* SVE_prfop: prefetch operation for SVE PRF[BHWD].  */
+    AARCH64_FIELD (16, 1), /* SVE_rot1: 1-bit rotation amount.  */
+    AARCH64_FIELD (10, 2), /* SVE_rot2: 2-bit rotation amount.  */
+    AARCH64_FIELD (10, 1), /* SVE_rot3: 1-bit rotation amount at bit 10.  */
+    AARCH64_FIELD (17, 2), /* SVE_size: 2-bit element size, bits [18,17].  */
+    AARCH64_FIELD (22, 1), /* SVE_sz: 1-bit element size select.  */
+    AARCH64_FIELD (30, 1), /* SVE_sz2: 1-bit element size select.  */
+    AARCH64_FIELD (17, 1), /* SVE_sz3: 1-bit element size select.  */
+    AARCH64_FIELD (14, 1), /* SVE_sz4: 1-bit element size select.  */
+    AARCH64_FIELD (16, 4), /* SVE_tsz: triangular size select.  */
+    AARCH64_FIELD (22, 2), /* SVE_tszh: triangular size select high, bits [23,22].  */
+    AARCH64_FIELD ( 8, 2), /* SVE_tszl_8: triangular size select low, bits [9,8].  */
+    AARCH64_FIELD (19, 2), /* SVE_tszl_19: triangular size select low, bits [20,19].  */
+    AARCH64_FIELD (14, 1), /* SVE_xs_14: UXTW/SXTW select (bit 14).  */
+    AARCH64_FIELD (22, 1), /* SVE_xs_22: UXTW/SXTW select (bit 22).  */
+    AARCH64_FIELD (22, 1), /* S_imm10: in LDRAA and LDRAB instructions.  */
+    AARCH64_FIELD (16, 3), /* abc: a:b:c bits in AdvSIMD modified immediate.  */
+    AARCH64_FIELD (13, 3), /* asisdlso_opcode: opcode in advsimd ld/st single element.  */
+    AARCH64_FIELD (19, 5), /* b40: in the test bit and branch instructions.  */
+    AARCH64_FIELD (31, 1), /* b5: in the test bit and branch instructions.  */
+    AARCH64_FIELD (12, 4), /* cmode: in advsimd modified immediate instructions.  */
+    AARCH64_FIELD (12, 4), /* cond: condition flags as a source operand.  */
+    AARCH64_FIELD ( 0, 4), /* cond2: condition in truly conditional-executed inst.  */
+    AARCH64_FIELD ( 5, 5), /* defgh: d:e:f:g:h bits in AdvSIMD modified immediate.  */
+    AARCH64_FIELD (21, 2), /* hw: in move wide constant instructions.  */
+    AARCH64_FIELD ( 0, 1), /* imm1_0: general immediate in bits [0].  */
+    AARCH64_FIELD ( 2, 1), /* imm1_2: general immediate in bits [2].  */
+    AARCH64_FIELD ( 3, 1), /* imm1_3: general immediate in bits [3].  */
+    AARCH64_FIELD ( 8, 1), /* imm1_8: general immediate in bits [8].  */
+    AARCH64_FIELD (10, 1), /* imm1_10: general immediate in bits [10].  */
+    AARCH64_FIELD (14, 1), /* imm1_14: general immediate in bits [14].  */
+    AARCH64_FIELD (15, 1), /* imm1_15: general immediate in bits [15].  */
+    AARCH64_FIELD (16, 1), /* imm1_16: general immediate in bits [16].  */
+    AARCH64_FIELD ( 0, 2), /* imm2_0: general immediate in bits [1:0].  */
+    AARCH64_FIELD ( 1, 2), /* imm2_1: general immediate in bits [2:1].  */
+    AARCH64_FIELD ( 2, 2), /* imm2_2: general immediate in bits [3:2].  */
+    AARCH64_FIELD ( 8, 2), /* imm2_8: general immediate in bits [9:8].  */
+    AARCH64_FIELD (10, 2), /* imm2_10: 2-bit immediate, bits [11:10] */
+    AARCH64_FIELD (12, 2), /* imm2_12: 2-bit immediate, bits [13:12] */
+    AARCH64_FIELD (13, 2), /* imm2_13: 2-bit immediate, bits [14:13] */
+    AARCH64_FIELD (15, 2), /* imm2_15: 2-bit immediate, bits [16:15] */
+    AARCH64_FIELD (16, 2), /* imm2_16: 2-bit immediate, bits [17:16] */
+    AARCH64_FIELD (19, 2), /* imm2_19: 2-bit immediate, bits [20:19] */
+    AARCH64_FIELD ( 0, 3), /* imm3_0: general immediate in bits [2:0].  */
+    AARCH64_FIELD ( 5, 3), /* imm3_5: general immediate in bits [7:5].  */
+    AARCH64_FIELD (10, 3), /* imm3_10: in add/sub extended reg instructions.  */
+    AARCH64_FIELD (12, 3), /* imm3_12: general immediate in bits [14:12].  */
+    AARCH64_FIELD (14, 3), /* imm3_14: general immediate in bits [16:14].  */
+    AARCH64_FIELD (15, 3), /* imm3_15: general immediate in bits [17:15].  */
+    AARCH64_FIELD (19, 3), /* imm3_19: general immediate in bits [21:19].  */
+    AARCH64_FIELD ( 0, 4), /* imm4_0: in rmif instructions.  */
+    AARCH64_FIELD ( 5, 4), /* imm4_5: in SME instructions.  */
+    AARCH64_FIELD (10, 4), /* imm4_10: in adddg/subg instructions.  */
+    AARCH64_FIELD (11, 4), /* imm4_11: in advsimd ext and advsimd ins instructions.  */
+    AARCH64_FIELD (14, 4), /* imm4_14: general immediate in bits [17:14].  */
+    AARCH64_FIELD (16, 5), /* imm5: in conditional compare (immediate) instructions.  */
+    AARCH64_FIELD (10, 6), /* imm6_10: in add/sub reg shifted instructions.  */
+    AARCH64_FIELD (15, 6), /* imm6_15: in rmif instructions.  */
+    AARCH64_FIELD (15, 7), /* imm7: in load/store pair pre/post index instructions.  */
+    AARCH64_FIELD (13, 8), /* imm8: in floating-point scalar move immediate inst.  */
+    AARCH64_FIELD (12, 9), /* imm9: in load/store pre/post index instructions.  */
+    AARCH64_FIELD ( 5, 9), /* imm9_5: in CB<cc> (immediate).  */
+    AARCH64_FIELD (10,12), /* imm12: in ld/st unsigned imm or add/sub shifted inst.  */
+    AARCH64_FIELD ( 5,14), /* imm14: in test bit and branch instructions.  */
+    AARCH64_FIELD ( 0,16), /* imm16_0: in udf instruction. */
+    AARCH64_FIELD ( 5,16), /* imm16_5: in exception instructions.  */
+    AARCH64_FIELD (17, 1), /* imm17_1: in 1 bit element index.  */
+    AARCH64_FIELD (17, 2), /* imm17_2: in 2 bits element index.  */
+    AARCH64_FIELD ( 5,19), /* imm19: e.g. in CBZ.  */
+    AARCH64_FIELD ( 0,26), /* imm26: in unconditional branch instructions.  */
+    AARCH64_FIELD (16, 3), /* immb: in advsimd shift by immediate instructions.  */
+    AARCH64_FIELD (19, 4), /* immh: in advsimd shift by immediate instructions.  */
+    AARCH64_FIELD ( 5,19), /* immhi: e.g. in ADRP.  */
+    AARCH64_FIELD (29, 2), /* immlo: e.g. in ADRP.  */
+    AARCH64_FIELD (16, 6), /* immr: in bitfield and logical immediate instructions.  */
+    AARCH64_FIELD (10, 6), /* imms: in bitfield and logical immediate instructions.  */
+    AARCH64_FIELD (11, 1), /* index: in ld/st inst deciding the pre/post-index.  */
+    AARCH64_FIELD (24, 1), /* index2: in ld/st pair inst deciding the pre/post-index.  */
+    AARCH64_FIELD (30, 2), /* ldst_size: size field in ld/st reg offset inst.  */
+    AARCH64_FIELD (13, 2), /* len: in advsimd tbl/tbx instructions.  */
+    AARCH64_FIELD (30, 1), /* lse_sz: in LSE extension atomic instructions.  */
+    AARCH64_FIELD ( 0, 4), /* nzcv: flag bit specifier, encoded in the "nzcv" field.  */
+    AARCH64_FIELD (29, 1), /* op: in AdvSIMD modified immediate instructions.  */
+    AARCH64_FIELD (19, 2), /* op0: in the system instructions.  */
+    AARCH64_FIELD (16, 3), /* op1: in the system instructions.  */
+    AARCH64_FIELD ( 5, 3), /* op2: in the system instructions.  */
+    AARCH64_FIELD (22, 2), /* opc: in load/store reg offset instructions.  */
+    AARCH64_FIELD (23, 1), /* opc1: in load/store reg offset instructions.  */
+    AARCH64_FIELD (12, 4), /* opcode: in advsimd load/store instructions.  */
+    AARCH64_FIELD (13, 3), /* option: in ld/st reg offset + add/sub extended reg inst.  */
+    AARCH64_FIELD (11, 2), /* rotate1: FCMLA immediate rotate.  */
+    AARCH64_FIELD (13, 2), /* rotate2: Indexed element FCMLA immediate rotate.  */
+    AARCH64_FIELD (12, 1), /* rotate3: FCADD immediate rotate.  */
+    AARCH64_FIELD (10, 6), /* scale: in the fixed-point scalar to fp converting inst.  */
+    AARCH64_FIELD (31, 1), /* sf: in integer data processing instructions.  */
+    AARCH64_FIELD (22, 2), /* shift: in add/sub reg/imm shifted instructions.  */
+    AARCH64_FIELD (22, 2), /* size: in most AdvSIMD and floating-point instructions.  */
+    AARCH64_FIELD (22, 1), /* sz: 1-bit element size select.  */
+    AARCH64_FIELD (22, 2), /* type: floating point type field in fp data inst.  */
+    AARCH64_FIELD (10, 2), /* vldst_size: size field in the AdvSIMD load/store inst.  */
+    AARCH64_FIELD ( 5, 3), /* off3: immediate offset used to calculate slice number in a ZA tile.  */
+    AARCH64_FIELD ( 5, 2), /* off2: immediate offset used to calculate slice number in a ZA tile.  */
+    AARCH64_FIELD ( 7, 1), /* ZAn_1: name of the 1bit encoded ZA tile.  */
+    AARCH64_FIELD ( 5, 1), /* ol: immediate offset used to calculate slice number in a ZA tile. */
+    AARCH64_FIELD ( 6, 2), /* ZAn_2: name of the 2bit encoded ZA tile.  */
+    AARCH64_FIELD ( 5, 3), /* ZAn_3: name of the 3bit encoded ZA tile.  */
+    AARCH64_FIELD ( 6, 1), /* ZAn: name of the bit encoded ZA tile.  */
+    AARCH64_FIELD (12, 4), /* opc2: in rcpc3 ld/st inst deciding the pre/post-index.  */
+    AARCH64_FIELD (30, 2), /* rcpc3_size: in rcpc3 ld/st, field controls Rt/Rt2 width.  */
+    AARCH64_FIELD ( 5, 1), /* FLD_brbop: used in BRB to mean IALL or INJ.  */
+    AARCH64_FIELD ( 8, 1), /* ZA8_1: name of the 1 bit encoded ZA tile ZA0-ZA1.  */
+    AARCH64_FIELD ( 7, 2), /* ZA7_2: name of the 2 bits encoded ZA tile ZA0-ZA3.  */
+    AARCH64_FIELD ( 6, 3), /* ZA6_3: name of the 3 bits encoded ZA tile ZA0-ZA7.  */
+    AARCH64_FIELD ( 5, 4), /* ZA5_4: name of the 4 bits encoded ZA tile ZA0-ZA15.  */
 };
 
 enum aarch64_operand_class
index 4182c9d5f678beac3a240e08c9842e8620a32bb6..7dbc00f64e49a521f68751fef48f74c8bdf4d00a 100644 (file)
@@ -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,15 +244,41 @@ enum aarch64_field_kind
   FLD_ZA5_4,
 };
 
-/* Field description.  */
+/* Field description.
+
+   If is_const is false, this identifies a bitfield in an instruction encoding
+   that has size WIDTH and has its least significant bit at position NUM.
+
+   If is_const is true, this represents the constant bit string of size WIDTH
+   bits stored in the least significant bits of NUM.  In this case, the
+   leading 8-WIDTH bits of VALUE must be zero.
+
+   A sequence of fields can be used to describe how instruction operands are
+   represented in the 32-bit instruction encoding.
+
+   For example, consider an instruction operand Zd that is an even numbered
+   register in z16-z30, with the middle three bits of the register number
+   stored in bits [19:17] of the encoding.  The register number can then be
+   constructed by concatenating:
+   - a constant bit '1' (represented here as {1, 1, true}),
+   - bits [19:17] of the encoding (represented here as {3, 17, false}), and
+   - a constant bit '0' (represented here as {1, 0, true}).
+   This sequence of fields fully describes both the constraints on which
+   register numbers are valid, and how valid register numbers are represented
+   in the instruction encoding.  */
 struct aarch64_field
 {
-  int lsb;
-  int width;
+  unsigned int width:8;
+  unsigned int num:7;
+  bool is_const:1;
 };
 
 typedef struct aarch64_field aarch64_field;
 
+#define AARCH64_FIELD(lsb, width) {width, lsb, false}
+#define AARCH64_FIELD_CONST(val, width) {width, val, true}
+#define AARCH64_FIELD_NIL {0, 0, false}
+
 extern const aarch64_field aarch64_fields[];
 \f
 /* Operand description.  */
@@ -484,7 +512,7 @@ gen_sub_field (enum aarch64_field_kind kind, int lsb_rel, int width, aarch64_fie
   const aarch64_field *field = &aarch64_fields[kind];
   if (lsb_rel < 0 || width <= 0 || lsb_rel + width > field->width)
     return 0;
-  ret->lsb = field->lsb + lsb_rel;
+  ret->num = field->num + lsb_rel;
   ret->width = width;
   return 1;
 }
@@ -496,10 +524,16 @@ static inline void
 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);
+  assert (field->width < 32 && field->width >= 1
+         && (field->is_const ? (field->num < 1 << field->width)
+                             : (field->num + field->width <= 32)));
   value &= gen_mask (field->width);
-  value <<= field->lsb;
+  if (field->is_const)
+    {
+      assert (value == field->num);
+      return;
+    }
+  value <<= field->num;
   /* 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.  */
   value &= ~mask;
@@ -514,9 +548,13 @@ extract_field_2 (const aarch64_field *field, aarch64_insn code,
                 aarch64_insn mask)
 {
   aarch64_insn value;
+  /* Check for constant field.  */
+  if (field->is_const)
+    return field->num;
+
   /* Clear any bit that is a part of the base opcode.  */
   code &= ~mask;
-  value = (code >> field->lsb) & gen_mask (field->width);
+  value = (code >> field->num) & gen_mask (field->width);
   return value;
 }