public inbox for gcc@gcc.gnu.org
 help / color / mirror / Atom feed
* 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).