Re: [PATCH v2] RISC-V: Add new relocation types for global array accesses
Jiawei <[email protected]> Fri, 24 Jul 2026 01:00:21 +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/R_RISCV_BASE_IDX_LO12_S/R_RISCV_BASE_IDX_ADD > > > * elfxx-riscv.c : Add HOWTOs for new reloaction type. > relocation > * libbfd.h: Regenerate. > * reloc.c: Document BFD_RELOC_RISCV_BASE_IDX_* type. > > + case INTERNAL_R_RISCV_BASE_IDX_I: > + case INTERNAL_R_RISCV_BASE_IDX_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 valid = (r_type == INTERNAL_R_RISCV_BASE_IDX_I) > + ? VALID_ITYPE_IMM (disp) > + : VALID_STYPE_IMM (disp); > + if (valid) > + rel->r_addend -= gp; > + else > + r = bfd_reloc_overflow; > + break; > + } > + > + case INTERNAL_R_RISCV_BASE_IDX_ADD: > + { > + /* Rewrite rs2 of the add/shXadd instruction to use gp 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); > + insn = (insn & ~(OP_MASK_RS2 << OP_SH_RS2)) | (X_GP << > OP_SH_RS2); > + bfd_putl32 (insn, contents + rel->r_offset); > + break; > + } > + > Hi Liqin, Currently INTERNAL_R_RISCV_BASE_IDX_ADD use gp rewrite rs2 with no limit, but the existing relaxation range of '_bfd_riscv_relax_lui' is not limited to gp-relative only. When symbol is located at a low address, like S + A = 0x100: The original code should have deleted lui and changed the address base register to x0; The new relocation calculates 0x100 - gp, which may result in an error report overflow or generate an incorrect displacement. When symbol value is 0, and the normal semantics should use x0, but the current code will still keep uses gp. I think it is better to create a dedicated '_bfd_riscv_relax_base_idx' for this set of relocations here and add some testcases here. > case R_RISCV_PCREL_HI20: > absolute = riscv_zero_pcrel_hi_reloc (rel, info, pc, &relocation, > contents, howto); > @@ -5148,6 +5191,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, INTERNAL_R_RISCV_BASE_IDX_I); > + return true; > + > + case R_RISCV_BASE_IDX_LO12_S: > + rel->r_info = ELFNN_R_INFO (sym, INTERNAL_R_RISCV_BASE_IDX_S); > + return true; > + > + case R_RISCV_BASE_IDX_ADD: > + rel->r_info = ELFNN_R_INFO (sym, INTERNAL_R_RISCV_BASE_IDX_ADD); > + return true; > + > case R_RISCV_HI20: > /* Delete unnecessary LUI and reuse the reloc. */ > *again = true; > @@ -5160,7 +5215,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 +5592,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..de385906589 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 (INTERNAL_R_RISCV_BASE_IDX_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 */ > + "INTERNAL_R_RISCV_BASE_IDX_I", /* name */ > + false, /* partial_inplace */ > + 0, /* src_mask */ > + ENCODE_ITYPE_IMM (-1U), /* dst_mask */ > + false), /* pcrel_offset */ > + > + HOWTO (INTERNAL_R_RISCV_BASE_IDX_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 */ > + "INTERNAL_R_RISCV_BASE_IDX_S", /* name */ > + false, /* partial_inplace */ > + 0, /* src_mask */ > + ENCODE_STYPE_IMM (-1U), /* dst_mask */ > + false), /* pcrel_offset */ > + > + HOWTO (INTERNAL_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 */ > + "INTERNAL_R_RISCV_BASE_IDX_ADD", /* name */ > + false, /* partial_inplace */ > + 0, /* src_mask */ > + 0, /* dst_mask */ > + false) /* pcrel_offset */ > }; > > /* A mapping from BFD reloc types to RISC-V ELF reloc types. */ > @@ -1023,6 +1123,9 @@ 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}, > }; > + { 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 }, > > struct riscv_profiles > diff --git a/bfd/libbfd.h b/bfd/libbfd.h > index a27134dcd78..7e49498d0f1 100644 > --- a/bfd/libbfd.h > +++ b/bfd/libbfd.h > @@ -2363,6 +2363,9 @@ static const char *const > bfd_reloc_code_real_names[] = { "@@uninitialized@@", > "BFD_RELOC_RISCV_TLSDESC_ADD_LO12", > "BFD_RELOC_RISCV_TLSDESC_CALL", > "BFD_RELOC_RISCV_ALIGN", > + "BFD_RELOC_RISCV_BASE_IDX_LO12_I", > + "BFD_RELOC_RISCV_BASE_IDX_LO12_S", > + "BFD_RELOC_RISCV_BASE_IDX_ADD", > "BFD_RELOC_RISCV_RVC_BRANCH", > "BFD_RELOC_RISCV_RVC_JUMP", > "BFD_RELOC_RISCV_RELAX", > 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..690c511a536 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 INTERNAL_R_RISCV_BASE_IDX_I (R_RISCV_max + 7) > +#define INTERNAL_R_RISCV_BASE_IDX_S (R_RISCV_max + 8) > +#define INTERNAL_R_RISCV_BASE_IDX_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-medlow-far.d > b/ld/testsuite/ld-riscv-elf/base-idx-relax-medlow-far.d > new file mode 100644 > index 00000000000..e7beb208842 > --- /dev/null > +++ b/ld/testsuite/ld-riscv-elf/base-idx-relax-medlow-far.d > @@ -0,0 +1,16 @@ > +#source: base-idx-relax.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]+:[ ]+20b52633[ ]+sh1add[ ]+a2,a0,a1 > +[ ]+[0-9a-f]+:[ ]+00064683[ ]+lbu[ ]+a3,0\(a2\) > +[ ]+[0-9a-f]+:[ ]+00d60023[ ]+sb[ ]+a3,0\(a2\) > 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..24e0615a0bf > --- /dev/null > +++ b/ld/testsuite/ld-riscv-elf/base-idx-relax-medlow-near.d > @@ -0,0 +1,15 @@ > +#source: base-idx-relax.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]+:[ ]+20352633[ ]+sh1add[ ]+a2,a0,gp > +[ ]+[0-9a-f]+:[ ]+10064683[ ]+lbu[ ]+a3,256\(a2\) > +[ ]+[0-9a-f]+:[ ]+10d60023[ ]+sb[ ]+a3,256\(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..31f3229b7b0 > --- /dev/null > +++ b/ld/testsuite/ld-riscv-elf/base-idx-relax-near.ld > @@ -0,0 +1,23 @@ > +/* Data symbols sit right next to __global_pointer$ so the gp-relaxable > + range is satisfied and R_RISCV_BASE_IDX_* / R_RISCV_PCREL_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.s > b/ld/testsuite/ld-riscv-elf/base-idx-relax.s > new file mode 100644 > index 00000000000..315e19cd83e > --- /dev/null > +++ b/ld/testsuite/ld-riscv-elf/base-idx-relax.s > @@ -0,0 +1,19 @@ > + > + .text > + .global _start > +_start: > + > +.ifdef __medlow__ > + lui a1, %hi(symL) > + add a2, a0, a1, %base_idx_add(symL) > + sh1add a2, a0, a1, %base_idx_add(symL) > + lbu a3, %base_idx_lo(symL)(a2) > + sb a3, %base_idx_lo(symL)(a2) > +.endif > + > + .size _start, .-_start > + > + .data > + .global symL > +symL: > + .dword 0x1111222233334444 > diff --git a/ld/testsuite/ld-riscv-elf/ld-riscv-elf.exp > b/ld/testsuite/ld-riscv-elf/ld-riscv-elf.exp > index 8e26ccff10a..bd531e9fa61 100644 > --- a/ld/testsuite/ld-riscv-elf/ld-riscv-elf.exp > +++ b/ld/testsuite/ld-riscv-elf/ld-riscv-elf.exp > @@ -154,6 +154,8 @@ 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-far" > run_dump_test "attr-merge-arch-01" > run_dump_test "attr-merge-arch-02" > run_dump_test "attr-merge-arch-03" > Could we also add a '--emit-relocs' test here? > 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..b08a0069f40 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*/ > /* 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. */ >