]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
RISC-V: Fix trampoline generation on big endian
authorMarcus Comstedt <marcus@mc.pp.se>
Fri, 19 Mar 2021 19:49:06 +0000 (20:49 +0100)
committerKito Cheng <kito.cheng@sifive.com>
Tue, 23 Mar 2021 09:31:13 +0000 (17:31 +0800)
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.

gcc/config/riscv/riscv.c

index 99b843867b5bc6dadaa772a89b29556765386a0d..fe48db7a27988704b6ce7f2198eae7c17e4aa55b 100644 (file)
@@ -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));
        }