@@ -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,
@@ -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,37 @@ 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 +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
@@ -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},
};
struct riscv_profiles
@@ -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",
@@ -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
@@ -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. */
new file mode 100644
@@ -0,0 +1,3 @@
+#as: -march=rv64imafdc_zbb_zba
+#source: base-idx-add.s
+#error_output: base-idx-add.l
new file mode 100644
@@ -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'
new file mode 100644
@@ -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
@@ -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. */
new file mode 100644
@@ -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;
+}
new file mode 100644
@@ -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\)
new file mode 100644
@@ -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\)
new file mode 100644
@@ -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
+}
new file mode 100644
@@ -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
@@ -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"
@@ -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)]);
@@ -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. */