- actual_fsize);
}
+/* Fetch the return address for the frame COUNT steps up from
+ the current frame, after the prologue. FRAMEADDR is the
+ frame pointer of the COUNT frame.
+
+ We want to ignore any export stub remnants here. */
+
+rtx
+return_addr_rtx (count, frameaddr)
+ int count;
+ rtx frameaddr;
+{
+ rtx label;
+ rtx saved_rp;
+ rtx ins;
+
+ saved_rp = gen_reg_rtx (Pmode);
+
+ /* First, we start off with the normal return address pointer from
+ -20[frameaddr]. */
+
+ emit_move_insn (saved_rp, plus_constant (frameaddr, -5 * UNITS_PER_WORD));
+
+ /* Get pointer to the instruction stream. We have to mask out the
+ privilege level from the two low order bits of the return address
+ pointer here so that ins will point to the start of the first
+ instruction that would have been executed if we returned. */
+ ins = copy_to_reg (gen_rtx (AND, Pmode,
+ copy_to_reg (gen_rtx (MEM, Pmode, saved_rp)),
+ MASK_RETURN_ADDR));
+ label = gen_label_rtx ();
+
+ /* Check the instruction stream at the normal return address for the
+ export stub:
+
+ 0x4bc23fd1 | stub+8: ldw -18(sr0,sp),rp
+ 0x004010a1 | stub+12: ldsid (sr0,rp),r1
+ 0x00011820 | stub+16: mtsp r1,sr0
+ 0xe0400002 | stub+20: be,n 0(sr0,rp)
+
+ If it is an export stub, than our return address is really in
+ -24[frameaddr]. */
+
+ emit_cmp_insn (gen_rtx (MEM, SImode, ins),
+ GEN_INT (0x4bc23fd1),
+ NE, NULL_RTX, SImode, 1, 0);
+ emit_jump_insn (gen_bne (label));
+
+ emit_cmp_insn (gen_rtx (MEM, SImode, plus_constant (ins, 4)),
+ GEN_INT (0x004010a1),
+ NE, NULL_RTX, SImode, 1, 0);
+ emit_jump_insn (gen_bne (label));
+
+ emit_cmp_insn (gen_rtx (MEM, SImode, plus_constant (ins, 8)),
+ GEN_INT (0x00011820),
+ NE, NULL_RTX, SImode, 1, 0);
+ emit_jump_insn (gen_bne (label));
+
+ emit_cmp_insn (gen_rtx (MEM, SImode, plus_constant (ins, 12)),
+ GEN_INT (0xe0400002),
+ NE, NULL_RTX, SImode, 1, 0);
+
+ /* If there is no export stub then just use our initial guess of
+ -20[frameaddr]. */
+
+ emit_jump_insn (gen_bne (label));
+
+ /* Here we know that our return address pointer points to an export
+ stub. We don't want to return the address of the export stub,
+ but rather the return address that leads back into user code.
+ That return address is stored at -24[frameaddr]. */
+
+ emit_move_insn (saved_rp, plus_constant (frameaddr, -6 * UNITS_PER_WORD));
+
+ emit_label (label);
+ return gen_rtx (MEM, Pmode, memory_address (Pmode, saved_rp));
+}
+
/* This is only valid once reload has completed because it depends on
knowing exactly how much (if any) frame there is and...
extern struct rtx_def *gen_cmp_fp ();
extern void hppa_encode_label ();
+/* Declare functions defined in pa.c and used in templates. */
+
+extern struct rtx_def *return_addr_rtx ();
+
/* We want __gcc_plt_call to appear in every program built by
gcc, so we make a reference to it out of __main.
We use the asm statement to fool the optimizer into not
(*p++) (); \
} while (0)
-/* The current return address is in [%sp-20]. */
-#define RETURN_ADDR_RTX(COUNT, FRAME) \
- ((COUNT == 0) \
- ? gen_rtx (MEM, Pmode, \
- memory_address (Pmode, plus_constant (FRAME, \
- -5 * UNITS_PER_WORD))) \
- : (rtx) 0)
+/* Find the return address associated with the frame given by
+ FRAMEADDR. */
+#define RETURN_ADDR_RTX(COUNT, FRAMEADDR) \
+ (return_addr_rtx (COUNT, FRAMEADDR))
/* Used to mask out junk bits from the return address, such as
processor state, interrupt status, condition codes and the like. */
-#define MASK_RETURN_ADDR \
- /* The priviledge level is in the two low order bits, mask em out \
+#define MASK_RETURN_ADDR \
+ /* The privilege level is in the two low order bits, mask em out \
of the return address. */ \
(GEN_INT (0xfffffffc))