[PATCH v3] aarch64: Support for FEAT_CMPBR

Alice Carlotti alice.carlotti@arm.com
Wed May 7 16:22:54 GMT 2025


On Wed, May 07, 2025 at 02:23:02PM +0100, Ezra.Sitorus@arm.com wrote:
> From: Ezra Sitorus <ezra.sitorus@arm.com>
> 
> FEAT_CMPBR - Compare and branch instructions. This patch adds these
> instructions:
> - CB<CC> (register)
> - CB<CC> (immediate)
> - CBH<CC>
> - CBB<CC>
> 
> where CC is one of the following:
> - EQ
> - NE
> - GT
> - GE
> - LT
> - LE
> - HI
> - HS
> - LO
> - LS
> ---
> Regression tested on aarch64-none-linux-gnu. Comments from v2 have been
> addressed in this version. Can somebody commit this if it looks OK?

Thanks for the changes; I have just a few testsuite nits/suggestions to
mention.

> 
> Ezra
> 
>  bfd/elfnn-aarch64.c                     |   3 +
>  bfd/reloc.c                             |   6 ++
>  gas/config/tc-aarch64.c                 |  42 +++++++++-
>  gas/doc/c-aarch64.texi                  |   2 +
>  gas/testsuite/gas/aarch64/cmpbr-1.d     |  67 +++++++++++++++
>  gas/testsuite/gas/aarch64/cmpbr-1.s     |  59 ++++++++++++++
>  gas/testsuite/gas/aarch64/cmpbr-bad-1.d |   4 +
>  gas/testsuite/gas/aarch64/cmpbr-bad-1.l |   3 +
>  gas/testsuite/gas/aarch64/cmpbr-bad-1.s |   3 +
>  gas/testsuite/gas/aarch64/cmpbr-bad.d   |   4 +
>  gas/testsuite/gas/aarch64/cmpbr-bad.l   |  13 +++
>  gas/testsuite/gas/aarch64/cmpbr-bad.s   |   5 ++
>  gas/testsuite/gas/aarch64/cmpbr-far.d   |   4 +
>  gas/testsuite/gas/aarch64/cmpbr-far.l   |   3 +
>  gas/testsuite/gas/aarch64/cmpbr-far.s   |  11 +++
>  gas/testsuite/gas/aarch64/cmpbr.d       | 103 ++++++++++++++++++++++++
>  gas/testsuite/gas/aarch64/cmpbr.s       |  90 +++++++++++++++++++++
>  include/opcode/aarch64.h                |   5 ++
>  opcodes/aarch64-opc.c                   |   3 +
>  opcodes/aarch64-opc.h                   |   1 +
>  opcodes/aarch64-tbl.h                   |  66 +++++++++++++++
>  21 files changed, 495 insertions(+), 2 deletions(-)
>  create mode 100644 gas/testsuite/gas/aarch64/cmpbr-1.d
>  create mode 100644 gas/testsuite/gas/aarch64/cmpbr-1.s
>  create mode 100644 gas/testsuite/gas/aarch64/cmpbr-bad-1.d
>  create mode 100644 gas/testsuite/gas/aarch64/cmpbr-bad-1.l
>  create mode 100644 gas/testsuite/gas/aarch64/cmpbr-bad-1.s
>  create mode 100644 gas/testsuite/gas/aarch64/cmpbr-bad.d
>  create mode 100644 gas/testsuite/gas/aarch64/cmpbr-bad.l
>  create mode 100644 gas/testsuite/gas/aarch64/cmpbr-bad.s
>  create mode 100644 gas/testsuite/gas/aarch64/cmpbr-far.d
>  create mode 100644 gas/testsuite/gas/aarch64/cmpbr-far.l
>  create mode 100644 gas/testsuite/gas/aarch64/cmpbr-far.s
>  create mode 100644 gas/testsuite/gas/aarch64/cmpbr.d
>  create mode 100644 gas/testsuite/gas/aarch64/cmpbr.s
> 
> diff --git a/bfd/elfnn-aarch64.c b/bfd/elfnn-aarch64.c
> index 548da1f8b30..8f399204f04 100644
> --- a/bfd/elfnn-aarch64.c
> +++ b/bfd/elfnn-aarch64.c
> @@ -2268,6 +2268,9 @@ elfNN_aarch64_howto_from_bfd_reloc (bfd_reloc_code_real_type code)
>    if (code == BFD_RELOC_AARCH64_NONE)
>      return &elfNN_aarch64_howto_none;
>  
> +  if (code == BFD_RELOC_AARCH64_BRANCH9)
> +    return &elfNN_aarch64_howto_none;
> +
>    return NULL;
>  }
>  
> diff --git a/bfd/reloc.c b/bfd/reloc.c
> index d3ddafb7305..c9d53bb9e11 100644
> --- a/bfd/reloc.c
> +++ b/bfd/reloc.c
> @@ -7418,6 +7418,12 @@ ENUM
>  ENUMDOC
>    AArch64 pseudo relocation code to be used internally by the AArch64
>    assembler and not (currently) written to any object files.
> +ENUM
> +  BFD_RELOC_AARCH64_BRANCH9
> +ENUMDOC
> +  AArch64 9 bit pc-relative conditional branch and compare & branch.
> +  The lowest two bits must be zero and are not stored in the
> +  instruction, giving an 11 bit signed byte offset.
>  ENUM
>    BFD_RELOC_TILEPRO_COPY
>  ENUMX
> diff --git a/gas/config/tc-aarch64.c b/gas/config/tc-aarch64.c
> index acb56044fb5..e6bd6a7e2f9 100644
> --- a/gas/config/tc-aarch64.c
> +++ b/gas/config/tc-aarch64.c
> @@ -5175,6 +5175,13 @@ encode_branch_ofs_26 (uint32_t ofs)
>    return ofs & ((1 << 26) - 1);
>  }
>  
> +/* encode the 9-bit offset of FEAT_CMPBR compare and branch */
> +static inline uint32_t
> +encode_cond_branch_ofs_9 (uint32_t ofs)
> +{
> +  return (ofs & ((1 << 9) - 1)) << 5;
> +}
> +
>  /* encode the 19-bit offset of conditional branch and compare & branch */
>  static inline uint32_t
>  encode_cond_branch_ofs_19 (uint32_t ofs)
> @@ -6388,6 +6395,8 @@ process_omitted_operand (enum aarch64_opnd type, const aarch64_opcode *opcode,
>      case AARCH64_OPND_UIMM3_OP2:
>      case AARCH64_OPND_IMM:
>      case AARCH64_OPND_IMM_2:
> +    case AARCH64_OPND_IMMP1_2:
> +    case AARCH64_OPND_IMMS1_2:
>      case AARCH64_OPND_WIDTH:
>      case AARCH64_OPND_UIMM7:
>      case AARCH64_OPND_NZCV:
> @@ -7154,6 +7163,16 @@ parse_operands (char *str, const aarch64_opcode *opcode)
>  	  info->imm.value = val;
>  	  break;
>  
> +	case AARCH64_OPND_IMMP1_2:
> +	  po_imm_or_fail (1, 64);
> +	  info->imm.value = val - 1;
> +	  break;
> +
> +	case AARCH64_OPND_IMMS1_2:
> +	  po_imm_or_fail (-1, 62);
> +	  info->imm.value = val + 1;
> +	  break;
> +
>  	case AARCH64_OPND_SVE_AIMM:
>  	case AARCH64_OPND_SVE_ASIMM:
>  	  po_imm_nc_or_fail ();
> @@ -7450,6 +7469,7 @@ parse_operands (char *str, const aarch64_opcode *opcode)
>  	  info->imm.value = 0;
>  	  break;
>  
> +	case AARCH64_OPND_ADDR_PCREL9:
>  	case AARCH64_OPND_ADDR_PCREL14:
>  	case AARCH64_OPND_ADDR_PCREL19:
>  	case AARCH64_OPND_ADDR_PCREL21:
> @@ -7487,8 +7507,11 @@ parse_operands (char *str, const aarch64_opcode *opcode)
>  		  case compbranch:
>  		  case condbranch:
>  		    /* e.g. CBZ or B.COND  */
> -		    gas_assert (operands[i] == AARCH64_OPND_ADDR_PCREL19);
> -		    inst.reloc.type = BFD_RELOC_AARCH64_BRANCH19;
> +		    gas_assert (operands[i] == AARCH64_OPND_ADDR_PCREL9
> +		                || operands[i] == AARCH64_OPND_ADDR_PCREL19);
> +		    inst.reloc.type = (operands[i] == AARCH64_OPND_ADDR_PCREL9)
> +		                       ? BFD_RELOC_AARCH64_BRANCH9
> +		                       : BFD_RELOC_AARCH64_BRANCH19;
>  		    break;
>  		  case testbranch:
>  		    /* e.g. TBZ  */
> @@ -9670,6 +9693,20 @@ md_apply_fix (fixS * fixP, valueT * valP, segT seg)
>  	}
>        break;
>  
> +    case BFD_RELOC_AARCH64_BRANCH9:
> +      if (fixP->fx_done || !seg->use_rela_p)
> +	{
> +	  if (value & 3)
> +	    as_bad_where (fixP->fx_file, fixP->fx_line,
> +			  _("conditional branch target not word aligned"));
> +	  if (signed_overflow (value, 11))
> +	    as_bad_where (fixP->fx_file, fixP->fx_line,
> +			  _("conditional branch out of range"));
> +	  insn = get_aarch64_insn (buf);
> +	  insn |= encode_cond_branch_ofs_9 (value >> 2);
> +	  put_aarch64_insn (buf, insn);
> +	}
> +        break;
>      case BFD_RELOC_AARCH64_BRANCH19:
>        if (fixP->fx_done || !seg->use_rela_p)
>  	{
> @@ -10672,6 +10709,7 @@ static const struct aarch64_option_cpu_value_table aarch64_features[] = {
>    {"rng",		AARCH64_FEATURE (RNG), AARCH64_NO_FEATURES},
>    {"ssbs",		AARCH64_FEATURE (SSBS), AARCH64_NO_FEATURES},
>    {"memtag",		AARCH64_FEATURE (MEMTAG), AARCH64_NO_FEATURES},
> +  {"cmpbr",		AARCH64_FEATURE (CMPBR), AARCH64_NO_FEATURES},
>    {"sve2",		AARCH64_FEATURE (SVE2), AARCH64_FEATURE (SVE)},
>    {"sve2-sm4",		AARCH64_FEATURE (SVE2_SM4),
>  			AARCH64_FEATURES (2, SVE2, SM4)},
> diff --git a/gas/doc/c-aarch64.texi b/gas/doc/c-aarch64.texi
> index 10888d1e78f..3a8e2819c5b 100644
> --- a/gas/doc/c-aarch64.texi
> +++ b/gas/doc/c-aarch64.texi
> @@ -167,6 +167,8 @@ automatically cause those extensions to be disabled.
>   @tab Enable the Branch Record Buffer extension.
>  @item @code{chk} @tab
>   @tab Enable the Check Feature Status Extension.
> +@item @code{cmpbr} @tab
> + @tab Enable Compare and Branch instructions.
>  @item @code{compnum} @tab @code{simd}
>   @tab Enable the complex number SIMD extensions.  An alias of @code{fcma}.
>  @item @code{cpa} @tab
> diff --git a/gas/testsuite/gas/aarch64/cmpbr-1.d b/gas/testsuite/gas/aarch64/cmpbr-1.d
> new file mode 100644
> index 00000000000..91b162c1b1c
> --- /dev/null
> +++ b/gas/testsuite/gas/aarch64/cmpbr-1.d
> @@ -0,0 +1,67 @@
> +#name: Test for FEAT_CMPBR pseudo-instructions
> +#as: -march=armv8-a+cmpbr
> +#objdump: -dr
> +
> +.*:     file format .*
> +
> +Disassembly of section .text:
> +
> +.* <a>:
> +.*:	741e0000 	cbgt	w0, w30, 0 <a>
> +.*:	741e3fe0 	cbgt	w0, w30, 0 <a>
> +.*:	743e3fc0 	cbge	w0, w30, 0 <a>
> +.*:	743e3fa0 	cbge	w0, w30, 0 <a>
> +.*:	745e3f80 	cbhi	w0, w30, 0 <a>
> +.*:	745e3f60 	cbhi	w0, w30, 0 <a>
> +.*:	747e3f40 	cbhs	w0, w30, 0 <a>
> +.*:	747e3f20 	cbhs	w0, w30, 0 <a>
> +
> +.* <b>:
> +.*:	f41e0000 	cbgt	x0, x30, 20 <b>
> +.*:	f41e3fe0 	cbgt	x0, x30, 20 <b>
> +.*:	f43e3fc0 	cbge	x0, x30, 20 <b>
> +.*:	f43e3fa0 	cbge	x0, x30, 20 <b>
> +.*:	f45e3f80 	cbhi	x0, x30, 20 <b>
> +.*:	f45e3f60 	cbhi	x0, x30, 20 <b>
> +.*:	f47e3f40 	cbhs	x0, x30, 20 <b>
> +.*:	f47e3f20 	cbhs	x0, x30, 20 <b>
> +
> +.* <c>:
> +.*:	75050000 	cbgt	w0, #10, 40 <c>
> +.*:	75053fe0 	cbgt	w0, #10, 40 <c>
> +.*:	75263fc0 	cblt	w0, #12, 40 <c>
> +.*:	75263fa0 	cblt	w0, #12, 40 <c>
> +.*:	75453f80 	cbhi	w0, #10, 40 <c>
> +.*:	75453f60 	cbhi	w0, #10, 40 <c>
> +.*:	75663f40 	cblo	w0, #12, 40 <c>
> +.*:	75663f20 	cblo	w0, #12, 40 <c>
> +
> +.* <d>:
> +.*:	f5050000 	cbgt	x0, #10, 60 <d>
> +.*:	f5053fe0 	cbgt	x0, #10, 60 <d>
> +.*:	f5263fc0 	cblt	x0, #12, 60 <d>
> +.*:	f5263fa0 	cblt	x0, #12, 60 <d>
> +.*:	f5453f80 	cbhi	x0, #10, 60 <d>
> +.*:	f5453f60 	cbhi	x0, #10, 60 <d>
> +.*:	f5663f5e 	cblo	x30, #12, 60 <d>
> +.*:	f5663f3e 	cblo	x30, #12, 60 <d>
> +
> +.* <e>:
> +.*:	741e8000 	cbbgt	w0, w30, 80 <e>
> +.*:	741ebfe0 	cbbgt	w0, w30, 80 <e>
> +.*:	743ebfc0 	cbbge	w0, w30, 80 <e>
> +.*:	743ebfa0 	cbbge	w0, w30, 80 <e>
> +.*:	745ebf80 	cbbhi	w0, w30, 80 <e>
> +.*:	745ebf60 	cbbhi	w0, w30, 80 <e>
> +.*:	747ebf40 	cbbhs	w0, w30, 80 <e>
> +.*:	747ebf20 	cbbhs	w0, w30, 80 <e>
> +
> +.* <f>:
> +.*:	741ec000 	cbhgt	w0, w30, a0 <f>
> +.*:	741effe0 	cbhgt	w0, w30, a0 <f>
> +.*:	743effc0 	cbhge	w0, w30, a0 <f>
> +.*:	743effa0 	cbhge	w0, w30, a0 <f>
> +.*:	745eff80 	cbhhi	w0, w30, a0 <f>
> +.*:	745eff60 	cbhhi	w0, w30, a0 <f>
> +.*:	747eff40 	cbhhs	w0, w30, a0 <f>
> +.*:	747eff20 	cbhhs	w0, w30, a0 <f>
> diff --git a/gas/testsuite/gas/aarch64/cmpbr-1.s b/gas/testsuite/gas/aarch64/cmpbr-1.s
> new file mode 100644
> index 00000000000..97ea7823f2c
> --- /dev/null
> +++ b/gas/testsuite/gas/aarch64/cmpbr-1.s
> @@ -0,0 +1,59 @@
> +a:
> +	cbgt	w0, w30, a
> +	cblt	w30, w0, a
> +	cbge	w0, w30, a
> +	cble	w30, w0, a
> +	cbhi	w0, w30, a
> +	cblo	w30, w0, a
> +	cbhs	w0, w30, a
> +	cbls	w30, w0, a
> +
> +b:
> +	cbgt	x0, x30, b
> +	cblt	x30, x0, b
> +	cbge	x0, x30, b
> +	cble	x30, x0, b
> +	cbhi	x0, x30, b
> +	cblo	x30, x0, b
> +	cbhs	x0, x30, b
> +	cbls	x30, x0, b
> +
> +c:
> +	cbgt	w0, #10, c
> +	cbge	w0, #11, c
> +	cblt	w0, #12, c
> +	cble	w0, #11, c
> +	cbhi	w0, #10, c
> +	cbhs	w0, #11, c
> +	cblo	w0, #12, c
> +	cbls	w0, #11, c
> +
> +d:
> +	cbgt	x0, #10, d
> +	cbge	x0, #11, d
> +	cblt	x0, #12, d
> +	cble	x0, #11, d
> +	cbhi	x0, #10, d
> +	cbhs	x0, #11, d
> +	cblo	x30, #12, d
> +	cbls	x30, #11, d
> +
> +e:
> +	cbbgt	w0, w30, e
> +	cbblt	w30, w0, e
> +	cbbge	w0, w30, e
> +	cbble	w30, w0, e
> +	cbbhi	w0, w30, e
> +	cbblo	w30, w0, e
> +	cbbhs	w0, w30, e
> +	cbbls	w30, w0, e
> +
> +f:
> +	cbhgt	w0, w30, f
> +	cbhlt	w30, w0, f
> +	cbhge	w0, w30, f
> +	cbhle	w30, w0, f
> +	cbhhi	w0, w30, f
> +	cbhlo	w30, w0, f
> +	cbhhs	w0, w30, f
> +	cbhls	w30, w0, f
> diff --git a/gas/testsuite/gas/aarch64/cmpbr-bad-1.d b/gas/testsuite/gas/aarch64/cmpbr-bad-1.d
> new file mode 100644
> index 00000000000..f563d274bad
> --- /dev/null
> +++ b/gas/testsuite/gas/aarch64/cmpbr-bad-1.d
> @@ -0,0 +1,4 @@
> +#name: Test of out-of-range cmpbr operands
> +#source: cmpbr-bad-1.s
> +#as: -march=armv8-a+cmpbr
> +#error_output: cmpbr-bad-1.l
> diff --git a/gas/testsuite/gas/aarch64/cmpbr-bad-1.l b/gas/testsuite/gas/aarch64/cmpbr-bad-1.l
> new file mode 100644
> index 00000000000..3839baf9772
> --- /dev/null
> +++ b/gas/testsuite/gas/aarch64/cmpbr-bad-1.l
> @@ -0,0 +1,3 @@
> +.[^ :]+: Assembler messages:
> +[^ :]+:[0-9]+: Error: immediate value out of range 1 to 64 at operand 2 -- `cbge w0,#0,a'
> +[^ :]+:[0-9]+: Error: immediate value out of range -1 to 62 at operand 2 -- `cble w0,#63,a'
> diff --git a/gas/testsuite/gas/aarch64/cmpbr-bad-1.s b/gas/testsuite/gas/aarch64/cmpbr-bad-1.s
> new file mode 100644
> index 00000000000..1fd0c3a3909
> --- /dev/null
> +++ b/gas/testsuite/gas/aarch64/cmpbr-bad-1.s
> @@ -0,0 +1,3 @@
> +a:
> +	cbge	w0, #0, a
> +	cble	w0, #63, a
> diff --git a/gas/testsuite/gas/aarch64/cmpbr-bad.d b/gas/testsuite/gas/aarch64/cmpbr-bad.d
> new file mode 100644
> index 00000000000..6487979e85f
> --- /dev/null
> +++ b/gas/testsuite/gas/aarch64/cmpbr-bad.d
> @@ -0,0 +1,4 @@
> +#name: Test of invalid cmpbr operands
> +#source: cmpbr-bad.s
> +#as: -march=armv8-a+cmpbr
> +#error_output: cmpbr-bad.l
> diff --git a/gas/testsuite/gas/aarch64/cmpbr-bad.l b/gas/testsuite/gas/aarch64/cmpbr-bad.l
> new file mode 100644
> index 00000000000..f705cfd0043
> --- /dev/null
> +++ b/gas/testsuite/gas/aarch64/cmpbr-bad.l
> @@ -0,0 +1,13 @@
> +.[^ :]+: Assembler messages:
> +[^ :]+:[0-9]+: Error: operand mismatch -- `cbgt w0,x1,a'
> +[^ :]+:[0-9]+: Info:    did you mean this\?
> +[^ :]+:[0-9]+: Info:    	cbgt w0, w1, #0x0
> +[^ :]+:[0-9]+: Info:    other valid variant\(s\):
> +[^ :]+:[0-9]+: Info:    	cbgt x0, x1, #0x0
> +[^ :]+:[0-9]+: Error: immediate value out of range 0 to 63 at operand 2 -- `cbgt w0,#64,a'
> +[^ :]+:[0-9]+: Error: operand mismatch -- `cbbgt x0,x1,a'
> +[^ :]+:[0-9]+: Info:    did you mean this\?
> +[^ :]+:[0-9]+: Info:    	cbbgt w0, w1, #0x0
> +[^ :]+:[0-9]+: Error: operand mismatch -- `cbhgt x0,x1,a'
> +[^ :]+:[0-9]+: Info:    did you mean this\?
> +[^ :]+:[0-9]+: Info:    	cbhgt w0, w1, #0x0
> diff --git a/gas/testsuite/gas/aarch64/cmpbr-bad.s b/gas/testsuite/gas/aarch64/cmpbr-bad.s
> new file mode 100644
> index 00000000000..8fb1e617254
> --- /dev/null
> +++ b/gas/testsuite/gas/aarch64/cmpbr-bad.s
> @@ -0,0 +1,5 @@
> +a:
> +	cbgt	w0, x1, a
> +	cbgt	w0, #64, a
> +	cbbgt	x0, x1, a
> +	cbhgt	x0, x1, a
> diff --git a/gas/testsuite/gas/aarch64/cmpbr-far.d b/gas/testsuite/gas/aarch64/cmpbr-far.d
> new file mode 100644
> index 00000000000..a027cdfb837
> --- /dev/null
> +++ b/gas/testsuite/gas/aarch64/cmpbr-far.d
> @@ -0,0 +1,4 @@
> +#name: CMPBR instructions that branch too far
> +#source: cmpbr-far.s
> +#as: -march=armv8-a+cmpbr
> +#error_output: cmpbr-far.l
> diff --git a/gas/testsuite/gas/aarch64/cmpbr-far.l b/gas/testsuite/gas/aarch64/cmpbr-far.l
> new file mode 100644
> index 00000000000..6432035a1f3
> --- /dev/null
> +++ b/gas/testsuite/gas/aarch64/cmpbr-far.l
> @@ -0,0 +1,3 @@
> +.[^ :]+: Assembler messages:
> +[^ :]+:[0-9]+: Error: conditional branch out of range
> +[^ :]+:[0-9]+: Error: conditional branch out of range

I don't think this test is as effective as it could be, since it doesn't show
which two offsets are rejected.  It would be more effective if you replaced all
the valid cbgt instructions with nops, and tested the valid offsets in a
separate test.

> diff --git a/gas/testsuite/gas/aarch64/cmpbr-far.s b/gas/testsuite/gas/aarch64/cmpbr-far.s
> new file mode 100644
> index 00000000000..56f63dce1eb
> --- /dev/null
> +++ b/gas/testsuite/gas/aarch64/cmpbr-far.s
> @@ -0,0 +1,11 @@
> +a:
> +	.rept 258
> +	cbgt w0, w1, a
> +	.endr
> +
> +	.rept 256
> +	cbgt w0, w1, b
> +	.endr
> +
> +b:
> +	nop
> diff --git a/gas/testsuite/gas/aarch64/cmpbr.d b/gas/testsuite/gas/aarch64/cmpbr.d
> new file mode 100644
> index 00000000000..33862a1b19a
> --- /dev/null
> +++ b/gas/testsuite/gas/aarch64/cmpbr.d
> @@ -0,0 +1,103 @@
> +#name: Test for FEAT_CMPBR
> +#as: -march=armv8-a+cmpbr
> +#objdump: -dr
> +
> +.*:     file format .*
> +
> +Disassembly of section .text:
> +
> +.* <a>:
> +.*:	74000000 	cbgt	w0, w0, 0 <a>
> +.*:	741e3fe0 	cbgt	w0, w30, 0 <a>
> +.*:	74003fde 	cbgt	w30, w0, 0 <a>
> +.*:	74203fa0 	cbge	w0, w0, 0 <a>
> +.*:	743e3f80 	cbge	w0, w30, 0 <a>
> +.*:	74203f7e 	cbge	w30, w0, 0 <a>
> +.*:	74403f40 	cbhi	w0, w0, 0 <a>
> +.*:	745e3f20 	cbhi	w0, w30, 0 <a>
> +.*:	74403f1e 	cbhi	w30, w0, 0 <a>
> +.*:	74603ee0 	cbhs	w0, w0, 0 <a>
> +.*:	747e3ec0 	cbhs	w0, w30, 0 <a>
> +.*:	74603ebe 	cbhs	w30, w0, 0 <a>
> +
> +.* <b>:
> +.*:	f4000000 	cbgt	x0, x0, 30 <b>
> +.*:	f41e3fe0 	cbgt	x0, x30, 30 <b>
> +.*:	f4003fde 	cbgt	x30, x0, 30 <b>
> +.*:	f4203fa0 	cbge	x0, x0, 30 <b>
> +.*:	f43e3f80 	cbge	x0, x30, 30 <b>
> +.*:	f4203f7e 	cbge	x30, x0, 30 <b>
> +.*:	f4403f40 	cbhi	x0, x0, 30 <b>
> +.*:	f45e3f20 	cbhi	x0, x30, 30 <b>
> +.*:	f4403f1e 	cbhi	x30, x0, 30 <b>
> +.*:	f4603ee0 	cbhs	x0, x0, 30 <b>
> +.*:	f47e3ec0 	cbhs	x0, x30, 30 <b>
> +.*:	f4603ebe 	cbhs	x30, x0, 30 <b>
> +
> +.* <c>:
> +.*:	75000000 	cbgt	w0, #0, 60 <c>
> +.*:	7500bffe 	cbgt	w30, #1, 60 <c>
> +.*:	75203fc0 	cblt	w0, #0, 60 <c>
> +.*:	75213fbe 	cblt	w30, #2, 60 <c>
> +.*:	75403f80 	cbhi	w0, #0, 60 <c>
> +.*:	7541bf7e 	cbhi	w30, #3, 60 <c>
> +.*:	75603f40 	cblo	w0, #0, 60 <c>
> +.*:	75623f3e 	cblo	w30, #4, 60 <c>
> +.*:	75c03f00 	cbeq	w0, #0, 60 <c>
> +.*:	75c2befe 	cbeq	w30, #5, 60 <c>
> +.*:	75e03ec0 	cbne	w0, #0, 60 <c>
> +.*:	75e33ebe 	cbne	w30, #6, 60 <c>
> +
> +.* <d>:
> +.*:	f5000000 	cbgt	x0, #0, 90 <d>
> +.*:	f500bffe 	cbgt	x30, #1, 90 <d>
> +.*:	f5203fc0 	cblt	x0, #0, 90 <d>
> +.*:	f5213fbe 	cblt	x30, #2, 90 <d>
> +.*:	f5403f80 	cbhi	x0, #0, 90 <d>
> +.*:	f541bf7e 	cbhi	x30, #3, 90 <d>
> +.*:	f5603f40 	cblo	x0, #0, 90 <d>
> +.*:	f5623f3e 	cblo	x30, #4, 90 <d>
> +.*:	f5c03f00 	cbeq	x0, #0, 90 <d>
> +.*:	f5c2befe 	cbeq	x30, #5, 90 <d>
> +.*:	f5e03ec0 	cbne	x0, #0, 90 <d>
> +.*:	f5e33ebe 	cbne	x30, #6, 90 <d>
> +
> +.* <e>:
> +.*:	74008000 	cbbgt	w0, w0, c0 <e>
> +.*:	741ebfe0 	cbbgt	w0, w30, c0 <e>
> +.*:	7400bfde 	cbbgt	w30, w0, c0 <e>
> +.*:	7420bfa0 	cbbge	w0, w0, c0 <e>
> +.*:	743ebf80 	cbbge	w0, w30, c0 <e>
> +.*:	7420bf7e 	cbbge	w30, w0, c0 <e>
> +.*:	7440bf40 	cbbhi	w0, w0, c0 <e>
> +.*:	745ebf20 	cbbhi	w0, w30, c0 <e>
> +.*:	7440bf1e 	cbbhi	w30, w0, c0 <e>
> +.*:	7460bee0 	cbbhs	w0, w0, c0 <e>
> +.*:	747ebec0 	cbbhs	w0, w30, c0 <e>
> +.*:	7460bebe 	cbbhs	w30, w0, c0 <e>
> +.*:	74c0be80 	cbbeq	w0, w0, c0 <e>
> +.*:	74debe60 	cbbeq	w0, w30, c0 <e>
> +.*:	74c0be5e 	cbbeq	w30, w0, c0 <e>
> +.*:	74e0be20 	cbbne	w0, w0, c0 <e>
> +.*:	74febe00 	cbbne	w0, w30, c0 <e>
> +.*:	74e0bdfe 	cbbne	w30, w0, c0 <e>
> +
> +.* <f>:
> +.*:	74008000 	cbbgt	w0, w0, 108 <f>
> +.*:	741ebfe0 	cbbgt	w0, w30, 108 <f>
> +.*:	7400bfde 	cbbgt	w30, w0, 108 <f>
> +.*:	7420bfa0 	cbbge	w0, w0, 108 <f>
> +.*:	743ebf80 	cbbge	w0, w30, 108 <f>
> +.*:	7420bf7e 	cbbge	w30, w0, 108 <f>
> +.*:	7440bf40 	cbbhi	w0, w0, 108 <f>
> +.*:	745ebf20 	cbbhi	w0, w30, 108 <f>
> +.*:	7440bf1e 	cbbhi	w30, w0, 108 <f>
> +.*:	7460bee0 	cbbhs	w0, w0, 108 <f>
> +.*:	747ebec0 	cbbhs	w0, w30, 108 <f>
> +.*:	7460bebe 	cbbhs	w30, w0, 108 <f>
> +.*:	74c0be80 	cbbeq	w0, w0, 108 <f>
> +.*:	74debe60 	cbbeq	w0, w30, 108 <f>
> +.*:	74c0be5e 	cbbeq	w30, w0, 108 <f>
> +.*:	74e0be20 	cbbne	w0, w0, 108 <f>
> +.*:	74febe00 	cbbne	w0, w30, 108 <f>
> +.*:	74e0bdfe 	cbbne	w30, w0, 108 <f>
> diff --git a/gas/testsuite/gas/aarch64/cmpbr.s b/gas/testsuite/gas/aarch64/cmpbr.s
> new file mode 100644
> index 00000000000..b10b16792bf
> --- /dev/null
> +++ b/gas/testsuite/gas/aarch64/cmpbr.s
> @@ -0,0 +1,90 @@
> +a:
> +	cbgt 	w0, w0, a
> +	cbgt 	w0, w30, a
> +	cbgt 	w30, w0, a
> +	cbge 	w0, w0, a
> +	cbge 	w0, w30, a
> +	cbge 	w30, w0, a
> +	cbhi 	w0, w0, a
> +	cbhi 	w0, w30, a
> +	cbhi 	w30, w0, a
> +	cbhs 	w0, w0, a
> +	cbhs 	w0, w30, a
> +	cbhs 	w30, w0, a
> +b:
> +	cbgt 	x0, x0, b
> +	cbgt 	x0, x30, b
> +	cbgt 	x30, x0, b
> +	cbge 	x0, x0, b
> +	cbge 	x0, x30, b
> +	cbge 	x30, x0, b
> +	cbhi 	x0, x0, b
> +	cbhi 	x0, x30, b
> +	cbhi 	x30, x0, b
> +	cbhs 	x0, x0, b
> +	cbhs 	x0, x30, b
> +	cbhs 	x30, x0, b
> +c:
> +	cbgt 	w0, #0, c
> +	cbgt 	w30, #1, c
> +	cblt 	w0, #0, c
> +	cblt 	w30, #2, c
> +	cbhi 	w0, #0, c
> +	cbhi 	w30, #3, c
> +	cblo 	w0, #0, c
> +	cblo 	w30, #4, c
> +	cbeq 	w0, #0, c
> +	cbeq 	w30, #5, c
> +	cbne 	w0, #0, c
> +	cbne 	w30, #6, c
> +d:
> +	cbgt 	x0, #0, d
> +	cbgt 	x30, #1, d
> +	cblt 	x0, #0, d
> +	cblt 	x30, #2, d
> +	cbhi 	x0, #0, d
> +	cbhi 	x30, #3, d
> +	cblo 	x0, #0, d
> +	cblo 	x30, #4, d
> +	cbeq 	x0, #0, d
> +	cbeq 	x30, #5, d
> +	cbne 	x0, #0, d
> +	cbne 	x30, #6, d
> +e:
> +	cbbgt 	w0, w0, e
> +	cbbgt 	w0, w30, e
> +	cbbgt 	w30, w0, e
> +	cbbge 	w0, w0, e
> +	cbbge 	w0, w30, e
> +	cbbge 	w30, w0, e
> +	cbbhi 	w0, w0, e
> +	cbbhi 	w0, w30, e
> +	cbbhi 	w30, w0, e
> +	cbbhs 	w0, w0, e
> +	cbbhs 	w0, w30, e
> +	cbbhs 	w30, w0, e
> +	cbbeq 	w0, w0, e
> +	cbbeq 	w0, w30, e
> +	cbbeq 	w30, w0, e
> +	cbbne 	w0, w0, e
> +	cbbne 	w0, w30, e
> +	cbbne 	w30, w0, e
> +f:
> +	cbbgt 	w0, w0, f
> +	cbbgt 	w0, w30, f
> +	cbbgt 	w30, w0, f
> +	cbbge 	w0, w0, f
> +	cbbge 	w0, w30, f
> +	cbbge 	w30, w0, f
> +	cbbhi 	w0, w0, f
> +	cbbhi 	w0, w30, f
> +	cbbhi 	w30, w0, f
> +	cbbhs 	w0, w0, f
> +	cbbhs 	w0, w30, f
> +	cbbhs 	w30, w0, f
> +	cbbeq 	w0, w0, f
> +	cbbeq 	w0, w30, f
> +	cbbeq 	w30, w0, f
> +	cbbne 	w0, w0, f
> +	cbbne 	w0, w30, f
> +	cbbne 	w30, w0, f

A few remarks:
I'm not sure why you have both cmpbr.[sd] and cmpbr-1.[sd].  I'd expect two
different tests with the same base name to be labelled -1 and -2 instead (at
least if they were being added at the same time).  However, in this case they
seem to be testing the same thing, so I don't see why it isn't just a single
test instead.

I think it's generally more effective to use wzr/xzr in tests instead of
w30/x30 (when used in combination with w0/x0 and no other values).  This
verifies that we are using the correct choice of wzr or wsp, and xzr or sp, for
register 31, and ensures that we have a test where the least significant bit of
the register number is not zero.

I'd also like to see better coverage of the offset values - e.g. by ensuring
that we test offsets of both 0 and -1 (i.e. 0x0 and 0x1ff) for every entry in
the opcode table.  You could achieve this by using a separate label for each
opcode table entry, so that the first offsets start again from 0 each time.

> diff --git a/include/opcode/aarch64.h b/include/opcode/aarch64.h
> index dfe3f05820a..0b124de59d7 100644
> --- a/include/opcode/aarch64.h
> +++ b/include/opcode/aarch64.h
> @@ -135,6 +135,8 @@ enum aarch64_feature_bit {
>    AARCH64_FEATURE_ID_PFR2,
>    /* SSBS mechanism enabled.  */
>    AARCH64_FEATURE_SSBS,
> +  /* Compare and branch instructions.  */
> +  AARCH64_FEATURE_CMPBR,
>    /* Memory Tagging Extension.  */
>    AARCH64_FEATURE_MEMTAG,
>    /* Transactional Memory Extension.  */
> @@ -618,6 +620,8 @@ enum aarch64_opnd
>    AARCH64_OPND_WIDTH,	/* Immediate #<width> in e.g. BFI.  */
>    AARCH64_OPND_IMM,	/* Immediate.  */
>    AARCH64_OPND_IMM_2,	/* Immediate.  */
> +  AARCH64_OPND_IMMP1_2,	/* Immediate plus 1.  */
> +  AARCH64_OPND_IMMS1_2,	/* Immediate minus 1.  */
>    AARCH64_OPND_UIMM3_OP1,/* Unsigned 3-bit immediate in the op1 field.  */
>    AARCH64_OPND_UIMM3_OP2,/* Unsigned 3-bit immediate in the op2 field.  */
>    AARCH64_OPND_UIMM4,	/* Unsigned 4-bit immediate in the CRm field.  */
> @@ -645,6 +649,7 @@ enum aarch64_opnd
>    AARCH64_OPND_COND1,	/* Same as the above, but excluding AL and NV.  */
>  
>    AARCH64_OPND_ADDR_ADRP,	/* Memory address for ADRP */
> +  AARCH64_OPND_ADDR_PCREL9,	/* 9-bit PC-relative address for e.g. CB<cc>.  */
>    AARCH64_OPND_ADDR_PCREL14,	/* 14-bit PC-relative address for e.g. TBZ.  */
>    AARCH64_OPND_ADDR_PCREL19,	/* 19-bit PC-relative address for e.g. LDR.  */
>    AARCH64_OPND_ADDR_PCREL21,	/* 21-bit PC-relative address for e.g. ADR.  */
> diff --git a/opcodes/aarch64-opc.c b/opcodes/aarch64-opc.c
> index 4f0c71696fa..b93c7069ef6 100644
> --- a/opcodes/aarch64-opc.c
> +++ b/opcodes/aarch64-opc.c
> @@ -381,6 +381,7 @@ const aarch64_field fields[] =
>      { 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. */
> @@ -2417,6 +2418,7 @@ operand_general_constraint_met_p (const aarch64_opnd_info *opnds, int idx,
>  	    }
>  	  break;
>  
> +	case AARCH64_OPND_ADDR_PCREL9:
>  	case AARCH64_OPND_ADDR_PCREL14:
>  	case AARCH64_OPND_ADDR_PCREL19:
>  	case AARCH64_OPND_ADDR_PCREL21:
> @@ -4781,6 +4783,7 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
>        snprintf (buf, size, "%s", style_addr (styler, "#0x%" PRIx64 , addr));
>        break;
>  
> +    case AARCH64_OPND_ADDR_PCREL9:
>      case AARCH64_OPND_ADDR_PCREL14:
>      case AARCH64_OPND_ADDR_PCREL19:
>      case AARCH64_OPND_ADDR_PCREL21:
> diff --git a/opcodes/aarch64-opc.h b/opcodes/aarch64-opc.h
> index 9ab9bdf5123..3086f0285d8 100644
> --- a/opcodes/aarch64-opc.h
> +++ b/opcodes/aarch64-opc.h
> @@ -185,6 +185,7 @@ enum aarch64_field_kind
>    FLD_imm7,
>    FLD_imm8,
>    FLD_imm9,
> +  FLD_imm9_5,
>    FLD_imm12,
>    FLD_imm14,
>    FLD_imm16_0,
> diff --git a/opcodes/aarch64-tbl.h b/opcodes/aarch64-tbl.h
> index 8b64eb07067..4f22f3491e5 100644
> --- a/opcodes/aarch64-tbl.h
> +++ b/opcodes/aarch64-tbl.h
> @@ -136,6 +136,19 @@
>    QLF2(X,NIL),			\
>  }
>  
> +/* e.g. CBBGT <Wt>, <Wm>, <label>.  */
> +#define QL_W2NIL		\
> +{				\
> +  QLF3(W,W,NIL),		\
> +}
> +
> +/* e.g. CBGT <Wt>, #<imm6>, <label>.  */
> +#define QL_R_IMM_NIL		\
> +{				\
> +  QLF3(W,imm_0_63,NIL),		\
> +  QLF3(X,imm_0_63,NIL),		\
> +}
> +
>  /* e.g. LDR <Dt>, <label>.  */
>  #define QL_FP_PCREL		\
>  {				\
> @@ -2737,6 +2750,8 @@ static const aarch64_feature_set aarch64_feature_predres =
>    AARCH64_FEATURE (PREDRES);
>  static const aarch64_feature_set aarch64_feature_predres2 =
>    AARCH64_FEATURES (2, PREDRES, PREDRES2);
> +static const aarch64_feature_set aarch64_feature_cmpbr =
> +  AARCH64_FEATURE (CMPBR);
>  static const aarch64_feature_set aarch64_feature_memtag =
>    AARCH64_FEATURE (MEMTAG);
>  static const aarch64_feature_set aarch64_feature_bfloat16 =
> @@ -2897,6 +2912,7 @@ static const aarch64_feature_set aarch64_feature_sve2p1_sme2p1 =
>  #define SB		&aarch64_feature_sb
>  #define PREDRES		&aarch64_feature_predres
>  #define PREDRES2	&aarch64_feature_predres2
> +#define CMPBR		&aarch64_feature_cmpbr
>  #define MEMTAG		&aarch64_feature_memtag
>  #define TME		&aarch64_feature_tme
>  #define SVE2		&aarch64_feature_sve2
> @@ -3022,6 +3038,8 @@ static const aarch64_feature_set aarch64_feature_sve2p1_sme2p1 =
>    { NAME, OPCODE, MASK, CLASS, 0, SB, OPS, QUALS, FLAGS, 0, 0, NULL }
>  #define PREDRES_INSN(NAME,OPCODE,MASK,CLASS,OPS,QUALS,FLAGS) \
>    { NAME, OPCODE, MASK, CLASS, 0, PREDRES, OPS, QUALS, FLAGS, 0, 0, NULL }
> +#define CMPBR_INSN(NAME,OPCODE,MASK,CLASS,OPS,QUALS,FLAGS) \
> +  { NAME, OPCODE, MASK, CLASS, 0, CMPBR, OPS, QUALS, FLAGS, 0, 0, NULL }
>  #define MEMTAG_INSN(NAME,OPCODE,MASK,CLASS,OPS,QUALS,FLAGS) \
>    { NAME, OPCODE, MASK, CLASS, 0, MEMTAG, OPS, QUALS, FLAGS, 0, 0, NULL }
>  #define _TME_INSN(NAME,OPCODE,MASK,CLASS,OP,OPS,QUALS,FLAGS) \
> @@ -3965,6 +3983,50 @@ const struct aarch64_opcode aarch64_opcode_table[] =
>    CORE_INSN ("cbnz", 0x35000000, 0x7f000000, compbranch, 0, OP2 (Rt, ADDR_PCREL19), QL_R_PCREL, F_SF),
>    /* Conditional branch (immediate).  */
>    CORE_INSN ("b.c", 0x54000000, 0xff000010, condbranch, 0, OP1 (ADDR_PCREL19), QL_PCREL_NIL, F_COND),
> +  /* Compare registers and branch. */
> +  CMPBR_INSN ("cbgt", 0x74000000, 0x7fe0c000, compbranch, OP3 (Rt, Rm, ADDR_PCREL9), QL_R2NIL, F_SF | F_HAS_ALIAS),
> +  CMPBR_INSN ("cblt", 0x74000000, 0x7fe0c000, compbranch, OP3 (Rm, Rt, ADDR_PCREL9), QL_R2NIL, F_SF | F_ALIAS | F_PSEUDO),
> +  CMPBR_INSN ("cbge", 0x74200000, 0x7fe0c000, compbranch, OP3 (Rt, Rm, ADDR_PCREL9), QL_R2NIL, F_SF | F_HAS_ALIAS),
> +  CMPBR_INSN ("cble", 0x74200000, 0x7fe0c000, compbranch, OP3 (Rm, Rt, ADDR_PCREL9), QL_R2NIL, F_SF | F_ALIAS | F_PSEUDO),
> +  CMPBR_INSN ("cbhi", 0x74400000, 0x7fe0c000, compbranch, OP3 (Rt, Rm, ADDR_PCREL9), QL_R2NIL, F_SF | F_HAS_ALIAS),
> +  CMPBR_INSN ("cblo", 0x74400000, 0x7fe0c000, compbranch, OP3 (Rm, Rt, ADDR_PCREL9), QL_R2NIL, F_SF | F_ALIAS | F_PSEUDO),
> +  CMPBR_INSN ("cbhs", 0x74600000, 0x7fe0c000, compbranch, OP3 (Rt, Rm, ADDR_PCREL9), QL_R2NIL, F_SF | F_HAS_ALIAS),
> +  CMPBR_INSN ("cbls", 0x74600000, 0x7fe0c000, compbranch, OP3 (Rm, Rt, ADDR_PCREL9), QL_R2NIL, F_SF | F_ALIAS | F_PSEUDO),
> +  CMPBR_INSN ("cbeq", 0x74c00000, 0x7fe0c000, compbranch, OP3 (Rt, Rm, ADDR_PCREL9), QL_R2NIL, F_SF),
> +  CMPBR_INSN ("cbne", 0x74e00000, 0x7fe0c000, compbranch, OP3 (Rt, Rm, ADDR_PCREL9), QL_R2NIL, F_SF),
> +  /* Compare register with immediate and branch.  */
> +  CMPBR_INSN ("cbgt", 0x75000000, 0x7fe04000, compbranch, OP3 (Rt, IMM_2, ADDR_PCREL9), QL_R_IMM_NIL, F_SF | F_HAS_ALIAS),
> +  CMPBR_INSN ("cbge", 0x75000000, 0x7fe04000, compbranch, OP3 (Rt, IMMP1_2, ADDR_PCREL9), QL_R_IMM_NIL, F_SF | F_ALIAS | F_PSEUDO),
> +  CMPBR_INSN ("cblt", 0x75200000, 0x7fe04000, compbranch, OP3 (Rt, IMM_2, ADDR_PCREL9), QL_R_IMM_NIL, F_SF | F_HAS_ALIAS),
> +  CMPBR_INSN ("cble", 0x75200000, 0x7fe04000, compbranch, OP3 (Rt, IMMS1_2, ADDR_PCREL9), QL_R_IMM_NIL, F_SF | F_ALIAS | F_PSEUDO),
> +  CMPBR_INSN ("cbhi", 0x75400000, 0x7fe04000, compbranch, OP3 (Rt, IMM_2, ADDR_PCREL9), QL_R_IMM_NIL, F_SF | F_HAS_ALIAS),
> +  CMPBR_INSN ("cbhs", 0x75400000, 0x7fe04000, compbranch, OP3 (Rt, IMMP1_2, ADDR_PCREL9), QL_R_IMM_NIL, F_SF | F_ALIAS | F_PSEUDO),
> +  CMPBR_INSN ("cblo", 0x75600000, 0x7fe04000, compbranch, OP3 (Rt, IMM_2, ADDR_PCREL9), QL_R_IMM_NIL, F_SF | F_HAS_ALIAS),
> +  CMPBR_INSN ("cbls", 0x75600000, 0x7fe04000, compbranch, OP3 (Rt, IMMS1_2, ADDR_PCREL9), QL_R_IMM_NIL, F_SF | F_ALIAS | F_PSEUDO),
> +  CMPBR_INSN ("cbeq", 0x75c00000, 0x7fe04000, compbranch, OP3 (Rt, IMM_2, ADDR_PCREL9), QL_R_IMM_NIL, F_SF),
> +  CMPBR_INSN ("cbne", 0x75e00000, 0x7fe04000, compbranch, OP3 (Rt, IMM_2, ADDR_PCREL9), QL_R_IMM_NIL, F_SF),
> +  /* Compare bytes and branch.  */
> +  CMPBR_INSN ("cbbgt", 0x74008000, 0xffe0c000, compbranch, OP3 (Rt, Rm, ADDR_PCREL9), QL_W2NIL, F_HAS_ALIAS),
> +  CMPBR_INSN ("cbblt", 0x74008000, 0xffe0c000, compbranch, OP3 (Rm, Rt, ADDR_PCREL9), QL_W2NIL, F_ALIAS | F_PSEUDO),
> +  CMPBR_INSN ("cbbge", 0x74208000, 0xffe0c000, compbranch, OP3 (Rt, Rm, ADDR_PCREL9), QL_W2NIL, F_HAS_ALIAS),
> +  CMPBR_INSN ("cbble", 0x74208000, 0xffe0c000, compbranch, OP3 (Rm, Rt, ADDR_PCREL9), QL_W2NIL, F_ALIAS | F_PSEUDO),
> +  CMPBR_INSN ("cbbhi", 0x74408000, 0xffe0c000, compbranch, OP3 (Rt, Rm, ADDR_PCREL9), QL_W2NIL, F_HAS_ALIAS),
> +  CMPBR_INSN ("cbblo", 0x74408000, 0xffe0c000, compbranch, OP3 (Rm, Rt, ADDR_PCREL9), QL_W2NIL, F_ALIAS | F_PSEUDO),
> +  CMPBR_INSN ("cbbhs", 0x74608000, 0xffe0c000, compbranch, OP3 (Rt, Rm, ADDR_PCREL9), QL_W2NIL, F_HAS_ALIAS),
> +  CMPBR_INSN ("cbbls", 0x74608000, 0xffe0c000, compbranch, OP3 (Rm, Rt, ADDR_PCREL9), QL_W2NIL, F_ALIAS | F_PSEUDO),
> +  CMPBR_INSN ("cbbeq", 0x74c08000, 0xffe0c000, compbranch, OP3 (Rt, Rm, ADDR_PCREL9), QL_W2NIL, 0),
> +  CMPBR_INSN ("cbbne", 0x74e08000, 0xffe0c000, compbranch, OP3 (Rt, Rm, ADDR_PCREL9), QL_W2NIL, 0),
> +  /* Compare halfwords and branch.  */
> +  CMPBR_INSN ("cbhgt", 0x7400c000, 0xffe0c000, compbranch, OP3 (Rt, Rm, ADDR_PCREL9), QL_W2NIL, F_HAS_ALIAS),
> +  CMPBR_INSN ("cbhlt", 0x7400c000, 0xffe0c000, compbranch, OP3 (Rm, Rt, ADDR_PCREL9), QL_W2NIL, F_ALIAS | F_PSEUDO),
> +  CMPBR_INSN ("cbhge", 0x7420c000, 0xffe0c000, compbranch, OP3 (Rt, Rm, ADDR_PCREL9), QL_W2NIL, F_HAS_ALIAS),
> +  CMPBR_INSN ("cbhle", 0x7420c000, 0xffe0c000, compbranch, OP3 (Rm, Rt, ADDR_PCREL9), QL_W2NIL, F_ALIAS | F_PSEUDO),
> +  CMPBR_INSN ("cbhhi", 0x7440c000, 0xffe0c000, compbranch, OP3 (Rt, Rm, ADDR_PCREL9), QL_W2NIL, F_HAS_ALIAS),
> +  CMPBR_INSN ("cbhlo", 0x7440c000, 0xffe0c000, compbranch, OP3 (Rm, Rt, ADDR_PCREL9), QL_W2NIL, F_ALIAS | F_PSEUDO),
> +  CMPBR_INSN ("cbhhs", 0x7460c000, 0xffe0c000, compbranch, OP3 (Rt, Rm, ADDR_PCREL9), QL_W2NIL, F_HAS_ALIAS),
> +  CMPBR_INSN ("cbhls", 0x7460c000, 0xffe0c000, compbranch, OP3 (Rm, Rt, ADDR_PCREL9), QL_W2NIL, F_ALIAS | F_PSEUDO),
> +  CMPBR_INSN ("cbheq", 0x74c0c000, 0xffe0c000, compbranch, OP3 (Rt, Rm, ADDR_PCREL9), QL_W2NIL, 0),
> +  CMPBR_INSN ("cbhne", 0x74e0c000, 0xffe0c000, compbranch, OP3 (Rt, Rm, ADDR_PCREL9), QL_W2NIL, 0),
>    /* Conditional compare (immediate).  */
>    CORE_INSN ("ccmn", 0x3a400800, 0x7fe00c10, condcmp_imm, 0, OP4 (Rn, CCMP_IMM, NZCV, COND), QL_CCMP_IMM, F_SF),
>    CORE_INSN ("ccmp", 0x7a400800, 0x7fe00c10, condcmp_imm, 0, OP4 (Rn, CCMP_IMM, NZCV, COND), QL_CCMP_IMM, F_SF),
> @@ -7126,6 +7188,8 @@ const struct aarch64_opcode aarch64_opcode_table[] =
>        "the width of the bit-field")					\
>      Y(IMMEDIATE, imm, "IMM", 0, F(FLD_imm6_10), "an immediate")         \
>      Y(IMMEDIATE, imm, "IMM_2", 0, F(FLD_imm6_15), "an immediate")       \
> +    Y(IMMEDIATE, imm, "IMMP1_2", 0, F(FLD_imm6_15), "an immediate plus 1")       \
> +    Y(IMMEDIATE, imm, "IMMS1_2", 0, F(FLD_imm6_15), "an immediate minus 1")       \
>      Y(IMMEDIATE, imm, "UIMM3_OP1", 0, F(FLD_op1),			\
>        "a 3-bit unsigned immediate")					\
>      Y(IMMEDIATE, imm, "UIMM3_OP2", 0, F(FLD_op2),			\
> @@ -7170,6 +7234,8 @@ const struct aarch64_opcode aarch64_opcode_table[] =
>        "one of the standard conditions, excluding AL and NV.")		\
>      X(ADDRESS, 0, ext_imm, "ADDR_ADRP", OPD_F_SEXT, F(FLD_immhi, FLD_immlo),\
>        "21-bit PC-relative address of a 4KB page")			\
> +    Y(ADDRESS, imm, "ADDR_PCREL9", OPD_F_SEXT | OPD_F_SHIFT_BY_2,	\
> +      F(FLD_imm9_5), "9-bit PC-relative address")			\
>      Y(ADDRESS, imm, "ADDR_PCREL14", OPD_F_SEXT | OPD_F_SHIFT_BY_2,	\
>        F(FLD_imm14), "14-bit PC-relative address")			\
>      Y(ADDRESS, imm, "ADDR_PCREL19", OPD_F_SEXT | OPD_F_SHIFT_BY_2,	\
> -- 
> 2.45.2


More information about the Binutils mailing list