summaryrefslogtreecommitdiff
path: root/gcc/config/mips/mips.md
diff options
context:
space:
mode:
authorrth <rth@138bc75d-0d04-0410-961f-82ee72b054a4>1998-02-02 19:28:57 +0000
committerrth <rth@138bc75d-0d04-0410-961f-82ee72b054a4>1998-02-02 19:28:57 +0000
commit0d179e03a9188621b28d235fa4f836af619e20c2 (patch)
tree6fde390bee19acf841e5ec6c02e403d195086099 /gcc/config/mips/mips.md
parent0722b5c976b8844f5121fbfb820c517d24d50ab2 (diff)
downloadgcc-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.md73
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;
}")
;;