aboutsummaryrefslogtreecommitdiff
path: root/bfd/elfnn-loongarch.c
diff options
context:
space:
mode:
authormengqinggang <mengqinggang@loongson.cn>2023-09-28 16:41:15 +0800
committerliuzhensong <liuzhensong@loongson.cn>2023-12-18 18:36:21 +0800
commitdc5f359ed6a36d2c895d89c3e4886f3a2b6d9232 (patch)
treeca60c74de15fdc76c54e8eb3a7d881078f3585d7 /bfd/elfnn-loongarch.c
parentd51cd0f64c6d3bd235f140ed71cc2c3e0b87a5ff (diff)
downloadbinutils-dc5f359ed6a36d2c895d89c3e4886f3a2b6d9232.zip
binutils-dc5f359ed6a36d2c895d89c3e4886f3a2b6d9232.tar.gz
binutils-dc5f359ed6a36d2c895d89c3e4886f3a2b6d9232.tar.bz2
LoongArch: Add new relocation R_LARCH_CALL36
R_LARCH_CALL36 is used for medium code model function call pcaddu18i+jirl, and these two instructions must adjacent. The LoongArch ABI v2.20 at here: https://github.com/loongson/la-abi-specs.
Diffstat (limited to 'bfd/elfnn-loongarch.c')
-rw-r--r--bfd/elfnn-loongarch.c19
1 files changed, 13 insertions, 6 deletions
diff --git a/bfd/elfnn-loongarch.c b/bfd/elfnn-loongarch.c
index 024c5d4..aa88ee8 100644
--- a/bfd/elfnn-loongarch.c
+++ b/bfd/elfnn-loongarch.c
@@ -780,6 +780,7 @@ loongarch_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
case R_LARCH_B16:
case R_LARCH_B21:
case R_LARCH_B26:
+ case R_LARCH_CALL36:
if (h != NULL)
{
h->needs_plt = 1;
@@ -1884,20 +1885,24 @@ loongarch_check_offset (const Elf_Internal_Rela *rel,
ret; \
})
+/* Write immediate to instructions. */
+
static bfd_reloc_status_type
loongarch_reloc_rewrite_imm_insn (const Elf_Internal_Rela *rel,
const asection *input_section ATTRIBUTE_UNUSED,
reloc_howto_type *howto, bfd *input_bfd,
bfd_byte *contents, bfd_vma reloc_val)
{
- int bits = bfd_get_reloc_size (howto) * 8;
- uint32_t insn = bfd_get (bits, input_bfd, contents + rel->r_offset);
-
+ /* Adjust the immediate based on alignment and
+ its position in the instruction. */
if (!loongarch_adjust_reloc_bitsfield (input_bfd, howto, &reloc_val))
return bfd_reloc_overflow;
- insn = (insn & (uint32_t)howto->src_mask)
- | ((insn & (~(uint32_t)howto->dst_mask)) | reloc_val);
+ int bits = bfd_get_reloc_size (howto) * 8;
+ uint64_t insn = bfd_get (bits, input_bfd, contents + rel->r_offset);
+
+ /* Write immediate to instruction. */
+ insn = (insn & ~howto->dst_mask) | (reloc_val & howto->dst_mask);
bfd_put (bits, input_bfd, insn, contents + rel->r_offset);
@@ -2120,6 +2125,7 @@ perform_relocation (const Elf_Internal_Rela *rel, asection *input_section,
case R_LARCH_TLS_GD_PC_HI20:
case R_LARCH_TLS_GD_HI20:
case R_LARCH_PCREL20_S2:
+ case R_LARCH_CALL36:
r = loongarch_check_offset (rel, input_section);
if (r != bfd_reloc_ok)
break;
@@ -3127,9 +3133,10 @@ loongarch_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
break;
/* New reloc types. */
+ case R_LARCH_B16:
case R_LARCH_B21:
case R_LARCH_B26:
- case R_LARCH_B16:
+ case R_LARCH_CALL36:
unresolved_reloc = false;
if (is_undefweak)
{