gcc/ChangeLog:
* config/rx/predicates.md (rx_plt_call_operand): New predicate.
* config/rx/rx.md (PIC_REG): New constant.
(UNSPEC_PIC): Likewise.
(UNSPEC_GOT): Likewise.
(UNSPEC_GOTOFF): Likewise.
(UNSPEC_PLT): Likewise.
(UNSPEC_GOTFUNCDESC): Likewise.
(UNSPEC_GOTOFFFUNCDESC): Likewise.
(UNSPEC_PCOFFSET): Likewise.
(UNSPEC_PIC_RESTORE): Likewise.
(UNSPEC_PC_LOCATION): Likewise.
(tablejump): Use relative in pic case.
(call): Add FDPIC call.
(call_value): Likewise.
(call_internal): Add use PICREG.
(call_value_internal): Likewise.
(mov<register_modes:mode>): Generate got reference code in pic.
(addsi3): Generate got reference code in pic.
(sym2GOT): New.
(sym2GOTreg): New.
(sym2GOTOFF): New.
(sym2GOTOFFreg): New.
(sym2GOTFUNCDESC): New.
(sym2GOTFUNCDESCreg): New.
(sym2GOTOFFFUNCDESC): New.
(sym2GOTOFFFUNCDESCreg): New.
(sym2PLT): New.
(call_fdpic): New.
(call_internal_fd): New.
(call_internal_plt): New.
(call_value_fdpic): New.
(call_value_internal_fd): New.
(call_value_internal_plt): New.
(pcoffset_label): New.
(set_got): New.
(load_pc_location): New.
Signed-off-by: Yoshinori Sato <[email protected]>
---
gcc/config/rx/predicates.md | 4 +
gcc/config/rx/rx.md | 314 +++++++++++++++++++++++++++++++++---
2 files changed, 298 insertions(+), 20 deletions(-)
diff --git a/gcc/config/rx/predicates.md b/gcc/config/rx/predicates.md
index c51a21449e2..736a8d7a376 100644
--- a/gcc/config/rx/predicates.md
+++ b/gcc/config/rx/predicates.md
@@ -307,3 +307,7 @@
(define_predicate "rshift_operator"
(match_code "ashiftrt,lshiftrt")
)
+
+(define_predicate "rx_plt_call_operand"
+ (match_code "const")
+)
diff --git a/gcc/config/rx/rx.md b/gcc/config/rx/rx.md
index a3d966efdcc..7d76661d51d 100644
--- a/gcc/config/rx/rx.md
+++ b/gcc/config/rx/rx.md
@@ -35,6 +35,7 @@
(define_constants
[
(SP_REG 0)
+ (PIC_REG 13)
(CC_REG 16)
(UNSPEC_LOW_REG 0)
@@ -76,6 +77,16 @@
(UNSPEC_PID_ADDR 52)
+ (UNSPEC_PIC 60)
+ (UNSPEC_GOT 61)
+ (UNSPEC_GOTOFF 62)
+ (UNSPEC_PLT 63)
+ (UNSPEC_GOTFUNCDESC 64)
+ (UNSPEC_GOTOFFFUNCDESC 65)
+ (UNSPEC_PCOFFSET 66)
+ (UNSPEC_PIC_RESTORE 67)
+ (UNSPEC_PC_LOCATION 68)
+
(CTRLREG_PSW 0)
(CTRLREG_PC 1)
(CTRLREG_USP 2)
@@ -342,9 +353,9 @@
(match_operand:SI 0 "register_operand" "r"))
(use (label_ref (match_operand 1 "" "")))]
""
- { return TARGET_PID ? (TARGET_AS100_SYNTAX ? "\n?:\tbra\t%0"
- : "\n1:\tbra\t%0")
- : "\n1:jmp\t%0";
+ { return TARGET_PID || flag_pic ? (TARGET_AS100_SYNTAX ? "\n?:\tbra\t%0"
+ : "\n1:\tbra\t%0")
+ : "\n1:jmp\t%0";
}
[(set_attr "timings" "33")
(set_attr "length" "2")]
@@ -425,14 +436,23 @@
(define_expand "call"
[(call (match_operand:QI 0 "general_operand")
- (match_operand:SI 1 "general_operand"))]
+ (match_operand:SI 1 "general_operand"))
+ (use (match_operand 2 "" ""))
+ (use (reg:SI PIC_REG))]
""
{
rtx dest = XEXP (operands[0], 0);
- if (! rx_call_operand (dest, Pmode))
- dest = force_reg (Pmode, dest);
- emit_call_insn (gen_call_internal (dest));
+ if (!TARGET_FDPIC)
+ {
+ if (! rx_call_operand (dest, Pmode))
+ dest = force_reg (Pmode, dest);
+ emit_call_insn (gen_call_internal (dest));
+ }
+ else
+ {
+ emit_call_insn (gen_call_fdpic(operands[0], operands[1], operands[2]));
+ }
DONE;
}
)
@@ -440,7 +460,8 @@
(define_insn "call_internal"
[(call (mem:QI (match_operand:SI 0 "rx_call_operand" "r,CALL_OP_SYMBOL_REF"))
(const_int 0))
- (clobber (reg:CC CC_REG))]
+ (clobber (reg:CC CC_REG))
+ (use (reg:SI PIC_REG))]
""
"@
jsr\t%0
@@ -452,14 +473,24 @@
(define_expand "call_value"
[(set (match_operand 0 "register_operand")
(call (match_operand:QI 1 "general_operand")
- (match_operand:SI 2 "general_operand")))]
+ (match_operand:SI 2 "general_operand")))
+ (use (match_operand 3 "" ""))
+ (use (reg:SI PIC_REG))]
""
{
rtx dest = XEXP (operands[1], 0);
- if (! rx_call_operand (dest, Pmode))
- dest = force_reg (Pmode, dest);
- emit_call_insn (gen_call_value_internal (operands[0], dest));
+ if (!TARGET_FDPIC ||
+ (SYMBOL_REF_P(dest) && SYMBOL_REF_LOCAL_P(dest)))
+ {
+ if (! rx_call_operand (dest, Pmode))
+ dest = force_reg (Pmode, dest);
+ emit_call_insn (gen_call_value_internal (operands[0], dest));
+ }
+ else
+ {
+ emit_call_insn (gen_call_value_fdpic(operands[0], operands[1],
operands[2]));
+ }
DONE;
}
)
@@ -468,7 +499,8 @@
[(set (match_operand 0 "register_operand" "=r,r")
(call (mem:QI (match_operand:SI 1 "rx_call_operand"
"r,CALL_OP_SYMBOL_REF"))
(const_int 0)))
- (clobber (reg:CC CC_REG))]
+ (clobber (reg:CC CC_REG))
+ (use (reg:SI PIC_REG))]
""
"@
jsr\t%1
@@ -576,8 +608,16 @@
{
if (MEM_P (operands[0]) && MEM_P (operands[1]))
operands[1] = copy_to_mode_reg (<register_modes:MODE>mode, operands[1]);
- operands[0] = rx_maybe_pidify_operand (operands[0], 0);
- operands[1] = rx_maybe_pidify_operand (operands[1], 0);
+ if (flag_pic)
+ {
+ operands[0] = rx_mov_pic_operands(operands[0], false);
+ operands[1] = rx_mov_pic_operands(operands[1], false);
+ }
+ else
+ {
+ operands[0] = rx_maybe_pidify_operand (operands[0], 0);
+ operands[1] = rx_maybe_pidify_operand (operands[1], 0);
+ }
if (GET_CODE (operands[0]) != REG
&& GET_CODE (operands[1]) == PLUS)
operands[1] = copy_to_mode_reg (<register_modes:MODE>mode, operands[1]);
@@ -869,11 +909,20 @@
(match_operand:SI 2 "rx_source_operand" "")))
(clobber (reg:CC CC_REG))])]
""
- "
- operands[0] = rx_maybe_pidify_operand (operands[0], 1);
- operands[1] = rx_maybe_pidify_operand (operands[1], 1);
- operands[2] = rx_maybe_pidify_operand (operands[2], 1);
- "
+ {
+ if (flag_pic)
+ {
+ operands[0] = rx_mov_pic_operands(operands[0], true);
+ operands[1] = rx_mov_pic_operands(operands[1], true);
+ operands[2] = rx_mov_pic_operands(operands[2], true);
+ }
+ else
+ {
+ operands[0] = rx_maybe_pidify_operand (operands[0], 1);
+ operands[1] = rx_maybe_pidify_operand (operands[1], 1);
+ operands[2] = rx_maybe_pidify_operand (operands[2], 1);
+ }
+ }
)
(define_insn "addsi3_internal"
@@ -2887,3 +2936,228 @@
[(set_attr "length" "16")
(set_attr "timings" "22")]
)
+
+(define_expand "sym2GOT"
+ [(const (unspec [(match_operand 0 "" "")] UNSPEC_GOT))]
+ ""
+ "")
+
+(define_expand "symGOT2reg"
+ [(match_operand 0 "" "") (match_operand 1 "" "")]
+ ""
+ {
+ rtx mem = !can_create_pseudo_p ()
+ ? operands[0] : gen_reg_rtx (GET_MODE (operands[0]));
+ rtx gotsym = gen_sym2GOTOFF (operands[1]);
+ rtx picreg = gen_rtx_REG (Pmode, PIC_REG);
+ PUT_MODE (gotsym, Pmode);
+
+ emit_insn (gen_addsi3(mem, picreg, gotsym));
+ emit_move_insn (operands[0], gen_rtx_MEM(Pmode, mem));
+ DONE;
+ }
+)
+
+(define_expand "sym2GOTOFF"
+ [(const (unspec [(match_operand 0 "" "")] UNSPEC_GOTOFF))]
+ ""
+ "")
+
+(define_expand "symGOTOFF2reg"
+ [(match_operand 0 "" "") (match_operand 1 "" "")]
+ ""
+ {
+ rtx picreg = gen_rtx_REG (Pmode, PIC_REG);
+
+ rtx gotoffsym = gen_sym2GOTOFF (operands[1]);
+ emit_move_insn (operands[0],
+ gen_rtx_MEM(Pmode,
+ gen_rtx_PLUS(Pmode, picreg, gotoffsym)));
+ DONE;
+ }
+)
+
+(define_expand "sym2GOTFUNCDESC"
+ [(const (unspec [(match_operand 0)] UNSPEC_GOTFUNCDESC))]
+ "TARGET_FDPIC")
+
+(define_expand "sym2GOTOFFFUNCDESC"
+ [(const (unspec [(match_operand 0)] UNSPEC_GOTOFFFUNCDESC))]
+ "TARGET_FDPIC")
+
+(define_expand "symGOTFUNCDESC2reg"
+ [(match_operand 0) (match_operand 1)]
+ "TARGET_FDPIC"
+ {
+ rtx picreg = rx_get_fdpic_reg_initial_val();
+ rtx gotsym = gen_sym2GOTFUNCDESC (operands[1]);
+ PUT_MODE (gotsym, Pmode);
+ emit_move_insn (operands[0], gen_rtx_PLUS(Pmode, picreg, gotsym));
+ DONE;
+ }
+)
+
+(define_expand "symGOTOFFFUNCDESC2reg"
+ [(match_operand 0) (match_operand 1)]
+ "TARGET_FDPIC"
+ {
+ rtx picreg = rx_get_fdpic_reg_initial_val();
+ rtx gotsym = gen_sym2GOTOFFFUNCDESC (operands[1]);
+ PUT_MODE (gotsym, Pmode);
+ emit_move_insn (operands[0], gen_rtx_PLUS(Pmode, picreg, gotsym));
+ DONE;
+ }
+)
+
+(define_expand "sym2PLT"
+ [(const (unspec [(match_operand 0 "" "")] UNSPEC_PLT))]
+ ""
+ "")
+
+(define_expand "call_fdpic"
+ [(call (match_operand:QI 0 "general_operand")
+ (match_operand:SI 1 "general_operand"))
+ (use (match_operand 2 "" ""))
+ (use (reg:SI PIC_REG))]
+ ""
+ {
+ rtx picreg = force_reg (Pmode, gen_rtx_REG(Pmode, PIC_REG));
+ rtx dest = XEXP (operands[0], 0);
+
+ if (SYMBOL_REF_P(dest) && SYMBOL_REF_LOCAL_P(dest))
+ {
+ if (! rx_call_operand (dest, Pmode))
+ dest = force_reg (Pmode, dest);
+ emit_call_insn (gen_call_internal (dest));
+ }
+ else
+ {
+ rtx savereg = gen_reg_rtx(Pmode);
+
+ emit_move_insn (savereg, picreg);
+ if (MEM_P(operands[0]) && SYMBOL_REF_P(dest))
+ {
+ dest = gen_sym2PLT(dest);
+ emit_call_insn (gen_call_internal_plt (dest));
+ }
+ else
+ {
+ rtx func = gen_reg_rtx(Pmode);
+ emit_move_insn(picreg, gen_rtx_MEM(Pmode,
+ plus_constant(Pmode, dest, 4)));
+ emit_move_insn(func, gen_rtx_MEM(Pmode, dest));
+ emit_call_insn (gen_call_internal_fd (func));
+ }
+ emit_move_insn (picreg, savereg);
+ }
+ DONE;
+ }
+)
+
+(define_insn "call_internal_fd"
+ [(call (mem:QI (match_operand:SI 0 "register_operand" "r"))
+ (const_int 0))
+ (clobber (reg:CC CC_REG))
+ (use (reg:SI PIC_REG))]
+ ""
+ "jsr\t%A0"
+ [(set_attr "length" "2")
+ (set_attr "timings" "33")]
+)
+
+(define_insn "call_internal_plt"
+ [(call (mem:QI (match_operand 0 "rx_plt_call_operand" ""))
+ (const_int 0))
+ (clobber (reg:CC CC_REG))
+ (use (reg:SI PIC_REG))]
+ ""
+ "bsr\t%A0"
+ [(set_attr "length" "4")
+ (set_attr "timings" "33")]
+)
+
+(define_expand "call_value_fdpic"
+ [(call (match_operand:QI 0 "general_operand")
+ (match_operand:SI 1 "general_operand"))
+ (use (match_operand 2 "" ""))
+ (use (reg:SI PIC_REG))]
+ ""
+ {
+ rtx picreg = force_reg (Pmode, gen_rtx_REG(Pmode, PIC_REG));
+ rtx dest = XEXP (operands[1], 0);
+
+ if (SYMBOL_REF_P(dest) && SYMBOL_REF_LOCAL_P(dest))
+ {
+ if (! rx_call_operand (dest, Pmode))
+ dest = force_reg (Pmode, dest);
+ emit_call_insn (gen_call_internal (dest));
+ }
+ else
+ {
+ rtx savereg = gen_reg_rtx(Pmode);
+ emit_move_insn (savereg, picreg);
+ if (MEM_P(operands[1]) && SYMBOL_REF_P(dest))
+ {
+ dest = gen_sym2PLT(dest);
+ emit_call_insn (gen_call_value_internal_plt (operands[0], dest));
+ }
+ else
+ {
+ rtx fnc = gen_reg_rtx(Pmode);
+ emit_move_insn(picreg, gen_rtx_MEM(Pmode,
+ plus_constant(Pmode, dest, 4)));
+ emit_move_insn(fnc, gen_rtx_MEM(Pmode, dest));
+ emit_call_insn (gen_call_value_internal_fd (operands[0], fnc));
+ }
+ emit_move_insn (picreg, savereg);
+ }
+ DONE;
+ }
+)
+
+(define_insn "call_value_internal_plt"
+ [(set (match_operand 0 "register_operand" "=r")
+ (call (mem:QI (match_operand 1 "rx_plt_call_operand" ""))
+ (const_int 0)))
+ (clobber (reg:CC CC_REG))
+ (use (reg:SI PIC_REG))]
+ ""
+ "bsr\t%A1"
+ [(set_attr "length" "4")
+ (set_attr "timings" "33")]
+)
+
+(define_insn "call_value_internal_fd"
+ [(set (match_operand 0 "register_operand" "=r")
+ (call (mem:QI (match_operand:SI 1 "register_operand" "r"))
+ (const_int 0)))
+ (clobber (reg:CC CC_REG))
+ (use (reg:SI PIC_REG))]
+ ""
+ "jsr\t%1"
+ [(set_attr "length" "2")
+ (set_attr "timings" "33")]
+)
+
+(define_expand "pcoffset_label"
+ [(const:SI (unspec:SI [(match_operand:SI 0)] UNSPEC_PCOFFSET))]
+ ""
+ ""
+)
+
+(define_insn "set_got"
+ [(set (match_operand:SI 0 "register_operand" "+r,r")
+ (unspec:SI [(match_dup 0)
+ (match_operand:SI 1 "nonimmediate_operand" "r,m")]
+ UNSPEC_PIC_RESTORE))]
+ ""
+ "mov.L\t%1, %0"
+)
+
+(define_insn "load_pc_location"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (unspec_volatile:SI [(match_operand:SI 1 "immediate_operand" "i")]
+ UNSPEC_PC_LOCATION))]
+ ""
+ "\n1:\tmvfc\t%C1, %0"
+)
--
2.47.3