diff options
author | rth <rth@138bc75d-0d04-0410-961f-82ee72b054a4> | 1998-02-02 19:28:57 +0000 |
---|---|---|
committer | rth <rth@138bc75d-0d04-0410-961f-82ee72b054a4> | 1998-02-02 19:28:57 +0000 |
commit | 0d179e03a9188621b28d235fa4f836af619e20c2 (patch) | |
tree | 6fde390bee19acf841e5ec6c02e403d195086099 /gcc/config/mips/mips.md | |
parent | 0722b5c976b8844f5121fbfb820c517d24d50ab2 (diff) | |
download | gcc-0d179e03a9188621b28d235fa4f836af619e20c2.tar.gz |
* expr.c (expand_builtin_setjmp): Accept two new arguments for
the labels to branch to on first and subsequent executions. Don't
play with __dummy. Rename `setjmp' insn to `builtin_setjmp_setup',
and provide it with the jmp_buf. Use only one of
`builtin_setjmp_receiver' or `nonlocal_goto_receiver',
and provide the former with the target label.
(expand_builtin) [BUILTIN_SETJMP]: Generate a label for use by setjmp.
(expand_builtin) [BUILTIN_LONGJMP]: Split out to ...
(expand_builtin_longjmp): ... here. Recognize a `builtin_longjmp'
insn to replace all of the normal nonlocal_goto code. Don't play
with __dummy. Correct arguments to nonlocal_goto.
* expr.h (expand_builtin_setjmp): Update prototype.
* except.c (start_dynamic_handler): When using builtin_setjmp,
generate more accurate flow information.
* alpha.md (nonlocal_goto_receiver_osf): Delete.
(nonlocal_goto_receiver_vms): Rename to nonlocal_goto_receiver.
(builtin_longjmp, builtin_setjmp_receiver): New.
* sparc.md (update_return): Disambiguate unspec number.
(nonlocal_goto): Rearrange arguments to match caller in except.c.
(builtin_setjmp_setup): Rename from setjmp. Match and ignore the
jmp_buf operand.
* mips.md (nonlocal_goto_receiver, builtin_setjmp_receiver): Remove.
(builtin_setjmp_setup*, builtin_longjmp): New.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@17602 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/config/mips/mips.md')
-rw-r--r-- | gcc/config/mips/mips.md | 73 |
1 files changed, 51 insertions, 22 deletions
diff --git a/gcc/config/mips/mips.md b/gcc/config/mips/mips.md index eaf80efacb9..10c0bfe261b 100644 --- a/gcc/config/mips/mips.md +++ b/gcc/config/mips/mips.md @@ -8820,35 +8820,64 @@ move\\t%0,%z4\\n\\ (set_attr "mode" "none") (set_attr "length" "6")]) -;; ??? This is a hack to work around a problem with expand_builtin_setjmp. -;; It restores the frame pointer, and then does a call to restore the global -;; pointer (gp) register. The call insn implicitly (via the assembler) reloads -;; gp from the stack. However, call insns do not depend on $fp, so it is -;; possible for the instruction scheduler to move the fp restore after the -;; call, which then causes gp to be corrupted. We fix this by emitting a -;; scheduler barrier. A better fix is to put code here that restores the -;; $gp, and then the call is unnecessary. This is only a problem when PIC -;; (TARGET_ABICALLS), and only when the gp register is caller-saved -;; (irix5/o32, but not irix6/n32/n64). - -(define_expand "nonlocal_goto_receiver" - [(const_int 0)] - "" +;; For o32/n32/n64, we save the gp in the jmp_buf as well. While it is +;; possible to either pull it off the stack (in the o32 case) or recalculate +;; it given t9 and our target label, it takes 3 or 4 insns to do so, and +;; this is easy. + +(define_expand "builtin_setjmp_setup" + [(unspec [(match_operand 0 "register_operand" "r")] 20)] + "TARGET_ABICALLS" " { - emit_insn (gen_blockage ()); + if (TARGET_LONG64) + emit_insn (gen_builtin_setjmp_setup_64 (operands[0])); + else + emit_insn (gen_builtin_setjmp_setup_32 (operands[0])); + DONE; }") -;; For n32/n64, we need to restore gp after a builtin setjmp. We do this -;; by making use of the fact that we've just called __dummy. +(define_expand "builtin_setjmp_setup_32" + [(set (mem:SI (plus:SI (match_operand:SI 0 "register_operand" "r") + (const_int 12))) + (reg:SI 28))] + "TARGET_ABICALLS && ! TARGET_LONG64" + "") -(define_expand "builtin_setjmp_receiver" - [(const_int 0)] - "TARGET_ABICALLS && mips_abi != ABI_32" +(define_expand "builtin_setjmp_setup_64" + [(set (mem:DI (plus:DI (match_operand:DI 0 "register_operand" "r") + (const_int 24))) + (reg:DI 28))] + "TARGET_ABICALLS && TARGET_LONG64" + "") + +;; For o32/n32/n64, we need to arrange for longjmp to put the +;; target address in t9 so that we can use it for loading $gp. + +(define_expand "builtin_longjmp" + [(unspec_volatile [(match_operand 0 "register_operand" "r")] 3)] + "TARGET_ABICALLS" " { - emit_insn (gen_loadgp (gen_rtx (SYMBOL_REF, Pmode, \"__dummy\"))); - emit_insn (gen_blockage ()); + /* The elements of the buffer are, in order: */ + int W = (TARGET_LONG64 ? 8 : 4); + rtx fp = gen_rtx_MEM (Pmode, operands[0]); + rtx lab = gen_rtx_MEM (Pmode, plus_constant (operands[0], 1*W)); + rtx stack = gen_rtx_MEM (Pmode, plus_constant (operands[0], 2*W)); + rtx gpv = gen_rtx_MEM (Pmode, plus_constant (operands[0], 3*W)); + rtx pv = gen_rtx_REG (Pmode, 25); + rtx gp = gen_rtx_REG (Pmode, 28); + + /* This bit is the same as expand_builtin_longjmp. */ + emit_move_insn (hard_frame_pointer_rtx, fp); + emit_move_insn (pv, lab); + emit_stack_restore (SAVE_NONLOCAL, stack, NULL_RTX); + emit_move_insn (gp, gpv); + emit_insn (gen_rtx_USE (VOIDmode, hard_frame_pointer_rtx)); + emit_insn (gen_rtx_USE (VOIDmode, stack_pointer_rtx)); + emit_insn (gen_rtx_USE (VOIDmode, gp)); + emit_indirect_jump (pv); + DONE; }") ;; |