1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
|
--- 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;
|