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,
/* ??? 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.
#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. */
/* 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)); \
}
""
"
{
- 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);
-
-#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
+ plus_constant (hard_frame_pointer_rtx, -56)),
+ replace_rtx (copy_rtx (handler), virtual_stack_vars_rtx,
+ hard_frame_pointer_rtx));
- /* 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);
+ /* Next, we put stack into the saved $sp value in the frame. */
+ emit_move_insn (gen_rtx (MEM, SImode,
+ 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