From: Mike Stump Date: Tue, 2 Jun 1998 20:11:21 +0000 (+0000) Subject: expr.c (expand_builtin_setjmp): Handle BUILTIN_SETJMP_FRAME_VALUE. X-Git-Tag: prereleases/egcs-1.1-prerelease~965 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=0bc02db4e61cfc1ab8e408d88f7a2e09f8b1cef0;p=thirdparty%2Fgcc.git 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 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 2766e29d7d68..5e58c0f4f705 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,12 @@ +1998-06-02 Mike Stump + + * 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 * alpha.md (divsi3, udivsi3, modsi3, umodsi3): Enable, and work diff --git a/gcc/config/i960/i960.h b/gcc/config/i960/i960.h index 1ba3dcc79f0d..4102c0ff2791 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 a4aae0f252a5..c99c6c1fdc9b 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 b8b1ab80c509..f6b52163e988 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 0968754821a6..b03e79100f0d 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})