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
This commit is contained in:
parent
9a566c0926
commit
a45f333130
@ -1,3 +1,12 @@
|
||||
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>
|
||||
|
||||
* config/arm/lib1funcs.asm: Test for __ELF__ not __elf__.
|
||||
|
@ -1349,7 +1349,9 @@ i960_function_prologue (file, size)
|
||||
|
||||
for (i = 0; i < FIRST_PSEUDO_REGISTER; 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;
|
||||
/* Count global registers that need saving. */
|
||||
|
@ -528,7 +528,7 @@ extern int target_flags;
|
||||
g0..g3 are used for return values,
|
||||
g0..g7 may always be used for parameters,
|
||||
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,
|
||||
g14 is the leaf return ptr or the arg block ptr otherwise zero,
|
||||
must be reset to zero before returning if it was used,
|
||||
@ -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
|
||||
fixed) in the definition of INITIAL_FRAME_POINTER_OFFSET which would have
|
||||
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
|
||||
and the stack pointer values immediately after the function prologue.
|
||||
@ -622,8 +627,9 @@ extern int hard_regno_mode_ok ();
|
||||
#define ARG_POINTER_REGNUM 14
|
||||
|
||||
/* Register in which static-chain is passed to a function.
|
||||
On i960, we use r3. */
|
||||
#define STATIC_CHAIN_REGNUM 19
|
||||
On i960, we use g12. We can't use any local register, because we need
|
||||
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
|
||||
to place the wanted value at in g13. */
|
||||
@ -1543,14 +1549,14 @@ extern struct rtx_def *gen_compare_reg ();
|
||||
|
||||
/* On the i960, the trampoline contains three instructions:
|
||||
ldconst _function, r4
|
||||
ldconst static addr, r3
|
||||
ldconst static addr, g12
|
||||
jump (r4) */
|
||||
|
||||
#define TRAMPOLINE_TEMPLATE(FILE) \
|
||||
{ \
|
||||
ASM_OUTPUT_INT (FILE, GEN_INT (0x8C203000)); \
|
||||
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 (0x84212000)); \
|
||||
}
|
||||
|
@ -2308,57 +2308,45 @@
|
||||
""
|
||||
"
|
||||
{
|
||||
rtx fp = operands[1];
|
||||
rtx new_pc = operands[3];
|
||||
rtx chain = operands[0];
|
||||
rtx handler = operands[1];
|
||||
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. */
|
||||
rtx label = operands[3];
|
||||
|
||||
/* 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 ());
|
||||
|
||||
/* 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
|
||||
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). */
|
||||
|
||||
emit_move_insn (gen_rtx (MEM, SImode,
|
||||
plus_constant (fp, 8)),
|
||||
new_pc);
|
||||
plus_constant (hard_frame_pointer_rtx, -56)),
|
||||
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). */
|
||||
|
||||
/* Next, we put stack into the saved $sp value in the frame. */
|
||||
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
|
||||
we want fp to be. */
|
||||
|
||||
emit_move_insn (gen_rtx (REG, SImode, 16), fp);
|
||||
plus_constant (hard_frame_pointer_rtx, -60)),
|
||||
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
|
||||
above into all the right registers, and also, all the local
|
||||
|
Loading…
Reference in New Issue
Block a user