aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorMike Stump <mrs@wrs.com>1998-06-02 20:11:21 +0000
committerJeff Law <law@gcc.gnu.org>1998-06-02 14:11:21 -0600
commit0bc02db4e61cfc1ab8e408d88f7a2e09f8b1cef0 (patch)
tree149e177d352af6c612cef699a23f5ac907ea20ec /gcc
parent666e0f5ad52098975ed535bc3f3a128aa5c8bf51 (diff)
downloadgcc-0bc02db4e61cfc1ab8e408d88f7a2e09f8b1cef0.zip
gcc-0bc02db4e61cfc1ab8e408d88f7a2e09f8b1cef0.tar.gz
gcc-0bc02db4e61cfc1ab8e408d88f7a2e09f8b1cef0.tar.bz2
expr.c (expand_builtin_setjmp): Handle BUILTIN_SETJMP_FRAME_VALUE.
* 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. From-SVN: r20192
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog9
-rw-r--r--gcc/config/i960/i960.h7
-rw-r--r--gcc/config/i960/i960.md89
-rw-r--r--gcc/expr.c6
-rw-r--r--gcc/tm.texi14
5 files changed, 121 insertions, 4 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 2766e29..5e58c0f 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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
diff --git a/gcc/config/i960/i960.h b/gcc/config/i960/i960.h
index 1ba3dcc..4102c0f 100644
--- a/gcc/config/i960/i960.h
+++ b/gcc/config/i960/i960.h
@@ -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. */
diff --git a/gcc/config/i960/i960.md b/gcc/config/i960/i960.md
index a4aae0f..c99c6c1 100644
--- a/gcc/config/i960/i960.md
+++ b/gcc/config/i960/i960.md
@@ -2287,6 +2287,95 @@
"* 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)]
""
diff --git a/gcc/expr.c b/gcc/expr.c
index b8b1ab8..f6b5216 100644
--- a/gcc/expr.c
+++ b/gcc/expr.c
@@ -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,
diff --git a/gcc/tm.texi b/gcc/tm.texi
index 0968754..b03e791 100644
--- a/gcc/tm.texi
+++ b/gcc/tm.texi
@@ -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})