pa.h (RETURN_ADDR_RTX): Fix to ignore export stubs.
authorMike Stump <mrs@gcc.gnu.org>
Fri, 7 Feb 1997 21:01:43 +0000 (21:01 +0000)
committerMike Stump <mrs@gcc.gnu.org>
Fri, 7 Feb 1997 21:01:43 +0000 (21:01 +0000)
* pa.h (RETURN_ADDR_RTX): Fix to ignore export stubs.
* pa.c (return_addr_rtx): Define.

From-SVN: r13621

gcc/config/pa/pa.c
gcc/config/pa/pa.h

index bab4a12fb7f8e264a272d6465d87f526bde67226..1d9100498cc207061b20edae9629a799f2272414 100644 (file)
@@ -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...
 
index 0755df08862a760c25726b7d26f34ade91761d74..e6995b353be064e2bcc80f3e460703d4fc4e8762 100644 (file)
@@ -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))