aarch64: Support for FEAT_CMPBR
Checks
Context |
Check |
Description |
linaro-tcwg-bot/tcwg_binutils_build--master-aarch64 |
fail
|
Build failed
|
linaro-tcwg-bot/tcwg_binutils_build--master-arm |
success
|
Build passed
|
linaro-tcwg-bot/tcwg_binutils_check--master-arm |
success
|
Test passed
|
Commit Message
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
Some instructions are pseudo-instructions: cbgt w0, w1, <label> is the
same as cblt w1, w0, <label>. No new relocation type for the 9 bit offset has
been introduced to the AArch64 ELF ABI.
Details of the instructions can be found here:
https://developer.arm.com/documentation/109697/2024_12/Feature-descriptions/The-Armv9-6-architecture-extension
https://developer.arm.com/documentation/ddi0602/2024-12/Base-Instructions/CB-cc---register---Compare-registers-and-branch-?lang=en
https://developer.arm.com/documentation/ddi0602/2024-12/Base-Instructions/CB-cc---immediate---Compare-register-with-immediate-and-branch-?lang=en
https://developer.arm.com/documentation/ddi0602/2024-12/Base-Instructions/CBB-cc---Compare-bytes-and-branch-?lang=en
https://developer.arm.com/documentation/ddi0602/2024-12/Base-Instructions/CBH-cc---Compare-halfwords-and-branch-?lang=en
---
If this looks ok, could somebody commit this? I don't have commit rights.
bfd/elfnn-aarch64.c | 3 ++
bfd/reloc.c | 8 +++-
gas/config/tc-aarch64.c | 40 +++++++++++++++-
gas/testsuite/gas/aarch64/cmpbr-1.d | 66 +++++++++++++++++++++++++++
gas/testsuite/gas/aarch64/cmpbr-1.s | 59 ++++++++++++++++++++++++
gas/testsuite/gas/aarch64/cmpbr-bad.d | 3 ++
gas/testsuite/gas/aarch64/cmpbr-bad.l | 13 ++++++
gas/testsuite/gas/aarch64/cmpbr-bad.s | 5 ++
gas/testsuite/gas/aarch64/cmpbr.d | 54 ++++++++++++++++++++++
gas/testsuite/gas/aarch64/cmpbr.s | 47 +++++++++++++++++++
include/opcode/aarch64.h | 3 ++
opcodes/aarch64-opc.c | 3 ++
opcodes/aarch64-opc.h | 1 +
opcodes/aarch64-tbl.h | 61 +++++++++++++++++++++++++
14 files changed, 363 insertions(+), 3 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.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.d
create mode 100644 gas/testsuite/gas/aarch64/cmpbr.s
Comments
On 07/04/2025 14:57, 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
>
> Some instructions are pseudo-instructions: cbgt w0, w1, <label> is the
> same as cblt w1, w0, <label>. No new relocation type for the 9 bit offset has
> been introduced to the AArch64 ELF ABI.
>
> Details of the instructions can be found here:
> https://developer.arm.com/documentation/109697/2024_12/Feature-descriptions/The-Armv9-6-architecture-extension
> https://developer.arm.com/documentation/ddi0602/2024-12/Base-Instructions/CB-cc---register---Compare-registers-and-branch-?lang=en
> https://developer.arm.com/documentation/ddi0602/2024-12/Base-Instructions/CB-cc---immediate---Compare-register-with-immediate-and-branch-?lang=en
> https://developer.arm.com/documentation/ddi0602/2024-12/Base-Instructions/CBB-cc---Compare-bytes-and-branch-?lang=en
> https://developer.arm.com/documentation/ddi0602/2024-12/Base-Instructions/CBH-cc---Compare-halfwords-and-branch-?lang=en
> ---
>
> If this looks ok, could somebody commit this? I don't have commit rights.
>
> bfd/elfnn-aarch64.c | 3 ++
> bfd/reloc.c | 8 +++-
> gas/config/tc-aarch64.c | 40 +++++++++++++++-
> gas/testsuite/gas/aarch64/cmpbr-1.d | 66 +++++++++++++++++++++++++++
> gas/testsuite/gas/aarch64/cmpbr-1.s | 59 ++++++++++++++++++++++++
> gas/testsuite/gas/aarch64/cmpbr-bad.d | 3 ++
> gas/testsuite/gas/aarch64/cmpbr-bad.l | 13 ++++++
> gas/testsuite/gas/aarch64/cmpbr-bad.s | 5 ++
> gas/testsuite/gas/aarch64/cmpbr.d | 54 ++++++++++++++++++++++
> gas/testsuite/gas/aarch64/cmpbr.s | 47 +++++++++++++++++++
> include/opcode/aarch64.h | 3 ++
> opcodes/aarch64-opc.c | 3 ++
> opcodes/aarch64-opc.h | 1 +
> opcodes/aarch64-tbl.h | 61 +++++++++++++++++++++++++
> 14 files changed, 363 insertions(+), 3 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.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.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..4182330d0bb 100644
> --- a/bfd/reloc.c
> +++ b/bfd/reloc.c
> @@ -7202,7 +7202,7 @@ ENUM
> BFD_RELOC_AARCH64_TLSLD_LDST32_DTPREL_LO12_NC
> ENUMDOC
> Similar to BFD_RELOC_AARCH64_TLSLD_LDST32_DTPREL_LO12, but no
> - overflow check.
> + overflow check.
> ENUM
> BFD_RELOC_AARCH64_TLSLD_LDST64_DTPREL_LO12
> ENUMDOC
> @@ -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.
There appear to be a lot of indentation issues in this patch. The above
is just the first. The text here should be indented by the same amount
as the other ENUMDOC entries (eg immediately above).
> ENUM
> BFD_RELOC_TILEPRO_COPY
> ENUMX
> diff --git a/gas/config/tc-aarch64.c b/gas/config/tc-aarch64.c
> index e071ad11f46..c34eb301b42 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_nc_or_fail ();
> + info->imm.value = val - 1;
> + break;
Indentation.
> +
> + case AARCH64_OPND_IMMS1_2:
> + po_imm_nc_or_fail ();
> + info->imm.value = val + 1;
> + break;
And again.
> +
> 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,10 @@ 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 ||
The '||' should be on the continuation line, not at the end of the
preceding one. It should be indented to be one character beyond the
nesting brace).
> + operands[i] == AARCH64_OPND_ADDR_PCREL19);
> + inst.reloc.type = operands[i] == AARCH64_OPND_ADDR_PCREL9 ?
Similarly for the '?'. In this case add parenthesis so that the entire
expression is indened cleanly...
a = (op == xx
? YYY
: ZZZ);
> + BFD_RELOC_AARCH64_BRANCH9 : BFD_RELOC_AARCH64_BRANCH19;
> break;
> case testbranch:
> /* e.g. TBZ */
> @@ -9670,6 +9692,20 @@ md_apply_fix (fixS * fixP, valueT * valP, segT seg)
> }
> break;
>
> + case BFD_RELOC_AARCH64_BRANCH9:
> + if (fixP->fx_done || !seg->use_rela_p)
Indentation is wrong here as well.
> + {
> + 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)
> {
> diff --git a/gas/testsuite/gas/aarch64/cmpbr-1.d b/gas/testsuite/gas/aarch64/cmpbr-1.d
> new file mode 100644
> index 00000000000..02a5aa07066
> --- /dev/null
> +++ b/gas/testsuite/gas/aarch64/cmpbr-1.d
> @@ -0,0 +1,66 @@
> +#name: Test for FEAT_CMPBR pseudo-instructions
> +#objdump: -dr
> +
> +.*: file format .*
> +
> +Disassembly of section .text:
> +
> +0000000000000000 <a>:
> + 0: 74010000 cbgt w0, w1, 0 <a>
> + 4: 74013fe0 cbgt w0, w1, 0 <a>
> + 8: 74213fc0 cbge w0, w1, 0 <a>
> + c: 74213fa0 cbge w0, w1, 0 <a>
> + 10: 74413f80 cbhi w0, w1, 0 <a>
> + 14: 74413f60 cbhi w0, w1, 0 <a>
> + 18: 74613f40 cbhs w0, w1, 0 <a>
> + 1c: 74613f20 cbhs w0, w1, 0 <a>
We normally replace the addresses with wild-card patterns so that there
is less churn on the tests if new instructions are inserted.
> +
> +0000000000000020 <b>:
> + 20: f4010000 cbgt x0, x1, 20 <b>
> + 24: f4013fe0 cbgt x0, x1, 20 <b>
> + 28: f4213fc0 cbge x0, x1, 20 <b>
> + 2c: f4213fa0 cbge x0, x1, 20 <b>
> + 30: f4413f80 cbhi x0, x1, 20 <b>
> + 34: f4413f60 cbhi x0, x1, 20 <b>
> + 38: f4613f40 cbhs x0, x1, 20 <b>
> + 3c: f4613f20 cbhs x0, x1, 20 <b>
> +
> +0000000000000040 <c>:
> + 40: 75050000 cbgt w0, #10, 40 <c>
> + 44: 75053fe0 cbgt w0, #10, 40 <c>
> + 48: 75263fc0 cblt w0, #12, 40 <c>
> + 4c: 75263fa1 cblt w1, #12, 40 <c>
> + 50: 75453f80 cbhi w0, #10, 40 <c>
> + 54: 75453f60 cbhi w0, #10, 40 <c>
> + 58: 75663f41 cblo w1, #12, 40 <c>
> + 5c: 7566bf21 cblo w1, #13, 40 <c>
> +
> +0000000000000060 <d>:
> + 60: f5050000 cbgt x0, #10, 60 <d>
> + 64: f5053fe0 cbgt x0, #10, 60 <d>
> + 68: f5263fc0 cblt x0, #12, 60 <d>
> + 6c: f5263fa1 cblt x1, #12, 60 <d>
> + 70: f5453f80 cbhi x0, #10, 60 <d>
> + 74: f5453f60 cbhi x0, #10, 60 <d>
> + 78: f5663f41 cblo x1, #12, 60 <d>
> + 7c: f566bf21 cblo x1, #13, 60 <d>
> +
> +0000000000000080 <e>:
> + 80: 74018000 cbbgt w0, w1, 80 <e>
> + 84: 7401bfe0 cbbgt w0, w1, 80 <e>
> + 88: 7421bfc0 cbbge w0, w1, 80 <e>
> + 8c: 7421bfa0 cbbge w0, w1, 80 <e>
> + 90: 7441bf80 cbbhi w0, w1, 80 <e>
> + 94: 7441bf60 cbbhi w0, w1, 80 <e>
> + 98: 7461bf40 cbbhs w0, w1, 80 <e>
> + 9c: 7461bf20 cbbhs w0, w1, 80 <e>
> +
> +00000000000000a0 <f>:
> + a0: 7401c000 cbhgt w0, w1, a0 <f>
> + a4: 7401ffe0 cbhgt w0, w1, a0 <f>
> + a8: 7421ffc0 cbhge w0, w1, a0 <f>
> + ac: 7421ffa0 cbhge w0, w1, a0 <f>
> + b0: 7441ff80 cbhhi w0, w1, a0 <f>
> + b4: 7440ff61 cbhhi w1, w0, a0 <f>
> + b8: 7461ff40 cbhhs w0, w1, a0 <f>
> + bc: 7461ff20 cbhhs w0, w1, 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..0d17ebb03c9
> --- /dev/null
> +++ b/gas/testsuite/gas/aarch64/cmpbr-1.s
> @@ -0,0 +1,59 @@
> +a:
> + cbgt w0, w1, a
The preferred style for assembler source is
<tab><mnemonic><tab><operands>
So
cbgt w0, r1, a
Tabs are standard hard tabs (8 columns).
> + cblt w1, w0, a
> + cbge w0, w1, a
> + cble w1, w0, a
> + cbhi w0, w1, a
> + cblo w1, w0, a
> + cbhs w0, w1, a
> + cbls w1, w0, a
> +
> +b:
> + cbgt x0, x1, b
> + cblt x1, x0, b
> + cbge x0, x1, b
> + cble x1, x0, b
> + cbhi x0, x1, b
> + cblo x1, x0, b
> + cbhs x0, x1, b
> + cbls x1, x0, b
> +
> +c:
> + cbgt w0, #10, c
> + cbge w0, #11, c
> + cblt w0, #12, c
> + cble w1, #11, c
> + cbhi w0, #10, c
> + cbhs w0, #11, c
> + cblo w1, #12, c
> + cbls w1, #12, c
> +
> +d:
> + cbgt x0, #10, d
> + cbge x0, #11, d
> + cblt x0, #12, d
> + cble x1, #11, d
> + cbhi x0, #10, d
> + cbhs x0, #11, d
> + cblo x1, #12, d
> + cbls x1, #12, d
> +
> +e:
> + cbbgt w0, w1, e
> + cbblt w1, w0, e
> + cbbge w0, w1, e
> + cbble w1, w0, e
> + cbbhi w0, w1, e
> + cbblo w1, w0, e
> + cbbhs w0, w1, e
> + cbbls w1, w0, e
> +
> +f:
> + cbhgt w0, w1, f
> + cbhlt w1, w0, f
> + cbhge w0, w1, f
> + cbhle w1, w0, f
> + cbhhi w0, w1, f
> + cbhlo w1, w0, f
> + cbhhs w0, w1, f
> + cbhls w1, w0, f
> diff --git a/gas/testsuite/gas/aarch64/cmpbr-bad.d b/gas/testsuite/gas/aarch64/cmpbr-bad.d
> new file mode 100644
> index 00000000000..802d39e7294
> --- /dev/null
> +++ b/gas/testsuite/gas/aarch64/cmpbr-bad.d
> @@ -0,0 +1,3 @@
> +#name: Test of invalid cmpbr operands
> +#source: cmpbr-bad.s
> +#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..80b31b827dc
> --- /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.d b/gas/testsuite/gas/aarch64/cmpbr.d
> new file mode 100644
> index 00000000000..1ee2d3a0f5d
> --- /dev/null
> +++ b/gas/testsuite/gas/aarch64/cmpbr.d
> @@ -0,0 +1,54 @@
> +#name: Test for FEAT_CMPBR
> +#objdump: -dr
> +
> +.*: file format .*
> +
> +Disassembly of section .text:
> +
> +0000000000000000 <a>:
> + 0: 74010000 cbgt w0, w1, 0 <a>
> + 4: 74213fe0 cbge w0, w1, 0 <a>
> + 8: 74413fc0 cbhi w0, w1, 0 <a>
> + c: 74613fa0 cbhs w0, w1, 0 <a>
> + 10: 74c13f80 cbeq w0, w1, 0 <a>
> + 14: 74e13f60 cbne w0, w1, 0 <a>
> +
> +0000000000000018 <b>:
> + 18: f4010000 cbgt x0, x1, 18 <b>
> + 1c: f4213fe0 cbge x0, x1, 18 <b>
> + 20: f4413fc0 cbhi x0, x1, 18 <b>
> + 24: f4613fa0 cbhs x0, x1, 18 <b>
> + 28: f4c13f80 cbeq x0, x1, 18 <b>
> + 2c: f4e13f60 cbne x0, x1, 18 <b>
> +
> +0000000000000030 <c>:
> + 30: 75010000 cbgt w0, #2, 30 <c>
> + 34: 75223fe0 cblt w0, #4, 30 <c>
> + 38: 75433fc0 cbhi w0, #6, 30 <c>
> + 3c: 75643fa0 cblo w0, #8, 30 <c>
> + 40: 75c53f80 cbeq w0, #10, 30 <c>
> + 44: 75e63f60 cbne w0, #12, 30 <c>
> +
> +0000000000000048 <d>:
> + 48: f5070000 cbgt x0, #14, 48 <d>
> + 4c: f5283fe0 cblt x0, #16, 48 <d>
> + 50: f5493fc0 cbhi x0, #18, 48 <d>
> + 54: f56a3fa0 cblo x0, #20, 48 <d>
> + 58: f5cb3f80 cbeq x0, #22, 48 <d>
> + 5c: f5ec3f60 cbne x0, #24, 48 <d>
> +
> +0000000000000060 <e>:
> + 60: 74018000 cbbgt w0, w1, 60 <e>
> + 64: 7421bfe0 cbbge w0, w1, 60 <e>
> + 68: 7441bfc0 cbbhi w0, w1, 60 <e>
> + 6c: 7461bfa0 cbbhs w0, w1, 60 <e>
> + 70: 74c1bf80 cbbeq w0, w1, 60 <e>
> + 74: 74e1bf60 cbbne w0, w1, 60 <e>
> +
> +0000000000000078 <f>:
> + 78: 7401c000 cbhgt w0, w1, 78 <f>
> + 7c: 7421ffe0 cbhge w0, w1, 78 <f>
> + 80: 7441ffc0 cbhhi w0, w1, 78 <f>
> + 84: 7461ffa0 cbhhs w0, w1, 78 <f>
> + 88: 74c1ff80 cbheq w0, w1, 78 <f>
> + 8c: 74e1ff60 cbhne w0, w1, 78 <f>
> diff --git a/gas/testsuite/gas/aarch64/cmpbr.s b/gas/testsuite/gas/aarch64/cmpbr.s
> new file mode 100644
> index 00000000000..a259dc8018d
> --- /dev/null
> +++ b/gas/testsuite/gas/aarch64/cmpbr.s
> @@ -0,0 +1,47 @@
> +a:
> + cbgt w0, w1, a
> + cbge w0, w1, a
> + cbhi w0, w1, a
> + cbhs w0, w1, a
> + cbeq w0, w1, a
> + cbne w0, w1, a
> +
> +b:
> + cbgt x0, x1, b
> + cbge x0, x1, b
> + cbhi x0, x1, b
> + cbhs x0, x1, b
> + cbeq x0, x1, b
> + cbne x0, x1, b
> +
> +c:
> + cbgt w0, #2, c
> + cblt w0, #4, c
> + cbhi w0, #6, c
> + cblo w0, #8, c
> + cbeq w0, #10, c
> + cbne w0, #12, c
> +
> +d:
> + cbgt x0, #14, d
> + cblt x0, #16, d
> + cbhi x0, #18, d
> + cblo x0, #20, d
> + cbeq x0, #22, d
> + cbne x0, #24, d
> +
> +e:
> + cbbgt w0, w1, e
> + cbbge w0, w1, e
> + cbbhi w0, w1, e
> + cbbhs w0, w1, e
> + cbbeq w0, w1, e
> + cbbne w0, w1, e
> +
> +f:
> + cbhgt w0, w1, f
> + cbhge w0, w1, f
> + cbhhi w0, w1, f
> + cbhhs w0, w1, f
> + cbheq w0, w1, f
> + cbhne w0, w1, f
> diff --git a/include/opcode/aarch64.h b/include/opcode/aarch64.h
> index dfe3f05820a..b6da2d962e6 100644
> --- a/include/opcode/aarch64.h
> +++ b/include/opcode/aarch64.h
> @@ -618,6 +618,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. */
Indentaion
> 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 +647,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>. */
And again
> 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..e4dc58f439a 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). */
and again (there are more below, please check them all).
> { 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..bb560139d1e 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_W2_PCREL \
> +{ \
> + QLF3(W,W,NIL), \
> +}
> +
> +/* e.g. CBGT <Wt>, #<imm6>, <label>. */
> +#define QL_R_IMM_PCREL \
> +{ \
> + QLF3(W,imm_0_63,NIL), \
> + QLF3(X,imm_0_63,NIL), \
> +}
> +
> /* e.g. LDR <Dt>, <label>. */
> #define QL_FP_PCREL \
> { \
> @@ -3965,6 +3978,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. */
> + CORE_INSN ("cbgt", 0x74000000, 0x7fe0c000, compbranch, 0, OP3 (Rt, Rm, ADDR_PCREL9), QL_R2NIL, F_SF | F_ALIAS),
> + CORE_INSN ("cblt", 0x74000000, 0x7fe0c000, compbranch, 0, OP3 (Rm, Rt, ADDR_PCREL9), QL_R2NIL, F_SF | F_HAS_ALIAS),
> + CORE_INSN ("cbge", 0x74200000, 0x7fe0c000, compbranch, 0, OP3 (Rt, Rm, ADDR_PCREL9), QL_R2NIL, F_SF | F_ALIAS),
> + CORE_INSN ("cble", 0x74200000, 0x7fe0c000, compbranch, 0, OP3 (Rm, Rt, ADDR_PCREL9), QL_R2NIL, F_SF | F_HAS_ALIAS),
> + CORE_INSN ("cbhi", 0x74400000, 0x7fe0c000, compbranch, 0, OP3 (Rt, Rm, ADDR_PCREL9), QL_R2NIL, F_SF | F_ALIAS),
> + CORE_INSN ("cblo", 0x74400000, 0x7fe0c000, compbranch, 0, OP3 (Rm, Rt, ADDR_PCREL9), QL_R2NIL, F_SF | F_HAS_ALIAS),
> + CORE_INSN ("cbhs", 0x74600000, 0x7fe0c000, compbranch, 0, OP3 (Rt, Rm, ADDR_PCREL9), QL_R2NIL, F_SF | F_ALIAS),
> + CORE_INSN ("cbls", 0x74600000, 0x7fe0c000, compbranch, 0, OP3 (Rm, Rt, ADDR_PCREL9), QL_R2NIL, F_SF | F_HAS_ALIAS),
> + CORE_INSN ("cbeq", 0x74c00000, 0x7fe0c000, compbranch, 0, OP3 (Rt, Rm, ADDR_PCREL9), QL_R2NIL, F_SF),
> + CORE_INSN ("cbne", 0x74e00000, 0x7fe0c000, compbranch, 0, OP3 (Rt, Rm, ADDR_PCREL9), QL_R2NIL, F_SF),
> + /* Compare register with immediate and branch. */
> + CORE_INSN ("cbgt", 0x75000000, 0x7fe04000, compbranch, 0, OP3 (Rt, IMM_2, ADDR_PCREL9), QL_R_IMM_PCREL, F_SF | F_ALIAS),
> + CORE_INSN ("cbge", 0x75000000, 0x7fe04000, compbranch, 0, OP3 (Rt, IMMP1_2, ADDR_PCREL9), QL_R_IMM_PCREL, F_SF | F_HAS_ALIAS),
> + CORE_INSN ("cblt", 0x75200000, 0x7fe04000, compbranch, 0, OP3 (Rt, IMM_2, ADDR_PCREL9), QL_R_IMM_PCREL, F_SF | F_ALIAS),
> + CORE_INSN ("cble", 0x75200000, 0x7fe04000, compbranch, 0, OP3 (Rt, IMMS1_2, ADDR_PCREL9), QL_R_IMM_PCREL, F_SF | F_HAS_ALIAS),
> + CORE_INSN ("cbhi", 0x75400000, 0x7fe04000, compbranch, 0, OP3 (Rt, IMM_2, ADDR_PCREL9), QL_R_IMM_PCREL, F_SF | F_ALIAS),
> + CORE_INSN ("cbhs", 0x75400000, 0x7fe04000, compbranch, 0, OP3 (Rt, IMMP1_2, ADDR_PCREL9), QL_R_IMM_PCREL, F_SF | F_HAS_ALIAS),
> + CORE_INSN ("cblo", 0x75600000, 0x7fe04000, compbranch, 0, OP3 (Rt, IMM_2, ADDR_PCREL9), QL_R_IMM_PCREL, F_SF | F_ALIAS),
> + CORE_INSN ("cbls", 0x75600000, 0x7fe04000, compbranch, 0, OP3 (Rt, IMMS1_2, ADDR_PCREL9), QL_R_IMM_PCREL, F_SF | F_HAS_ALIAS),
> + CORE_INSN ("cbeq", 0x75c00000, 0x7fe04000, compbranch, 0, OP3 (Rt, IMM_2, ADDR_PCREL9), QL_R_IMM_PCREL, F_SF),
> + CORE_INSN ("cbne", 0x75e00000, 0x7fe04000, compbranch, 0, OP3 (Rt, IMM_2, ADDR_PCREL9), QL_R_IMM_PCREL, F_SF),
> + // /* Compare bytes and branch. */
We don't use C++ style // comments in binutils.
> + CORE_INSN ("cbbgt", 0x74008000, 0xffe0c000, compbranch, 0, OP3 (Rt, Rm, ADDR_PCREL9), QL_W2_PCREL, F_ALIAS),
> + CORE_INSN ("cbblt", 0x74008000, 0xffe0c000, compbranch, 0, OP3 (Rm, Rt, ADDR_PCREL9), QL_W2_PCREL, F_HAS_ALIAS),
> + CORE_INSN ("cbbge", 0x74208000, 0xffe0c000, compbranch, 0, OP3 (Rt, Rm, ADDR_PCREL9), QL_W2_PCREL, F_ALIAS),
> + CORE_INSN ("cbble", 0x74208000, 0xffe0c000, compbranch, 0, OP3 (Rm, Rt, ADDR_PCREL9), QL_W2_PCREL, F_HAS_ALIAS),
> + CORE_INSN ("cbbhi", 0x74408000, 0xffe0c000, compbranch, 0, OP3 (Rt, Rm, ADDR_PCREL9), QL_W2_PCREL, F_ALIAS),
> + CORE_INSN ("cbblo", 0x74408000, 0xffe0c000, compbranch, 0, OP3 (Rm, Rt, ADDR_PCREL9), QL_W2_PCREL, F_HAS_ALIAS),
> + CORE_INSN ("cbbhs", 0x74608000, 0xffe0c000, compbranch, 0, OP3 (Rt, Rm, ADDR_PCREL9), QL_W2_PCREL, F_ALIAS),
> + CORE_INSN ("cbbls", 0x74608000, 0xffe0c000, compbranch, 0, OP3 (Rm, Rt, ADDR_PCREL9), QL_W2_PCREL, F_HAS_ALIAS),
> + CORE_INSN ("cbbeq", 0x74c08000, 0xffe0c000, compbranch, 0, OP3 (Rt, Rm, ADDR_PCREL9), QL_W2_PCREL, 0),
> + CORE_INSN ("cbbne", 0x74e08000, 0xffe0c000, compbranch, 0, OP3 (Rt, Rm, ADDR_PCREL9), QL_W2_PCREL, 0),
> + // /* Compare halfwords and branch. */
And here.
> + CORE_INSN ("cbhgt", 0x7400c000, 0xffe0c000, compbranch, 0, OP3 (Rt, Rm, ADDR_PCREL9), QL_W2_PCREL, F_ALIAS),
> + CORE_INSN ("cbhlt", 0x7400c000, 0xffe0c000, compbranch, 0, OP3 (Rm, Rt, ADDR_PCREL9), QL_W2_PCREL, F_HAS_ALIAS),
> + CORE_INSN ("cbhge", 0x7420c000, 0xffe0c000, compbranch, 0, OP3 (Rt, Rm, ADDR_PCREL9), QL_W2_PCREL, F_ALIAS),
> + CORE_INSN ("cbhle", 0x7420c000, 0xffe0c000, compbranch, 0, OP3 (Rm, Rt, ADDR_PCREL9), QL_W2_PCREL, F_HAS_ALIAS),
> + CORE_INSN ("cbhhi", 0x7440c000, 0xffe0c000, compbranch, 0, OP3 (Rt, Rm, ADDR_PCREL9), QL_W2_PCREL, F_ALIAS),
> + CORE_INSN ("cbhlo", 0x7440c000, 0xffe0c000, compbranch, 0, OP3 (Rt, Rm, ADDR_PCREL9), QL_W2_PCREL, F_HAS_ALIAS),
> + CORE_INSN ("cbhhs", 0x7460c000, 0xffe0c000, compbranch, 0, OP3 (Rt, Rm, ADDR_PCREL9), QL_W2_PCREL, F_ALIAS),
> + CORE_INSN ("cbhls", 0x7460c000, 0xffe0c000, compbranch, 0, OP3 (Rm, Rt, ADDR_PCREL9), QL_W2_PCREL, F_HAS_ALIAS),
> + CORE_INSN ("cbheq", 0x74c0c000, 0xffe0c000, compbranch, 0, OP3 (Rt, Rm, ADDR_PCREL9), QL_W2_PCREL, 0),
> + CORE_INSN ("cbhne", 0x74e0c000, 0xffe0c000, compbranch, 0, OP3 (Rt, Rm, ADDR_PCREL9), QL_W2_PCREL, 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 +7183,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 +7229,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, \
I don't immediately see anything technically wrong with this, but there
are a lot of minor formatting issues that need to be cleaned up before
it can be committed.
R.
Thanks! I'll address the formatting issues.
Ezra
@@ -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;
}
@@ -7202,7 +7202,7 @@ ENUM
BFD_RELOC_AARCH64_TLSLD_LDST32_DTPREL_LO12_NC
ENUMDOC
Similar to BFD_RELOC_AARCH64_TLSLD_LDST32_DTPREL_LO12, but no
- overflow check.
+ overflow check.
ENUM
BFD_RELOC_AARCH64_TLSLD_LDST64_DTPREL_LO12
ENUMDOC
@@ -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
@@ -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_nc_or_fail ();
+ info->imm.value = val - 1;
+ break;
+
+ case AARCH64_OPND_IMMS1_2:
+ po_imm_nc_or_fail ();
+ 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,10 @@ 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 +9692,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)
{
new file mode 100644
@@ -0,0 +1,66 @@
+#name: Test for FEAT_CMPBR pseudo-instructions
+#objdump: -dr
+
+.*: file format .*
+
+Disassembly of section .text:
+
+0000000000000000 <a>:
+ 0: 74010000 cbgt w0, w1, 0 <a>
+ 4: 74013fe0 cbgt w0, w1, 0 <a>
+ 8: 74213fc0 cbge w0, w1, 0 <a>
+ c: 74213fa0 cbge w0, w1, 0 <a>
+ 10: 74413f80 cbhi w0, w1, 0 <a>
+ 14: 74413f60 cbhi w0, w1, 0 <a>
+ 18: 74613f40 cbhs w0, w1, 0 <a>
+ 1c: 74613f20 cbhs w0, w1, 0 <a>
+
+0000000000000020 <b>:
+ 20: f4010000 cbgt x0, x1, 20 <b>
+ 24: f4013fe0 cbgt x0, x1, 20 <b>
+ 28: f4213fc0 cbge x0, x1, 20 <b>
+ 2c: f4213fa0 cbge x0, x1, 20 <b>
+ 30: f4413f80 cbhi x0, x1, 20 <b>
+ 34: f4413f60 cbhi x0, x1, 20 <b>
+ 38: f4613f40 cbhs x0, x1, 20 <b>
+ 3c: f4613f20 cbhs x0, x1, 20 <b>
+
+0000000000000040 <c>:
+ 40: 75050000 cbgt w0, #10, 40 <c>
+ 44: 75053fe0 cbgt w0, #10, 40 <c>
+ 48: 75263fc0 cblt w0, #12, 40 <c>
+ 4c: 75263fa1 cblt w1, #12, 40 <c>
+ 50: 75453f80 cbhi w0, #10, 40 <c>
+ 54: 75453f60 cbhi w0, #10, 40 <c>
+ 58: 75663f41 cblo w1, #12, 40 <c>
+ 5c: 7566bf21 cblo w1, #13, 40 <c>
+
+0000000000000060 <d>:
+ 60: f5050000 cbgt x0, #10, 60 <d>
+ 64: f5053fe0 cbgt x0, #10, 60 <d>
+ 68: f5263fc0 cblt x0, #12, 60 <d>
+ 6c: f5263fa1 cblt x1, #12, 60 <d>
+ 70: f5453f80 cbhi x0, #10, 60 <d>
+ 74: f5453f60 cbhi x0, #10, 60 <d>
+ 78: f5663f41 cblo x1, #12, 60 <d>
+ 7c: f566bf21 cblo x1, #13, 60 <d>
+
+0000000000000080 <e>:
+ 80: 74018000 cbbgt w0, w1, 80 <e>
+ 84: 7401bfe0 cbbgt w0, w1, 80 <e>
+ 88: 7421bfc0 cbbge w0, w1, 80 <e>
+ 8c: 7421bfa0 cbbge w0, w1, 80 <e>
+ 90: 7441bf80 cbbhi w0, w1, 80 <e>
+ 94: 7441bf60 cbbhi w0, w1, 80 <e>
+ 98: 7461bf40 cbbhs w0, w1, 80 <e>
+ 9c: 7461bf20 cbbhs w0, w1, 80 <e>
+
+00000000000000a0 <f>:
+ a0: 7401c000 cbhgt w0, w1, a0 <f>
+ a4: 7401ffe0 cbhgt w0, w1, a0 <f>
+ a8: 7421ffc0 cbhge w0, w1, a0 <f>
+ ac: 7421ffa0 cbhge w0, w1, a0 <f>
+ b0: 7441ff80 cbhhi w0, w1, a0 <f>
+ b4: 7440ff61 cbhhi w1, w0, a0 <f>
+ b8: 7461ff40 cbhhs w0, w1, a0 <f>
+ bc: 7461ff20 cbhhs w0, w1, a0 <f>
new file mode 100644
@@ -0,0 +1,59 @@
+a:
+ cbgt w0, w1, a
+ cblt w1, w0, a
+ cbge w0, w1, a
+ cble w1, w0, a
+ cbhi w0, w1, a
+ cblo w1, w0, a
+ cbhs w0, w1, a
+ cbls w1, w0, a
+
+b:
+ cbgt x0, x1, b
+ cblt x1, x0, b
+ cbge x0, x1, b
+ cble x1, x0, b
+ cbhi x0, x1, b
+ cblo x1, x0, b
+ cbhs x0, x1, b
+ cbls x1, x0, b
+
+c:
+ cbgt w0, #10, c
+ cbge w0, #11, c
+ cblt w0, #12, c
+ cble w1, #11, c
+ cbhi w0, #10, c
+ cbhs w0, #11, c
+ cblo w1, #12, c
+ cbls w1, #12, c
+
+d:
+ cbgt x0, #10, d
+ cbge x0, #11, d
+ cblt x0, #12, d
+ cble x1, #11, d
+ cbhi x0, #10, d
+ cbhs x0, #11, d
+ cblo x1, #12, d
+ cbls x1, #12, d
+
+e:
+ cbbgt w0, w1, e
+ cbblt w1, w0, e
+ cbbge w0, w1, e
+ cbble w1, w0, e
+ cbbhi w0, w1, e
+ cbblo w1, w0, e
+ cbbhs w0, w1, e
+ cbbls w1, w0, e
+
+f:
+ cbhgt w0, w1, f
+ cbhlt w1, w0, f
+ cbhge w0, w1, f
+ cbhle w1, w0, f
+ cbhhi w0, w1, f
+ cbhlo w1, w0, f
+ cbhhs w0, w1, f
+ cbhls w1, w0, f
new file mode 100644
@@ -0,0 +1,3 @@
+#name: Test of invalid cmpbr operands
+#source: cmpbr-bad.s
+#error_output: cmpbr-bad.l
new file mode 100644
@@ -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
new file mode 100644
@@ -0,0 +1,5 @@
+a:
+ cbgt w0, x1, a
+ cbgt w0, #64, a
+ cbbgt x0, x1, a
+ cbhgt x0, x1, a
new file mode 100644
@@ -0,0 +1,54 @@
+#name: Test for FEAT_CMPBR
+#objdump: -dr
+
+.*: file format .*
+
+Disassembly of section .text:
+
+0000000000000000 <a>:
+ 0: 74010000 cbgt w0, w1, 0 <a>
+ 4: 74213fe0 cbge w0, w1, 0 <a>
+ 8: 74413fc0 cbhi w0, w1, 0 <a>
+ c: 74613fa0 cbhs w0, w1, 0 <a>
+ 10: 74c13f80 cbeq w0, w1, 0 <a>
+ 14: 74e13f60 cbne w0, w1, 0 <a>
+
+0000000000000018 <b>:
+ 18: f4010000 cbgt x0, x1, 18 <b>
+ 1c: f4213fe0 cbge x0, x1, 18 <b>
+ 20: f4413fc0 cbhi x0, x1, 18 <b>
+ 24: f4613fa0 cbhs x0, x1, 18 <b>
+ 28: f4c13f80 cbeq x0, x1, 18 <b>
+ 2c: f4e13f60 cbne x0, x1, 18 <b>
+
+0000000000000030 <c>:
+ 30: 75010000 cbgt w0, #2, 30 <c>
+ 34: 75223fe0 cblt w0, #4, 30 <c>
+ 38: 75433fc0 cbhi w0, #6, 30 <c>
+ 3c: 75643fa0 cblo w0, #8, 30 <c>
+ 40: 75c53f80 cbeq w0, #10, 30 <c>
+ 44: 75e63f60 cbne w0, #12, 30 <c>
+
+0000000000000048 <d>:
+ 48: f5070000 cbgt x0, #14, 48 <d>
+ 4c: f5283fe0 cblt x0, #16, 48 <d>
+ 50: f5493fc0 cbhi x0, #18, 48 <d>
+ 54: f56a3fa0 cblo x0, #20, 48 <d>
+ 58: f5cb3f80 cbeq x0, #22, 48 <d>
+ 5c: f5ec3f60 cbne x0, #24, 48 <d>
+
+0000000000000060 <e>:
+ 60: 74018000 cbbgt w0, w1, 60 <e>
+ 64: 7421bfe0 cbbge w0, w1, 60 <e>
+ 68: 7441bfc0 cbbhi w0, w1, 60 <e>
+ 6c: 7461bfa0 cbbhs w0, w1, 60 <e>
+ 70: 74c1bf80 cbbeq w0, w1, 60 <e>
+ 74: 74e1bf60 cbbne w0, w1, 60 <e>
+
+0000000000000078 <f>:
+ 78: 7401c000 cbhgt w0, w1, 78 <f>
+ 7c: 7421ffe0 cbhge w0, w1, 78 <f>
+ 80: 7441ffc0 cbhhi w0, w1, 78 <f>
+ 84: 7461ffa0 cbhhs w0, w1, 78 <f>
+ 88: 74c1ff80 cbheq w0, w1, 78 <f>
+ 8c: 74e1ff60 cbhne w0, w1, 78 <f>
new file mode 100644
@@ -0,0 +1,47 @@
+a:
+ cbgt w0, w1, a
+ cbge w0, w1, a
+ cbhi w0, w1, a
+ cbhs w0, w1, a
+ cbeq w0, w1, a
+ cbne w0, w1, a
+
+b:
+ cbgt x0, x1, b
+ cbge x0, x1, b
+ cbhi x0, x1, b
+ cbhs x0, x1, b
+ cbeq x0, x1, b
+ cbne x0, x1, b
+
+c:
+ cbgt w0, #2, c
+ cblt w0, #4, c
+ cbhi w0, #6, c
+ cblo w0, #8, c
+ cbeq w0, #10, c
+ cbne w0, #12, c
+
+d:
+ cbgt x0, #14, d
+ cblt x0, #16, d
+ cbhi x0, #18, d
+ cblo x0, #20, d
+ cbeq x0, #22, d
+ cbne x0, #24, d
+
+e:
+ cbbgt w0, w1, e
+ cbbge w0, w1, e
+ cbbhi w0, w1, e
+ cbbhs w0, w1, e
+ cbbeq w0, w1, e
+ cbbne w0, w1, e
+
+f:
+ cbhgt w0, w1, f
+ cbhge w0, w1, f
+ cbhhi w0, w1, f
+ cbhhs w0, w1, f
+ cbheq w0, w1, f
+ cbhne w0, w1, f
@@ -618,6 +618,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 +647,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. */
@@ -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:
@@ -185,6 +185,7 @@ enum aarch64_field_kind
FLD_imm7,
FLD_imm8,
FLD_imm9,
+ FLD_imm9_5,
FLD_imm12,
FLD_imm14,
FLD_imm16_0,
@@ -136,6 +136,19 @@
QLF2(X,NIL), \
}
+/* e.g. CBBGT <Wt>, <Wm>, <label>. */
+#define QL_W2_PCREL \
+{ \
+ QLF3(W,W,NIL), \
+}
+
+/* e.g. CBGT <Wt>, #<imm6>, <label>. */
+#define QL_R_IMM_PCREL \
+{ \
+ QLF3(W,imm_0_63,NIL), \
+ QLF3(X,imm_0_63,NIL), \
+}
+
/* e.g. LDR <Dt>, <label>. */
#define QL_FP_PCREL \
{ \
@@ -3965,6 +3978,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. */
+ CORE_INSN ("cbgt", 0x74000000, 0x7fe0c000, compbranch, 0, OP3 (Rt, Rm, ADDR_PCREL9), QL_R2NIL, F_SF | F_ALIAS),
+ CORE_INSN ("cblt", 0x74000000, 0x7fe0c000, compbranch, 0, OP3 (Rm, Rt, ADDR_PCREL9), QL_R2NIL, F_SF | F_HAS_ALIAS),
+ CORE_INSN ("cbge", 0x74200000, 0x7fe0c000, compbranch, 0, OP3 (Rt, Rm, ADDR_PCREL9), QL_R2NIL, F_SF | F_ALIAS),
+ CORE_INSN ("cble", 0x74200000, 0x7fe0c000, compbranch, 0, OP3 (Rm, Rt, ADDR_PCREL9), QL_R2NIL, F_SF | F_HAS_ALIAS),
+ CORE_INSN ("cbhi", 0x74400000, 0x7fe0c000, compbranch, 0, OP3 (Rt, Rm, ADDR_PCREL9), QL_R2NIL, F_SF | F_ALIAS),
+ CORE_INSN ("cblo", 0x74400000, 0x7fe0c000, compbranch, 0, OP3 (Rm, Rt, ADDR_PCREL9), QL_R2NIL, F_SF | F_HAS_ALIAS),
+ CORE_INSN ("cbhs", 0x74600000, 0x7fe0c000, compbranch, 0, OP3 (Rt, Rm, ADDR_PCREL9), QL_R2NIL, F_SF | F_ALIAS),
+ CORE_INSN ("cbls", 0x74600000, 0x7fe0c000, compbranch, 0, OP3 (Rm, Rt, ADDR_PCREL9), QL_R2NIL, F_SF | F_HAS_ALIAS),
+ CORE_INSN ("cbeq", 0x74c00000, 0x7fe0c000, compbranch, 0, OP3 (Rt, Rm, ADDR_PCREL9), QL_R2NIL, F_SF),
+ CORE_INSN ("cbne", 0x74e00000, 0x7fe0c000, compbranch, 0, OP3 (Rt, Rm, ADDR_PCREL9), QL_R2NIL, F_SF),
+ /* Compare register with immediate and branch. */
+ CORE_INSN ("cbgt", 0x75000000, 0x7fe04000, compbranch, 0, OP3 (Rt, IMM_2, ADDR_PCREL9), QL_R_IMM_PCREL, F_SF | F_ALIAS),
+ CORE_INSN ("cbge", 0x75000000, 0x7fe04000, compbranch, 0, OP3 (Rt, IMMP1_2, ADDR_PCREL9), QL_R_IMM_PCREL, F_SF | F_HAS_ALIAS),
+ CORE_INSN ("cblt", 0x75200000, 0x7fe04000, compbranch, 0, OP3 (Rt, IMM_2, ADDR_PCREL9), QL_R_IMM_PCREL, F_SF | F_ALIAS),
+ CORE_INSN ("cble", 0x75200000, 0x7fe04000, compbranch, 0, OP3 (Rt, IMMS1_2, ADDR_PCREL9), QL_R_IMM_PCREL, F_SF | F_HAS_ALIAS),
+ CORE_INSN ("cbhi", 0x75400000, 0x7fe04000, compbranch, 0, OP3 (Rt, IMM_2, ADDR_PCREL9), QL_R_IMM_PCREL, F_SF | F_ALIAS),
+ CORE_INSN ("cbhs", 0x75400000, 0x7fe04000, compbranch, 0, OP3 (Rt, IMMP1_2, ADDR_PCREL9), QL_R_IMM_PCREL, F_SF | F_HAS_ALIAS),
+ CORE_INSN ("cblo", 0x75600000, 0x7fe04000, compbranch, 0, OP3 (Rt, IMM_2, ADDR_PCREL9), QL_R_IMM_PCREL, F_SF | F_ALIAS),
+ CORE_INSN ("cbls", 0x75600000, 0x7fe04000, compbranch, 0, OP3 (Rt, IMMS1_2, ADDR_PCREL9), QL_R_IMM_PCREL, F_SF | F_HAS_ALIAS),
+ CORE_INSN ("cbeq", 0x75c00000, 0x7fe04000, compbranch, 0, OP3 (Rt, IMM_2, ADDR_PCREL9), QL_R_IMM_PCREL, F_SF),
+ CORE_INSN ("cbne", 0x75e00000, 0x7fe04000, compbranch, 0, OP3 (Rt, IMM_2, ADDR_PCREL9), QL_R_IMM_PCREL, F_SF),
+ // /* Compare bytes and branch. */
+ CORE_INSN ("cbbgt", 0x74008000, 0xffe0c000, compbranch, 0, OP3 (Rt, Rm, ADDR_PCREL9), QL_W2_PCREL, F_ALIAS),
+ CORE_INSN ("cbblt", 0x74008000, 0xffe0c000, compbranch, 0, OP3 (Rm, Rt, ADDR_PCREL9), QL_W2_PCREL, F_HAS_ALIAS),
+ CORE_INSN ("cbbge", 0x74208000, 0xffe0c000, compbranch, 0, OP3 (Rt, Rm, ADDR_PCREL9), QL_W2_PCREL, F_ALIAS),
+ CORE_INSN ("cbble", 0x74208000, 0xffe0c000, compbranch, 0, OP3 (Rm, Rt, ADDR_PCREL9), QL_W2_PCREL, F_HAS_ALIAS),
+ CORE_INSN ("cbbhi", 0x74408000, 0xffe0c000, compbranch, 0, OP3 (Rt, Rm, ADDR_PCREL9), QL_W2_PCREL, F_ALIAS),
+ CORE_INSN ("cbblo", 0x74408000, 0xffe0c000, compbranch, 0, OP3 (Rm, Rt, ADDR_PCREL9), QL_W2_PCREL, F_HAS_ALIAS),
+ CORE_INSN ("cbbhs", 0x74608000, 0xffe0c000, compbranch, 0, OP3 (Rt, Rm, ADDR_PCREL9), QL_W2_PCREL, F_ALIAS),
+ CORE_INSN ("cbbls", 0x74608000, 0xffe0c000, compbranch, 0, OP3 (Rm, Rt, ADDR_PCREL9), QL_W2_PCREL, F_HAS_ALIAS),
+ CORE_INSN ("cbbeq", 0x74c08000, 0xffe0c000, compbranch, 0, OP3 (Rt, Rm, ADDR_PCREL9), QL_W2_PCREL, 0),
+ CORE_INSN ("cbbne", 0x74e08000, 0xffe0c000, compbranch, 0, OP3 (Rt, Rm, ADDR_PCREL9), QL_W2_PCREL, 0),
+ // /* Compare halfwords and branch. */
+ CORE_INSN ("cbhgt", 0x7400c000, 0xffe0c000, compbranch, 0, OP3 (Rt, Rm, ADDR_PCREL9), QL_W2_PCREL, F_ALIAS),
+ CORE_INSN ("cbhlt", 0x7400c000, 0xffe0c000, compbranch, 0, OP3 (Rm, Rt, ADDR_PCREL9), QL_W2_PCREL, F_HAS_ALIAS),
+ CORE_INSN ("cbhge", 0x7420c000, 0xffe0c000, compbranch, 0, OP3 (Rt, Rm, ADDR_PCREL9), QL_W2_PCREL, F_ALIAS),
+ CORE_INSN ("cbhle", 0x7420c000, 0xffe0c000, compbranch, 0, OP3 (Rm, Rt, ADDR_PCREL9), QL_W2_PCREL, F_HAS_ALIAS),
+ CORE_INSN ("cbhhi", 0x7440c000, 0xffe0c000, compbranch, 0, OP3 (Rt, Rm, ADDR_PCREL9), QL_W2_PCREL, F_ALIAS),
+ CORE_INSN ("cbhlo", 0x7440c000, 0xffe0c000, compbranch, 0, OP3 (Rt, Rm, ADDR_PCREL9), QL_W2_PCREL, F_HAS_ALIAS),
+ CORE_INSN ("cbhhs", 0x7460c000, 0xffe0c000, compbranch, 0, OP3 (Rt, Rm, ADDR_PCREL9), QL_W2_PCREL, F_ALIAS),
+ CORE_INSN ("cbhls", 0x7460c000, 0xffe0c000, compbranch, 0, OP3 (Rm, Rt, ADDR_PCREL9), QL_W2_PCREL, F_HAS_ALIAS),
+ CORE_INSN ("cbheq", 0x74c0c000, 0xffe0c000, compbranch, 0, OP3 (Rt, Rm, ADDR_PCREL9), QL_W2_PCREL, 0),
+ CORE_INSN ("cbhne", 0x74e0c000, 0xffe0c000, compbranch, 0, OP3 (Rt, Rm, ADDR_PCREL9), QL_W2_PCREL, 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 +7183,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 +7229,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, \