diff options
author | Alexandre Oliva <aoliva@redhat.com> | 2004-05-02 04:57:47 +0000 |
---|---|---|
committer | Alexandre Oliva <aoliva@gcc.gnu.org> | 2004-05-02 04:57:47 +0000 |
commit | 764678d17d7e22a3b5d087b3f3e1d9a518df9a22 (patch) | |
tree | 1d04e1233f03f836fa8708f2a315b1ba2834a01c /gcc/config/frv/frv.md | |
parent | afbe7e61febc8df565418161787af714550c8244 (diff) | |
download | gcc-764678d17d7e22a3b5d087b3f3e1d9a518df9a22.zip gcc-764678d17d7e22a3b5d087b3f3e1d9a518df9a22.tar.gz gcc-764678d17d7e22a3b5d087b3f3e1d9a518df9a22.tar.bz2 |
frv-protos.h (frv_expand_epilogue, [...]): Add bool argument.
* config/frv/frv-protos.h (frv_expand_epilogue,
frv_expand_fdpic_call): Add bool argument.
* config/frv/frv.c (frv_function_ok_for_sibcall): New.
(TARGET_FUNCTION_OK_FOR_SIBCALL): Define to it.
(frv_expand_epilogue): Use new argument to decide whether to emit
return instruction or copy the return address to LR.
(frv_expand_fdpic_call): Inline PLT entry when emitting direct
sibcalls.
(sibcall_operand): New.
* config/frv/frv.h (PREDICATE_CODES): call_operand doesn't match
PLUS nor LABEL_REF. Add sibcall_operand.
* config/frv/frv.md (call, call_value): Pass false to
frv_expand_fdpic_call.
(call_fdpicdi, call_value_fdpicdi): Insert %i0 in calll.
(sibcall, sibcall_internal, sibcall_fdpicdi, sibcall_value,
sibcall_value_internal, sibcall_value_fdpicdi): New.
(return_unsigned_true, return_unsigned_false): New.
(epilogue): Adjust call to frv_expand_epilogue.
(sibcall_epilogue): New.
From-SVN: r81405
Diffstat (limited to 'gcc/config/frv/frv.md')
-rw-r--r-- | gcc/config/frv/frv.md | 145 |
1 files changed, 139 insertions, 6 deletions
diff --git a/gcc/config/frv/frv.md b/gcc/config/frv/frv.md index 20170bd..36b6d8e 100644 --- a/gcc/config/frv/frv.md +++ b/gcc/config/frv/frv.md @@ -5260,7 +5260,7 @@ operands[2] = const0_rtx; if (TARGET_FDPIC) - frv_expand_fdpic_call (operands, 0); + frv_expand_fdpic_call (operands, false, false); else emit_call_insn (gen_call_internal (addr, operands[1], operands[2], lr)); @@ -5308,7 +5308,7 @@ (match_operand 1 "" "")) (clobber (match_operand:SI 2 "lr_operand" "=l"))] "TARGET_FDPIC" - "calll %M0" + "call%i0l %M0" [(set_attr "length" "4") (set_attr "type" "jumpl")]) @@ -5325,6 +5325,65 @@ [(set_attr "length" "4") (set_attr "type" "call,jumpl")]) +(define_expand "sibcall" + [(use (match_operand:QI 0 "" "")) + (use (match_operand 1 "" "")) + (use (match_operand 2 "" "")) + (use (match_operand 3 "" ""))] + "" + " +{ + rtx addr; + + if (GET_CODE (operands[0]) != MEM) + abort (); + + addr = XEXP (operands[0], 0); + if (! sibcall_operand (addr, Pmode)) + addr = force_reg (Pmode, addr); + + if (! operands[2]) + operands[2] = const0_rtx; + + if (TARGET_FDPIC) + frv_expand_fdpic_call (operands, false, true); + else + emit_call_insn (gen_sibcall_internal (addr, operands[1], operands[2])); + + DONE; +}") + +;; It might seem that these sibcall patterns are missing references to +;; LR, but they're not necessary because sibcall_epilogue will make +;; sure LR is restored, and having LR here will set +;; regs_ever_used[REG_LR], forcing it to be saved on the stack, and +;; then restored in sibcalls and regular return code paths, even if +;; the function becomes a leaf function after tail-call elimination. + +;; We must not use a call-saved register here. `W' limits ourselves +;; to gr14 or gr15, but since we're almost running out of constraint +;; letters, and most other call-clobbered registers are often used for +;; argument-passing, this will do. +(define_insn "sibcall_internal" + [(call (mem:QI (match_operand:SI 0 "sibcall_operand" "WNOP")) + (match_operand 1 "" "")) + (use (match_operand 2 "" "")) + (return)] + "! TARGET_FDPIC" + "jmp%i0l %M0" + [(set_attr "length" "4") + (set_attr "type" "jumpl")]) + +(define_insn "sibcall_fdpicdi" + [(call (mem:QI (match_operand:DI 0 "fdpic_fptr_operand" "W")) + (match_operand 1 "" "")) + (return)] + "TARGET_FDPIC" + "jmp%i0l %M0" + [(set_attr "length" "4") + (set_attr "type" "jumpl")]) + + ;; Subroutine call instruction returning a value. Operand 0 is the hard ;; register in which the value is returned. There are three more operands, the ;; same as the three operands of the `call' instruction (but with numbers @@ -5355,7 +5414,7 @@ operands[3] = const0_rtx; if (TARGET_FDPIC) - frv_expand_fdpic_call (operands, 1); + frv_expand_fdpic_call (operands, true, false); else emit_call_insn (gen_call_value_internal (operands[0], addr, operands[2], operands[3], lr)); @@ -5382,7 +5441,7 @@ (match_operand 2 "" ""))) (clobber (match_operand:SI 3 "lr_operand" "=l"))] "TARGET_FDPIC" - "calll %M1" + "call%i1l %M1" [(set_attr "length" "4") (set_attr "type" "jumpl")]) @@ -5400,6 +5459,56 @@ [(set_attr "length" "4") (set_attr "type" "call,jumpl")]) +(define_expand "sibcall_value" + [(use (match_operand 0 "" "")) + (use (match_operand:QI 1 "" "")) + (use (match_operand 2 "" "")) + (use (match_operand 3 "" "")) + (use (match_operand 4 "" ""))] + "" + " +{ + rtx addr; + + if (GET_CODE (operands[1]) != MEM) + abort (); + + addr = XEXP (operands[1], 0); + if (! sibcall_operand (addr, Pmode)) + addr = force_reg (Pmode, addr); + + if (! operands[3]) + operands[3] = const0_rtx; + + if (TARGET_FDPIC) + frv_expand_fdpic_call (operands, true, true); + else + emit_call_insn (gen_sibcall_value_internal (operands[0], addr, operands[2], + operands[3])); + DONE; +}") + +(define_insn "sibcall_value_internal" + [(set (match_operand 0 "register_operand" "=d") + (call (mem:QI (match_operand:SI 1 "sibcall_operand" "WNOP")) + (match_operand 2 "" ""))) + (use (match_operand 3 "" "")) + (return)] + "! TARGET_FDPIC" + "jmp%i1l %M1" + [(set_attr "length" "4") + (set_attr "type" "jumpl")]) + +(define_insn "sibcall_value_fdpicdi" + [(set (match_operand 0 "register_operand" "=d") + (call (mem:QI (match_operand:DI 1 "fdpic_fptr_operand" "W")) + (match_operand 2 "" ""))) + (return)] + "TARGET_FDPIC" + "jmp%i1l %M1" + [(set_attr "length" "4") + (set_attr "type" "jumpl")]) + ;; return instruction generated instead of jmp to epilog (define_expand "return" [(parallel [(return) @@ -5430,6 +5539,30 @@ [(set_attr "length" "4") (set_attr "type" "jump,jumpl")]) +(define_insn "*return_unsigned_true" + [(set (pc) + (if_then_else (match_operator:CC_UNS 0 "unsigned_relational_operator" + [(match_operand 1 "icc_operand" "t") + (const_int 0)]) + (return) + (pc)))] + "direct_return_p ()" + "b%c0lr %1,%#" + [(set_attr "length" "4") + (set_attr "type" "jump")]) + +(define_insn "*return_unsigned_false" + [(set (pc) + (if_then_else (match_operator:CC_UNS 0 "unsigned_relational_operator" + [(match_operand 1 "icc_operand" "t") + (const_int 0)]) + (pc) + (return)))] + "direct_return_p ()" + "b%C0lr %1,%#" + [(set_attr "length" "4") + (set_attr "type" "jump")]) + ;; A version of addsi3 for deallocating stack space at the end of the ;; epilogue. The addition is done in parallel with an (unspec_volatile), ;; which represents the clobbering of the deallocated space. @@ -5634,7 +5767,7 @@ "" " { - frv_expand_epilogue (FALSE); + frv_expand_epilogue (true); DONE; }") @@ -5650,7 +5783,7 @@ "" " { - frv_expand_epilogue (TRUE); + frv_expand_epilogue (false); DONE; }") |