aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarcus Comstedt <marcus@mc.pp.se>2021-03-19 20:49:06 +0100
committerKito Cheng <kito.cheng@sifive.com>2021-03-23 17:31:13 +0800
commit28bddf0e322a5fdc33d3dcc3b9928d559ad7f124 (patch)
treee07d7eff08d2d0d50b0b636ddab6306fcfe34351
parentf1af1326d269b1d8efb696a50c9e88d0ab6ec45e (diff)
downloadgcc-28bddf0e322a5fdc33d3dcc3b9928d559ad7f124.zip
gcc-28bddf0e322a5fdc33d3dcc3b9928d559ad7f124.tar.gz
gcc-28bddf0e322a5fdc33d3dcc3b9928d559ad7f124.tar.bz2
RISC-V: Fix trampoline generation on big endian
gcc/ * config/riscv/riscv.c (riscv_swap_instruction): New function to byteswap an SImode rtx containing an instruction. (riscv_trampoline_init): Byteswap the generated instructions when needed.
-rw-r--r--gcc/config/riscv/riscv.c19
1 files changed, 15 insertions, 4 deletions
diff --git a/gcc/config/riscv/riscv.c b/gcc/config/riscv/riscv.c
index 99b8438..fe48db7 100644
--- a/gcc/config/riscv/riscv.c
+++ b/gcc/config/riscv/riscv.c
@@ -1073,6 +1073,15 @@ riscv_force_binary (machine_mode mode, enum rtx_code code, rtx x, rtx y)
return riscv_emit_binary (code, gen_reg_rtx (mode), x, y);
}
+static rtx
+riscv_swap_instruction (rtx inst)
+{
+ gcc_assert (GET_MODE (inst) == SImode);
+ if (BYTES_BIG_ENDIAN)
+ inst = expand_unop (SImode, bswap_optab, inst, gen_reg_rtx (SImode), 1);
+ return inst;
+}
+
/* Copy VALUE to a register and return that register. If new pseudos
are allowed, copy it into a new register, otherwise use DEST. */
@@ -4955,7 +4964,7 @@ riscv_trampoline_init (rtx m_tramp, tree fndecl, rtx chain_value)
gen_int_mode (lui_hi_chain_code, SImode));
mem = adjust_address (m_tramp, SImode, 0);
- riscv_emit_move (mem, lui_hi_chain);
+ riscv_emit_move (mem, riscv_swap_instruction (lui_hi_chain));
/* Gen lui t0, hi(func). */
rtx hi_func = riscv_force_binary (SImode, PLUS, target_function,
@@ -4967,7 +4976,7 @@ riscv_trampoline_init (rtx m_tramp, tree fndecl, rtx chain_value)
gen_int_mode (lui_hi_func_code, SImode));
mem = adjust_address (m_tramp, SImode, 1 * GET_MODE_SIZE (SImode));
- riscv_emit_move (mem, lui_hi_func);
+ riscv_emit_move (mem, riscv_swap_instruction (lui_hi_func));
/* Gen addi t2, t2, lo(chain). */
rtx lo_chain = riscv_force_binary (SImode, AND, chain_value,
@@ -4982,7 +4991,7 @@ riscv_trampoline_init (rtx m_tramp, tree fndecl, rtx chain_value)
force_reg (SImode, GEN_INT (lo_chain_code)));
mem = adjust_address (m_tramp, SImode, 2 * GET_MODE_SIZE (SImode));
- riscv_emit_move (mem, addi_lo_chain);
+ riscv_emit_move (mem, riscv_swap_instruction (addi_lo_chain));
/* Gen jr t0, lo(func). */
rtx lo_func = riscv_force_binary (SImode, AND, target_function,
@@ -4995,7 +5004,7 @@ riscv_trampoline_init (rtx m_tramp, tree fndecl, rtx chain_value)
force_reg (SImode, GEN_INT (lo_func_code)));
mem = adjust_address (m_tramp, SImode, 3 * GET_MODE_SIZE (SImode));
- riscv_emit_move (mem, jr_lo_func);
+ riscv_emit_move (mem, riscv_swap_instruction (jr_lo_func));
}
else
{
@@ -5021,6 +5030,8 @@ riscv_trampoline_init (rtx m_tramp, tree fndecl, rtx chain_value)
/* Copy the trampoline code. */
for (i = 0; i < ARRAY_SIZE (trampoline); i++)
{
+ if (BYTES_BIG_ENDIAN)
+ trampoline[i] = __builtin_bswap32(trampoline[i]);
mem = adjust_address (m_tramp, SImode, i * GET_MODE_SIZE (SImode));
riscv_emit_move (mem, gen_int_mode (trampoline[i], SImode));
}