--- gcc/gcc/config/sh/sh.c +++ gcc/gcc/config/sh/sh.c @@ -9106,6 +9106,15 @@ sh_output_mi_thunk (FILE *file, tree thu } this = FUNCTION_ARG (cum, Pmode, ptr_type_node, 1); + /* In PIC case, we set PIC register to compute the target address. We + can use a scratch register to save and restore the original value + except for SHcompact. For SHcompact, use stack. */ + if (flag_pic && TARGET_SHCOMPACT) + { + push (PIC_OFFSET_TABLE_REGNUM); + emit_insn (gen_GOTaddr2picreg ()); + } + /* For SHcompact, we only have r0 for a scratch register: r1 is the static chain pointer (even if you can't have nested virtual functions right now, someone might implement them sometime), and the rest of the @@ -9188,8 +9197,24 @@ sh_output_mi_thunk (FILE *file, tree thu assemble_external (function); TREE_USED (function) = 1; } + /* We can use scratch1 to save and restore the original value of + PIC register except for SHcompact. */ + if (flag_pic && ! TARGET_SHCOMPACT) + { + emit_move_insn (scratch1, + gen_rtx_REG (Pmode, PIC_OFFSET_TABLE_REGNUM)); + emit_insn (gen_GOTaddr2picreg ()); + } funexp = XEXP (DECL_RTL (function), 0); emit_move_insn (scratch2, funexp); + if (flag_pic) + { + if (! TARGET_SHCOMPACT) + emit_move_insn (gen_rtx_REG (Pmode, PIC_OFFSET_TABLE_REGNUM), + scratch1); + else + pop (PIC_OFFSET_TABLE_REGNUM); + } funexp = gen_rtx_MEM (FUNCTION_MODE, scratch2); sibcall = emit_call_insn (gen_sibcall (funexp, const0_rtx, NULL_RTX)); SIBLING_CALL_P (sibcall) = 1;