diff options
author | Richard Henderson <rth@redhat.com> | 2001-05-19 17:35:24 -0700 |
---|---|---|
committer | Mark Mitchell <mmitchel@gcc.gnu.org> | 2001-05-20 00:35:24 +0000 |
commit | 9e800206badd2be563d344e4a0aee83e3ac96f03 (patch) | |
tree | acfb4573f234684042fcc91f25abdf25bb73a6f5 /gcc/config | |
parent | 878de307d62595211f10a0a88a9551215c14c898 (diff) | |
download | gcc-9e800206badd2be563d344e4a0aee83e3ac96f03.zip gcc-9e800206badd2be563d344e4a0aee83e3ac96f03.tar.gz gcc-9e800206badd2be563d344e4a0aee83e3ac96f03.tar.bz2 |
except.c (dw2_build_landing_pads): Use word_mode, not Pmode, as ncessary.
* except.c (dw2_build_landing_pads): Use word_mode, not Pmode,
as ncessary.
(expand_eh_return): Convert between word_mode and Pmode.
* unwind-dw2.c (extract_cie_info): Do not assume words and pointers
are the same size.
(execute_stack_op): Likewise.
(execute_cfa_program): Likewise.
(uw_frame_state_for): Likewise.
(uw_update_context_1): Likewise.
* unwind.inc (_Unwind_Reason_Code): Likewise.
* config/mips/mips.h (EH_RETURN_DATA_REGNO): Define.
(EH_RETURN_STACKADJ_RTX): Likewise.
* config/mips/mips.c (compute_frame_size): Make space for saving
EH return registers.
(mips_expand_epilogue): Handle EH stack adjustments.
* config/mips/mips.md (eh_return): New pattern.
(eh_set_lr_si): Likewise.
(eh_set_lr_di): Likewise.
Add splitter to perform EH return after reload.
From-SVN: r42332
Diffstat (limited to 'gcc/config')
-rw-r--r-- | gcc/config/mips/mips.c | 40 | ||||
-rw-r--r-- | gcc/config/mips/mips.h | 4 | ||||
-rw-r--r-- | gcc/config/mips/mips.md | 87 |
3 files changed, 125 insertions, 6 deletions
diff --git a/gcc/config/mips/mips.c b/gcc/config/mips/mips.c index f208137..c90857e 100644 --- a/gcc/config/mips/mips.c +++ b/gcc/config/mips/mips.c @@ -6244,6 +6244,20 @@ compute_frame_size (size) } } + /* We need to restore these for the handler. */ + if (current_function_calls_eh_return) + { + int i; + for (i = 0; ; ++i) + { + regno = EH_RETURN_DATA_REGNO (i); + if (regno == INVALID_REGNUM) + break; + gp_reg_size += GET_MODE_SIZE (gpr_mode); + mask |= 1L << (regno - GP_REG_FIRST); + } + } + /* Calculate space needed for fp registers. */ if (TARGET_FLOAT64 || TARGET_SINGLE_FLOAT) { @@ -7534,13 +7548,27 @@ mips_expand_epilogue () if (tsize > 32767 && TARGET_MIPS16) abort (); + if (current_function_calls_eh_return) + { + rtx eh_ofs = EH_RETURN_STACKADJ_RTX; + if (Pmode == DImode) + emit_insn (gen_adddi3 (eh_ofs, eh_ofs, tsize_rtx)); + else + emit_insn (gen_addsi3 (eh_ofs, eh_ofs, tsize_rtx)); + tsize_rtx = eh_ofs; + } + emit_insn (gen_blockage ()); - if (Pmode == DImode && tsize != 0) - emit_insn (gen_adddi3 (stack_pointer_rtx, stack_pointer_rtx, - tsize_rtx)); - else if (tsize != 0) - emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx, - tsize_rtx)); + + if (tsize != 0 || current_function_calls_eh_return) + { + if (Pmode == DImode) + emit_insn (gen_adddi3 (stack_pointer_rtx, stack_pointer_rtx, + tsize_rtx)); + else + emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx, + tsize_rtx)); + } } /* The mips16 loads the return address into $7, not $31. */ diff --git a/gcc/config/mips/mips.h b/gcc/config/mips/mips.h index 08f35fa..3d3ea80 100644 --- a/gcc/config/mips/mips.h +++ b/gcc/config/mips/mips.h @@ -1105,6 +1105,10 @@ while (0) /* Before the prologue, RA lives in r31. */ #define INCOMING_RETURN_ADDR_RTX gen_rtx_REG (VOIDmode, GP_REG_FIRST + 31) +/* Describe how we implement __builtin_eh_return. */ +#define EH_RETURN_DATA_REGNO(N) ((N) < 4 ? (N) + GP_ARG_FIRST : INVALID_REGNUM) +#define EH_RETURN_STACKADJ_RTX gen_rtx_REG (Pmode, GP_REG_FIRST + 3) + /* Overrides for the COFF debug format. */ #define PUT_SDB_SCL(a) \ do { \ diff --git a/gcc/config/mips/mips.md b/gcc/config/mips/mips.md index 31ee4d6..5b8d00e 100644 --- a/gcc/config/mips/mips.md +++ b/gcc/config/mips/mips.md @@ -26,6 +26,26 @@ ;; ??? Currently does not have define_function_unit support for the R8000. ;; Must include new entries for fmadd in addition to existing entries. +;; UNSPEC values used in mips.md +;; Number USE +;; 0 movsi_ul +;; 1 movsi_us, get_fnaddr +;; 2 loadgp +;; 3 eh_set_return +;; 20 builtin_setjmp_setup +;; +;; UNSPEC_VOLATILE values +;; 0 blockage +;; 3 builtin_longjmp +;; 10 consttable_qi +;; 11 consttable_hi +;; 12 consttable_si +;; 13 consttable_di +;; 14 consttable_sf +;; 15 consttable_df +;; 16 align_2 +;; 17 align_4 +;; 18 align_8 ;; .................... @@ -9484,6 +9504,73 @@ ld\\t%2,%1-%S1(%2)\;daddu\\t%2,%2,$31\;j\\t%2" (set_attr "mode" "none") (set_attr "length" "16")]) +;; This is used in compiling the unwind routines. +(define_expand "eh_return" + [(use (match_operand 0 "general_operand" "")) + (use (match_operand 1 "general_operand" ""))] + "" + " +{ + enum machine_mode gpr_mode = TARGET_64BIT ? DImode : SImode; + + if (GET_MODE (operands[1]) != gpr_mode) + operands[1] = convert_to_mode (gpr_mode, operands[1], 0); + if (TARGET_64BIT) + emit_insn (gen_eh_set_lr_di (operands[1])); + else + emit_insn (gen_eh_set_lr_si (operands[1])); + + emit_move_insn (EH_RETURN_STACKADJ_RTX, operands[0]); + DONE; +}") + +;; Clobber the return address on the stack. We can't expand this +;; until we know where it will be put in the stack frame. + +(define_insn "eh_set_lr_si" + [(unspec [(match_operand:SI 0 "register_operand" "r")] 3) + (clobber (match_scratch:SI 1 "=&r"))] + "! TARGET_64BIT" + "#") + +(define_insn "eh_set_lr_di" + [(unspec [(match_operand:DI 0 "register_operand" "r")] 3) + (clobber (match_scratch:DI 1 "=&r"))] + "TARGET_64BIT" + "#") + +(define_split + [(unspec [(match_operand 0 "register_operand" "r")] 3) + (clobber (match_scratch 1 "=&r"))] + "reload_completed" + [(const_int 0)] + " +{ + HOST_WIDE_INT gp_offset; + rtx base; + + compute_frame_size (get_frame_size ()); + if (((current_frame_info.mask >> 31) & 1) == 0) + abort (); + gp_offset = current_frame_info.gp_sp_offset; + + if (gp_offset < 32768) + base = stack_pointer_rtx; + else + { + base = operands[1]; + emit_move_insn (base, GEN_INT (gp_offset)); + if (Pmode == DImode) + emit_insn (gen_adddi3 (base, base, stack_pointer_rtx)); + else + emit_insn (gen_addsi3 (base, base, stack_pointer_rtx)); + gp_offset = 0; + } + emit_move_insn (gen_rtx_MEM (GET_MODE (operands[0]), + plus_constant (base, gp_offset)), + operands[0]); + DONE; +}") ;; ;; .................... |