aboutsummaryrefslogtreecommitdiff
path: root/gcc/config
diff options
context:
space:
mode:
authorRichard Henderson <rth@redhat.com>2001-05-19 17:35:24 -0700
committerMark Mitchell <mmitchel@gcc.gnu.org>2001-05-20 00:35:24 +0000
commit9e800206badd2be563d344e4a0aee83e3ac96f03 (patch)
treeacfb4573f234684042fcc91f25abdf25bb73a6f5 /gcc/config
parent878de307d62595211f10a0a88a9551215c14c898 (diff)
downloadgcc-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.c40
-rw-r--r--gcc/config/mips/mips.h4
-rw-r--r--gcc/config/mips/mips.md87
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;
+}")
;;
;; ....................