+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
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. */
#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
/* 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 */
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:
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. */
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)
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:
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:
"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",
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
+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
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)
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:
: 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);
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)
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)
{
+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.
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
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
OP_PRFUM,
OP_LDR_LIT,
+ OP_LDR_LIT_2,
OP_LDRV_LIT,
OP_LDRSW_LIT,
OP_PRFM_LIT,
+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.
{ 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
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))
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)
FLD_form,
FLD_capaddr_simm7,
FLD_a64c_index2,
+ FLD_imm17,
};
/* Field description. */
QLF2(X, S_D), \
}
+# define QL2_A64C_CA_PCREL \
+{ \
+ QLF2(CA,NIL), \
+}
+
#define QL3_A64C_CA_CA_NIL \
{ \
QLF3(CA, CA, NIL), \
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),
"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")