From: Mike Stump Date: Fri, 7 Feb 1997 21:01:43 +0000 (+0000) Subject: pa.h (RETURN_ADDR_RTX): Fix to ignore export stubs. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=e99d6592219f26c6cd2c06daf7884bef466ff034;p=gcc.git 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 --- diff --git a/gcc/config/pa/pa.c b/gcc/config/pa/pa.c index bab4a12fb7f..1d9100498cc 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 0755df08862..e6995b353be 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))