Commit a45f3331 by Jim Wilson Committed by Jim Wilson

Patch to make nested functions and non-local gotos work.

	* i960/i960.c (i960_function_prologue): Don't save static chain
	pointer.
	* i960/i960.h (STACK_CHAIN_REGNUM): Change from r3 to g12.
	(TRAMPOLINE_TEMPLATE): Likewise.
	(FRAME_POINTER_REQUIRED): Check current_function_has_nonlocal_goto.
	* i960/i960.md (nonlocal_goto): Rewrite.

From-SVN: r26282
parent 9a566c09
Wed Apr 7 22:40:19 1999 Jim Wilson <wilson@cygnus.com>
* i960/i960.c (i960_function_prologue): Don't save static chain
pointer.
* i960/i960.h (STACK_CHAIN_REGNUM): Change from r3 to g12.
(TRAMPOLINE_TEMPLATE): Likewise.
(FRAME_POINTER_REQUIRED): Check current_function_has_nonlocal_goto.
* i960/i960.md (nonlocal_goto): Rewrite.
Tue Apr 6 17:49:49 1999 Philip Blundell <pb@nexus.co.uk> Tue Apr 6 17:49:49 1999 Philip Blundell <pb@nexus.co.uk>
* config/arm/lib1funcs.asm: Test for __ELF__ not __elf__. * config/arm/lib1funcs.asm: Test for __ELF__ not __elf__.
......
...@@ -1349,7 +1349,9 @@ i960_function_prologue (file, size) ...@@ -1349,7 +1349,9 @@ i960_function_prologue (file, size)
for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
if (regs_ever_live[i] if (regs_ever_live[i]
&& ((! call_used_regs[i]) || (i > 7 && i < 12))) && ((! call_used_regs[i]) || (i > 7 && i < 12))
/* No need to save the static chain pointer. */
&& ! (i == STATIC_CHAIN_REGNUM && current_function_needs_context))
{ {
regs[i] = -1; regs[i] = -1;
/* Count global registers that need saving. */ /* Count global registers that need saving. */
......
...@@ -528,7 +528,7 @@ extern int target_flags; ...@@ -528,7 +528,7 @@ extern int target_flags;
g0..g3 are used for return values, g0..g3 are used for return values,
g0..g7 may always be used for parameters, g0..g7 may always be used for parameters,
g8..g11 may be used for parameters, but are preserved if they aren't, g8..g11 may be used for parameters, but are preserved if they aren't,
g12 is always preserved, but otherwise unused, g12 is the static chain if needed, otherwise is preserved
g13 is the struct return ptr if used, or temp, but may be trashed, g13 is the struct return ptr if used, or temp, but may be trashed,
g14 is the leaf return ptr or the arg block ptr otherwise zero, g14 is the leaf return ptr or the arg block ptr otherwise zero,
must be reset to zero before returning if it was used, must be reset to zero before returning if it was used,
...@@ -606,7 +606,12 @@ extern int hard_regno_mode_ok (); ...@@ -606,7 +606,12 @@ extern int hard_regno_mode_ok ();
/* ??? It isn't clear to me why this is here. Perhaps because of a bug (since /* ??? It isn't clear to me why this is here. Perhaps because of a bug (since
fixed) in the definition of INITIAL_FRAME_POINTER_OFFSET which would have fixed) in the definition of INITIAL_FRAME_POINTER_OFFSET which would have
caused this to fail. */ caused this to fail. */
#define FRAME_POINTER_REQUIRED (! leaf_function_p ()) /* ??? Must check current_function_has_nonlocal_goto, otherwise frame pointer
elimination messes up nonlocal goto sequences. I think this works for other
targets because they use indirect jumps for the return which disables fp
elimination. */
#define FRAME_POINTER_REQUIRED \
(! leaf_function_p () || current_function_has_nonlocal_goto)
/* C statement to store the difference between the frame pointer /* C statement to store the difference between the frame pointer
and the stack pointer values immediately after the function prologue. and the stack pointer values immediately after the function prologue.
...@@ -622,8 +627,9 @@ extern int hard_regno_mode_ok (); ...@@ -622,8 +627,9 @@ extern int hard_regno_mode_ok ();
#define ARG_POINTER_REGNUM 14 #define ARG_POINTER_REGNUM 14
/* Register in which static-chain is passed to a function. /* Register in which static-chain is passed to a function.
On i960, we use r3. */ On i960, we use g12. We can't use any local register, because we need
#define STATIC_CHAIN_REGNUM 19 a register that can be set before a call or before a jump. */
#define STATIC_CHAIN_REGNUM 12
/* Functions which return large structures get the address /* Functions which return large structures get the address
to place the wanted value at in g13. */ to place the wanted value at in g13. */
...@@ -1543,14 +1549,14 @@ extern struct rtx_def *gen_compare_reg (); ...@@ -1543,14 +1549,14 @@ extern struct rtx_def *gen_compare_reg ();
/* On the i960, the trampoline contains three instructions: /* On the i960, the trampoline contains three instructions:
ldconst _function, r4 ldconst _function, r4
ldconst static addr, r3 ldconst static addr, g12
jump (r4) */ jump (r4) */
#define TRAMPOLINE_TEMPLATE(FILE) \ #define TRAMPOLINE_TEMPLATE(FILE) \
{ \ { \
ASM_OUTPUT_INT (FILE, GEN_INT (0x8C203000)); \ ASM_OUTPUT_INT (FILE, GEN_INT (0x8C203000)); \
ASM_OUTPUT_INT (FILE, GEN_INT (0x00000000)); \ ASM_OUTPUT_INT (FILE, GEN_INT (0x00000000)); \
ASM_OUTPUT_INT (FILE, GEN_INT (0x8C183000)); \ ASM_OUTPUT_INT (FILE, GEN_INT (0x8CE03000)); \
ASM_OUTPUT_INT (FILE, GEN_INT (0x00000000)); \ ASM_OUTPUT_INT (FILE, GEN_INT (0x00000000)); \
ASM_OUTPUT_INT (FILE, GEN_INT (0x84212000)); \ ASM_OUTPUT_INT (FILE, GEN_INT (0x84212000)); \
} }
......
...@@ -2308,57 +2308,45 @@ ...@@ -2308,57 +2308,45 @@
"" ""
" "
{ {
rtx fp = operands[1]; rtx chain = operands[0];
rtx new_pc = operands[3]; rtx handler = operands[1];
rtx stack = operands[2]; rtx stack = operands[2];
rtx val = operands[0]; rtx label = operands[3];
/* 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 /* We must restore the stack pointer, frame pointer, previous frame
pointer and the return instruction pointer. Since the ret pointer and the return instruction pointer. Since the ret
instruction does all this for us with one instruction, we arrange instruction does all this for us with one instruction, we arrange
everything so that ret will do everything we need done. */ 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 /* First, we must flush the register windows, so that we can modify
the saved local registers on the stack directly and because we the saved local registers on the stack directly and because we
are going to change the previous frame pointer. */ are going to change the previous frame pointer. */
emit_insn (gen_flush_register_windows ()); emit_insn (gen_flush_register_windows ());
/* Load the static chain value for the containing fn into fp. This is needed
because STACK refers to fp. */
emit_move_insn (hard_frame_pointer_rtx, chain);
/* Now move the adjusted value into the pfp register for the following return
instruction. */
emit_move_insn (gen_rtx (REG, SImode, 16),
plus_constant (hard_frame_pointer_rtx, -64));
/* Next, we put the address that we want to transfer to, into the /* 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 saved $rip value in the frame. Once we ret below, that value
will be loaded into the pc (IP). */ will be loaded into the pc (IP). */
emit_move_insn (gen_rtx (MEM, SImode, emit_move_insn (gen_rtx (MEM, SImode,
plus_constant (fp, 8)), plus_constant (hard_frame_pointer_rtx, -56)),
new_pc); replace_rtx (copy_rtx (handler), virtual_stack_vars_rtx,
hard_frame_pointer_rtx));
#if 0
/* 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);
#endif
/* We now load pfp (the previous frame pointer) with the value that /* Next, we put stack into the saved $sp value in the frame. */
we want fp to be. */ emit_move_insn (gen_rtx (MEM, SImode,
plus_constant (hard_frame_pointer_rtx, -60)),
emit_move_insn (gen_rtx (REG, SImode, 16), fp); replace_rtx (copy_rtx (stack), virtual_stack_vars_rtx,
hard_frame_pointer_rtx));
/* And finally, we can now just ret to get all the values saved /* And finally, we can now just ret to get all the values saved
above into all the right registers, and also, all the local above into all the right registers, and also, all the local
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment