pa.md (interspace_jump): New pattern.
authorJohn David Anglin <dave@hiauly1.hia.nrc.ca>
Sun, 29 Aug 1999 11:04:24 +0000 (11:04 +0000)
committerJeff Law <law@gcc.gnu.org>
Sun, 29 Aug 1999 11:04:24 +0000 (05:04 -0600)
        * pa.md (interspace_jump): New pattern.
        (builtin_longjmp): New expander.

From-SVN: r28964

gcc/ChangeLog
gcc/config/pa/pa.md

index c43a6bba3f05b01531cbf30962f85aac921858a4..1ecc178009a5d7ed420dc2f2b164636b28b8a63d 100644 (file)
@@ -1,3 +1,8 @@
+Sun Aug 29 05:01:17 1999  John David Anglin <dave@hiauly1.hia.nrc.ca>
+
+       * pa.md (interspace_jump): New pattern.
+       (builtin_longjmp): New expander.
+
 1999-08-29  Bernd Schmidt  <bernds@cygnus.co.uk>
 
        * fp-bit.c (add, sub, multiply, divide, compare, _eq_f2, _ne_f2,
index 8b22dc098568385171553e0b486d499fdf9af99a..f28d191564382b539b8726dd38523a2e8ab78015 100644 (file)
   [(set_attr "type" "branch")
    (set_attr "length" "4")])
 
+;;; EH does longjmp's from and within the data section.  Thus,
+;;; an interspace branch is required for the longjmp implementation.
+;;; Registers r1 and r2 are not saved in the jmpbuf environment.
+;;; Thus, they can be used as scratch registers for the jump.
+(define_insn "interspace_jump"
+  [(set (pc) (match_operand:SI 0 "register_operand" "a"))
+  (clobber (reg:SI 2))]
+  ""
+  "ldsid (%%sr0,%0),%%r2\; mtsp %%r2,%%sr0\; be%* 0(%%sr0,%0)"
+   [(set_attr "type" "branch")
+    (set_attr "length" "12")])
+
+(define_expand "builtin_longjmp"
+  [(unspec_volatile [(match_operand 0 "register_operand" "r")] 3)]
+  ""
+  "
+{
+  /* The elements of the buffer are, in order:  */
+  rtx fp = gen_rtx_MEM (Pmode, operands[0]);
+  rtx lab = gen_rtx_MEM (Pmode, plus_constant (operands[0], 4));
+  rtx stack = gen_rtx_MEM (Pmode, plus_constant (operands[0], 8));
+  rtx pv = gen_rtx_REG (Pmode, 1);
+
+  /* This bit is the same as expand_builtin_longjmp.  */
+  emit_move_insn (hard_frame_pointer_rtx, fp);
+  emit_stack_restore (SAVE_NONLOCAL, stack, NULL_RTX);
+  emit_insn (gen_rtx_USE (VOIDmode, hard_frame_pointer_rtx));
+  emit_insn (gen_rtx_USE (VOIDmode, stack_pointer_rtx));
+
+  /* Load the label we are jumping through into r1 so that we know
+     where to look for it when we get back to setjmp's function for
+     restoring the gp.  */
+  emit_move_insn (pv, lab);
+  emit_jump_insn (gen_interspace_jump (pv));
+  emit_barrier ();
+  DONE;
+}")
+
 (define_insn "extzv"
   [(set (match_operand:SI 0 "register_operand" "=r")
        (zero_extract:SI (match_operand:SI 1 "register_operand" "r")