Skip to content

Commit

Permalink
Expand large offset for bc and balc (#5)
Browse files Browse the repository at this point in the history
* Expand balc/bc with long offset close to boundaries

Perform expand if:
  1) the offset in forward branch is >= 0xff0000
  2) the offset in backward branch is <= 0xffff

This is controled by an option --fix-nmips-hw113064.
It is off by default (--no-fix-nmips-hw113064).
  • Loading branch information
djtodoro authored Sep 24, 2023
1 parent 07e1678 commit 2723399
Show file tree
Hide file tree
Showing 6 changed files with 161 additions and 1 deletion.
21 changes: 20 additions & 1 deletion gold/nanomips.cc
Original file line number Diff line number Diff line change
Expand Up @@ -5432,8 +5432,27 @@ Nanomips_expand_insn<size, big_endian>::type(
case elfcpp::R_NANOMIPS_PC25_S1:
{
Valtype value = psymval->value(relobj, r_addend) - address - 4;
if (!this->template has_overflow_signed<26>(value))

if (!this->template has_overflow_signed<26>(value)) {
if (parameters->options().fix_nmips_hw113064()) {
typedef typename elfcpp::Elf_types<size>::Elf_Swxword Signed_valtype;
// The offset in backward branch should be less than or equal to 0xffff.
// The offset in forward branch should be greater than or equal to
// 0xff0000. The range is (-33423362, 33423360).
if (!this->template has_overflow_signed<26>(value)) {
if (static_cast<Signed_valtype>(value) <=
static_cast<Signed_valtype>(0xfe01fffe) ||
static_cast<Signed_valtype>(value) >=
static_cast<Signed_valtype>(0x1fe0000)) {
// Expand this to lapc+jalrc.
return TT_PCREL_NMF;
}
}
}

return TT_NONE;
}

break;
}
case elfcpp::R_NANOMIPS_PC21_S1:
Expand Down
4 changes: 4 additions & 0 deletions gold/options.h
Original file line number Diff line number Diff line change
Expand Up @@ -1217,6 +1217,10 @@ class General_options
N_("(nanoMIPS only) Relax R_NANOMIPS_LO12 relocation"),
N_("(nanoMIPS only) Do not relax R_NANOMIPS_LO12 relocation"));

DEFINE_bool(fix_nmips_hw113064, options::TWO_DASHES, '\0', false,
N_("(nanoMIPS only) Fix binaries for nanoMIPS erratum 113064"),
N_("(nanoMIPS only) Do not fix binaries for nanoMIPS erratum 113064"));

DEFINE_string(retain_symbols_file, options::TWO_DASHES, '\0', NULL,
N_("keep only symbols listed in this file"), N_("FILE"));

Expand Down
45 changes: 45 additions & 0 deletions gold/testsuite/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -4263,6 +4263,12 @@ check_DATA += nanomips_b_out_of_range_pcrel.stdout \
nanomips_b_cond_out_of_range_pcrel.stdout \
nanomips_move_balc_1_out_of_range_pcrel.stdout \
nanomips_move_balc_2_out_of_range_pcrel.stdout \
nanomips_long_balc_bc_offset_1.stdout \
nanomips_long_balc_bc_offset_2.stdout \
nanomips_long_balc_bc_offset_3.stdout \
nanomips_long_balc_bc_offset_4.stdout \
nanomips_long_balc_bc_offset_5.stdout \
nanomips_long_balc_bc_offset_6.stdout \
nanomips_lapc_out_of_range_pcrel.stdout \
nanomips_lapc_out_of_range_nmf_pcrel.stdout \
nanomips_lapc_out_of_range_abs.stdout \
Expand Down Expand Up @@ -4292,6 +4298,24 @@ nanomips_move_balc_1_out_of_range_pcrel.stdout: nanomips_move_balc_1_out_of_rang
nanomips_move_balc_2_out_of_range_pcrel.stdout: nanomips_move_balc_2_out_of_range_pcrel
$(TEST_OBJDUMP) -d $< > $@

nanomips_long_balc_bc_offset_1.stdout: nanomips_long_balc_bc_offset_1
$(TEST_OBJDUMP) -d $< > $@

nanomips_long_balc_bc_offset_2.stdout: nanomips_long_balc_bc_offset_2
$(TEST_OBJDUMP) -d $< > $@

nanomips_long_balc_bc_offset_3.stdout: nanomips_long_balc_bc_offset_3
$(TEST_OBJDUMP) -d $< > $@

nanomips_long_balc_bc_offset_4.stdout: nanomips_long_balc_bc_offset_4
$(TEST_OBJDUMP) -d $< > $@

nanomips_long_balc_bc_offset_5.stdout: nanomips_long_balc_bc_offset_5
$(TEST_OBJDUMP) -d $< > $@

nanomips_long_balc_bc_offset_6.stdout: nanomips_long_balc_bc_offset_6
$(TEST_OBJDUMP) -d $< > $@

nanomips_b_cond_out_of_range_pcrel.stdout: nanomips_b_cond_out_of_range_pcrel
$(TEST_OBJDUMP) -d $< > $@

Expand Down Expand Up @@ -4334,6 +4358,24 @@ nanomips_move_balc_1_out_of_range_pcrel: nanomips_move_balc_out_of_range_pcrel.o
nanomips_move_balc_2_out_of_range_pcrel: nanomips_move_balc_out_of_range_pcrel.o ../ld-new
../ld-new --section-start .text=0x1000 --section-start .foo=0x2001020 -o $@ $<

nanomips_long_balc_bc_offset_1: nanomips_long_balc_bc_offset.o ../ld-new
../ld-new --fix-nmips-hw113064 --section-start .text=0x1000 --section-start .foo=0x1fe1002 -o $@ $<

nanomips_long_balc_bc_offset_2: nanomips_long_balc_bc_offset.o ../ld-new
../ld-new --section-start .text=0x1000 --section-start .foo=0x1fe1002 -o $@ $<

nanomips_long_balc_bc_offset_3: nanomips_long_balc_bc_offset.o ../ld-new
../ld-new --fix-nmips-hw113064 --section-start .text=0x1000 --section-start .foo=0x1fe1004 -o $@ $<

nanomips_long_balc_bc_offset_4: nanomips_long_balc_bc_offset.o ../ld-new
../ld-new --section-start .text=0x1000 --section-start .foo=0x1fe1004 -o $@ $<

nanomips_long_balc_bc_offset_5: nanomips_long_balc_bc_offset.o ../ld-new
../ld-new --fix-nmips-hw113064 --section-start .text=0x1fe0ffc --section-start .foo=0x1000 -o $@ $<

nanomips_long_balc_bc_offset_6: nanomips_long_balc_bc_offset.o ../ld-new
../ld-new --fix-nmips-hw113064 --section-start .text=0x1fe0ffe --section-start .foo=0x1000 -o $@ $<

nanomips_lapc_out_of_range_pcrel: nanomips_lapc_out_of_range_pcrel.o ../ld-new
../ld-new --section-start .text=0x1000 --section-start .foo=0x2001020 -o $@ $<

Expand Down Expand Up @@ -4370,6 +4412,9 @@ nanomips_b_cond_out_of_range_pcrel.o: nanomips_b_cond_out_of_range.s
nanomips_move_balc_out_of_range_pcrel.o: nanomips_move_balc_out_of_range.s
$(TEST_AS) -EL -march=32r6 -m32 -mpcrel -o $@ $<

nanomips_long_balc_bc_offset.o: nanomips_long_balc_bc_offset.s
$(TEST_AS) -EL -march=32r6 -m32 -mpcrel -o $@ $<

nanomips_lapc_out_of_range_pcrel.o: nanomips_lapc_out_of_range.s
$(TEST_AS) -EL -march=32r6s -m32 -mpcrel -o $@ $<

Expand Down
51 changes: 51 additions & 0 deletions gold/testsuite/Makefile.in
Original file line number Diff line number Diff line change
Expand Up @@ -1134,6 +1134,12 @@ check_PROGRAMS = $(am__EXEEXT_1) $(am__EXEEXT_2) $(am__EXEEXT_3) \
@DEFAULT_TARGET_NANOMIPS_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@ nanomips_b_cond_out_of_range_pcrel.stdout \
@DEFAULT_TARGET_NANOMIPS_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@ nanomips_move_balc_1_out_of_range_pcrel.stdout \
@DEFAULT_TARGET_NANOMIPS_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@ nanomips_move_balc_2_out_of_range_pcrel.stdout \
@DEFAULT_TARGET_NANOMIPS_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@ nanomips_long_balc_bc_offset_1.stdout \
@DEFAULT_TARGET_NANOMIPS_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@ nanomips_long_balc_bc_offset_2.stdout \
@DEFAULT_TARGET_NANOMIPS_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@ nanomips_long_balc_bc_offset_3.stdout \
@DEFAULT_TARGET_NANOMIPS_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@ nanomips_long_balc_bc_offset_4.stdout \
@DEFAULT_TARGET_NANOMIPS_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@ nanomips_long_balc_bc_offset_5.stdout \
@DEFAULT_TARGET_NANOMIPS_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@ nanomips_long_balc_bc_offset_6.stdout \
@DEFAULT_TARGET_NANOMIPS_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@ nanomips_lapc_out_of_range_pcrel.stdout \
@DEFAULT_TARGET_NANOMIPS_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@ nanomips_lapc_out_of_range_nmf_pcrel.stdout \
@DEFAULT_TARGET_NANOMIPS_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@ nanomips_lapc_out_of_range_abs.stdout \
Expand Down Expand Up @@ -1192,6 +1198,12 @@ check_PROGRAMS = $(am__EXEEXT_1) $(am__EXEEXT_2) $(am__EXEEXT_3) \
@DEFAULT_TARGET_NANOMIPS_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@ nanomips_b_out_of_range_nmf_abs \
@DEFAULT_TARGET_NANOMIPS_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@ nanomips_move_balc_1_out_of_range_pcrel \
@DEFAULT_TARGET_NANOMIPS_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@ nanomips_move_balc_2_out_of_range_pcrel \
@DEFAULT_TARGET_NANOMIPS_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@ nanomips_long_balc_bc_offset_1 \
@DEFAULT_TARGET_NANOMIPS_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@ nanomips_long_balc_bc_offset_2 \
@DEFAULT_TARGET_NANOMIPS_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@ nanomips_long_balc_bc_offset_3 \
@DEFAULT_TARGET_NANOMIPS_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@ nanomips_long_balc_bc_offset_4 \
@DEFAULT_TARGET_NANOMIPS_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@ nanomips_long_balc_bc_offset_5 \
@DEFAULT_TARGET_NANOMIPS_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@ nanomips_long_balc_bc_offset_6 \
@DEFAULT_TARGET_NANOMIPS_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@ nanomips_lapc_out_of_range_pcrel \
@DEFAULT_TARGET_NANOMIPS_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@ nanomips_lapc_out_of_range_nmf_pcrel \
@DEFAULT_TARGET_NANOMIPS_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@ nanomips_lapc_out_of_range_abs \
Expand Down Expand Up @@ -8584,6 +8596,24 @@ uninstall-am:
@DEFAULT_TARGET_NANOMIPS_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@nanomips_move_balc_2_out_of_range_pcrel.stdout: nanomips_move_balc_2_out_of_range_pcrel
@DEFAULT_TARGET_NANOMIPS_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@ $(TEST_OBJDUMP) -d $< > $@

@DEFAULT_TARGET_NANOMIPS_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@nanomips_long_balc_bc_offset_1.stdout: nanomips_long_balc_bc_offset_1
@DEFAULT_TARGET_NANOMIPS_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@ $(TEST_OBJDUMP) -d $< > $@

@DEFAULT_TARGET_NANOMIPS_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@nanomips_long_balc_bc_offset_2.stdout: nanomips_long_balc_bc_offset_2
@DEFAULT_TARGET_NANOMIPS_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@ $(TEST_OBJDUMP) -d $< > $@

@DEFAULT_TARGET_NANOMIPS_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@nanomips_long_balc_bc_offset_3.stdout: nanomips_long_balc_bc_offset_3
@DEFAULT_TARGET_NANOMIPS_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@ $(TEST_OBJDUMP) -d $< > $@

@DEFAULT_TARGET_NANOMIPS_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@nanomips_long_balc_bc_offset_4.stdout: nanomips_long_balc_bc_offset_4
@DEFAULT_TARGET_NANOMIPS_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@ $(TEST_OBJDUMP) -d $< > $@

@DEFAULT_TARGET_NANOMIPS_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@nanomips_long_balc_bc_offset_5.stdout: nanomips_long_balc_bc_offset_5
@DEFAULT_TARGET_NANOMIPS_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@ $(TEST_OBJDUMP) -d $< > $@

@DEFAULT_TARGET_NANOMIPS_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@nanomips_long_balc_bc_offset_6.stdout: nanomips_long_balc_bc_offset_6
@DEFAULT_TARGET_NANOMIPS_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@ $(TEST_OBJDUMP) -d $< > $@

@DEFAULT_TARGET_NANOMIPS_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@nanomips_b_cond_out_of_range_pcrel.stdout: nanomips_b_cond_out_of_range_pcrel
@DEFAULT_TARGET_NANOMIPS_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@ $(TEST_OBJDUMP) -d $< > $@

Expand Down Expand Up @@ -8626,6 +8656,24 @@ uninstall-am:
@DEFAULT_TARGET_NANOMIPS_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@nanomips_move_balc_2_out_of_range_pcrel: nanomips_move_balc_out_of_range_pcrel.o ../ld-new
@DEFAULT_TARGET_NANOMIPS_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@ ../ld-new --section-start .text=0x1000 --section-start .foo=0x2001020 -o $@ $<

@DEFAULT_TARGET_NANOMIPS_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@nanomips_long_balc_bc_offset_1: nanomips_long_balc_bc_offset.o ../ld-new
@DEFAULT_TARGET_NANOMIPS_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@ ../ld-new --fix-nmips-hw113064 --section-start .text=0x1000 --section-start .foo=0x1fe1002 -o $@ $<

@DEFAULT_TARGET_NANOMIPS_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@nanomips_long_balc_bc_offset_2: nanomips_long_balc_bc_offset.o ../ld-new
@DEFAULT_TARGET_NANOMIPS_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@ ../ld-new --section-start .text=0x1000 --section-start .foo=0x1fe1002 -o $@ $<

@DEFAULT_TARGET_NANOMIPS_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@nanomips_long_balc_bc_offset_3: nanomips_long_balc_bc_offset.o ../ld-new
@DEFAULT_TARGET_NANOMIPS_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@ ../ld-new --fix-nmips-hw113064 --section-start .text=0x1000 --section-start .foo=0x1fe1004 -o $@ $<

@DEFAULT_TARGET_NANOMIPS_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@nanomips_long_balc_bc_offset_4: nanomips_long_balc_bc_offset.o ../ld-new
@DEFAULT_TARGET_NANOMIPS_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@ ../ld-new --section-start .text=0x1000 --section-start .foo=0x1fe1004 -o $@ $<

@DEFAULT_TARGET_NANOMIPS_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@nanomips_long_balc_bc_offset_5: nanomips_long_balc_bc_offset.o ../ld-new
@DEFAULT_TARGET_NANOMIPS_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@ ../ld-new --fix-nmips-hw113064 --section-start .text=0x1fe0ffc --section-start .foo=0x1000 -o $@ $<

@DEFAULT_TARGET_NANOMIPS_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@nanomips_long_balc_bc_offset_6: nanomips_long_balc_bc_offset.o ../ld-new
@DEFAULT_TARGET_NANOMIPS_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@ ../ld-new --fix-nmips-hw113064 --section-start .text=0x1fe0ffe --section-start .foo=0x1000 -o $@ $<

@DEFAULT_TARGET_NANOMIPS_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@nanomips_lapc_out_of_range_pcrel: nanomips_lapc_out_of_range_pcrel.o ../ld-new
@DEFAULT_TARGET_NANOMIPS_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@ ../ld-new --section-start .text=0x1000 --section-start .foo=0x2001020 -o $@ $<

Expand Down Expand Up @@ -8662,6 +8710,9 @@ uninstall-am:
@DEFAULT_TARGET_NANOMIPS_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@nanomips_move_balc_out_of_range_pcrel.o: nanomips_move_balc_out_of_range.s
@DEFAULT_TARGET_NANOMIPS_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@ $(TEST_AS) -EL -march=32r6 -m32 -mpcrel -o $@ $<

@DEFAULT_TARGET_NANOMIPS_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@nanomips_long_balc_bc_offset.o: nanomips_long_balc_bc_offset.s
@DEFAULT_TARGET_NANOMIPS_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@ $(TEST_AS) -EL -march=32r6 -m32 -mpcrel -o $@ $<

@DEFAULT_TARGET_NANOMIPS_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@nanomips_lapc_out_of_range_pcrel.o: nanomips_lapc_out_of_range.s
@DEFAULT_TARGET_NANOMIPS_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@ $(TEST_AS) -EL -march=32r6s -m32 -mpcrel -o $@ $<

Expand Down
18 changes: 18 additions & 0 deletions gold/testsuite/nanomips_long_balc_bc_offset.s
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
.linkrelax
.section .text,"ax",@progbits
.align 1
.globl __start
.ent __start
__start:
balc foo
.end __start
.size __start, .-__start

.section .foo,"ax",@progbits
.align 1
.globl foo
.ent foo
foo:
jrc $ra
.end foo
.size foo, .-foo
23 changes: 23 additions & 0 deletions gold/testsuite/nanomips_pcrel_out_of_range.sh
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,29 @@ check nanomips_move_balc_2_out_of_range_pcrel.stdout " 1002: 6023 0018 lapc at,
check nanomips_move_balc_2_out_of_range_pcrel.stdout " 1006: 0200"
check nanomips_move_balc_2_out_of_range_pcrel.stdout " 1008: d830 jalrc at"

# Test 1 and 2 checks the largest value that does not trigger the expansion,
# regardless the option was set or not.
check nanomips_long_balc_bc_offset_1.stdout "1000:.*2bfd fffe.*balc.*1fe1002 <foo>"
check nanomips_long_balc_bc_offset_2.stdout "1000:.*2bfd fffe.*balc.*1fe1002 <foo>"

# Test 3 checks that if the option is set, it triggers the expansion if the
# offset is close to ~+-32Mb into the lapc+jalrc. This is needed in order to
# work around a bug in the hardware.
check nanomips_long_balc_bc_offset_3.stdout "1000:.*6023 fffe.*lapc.*at,1fe1004 <foo>"
check nanomips_long_balc_bc_offset_3.stdout "1004:.*01fd"
check nanomips_long_balc_bc_offset_3.stdout "1006:.*d830.*jalrc.*at"

# Test 4 checks that the code remains the same, without the expansion applied.
check nanomips_long_balc_bc_offset_4.stdout "1000:.*2bfe 0000.*balc.*fe1004 <foo>"

# Test 5 checks that the expansion won't be applied, for the backward branch.
check nanomips_long_balc_bc_offset_5.stdout "1fe0ffc:.*2a02 0001.*balc.*1000 <foo>"

# Test 6 checks that the expansion will be applied, for the backward branch.
check nanomips_long_balc_bc_offset_6.stdout "1fe0ffe:.*6023 fffc.*lapc.*at,1000.*"
check nanomips_long_balc_bc_offset_6.stdout "1fe1002:.*fe01"
check nanomips_long_balc_bc_offset_6.stdout "1fe1004:.*d830.*jalrc.*at"

# Test lapc expansion to aluipc and ori.
check nanomips_lapc_out_of_range_pcrel.stdout " 1000: e080 0042 aluipc a0,.*"
check nanomips_lapc_out_of_range_pcrel.stdout " 1004: 8084 0020 ori a0,a0,0x20"
Expand Down

0 comments on commit 2723399

Please sign in to comment.