Skip to content

Commit

Permalink
Merge pull request #6 from MediaTek-Labs/fix_imm48
Browse files Browse the repository at this point in the history
Rewrite instructions with problematic imm48 encoding
  • Loading branch information
farazs-github authored Sep 25, 2023
2 parents 2723399 + 790dba8 commit d772b7a
Show file tree
Hide file tree
Showing 9 changed files with 260 additions and 35 deletions.
4 changes: 3 additions & 1 deletion gold/nanomips-insn-property.h
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,9 @@ enum Transform_type
// Transform to 16-bit save/restore.jrc instruction.
TT_SAVERESTORE16,
// Transform to 16-bit bxxzc instruction.
TT_PCREL16_ZERO
TT_PCREL16_ZERO,
// Transform to avoid hw110880 issue
TT_IMM48_FIX,
};

// The Nanomips_insn_template class is to store information about a
Expand Down
67 changes: 41 additions & 26 deletions gold/nanomips-insn.def

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion gold/nanomips-reloc.def
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ NRD(HI20, STATIC, 32, 20, 0,
NRD(LO12, STATIC, 32, 12, 0xfc00f000, Symbol::ABSOLUTE_REF)
NRD(GPREL_I32, STATIC, 48, 32, 0xfc1f, Symbol::RELATIVE_REF)
NRD(PC_I32, STATIC, 48, 32, 0xfc1f, Symbol::RELATIVE_REF)
NRD(I32, STATIC, 48, 32, 0, Symbol::ABSOLUTE_REF)
NRD(I32, STATIC, 48, 32, 0xfc1f, Symbol::ABSOLUTE_REF)
NRD(GOT_DISP, STATIC, 32, 21, 0xfc000003, Symbol::RELATIVE_REF)
NRD(GOTPC_I32, STATIC, 48, 32, 0, Symbol::RELATIVE_REF)
NRD(GOTPC_HI20, STATIC, 32, 20, 0, Symbol::RELATIVE_REF)
Expand Down
55 changes: 51 additions & 4 deletions gold/nanomips.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2495,6 +2495,15 @@ class Nanomips_relocate_functions
}

public:
static inline bool
value_needs_hw110880_fix(Address value)
{
if (!parameters->options().fix_nmips_hw110880())
return false;

return (((value & 0x50016400) == 0x50012400) &&
(((value >> 24) & 0x7) == 0x1 || ((value >> 24) & 0x2) == 0x2));
}
// R_NANOMIPS_GOT_DISP, R_NANOMIPS_GOT_PAGE, R_NANOMIPS_GOT_CALL,
// R_NANOMIPS_TLS_GD, , R_NANOMIPS_TLS_LD, R_NANOMIPS_TLS_GOTTPREL
static inline Status
Expand Down Expand Up @@ -2646,8 +2655,17 @@ class Nanomips_relocate_functions
// R_NANOMIPS_TLS_GOTTPREL_PC_I32, R_NANOMIPS_TLS_TPREL_I32,
// R_NANOMIPS_TLS_DTPREL_I32
static inline Status
rel48(unsigned char* view, Address value, bool should_check_overflow)
rel48(unsigned char* view, Address value, bool should_check_overflow,
const Nanomips_reloc_property* reloc_property)
{
if (value_needs_hw110880_fix(value) &&
(reloc_property->name() == "li[48]" ||
reloc_property->name() == "addiu[48]" ||
reloc_property->name() == "addiugp[48]" ||
reloc_property->name() == "lapc[48]" ||
reloc_property->name() == "swpc[48]"))
return Status::STATUS_UNALIGNED;

Nanomips_insn_swap<48, big_endian>::writeval(view, value);
return (should_check_overflow ? check_overflow<32>(value, CHECK_SIGNED)
: STATUS_OKAY);
Expand Down Expand Up @@ -4558,11 +4576,17 @@ Nanomips_transformations<size, big_endian>::transform(
switch (r_type)
{
case elfcpp::R_NANOMIPS_GPREL_I32:
case elfcpp::R_NANOMIPS_PC_I32:
r_offset -= 2;
treg = insn_property->treg(insn);
sreg = 0;
break;
case elfcpp::R_NANOMIPS_PC_I32:
case elfcpp::R_NANOMIPS_I32:
r_offset -= 2;
treg = insn_property->treg(insn);
treg = treg << 5 | treg;
sreg = parameters->options().expand_reg();
break;
case elfcpp::R_NANOMIPS_PC25_S1:
treg = parameters->options().expand_reg();
sreg = parameters->options().expand_reg();
Expand Down Expand Up @@ -5248,6 +5272,8 @@ Nanomips_expand_insn<size, big_endian>::find_insn(
case elfcpp::R_NANOMIPS_TLS_GD:
case elfcpp::R_NANOMIPS_TLS_LD:
case elfcpp::R_NANOMIPS_TLS_GOTTPREL:
case elfcpp::R_NANOMIPS_PC_I32:
case elfcpp::R_NANOMIPS_I32:
return nanomips_insn_property_table->get_insn_property(insn, mask,
r_type);
default:
Expand Down Expand Up @@ -5344,6 +5370,11 @@ Nanomips_expand_insn<size, big_endian>::expand_type(
case elfcpp::R_NANOMIPS_LO4_S2:
// Transform [ls]w[16] into [ls]w.
return TT_ABS32;
case elfcpp::R_NANOMIPS_PC_I32:
case elfcpp::R_NANOMIPS_I32:
return (insn_property->has_transform(TT_IMM48_FIX, r_type)
? TT_IMM48_FIX
: TT_NONE);
default:
gold_unreachable();
}
Expand Down Expand Up @@ -5420,13 +5451,15 @@ Nanomips_expand_insn<size, big_endian>::type(
Address address,
Address gp)
{
typedef Nanomips_relocate_functions<size, big_endian> Reloc_funcs;
const Address invalid_address = static_cast<Address>(0) - 1;
const Nanomips_relobj<size, big_endian>* relobj =
Nanomips_relobj<size, big_endian>::as_nanomips_relobj(relinfo->object);
unsigned int r_type = elfcpp::elf_r_type<size>(reloc.get_r_info());
typename elfcpp::Elf_types<size>::Elf_Swxword r_addend =
reloc.get_r_addend();


switch (r_type)
{
case elfcpp::R_NANOMIPS_PC25_S1:
Expand Down Expand Up @@ -5550,6 +5583,20 @@ Nanomips_expand_insn<size, big_endian>::type(
case elfcpp::R_NANOMIPS_TLS_LD:
case elfcpp::R_NANOMIPS_TLS_GOTTPREL:
return this->expand_code_and_data_models(target, relobj, gsym, reloc, gp);
case elfcpp::R_NANOMIPS_PC_I32:
{
Valtype value = psymval->value(relobj, r_addend) - address - 6;
if (!Reloc_funcs::value_needs_hw110880_fix(value))
return TT_NONE;
break;
}
case elfcpp::R_NANOMIPS_I32:
{
Valtype value = psymval->value(relobj, r_addend);
if (!Reloc_funcs::value_needs_hw110880_fix(value))
return TT_NONE;
break;
}
default:
gold_unreachable();
}
Expand Down Expand Up @@ -6963,7 +7010,7 @@ Target_nanomips<size, big_endian>::resolve_pcrel_relocatable(
switch (r_type)
{
case elfcpp::R_NANOMIPS_PC_I32:
reloc_status = Reloc_funcs::rel48(view, value, true);
reloc_status = Reloc_funcs::rel48(view, value, true, reloc_property);
break;
case elfcpp::R_NANOMIPS_PC25_S1:
reloc_status = Reloc_funcs::relpc25_s1(view, value, true);
Expand Down Expand Up @@ -8376,7 +8423,7 @@ Target_nanomips<size, big_endian>::Relocate::relocate(
case elfcpp::R_NANOMIPS_TLS_GOTTPREL_PC_I32:
case elfcpp::R_NANOMIPS_TLS_TPREL_I32:
case elfcpp::R_NANOMIPS_TLS_DTPREL_I32:
reloc_status = Reloc_funcs::rel48(view, value, check_overflow);
reloc_status = Reloc_funcs::rel48(view, value, check_overflow, reloc_property);
break;
case elfcpp::R_NANOMIPS_32:
{
Expand Down
4 changes: 4 additions & 0 deletions gold/options.h
Original file line number Diff line number Diff line change
Expand Up @@ -880,6 +880,10 @@ class General_options
N_("(nanoMIPS only) Do not finalize relocations in "
"relocatable output"));

DEFINE_bool(fix_nmips_hw110880, options::TWO_DASHES, '\0', false,
N_("(nanoMIPS only) Rewrite instructions to avoid hw110880 issue"),
N_("(nanoMIPS only) Do not rewrite instructions to avoid hw110880 issue"));

DEFINE_string(filter, options::TWO_DASHES, 'F', NULL,
N_("Filter for shared object symbol table"),
N_("SHLIB"));
Expand Down
18 changes: 18 additions & 0 deletions gold/testsuite/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -4920,6 +4920,24 @@ nanomips_emit_relocs.o: nanomips_emit_relocs.s

MOSTLYCLEANFILES += nanomips_emit_relocs

# Test that the -fix-nmips-hw110880 performs transformations

check_SCRIPTS += nanomips_fix_hw110880.sh
check_DATA += nanomips_fix_hw110880.stdout

nanomips_fix_hw110880.stdout: nanomips_fix_hw110880
$(TEST_OBJDUMP) -d -M show-arch-insn $< > $@

nanomips_fix_hw110880: nanomips_fix_hw110880.o ../ld-new
../ld-new nanomips_fix_hw110880.o --fix-nmips-hw110880 --no-relax \
--section-start .text=0x1000000 --section-start .foo=0x51012400 \
--section-start .bar=0x52012500 --section-start .frob=0x2000000 -o $@

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

MOSTLYCLEANFILES += nanomips_fix_hw110880

endif DEFAULT_TARGET_NANOMIPS

endif NATIVE_OR_CROSS_LINKER
Expand Down
24 changes: 21 additions & 3 deletions gold/testsuite/Makefile.in
Original file line number Diff line number Diff line change
Expand Up @@ -1112,6 +1112,8 @@ check_PROGRAMS = $(am__EXEEXT_1) $(am__EXEEXT_2) $(am__EXEEXT_3) \

# Test that the --emit-relocs works with --gc-sections.
# Not nanoMIPS specific, but we only run these tests on host.

# Test that the -fix-nmips-hw110880 performs transformations
@DEFAULT_TARGET_NANOMIPS_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@am__append_106 = nanomips_pcrel_out_of_range.sh \
@DEFAULT_TARGET_NANOMIPS_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@ nanomips_gprel_out_of_range.sh \
@DEFAULT_TARGET_NANOMIPS_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@ nanomips_sort_by_ref.sh \
Expand All @@ -1124,7 +1126,8 @@ check_PROGRAMS = $(am__EXEEXT_1) $(am__EXEEXT_2) $(am__EXEEXT_3) \
@DEFAULT_TARGET_NANOMIPS_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@ nanomips_wrap.sh \
@DEFAULT_TARGET_NANOMIPS_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@ nanomips_saverestore_relax.sh \
@DEFAULT_TARGET_NANOMIPS_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@ nanomips_bxxzc32_relax.sh \
@DEFAULT_TARGET_NANOMIPS_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@ nanomips_emit_relocs.sh
@DEFAULT_TARGET_NANOMIPS_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@ nanomips_emit_relocs.sh \
@DEFAULT_TARGET_NANOMIPS_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@ nanomips_fix_hw110880.sh
@DEFAULT_TARGET_NANOMIPS_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@am__append_107 = nanomips_b_out_of_range_pcrel.stdout \
@DEFAULT_TARGET_NANOMIPS_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@ nanomips_b_out_of_range_insn32_pcrel.stdout \
@DEFAULT_TARGET_NANOMIPS_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@ nanomips_b_out_of_range_nmf_pcrel.stdout \
Expand Down Expand Up @@ -1188,7 +1191,8 @@ check_PROGRAMS = $(am__EXEEXT_1) $(am__EXEEXT_2) $(am__EXEEXT_3) \
@DEFAULT_TARGET_NANOMIPS_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@ nanomips_wrap.stdout \
@DEFAULT_TARGET_NANOMIPS_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@ nanomips_saverestore_relax.stdout \
@DEFAULT_TARGET_NANOMIPS_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@ nanomips_bxxzc32_relax.stdout \
@DEFAULT_TARGET_NANOMIPS_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@ nanomips_emit_relocs.stdout
@DEFAULT_TARGET_NANOMIPS_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@ nanomips_emit_relocs.stdout \
@DEFAULT_TARGET_NANOMIPS_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@ nanomips_fix_hw110880.stdout
@DEFAULT_TARGET_NANOMIPS_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@am__append_108 = nanomips_b_out_of_range_pcrel \
@DEFAULT_TARGET_NANOMIPS_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@ nanomips_b_out_of_range_insn32_pcrel \
@DEFAULT_TARGET_NANOMIPS_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@ nanomips_b_out_of_range_nmf_pcrel \
Expand Down Expand Up @@ -1246,7 +1250,8 @@ check_PROGRAMS = $(am__EXEEXT_1) $(am__EXEEXT_2) $(am__EXEEXT_3) \
@DEFAULT_TARGET_NANOMIPS_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@ nanomips_wrap \
@DEFAULT_TARGET_NANOMIPS_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@ nanomips_saverestore_relax \
@DEFAULT_TARGET_NANOMIPS_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@ nanomips_bxxzc32_relax \
@DEFAULT_TARGET_NANOMIPS_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@ nanomips_emit_relocs
@DEFAULT_TARGET_NANOMIPS_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@ nanomips_emit_relocs \
@DEFAULT_TARGET_NANOMIPS_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@ nanomips_fix_hw110880
@DEFAULT_TARGET_X86_64_TRUE@am__append_109 = *.dwo *.dwp
@DEFAULT_TARGET_X86_64_TRUE@am__append_110 = dwp_test_1.sh \
@DEFAULT_TARGET_X86_64_TRUE@ dwp_test_2.sh
Expand Down Expand Up @@ -5680,6 +5685,8 @@ nanomips_bxxzc32_relax.sh.log: nanomips_bxxzc32_relax.sh
@p='nanomips_bxxzc32_relax.sh'; $(am__check_pre) $(LOG_COMPILE) "$$tst" $(am__check_post)
nanomips_emit_relocs.sh.log: nanomips_emit_relocs.sh
@p='nanomips_emit_relocs.sh'; $(am__check_pre) $(LOG_COMPILE) "$$tst" $(am__check_post)
nanomips_fix_hw110880.sh.log: nanomips_fix_hw110880.sh
@p='nanomips_fix_hw110880.sh'; $(am__check_pre) $(LOG_COMPILE) "$$tst" $(am__check_post)
dwp_test_1.sh.log: dwp_test_1.sh
@p='dwp_test_1.sh'; $(am__check_pre) $(LOG_COMPILE) "$$tst" $(am__check_post)
dwp_test_2.sh.log: dwp_test_2.sh
Expand Down Expand Up @@ -9079,6 +9086,17 @@ uninstall-am:
@DEFAULT_TARGET_NANOMIPS_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@nanomips_emit_relocs.o: nanomips_emit_relocs.s
@DEFAULT_TARGET_NANOMIPS_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@ $(TEST_AS) -EL -march=32r6 -m32 -o $@ $<

@DEFAULT_TARGET_NANOMIPS_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@nanomips_fix_hw110880.stdout: nanomips_fix_hw110880
@DEFAULT_TARGET_NANOMIPS_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@ $(TEST_OBJDUMP) -d -M show-arch-insn $< > $@

@DEFAULT_TARGET_NANOMIPS_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@nanomips_fix_hw110880: nanomips_fix_hw110880.o ../ld-new
@DEFAULT_TARGET_NANOMIPS_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@ ../ld-new nanomips_fix_hw110880.o --fix-nmips-hw110880 --no-relax \
@DEFAULT_TARGET_NANOMIPS_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@ --section-start .text=0x1000000 --section-start .foo=0x51012400 \
@DEFAULT_TARGET_NANOMIPS_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@ --section-start .bar=0x52012500 --section-start .frob=0x2000000 -o $@

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

# Tests for the dwp tool.
# We don't want to rely yet on GCC support for -gsplit-dwarf,
# so we use (for now) test cases in x86 assembly language,
Expand Down
48 changes: 48 additions & 0 deletions gold/testsuite/nanomips_fix_hw110880.s
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
.linkrelax
.section .text,"ax",@progbits
.align 4
.globl __start
.ent __start
__start:
# li[48] -> lapc[48].
li $a0, foo
# li[48] -> aluipc + ori.
li $a1, bar
li $a2, frob
# addiu[48] -> lapc[48] + addu
addiu $a3, foo
# addiu[48] -> aluipc + ori + addu
addiu $a4, bar
addiu $a5, frob
# lapc[48] -> aluipc + ori.
lapc.b $t0, foo
lapc.b $t1, bar
swpc $t2, foo
swpc $t3, bar
.end __start
.size __start, .-__start

.section .foo,"ax",@progbits
.align 4
.globl foo
.ent foo
foo:
jrc $ra
.end foo
.size foo, .-foo
.section .bar,"ax",@progbits
.align 4
.globl bar
.ent bar
bar:
jrc $ra
.end bar
.size bar, .-bar
.section .frob,"ax",@progbits
.align 4
.globl frob
.ent frob
frob:
jrc $ra
.end frob
.size frob, .-frob
73 changes: 73 additions & 0 deletions gold/testsuite/nanomips_fix_hw110880.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
#!/bin/sh

# nanomips_function_call.sh -- test nanoMIPS function call transformations.

# Copyright (C) 2018 Free Software Foundation, Inc.
# Written by Vladimir Radosavljevic <[email protected]>.

# This file is part of gold.

# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.

# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.

# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
# MA 02110-1301, USA.

check()
{
file=$1
pattern=$2

found=`grep "$pattern" $file`
if test -z "$found"; then
echo "pattern \"$pattern\" not found in file $file."
exit 1
fi
}

# Test li[48] transformation into lapc[48].
check nanomips_fix_hw110880.stdout " 1000000: 6083 23fa lapc\[48\] a0.*"

# Test li[48] transformation into aluipc, ori.
check nanomips_fix_hw110880.stdout " 1000006: e0a1 2a22 aluipc a1,.*"
check nanomips_fix_hw110880.stdout " 100000a: 80a5 0500 ori a1,a1,.*"

# Test li[48] not being transformed
check nanomips_fix_hw110880.stdout " 100000e: 60c0 0000 li\[48\] a2,.*"

# Test addiu[48] transformation into lapc[48], addu.
check nanomips_fix_hw110880.stdout " 1000014: 6023 23e6 lapc\[48\] at,.*"
check nanomips_fix_hw110880.stdout " 100001a: 2027 3950 addu\[32\] a3,a3,at"

# Test addiu[48] transformation into aluipc, ori, addu.
check nanomips_fix_hw110880.stdout " 100001e: e021 2a22 aluipc at,.*"
check nanomips_fix_hw110880.stdout " 1000022: 8021 0500 ori at,at,.*"
check nanomips_fix_hw110880.stdout " 1000026: 2028 4150 addu\[32\] a4,a4,at"

# Test addiu[48] not being transformed
check nanomips_fix_hw110880.stdout " 100002a: 6121 0000 addiu\[48\] a5,a5,.*"

# Test lapc[48] not being transformed
check nanomips_fix_hw110880.stdout " 1000030: 6183 23ca lapc\[48\] t0,.*"

# Test lapc[48] transformation into aluipc, ori.
check nanomips_fix_hw110880.stdout " 1000036: e1a1 2a22 aluipc t1,.*"
check nanomips_fix_hw110880.stdout " 100003a: 81ad 0500 ori t1,t1,.*"

# Test swpc[48] not being transformed
check nanomips_fix_hw110880.stdout " 100003e: 61cf 23bc swpc\[48\] t2,.*"

# Test swpc[48] transformation into aluipc, sw.
check nanomips_fix_hw110880.stdout " 1000044: e021 2a22 aluipc at,.*"
check nanomips_fix_hw110880.stdout " 1000048: 85e1 9500 sw\[u12\] t3,.*(at)"

exit 0

0 comments on commit d772b7a

Please sign in to comment.