* improved i960 builtin setjmp/longjmp handling
@ 1998-04-23 18:49 Mike Stump
1998-04-23 23:53 ` Richard Henderson
0 siblings, 1 reply; 2+ messages in thread
From: Mike Stump @ 1998-04-23 18:49 UTC (permalink / raw)
To: kenner; +Cc: egcs
builtin setjmp/long jump don't work on the i960. The patch below
makes them work. nonlocal gotos in nested functions I also don't
think work very well on the i960. The below doesn't fix that problem.
I tested these by using setjmp/longjmp based exception handling, and
running all the eh*.C tests out of the g++ testsuite. They all work
to the limits of my i960 board (out of memory on two of the tests,
unrelated OS conflicts on the other).
1998-04-23 Mike Stump <mrs@wrs.com>
* expr.c (expand_builtin_setjmp): Add support to use the
hard_frame_pointer_rtx instead of virtual_stack_vars_rtx for
machines that require it.
* i960.h (SETUP_FRAME_ADDRESSES): Define.
(NEED_HARD_FRAME_FOR_NONLOCAL_GOTO): Define.
* i960.md (ret): Define support routine for nonlocal_goto.
(nonlocal_goto): Define. Doesn't yet support nested function
nonlocal gotos.
(flush_register_windows): Define.
Doing diffs in expr.c.~1~:
*** expr.c.~1~ Fri Apr 17 16:14:36 1998
--- expr.c Thu Apr 23 15:21:24 1998
*************** expand_builtin_setjmp (buf_addr, target,
*** 7689,7699 ****
emit_queue ();
! /* 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);
emit_move_insn (validize_mem
(gen_rtx_MEM (Pmode,
plus_constant (buf_addr,
--- 7689,7709 ----
emit_queue ();
! #if defined (HAVE_nonlocal_goto) && defined (NEED_HARD_FRAME_FOR_NONLOCAL_GOTO)
! if (HAVE_nonlocal_goto && NEED_HARD_FRAME_FOR_NONLOCAL_GOTO)
! /* 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),
! hard_frame_pointer_rtx);
! else
! #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);
!
emit_move_insn (validize_mem
(gen_rtx_MEM (Pmode,
plus_constant (buf_addr,
--------------
Doing diffs in config/i960/i960.h.~1~:
*** config/i960/i960.h.~1~ Wed Apr 1 10:58:27 1998
--- config/i960/i960.h Thu Apr 23 15:16:34 1998
*************** extern struct rtx_def *gen_compare_reg (
*** 1496,1501 ****
--- 1496,1508 ----
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 NEED_HARD_FRAME_FOR_NONLOCAL_GOTO 1
+
#if 0
/* Promote char and short arguments to ints, when want compatibility with
the iC960 compilers. */
--------------
Doing diffs in config/i960/i960.md.~1~:
*** config/i960/i960.md.~1~ Fri Apr 10 14:05:52 1998
--- config/i960/i960.md Thu Apr 23 15:16:34 1998
***************
*** 2287,2292 ****
--- 2287,2381 ----
"* 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)]
""
--------------
^ permalink raw reply [flat|nested] 2+ messages in thread
* Re: improved i960 builtin setjmp/longjmp handling
1998-04-23 18:49 improved i960 builtin setjmp/longjmp handling Mike Stump
@ 1998-04-23 23:53 ` Richard Henderson
0 siblings, 0 replies; 2+ messages in thread
From: Richard Henderson @ 1998-04-23 23:53 UTC (permalink / raw)
To: Mike Stump; +Cc: kenner, egcs
> ! #if defined (HAVE_nonlocal_goto) && defined (NEED_HARD_FRAME_FOR_NONLOCAL_GOTO)
> ! if (HAVE_nonlocal_goto && NEED_HARD_FRAME_FOR_NONLOCAL_GOTO)
> ! /* 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),
> ! hard_frame_pointer_rtx);
> ! else
> ! #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);
> !
I would suggest one of two alternate courses:
(1) Define builtin_setjmp_setup to store the hard frame pointer, either
on top of the v_s_v_rtx, or in unused slots 4 or 5.
(2) Define a macro that is an expression that evaluates to an rtx to
use, and default that macro to v_s_v_rtx. The i960 header can then
define it to h_f_p_rtx directly.
r~
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~1998-04-23 23:53 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
1998-04-23 18:49 improved i960 builtin setjmp/longjmp handling Mike Stump
1998-04-23 23:53 ` Richard Henderson
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).