[PATCH] RISCV-V: Add new relocation type for global array accesses with non-constant indices
翁丽琴
liqin.weng@spacemit.com
Wed Jul 8 07:06:12 GMT 2026
1. Address the comments && clang-format
2. Rename the relocation name: R_RISCV_BASE_IDX_ADD/R_RISCV_BASE_IDX_LO12_I/R_RISCV_BASE_IDX_LO12_S
3. Remove the R_RISCV_BASE_IDX_SHXADD
LLVM Implement in LLD && MC : https://github.com/llvm/llvm-project/pull/207901
-----
From b33b8deaaa6f9f1a436db2e4a114ce122913c2e2 Mon Sep 17 00:00:00 2001
From: wengliqin <liqin.weng@spacemit.com>
Date: Wed, 24 Jun 2026 18:57:07 +0800
Subject: [PATCH] RISCV-V: Add new relocation type for global array accesses
with non-constant indices.
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
RISC-V PSABI specification: https://github.com/riscv-non-isa/riscv-elf-psabi-doc/pull/489
---
bfd/ChangeLog | 13 ++++
bfd/bfd-in2.h | 3 +
bfd/elfnn-riscv.c | 61 ++++++++++++++-
bfd/elfxx-riscv.c | 104 ++++++++++++++++++++++++-
bfd/libbfd.h | 3 +
bfd/reloc.c | 6 ++
gas/ChangeLog | 10 +++
gas/config/tc-riscv.c | 35 +++++++--
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/ChangeLog | 4 +
include/elf/riscv.h | 6 ++
opcodes/riscv-opc.c | 19 +++--
14 files changed, 282 insertions(+), 14 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
diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index 6046f658f8b..ea4b9e41c69 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -1,3 +1,16 @@
+2026-06-22 wengliqin <liqin.weng@spacemit.com>
+
+ * reloc.c (BFD_RELOC_RISCV_BASE_IDX_LO12_I, BFD_RELOC_RISCV_BASE_IDX_LO12_S,
+ BFD_RELOC_RISCV_BASE_IDX_ADD): New
+ relocation types.
+ * bfd-in2.h: Regenerate.
+ * libbfd.h: Regenerate.
+ * elfnn-riscv.c (perform_relocation): Add support for new REGREL
+ relocations.
+ (riscv_elf_relocate_section): Handle REGREL relocations for global
+ array accesses with non-constant indices.
+ * elfxx-riscv.c: Define relocation information for new REGREL types.
+
2025-09-16 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE>
* config.bfd <powerpc-*-solaris2*>: Remove.
diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h
index d4e4f8e4375..b958ed3c048 100644
--- a/bfd/bfd-in2.h
+++ b/bfd/bfd-in2.h
@@ -5364,6 +5364,9 @@ enum bfd_reloc_code_real
BFD_RELOC_RISCV_32_PCREL,
BFD_RELOC_RISCV_SET_ULEB128,
BFD_RELOC_RISCV_SUB_ULEB128,
+ BFD_RELOC_RISCV_BASE_IDX_LO12_I,
+ BFD_RELOC_RISCV_BASE_IDX_LO12_S,
+ BFD_RELOC_RISCV_BASE_IDX_ADD,
/* Renesas RL78 Relocations. */
BFD_RELOC_RL78_NEG8,
diff --git a/bfd/elfnn-riscv.c b/bfd/elfnn-riscv.c
index d3963ec9a58..71212e5c78b 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 INTERNAL_R_RISCV_BASE_IDX_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 INTERNAL_R_RISCV_BASE_IDX_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 INTERNAL_R_RISCV_BASE_IDX_ADD:
break;
case R_RISCV_DELETE:
@@ -2722,6 +2728,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 +2797,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 +3101,36 @@ riscv_elf_relocate_section (bfd *output_bfd,
break;
}
+ 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;
+ }
+
case R_RISCV_PCREL_HI20:
absolute = riscv_zero_pcrel_hi_reloc (rel, info, pc, &relocation,
contents, howto);
@@ -5148,6 +5190,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 +5214,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. */
@@ -5539,7 +5593,10 @@ _bfd_riscv_relax_section (bfd *abfd, asection *sec,
relax_func = _bfd_riscv_relax_call;
else if (type == R_RISCV_HI20
|| type == R_RISCV_LO12_I
- || type == R_RISCV_LO12_S)
+ || 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..8c87bbfe815 100644
--- a/bfd/elfxx-riscv.c
+++ b/bfd/elfxx-riscv.c
@@ -876,7 +876,62 @@ 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 (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 +1016,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 +1122,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},
};
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/ChangeLog b/gas/ChangeLog
index 492475658f1..5c69c63bce6 100644
--- a/gas/ChangeLog
+++ b/gas/ChangeLog
@@ -1,3 +1,13 @@
+2026-03-24 wengliqin <liqin.weng@spacemit.com>
+
+ * config/tc-riscv.c: Add support for RISC-V Base IDX relocations.
+ * testsuite/gas/riscv/base-idx-add.s: New test for BASE_IDX_ADD.
+ * testsuite/gas/riscv/base-idx-add.d: Corresponding test output.
+ * testsuite/gas/riscv/base-idx-add.l: Corresponding test output.
+ * testsuite/gas/riscv/base-idx-shxadd.s: Ditto
+ * testsuite/gas/riscv/base-idx-shxadd.d: Corresponding test output.
+ * testsuite/gas/riscv/base-idx-shxadd.l: Corresponding test output.
+
2025-09-16 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE>
* NEWS: Mention Solaris/PowerPC removal.
diff --git a/gas/config/tc-riscv.c b/gas/config/tc-riscv.c
index 6bcf53832a0..f1e56ec4aa6 100644
--- a/gas/config/tc-riscv.c
+++ b/gas/config/tc-riscv.c
@@ -1958,6 +1958,12 @@ riscv_apply_const_reloc (bfd_reloc_code_real_type reloc_type, bfd_vma value)
case BFD_RELOC_RISCV_LO12_I:
return ENCODE_ITYPE_IMM (value);
+ case BFD_RELOC_RISCV_BASE_IDX_LO12_S:
+ return ENCODE_STYPE_IMM (value);
+
+ case BFD_RELOC_RISCV_BASE_IDX_LO12_I:
+ return ENCODE_ITYPE_IMM (value);
+
default:
abort ();
}
@@ -2022,7 +2028,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 +2462,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 +2473,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 +2483,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}
};
@@ -3633,15 +3643,24 @@ riscv_ip (char *str, struct riscv_cl_insn *ip, expressionS *imm_expr,
case 'j': /* Sign-extended immediate. */
p = percent_op_itype;
- *imm_reloc = BFD_RELOC_RISCV_LO12_I;
+ if (strncmp(asarg, "%base_idx_lo", 9) == 0)
+ *imm_reloc = BFD_RELOC_RISCV_BASE_IDX_LO12_I;
+ else
+ *imm_reloc = BFD_RELOC_RISCV_LO12_I;
goto alu_op;
case 'q': /* Store displacement. */
p = percent_op_stype;
- *imm_reloc = BFD_RELOC_RISCV_LO12_S;
+ if (strncmp(asarg, "%base_idx_lo", 9) == 0)
+ *imm_reloc = BFD_RELOC_RISCV_BASE_IDX_LO12_S;
+ else
+ *imm_reloc = BFD_RELOC_RISCV_LO12_S;
goto load_store;
case 'o': /* Load displacement. */
- p = percent_op_itype;
- *imm_reloc = BFD_RELOC_RISCV_LO12_I;
+ p = percent_op_itype;
+ if (strncmp(asarg, "%base_idx_lo", 9) == 0)
+ *imm_reloc = BFD_RELOC_RISCV_BASE_IDX_LO12_I;
+ else
+ *imm_reloc = BFD_RELOC_RISCV_LO12_I;
goto load_store;
case '1':
/* This is used for TLS relocations that acts as relaxation
@@ -4687,6 +4706,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 +4715,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..5a068e80ce4
--- /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/ChangeLog b/include/ChangeLog
index 2d05f2e4da1..97ab4a9b2d7 100644
--- a/include/ChangeLog
+++ b/include/ChangeLog
@@ -1,3 +1,7 @@
+2026-03-24 wengliqin <liqin.weng@spacemit.com>
+
+ * elf/riscv.h: Define new RISC-V base-idx relocation macros.
+
2025-07-13 Nick Clifton <nickc@redhat.com>
* 2.45 Branch point.
diff --git a/include/elf/riscv.h b/include/elf/riscv.h
index f6ca3d4acd8..52a67294ae9 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/opcodes/riscv-opc.c b/opcodes/riscv-opc.c
index 54887c97880..0433d2ca41f 100644
--- a/opcodes/riscv-opc.c
+++ b/opcodes/riscv-opc.c
@@ -1378,16 +1378,23 @@ 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 },
+{"sh1add", 0, INSN_CLASS_ZBA, "d,s,t", MATCH_SH1ADD, MASK_SH1ADD, match_opcode, 0 },
+{"sh1add", 0, INSN_CLASS_ZBA, "d,s,t,1", MATCH_SH1ADD, MASK_SH1ADD, match_opcode, 0 },
+{"sh2add", 0, INSN_CLASS_ZBA, "d,s,t", MATCH_SH2ADD, MASK_SH2ADD, match_opcode, 0 },
+{"sh2add", 0, INSN_CLASS_ZBA, "d,s,t,1", MATCH_SH2ADD, MASK_SH2ADD, match_opcode, 0 },
+{"sh3add", 0, INSN_CLASS_ZBA, "d,s,t", MATCH_SH3ADD, MASK_SH3ADD, match_opcode, 0 },
+{"sh3add", 0, INSN_CLASS_ZBA, "d,s,t,1", 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 },
+{"sh1add.uw", 64, INSN_CLASS_ZBA, "d,s,t,1", 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 },
+{"sh2add.uw", 64, INSN_CLASS_ZBA, "d,s,t,1", 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 },
+{"sh3add.uw", 64, INSN_CLASS_ZBA, "d,s,t,1", 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 },
+{"add.uw", 64, INSN_CLASS_ZBA, "d,s,t,1", 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
> From: "Jan Beulich"<jbeulich@suse.com>
> Date: Tue, Mar 24, 2026, 18:08
> Subject: Re: [PATCH] RISCV-V: Add new relocation type for global array accesses with non-constant indices
> To: "翁丽琴"<liqin.weng@spacemit.com>
> Cc: "craig.topper@sifive.com"<craig.topper@sifive.com>, "kavin.balag@gmail.com"<kavin.balag@gmail.com>, "kito.cheng@gmail.com"<kito.cheng@gmail.com>, "binutils@sourceware.org"<binutils@sourceware.org>
> On 24.03.2026 10:44, 翁丽琴 wrote:
> > @@ -3089,6 +3107,30 @@ riscv_elf_relocate_section (bfd *output_bfd,
> > break;
> > }
> >
> > + case INTERNAL_R_RISCV_REGREL_LO12_I:
> > + case INTERNAL_R_RISCV_REGREL_LO12_S:
> > + {
> > + bfd_vma gp = riscv_global_pointer_value (info);
> > + if (VALID_ITYPE_IMM (relocation + rel->r_addend - gp))
> > + {
> > + bfd_vma insn = bfd_getl32 (contents + rel->r_offset);
> > + rel->r_addend -= gp;
> > + bfd_putl32 (insn, contents + rel->r_offset);
> > + }
> > + else
> > + r = bfd_reloc_overflow;
> > + break;
> > + }
> > +
> > + case INTERNAL_R_RISCV_REGREL_ADD:
> > + case INTERNAL_R_RISCV_REGREL_SHXADD:
> > + {
> > + 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;
> > + }
>
> Nit: Entirely bogus indentation.
>
> > --- a/bfd/elfxx-riscv.c
> > +++ b/bfd/elfxx-riscv.c
> > @@ -876,7 +876,70 @@ 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 */
>
> Why the fiddling with existing code?
>
> > + /* Global array non-constant subscript addressing */
> > + HOWTO (R_RISCV_REGREL_LO12_I, /* type */
> > + 0, /* rightshift */
> > + 4, /* size */
> > + 32, /* bitsize */
>
> I realize you copy what other, similar entries have, but are these bit
> sizes (and perhaps also sizes) actually sensible? This is a 12-bit
> reloc, isn't it?
>
> > --- a/gas/config/tc-riscv.c
> > +++ b/gas/config/tc-riscv.c
> > @@ -1957,6 +1957,13 @@ riscv_apply_const_reloc (bfd_reloc_code_real_type reloc_type, bfd_vma value)
> > case BFD_RELOC_RISCV_LO12_I:
> > return ENCODE_ITYPE_IMM (value);
> >
> > +
>
> Please don't introduce double blank lines.
>
> > @@ -3631,16 +3644,25 @@ riscv_ip (char *str, struct riscv_cl_insn *ip, expressionS *imm_expr,
> > continue;
> >
> > case 'j': /* Sign-extended immediate. */
> > - p = percent_op_itype;
> > - *imm_reloc = BFD_RELOC_RISCV_LO12_I;
> > + p = percent_op_itype;
> > + if (strncmp(asarg, "%regrel_lo", 9) == 0)
> > + *imm_reloc = BFD_RELOC_RISCV_REGREL_LO12_I;
> > + else
> > + *imm_reloc = BFD_RELOC_RISCV_LO12_I;
> > goto alu_op;
> > case 'q': /* Store displacement. */
> > - p = percent_op_stype;
> > - *imm_reloc = BFD_RELOC_RISCV_LO12_S;
> > + p = percent_op_stype;
> > + if (strncmp(asarg, "%regrel_lo", 9) == 0)
> > + *imm_reloc = BFD_RELOC_RISCV_REGREL_LO12_S;
> > + else
> > + *imm_reloc = BFD_RELOC_RISCV_LO12_S;
> > goto load_store;
> > case 'o': /* Load displacement. */
> > - p = percent_op_itype;
> > - *imm_reloc = BFD_RELOC_RISCV_LO12_I;
> > + p = percent_op_itype;
> > + if (strncmp(asarg, "%regrel_lo", 9) == 0)
> > + *imm_reloc = BFD_RELOC_RISCV_REGREL_LO12_I;
> > + else
> > + *imm_reloc = BFD_RELOC_RISCV_LO12_I;
> > goto load_store;
>
> Why all the re-indentation, causing extra churn? And then while causing extra
> churn you don't even fix the style problem (using hard tabs for 8 leading
> blanks).
>
> > --- /dev/null
> > +++ b/gas/testsuite/gas/riscv/regrel-add.d
> > @@ -0,0 +1,3 @@
> > +#as: -march=rv32ia
> > +#source regrel-add.s
> > +#error_output: regrel-add.l
> > \ No newline at end of file
>
> Please (throughout) can you avoid introduction of files without trailing
> newlines?
>
> > --- a/include/elf/riscv.h
> > +++ b/include/elf/riscv.h
> > @@ -95,6 +95,14 @@ 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_REGREL_LO12_I, 77)
> > + RELOC_NUMBER (R_RISCV_REGREL_LO12_S, 78)
> > + RELOC_NUMBER (R_RISCV_REGREL_ADD, 79)
> > + RELOC_NUMBER (R_RISCV_REGREL_SHXADD, 80)
> > + RELOC_NUMBER (INTERNAL_R_RISCV_REGREL_LO12_I, 81)
> > + RELOC_NUMBER (INTERNAL_R_RISCV_REGREL_LO12_S, 82)
> > + RELOC_NUMBER (INTERNAL_R_RISCV_REGREL_ADD, 83)
> > + RELOC_NUMBER (INTERNAL_R_RISCV_REGREL_SHXADD, 84)
>
> These last four don't appear in the spec (and the numbers used collide with
> whatever the spec may assign later). Why do yu need them, when you have ...
>
> > END_RELOC_NUMBERS (R_RISCV_max)
> >
> > /* Internal relocations used exclusively by the relaxation pass. */
> > @@ -105,6 +113,10 @@ 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_REGREL_LO12_I (R_RISCV_max + 7)
> > +#define INTERNAL_R_RISCV_REGREL_LO12_S (R_RISCV_max + 8)
> > +#define INTERNAL_R_RISCV_REGREL_ADD (R_RISCV_max + 9)
> > +#define INTERNAL_R_RISCV_REGREL_SHXADD (R_RISCV_max + 10)
>
> ... these?
>
> > --- a/opcodes/ChangeLog
> > +++ b/opcodes/ChangeLog
> > @@ -1,3 +1,7 @@
> > +2026-03-24 wengliqin <liqin.weng@spacemit.com>
> > +
> > + * riscv-opc.c: Update relocation definitions for new REGREL types.
>
> I don't think this adequately describes the changes being made. (Such patching
> of ChangeLog files shouldn't be done anymore anyway, aiui. If you want ChangeLog
> entries, make them part of the commit message.)
>
> Jan
>
This message and any attachment are confidential and may be privileged or otherwise protected from disclosure. If you are not an intended recipient of this message, please delete it and any attachment from your system and notify the sender immediately by reply e-mail. Unintended recipients should not use, copy, disclose or take any action based on this message or any information contained in this message. Emails cannot be guaranteed to be secure or error free as they can be intercepted, amended, lost or destroyed, and you should take full responsibility for security checking.
本邮件及其任何附件具有保密性质,并可能受其他保护或不允许被披露给第三方。如阁下误收到本邮件,敬请立即以回复电子邮件的方式通知发件人,并将本邮件及其任何附件从阁下系统中予以删除。如阁下并非本邮件写明之收件人,敬请切勿使用、复制、披露本邮件或其任何内容,亦请切勿依本邮件或其任何内容而采取任何行动。电子邮件无法保证是一种安全和不会出现任何差错的通信方式,可能会被拦截、修改、丢失或损坏,收件人需自行负责做好安全检查。
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://sourceware.org/pipermail/binutils/attachments/20260708/49fdc919/attachment-0001.htm>
More information about the Binutils
mailing list