OSDN Git Service

* expr.c (expand_builtin_setjmp): Handle BUILTIN_SETJMP_FRAME_VALUE.
authorlaw <law@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 2 Jun 1998 20:11:21 +0000 (20:11 +0000)
committerlaw <law@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 2 Jun 1998 20:11:21 +0000 (20:11 +0000)
        * i960.h (SETUP_FRAME_ADDRESSES, BUILTIN_SETJMP_FRAME_VALUE): Define.
        * i960.md (ret, flush_register_windows): Define.
        (nonlocal_goto): Likewise.  Nested function nonlocal gotos don't
        work yet.
        * tm.texi (BUILTIN_SETJMP_FRAME_VALUE): Document new macro.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@20192 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/config/i960/i960.h
gcc/config/i960/i960.md
gcc/expr.c
gcc/tm.texi

index 2766e29..5e58c0f 100644 (file)
@@ -1,3 +1,12 @@
+1998-06-02  Mike Stump  <mrs@wrs.com>
+
+       * expr.c (expand_builtin_setjmp): Handle BUILTIN_SETJMP_FRAME_VALUE.
+       * i960.h (SETUP_FRAME_ADDRESSES, BUILTIN_SETJMP_FRAME_VALUE): Define.
+       * i960.md (ret, flush_register_windows): Define.
+       (nonlocal_goto): Likewise.  Nested function nonlocal gotos don't
+       work yet.
+       * tm.texi (BUILTIN_SETJMP_FRAME_VALUE): Document new macro.
+
 Tue Jun  2 14:02:38 1998  Richard Henderson  <rth@cygnus.com>
 
        * alpha.md (divsi3, udivsi3, modsi3, umodsi3): Enable, and work
index 1ba3dcc..4102c0f 100644 (file)
@@ -1495,6 +1495,13 @@ extern struct rtx_def *gen_compare_reg ();
                  CXT);                                                 \
 }
 
+/* Generate RTL to flush the register windows so as to make arbitrary frames
+   available.  */
+#define SETUP_FRAME_ADDRESSES()                \
+  emit_insn (gen_flush_register_windows ())
+
+#define BUILTIN_SETJMP_FRAME_VALUE hard_frame_pointer_rtx
+
 #if 0
 /* Promote char and short arguments to ints, when want compatibility with
    the iC960 compilers.  */
index a4aae0f..c99c6c1 100644 (file)
   "* return i960_output_ret_insn (insn);"
   [(set_attr "type" "branch")])
 
+;; A return instruction.  Used only by nonlocal_goto to change the
+;; stack pointer, frame pointer, previous frame pointer and the return
+;; instruction pointer.
+(define_insn "ret"
+  [(use (reg:SI 16))
+   (unspec_volatile [(const_int 0)] 3)]
+  ""
+  "ret"
+  [(set_attr "type" "branch")
+   (set_attr "length" "1")])
+
+(define_expand "nonlocal_goto"
+  [(match_operand:SI 0 "" "")
+   (match_operand:SI 1 "general_operand" "")
+   (match_operand:SI 2 "general_operand" "")
+   (match_operand:SI 3 "general_operand" "")]
+  ""
+  "
+{
+  rtx fp = operands[1];
+  rtx new_pc = operands[3];
+  rtx stack = operands[2];
+  rtx val = operands[0];
+
+  /* This code isn't sufficient to make nonlocal_gotos for nested
+     functions to work fully.  Here we assume that the passed frame
+     pointer is a real hard frame pointer, not a
+     virtual_stack_vars_rtx type of frame.  */
+
+  /* We must restore the stack pointer, frame pointer, previous frame
+     pointer and the return instruction pointer.  Since the ret
+     instruction does all this for us with one instruction, we arrange
+     everything so that ret will do everything we need done.  */
+
+  if (GET_CODE (fp) != REG)
+    fp = force_reg (Pmode, fp);
+  if (GET_CODE (val) != REG)
+    val = force_reg (Pmode, val);
+  if (GET_CODE (new_pc) != REG)
+    new_pc = force_reg (Pmode, new_pc);
+
+
+  /* First, we must flush the register windows, so that we can modify
+     the saved local registers on the stack directly and because we
+     are going to change the previous frame pointer.  */
+
+  emit_insn (gen_flush_register_windows ());
+
+  /* Next, we put the address that we want to transfer to, into the
+     saved $rip value on the stack.  Once we ret below, that value
+     will be loaded into the pc (IP).  */
+
+  emit_move_insn (gen_rtx (MEM, SImode,
+                          plus_constant (fp, 8)),
+                 new_pc);
+
+  /* Next, we put the value into the static chain register's save
+     area on the stack.  After the ret below, this will be loaded into
+     r3 (the static chain).  */
+     
+  emit_move_insn (gen_rtx (MEM, SImode,
+                          plus_constant (fp, 12)),
+                 val);
+
+  /* We now load pfp (the previous frame pointer) with the value that
+     we want fp to be.  */
+
+  emit_move_insn (gen_rtx (REG, SImode, 16), fp);
+
+  /* And finally, we can now just ret to get all the values saved
+     above into all the right registers, and also, all the local
+     register that were in use in the function, are restored from
+     their saved values (from the call instruction) on the stack
+     because we are very careful to ret from the exact save area in
+     use during the original call.  */
+
+  emit_insn (gen_ret ());
+  emit_barrier ();
+  DONE;
+}")
+
+;; Special insn to flush register windows.
+(define_insn "flush_register_windows"
+  [(unspec_volatile [(const_int 0)] 1)]
+  ""
+  "flushreg"
+  [(set_attr "type" "misc")
+   (set_attr "length" "1")])
+
 (define_insn "nop"
   [(const_int 0)]
   ""
index b8b1ab8..f6b5216 100644 (file)
@@ -7725,11 +7725,15 @@ expand_builtin_setjmp (buf_addr, target, first_label, next_label)
 
   emit_queue ();
 
+#ifndef BUILTIN_SETJMP_FRAME_VALUE
+#define BUILTIN_SETJMP_FRAME_VALUE virtual_stack_vars_rtx
+#endif
+
   /* We store the frame pointer and the address of lab1 in the buffer
      and use the rest of it for the stack save area, which is
      machine-dependent.  */
   emit_move_insn (gen_rtx_MEM (Pmode, buf_addr),
-                 virtual_stack_vars_rtx);
+                 BUILTIN_SETJMP_FRAME_VALUE);
   emit_move_insn (validize_mem
                  (gen_rtx_MEM (Pmode,
                                plus_constant (buf_addr,
index 0968754..b03e791 100644 (file)
@@ -2188,12 +2188,20 @@ of @var{frameaddr}---that is, the stack frame address is also the
 address of the stack word that points to the previous frame.
 
 @findex SETUP_FRAME_ADDRESSES
-@item SETUP_FRAME_ADDRESSES ()
+@item SETUP_FRAME_ADDRESSES
 If defined, a C expression that produces the machine-specific code to
 setup the stack so that arbitrary frames can be accessed.  For example,
 on the Sparc, we must flush all of the register windows to the stack
-before we can access arbitrary stack frames.
-This macro will seldom need to be defined.
+before we can access arbitrary stack frames.  You will seldom need to
+define this macro.
+
+@findex BUILTIN_SETJMP_FRAME_VALUE
+@item BUILTIN_SETJMP_FRAME_VALUE
+If defined, a C expression that contains an rtx that is used to store
+the address of the current frame into the built in @code{setjmp} buffer.
+The default value, @code{virtual_stack_vars_rtx}, is correct for most
+machines.  One reason you may need to define this macro is if
+@code{hard_frame_pointer_rtx} is the appropriate value on your machine.
 
 @findex RETURN_ADDR_RTX
 @item RETURN_ADDR_RTX (@var{count}, @var{frameaddr})