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