[PATCH v5] RISC-V: Add new relocation types for global array accesses with non-constant indices
Liqin Weng <[email protected]> Tue, 4 Aug 2026 15:52:02 +0800
| Newsgroups | gmane.comp.gnu.binutils |
|---|---|
| Message-ID | <[email protected]> |
From: wengliqin <[email protected]> This patch introduces support for new RISC-V relocation types (R_RISCV_BASE_IDX_*) to enable more efficient code generation for global array accesses with non-constant array subscripts. New Reloc includes : R_RISCV_BASE_IDX_LO12_I/R_RISCV_BASE_IDX_LO12_S/R_RISCV_BASE_IDX_ADD RISC-V PSABI specification: https://github.com/riscv-non-isa/riscv-elf-psabi-doc/pull/489 bfd/ChangeLog: * bfd-in2.h : Add new relocation type. * elfnn-riscv.c : Define relocation information for new relocation type. Convert the internal R_RISCV_BASE_IDX_GPREL_* relocations produced by relaxation back to their public equivalents before they can be written out, e.g. via --emit-relocs/-r. * elfxx-riscv.c : Add HOWTOs for new relocation type. Add riscv_internal_reloc_map and riscv_elf_reloc_type_lookup to map each internal-only relaxed relocation type to the elf type that should be emitted in its place. * libbfd.h: Regenerate. * reloc.c: Document BFD_RELOC_RISCV_BASE_IDX_* type. gas/ChangeLog: * config/tc-riscv.c: Add support for RISC-V Base IDX relocations * testsuite/gas/riscv/base-idx-add.s: New test for BASE_IDX*. * testsuite/gas/riscv/base-idx-add.d: New test. * testsuite/gas/riscv/base-idx-add.l: New test. include/ChangeLog: * elf/riscv.h: Update relocation definitions for new BASE_IDX* Type. ld/ChangeLog: * testsuite/ld-riscv-elf/base-idx-relax-gp.s: New test source exercising base-idx relaxation to gp. * testsuite/ld-riscv-elf/base-idx-relax-x0.s: New test source exercising base-idx relaxation to x0 only, covering both a defined symbol (symL) and an undefined weak symbol referenced with a non-zero addend (weakL+0x8). * testsuite/ld-riscv-elf/base-idx-relax-near.ld: New linker script placing __global_pointer$ within gp-relaxable range. * testsuite/ld-riscv-elf/base-idx-relax-far.ld: New linker script keeping data out of gp/x0 range so relaxation cannot fire. * testsuite/ld-riscv-elf/base-idx-relax-x0.ld: New linker script exercising the x0-only relaxation path. * testsuite/ld-riscv-elf/base-idx-relax-medlow-near.d, testsuite/ld-riscv-elf/base-idx-relax-medlow-near-emit-relocs.d, testsuite/ld-riscv-elf/base-idx-relax-medlow-far.d, testsuite/ld-riscv-elf/base-idx-relax-medlow-far-emit-relocs.d, testsuite/ld-riscv-elf/base-idx-relax-x0.d, testsuite/ld-riscv-elf/base-idx-relax-x0-emit-relocs.d: New dump tests covering base-idx relaxation to gp and x0 for both defined and weak symbols, with and without --emit-relocs; confirm the internal R_RISCV_BASE_IDX_GPREL_* relocation types never leak into --emit-relocs output. * testsuite/ld-riscv-elf/ld-riscv-elf.exp: Register the new base-idx-relax dump tests. opcodes/ChangeLog: * riscv-opc.c : add new pattern for add/shaxadd/add.uw/shxadd.uw * riscv-dis.c (print_insn_args): Add a no-op case for the '1' relaxation-marker operand, so that disassembling an instruction whose only matching opcode-table row now includes it (e.g. add, shNadd) no longer hits "undefined modifier" -- the marker carries no encoding bits, so nothing is printed for it. --- This Patch update: 1. clang-format 2. add the weak symbol tests && remove the implement add x0, x0, zero(weak symbol may relax gp, so remove 'add a0, a0, zero' will be implemented in the new patch) 3. Convert the internal 'R_RISCV_BASE_IDX_GPREL_*' relocations produced by relaxation back to their elf equivalents before they can be written out, eg. via --emit-relocs/-r. bfd/bfd-in2.h | 3 + bfd/elfnn-riscv.c | 92 +++++++++++- bfd/elfxx-riscv.c | 138 +++++++++++++++++- bfd/libbfd.h | 3 + bfd/reloc.c | 6 + gas/config/tc-riscv.c | 34 ++++- gas/testsuite/gas/riscv/base-idx-add.d | 3 + gas/testsuite/gas/riscv/base-idx-add.l | 10 ++ gas/testsuite/gas/riscv/base-idx-add.s | 19 +++ include/elf/riscv.h | 6 + .../ld-riscv-elf/base-idx-relax-far.ld | 21 +++ ld/testsuite/ld-riscv-elf/base-idx-relax-gp.s | 36 +++++ .../base-idx-relax-medlow-far-emit-relocs.d | 65 +++++++++ .../ld-riscv-elf/base-idx-relax-medlow-far.d | 29 ++++ .../base-idx-relax-medlow-near-emit-relocs.d | 63 ++++++++ .../ld-riscv-elf/base-idx-relax-medlow-near.d | 27 ++++ .../ld-riscv-elf/base-idx-relax-near.ld | 22 +++ .../base-idx-relax-x0-emit-relocs.d | 63 ++++++++ ld/testsuite/ld-riscv-elf/base-idx-relax-x0.d | 27 ++++ .../ld-riscv-elf/base-idx-relax-x0.ld | 28 ++++ ld/testsuite/ld-riscv-elf/base-idx-relax-x0.s | 34 +++++ ld/testsuite/ld-riscv-elf/ld-riscv-elf.exp | 6 + opcodes/riscv-dis.c | 6 + opcodes/riscv-opc.c | 20 +-- 24 files changed, 743 insertions(+), 18 deletions(-) create mode 100644 gas/testsuite/gas/riscv/base-idx-add.d create mode 100644 gas/testsuite/gas/riscv/base-idx-add.l create mode 100644 gas/testsuite/gas/riscv/base-idx-add.s create mode 100644 ld/testsuite/ld-riscv-elf/base-idx-relax-far.ld create mode 100644 ld/testsuite/ld-riscv-elf/base-idx-relax-gp.s create mode 100644 ld/testsuite/ld-riscv-elf/base-idx-relax-medlow-far-emit-relocs.d create mode 100644 ld/testsuite/ld-riscv-elf/base-idx-relax-medlow-far.d create mode 100644 ld/testsuite/ld-riscv-elf/base-idx-relax-medlow-near-emit-relocs.d create mode 100644 ld/testsuite/ld-riscv-elf/base-idx-relax-medlow-near.d create mode 100644 ld/testsuite/ld-riscv-elf/base-idx-relax-near.ld create mode 100644 ld/testsuite/ld-riscv-elf/base-idx-relax-x0-emit-relocs.d create mode 100644 ld/testsuite/ld-riscv-elf/base-idx-relax-x0.d create mode 100644 ld/testsuite/ld-riscv-elf/base-idx-relax-x0.ld create mode 100644 ld/testsuite/ld-riscv-elf/base-idx-relax-x0.s diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h index d4e4f8e4375..71044bcd3f1 100644 --- a/bfd/bfd-in2.h +++ b/bfd/bfd-in2.h @@ -5351,6 +5351,9 @@ enum bfd_reloc_code_real BFD_RELOC_RISCV_TLSDESC_LOAD_LO12, BFD_RELOC_RISCV_TLSDESC_ADD_LO12, BFD_RELOC_RISCV_TLSDESC_CALL, + BFD_RELOC_RISCV_BASE_IDX_LO12_I, + BFD_RELOC_RISCV_BASE_IDX_LO12_S, + BFD_RELOC_RISCV_BASE_IDX_ADD, BFD_RELOC_RISCV_ALIGN, BFD_RELOC_RISCV_RVC_BRANCH, BFD_RELOC_RISCV_RVC_JUMP, diff --git a/bfd/elfnn-riscv.c b/bfd/elfnn-riscv.c index d3963ec9a58..f8ed892edf3 100644 --- a/bfd/elfnn-riscv.c +++ b/bfd/elfnn-riscv.c @@ -1999,7 +1999,9 @@ perform_relocation (const reloc_howto_type *howto, break; case R_RISCV_LO12_I: + case R_RISCV_BASE_IDX_LO12_I: case R_RISCV_GPREL_I: + case R_RISCV_BASE_IDX_GPREL_I: case R_RISCV_TPREL_LO12_I: case R_RISCV_TPREL_I: case R_RISCV_PCREL_LO12_I: @@ -2009,7 +2011,9 @@ perform_relocation (const reloc_howto_type *howto, break; case R_RISCV_LO12_S: + case R_RISCV_BASE_IDX_LO12_S: case R_RISCV_GPREL_S: + case R_RISCV_BASE_IDX_GPREL_S: case R_RISCV_TPREL_LO12_S: case R_RISCV_TPREL_S: case R_RISCV_PCREL_LO12_S: @@ -2130,6 +2134,8 @@ perform_relocation (const reloc_howto_type *howto, case R_RISCV_32_PCREL: case R_RISCV_TLS_DTPREL32: case R_RISCV_TLS_DTPREL64: + case R_RISCV_BASE_IDX_ADD: + case R_RISCV_BASE_IDX_GPREL_ADD: break; case R_RISCV_DELETE: @@ -2389,6 +2395,21 @@ riscv_resolve_pcrel_lo_relocs (riscv_pcrel_relocs *p) return true; } +static void +change_internal_relocs_to_elf_relocs (Elf_Internal_Rela *relocs, + Elf_Internal_Rela *relend) +{ + Elf_Internal_Rela *rel; + + for (rel = relocs; rel < relend; rel++) + { + unsigned int r_type = ELFNN_R_TYPE (rel->r_info); + unsigned int elf_type = riscv_elf_reloc_type_lookup (r_type); + if (elf_type != r_type) + rel->r_info = ELFNN_R_INFO (ELFNN_R_SYM (rel->r_info), elf_type); + } +} + /* Relocate a RISC-V ELF section. The RELOCATE_SECTION function is called by the new ELF backend linker @@ -2722,6 +2743,9 @@ riscv_elf_relocate_section (bfd *output_bfd, case R_RISCV_HI20: case R_RISCV_LO12_I: case R_RISCV_LO12_S: + case R_RISCV_BASE_IDX_LO12_I: + case R_RISCV_BASE_IDX_LO12_S: + case R_RISCV_BASE_IDX_ADD: goto do_relocation; case R_RISCV_PCREL_HI20: @@ -2788,6 +2812,9 @@ riscv_elf_relocate_section (bfd *output_bfd, case R_RISCV_RVC_LUI: case R_RISCV_LO12_I: case R_RISCV_LO12_S: + case R_RISCV_BASE_IDX_LO12_I: + case R_RISCV_BASE_IDX_LO12_S: + case R_RISCV_BASE_IDX_ADD: case R_RISCV_SET6: case R_RISCV_SET8: case R_RISCV_SET16: @@ -3089,6 +3116,48 @@ riscv_elf_relocate_section (bfd *output_bfd, break; } + case R_RISCV_BASE_IDX_GPREL_I: + case R_RISCV_BASE_IDX_GPREL_S: + { + /* After relaxation, the ld/st uses (gp + index) as its base + register, so the immediate encodes the symbol's displacement + from gp. perform_relocation will encode the final value + from (relocation + r_addend). */ + bfd_vma gp = riscv_global_pointer_value (info); + bfd_vma disp = relocation + rel->r_addend - gp; + bool x0_base = VALID_ITYPE_IMM (relocation + rel->r_addend); + bool gp_base = (r_type == R_RISCV_BASE_IDX_GPREL_I) + ? VALID_ITYPE_IMM (disp) + : VALID_STYPE_IMM (disp); + if (!x0_base) + { + /* Only when gp is actually used as the base do we need to + express the immediate as a displacement from gp. */ + if (gp_base) + rel->r_addend -= gp; + else + r = bfd_reloc_overflow; + } + break; + } + + case R_RISCV_BASE_IDX_GPREL_ADD: + { + /* Rewrite rs2 of the add/shXadd instruction to use gp or x0 as the + base register after relaxation. The same encoding change + applies to both add and shXadd — the opcode itself is left + intact. */ + bfd_vma insn = bfd_getl32 (contents + rel->r_offset); + bool x0_base = VALID_ITYPE_IMM (relocation + rel->r_addend); + insn &= ~(OP_MASK_RS2 << OP_SH_RS2); + if (!x0_base) + { + insn |= X_GP << OP_SH_RS2; + } + bfd_putl32 (insn, contents + rel->r_offset); + break; + } + case R_RISCV_PCREL_HI20: absolute = riscv_zero_pcrel_hi_reloc (rel, info, pc, &relocation, contents, howto); @@ -3434,6 +3503,8 @@ riscv_elf_relocate_section (bfd *output_bfd, goto out; } + change_internal_relocs_to_elf_relocs (relocs, relend); + ret = riscv_resolve_pcrel_lo_relocs (&pcrel_relocs); out: riscv_free_pcrel_relocs (&pcrel_relocs); @@ -5148,6 +5219,18 @@ _bfd_riscv_relax_lui (bfd *abfd, rel->r_info = ELFNN_R_INFO (sym, R_RISCV_GPREL_S); return true; + case R_RISCV_BASE_IDX_LO12_I: + rel->r_info = ELFNN_R_INFO (sym, R_RISCV_BASE_IDX_GPREL_I); + return true; + + case R_RISCV_BASE_IDX_LO12_S: + rel->r_info = ELFNN_R_INFO (sym, R_RISCV_BASE_IDX_GPREL_S); + return true; + + case R_RISCV_BASE_IDX_ADD: + rel->r_info = ELFNN_R_INFO (sym, R_RISCV_BASE_IDX_GPREL_ADD); + return true; + case R_RISCV_HI20: /* Delete unnecessary LUI and reuse the reloc. */ *again = true; @@ -5160,7 +5243,7 @@ _bfd_riscv_relax_lui (bfd *abfd, } /* Can we relax LUI to C.LUI? Alignment might move the section forward; - account for this assuming page alignment at worst. In the presence of + account for this assuming page alignment at worst. In the presence of RELRO segment the linker aligns it by one page size, therefore sections after the segment can be moved more than one page. */ @@ -5537,9 +5620,10 @@ _bfd_riscv_relax_section (bfd *abfd, asection *sec, if (type == R_RISCV_CALL || type == R_RISCV_CALL_PLT) relax_func = _bfd_riscv_relax_call; - else if (type == R_RISCV_HI20 - || type == R_RISCV_LO12_I - || type == R_RISCV_LO12_S) + else if (type == R_RISCV_HI20 || type == R_RISCV_LO12_I + || type == R_RISCV_LO12_S || type == R_RISCV_BASE_IDX_LO12_I + || type == R_RISCV_BASE_IDX_LO12_S + || type == R_RISCV_BASE_IDX_ADD) relax_func = _bfd_riscv_relax_lui; else if (type == R_RISCV_TPREL_HI20 || type == R_RISCV_TPREL_ADD diff --git a/bfd/elfxx-riscv.c b/bfd/elfxx-riscv.c index ee962b4f6f1..0db219b5521 100644 --- a/bfd/elfxx-riscv.c +++ b/bfd/elfxx-riscv.c @@ -876,7 +876,63 @@ static const reloc_howto_type howto_table[] = false, /* partial_inplace */ 0, /* src_mask */ ENCODE_ITYPE_IMM (-1U), /* dst_mask */ - false) /* pcrel_offset */ + false), /* pcrel_offset */ + + /* Reserved slots 66-76. */ + EMPTY_HOWTO (66), + EMPTY_HOWTO (67), + EMPTY_HOWTO (68), + EMPTY_HOWTO (69), + EMPTY_HOWTO (70), + EMPTY_HOWTO (71), + EMPTY_HOWTO (72), + EMPTY_HOWTO (73), + EMPTY_HOWTO (74), + EMPTY_HOWTO (75), + EMPTY_HOWTO (76), + + /* Global array accesses with non-constant subscript (base + index). */ + HOWTO (R_RISCV_BASE_IDX_LO12_I, /* type */ + 0, /* rightshift */ + 4, /* size */ + 32, /* bitsize */ + false, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont, /* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_RISCV_BASE_IDX_LO12_I", /* name */ + false, /* partial_inplace */ + 0, /* src_mask */ + ENCODE_ITYPE_IMM (-1U), /* dst_mask */ + false), /* pcrel_offset */ + + HOWTO (R_RISCV_BASE_IDX_LO12_S, /* type */ + 0, /* rightshift */ + 4, /* size */ + 32, /* bitsize */ + false, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont, /* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_RISCV_BASE_IDX_LO12_S", /* name */ + false, /* partial_inplace */ + 0, /* src_mask */ + ENCODE_STYPE_IMM (-1U), /* dst_mask */ + false), /* pcrel_offset */ + + HOWTO (R_RISCV_BASE_IDX_ADD, /* type */ + 0, /* rightshift */ + 4, /* size */ + 32, /* bitsize */ + false, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont, /* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_RISCV_BASE_IDX_ADD", /* name */ + false, /* partial_inplace */ + 0, /* src_mask */ + 0, /* dst_mask */ + false), /* pcrel_offset */ }; static const reloc_howto_type howto_table_internal[] = @@ -961,6 +1017,50 @@ static const reloc_howto_type howto_table_internal[] = 0, /* src_mask */ ENCODE_STYPE_IMM (-1U), /* dst_mask */ false), /* pcrel_offset */ + + /* Global array accesses with non-constant subscript (base + index), + after relaxation. */ + HOWTO (R_RISCV_BASE_IDX_GPREL_I, /* type */ + 0, /* rightshift */ + 4, /* size */ + 32, /* bitsize */ + false, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont, /* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_RISCV_BASE_IDX_GPREL_I", /* name */ + false, /* partial_inplace */ + 0, /* src_mask */ + ENCODE_ITYPE_IMM (-1U), /* dst_mask */ + false), /* pcrel_offset */ + + HOWTO (R_RISCV_BASE_IDX_GPREL_S, /* type */ + 0, /* rightshift */ + 4, /* size */ + 32, /* bitsize */ + false, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont, /* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_RISCV_BASE_IDX_GPREL_S", /* name */ + false, /* partial_inplace */ + 0, /* src_mask */ + ENCODE_STYPE_IMM (-1U), /* dst_mask */ + false), /* pcrel_offset */ + + HOWTO (R_RISCV_BASE_IDX_GPREL_ADD, /* type */ + 0, /* rightshift */ + 4, /* size */ + 32, /* bitsize */ + false, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont, /* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_RISCV_BASE_IDX_GPREL_ADD", /* name */ + false, /* partial_inplace */ + 0, /* src_mask */ + 0, /* dst_mask */ + false) }; /* A mapping from BFD reloc types to RISC-V ELF reloc types. */ @@ -1023,6 +1123,26 @@ static const struct elf_reloc_map riscv_reloc_map[] = { BFD_RELOC_RISCV_32_PCREL, R_RISCV_32_PCREL }, { BFD_RELOC_RISCV_SET_ULEB128, R_RISCV_SET_ULEB128 }, { BFD_RELOC_RISCV_SUB_ULEB128, R_RISCV_SUB_ULEB128 }, + { BFD_RELOC_RISCV_BASE_IDX_LO12_I, R_RISCV_BASE_IDX_LO12_I }, + { BFD_RELOC_RISCV_BASE_IDX_LO12_S, R_RISCV_BASE_IDX_LO12_S }, + { BFD_RELOC_RISCV_BASE_IDX_ADD, R_RISCV_BASE_IDX_ADD }, +}; + +/* A mapping from internal-only relocation types (produced by the linker's + relaxation passes; numbered after R_RISCV_max and never valid in an + object file) to the elf relocation type that should be substituted + before the type is written out, e.g. for --emit-relocs/-r output. */ +struct internal_reloc_map +{ + unsigned int internal_type; + enum elf_riscv_reloc_type elf_val; +}; + +/* TODO: add another internal relocation type */ +static const struct internal_reloc_map riscv_internal_reloc_map[] = { + { R_RISCV_BASE_IDX_GPREL_I, R_RISCV_BASE_IDX_LO12_I }, + { R_RISCV_BASE_IDX_GPREL_S, R_RISCV_BASE_IDX_LO12_S }, + { R_RISCV_BASE_IDX_GPREL_ADD, R_RISCV_BASE_IDX_ADD }, }; struct riscv_profiles @@ -1059,6 +1179,22 @@ riscv_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, const char *r_name) return NULL; } +/* If R_TYPE is one of the internal-only relocation types produced by + relaxation, return the elf relocation type that should be emitted + in its place. Otherwise return R_TYPE unchanged. */ + +unsigned int +riscv_elf_reloc_type_lookup (unsigned int r_type) +{ + unsigned int i; + + for (i = 0; i < ARRAY_SIZE (riscv_internal_reloc_map); i++) + if (riscv_internal_reloc_map[i].internal_type == r_type) + return riscv_internal_reloc_map[i].elf_val; + + return r_type; +} + reloc_howto_type * riscv_elf_rtype_to_howto (bfd *abfd, unsigned int r_type) { diff --git a/bfd/libbfd.h b/bfd/libbfd.h index a27134dcd78..ef4f96a1747 100644 --- a/bfd/libbfd.h +++ b/bfd/libbfd.h @@ -2362,6 +2362,9 @@ static const char *const bfd_reloc_code_real_names[] = { "@@uninitialized@@", "BFD_RELOC_RISCV_TLSDESC_LOAD_LO12", "BFD_RELOC_RISCV_TLSDESC_ADD_LO12", "BFD_RELOC_RISCV_TLSDESC_CALL", + "BFD_RELOC_RISCV_BASE_IDX_LO12_I", + "BFD_RELOC_RISCV_BASE_IDX_LO12_S", + "BFD_RELOC_RISCV_BASE_IDX_ADD", "BFD_RELOC_RISCV_ALIGN", "BFD_RELOC_RISCV_RVC_BRANCH", "BFD_RELOC_RISCV_RVC_JUMP", diff --git a/bfd/reloc.c b/bfd/reloc.c index 98343696a33..6f6ff98c4a5 100644 --- a/bfd/reloc.c +++ b/bfd/reloc.c @@ -4861,6 +4861,12 @@ ENUMX BFD_RELOC_RISCV_TLSDESC_ADD_LO12 ENUMX BFD_RELOC_RISCV_TLSDESC_CALL +ENUMX + BFD_RELOC_RISCV_BASE_IDX_LO12_I +ENUMX + BFD_RELOC_RISCV_BASE_IDX_LO12_S +ENUMX + BFD_RELOC_RISCV_BASE_IDX_ADD ENUMX BFD_RELOC_RISCV_ALIGN ENUMX diff --git a/gas/config/tc-riscv.c b/gas/config/tc-riscv.c index 6bcf53832a0..11d9db0f977 100644 --- a/gas/config/tc-riscv.c +++ b/gas/config/tc-riscv.c @@ -1953,9 +1953,11 @@ riscv_apply_const_reloc (bfd_reloc_code_real_type reloc_type, bfd_vma value) return ENCODE_UTYPE_IMM (RISCV_CONST_HIGH_PART (value)); case BFD_RELOC_RISCV_LO12_S: + case BFD_RELOC_RISCV_BASE_IDX_LO12_S: return ENCODE_STYPE_IMM (value); case BFD_RELOC_RISCV_LO12_I: + case BFD_RELOC_RISCV_BASE_IDX_LO12_I: return ENCODE_ITYPE_IMM (value); default: @@ -2022,7 +2024,8 @@ append_insn (struct riscv_cl_insn *ip, expressionS *address_expr, if (reloc_type == BFD_RELOC_RISCV_HI20 || reloc_type == BFD_RELOC_RISCV_PCREL_HI20 || reloc_type == BFD_RELOC_RISCV_TPREL_HI20 - || reloc_type == BFD_RELOC_RISCV_TPREL_ADD) + || reloc_type == BFD_RELOC_RISCV_TPREL_ADD + || reloc_type == BFD_RELOC_RISCV_BASE_IDX_ADD) { frag_wane (frag_now); frag_new (0); @@ -2455,6 +2458,7 @@ static const struct percent_op_match percent_op_utype[] = static const struct percent_op_match percent_op_itype[] = { {"lo", BFD_RELOC_RISCV_LO12_I}, + {"base_idx_lo", BFD_RELOC_RISCV_BASE_IDX_LO12_I}, {"tprel_lo", BFD_RELOC_RISCV_TPREL_LO12_I}, {"pcrel_lo", BFD_RELOC_RISCV_PCREL_LO12_I}, {"tlsdesc_load_lo", BFD_RELOC_RISCV_TLSDESC_LOAD_LO12}, @@ -2465,6 +2469,7 @@ static const struct percent_op_match percent_op_itype[] = static const struct percent_op_match percent_op_stype[] = { {"lo", BFD_RELOC_RISCV_LO12_S}, + {"base_idx_lo", BFD_RELOC_RISCV_BASE_IDX_LO12_S}, {"tprel_lo", BFD_RELOC_RISCV_TPREL_LO12_S}, {"pcrel_lo", BFD_RELOC_RISCV_PCREL_LO12_S}, {0, 0} @@ -2474,6 +2479,7 @@ static const struct percent_op_match percent_op_relax_only[] = { {"tlsdesc_call", BFD_RELOC_RISCV_TLSDESC_CALL}, {"tprel_add", BFD_RELOC_RISCV_TPREL_ADD}, + {"base_idx_add", BFD_RELOC_RISCV_BASE_IDX_ADD}, {0, 0} }; @@ -3644,9 +3650,23 @@ riscv_ip (char *str, struct riscv_cl_insn *ip, expressionS *imm_expr, *imm_reloc = BFD_RELOC_RISCV_LO12_I; goto load_store; case '1': - /* This is used for TLS relocations that acts as relaxation - markers and do not change the instruction encoding, - i.e. %tprel_add and %tlsdesc_call. */ + /* This operand is a relaxation marker that does not change + the instruction encoding, e.g. %tprel_add, %tlsdesc_call + and %base_idx_add. It is mandatory when a literal ',' + precedes it in the operand string (e.g. "d,s,1" for + jalr's %tlsdesc_call), in which case that ',' is already + consumed by the general ',' handling above and *asarg + points straight at the marker text. It is optional when + it directly follows another operand letter with no + separating ',' in the operand string (e.g. "d,s,t1" on + add/shNadd/add.uw for %base_idx_add), in which case we + must recognise here whether it was actually given -- + mirrors the "optional vector mask" handling of 'Vm' + above. */ + if (*asarg == '\0') + continue; + if (*asarg == ',') + ++asarg; p = percent_op_relax_only; goto alu_op; case '0': /* AMO displacement, which must be zero. */ @@ -4687,6 +4707,8 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg) case BFD_RELOC_RISCV_HI20: case BFD_RELOC_RISCV_LO12_I: case BFD_RELOC_RISCV_LO12_S: + case BFD_RELOC_RISCV_BASE_IDX_LO12_I: + case BFD_RELOC_RISCV_BASE_IDX_LO12_S: bfd_putl32 (riscv_apply_const_reloc (fixP->fx_r_type, *valP) | bfd_getl32 (buf), buf); if (fixP->fx_addsy == NULL) @@ -4694,6 +4716,10 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg) relaxable = true; break; + case BFD_RELOC_RISCV_BASE_IDX_ADD: + relaxable = true; + break; + case BFD_RELOC_RISCV_GOT_HI20: /* R_RISCV_GOT_HI20 and the following R_RISCV_LO12_I are relaxable only if it is created as a result of la or lga assembler macros. */ diff --git a/gas/testsuite/gas/riscv/base-idx-add.d b/gas/testsuite/gas/riscv/base-idx-add.d new file mode 100644 index 00000000000..488ffbc1956 --- /dev/null +++ b/gas/testsuite/gas/riscv/base-idx-add.d @@ -0,0 +1,3 @@ +#as: -march=rv64imafdc_zbb_zba +#source: base-idx-add.s +#error_output: base-idx-add.l diff --git a/gas/testsuite/gas/riscv/base-idx-add.l b/gas/testsuite/gas/riscv/base-idx-add.l new file mode 100644 index 00000000000..8321b40ccc6 --- /dev/null +++ b/gas/testsuite/gas/riscv/base-idx-add.l @@ -0,0 +1,10 @@ +.*: Assembler messages: +.*: Error: illegal operands `amoadd.w x8,x9,%base_idx_add\(sym\)\(x10\)' +.*: Error: illegal operands `add a5,a5,a0,0' +.*: Error: illegal operands `sh1add a0,a0,a5,0' +.*: Error: illegal operands `sh1add.uw a0,a0,a5,0' +.*: Error: illegal operands `sh2add a0,a0,a5,0' +.*: Error: illegal operands `sh2add.uw a0,a0,a5,0' +.*: Error: illegal operands `sh3add a0,a0,a5,0' +.*: Error: illegal operands `sh3add.uw a0,a0,a5,0' +.*: Error: illegal operands `add.uw a0,a0,a5,0' diff --git a/gas/testsuite/gas/riscv/base-idx-add.s b/gas/testsuite/gas/riscv/base-idx-add.s new file mode 100644 index 00000000000..47d1b3b5aa3 --- /dev/null +++ b/gas/testsuite/gas/riscv/base-idx-add.s @@ -0,0 +1,19 @@ +.option arch, +a + # Don't allow base_idx_add in amoadd. + amoadd.w x8,x9,%base_idx_add(sym)(x10) + # Do require base_idx_add in 4-operand add. + add a5,a5,a0,0 + sh1add a0,a0,a5,0 + sh1add.uw a0,a0,a5,0 + sh2add a0,a0,a5,0 + sh2add.uw a0,a0,a5,0 + sh3add a0,a0,a5,0 + sh3add.uw a0,a0,a5,0 + add.uw a0,a0,a5,0 + .globl sym + .section .tbss,"awT",@nobits + .align 2 + .type sym, @object + .size sym, 4 +sym: + .zero 4 diff --git a/include/elf/riscv.h b/include/elf/riscv.h index f6ca3d4acd8..a19bee4b684 100644 --- a/include/elf/riscv.h +++ b/include/elf/riscv.h @@ -95,6 +95,9 @@ START_RELOC_NUMBERS (elf_riscv_reloc_type) RELOC_NUMBER (R_RISCV_TLSDESC_LOAD_LO12, 63) RELOC_NUMBER (R_RISCV_TLSDESC_ADD_LO12, 64) RELOC_NUMBER (R_RISCV_TLSDESC_CALL, 65) + RELOC_NUMBER (R_RISCV_BASE_IDX_LO12_I, 77) + RELOC_NUMBER (R_RISCV_BASE_IDX_LO12_S, 78) + RELOC_NUMBER (R_RISCV_BASE_IDX_ADD, 79) END_RELOC_NUMBERS (R_RISCV_max) /* Internal relocations used exclusively by the relaxation pass. */ @@ -105,6 +108,9 @@ END_RELOC_NUMBERS (R_RISCV_max) #define R_RISCV_GPREL_S (R_RISCV_max + 4) #define R_RISCV_TPREL_I (R_RISCV_max + 5) #define R_RISCV_TPREL_S (R_RISCV_max + 6) +#define R_RISCV_BASE_IDX_GPREL_I (R_RISCV_max + 7) +#define R_RISCV_BASE_IDX_GPREL_S (R_RISCV_max + 8) +#define R_RISCV_BASE_IDX_GPREL_ADD (R_RISCV_max + 9) /* Processor specific flags for the ELF header e_flags field. */ diff --git a/ld/testsuite/ld-riscv-elf/base-idx-relax-far.ld b/ld/testsuite/ld-riscv-elf/base-idx-relax-far.ld new file mode 100644 index 00000000000..123f9c4cbe9 --- /dev/null +++ b/ld/testsuite/ld-riscv-elf/base-idx-relax-far.ld @@ -0,0 +1,21 @@ +/* Data symbols reachable by lui/auipc+addi but far from __global_pointer$, + so BASE_IDX gp-relaxation cannot fire. The original instruction sequence + is preserved. */ + +ENTRY(_start) +MEMORY +{ + rom (rx) : ORIGIN = 0x10000, LENGTH = 0x1000 + ram (!rx) : ORIGIN = 0x100000, LENGTH = 0x1000 +} +SECTIONS { + .text : { + *(.text*) + } >rom + + .data : { + *(.data*) + } >ram + + __global_pointer$ = 0x20000; +} diff --git a/ld/testsuite/ld-riscv-elf/base-idx-relax-gp.s b/ld/testsuite/ld-riscv-elf/base-idx-relax-gp.s new file mode 100644 index 00000000000..b157b0b79bb --- /dev/null +++ b/ld/testsuite/ld-riscv-elf/base-idx-relax-gp.s @@ -0,0 +1,36 @@ + .text + .global _start +_start: + +.ifdef __medlow__ + lui a1, %hi(symL) + add a2, a0, a1, %base_idx_add(symL) + add.uw a2, a0, a1, %base_idx_add(symL) + sh1add a2, a0, a1, %base_idx_add(symL) + sh2add a2, a0, a1, %base_idx_add(symL) + sh3add a2, a0, a1, %base_idx_add(symL) + sh3add.uw a2, a0, a1, %base_idx_add(symL) + lbu a3, %base_idx_lo(symL)(a2) + sb a3, %base_idx_lo(symL)(a2) + + lui a1, %hi(weakL) + add a2, a0, a1, %base_idx_add(weakL) + add.uw a2, a0, a1, %base_idx_add(weakL) + sh1add a2, a0, a1, %base_idx_add(weakL) + sh2add a2, a0, a1, %base_idx_add(weakL) + sh3add a2, a0, a1, %base_idx_add(weakL) + sh3add.uw a2, a0, a1, %base_idx_add(weakL) + lbu a3, %base_idx_lo(weakL)(a2) + sb a3, %base_idx_lo(weakL)(a2) +.endif + + .size _start, .-_start + + .data + .global symL +symL: + .dword 0x1111222233334444 + + .weak weakL +weakL: + .dword 0x5555666677778888 diff --git a/ld/testsuite/ld-riscv-elf/base-idx-relax-medlow-far-emit-relocs.d b/ld/testsuite/ld-riscv-elf/base-idx-relax-medlow-far-emit-relocs.d new file mode 100644 index 00000000000..64a2aeb65cc --- /dev/null +++ b/ld/testsuite/ld-riscv-elf/base-idx-relax-medlow-far-emit-relocs.d @@ -0,0 +1,65 @@ +#source: base-idx-relax-gp.s +#as: -march=rv64i_zba -mabi=lp64 --defsym __medlow__=1 +#ld: -Tbase-idx-relax-far.ld -melf64lriscv --relax --emit-relocs +#objdump: -dr -Mno-aliases + +.*:[ ]+file format .* + + +Disassembly of section .text: + +0+10000 <_start>: +[ ]+[0-9a-f]+:[ ]+001005b7[ ]+lui[ ]+a1,0x100 +[ ]+[0-9a-f]+:[ ]+R_RISCV_HI20[ ]+symL +[ ]+[0-9a-f]+:[ ]+R_RISCV_RELAX[ ]+\*ABS\* +[ ]+[0-9a-f]+:[ ]+00b50633[ ]+add[ ]+a2,a0,a1 +[ ]+[0-9a-f]+:[ ]+R_RISCV_BASE_IDX_ADD[ ]+symL +[ ]+[0-9a-f]+:[ ]+R_RISCV_RELAX[ ]+\*ABS\* +[ ]+[0-9a-f]+:[ ]+08b5063b[ ]+add\.uw[ ]+a2,a0,a1 +[ ]+[0-9a-f]+:[ ]+R_RISCV_BASE_IDX_ADD[ ]+symL +[ ]+[0-9a-f]+:[ ]+R_RISCV_RELAX[ ]+\*ABS\* +[ ]+[0-9a-f]+:[ ]+20b52633[ ]+sh1add[ ]+a2,a0,a1 +[ ]+[0-9a-f]+:[ ]+R_RISCV_BASE_IDX_ADD[ ]+symL +[ ]+[0-9a-f]+:[ ]+R_RISCV_RELAX[ ]+\*ABS\* +[ ]+[0-9a-f]+:[ ]+20b54633[ ]+sh2add[ ]+a2,a0,a1 +[ ]+[0-9a-f]+:[ ]+R_RISCV_BASE_IDX_ADD[ ]+symL +[ ]+[0-9a-f]+:[ ]+R_RISCV_RELAX[ ]+\*ABS\* +[ ]+[0-9a-f]+:[ ]+20b56633[ ]+sh3add[ ]+a2,a0,a1 +[ ]+[0-9a-f]+:[ ]+R_RISCV_BASE_IDX_ADD[ ]+symL +[ ]+[0-9a-f]+:[ ]+R_RISCV_RELAX[ ]+\*ABS\* +[ ]+[0-9a-f]+:[ ]+20b5663b[ ]+sh3add\.uw[ ]+a2,a0,a1 +[ ]+[0-9a-f]+:[ ]+R_RISCV_BASE_IDX_ADD[ ]+symL +[ ]+[0-9a-f]+:[ ]+R_RISCV_RELAX[ ]+\*ABS\* +[ ]+[0-9a-f]+:[ ]+00064683[ ]+lbu[ ]+a3,0\(a2\) +[ ]+[0-9a-f]+:[ ]+R_RISCV_BASE_IDX_LO12_I[ ]+symL +[ ]+[0-9a-f]+:[ ]+R_RISCV_RELAX[ ]+\*ABS\* +[ ]+[0-9a-f]+:[ ]+00d60023[ ]+sb[ ]+a3,0\(a2\) +[ ]+[0-9a-f]+:[ ]+R_RISCV_BASE_IDX_LO12_S[ ]+symL +[ ]+[0-9a-f]+:[ ]+R_RISCV_RELAX[ ]+\*ABS\* +[ ]+[0-9a-f]+:[ ]+001005b7[ ]+lui[ ]+a1,0x100 +[ ]+[0-9a-f]+:[ ]+R_RISCV_HI20[ ]+weakL +[ ]+[0-9a-f]+:[ ]+R_RISCV_RELAX[ ]+\*ABS\* +[ ]+[0-9a-f]+:[ ]+00b50633[ ]+add[ ]+a2,a0,a1 +[ ]+[0-9a-f]+:[ ]+R_RISCV_BASE_IDX_ADD[ ]+weakL +[ ]+[0-9a-f]+:[ ]+R_RISCV_RELAX[ ]+\*ABS\* +[ ]+[0-9a-f]+:[ ]+08b5063b[ ]+add\.uw[ ]+a2,a0,a1 +[ ]+[0-9a-f]+:[ ]+R_RISCV_BASE_IDX_ADD[ ]+weakL +[ ]+[0-9a-f]+:[ ]+R_RISCV_RELAX[ ]+\*ABS\* +[ ]+[0-9a-f]+:[ ]+20b52633[ ]+sh1add[ ]+a2,a0,a1 +[ ]+[0-9a-f]+:[ ]+R_RISCV_BASE_IDX_ADD[ ]+weakL +[ ]+[0-9a-f]+:[ ]+R_RISCV_RELAX[ ]+\*ABS\* +[ ]+[0-9a-f]+:[ ]+20b54633[ ]+sh2add[ ]+a2,a0,a1 +[ ]+[0-9a-f]+:[ ]+R_RISCV_BASE_IDX_ADD[ ]+weakL +[ ]+[0-9a-f]+:[ ]+R_RISCV_RELAX[ ]+\*ABS\* +[ ]+[0-9a-f]+:[ ]+20b56633[ ]+sh3add[ ]+a2,a0,a1 +[ ]+[0-9a-f]+:[ ]+R_RISCV_BASE_IDX_ADD[ ]+weakL +[ ]+[0-9a-f]+:[ ]+R_RISCV_RELAX[ ]+\*ABS\* +[ ]+[0-9a-f]+:[ ]+20b5663b[ ]+sh3add\.uw[ ]+a2,a0,a1 +[ ]+[0-9a-f]+:[ ]+R_RISCV_BASE_IDX_ADD[ ]+weakL +[ ]+[0-9a-f]+:[ ]+R_RISCV_RELAX[ ]+\*ABS\* +[ ]+[0-9a-f]+:[ ]+00864683[ ]+lbu[ ]+a3,8\(a2\) +[ ]+[0-9a-f]+:[ ]+R_RISCV_BASE_IDX_LO12_I[ ]+weakL +[ ]+[0-9a-f]+:[ ]+R_RISCV_RELAX[ ]+\*ABS\* +[ ]+[0-9a-f]+:[ ]+00d60423[ ]+sb[ ]+a3,8\(a2\) +[ ]+[0-9a-f]+:[ ]+R_RISCV_BASE_IDX_LO12_S[ ]+weakL +[ ]+[0-9a-f]+:[ ]+R_RISCV_RELAX[ ]+\*ABS\* diff --git a/ld/testsuite/ld-riscv-elf/base-idx-relax-medlow-far.d b/ld/testsuite/ld-riscv-elf/base-idx-relax-medlow-far.d new file mode 100644 index 00000000000..753518183fe --- /dev/null +++ b/ld/testsuite/ld-riscv-elf/base-idx-relax-medlow-far.d @@ -0,0 +1,29 @@ +#source: base-idx-relax-gp.s +#as: -march=rv64i_zba -mabi=lp64 --defsym __medlow__=1 +#ld: -Tbase-idx-relax-far.ld -melf64lriscv --relax +#objdump: -d -Mno-aliases + +.*:[ ]+file format .* + + +Disassembly of section .text: + +0+10000 <_start>: +[ ]+[0-9a-f]+:[ ]+001005b7[ ]+lui[ ]+a1,0x100 +[ ]+[0-9a-f]+:[ ]+00b50633[ ]+add[ ]+a2,a0,a1 +[ ]+[0-9a-f]+:[ ]+08b5063b[ ]+add\.uw[ ]+a2,a0,a1 +[ ]+[0-9a-f]+:[ ]+20b52633[ ]+sh1add[ ]+a2,a0,a1 +[ ]+[0-9a-f]+:[ ]+20b54633[ ]+sh2add[ ]+a2,a0,a1 +[ ]+[0-9a-f]+:[ ]+20b56633[ ]+sh3add[ ]+a2,a0,a1 +[ ]+[0-9a-f]+:[ ]+20b5663b[ ]+sh3add\.uw[ ]+a2,a0,a1 +[ ]+[0-9a-f]+:[ ]+00064683[ ]+lbu[ ]+a3,0\(a2\) +[ ]+[0-9a-f]+:[ ]+00d60023[ ]+sb[ ]+a3,0\(a2\) +[ ]+[0-9a-f]+:[ ]+001005b7[ ]+lui[ ]+a1,0x100 +[ ]+[0-9a-f]+:[ ]+00b50633[ ]+add[ ]+a2,a0,a1 +[ ]+[0-9a-f]+:[ ]+08b5063b[ ]+add\.uw[ ]+a2,a0,a1 +[ ]+[0-9a-f]+:[ ]+20b52633[ ]+sh1add[ ]+a2,a0,a1 +[ ]+[0-9a-f]+:[ ]+20b54633[ ]+sh2add[ ]+a2,a0,a1 +[ ]+[0-9a-f]+:[ ]+20b56633[ ]+sh3add[ ]+a2,a0,a1 +[ ]+[0-9a-f]+:[ ]+20b5663b[ ]+sh3add\.uw[ ]+a2,a0,a1 +[ ]+[0-9a-f]+:[ ]+00864683[ ]+lbu[ ]+a3,8\(a2\) +[ ]+[0-9a-f]+:[ ]+00d60423[ ]+sb[ ]+a3,8\(a2\) diff --git a/ld/testsuite/ld-riscv-elf/base-idx-relax-medlow-near-emit-relocs.d b/ld/testsuite/ld-riscv-elf/base-idx-relax-medlow-near-emit-relocs.d new file mode 100644 index 00000000000..71caba35bb1 --- /dev/null +++ b/ld/testsuite/ld-riscv-elf/base-idx-relax-medlow-near-emit-relocs.d @@ -0,0 +1,63 @@ +#source: base-idx-relax-gp.s +#as: -march=rv64i_zba -mabi=lp64 --defsym __medlow__=1 +#ld: -Tbase-idx-relax-near.ld -melf64lriscv --relax --emit-relocs +#objdump: -dr -Mno-aliases + +.*:[ ]+file format .* + + +Disassembly of section .text: + +0+10000 <_start>: +[ ]+[0-9a-f]+:[ ]+00350633[ ]+add[ ]+a2,a0,gp +[ ]+[0-9a-f]+:[ ]+R_RISCV_NONE[ ]+\*ABS\*\+0x4 +[ ]+[0-9a-f]+:[ ]+R_RISCV_RELAX[ ]+\*ABS\* +[ ]+[0-9a-f]+:[ ]+R_RISCV_BASE_IDX_ADD[ ]+symL +[ ]+[0-9a-f]+:[ ]+R_RISCV_RELAX[ ]+\*ABS\* +[ ]+[0-9a-f]+:[ ]+0835063b[ ]+add\.uw[ ]+a2,a0,gp +[ ]+[0-9a-f]+:[ ]+R_RISCV_BASE_IDX_ADD[ ]+symL +[ ]+[0-9a-f]+:[ ]+R_RISCV_RELAX[ ]+\*ABS\* +[ ]+[0-9a-f]+:[ ]+20352633[ ]+sh1add[ ]+a2,a0,gp +[ ]+[0-9a-f]+:[ ]+R_RISCV_BASE_IDX_ADD[ ]+symL +[ ]+[0-9a-f]+:[ ]+R_RISCV_RELAX[ ]+\*ABS\* +[ ]+[0-9a-f]+:[ ]+20354633[ ]+sh2add[ ]+a2,a0,gp +[ ]+[0-9a-f]+:[ ]+R_RISCV_BASE_IDX_ADD[ ]+symL +[ ]+[0-9a-f]+:[ ]+R_RISCV_RELAX[ ]+\*ABS\* +[ ]+[0-9a-f]+:[ ]+20356633[ ]+sh3add[ ]+a2,a0,gp +[ ]+[0-9a-f]+:[ ]+R_RISCV_BASE_IDX_ADD[ ]+symL +[ ]+[0-9a-f]+:[ ]+R_RISCV_RELAX[ ]+\*ABS\* +[ ]+[0-9a-f]+:[ ]+2035663b[ ]+sh3add\.uw[ ]+a2,a0,gp +[ ]+[0-9a-f]+:[ ]+R_RISCV_BASE_IDX_ADD[ ]+symL +[ ]+[0-9a-f]+:[ ]+R_RISCV_RELAX[ ]+\*ABS\* +[ ]+[0-9a-f]+:[ ]+10064683[ ]+lbu[ ]+a3,256\(a2\) +[ ]+[0-9a-f]+:[ ]+R_RISCV_BASE_IDX_LO12_I[ ]+symL-0x20000 +[ ]+[0-9a-f]+:[ ]+R_RISCV_RELAX[ ]+\*ABS\* +[ ]+[0-9a-f]+:[ ]+10d60023[ ]+sb[ ]+a3,256\(a2\) +[ ]+[0-9a-f]+:[ ]+R_RISCV_BASE_IDX_LO12_S[ ]+symL-0x20000 +[ ]+[0-9a-f]+:[ ]+R_RISCV_RELAX[ ]+\*ABS\* +[ ]+[0-9a-f]+:[ ]+00350633[ ]+add[ ]+a2,a0,gp +[ ]+[0-9a-f]+:[ ]+R_RISCV_NONE[ ]+\*ABS\*\+0x4 +[ ]+[0-9a-f]+:[ ]+R_RISCV_RELAX[ ]+\*ABS\* +[ ]+[0-9a-f]+:[ ]+R_RISCV_BASE_IDX_ADD[ ]+weakL +[ ]+[0-9a-f]+:[ ]+R_RISCV_RELAX[ ]+\*ABS\* +[ ]+[0-9a-f]+:[ ]+0835063b[ ]+add\.uw[ ]+a2,a0,gp +[ ]+[0-9a-f]+:[ ]+R_RISCV_BASE_IDX_ADD[ ]+weakL +[ ]+[0-9a-f]+:[ ]+R_RISCV_RELAX[ ]+\*ABS\* +[ ]+[0-9a-f]+:[ ]+20352633[ ]+sh1add[ ]+a2,a0,gp +[ ]+[0-9a-f]+:[ ]+R_RISCV_BASE_IDX_ADD[ ]+weakL +[ ]+[0-9a-f]+:[ ]+R_RISCV_RELAX[ ]+\*ABS\* +[ ]+[0-9a-f]+:[ ]+20354633[ ]+sh2add[ ]+a2,a0,gp +[ ]+[0-9a-f]+:[ ]+R_RISCV_BASE_IDX_ADD[ ]+weakL +[ ]+[0-9a-f]+:[ ]+R_RISCV_RELAX[ ]+\*ABS\* +[ ]+[0-9a-f]+:[ ]+20356633[ ]+sh3add[ ]+a2,a0,gp +[ ]+[0-9a-f]+:[ ]+R_RISCV_BASE_IDX_ADD[ ]+weakL +[ ]+[0-9a-f]+:[ ]+R_RISCV_RELAX[ ]+\*ABS\* +[ ]+[0-9a-f]+:[ ]+2035663b[ ]+sh3add\.uw[ ]+a2,a0,gp +[ ]+[0-9a-f]+:[ ]+R_RISCV_BASE_IDX_ADD[ ]+weakL +[ ]+[0-9a-f]+:[ ]+R_RISCV_RELAX[ ]+\*ABS\* +[ ]+[0-9a-f]+:[ ]+10864683[ ]+lbu[ ]+a3,264\(a2\) +[ ]+[0-9a-f]+:[ ]+R_RISCV_BASE_IDX_LO12_I[ ]+weakL-0x20000 +[ ]+[0-9a-f]+:[ ]+R_RISCV_RELAX[ ]+\*ABS\* +[ ]+[0-9a-f]+:[ ]+10d60423[ ]+sb[ ]+a3,264\(a2\) +[ ]+[0-9a-f]+:[ ]+R_RISCV_BASE_IDX_LO12_S[ ]+weakL-0x20000 +[ ]+[0-9a-f]+:[ ]+R_RISCV_RELAX[ ]+\*ABS\* diff --git a/ld/testsuite/ld-riscv-elf/base-idx-relax-medlow-near.d b/ld/testsuite/ld-riscv-elf/base-idx-relax-medlow-near.d new file mode 100644 index 00000000000..2249dcde471 --- /dev/null +++ b/ld/testsuite/ld-riscv-elf/base-idx-relax-medlow-near.d @@ -0,0 +1,27 @@ +#source: base-idx-relax-gp.s +#as: -march=rv64i_zba -mabi=lp64 --defsym __medlow__=1 +#ld: -Tbase-idx-relax-near.ld -melf64lriscv --relax +#objdump: -d -Mno-aliases + +.*:[ ]+file format .* + + +Disassembly of section .text: + +0+10000 <_start>: +[ ]+[0-9a-f]+:[ ]+00350633[ ]+add[ ]+a2,a0,gp +[ ]+[0-9a-f]+:[ ]+0835063b[ ]+add\.uw[ ]+a2,a0,gp +[ ]+[0-9a-f]+:[ ]+20352633[ ]+sh1add[ ]+a2,a0,gp +[ ]+[0-9a-f]+:[ ]+20354633[ ]+sh2add[ ]+a2,a0,gp +[ ]+[0-9a-f]+:[ ]+20356633[ ]+sh3add[ ]+a2,a0,gp +[ ]+[0-9a-f]+:[ ]+2035663b[ ]+sh3add\.uw[ ]+a2,a0,gp +[ ]+[0-9a-f]+:[ ]+10064683[ ]+lbu[ ]+a3,256\(a2\) +[ ]+[0-9a-f]+:[ ]+10d60023[ ]+sb[ ]+a3,256\(a2\) +[ ]+[0-9a-f]+:[ ]+00350633[ ]+add[ ]+a2,a0,gp +[ ]+[0-9a-f]+:[ ]+0835063b[ ]+add\.uw[ ]+a2,a0,gp +[ ]+[0-9a-f]+:[ ]+20352633[ ]+sh1add[ ]+a2,a0,gp +[ ]+[0-9a-f]+:[ ]+20354633[ ]+sh2add[ ]+a2,a0,gp +[ ]+[0-9a-f]+:[ ]+20356633[ ]+sh3add[ ]+a2,a0,gp +[ ]+[0-9a-f]+:[ ]+2035663b[ ]+sh3add\.uw[ ]+a2,a0,gp +[ ]+[0-9a-f]+:[ ]+10864683[ ]+lbu[ ]+a3,264\(a2\) +[ ]+[0-9a-f]+:[ ]+10d60423[ ]+sb[ ]+a3,264\(a2\) diff --git a/ld/testsuite/ld-riscv-elf/base-idx-relax-near.ld b/ld/testsuite/ld-riscv-elf/base-idx-relax-near.ld new file mode 100644 index 00000000000..b04e15d2fb8 --- /dev/null +++ b/ld/testsuite/ld-riscv-elf/base-idx-relax-near.ld @@ -0,0 +1,22 @@ +/* Data symbols sit right next to __global_pointer$ so the gp-relaxable + range is satisfied and R_RISCV_BASE_IDX_* are fully relaxed. */ + +ENTRY(_start) +MEMORY +{ + rom (rx) : ORIGIN = 0x10000, LENGTH = 0x1000 + ram (!rx) : ORIGIN = 0x20000, LENGTH = 0x1000 +} +SECTIONS { + .text : { + *(.text*) + } >rom + + .data : { + __global_pointer$ = .; + /* Pad so that symL sits at gp + 0x100, giving the relaxed + lbu/sb a non-zero gp-relative immediate. */ + . = . + 0x100; + *(.data*) + } >ram +} diff --git a/ld/testsuite/ld-riscv-elf/base-idx-relax-x0-emit-relocs.d b/ld/testsuite/ld-riscv-elf/base-idx-relax-x0-emit-relocs.d new file mode 100644 index 00000000000..59ca62578c7 --- /dev/null +++ b/ld/testsuite/ld-riscv-elf/base-idx-relax-x0-emit-relocs.d @@ -0,0 +1,63 @@ +#source: base-idx-relax-x0.s +#as: -march=rv64i_zba -mabi=lp64 --defsym __medlow__=1 +#ld: -Tbase-idx-relax-x0.ld -melf64lriscv --relax --emit-relocs +#objdump: -dr -Mno-aliases + +.*:[ ]+file format .* + + +Disassembly of section .text: + +0+10000 <_start>: +[ ]+[0-9a-f]+:[ ]+00050533[ ]+add[ ]+a0,a0,zero +[ ]+[0-9a-f]+:[ ]+R_RISCV_NONE[ ]+\*ABS\*\+0x4 +[ ]+[0-9a-f]+:[ ]+R_RISCV_RELAX[ ]+\*ABS\* +[ ]+[0-9a-f]+:[ ]+R_RISCV_BASE_IDX_ADD[ ]+symL +[ ]+[0-9a-f]+:[ ]+R_RISCV_RELAX[ ]+\*ABS\* +[ ]+[0-9a-f]+:[ ]+0805053b[ ]+add\.uw[ ]+a0,a0,zero +[ ]+[0-9a-f]+:[ ]+R_RISCV_BASE_IDX_ADD[ ]+symL +[ ]+[0-9a-f]+:[ ]+R_RISCV_RELAX[ ]+\*ABS\* +[ ]+[0-9a-f]+:[ ]+20052533[ ]+sh1add[ ]+a0,a0,zero +[ ]+[0-9a-f]+:[ ]+R_RISCV_BASE_IDX_ADD[ ]+symL +[ ]+[0-9a-f]+:[ ]+R_RISCV_RELAX[ ]+\*ABS\* +[ ]+[0-9a-f]+:[ ]+20054533[ ]+sh2add[ ]+a0,a0,zero +[ ]+[0-9a-f]+:[ ]+R_RISCV_BASE_IDX_ADD[ ]+symL +[ ]+[0-9a-f]+:[ ]+R_RISCV_RELAX[ ]+\*ABS\* +[ ]+[0-9a-f]+:[ ]+20056533[ ]+sh3add[ ]+a0,a0,zero +[ ]+[0-9a-f]+:[ ]+R_RISCV_BASE_IDX_ADD[ ]+symL +[ ]+[0-9a-f]+:[ ]+R_RISCV_RELAX[ ]+\*ABS\* +[ ]+[0-9a-f]+:[ ]+2005653b[ ]+sh3add\.uw[ ]+a0,a0,zero +[ ]+[0-9a-f]+:[ ]+R_RISCV_BASE_IDX_ADD[ ]+symL +[ ]+[0-9a-f]+:[ ]+R_RISCV_RELAX[ ]+\*ABS\* +[ ]+[0-9a-f]+:[ ]+10054603[ ]+lbu[ ]+a2,256\(a0\) +[ ]+[0-9a-f]+:[ ]+R_RISCV_BASE_IDX_LO12_I[ ]+symL +[ ]+[0-9a-f]+:[ ]+R_RISCV_RELAX[ ]+\*ABS\* +[ ]+[0-9a-f]+:[ ]+10c50023[ ]+sb[ ]+a2,256\(a0\) +[ ]+[0-9a-f]+:[ ]+R_RISCV_BASE_IDX_LO12_S[ ]+symL +[ ]+[0-9a-f]+:[ ]+R_RISCV_RELAX[ ]+\*ABS\* +[ ]+[0-9a-f]+:[ ]+00050533[ ]+add[ ]+a0,a0,zero +[ ]+[0-9a-f]+:[ ]+R_RISCV_NONE[ ]+\*ABS\*\+0x4 +[ ]+[0-9a-f]+:[ ]+R_RISCV_RELAX[ ]+\*ABS\*\+0x8 +[ ]+[0-9a-f]+:[ ]+R_RISCV_BASE_IDX_ADD[ ]+weakL\+0x8 +[ ]+[0-9a-f]+:[ ]+R_RISCV_RELAX[ ]+\*ABS\*\+0x8 +[ ]+[0-9a-f]+:[ ]+0805053b[ ]+add\.uw[ ]+a0,a0,zero +[ ]+[0-9a-f]+:[ ]+R_RISCV_BASE_IDX_ADD[ ]+weakL\+0x8 +[ ]+[0-9a-f]+:[ ]+R_RISCV_RELAX[ ]+\*ABS\*\+0x8 +[ ]+[0-9a-f]+:[ ]+20052533[ ]+sh1add[ ]+a0,a0,zero +[ ]+[0-9a-f]+:[ ]+R_RISCV_BASE_IDX_ADD[ ]+weakL\+0x8 +[ ]+[0-9a-f]+:[ ]+R_RISCV_RELAX[ ]+\*ABS\*\+0x8 +[ ]+[0-9a-f]+:[ ]+20054533[ ]+sh2add[ ]+a0,a0,zero +[ ]+[0-9a-f]+:[ ]+R_RISCV_BASE_IDX_ADD[ ]+weakL\+0x8 +[ ]+[0-9a-f]+:[ ]+R_RISCV_RELAX[ ]+\*ABS\*\+0x8 +[ ]+[0-9a-f]+:[ ]+20056533[ ]+sh3add[ ]+a0,a0,zero +[ ]+[0-9a-f]+:[ ]+R_RISCV_BASE_IDX_ADD[ ]+weakL\+0x8 +[ ]+[0-9a-f]+:[ ]+R_RISCV_RELAX[ ]+\*ABS\*\+0x8 +[ ]+[0-9a-f]+:[ ]+2005653b[ ]+sh3add\.uw[ ]+a0,a0,zero +[ ]+[0-9a-f]+:[ ]+R_RISCV_BASE_IDX_ADD[ ]+weakL\+0x8 +[ ]+[0-9a-f]+:[ ]+R_RISCV_RELAX[ ]+\*ABS\*\+0x8 +[ ]+[0-9a-f]+:[ ]+00854603[ ]+lbu[ ]+a2,8\(a0\) +[ ]+[0-9a-f]+:[ ]+R_RISCV_BASE_IDX_LO12_I[ ]+weakL\+0x8 +[ ]+[0-9a-f]+:[ ]+R_RISCV_RELAX[ ]+\*ABS\*\+0x8 +[ ]+[0-9a-f]+:[ ]+00c50423[ ]+sb[ ]+a2,8\(a0\) +[ ]+[0-9a-f]+:[ ]+R_RISCV_BASE_IDX_LO12_S[ ]+weakL\+0x8 +[ ]+[0-9a-f]+:[ ]+R_RISCV_RELAX[ ]+\*ABS\*\+0x8 diff --git a/ld/testsuite/ld-riscv-elf/base-idx-relax-x0.d b/ld/testsuite/ld-riscv-elf/base-idx-relax-x0.d new file mode 100644 index 00000000000..c1687ee0699 --- /dev/null +++ b/ld/testsuite/ld-riscv-elf/base-idx-relax-x0.d @@ -0,0 +1,27 @@ +#source: base-idx-relax-x0.s +#as: -march=rv64i_zba -mabi=lp64 --defsym __medlow__=1 +#ld: -Tbase-idx-relax-x0.ld -melf64lriscv --relax +#objdump: -d -Mno-aliases + +.*:[ ]+file format .* + + +Disassembly of section .text: + +0+10000 <_start>: +[ ]+[0-9a-f]+:[ ]+00050533[ ]+add[ ]+a0,a0,zero +[ ]+[0-9a-f]+:[ ]+0805053b[ ]+add\.uw[ ]+a0,a0,zero +[ ]+[0-9a-f]+:[ ]+20052533[ ]+sh1add[ ]+a0,a0,zero +[ ]+[0-9a-f]+:[ ]+20054533[ ]+sh2add[ ]+a0,a0,zero +[ ]+[0-9a-f]+:[ ]+20056533[ ]+sh3add[ ]+a0,a0,zero +[ ]+[0-9a-f]+:[ ]+2005653b[ ]+sh3add\.uw[ ]+a0,a0,zero +[ ]+[0-9a-f]+:[ ]+10054603[ ]+lbu[ ]+a2,256\(a0\) +[ ]+[0-9a-f]+:[ ]+10c50023[ ]+sb[ ]+a2,256\(a0\) +[ ]+[0-9a-f]+:[ ]+00050533[ ]+add[ ]+a0,a0,zero +[ ]+[0-9a-f]+:[ ]+0805053b[ ]+add\.uw[ ]+a0,a0,zero +[ ]+[0-9a-f]+:[ ]+20052533[ ]+sh1add[ ]+a0,a0,zero +[ ]+[0-9a-f]+:[ ]+20054533[ ]+sh2add[ ]+a0,a0,zero +[ ]+[0-9a-f]+:[ ]+20056533[ ]+sh3add[ ]+a0,a0,zero +[ ]+[0-9a-f]+:[ ]+2005653b[ ]+sh3add\.uw[ ]+a0,a0,zero +[ ]+[0-9a-f]+:[ ]+00854603[ ]+lbu[ ]+a2,8\(a0\) +[ ]+[0-9a-f]+:[ ]+00c50423[ ]+sb[ ]+a2,8\(a0\) diff --git a/ld/testsuite/ld-riscv-elf/base-idx-relax-x0.ld b/ld/testsuite/ld-riscv-elf/base-idx-relax-x0.ld new file mode 100644 index 00000000000..883ebeae167 --- /dev/null +++ b/ld/testsuite/ld-riscv-elf/base-idx-relax-x0.ld @@ -0,0 +1,28 @@ +/* Three base-idx-relax cases sharing one gp placement (__global_pointer$ = + 0x1000): + + - symL is a defined symbol whose address (0x100) fits a 12-bit signed + immediate directly, while its displacement from gp does not, so x0 is + selected both at relaxation time and at final relocation time. + + - weakL is an undefined weak symbol referenced with a +0x8 addend, so + both relaxation time (undefined_weak forces x0) and final relocation + time (0 + 0x8 fits a 12-bit immediate) agree on x0. */ + +ENTRY(_start) +MEMORY +{ + rom (rx) : ORIGIN = 0x10000, LENGTH = 0x1000 + ram (!rx) : ORIGIN = 0x100, LENGTH = 0x1000 +} +SECTIONS { + .text : { + *(.text*) + } >rom + + .data : { + *(.data*) + } >ram + + __global_pointer$ = 0x1000; +} diff --git a/ld/testsuite/ld-riscv-elf/base-idx-relax-x0.s b/ld/testsuite/ld-riscv-elf/base-idx-relax-x0.s new file mode 100644 index 00000000000..caa2fe7124f --- /dev/null +++ b/ld/testsuite/ld-riscv-elf/base-idx-relax-x0.s @@ -0,0 +1,34 @@ + .text + .global _start +_start: + +.ifdef __medlow__ + lui a1, %hi(symL) + add a0, a0, a1, %base_idx_add(symL) + add.uw a0, a0, a1, %base_idx_add(symL) + sh1add a0, a0, a1, %base_idx_add(symL) + sh2add a0, a0, a1, %base_idx_add(symL) + sh3add a0, a0, a1, %base_idx_add(symL) + sh3add.uw a0, a0, a1, %base_idx_add(symL) + lbu a2, %base_idx_lo(symL)(a0) + sb a2, %base_idx_lo(symL)(a0) + + lui a1, %hi(weakL+0x8) + add a0, a0, a1, %base_idx_add(weakL+0x8) + add.uw a0, a0, a1, %base_idx_add(weakL+0x8) + sh1add a0, a0, a1, %base_idx_add(weakL+0x8) + sh2add a0, a0, a1, %base_idx_add(weakL+0x8) + sh3add a0, a0, a1, %base_idx_add(weakL+0x8) + sh3add.uw a0, a0, a1, %base_idx_add(weakL+0x8) + lbu a2, %base_idx_lo(weakL+0x8)(a0) + sb a2, %base_idx_lo(weakL+0x8)(a0) +.endif + + .size _start, .-_start + + .data + .global symL +symL: + .dword 0x1111222233334444 + + .weak weakL diff --git a/ld/testsuite/ld-riscv-elf/ld-riscv-elf.exp b/ld/testsuite/ld-riscv-elf/ld-riscv-elf.exp index 8e26ccff10a..82e906503d4 100644 --- a/ld/testsuite/ld-riscv-elf/ld-riscv-elf.exp +++ b/ld/testsuite/ld-riscv-elf/ld-riscv-elf.exp @@ -154,6 +154,12 @@ if [istarget "riscv*-*-*"] { run_dump_test "code-model-relax-medany-02" run_dump_test "code-model-relax-medany-weakref-01" run_dump_test "code-model-relax-medany-weakref-02" + run_dump_test "base-idx-relax-medlow-near" + run_dump_test "base-idx-relax-medlow-near-emit-relocs" + run_dump_test "base-idx-relax-medlow-far" + run_dump_test "base-idx-relax-medlow-far-emit-relocs" + run_dump_test "base-idx-relax-x0" + run_dump_test "base-idx-relax-x0-emit-relocs" run_dump_test "attr-merge-arch-01" run_dump_test "attr-merge-arch-02" run_dump_test "attr-merge-arch-03" diff --git a/opcodes/riscv-dis.c b/opcodes/riscv-dis.c index 03c8cf1e344..5a53367fdd6 100644 --- a/opcodes/riscv-dis.c +++ b/opcodes/riscv-dis.c @@ -513,6 +513,12 @@ print_insn_args (const char *oparg, insn_t l, bfd_vma pc, disassemble_info *info print (info->stream, dis_style_immediate, "0"); break; + case '1': + /* This is a relaxation marker operand (e.g. %tprel_add, + %tlsdesc_call, %base_idx_add) that does not correspond to + any encoding bits, so there is nothing to print for it. */ + break; + case 'r': print (info->stream, dis_style_register, "%s", pd->riscv_gpr_names[EXTRACT_OPERAND (RS3, l)]); diff --git a/opcodes/riscv-opc.c b/opcodes/riscv-opc.c index 54887c97880..86084dbe091 100644 --- a/opcodes/riscv-opc.c +++ b/opcodes/riscv-opc.c @@ -556,8 +556,8 @@ const struct riscv_opcode riscv_opcodes[] = {"add", 0, INSN_CLASS_ZCA, "Ct,Cc,CK", MATCH_C_ADDI4SPN, MASK_C_ADDI4SPN, match_c_addi4spn, INSN_ALIAS }, {"add", 0, INSN_CLASS_ZCA, "Cc,Cc,CL", MATCH_C_ADDI16SP, MASK_C_ADDI16SP, match_c_addi16sp, INSN_ALIAS }, {"add", 0, INSN_CLASS_ZCA, "d,Cz,CV", MATCH_C_MV, MASK_C_MV, match_c_add, INSN_ALIAS }, -{"add", 0, INSN_CLASS_I, "d,s,t", MATCH_ADD, MASK_ADD, match_opcode, 0 }, -{"add", 0, INSN_CLASS_I, "d,s,t,1", MATCH_ADD, MASK_ADD, match_opcode, 0 }, +/* make fourth operand (tprel_add/base_idx_add) of add an optional operand. */ +{"add", 0, INSN_CLASS_I, "d,s,t1", MATCH_ADD, MASK_ADD, match_opcode, 0 }, {"add", 0, INSN_CLASS_I, "d,s,j", MATCH_ADDI, MASK_ADDI, match_opcode, INSN_ALIAS }, {"la", 0, INSN_CLASS_I, "d,B", 0, (int) M_LA, match_rd_nonzero, INSN_MACRO }, {"lla", 0, INSN_CLASS_I, "d,B", 0, (int) M_LLA, NULL, INSN_MACRO }, @@ -1378,16 +1378,18 @@ const struct riscv_opcode riscv_opcodes[] = {"rorw", 64, INSN_CLASS_ZBB_OR_ZBKB, "d,s,<", MATCH_RORIW, MASK_RORIW, match_opcode, INSN_ALIAS }, /* Zba instructions. */ -{"sh1add", 0, INSN_CLASS_ZBA, "d,s,t", MATCH_SH1ADD, MASK_SH1ADD, match_opcode, 0 }, -{"sh2add", 0, INSN_CLASS_ZBA, "d,s,t", MATCH_SH2ADD, MASK_SH2ADD, match_opcode, 0 }, -{"sh3add", 0, INSN_CLASS_ZBA, "d,s,t", MATCH_SH3ADD, MASK_SH3ADD, match_opcode, 0 }, -{"sh1add.uw", 64, INSN_CLASS_ZBA, "d,s,t", MATCH_SH1ADD_UW, MASK_SH1ADD_UW, match_opcode, 0 }, -{"sh2add.uw", 64, INSN_CLASS_ZBA, "d,s,t", MATCH_SH2ADD_UW, MASK_SH2ADD_UW, match_opcode, 0 }, -{"sh3add.uw", 64, INSN_CLASS_ZBA, "d,s,t", MATCH_SH3ADD_UW, MASK_SH3ADD_UW, match_opcode, 0 }, +/* make fourth operand (base_idx_add) of shxadd/shxadd.uw an optional operand. */ +{"sh1add", 0, INSN_CLASS_ZBA, "d,s,t1", MATCH_SH1ADD, MASK_SH1ADD, match_opcode, 0 }, +{"sh2add", 0, INSN_CLASS_ZBA, "d,s,t1", MATCH_SH2ADD, MASK_SH2ADD, match_opcode, 0 }, +{"sh3add", 0, INSN_CLASS_ZBA, "d,s,t1", MATCH_SH3ADD, MASK_SH3ADD, match_opcode, 0 }, +{"sh1add.uw", 64, INSN_CLASS_ZBA, "d,s,t1", MATCH_SH1ADD_UW, MASK_SH1ADD_UW, match_opcode, 0 }, +{"sh2add.uw", 64, INSN_CLASS_ZBA, "d,s,t1", MATCH_SH2ADD_UW, MASK_SH2ADD_UW, match_opcode, 0 }, +{"sh3add.uw", 64, INSN_CLASS_ZBA, "d,s,t1", MATCH_SH3ADD_UW, MASK_SH3ADD_UW, match_opcode, 0 }, {"zext.w", 64, INSN_CLASS_ZCB_AND_ZBA, "Cs,Cw", MATCH_C_ZEXT_W, MASK_C_ZEXT_W, match_opcode, INSN_ALIAS }, {"zext.w", 64, INSN_CLASS_ZBA, "d,s", MATCH_ADD_UW, MASK_ADD_UW | MASK_RS2, match_opcode, INSN_ALIAS }, {"zext.w", 64, INSN_CLASS_I, "d,s", 0, (int) M_ZEXTW, NULL, INSN_MACRO }, -{"add.uw", 64, INSN_CLASS_ZBA, "d,s,t", MATCH_ADD_UW, MASK_ADD_UW, match_opcode, 0 }, +/* make fourth operand (base_idx_add) of add.uw an optional operand. */ +{"add.uw", 64, INSN_CLASS_ZBA, "d,s,t1", MATCH_ADD_UW, MASK_ADD_UW, match_opcode, 0 }, {"slli.uw", 64, INSN_CLASS_ZBA, "d,s,>", MATCH_SLLI_UW, MASK_SLLI_UW, match_opcode, 0 }, /* Zbc or zbkc instructions. */ -- 2.43.0