]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
[Morello] LDR immediate
authorSiddhesh Poyarekar <siddesh.poyarekar@arm.com>
Fri, 11 Sep 2020 03:48:07 +0000 (09:18 +0530)
committerJohn Baldwin <jhb@FreeBSD.org>
Thu, 1 Sep 2022 22:53:20 +0000 (15:53 -0700)
The 17-bit signed offset needs to be 16-byte aligned, but the
PCC-relative address resolution rounds down the final address to the
16-byte boundary.  Due to this, disassembly of the instruction will
show as if it is loading from the middle of an object.

bfd/ChangeLog:

2020-10-20  Siddhesh Poyarekar  <siddesh.poyarekar@arm.com>

* elfnn-aarch64.c (elfNN_aarch64_howto_table): Add
LD_PREL_LO17.
(elfNN_aarch64_final_link_relocate,
elfNN_aarch64_check_relocs): Likewise.
* elfxx-aarch64.c (reencode_ld_lit_ofs_17): New function.
(_bfd_aarch64_elf_put_addend,
_bfd_aarch64_elf_resolve_relocation): Add LD_PREL_LO17.
* libbfd.h (bfd_reloc_code_real_names): Add
BFD_RELOC_MORELLO_LD_LO17_PCREL.
* reloc.c: Add BFD_RELOC_AARCH64_LD_LO17_PCREL.
* bfd-in2.h: Regenerate.

gas/ChangeLog:

2020-10-20  Siddhesh Poyarekar  <siddesh.poyarekar@arm.com>

* config/tc-aarch64.c (encode_ld_lit_ofs_17): New function.
(parse_operands, programmer_friendly_fixup, md_apply_fix): Add
ADDR_PCREL17.

include/ChangeLog:

2020-10-20  Siddhesh Poyarekar  <siddesh.poyarekar@arm.com>

* elf/aarch64.h: New relocation R_MORELLO_LD_PREL_LO17.
* opcode/aarch64.h (aarch64_opnd): Add ADDR_PCREL17.
(aarch64_op): Add OP_LDR_LIT_2.

opcodes/ChangeLog:

2020-10-20  Siddhesh Poyarekar  <siddesh.poyarekar@arm.com>

* aarch64-asm-2.c: Regenerate.
* aarch64-dis-2.c: Regenerate.
* aarch64-opc-2.c: Regenerate.
* aarch64-opc.c (fields): Add imm17.
(operand_general_constraint_met_p, aarch64_print_operand): Add
ADDR_PCREL17.
* aarch64-opc.h (aarch64_field_kind): Add FLD_imm17.
* aarch64-tbl.h (QL2_A64C_CA_PCREL): New macro.
(aarch64_opcode_table): New instruction.
(AARCH64_OPERANDS): New operand.

15 files changed:
bfd/ChangeLog
bfd/bfd-in2.h
bfd/elfnn-aarch64.c
bfd/elfxx-aarch64.c
bfd/libbfd.h
bfd/reloc.c
gas/ChangeLog
gas/config/tc-aarch64.c
include/ChangeLog
include/elf/aarch64.h
include/opcode/aarch64.h
opcodes/ChangeLog
opcodes/aarch64-opc.c
opcodes/aarch64-opc.h
opcodes/aarch64-tbl.h

index 0a5aa97aed24b48c444e701eca7a5a1787eec2ae..3c21dd46f348ff6fc9647cb59ce6e424871a7a02 100644 (file)
@@ -1,3 +1,17 @@
+2020-10-20  Siddhesh Poyarekar  <siddesh.poyarekar@arm.com>
+
+       * elfnn-aarch64.c (elfNN_aarch64_howto_table): Add
+       LD_PREL_LO17.
+       (elfNN_aarch64_final_link_relocate,
+       elfNN_aarch64_check_relocs): Likewise.
+       * elfxx-aarch64.c (reencode_ld_lit_ofs_17): New function.
+       (_bfd_aarch64_elf_put_addend,
+       _bfd_aarch64_elf_resolve_relocation): Add LD_PREL_LO17.
+       * libbfd.h (bfd_reloc_code_real_names): Add
+       BFD_RELOC_MORELLO_LD_LO17_PCREL.
+       * reloc.c: Add BFD_RELOC_AARCH64_LD_LO17_PCREL.
+       * bfd-in2.h: Regenerate.
+
 2020-10-20  Siddhesh Poyarekar  <siddesh.poyarekar@arm.com>
 
        * elf-bfd.h (bfd_elf_section_data): New member
index c0b563aec02a6784481cc662b1ab1c0856acc2ee..812bd07f0acaee37434984fc2996a7bf50485dab 100644 (file)
@@ -5615,6 +5615,11 @@ of a signed value.  */
 of a signed value.  */
   BFD_RELOC_AARCH64_MOVW_PREL_G3,
 
+/* AArch64 A64C Load Literal instruction, holding a 17 bit pc-relative
+word offset.  The lowest four bits must be zero and are not stored in
+the instruction, giving a 21 bit signed byte offset.  */
+  BFD_RELOC_MORELLO_LD_LO17_PCREL,
+
 /* AArch64 Load Literal instruction, holding a 19 bit pc-relative word
 offset.  The lowest two bits must be zero and are not stored in the
 instruction, giving a 21 bit signed byte offset.  */
index 70d19a27468d778333fe13efdb3dce003161da67..52b80334079cd4b397b359c6ea12ad048dfb479c 100644 (file)
 #define BFD_RELOC_AARCH64_TLSDESC_LD64_LO12_NC BFD_RELOC_AARCH64_TLSDESC_LD64_LO12
 #endif
 
+#define MORELLO_R(NAME)                R_MORELLO_ ## NAME
+#define MORELLO_R_STR(NAME)    "R_MORELLO_" #NAME
+
 #if ARCH_SIZE == 32
 #define AARCH64_R(NAME)                R_AARCH64_P32_ ## NAME
 #define AARCH64_R_STR(NAME)    "R_AARCH64_P32_" #NAME
@@ -825,6 +828,21 @@ static reloc_howto_type elfNN_aarch64_howto_table[] =
 /* Relocations to generate 19, 21 and 33 bit PC-relative load/store
    addresses: PG(x) is (x & ~0xfff).  */
 
+  /* LD-lit: ((S+A-P) >> 4) & 0x1ffff */
+  HOWTO64 (MORELLO_R (LD_PREL_LO17),   /* type */
+        4,                     /* rightshift */
+        2,                     /* size (0 = byte, 1 = short, 2 = long) */
+        17,                    /* bitsize */
+        true,                  /* pc_relative */
+        0,                     /* bitpos */
+        complain_overflow_signed,      /* complain_on_overflow */
+        bfd_elf_generic_reloc, /* special_function */
+        MORELLO_R_STR (LD_PREL_LO17),  /* name */
+        false,                 /* partial_inplace */
+        0x1ffff,               /* src_mask */
+        0x1ffff,               /* dst_mask */
+        true),                 /* pcrel_offset */
+
   /* LD-lit: ((S+A-P) >> 2) & 0x7ffff */
   HOWTO (AARCH64_R (LD_PREL_LO19),     /* type */
         2,                     /* rightshift */
@@ -5939,6 +5957,7 @@ elfNN_aarch64_final_link_relocate (reloc_howto_type *howto,
     case BFD_RELOC_AARCH64_ADR_HI21_PCREL:
     case BFD_RELOC_AARCH64_ADR_LO21_PCREL:
     case BFD_RELOC_AARCH64_LD_LO19_PCREL:
+    case BFD_RELOC_MORELLO_LD_LO17_PCREL:
     case BFD_RELOC_AARCH64_MOVW_PREL_G0:
     case BFD_RELOC_AARCH64_MOVW_PREL_G0_NC:
     case BFD_RELOC_AARCH64_MOVW_PREL_G1:
@@ -7844,6 +7863,7 @@ elfNN_aarch64_check_relocs (bfd *abfd, struct bfd_link_info *info,
        case BFD_RELOC_AARCH64_LDST64_LO12:
        case BFD_RELOC_AARCH64_LDST8_LO12:
        case BFD_RELOC_AARCH64_LD_LO19_PCREL:
+       case BFD_RELOC_MORELLO_LD_LO17_PCREL:
          if (h == NULL || bfd_link_pic (info))
            break;
          /* Fall through.  */
index 63be6dc0e6eb1a2f4af87a1414e8c5498f112f2b..3e57a97683dada5772df8ad479bc4e4be728e7e1 100644 (file)
@@ -84,6 +84,13 @@ reencode_cond_branch_ofs_19 (uint32_t insn, uint32_t ofs)
   return (insn & ~(MASK (19) << 5)) | ((ofs & MASK (19)) << 5);
 }
 
+/* Decode the 17-bit offset of A64C load literal.  */
+static inline uint32_t
+reencode_ld_lit_ofs_17 (uint32_t insn, uint32_t ofs)
+{
+  return (insn & ~(MASK (17) << 5)) | ((ofs & MASK (17)) << 5);
+}
+
 /* Decode the 19-bit offset of load literal.  */
 static inline uint32_t
 reencode_ld_lit_ofs_19 (uint32_t insn, uint32_t ofs)
@@ -222,6 +229,12 @@ _bfd_aarch64_elf_put_addend (bfd *abfd,
       contents = reencode_tst_branch_ofs_14 (contents, addend);
       break;
 
+    case BFD_RELOC_MORELLO_LD_LO17_PCREL:
+      if (old_addend & ((1 << howto->rightshift) - 1))
+       addend++;
+      contents = reencode_ld_lit_ofs_17 (contents, addend);
+      break;
+
     case BFD_RELOC_AARCH64_GOT_LD_PREL19:
     case BFD_RELOC_AARCH64_LD_LO19_PCREL:
     case BFD_RELOC_AARCH64_TLSDESC_LD_PREL19:
@@ -407,6 +420,7 @@ _bfd_aarch64_elf_resolve_relocation (bfd *input_bfd,
     case BFD_RELOC_AARCH64_TLSDESC_CALL:
       break;
 
+    case BFD_RELOC_MORELLO_LD_LO17_PCREL:
     case BFD_RELOC_AARCH64_16_PCREL:
     case BFD_RELOC_AARCH64_32_PCREL:
     case BFD_RELOC_AARCH64_64_PCREL:
index 6e62e5569623ef4c228e1be24b7cd65c99f0e75c..a6adcad23b1d82438952e70191af76776867b7be 100644 (file)
@@ -3035,6 +3035,7 @@ static const char *const bfd_reloc_code_real_names[] = { "@@uninitialized@@",
   "BFD_RELOC_AARCH64_MOVW_PREL_G2",
   "BFD_RELOC_AARCH64_MOVW_PREL_G2_NC",
   "BFD_RELOC_AARCH64_MOVW_PREL_G3",
+  "BFD_RELOC_MORELLO_LD_LO17_PCREL",
   "BFD_RELOC_AARCH64_LD_LO19_PCREL",
   "BFD_RELOC_AARCH64_ADR_LO21_PCREL",
   "BFD_RELOC_AARCH64_ADR_HI21_PCREL",
index 164060361a97eecca87f159b91e778b5b3702548..f2a9f0d436e482342590c67def969a333fb6713f 100644 (file)
@@ -7115,6 +7115,12 @@ ENUM
 ENUMDOC
   AArch64 MOVK instruction with most significant bits 47 to 63
   of a signed value.
+ENUM
+  BFD_RELOC_MORELLO_LD_LO17_PCREL
+ENUMDOC
+  AArch64 A64C Load Literal instruction, holding a 17 bit pc-relative
+  word offset.  The lowest four bits must be zero and are not stored in
+  the instruction, giving a 21 bit signed byte offset.
 ENUM
   BFD_RELOC_AARCH64_LD_LO19_PCREL
 ENUMDOC
index 59409d2f62e5679233b2270ec522a48020a22727..345914f0cb21c66f6a6e6325dfebeaca0d796534 100644 (file)
@@ -1,3 +1,9 @@
+2020-10-20  Siddhesh Poyarekar  <siddesh.poyarekar@arm.com>
+
+       * config/tc-aarch64.c (encode_ld_lit_ofs_17): New function.
+       (parse_operands, programmer_friendly_fixup, md_apply_fix): Add
+       ADDR_PCREL17.
+
 2020-10-20  Siddhesh Poyarekar  <siddesh.poyarekar@arm.com>
 
        * config/tc-aarch64.c (parse_operands, fix_insn): Add
index 373c8c1eea014dae4ed70da37144755ab9eca0f2..cb7034a41b1f841b5f46d0a4ee78ec02dc2a8e0e 100644 (file)
@@ -5022,6 +5022,13 @@ encode_cond_branch_ofs_19 (uint32_t ofs)
   return (ofs & ((1 << 19) - 1)) << 5;
 }
 
+/* encode the 17-bit offset of ld literal */
+static inline uint32_t
+encode_ld_lit_ofs_17 (uint32_t ofs)
+{
+  return (ofs & ((1 << 17) - 1)) << 5;
+}
+
 /* encode the 19-bit offset of ld literal */
 static inline uint32_t
 encode_ld_lit_ofs_19 (uint32_t ofs)
@@ -7147,6 +7154,7 @@ parse_operands (char *str, const aarch64_opcode *opcode)
          break;
 
        case AARCH64_OPND_ADDR_PCREL14:
+       case AARCH64_OPND_ADDR_PCREL17:
        case AARCH64_OPND_ADDR_PCREL19:
        case AARCH64_OPND_ADDR_PCREL21:
        case AARCH64_OPND_ADDR_PCREL26:
@@ -7202,8 +7210,11 @@ parse_operands (char *str, const aarch64_opcode *opcode)
                         : BFD_RELOC_AARCH64_JUMP26;
                    break;
                  case loadlit:
-                   gas_assert (operands[i] == AARCH64_OPND_ADDR_PCREL19);
-                   inst.reloc.type = BFD_RELOC_AARCH64_LD_LO19_PCREL;
+                   gas_assert (operands[i] == AARCH64_OPND_ADDR_PCREL19
+                               || operands[i] == AARCH64_OPND_ADDR_PCREL17);
+                   inst.reloc.type = (operands[i] == AARCH64_OPND_ADDR_PCREL19
+                                      ? BFD_RELOC_AARCH64_LD_LO19_PCREL
+                                      : BFD_RELOC_MORELLO_LD_LO17_PCREL);
                    break;
                  case pcreladdr:
                    gas_assert (operands[i] == AARCH64_OPND_ADDR_PCREL21);
@@ -7994,7 +8005,8 @@ programmer_friendly_fixup (aarch64_instruction *instr)
         nearby literal pool and generate a hidden label which references it.
         ISREG has been set to 0 in the case of =value.  */
       if (instr->gen_lit_pool
-         && (op == OP_LDR_LIT || op == OP_LDRV_LIT || op == OP_LDRSW_LIT))
+         && (op == OP_LDR_LIT || op == OP_LDRV_LIT || op == OP_LDRSW_LIT
+             || op == OP_LDR_LIT_2))
        {
          int size = aarch64_get_qualifier_esize (operands[0].qualifier);
          if (op == OP_LDRSW_LIT)
@@ -9195,6 +9207,25 @@ md_apply_fix (fixS * fixP, valueT * valP, segT seg)
       fix_insn (fixP, flags, value);
       break;
 
+    case BFD_RELOC_MORELLO_LD_LO17_PCREL:
+      if (fixP->fx_done || !seg->use_rela_p)
+       {
+         /* The LDR-immediate that uses LO17 aligns the address down to
+            16-byte boundary to get the final address of the capability.
+            Since the fixed up immediate also needs to be 16-byte aligned,
+            align it up to the 16-byte boundary so that the downward alignment
+            of the load literal instruction gets us the correct address.  */
+         value = (value + 0xf) & ~(offsetT) 0xf;
+
+         if (signed_overflow (value, 21))
+           as_bad_where (fixP->fx_file, fixP->fx_line,
+                         _("pcc-relative load offset out of range"));
+         insn = get_aarch64_insn (buf);
+         insn |= encode_ld_lit_ofs_17 (value >> 4);
+         put_aarch64_insn (buf, insn);
+       }
+      break;
+
     case BFD_RELOC_AARCH64_LD_LO19_PCREL:
       if (fixP->fx_done || !seg->use_rela_p)
        {
index 0195f044bc9fe113d8f96bc1f4e70aa28a41e328..4604eaece7943a115ff0f2db7aae8a551857121f 100644 (file)
@@ -1,3 +1,9 @@
+2020-10-20  Siddhesh Poyarekar  <siddesh.poyarekar@arm.com>
+
+       * elf/aarch64.h: New relocation R_MORELLO_LD_PREL_LO17.
+       * opcode/aarch64.h (aarch64_opnd): Add ADDR_PCREL17.
+       (aarch64_op): Add OP_LDR_LIT_2.
+
 2020-10-20  Siddhesh Poyarekar  <siddesh.poyarekar@arm.com>
 
        * opcode/aarch64.h (aarch64_opnd): Add A64C_ADDR_SIMM7.
index ec04bb6a17bec5583cb06a3a14f9181d9c943f55..b29a1c8161d13edbf74b4cd004cd1d0f5395d238 100644 (file)
@@ -445,6 +445,11 @@ RELOC_NUMBER (R_AARCH64_TLS_TPREL, 1030)
 RELOC_NUMBER (R_AARCH64_TLSDESC, 1031)
 RELOC_NUMBER (R_AARCH64_IRELATIVE, 1032)
 
+/* Morello Relocations.  */
+
+/* A64C LD-lit: ((S+A-P) >> 4) & 0x1ffff */
+RELOC_NUMBER (R_MORELLO_LD_PREL_LO17, 57348)
+
 END_RELOC_NUMBERS (R_AARCH64_end)
 
 enum aarch64_st_branch_type
index e563c111414cd695b115cbb3bcd4b4f4ba00bbc4..716e0e3b34ebaa3cbb73946f3d6e0a4fe760f335 100644 (file)
@@ -530,6 +530,7 @@ enum aarch64_opnd
                                   BLR/BR.  */
   AARCH64_OPND_CAPADDR_SIMPLE, /* Simple base address with no offset.  */
   AARCH64_OPND_A64C_ADDR_SIMM7,        /* Address with 7-bit immediate offset.  */
+  AARCH64_OPND_ADDR_PCREL17,   /* 17-bit PC-relative address for e.g. LDR.  */
 };
 
 /* Qualifier constrains an operand.  It either specifies a variant of an
@@ -761,6 +762,7 @@ enum aarch64_op
   OP_PRFUM,
 
   OP_LDR_LIT,
+  OP_LDR_LIT_2,
   OP_LDRV_LIT,
   OP_LDRSW_LIT,
   OP_PRFM_LIT,
index 7b9cd529a55bd3b6400fd97b8b27ffcf4adf4710..64979cf399f8be98e67461da28762a268888ac5b 100644 (file)
@@ -1,3 +1,16 @@
+2020-10-20  Siddhesh Poyarekar  <siddesh.poyarekar@arm.com>
+
+       * aarch64-asm-2.c: Regenerate.
+       * aarch64-dis-2.c: Regenerate.
+       * aarch64-opc-2.c: Regenerate.
+       * aarch64-opc.c (fields): Add imm17.
+       (operand_general_constraint_met_p, aarch64_print_operand): Add
+       ADDR_PCREL17.
+       * aarch64-opc.h (aarch64_field_kind): Add FLD_imm17.
+       * aarch64-tbl.h (QL2_A64C_CA_PCREL): New macro.
+       (aarch64_opcode_table): New instruction.
+       (AARCH64_OPERANDS): New operand.
+
 2020-10-20  Siddhesh Poyarekar  <siddesh.poyarekar@arm.com>
 
        * aarch64-asm-2.c: Regenerate.
index dcf094620efeeccdc0e5cf25675afaf137e5fa2c..44f69cdbd6bcd17b1214e581b12d9fa63d202e99 100644 (file)
@@ -359,6 +359,7 @@ const aarch64_field fields[] =
     { 13,  2 },        /* form: form specifier in seal.  */
     { 13,  7 },        /* capaddr_simm7: Signed immediate for BLR/BR.  */
     { 30,  1 },        /* a64c_index2: in ld/st pair inst deciding the pre/post-index.  */
+    {  5, 17 },        /* imm17: in ld/st pair inst deciding the pre/post-index.  */
 };
 
 enum aarch64_operand_class
@@ -1913,31 +1914,43 @@ operand_general_constraint_met_p (aarch64_feature_set features,
          break;
 
        case AARCH64_OPND_ADDR_PCREL14:
+       case AARCH64_OPND_ADDR_PCREL17:
        case AARCH64_OPND_ADDR_PCREL19:
        case AARCH64_OPND_ADDR_PCREL21:
        case AARCH64_OPND_ADDR_PCREL26:
-         imm = opnd->imm.value;
-         if (operand_need_shift_by_two (get_operand_from_code (type)))
            {
-             /* The offset value in a PC-relative branch instruction is alway
-                4-byte aligned and is encoded without the lowest 2 bits.  */
-             if (!value_aligned_p (imm, 4))
+             int shift_amt = 0;
+             const aarch64_operand *op = get_operand_from_code (type);
+             if (operand_need_shift_by_two (op))
+               shift_amt = 2;
+             else if (operand_need_shift_by_four (op))
+               shift_amt = 4;
+
+             imm = opnd->imm.value;
+
+             if (shift_amt > 0)
+               {
+                 /* The offset value in a PC-relative (or PCC-relative) branch
+                    instruction is always encoded without the lowest alignment
+                    bits, i.e. 2 bits for PC and 4 bits for PCC.  */
+                 if (!value_aligned_p (imm, 1 << shift_amt))
+                   {
+                     set_unaligned_error (mismatch_detail, idx, 1 << shift_amt);
+                     return 0;
+                   }
+                 /* Right shift by 2 so that we can carry out the following check
+                    canonically.  */
+                 imm >>= shift_amt;
+               }
+             size = get_operand_fields_width (get_operand_from_code (type));
+             if (!value_fit_signed_field_p (imm, size))
                {
-                 set_unaligned_error (mismatch_detail, idx, 4);
+                 set_other_error (mismatch_detail, idx,
+                                  _("immediate out of range"));
                  return 0;
                }
-             /* Right shift by 2 so that we can carry out the following check
-                canonically.  */
-             imm >>= 2;
-           }
-         size = get_operand_fields_width (get_operand_from_code (type));
-         if (!value_fit_signed_field_p (imm, size))
-           {
-             set_other_error (mismatch_detail, idx,
-                              _("immediate out of range"));
-             return 0;
+             break;
            }
-         break;
 
        case AARCH64_OPND_SME_ADDR_RI_U4xVL:
          if (!value_in_range_p (opnd->addr.offset.imm, 0, 15))
@@ -3873,10 +3886,17 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
       break;
 
     case AARCH64_OPND_ADDR_PCREL14:
+    case AARCH64_OPND_ADDR_PCREL17:
     case AARCH64_OPND_ADDR_PCREL19:
     case AARCH64_OPND_ADDR_PCREL21:
     case AARCH64_OPND_ADDR_PCREL26:
       addr = pc + AARCH64_PCREL_OFFSET + opnd->imm.value;
+
+      /* For A64C PCREL17, the final address is rounded down to align to
+         capability boundary.  */
+      if (opnd->type == AARCH64_OPND_ADDR_PCREL17)
+       addr = addr & ~(uint64_t) 0xf;
+
       if (pcrel_p)
        *pcrel_p = 1;
       if (address)
index a774d38f8207265ac5cdd2dfe26e441c74d939de..78bd4d801f34bd2248ac097b0ffa0f48f193f1d9 100644 (file)
@@ -182,6 +182,7 @@ enum aarch64_field_kind
   FLD_form,
   FLD_capaddr_simm7,
   FLD_a64c_index2,
+  FLD_imm17,
 };
 
 /* Field description.  */
index f70d9a5efac59daf1eeabc6df04059d9b7ebaa2d..dbfbf4404101d18d09677eb2e2f8854fa30acb7e 100644 (file)
   QLF2(X, S_D),                        \
 }
 
+# define QL2_A64C_CA_PCREL     \
+{                              \
+  QLF2(CA,NIL),                        \
+}
+
 #define QL3_A64C_CA_CA_NIL     \
 {                              \
  QLF3(CA, CA, NIL),            \
@@ -4206,6 +4211,8 @@ const struct aarch64_opcode aarch64_opcode_table[] =
   A64C_INSN ("ldp", 0x22c00000, 0xbfc00000, ldstpair_indexed, 0, OP3 (Cat, Cat2, A64C_ADDR_SIMM7), QL3_A64C_CA_CA_ADDR, 0),
   A64C_INSN ("stp", 0x22800000, 0xbfc00000, ldstpair_indexed, 0, OP3 (Cat, Cat2, A64C_ADDR_SIMM7), QL3_A64C_CA_CA_ADDR, 0),
 
+  A64C_INSN ("ldr", 0x82000000, 0xffc00000, loadlit, OP_LDR_LIT_2, OP2 (Cat, ADDR_PCREL17), QL2_A64C_CA_PCREL, 0),
+
   A64C_INSN ("ldct", 0xc2c4b000, 0xfffffc00, a64c, 0, OP2 (Rt, ADDR_SIMPLE), QL2_A64C_X_ADDR, 0),
   A64C_INSN ("stct", 0xc2c49000, 0xfffffc00, a64c, 0, OP2 (Rt, ADDR_SIMPLE), QL2_A64C_X_ADDR, 0),
 
@@ -6181,4 +6188,6 @@ const struct aarch64_opcode aarch64_opcode_table[] =
       "a capability address with base register (no offset)")           \
     Y(ADDRESS, addr_simm, "A64C_ADDR_SIMM7", 0,                                \
       F(FLD_imm7,FLD_a64c_index2),                                     \
-      "an address with 7-bit signed immediate offset")
+      "an address with 7-bit signed immediate offset")                 \
+    Y(ADDRESS, imm, "ADDR_PCREL17", OPD_F_SEXT | OPD_F_SHIFT_BY_4,     \
+      F(FLD_imm17), "17-bit PC-relative address")