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

Richard Earnshaw (lists) Richard.Earnshaw@arm.com
Wed Oct 8 10:17:21 GMT 2025


On 08/10/2025 01:38, Alice Carlotti wrote:
> 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.

I'm likely missing something, but it would be nice if there were some explanation of how to use this feature in the comments.

For example, how would I express a even numbered register? an odd-numbered register or a register in the first 16 of a 32-register set?  Can I express things like an odd numbered register that is in the range 0-16 (ie one bit set and one bit clear)?

R.

> 
> 
> 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