diff options
Diffstat (limited to 'gcc/config/sh/sh.md')
-rw-r--r-- | gcc/config/sh/sh.md | 480 |
1 files changed, 394 insertions, 86 deletions
diff --git a/gcc/config/sh/sh.md b/gcc/config/sh/sh.md index e8d3e5181215..557a0f0ff5f6 100644 --- a/gcc/config/sh/sh.md +++ b/gcc/config/sh/sh.md @@ -170,6 +170,9 @@ UNSPEC_SYMOFF ;; (unspec [OFFSET ANCHOR] UNSPEC_PCREL_SYMOFF) == OFFSET - (ANCHOR - .). UNSPEC_PCREL_SYMOFF + ;; For FDPIC + UNSPEC_GOTFUNCDESC + UNSPEC_GOTOFFFUNCDESC ;; Misc builtins UNSPEC_BUILTIN_STRLEN ]) @@ -2591,15 +2594,18 @@ ;; This reload would clobber the value in r0 we are trying to store. ;; If we let reload allocate r0, then this problem can never happen. (define_insn "udivsi3_i1" - [(set (match_operand:SI 0 "register_operand" "=z") + [(set (match_operand:SI 0 "register_operand" "=z,z") (udiv:SI (reg:SI R4_REG) (reg:SI R5_REG))) (clobber (reg:SI T_REG)) (clobber (reg:SI PR_REG)) (clobber (reg:SI R1_REG)) (clobber (reg:SI R4_REG)) - (use (match_operand:SI 1 "arith_reg_operand" "r"))] + (use (match_operand:SI 1 "arith_reg_operand" "r,r")) + (use (match_operand 2 "" "Z,Ccl"))] "TARGET_SH1 && TARGET_DIVIDE_CALL_DIV1" - "jsr @%1%#" + "@ + jsr @%1%# + bsrf %1\n%O2:%#" [(set_attr "type" "sfunc") (set_attr "needs_delay_slot" "yes")]) @@ -2648,7 +2654,7 @@ }) (define_insn "udivsi3_i4" - [(set (match_operand:SI 0 "register_operand" "=y") + [(set (match_operand:SI 0 "register_operand" "=y,y") (udiv:SI (reg:SI R4_REG) (reg:SI R5_REG))) (clobber (reg:SI T_REG)) (clobber (reg:SI PR_REG)) @@ -2660,16 +2666,19 @@ (clobber (reg:SI R4_REG)) (clobber (reg:SI R5_REG)) (clobber (reg:SI FPSCR_STAT_REG)) - (use (match_operand:SI 1 "arith_reg_operand" "r")) + (use (match_operand:SI 1 "arith_reg_operand" "r,r")) + (use (match_operand 2 "" "Z,Ccl")) (use (reg:SI FPSCR_MODES_REG))] "TARGET_FPU_DOUBLE && ! TARGET_FPU_SINGLE" - "jsr @%1%#" + "@ + jsr @%1%# + bsrf %1\n%O2:%#" [(set_attr "type" "sfunc") (set_attr "fp_mode" "double") (set_attr "needs_delay_slot" "yes")]) (define_insn "udivsi3_i4_single" - [(set (match_operand:SI 0 "register_operand" "=y") + [(set (match_operand:SI 0 "register_operand" "=y,y") (udiv:SI (reg:SI R4_REG) (reg:SI R5_REG))) (clobber (reg:SI T_REG)) (clobber (reg:SI PR_REG)) @@ -2680,10 +2689,13 @@ (clobber (reg:SI R1_REG)) (clobber (reg:SI R4_REG)) (clobber (reg:SI R5_REG)) - (use (match_operand:SI 1 "arith_reg_operand" "r"))] + (use (match_operand:SI 1 "arith_reg_operand" "r,r")) + (use (match_operand 2 "" "Z,Ccl"))] "(TARGET_FPU_SINGLE_ONLY || TARGET_FPU_DOUBLE || TARGET_SHCOMPACT) && TARGET_FPU_SINGLE" - "jsr @%1%#" + "@ + jsr @%1%# + bsrf %1\n%O2:%#" [(set_attr "type" "sfunc") (set_attr "needs_delay_slot" "yes")]) @@ -2742,11 +2754,11 @@ } else if (TARGET_DIVIDE_CALL_FP) { - function_symbol (operands[3], "__udivsi3_i4", SFUNC_STATIC); + rtx lab = function_symbol (operands[3], "__udivsi3_i4", SFUNC_STATIC).lab; if (TARGET_FPU_SINGLE) - last = gen_udivsi3_i4_single (operands[0], operands[3]); + last = gen_udivsi3_i4_single (operands[0], operands[3], lab); else - last = gen_udivsi3_i4 (operands[0], operands[3]); + last = gen_udivsi3_i4 (operands[0], operands[3], lab); } else if (TARGET_SHMEDIA_FPU) { @@ -2771,14 +2783,14 @@ if (TARGET_SHMEDIA) last = gen_udivsi3_i1_media (operands[0], operands[3]); else if (TARGET_FPU_ANY) - last = gen_udivsi3_i4_single (operands[0], operands[3]); + last = gen_udivsi3_i4_single (operands[0], operands[3], const0_rtx); else - last = gen_udivsi3_i1 (operands[0], operands[3]); + last = gen_udivsi3_i1 (operands[0], operands[3], const0_rtx); } else { - function_symbol (operands[3], "__udivsi3", SFUNC_STATIC); - last = gen_udivsi3_i1 (operands[0], operands[3]); + rtx lab = function_symbol (operands[3], "__udivsi3", SFUNC_STATIC).lab; + last = gen_udivsi3_i1 (operands[0], operands[3], lab); } emit_move_insn (gen_rtx_REG (SImode, 4), operands[1]); emit_move_insn (gen_rtx_REG (SImode, 5), operands[2]); @@ -2906,7 +2918,7 @@ emit_move_insn (gen_rtx_REG (DImode, R20_REG), x); break; } - sym = function_symbol (NULL, name, kind); + sym = function_symbol (NULL, name, kind).sym; emit_insn (gen_divsi3_media_2 (operands[0], sym)); DONE; } @@ -2926,31 +2938,37 @@ }) (define_insn "divsi3_i4" - [(set (match_operand:SI 0 "register_operand" "=y") + [(set (match_operand:SI 0 "register_operand" "=y,y") (div:SI (reg:SI R4_REG) (reg:SI R5_REG))) (clobber (reg:SI PR_REG)) (clobber (reg:DF DR0_REG)) (clobber (reg:DF DR2_REG)) (clobber (reg:SI FPSCR_STAT_REG)) - (use (match_operand:SI 1 "arith_reg_operand" "r")) + (use (match_operand:SI 1 "arith_reg_operand" "r,r")) + (use (match_operand 2 "" "Z,Ccl")) (use (reg:SI FPSCR_MODES_REG))] "TARGET_FPU_DOUBLE && ! TARGET_FPU_SINGLE" - "jsr @%1%#" + "@ + jsr @%1%# + bsrf %1\n%O2:%#" [(set_attr "type" "sfunc") (set_attr "fp_mode" "double") (set_attr "needs_delay_slot" "yes")]) (define_insn "divsi3_i4_single" - [(set (match_operand:SI 0 "register_operand" "=y") + [(set (match_operand:SI 0 "register_operand" "=y,y") (div:SI (reg:SI R4_REG) (reg:SI R5_REG))) (clobber (reg:SI PR_REG)) (clobber (reg:DF DR0_REG)) (clobber (reg:DF DR2_REG)) (clobber (reg:SI R2_REG)) - (use (match_operand:SI 1 "arith_reg_operand" "r"))] + (use (match_operand:SI 1 "arith_reg_operand" "r,r")) + (use (match_operand 2 "" "Z,Ccl"))] "(TARGET_FPU_SINGLE_ONLY || TARGET_FPU_DOUBLE || TARGET_SHCOMPACT) && TARGET_FPU_SINGLE" - "jsr @%1%#" + "@ + jsr @%1%# + bsrf %1\n%O2:%#" [(set_attr "type" "sfunc") (set_attr "needs_delay_slot" "yes")]) @@ -2994,11 +3012,12 @@ } else if (TARGET_DIVIDE_CALL_FP) { - function_symbol (operands[3], sh_divsi3_libfunc, SFUNC_STATIC); + rtx lab = function_symbol (operands[3], sh_divsi3_libfunc, + SFUNC_STATIC).lab; if (TARGET_FPU_SINGLE) - last = gen_divsi3_i4_single (operands[0], operands[3]); + last = gen_divsi3_i4_single (operands[0], operands[3], lab); else - last = gen_divsi3_i4 (operands[0], operands[3]); + last = gen_divsi3_i4 (operands[0], operands[3], lab); } else if (TARGET_SH2A) { @@ -3113,7 +3132,7 @@ last = ((TARGET_DIVIDE_CALL2 ? gen_divsi3_media_2 : gen_divsi3_i1_media) (operands[0], operands[3])); else if (TARGET_FPU_ANY) - last = gen_divsi3_i4_single (operands[0], operands[3]); + last = gen_divsi3_i4_single (operands[0], operands[3], const0_rtx); else last = gen_divsi3_i1 (operands[0], operands[3]); } @@ -3713,7 +3732,7 @@ label: { /* The address must be set outside the libcall, since it goes into a pseudo. */ - rtx sym = function_symbol (NULL, "__mulsi3", SFUNC_STATIC); + rtx sym = function_symbol (NULL, "__mulsi3", SFUNC_STATIC).sym; rtx addr = force_reg (SImode, sym); rtx insns = gen_mulsi3_call (operands[0], operands[1], operands[2], addr); @@ -4970,8 +4989,8 @@ label: { emit_move_insn (gen_rtx_REG (SImode, R4_REG), operands[1]); rtx funcaddr = gen_reg_rtx (Pmode); - function_symbol (funcaddr, "__ashlsi3_r0", SFUNC_STATIC); - emit_insn (gen_ashlsi3_d_call (operands[0], operands[2], funcaddr)); + rtx lab = function_symbol (funcaddr, "__ashlsi3_r0", SFUNC_STATIC).lab; + emit_insn (gen_ashlsi3_d_call (operands[0], operands[2], funcaddr, lab)); DONE; } @@ -5024,15 +5043,18 @@ label: ;; In order to make combine understand the truncation of the shift amount ;; operand we have to allow it to use pseudo regs for the shift operands. (define_insn "ashlsi3_d_call" - [(set (match_operand:SI 0 "arith_reg_dest" "=z") + [(set (match_operand:SI 0 "arith_reg_dest" "=z,z") (ashift:SI (reg:SI R4_REG) - (and:SI (match_operand:SI 1 "arith_reg_operand" "z") + (and:SI (match_operand:SI 1 "arith_reg_operand" "z,z") (const_int 31)))) - (use (match_operand:SI 2 "arith_reg_operand" "r")) + (use (match_operand:SI 2 "arith_reg_operand" "r,r")) + (use (match_operand 3 "" "Z,Ccl")) (clobber (reg:SI T_REG)) (clobber (reg:SI PR_REG))] "TARGET_SH1 && !TARGET_DYNSHIFT" - "jsr @%2%#" + "@ + jsr @%2%# + bsrf %2\n%O3:%#" [(set_attr "type" "sfunc") (set_attr "needs_delay_slot" "yes")]) @@ -5374,12 +5396,15 @@ label: (define_insn "ashrsi3_n" [(set (reg:SI R4_REG) (ashiftrt:SI (reg:SI R4_REG) - (match_operand:SI 0 "const_int_operand" "i"))) + (match_operand:SI 0 "const_int_operand" "i,i"))) (clobber (reg:SI T_REG)) (clobber (reg:SI PR_REG)) - (use (match_operand:SI 1 "arith_reg_operand" "r"))] + (use (match_operand:SI 1 "arith_reg_operand" "r,r")) + (use (match_operand 2 "" "Z,Ccl"))] "TARGET_SH1" - "jsr @%1%#" + "@ + jsr @%1%# + bsrf %1\n%O2:%#" [(set_attr "type" "sfunc") (set_attr "needs_delay_slot" "yes")]) @@ -5532,8 +5557,8 @@ label: { emit_move_insn (gen_rtx_REG (SImode, R4_REG), operands[1]); rtx funcaddr = gen_reg_rtx (Pmode); - function_symbol (funcaddr, "__lshrsi3_r0", SFUNC_STATIC); - emit_insn (gen_lshrsi3_d_call (operands[0], operands[2], funcaddr)); + rtx lab = function_symbol (funcaddr, "__lshrsi3_r0", SFUNC_STATIC).lab; + emit_insn (gen_lshrsi3_d_call (operands[0], operands[2], funcaddr, lab)); DONE; } }) @@ -5585,15 +5610,18 @@ label: ;; In order to make combine understand the truncation of the shift amount ;; operand we have to allow it to use pseudo regs for the shift operands. (define_insn "lshrsi3_d_call" - [(set (match_operand:SI 0 "arith_reg_dest" "=z") + [(set (match_operand:SI 0 "arith_reg_dest" "=z,z") (lshiftrt:SI (reg:SI R4_REG) - (and:SI (match_operand:SI 1 "arith_reg_operand" "z") + (and:SI (match_operand:SI 1 "arith_reg_operand" "z,z") (const_int 31)))) - (use (match_operand:SI 2 "arith_reg_operand" "r")) + (use (match_operand:SI 2 "arith_reg_operand" "r,r")) + (use (match_operand 3 "" "Z,Ccl")) (clobber (reg:SI T_REG)) (clobber (reg:SI PR_REG))] "TARGET_SH1 && !TARGET_DYNSHIFT" - "jsr @%2%#" + "@ + jsr @%2%# + bsrf %2\n%O3:%#" [(set_attr "type" "sfunc") (set_attr "needs_delay_slot" "yes")]) @@ -7315,7 +7343,7 @@ label: } else if (TARGET_SHCOMPACT) { - operands[1] = function_symbol (NULL, "__ic_invalidate", SFUNC_STATIC); + operands[1] = function_symbol (NULL, "__ic_invalidate", SFUNC_STATIC).sym; operands[1] = force_reg (Pmode, operands[1]); emit_insn (gen_ic_invalidate_line_compact (operands[0], operands[1])); DONE; @@ -7397,7 +7425,7 @@ label: tramp = force_reg (Pmode, operands[0]); sfun = force_reg (Pmode, function_symbol (NULL, "__init_trampoline", - SFUNC_STATIC)); + SFUNC_STATIC).sym); emit_move_insn (gen_rtx_REG (SImode, R2_REG), operands[1]); emit_move_insn (gen_rtx_REG (SImode, R3_REG), operands[2]); @@ -9455,9 +9483,29 @@ label: (match_operand 1 "" "")) (use (reg:SI FPSCR_MODES_REG)) (clobber (reg:SI PR_REG))] - "TARGET_SH1" + "TARGET_SH1 && !TARGET_FDPIC" { - if (TARGET_SH2A && (dbr_sequence_length () == 0)) + if (TARGET_SH2A && dbr_sequence_length () == 0) + return "jsr/n @%0"; + else + return "jsr @%0%#"; +} + [(set_attr "type" "call") + (set (attr "fp_mode") + (if_then_else (eq_attr "fpu_single" "yes") + (const_string "single") (const_string "double"))) + (set_attr "needs_delay_slot" "yes") + (set_attr "fp_set" "unknown")]) + +(define_insn "calli_fdpic" + [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "r")) + (match_operand 1)) + (use (reg:SI FPSCR_MODES_REG)) + (use (reg:SI PIC_REG)) + (clobber (reg:SI PR_REG))] + "TARGET_FDPIC" +{ + if (TARGET_SH2A && dbr_sequence_length () == 0) return "jsr/n @%0"; else return "jsr @%0%#"; @@ -9584,9 +9632,30 @@ label: (match_operand 2 "" ""))) (use (reg:SI FPSCR_MODES_REG)) (clobber (reg:SI PR_REG))] - "TARGET_SH1" + "TARGET_SH1 && !TARGET_FDPIC" +{ + if (TARGET_SH2A && dbr_sequence_length () == 0) + return "jsr/n @%1"; + else + return "jsr @%1%#"; +} + [(set_attr "type" "call") + (set (attr "fp_mode") + (if_then_else (eq_attr "fpu_single" "yes") + (const_string "single") (const_string "double"))) + (set_attr "needs_delay_slot" "yes") + (set_attr "fp_set" "unknown")]) + +(define_insn "call_valuei_fdpic" + [(set (match_operand 0 "" "=rf") + (call (mem:SI (match_operand:SI 1 "arith_reg_operand" "r")) + (match_operand 2))) + (use (reg:SI FPSCR_REG)) + (use (reg:SI PIC_REG)) + (clobber (reg:SI PR_REG))] + "TARGET_FDPIC" { - if (TARGET_SH2A && (dbr_sequence_length () == 0)) + if (TARGET_SH2A && dbr_sequence_length () == 0) return "jsr/n @%1"; else return "jsr @%1%#"; @@ -9721,6 +9790,12 @@ label: (clobber (reg:SI PR_REG))])] "" { + if (TARGET_FDPIC) + { + rtx pic_reg = gen_rtx_REG (Pmode, PIC_REG); + emit_move_insn (pic_reg, sh_get_fdpic_reg_initial_val ()); + } + if (TARGET_SHMEDIA) { operands[0] = shmedia_prepare_call_address (operands[0], 0); @@ -9755,8 +9830,8 @@ label: run out of registers when adjusting fpscr for the call. */ emit_insn (gen_force_mode_for_call ()); - operands[0] - = function_symbol (NULL, "__GCC_shcompact_call_trampoline", SFUNC_GOT); + operands[0] = function_symbol (NULL, "__GCC_shcompact_call_trampoline", + SFUNC_GOT).sym; operands[0] = force_reg (SImode, operands[0]); emit_move_insn (r0, func); @@ -9804,7 +9879,13 @@ label: operands[1] = operands[2]; } - emit_call_insn (gen_calli (operands[0], operands[1])); + if (TARGET_FDPIC) + { + operands[0] = sh_load_function_descriptor (operands[0]); + emit_call_insn (gen_calli_fdpic (operands[0], operands[1])); + } + else + emit_call_insn (gen_calli (operands[0], operands[1])); DONE; }) @@ -9884,7 +9965,7 @@ label: emit_insn (gen_force_mode_for_call ()); operands[0] = function_symbol (NULL, "__GCC_shcompact_call_trampoline", - SFUNC_GOT); + SFUNC_GOT).sym; operands[0] = force_reg (SImode, operands[0]); emit_move_insn (r0, func); @@ -9909,6 +9990,12 @@ label: (clobber (reg:SI PR_REG))])] "" { + if (TARGET_FDPIC) + { + rtx pic_reg = gen_rtx_REG (Pmode, PIC_REG); + emit_move_insn (pic_reg, sh_get_fdpic_reg_initial_val ()); + } + if (TARGET_SHMEDIA) { operands[1] = shmedia_prepare_call_address (operands[1], 0); @@ -9944,8 +10031,8 @@ label: run out of registers when adjusting fpscr for the call. */ emit_insn (gen_force_mode_for_call ()); - operands[1] - = function_symbol (NULL, "__GCC_shcompact_call_trampoline", SFUNC_GOT); + operands[1] = function_symbol (NULL, "__GCC_shcompact_call_trampoline", + SFUNC_GOT).sym; operands[1] = force_reg (SImode, operands[1]); emit_move_insn (r0, func); @@ -9993,7 +10080,14 @@ label: else operands[1] = force_reg (SImode, XEXP (operands[1], 0)); - emit_call_insn (gen_call_valuei (operands[0], operands[1], operands[2])); + if (TARGET_FDPIC) + { + operands[1] = sh_load_function_descriptor (operands[1]); + emit_call_insn (gen_call_valuei_fdpic (operands[0], operands[1], + operands[2])); + } + else + emit_call_insn (gen_call_valuei (operands[0], operands[1], operands[2])); DONE; }) @@ -10002,7 +10096,21 @@ label: (match_operand 1 "" "")) (use (reg:SI FPSCR_MODES_REG)) (return)] - "TARGET_SH1" + "TARGET_SH1 && !TARGET_FDPIC" + "jmp @%0%#" + [(set_attr "needs_delay_slot" "yes") + (set (attr "fp_mode") + (if_then_else (eq_attr "fpu_single" "yes") + (const_string "single") (const_string "double"))) + (set_attr "type" "jump_ind")]) + +(define_insn "sibcalli_fdpic" + [(call (mem:SI (match_operand:SI 0 "register_operand" "k")) + (match_operand 1)) + (use (reg:SI FPSCR_MODES_REG)) + (use (reg:SI PIC_REG)) + (return)] + "TARGET_FDPIC" "jmp @%0%#" [(set_attr "needs_delay_slot" "yes") (set (attr "fp_mode") @@ -10016,7 +10124,25 @@ label: (use (match_operand 2 "" "")) (use (reg:SI FPSCR_MODES_REG)) (return)] - "TARGET_SH2" + "TARGET_SH2 && !TARGET_FDPIC" +{ + return "braf %0" "\n" + "%O2:%#"; +} + [(set_attr "needs_delay_slot" "yes") + (set (attr "fp_mode") + (if_then_else (eq_attr "fpu_single" "yes") + (const_string "single") (const_string "double"))) + (set_attr "type" "jump_ind")]) + +(define_insn "sibcalli_pcrel_fdpic" + [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "k")) + (match_operand 1)) + (use (match_operand 2)) + (use (reg:SI FPSCR_MODES_REG)) + (use (reg:SI PIC_REG)) + (return)] + "TARGET_SH2 && TARGET_FDPIC" { return "braf %0" "\n" "%O2:%#"; @@ -10049,7 +10175,7 @@ label: (use (reg:SI FPSCR_MODES_REG)) (clobber (match_scratch:SI 2 "=&k")) (return)] - "TARGET_SH2" + "TARGET_SH2 && !TARGET_FDPIC" "#" "reload_completed" [(const_int 0)] @@ -10069,6 +10195,32 @@ label: (const_string "single") (const_string "double"))) (set_attr "type" "jump_ind")]) +(define_insn_and_split "sibcall_pcrel_fdpic" + [(call (mem:SI (match_operand:SI 0 "symbol_ref_operand")) + (match_operand 1)) + (use (reg:SI FPSCR_MODES_REG)) + (use (reg:SI PIC_REG)) + (clobber (match_scratch:SI 2 "=k")) + (return)] + "TARGET_SH2 && TARGET_FDPIC" + "#" + "&& reload_completed" + [(const_int 0)] +{ + rtx lab = PATTERN (gen_call_site ()); + + sh_expand_sym_label2reg (operands[2], operands[0], lab, true); + rtx i = emit_call_insn (gen_sibcalli_pcrel_fdpic (operands[2], operands[1], + copy_rtx (lab))); + SIBLING_CALL_P (i) = 1; + DONE; +} + [(set_attr "needs_delay_slot" "yes") + (set (attr "fp_mode") + (if_then_else (eq_attr "fpu_single" "yes") + (const_string "single") (const_string "double"))) + (set_attr "type" "jump_ind")]) + (define_insn "sibcall_compact" [(call (mem:SI (match_operand:SI 0 "register_operand" "k,k")) (match_operand 1 "" "")) @@ -10113,6 +10265,12 @@ label: (return)])] "" { + if (TARGET_FDPIC) + { + rtx pic_reg = gen_rtx_REG (Pmode, PIC_REG); + emit_move_insn (pic_reg, sh_get_fdpic_reg_initial_val ()); + } + if (TARGET_SHMEDIA) { operands[0] = shmedia_prepare_call_address (operands[0], 1); @@ -10157,8 +10315,8 @@ label: run out of registers when adjusting fpscr for the call. */ emit_insn (gen_force_mode_for_call ()); - operands[0] - = function_symbol (NULL, "__GCC_shcompact_call_trampoline", SFUNC_GOT); + operands[0] = function_symbol (NULL, "__GCC_shcompact_call_trampoline", + SFUNC_GOT).sym; operands[0] = force_reg (SImode, operands[0]); /* We don't need a return trampoline, since the callee will @@ -10192,13 +10350,23 @@ label: static functions. */ && SYMBOL_REF_LOCAL_P (XEXP (operands[0], 0))) { - emit_call_insn (gen_sibcall_pcrel (XEXP (operands[0], 0), operands[1])); + if (TARGET_FDPIC) + emit_call_insn (gen_sibcall_pcrel_fdpic (XEXP (operands[0], 0), + operands[1])); + else + emit_call_insn (gen_sibcall_pcrel (XEXP (operands[0], 0), operands[1])); DONE; } else operands[0] = force_reg (SImode, XEXP (operands[0], 0)); - emit_call_insn (gen_sibcalli (operands[0], operands[1])); + if (TARGET_FDPIC) + { + operands[0] = sh_load_function_descriptor (operands[0]); + emit_call_insn (gen_sibcalli_fdpic (operands[0], operands[1])); + } + else + emit_call_insn (gen_sibcalli (operands[0], operands[1])); DONE; }) @@ -10208,7 +10376,22 @@ label: (match_operand 2 "" ""))) (use (reg:SI FPSCR_MODES_REG)) (return)] - "TARGET_SH1" + "TARGET_SH1 && !TARGET_FDPIC" + "jmp @%1%#" + [(set_attr "needs_delay_slot" "yes") + (set (attr "fp_mode") + (if_then_else (eq_attr "fpu_single" "yes") + (const_string "single") (const_string "double"))) + (set_attr "type" "jump_ind")]) + +(define_insn "sibcall_valuei_fdpic" + [(set (match_operand 0 "" "=rf") + (call (mem:SI (match_operand:SI 1 "register_operand" "k")) + (match_operand 2))) + (use (reg:SI FPSCR_MODES_REG)) + (use (reg:SI PIC_REG)) + (return)] + "TARGET_FDPIC" "jmp @%1%#" [(set_attr "needs_delay_slot" "yes") (set (attr "fp_mode") @@ -10223,7 +10406,26 @@ label: (use (match_operand 3 "" "")) (use (reg:SI FPSCR_MODES_REG)) (return)] - "TARGET_SH2" + "TARGET_SH2 && !TARGET_FDPIC" +{ + return "braf %1" "\n" + "%O3:%#"; +} + [(set_attr "needs_delay_slot" "yes") + (set (attr "fp_mode") + (if_then_else (eq_attr "fpu_single" "yes") + (const_string "single") (const_string "double"))) + (set_attr "type" "jump_ind")]) + +(define_insn "sibcall_valuei_pcrel_fdpic" + [(set (match_operand 0 "" "=rf") + (call (mem:SI (match_operand:SI 1 "arith_reg_operand" "k")) + (match_operand 2))) + (use (match_operand 3)) + (use (reg:SI FPSCR_MODES_REG)) + (use (reg:SI PIC_REG)) + (return)] + "TARGET_SH2 && TARGET_FDPIC" { return "braf %1" "\n" "%O3:%#"; @@ -10241,7 +10443,7 @@ label: (use (reg:SI FPSCR_MODES_REG)) (clobber (match_scratch:SI 3 "=&k")) (return)] - "TARGET_SH2" + "TARGET_SH2 && !TARGET_FDPIC" "#" "reload_completed" [(const_int 0)] @@ -10263,6 +10465,35 @@ label: (const_string "single") (const_string "double"))) (set_attr "type" "jump_ind")]) +(define_insn_and_split "sibcall_value_pcrel_fdpic" + [(set (match_operand 0 "" "=rf") + (call (mem:SI (match_operand:SI 1 "symbol_ref_operand")) + (match_operand 2))) + (use (reg:SI FPSCR_MODES_REG)) + (use (reg:SI PIC_REG)) + (clobber (match_scratch:SI 3 "=k")) + (return)] + "TARGET_SH2 && TARGET_FDPIC" + "#" + "&& reload_completed" + [(const_int 0)] +{ + rtx lab = PATTERN (gen_call_site ()); + + sh_expand_sym_label2reg (operands[3], operands[1], lab, true); + rtx i = emit_call_insn (gen_sibcall_valuei_pcrel_fdpic (operands[0], + operands[3], + operands[2], + copy_rtx (lab))); + SIBLING_CALL_P (i) = 1; + DONE; +} + [(set_attr "needs_delay_slot" "yes") + (set (attr "fp_mode") + (if_then_else (eq_attr "fpu_single" "yes") + (const_string "single") (const_string "double"))) + (set_attr "type" "jump_ind")]) + (define_insn "sibcall_value_compact" [(set (match_operand 0 "" "=rf,rf") (call (mem:SI (match_operand:SI 1 "register_operand" "k,k")) @@ -10310,6 +10541,12 @@ label: (return)])] "" { + if (TARGET_FDPIC) + { + rtx pic_reg = gen_rtx_REG (Pmode, PIC_REG); + emit_move_insn (pic_reg, sh_get_fdpic_reg_initial_val ()); + } + if (TARGET_SHMEDIA) { operands[1] = shmedia_prepare_call_address (operands[1], 1); @@ -10355,8 +10592,8 @@ label: run out of registers when adjusting fpscr for the call. */ emit_insn (gen_force_mode_for_call ()); - operands[1] - = function_symbol (NULL, "__GCC_shcompact_call_trampoline", SFUNC_GOT); + operands[1] = function_symbol (NULL, "__GCC_shcompact_call_trampoline", + SFUNC_GOT).sym; operands[1] = force_reg (SImode, operands[1]); /* We don't need a return trampoline, since the callee will @@ -10391,15 +10628,27 @@ label: static functions. */ && SYMBOL_REF_LOCAL_P (XEXP (operands[1], 0))) { - emit_call_insn (gen_sibcall_value_pcrel (operands[0], - XEXP (operands[1], 0), - operands[2])); + if (TARGET_FDPIC) + emit_call_insn (gen_sibcall_value_pcrel_fdpic (operands[0], + XEXP (operands[1], 0), + operands[2])); + else + emit_call_insn (gen_sibcall_value_pcrel (operands[0], + XEXP (operands[1], 0), + operands[2])); DONE; } else operands[1] = force_reg (SImode, XEXP (operands[1], 0)); - emit_call_insn (gen_sibcall_valuei (operands[0], operands[1], operands[2])); + if (TARGET_FDPIC) + { + operands[1] = sh_load_function_descriptor (operands[1]); + emit_call_insn (gen_sibcall_valuei_fdpic (operands[0], operands[1], + operands[2])); + } + else + emit_call_insn (gen_sibcall_valuei (operands[0], operands[1], operands[2])); DONE; }) @@ -10483,7 +10732,7 @@ label: emit_insn (gen_force_mode_for_call ()); operands[1] = function_symbol (NULL, "__GCC_shcompact_call_trampoline", - SFUNC_GOT); + SFUNC_GOT).sym; operands[1] = force_reg (SImode, operands[1]); emit_move_insn (r0, func); @@ -10681,6 +10930,13 @@ label: DONE; } + if (TARGET_FDPIC) + { + rtx pic_reg = gen_rtx_REG (Pmode, PIC_REG); + emit_move_insn (pic_reg, sh_get_fdpic_reg_initial_val ()); + DONE; + } + operands[1] = gen_rtx_REG (Pmode, PIC_REG); operands[2] = gen_rtx_SYMBOL_REF (VOIDmode, GOT_SYMBOL_NAME); @@ -10816,6 +11072,9 @@ label: rtx mem; bool stack_chk_guard_p = false; + rtx picreg = TARGET_FDPIC ? sh_get_fdpic_reg_initial_val () + : gen_rtx_REG (Pmode, PIC_REG); + operands[2] = !can_create_pseudo_p () ? operands[0] : gen_reg_rtx (Pmode); operands[3] = !can_create_pseudo_p () ? operands[0] : gen_reg_rtx (Pmode); @@ -10858,8 +11117,7 @@ label: if (stack_chk_guard_p) emit_insn (gen_chk_guard_add (operands[3], operands[2])); else - emit_move_insn (operands[3], gen_rtx_PLUS (Pmode, operands[2], - gen_rtx_REG (Pmode, PIC_REG))); + emit_move_insn (operands[3], gen_rtx_PLUS (Pmode, operands[2], picreg)); /* N.B. This is not constant for a GOTPLT relocation. */ mem = gen_rtx_MEM (Pmode, operands[3]); @@ -10890,6 +11148,23 @@ label: DONE; }) +(define_expand "sym2GOTFUNCDESC" + [(const (unspec [(match_operand 0)] UNSPEC_GOTFUNCDESC))] + "TARGET_FDPIC") + +(define_expand "symGOTFUNCDESC2reg" + [(match_operand 0) (match_operand 1)] + "TARGET_FDPIC" +{ + rtx gotsym = gen_sym2GOTFUNCDESC (operands[1]); + PUT_MODE (gotsym, Pmode); + rtx insn = emit_insn (gen_symGOT_load (operands[0], gotsym)); + + MEM_READONLY_P (SET_SRC (PATTERN (insn))) = 1; + + DONE; +}) + (define_expand "symGOTPLT2reg" [(match_operand 0 "" "") (match_operand 1 "" "")] "" @@ -10916,18 +11191,39 @@ label: ? operands[0] : gen_reg_rtx (GET_MODE (operands[0]))); + rtx picreg = TARGET_FDPIC ? sh_get_fdpic_reg_initial_val () + : gen_rtx_REG (Pmode, PIC_REG); + gotoffsym = gen_sym2GOTOFF (operands[1]); PUT_MODE (gotoffsym, Pmode); emit_move_insn (t, gotoffsym); - insn = emit_move_insn (operands[0], - gen_rtx_PLUS (Pmode, t, - gen_rtx_REG (Pmode, PIC_REG))); + insn = emit_move_insn (operands[0], gen_rtx_PLUS (Pmode, t, picreg)); set_unique_reg_note (insn, REG_EQUAL, operands[1]); DONE; }) +(define_expand "sym2GOTOFFFUNCDESC" + [(const (unspec [(match_operand 0)] UNSPEC_GOTOFFFUNCDESC))] + "TARGET_FDPIC") + +(define_expand "symGOTOFFFUNCDESC2reg" + [(match_operand 0) (match_operand 1)] + "TARGET_FDPIC" +{ + rtx picreg = sh_get_fdpic_reg_initial_val (); + rtx t = !can_create_pseudo_p () + ? operands[0] + : gen_reg_rtx (GET_MODE (operands[0])); + + rtx gotoffsym = gen_sym2GOTOFFFUNCDESC (operands[1]); + PUT_MODE (gotoffsym, Pmode); + emit_move_insn (t, gotoffsym); + emit_move_insn (operands[0], gen_rtx_PLUS (Pmode, t, picreg)); + DONE; +}) + (define_expand "symPLT_label2reg" [(set (match_operand:SI 0 "" "") (const:SI @@ -12678,18 +12974,22 @@ label: (define_insn "block_move_real" [(parallel [(set (mem:BLK (reg:SI R4_REG)) (mem:BLK (reg:SI R5_REG))) - (use (match_operand:SI 0 "arith_reg_operand" "r")) + (use (match_operand:SI 0 "arith_reg_operand" "r,r")) + (use (match_operand 1 "" "Z,Ccl")) (clobber (reg:SI PR_REG)) (clobber (reg:SI R0_REG))])] "TARGET_SH1 && ! TARGET_HARD_SH4" - "jsr @%0%#" + "@ + jsr @%0%# + bsrf %0\n%O1:%#" [(set_attr "type" "sfunc") (set_attr "needs_delay_slot" "yes")]) (define_insn "block_lump_real" [(parallel [(set (mem:BLK (reg:SI R4_REG)) (mem:BLK (reg:SI R5_REG))) - (use (match_operand:SI 0 "arith_reg_operand" "r")) + (use (match_operand:SI 0 "arith_reg_operand" "r,r")) + (use (match_operand 1 "" "Z,Ccl")) (use (reg:SI R6_REG)) (clobber (reg:SI PR_REG)) (clobber (reg:SI T_REG)) @@ -12698,27 +12998,33 @@ label: (clobber (reg:SI R6_REG)) (clobber (reg:SI R0_REG))])] "TARGET_SH1 && ! TARGET_HARD_SH4" - "jsr @%0%#" + "@ + jsr @%0%# + bsrf %0\n%O1:%#" [(set_attr "type" "sfunc") (set_attr "needs_delay_slot" "yes")]) (define_insn "block_move_real_i4" [(parallel [(set (mem:BLK (reg:SI R4_REG)) (mem:BLK (reg:SI R5_REG))) - (use (match_operand:SI 0 "arith_reg_operand" "r")) + (use (match_operand:SI 0 "arith_reg_operand" "r,r")) + (use (match_operand 1 "" "Z,Ccl")) (clobber (reg:SI PR_REG)) (clobber (reg:SI R0_REG)) (clobber (reg:SI R1_REG)) (clobber (reg:SI R2_REG))])] "TARGET_HARD_SH4" - "jsr @%0%#" + "@ + jsr @%0%# + bsrf %0\n%O1:%#" [(set_attr "type" "sfunc") (set_attr "needs_delay_slot" "yes")]) (define_insn "block_lump_real_i4" [(parallel [(set (mem:BLK (reg:SI R4_REG)) (mem:BLK (reg:SI R5_REG))) - (use (match_operand:SI 0 "arith_reg_operand" "r")) + (use (match_operand:SI 0 "arith_reg_operand" "r,r")) + (use (match_operand 1 "" "Z,Ccl")) (use (reg:SI R6_REG)) (clobber (reg:SI PR_REG)) (clobber (reg:SI T_REG)) @@ -12730,7 +13036,9 @@ label: (clobber (reg:SI R2_REG)) (clobber (reg:SI R3_REG))])] "TARGET_HARD_SH4" - "jsr @%0%#" + "@ + jsr @%0%# + bsrf %0\n%O1:%#" [(set_attr "type" "sfunc") (set_attr "needs_delay_slot" "yes")]) |