aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorMike Stump <mrs@gcc.gnu.org>1997-02-07 21:01:43 +0000
committerMike Stump <mrs@gcc.gnu.org>1997-02-07 21:01:43 +0000
commite99d6592219f26c6cd2c06daf7884bef466ff034 (patch)
treed7b993e292b76d4082c52518b49aafc1d1efa236 /gcc
parent3bcf86ebf5cbf743c0110f5af7533d7e0af281e0 (diff)
downloadgcc-e99d6592219f26c6cd2c06daf7884bef466ff034.zip
gcc-e99d6592219f26c6cd2c06daf7884bef466ff034.tar.gz
gcc-e99d6592219f26c6cd2c06daf7884bef466ff034.tar.bz2
pa.h (RETURN_ADDR_RTX): Fix to ignore export stubs.
* pa.h (RETURN_ADDR_RTX): Fix to ignore export stubs. * pa.c (return_addr_rtx): Define. From-SVN: r13621
Diffstat (limited to 'gcc')
-rw-r--r--gcc/config/pa/pa.c77
-rw-r--r--gcc/config/pa/pa.h19
2 files changed, 87 insertions, 9 deletions
diff --git a/gcc/config/pa/pa.c b/gcc/config/pa/pa.c
index bab4a12..1d91004 100644
--- a/gcc/config/pa/pa.c
+++ b/gcc/config/pa/pa.c
@@ -3034,6 +3034,83 @@ hppa_expand_epilogue ()
- 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...
diff --git a/gcc/config/pa/pa.h b/gcc/config/pa/pa.h
index 0755df0..e6995b3 100644
--- a/gcc/config/pa/pa.h
+++ b/gcc/config/pa/pa.h
@@ -2357,6 +2357,10 @@ extern struct rtx_def *legitimize_pic_address ();
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
@@ -2373,17 +2377,14 @@ do { \
(*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))