aboutsummaryrefslogtreecommitdiff
path: root/gcc/config/rs6000/rs6000.md
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/config/rs6000/rs6000.md')
-rw-r--r--gcc/config/rs6000/rs6000.md694
1 files changed, 291 insertions, 403 deletions
diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md
index 9df70cf3eaf..8c51a129b98 100644
--- a/gcc/config/rs6000/rs6000.md
+++ b/gcc/config/rs6000/rs6000.md
@@ -1422,16 +1422,14 @@
rtx tmp = ((no_new_pseudos || rtx_equal_p (operands[0], operands[1]))
? operands[0] : gen_reg_rtx (SImode));
- HOST_WIDE_INT low = INTVAL (operands[2]) & 0xffff;
- HOST_WIDE_INT high = INTVAL (operands[2]) & (~ (HOST_WIDE_INT) 0xffff);
-
- if (low & 0x8000)
- high += 0x10000, low |= ((HOST_WIDE_INT) -1) << 16;
+ HOST_WIDE_INT val = INTVAL (operands[2]);
+ HOST_WIDE_INT low = (val & 0xffff) - 2 * (val & 0x8000);
+ HOST_WIDE_INT rest = trunc_int_for_mode (val - low, SImode);
/* The ordering here is important for the prolog expander.
When space is allocated from the stack, adding 'low' first may
produce a temporary deallocation (which would be bad). */
- emit_insn (gen_addsi3 (tmp, operands[1], GEN_INT (high)));
+ emit_insn (gen_addsi3 (tmp, operands[1], GEN_INT (rest)));
emit_insn (gen_addsi3 (operands[0], tmp, GEN_INT (low)));
DONE;
}
@@ -1525,13 +1523,11 @@
(set (match_dup 0) (plus:SI (match_dup 0) (match_dup 4)))]
"
{
- HOST_WIDE_INT low = INTVAL (operands[2]) & 0xffff;
- HOST_WIDE_INT high = INTVAL (operands[2]) & (~ (HOST_WIDE_INT) 0xffff);
-
- if (low & 0x8000)
- high += 0x10000, low |= ((HOST_WIDE_INT) -1) << 16;
+ HOST_WIDE_INT val = INTVAL (operands[2]);
+ HOST_WIDE_INT low = (val & 0xffff) - 2 * (val & 0x8000);
+ HOST_WIDE_INT rest = trunc_int_for_mode (val - low, SImode);
- operands[3] = GEN_INT (high);
+ operands[3] = GEN_INT (rest);
operands[4] = GEN_INT (low);
}")
@@ -2263,6 +2259,7 @@
"
{
if (GET_CODE (operands[2]) == CONST_INT
+ && INTVAL (operands[2]) > 0
&& exact_log2 (INTVAL (operands[2])) >= 0)
;
else if (TARGET_POWERPC)
@@ -2314,12 +2311,9 @@
rtx temp1;
rtx temp2;
- if (GET_CODE (operands[2]) != CONST_INT)
- FAIL;
-
- i = exact_log2 (INTVAL (operands[2]));
-
- if (i < 0)
+ if (GET_CODE (operands[2]) != CONST_INT
+ || INTVAL (operands[2]) < 0
+ || (i = exact_log2 (INTVAL (operands[2]))) < 0)
FAIL;
temp1 = gen_reg_rtx (SImode);
@@ -2335,7 +2329,7 @@
[(set (match_operand:SI 0 "gpc_reg_operand" "=r")
(div:SI (match_operand:SI 1 "gpc_reg_operand" "r")
(match_operand:SI 2 "const_int_operand" "N")))]
- "exact_log2 (INTVAL (operands[2])) >= 0"
+ "INTVAL (operands[2]) > 0 && exact_log2 (INTVAL (operands[2])) >= 0"
"{srai|srawi} %0,%1,%p2\;{aze|addze} %0,%0"
[(set_attr "length" "8")])
@@ -2345,7 +2339,7 @@
(match_operand:SI 2 "const_int_operand" "N,N"))
(const_int 0)))
(clobber (match_scratch:SI 3 "=r,r"))]
- "exact_log2 (INTVAL (operands[2])) >= 0"
+ "INTVAL (operands[2]) > 0 && exact_log2 (INTVAL (operands[2])) >= 0"
"@
{srai|srawi} %3,%1,%p2\;{aze.|addze.} %3,%3
#"
@@ -2358,7 +2352,8 @@
(match_operand:SI 2 "const_int_operand" ""))
(const_int 0)))
(clobber (match_scratch:SI 3 ""))]
- "exact_log2 (INTVAL (operands[2])) >= 0 && reload_completed"
+ "INTVAL (operands[2]) > 0 && exact_log2 (INTVAL (operands[2])) >= 0
+ && reload_completed"
[(set (match_dup 3)
(div:SI (match_dup 1) (match_dup 2)))
(set (match_dup 0)
@@ -2373,7 +2368,7 @@
(const_int 0)))
(set (match_operand:SI 0 "gpc_reg_operand" "=r,r")
(div:SI (match_dup 1) (match_dup 2)))]
- "exact_log2 (INTVAL (operands[2])) >= 0"
+ "INTVAL (operands[2]) > 0 && exact_log2 (INTVAL (operands[2])) >= 0"
"@
{srai|srawi} %0,%1,%p2\;{aze.|addze.} %0,%0
#"
@@ -2387,7 +2382,8 @@
(const_int 0)))
(set (match_operand:SI 0 "gpc_reg_operand" "")
(div:SI (match_dup 1) (match_dup 2)))]
- "exact_log2 (INTVAL (operands[2])) >= 0 && reload_completed"
+ "INTVAL (operands[2]) > 0 && exact_log2 (INTVAL (operands[2])) >= 0
+ && reload_completed"
[(set (match_dup 0)
(div:SI (match_dup 1) (match_dup 2)))
(set (match_dup 3)
@@ -4808,60 +4804,35 @@
;; single DEFINE_INSN for fsel and the define_splits to make them if made by
;; combine.
(define_expand "maxsf3"
- [(set (match_dup 3)
- (minus:SF (match_operand:SF 1 "gpc_reg_operand" "")
- (match_operand:SF 2 "gpc_reg_operand" "")))
- (set (match_operand:SF 0 "gpc_reg_operand" "")
- (if_then_else:SF (ge (match_dup 3)
- (const_int 0))
- (match_dup 1)
- (match_dup 2)))]
- "TARGET_PPC_GFXOPT && TARGET_HARD_FLOAT"
- "
-{ operands[3] = gen_reg_rtx (SFmode); }")
-
-(define_split
[(set (match_operand:SF 0 "gpc_reg_operand" "")
- (smax:SF (match_operand:SF 1 "gpc_reg_operand" "")
- (match_operand:SF 2 "gpc_reg_operand" "")))
- (clobber (match_operand:SF 3 "gpc_reg_operand" ""))]
- "TARGET_PPC_GFXOPT && TARGET_HARD_FLOAT"
- [(set (match_dup 3)
- (minus:SF (match_dup 1) (match_dup 2)))
- (set (match_dup 0)
- (if_then_else:SF (ge (match_dup 3)
- (const_int 0))
+ (if_then_else:SF (ge (match_operand:SF 1 "gpc_reg_operand" "")
+ (match_operand:SF 2 "gpc_reg_operand" ""))
(match_dup 1)
(match_dup 2)))]
- "")
+ "TARGET_PPC_GFXOPT && TARGET_HARD_FLOAT"
+ "{ rs6000_emit_minmax (operands[0], SMAX, operands[1], operands[2]); DONE;}")
(define_expand "minsf3"
- [(set (match_dup 3)
- (minus:SF (match_operand:SF 2 "gpc_reg_operand" "")
- (match_operand:SF 1 "gpc_reg_operand" "")))
- (set (match_operand:SF 0 "gpc_reg_operand" "")
- (if_then_else:SF (ge (match_dup 3)
- (const_int 0))
- (match_dup 1)
- (match_dup 2)))]
+ [(set (match_operand:SF 0 "gpc_reg_operand" "")
+ (if_then_else:SF (ge (match_operand:SF 1 "gpc_reg_operand" "")
+ (match_operand:SF 2 "gpc_reg_operand" ""))
+ (match_dup 2)
+ (match_dup 1)))]
"TARGET_PPC_GFXOPT && TARGET_HARD_FLOAT"
- "
-{ operands[3] = gen_reg_rtx (SFmode); }")
+ "{ rs6000_emit_minmax (operands[0], SMIN, operands[1], operands[2]); DONE;}")
(define_split
[(set (match_operand:SF 0 "gpc_reg_operand" "")
- (smin:SF (match_operand:SF 1 "gpc_reg_operand" "")
- (match_operand:SF 2 "gpc_reg_operand" "")))
- (clobber (match_operand:SF 3 "gpc_reg_operand" ""))]
+ (match_operator:SF 3 "min_max_operator"
+ [(match_operand:SF 1 "gpc_reg_operand" "")
+ (match_operand:SF 2 "gpc_reg_operand" "")]))]
"TARGET_PPC_GFXOPT && TARGET_HARD_FLOAT"
- [(set (match_dup 3)
- (minus:SF (match_dup 2) (match_dup 1)))
- (set (match_dup 0)
- (if_then_else:SF (ge (match_dup 3)
- (const_int 0))
- (match_dup 1)
- (match_dup 2)))]
- "")
+ [(const_int 0)]
+ "
+{ rs6000_emit_minmax (operands[0], GET_CODE (operands[3]),
+ operands[1], operands[2]);
+ DONE;
+}")
(define_expand "movsfcc"
[(set (match_operand:SF 0 "gpc_reg_operand" "")
@@ -4871,82 +4842,26 @@
"TARGET_PPC_GFXOPT && TARGET_HARD_FLOAT"
"
{
- rtx temp, op0, op1;
- enum rtx_code code = GET_CODE (operands[1]);
- if (! rs6000_compare_fp_p)
- FAIL;
- switch (code)
- {
- case GE: case EQ: case NE:
- op0 = rs6000_compare_op0;
- op1 = rs6000_compare_op1;
- break;
- case GT:
- op0 = rs6000_compare_op1;
- op1 = rs6000_compare_op0;
- temp = operands[2]; operands[2] = operands[3]; operands[3] = temp;
- break;
- case LE:
- op0 = rs6000_compare_op1;
- op1 = rs6000_compare_op0;
- break;
- case LT:
- op0 = rs6000_compare_op0;
- op1 = rs6000_compare_op1;
- temp = operands[2]; operands[2] = operands[3]; operands[3] = temp;
- break;
- default:
- FAIL;
- }
- if (GET_MODE (rs6000_compare_op0) == DFmode)
- {
- temp = gen_reg_rtx (DFmode);
- emit_insn (gen_subdf3 (temp, op0, op1));
- emit_insn (gen_fseldfsf4 (operands[0], temp, operands[2], operands[3]));
- if (code == EQ)
- {
- emit_insn (gen_negdf2 (temp, temp));
- emit_insn (gen_fseldfsf4 (operands[0], temp, operands[0], operands[3]));
- }
- else if (code == NE)
- {
- emit_insn (gen_negdf2 (temp, temp));
- emit_insn (gen_fseldfsf4 (operands[0], temp, operands[3], operands[0]));
- }
- }
+ if (rs6000_emit_cmove (operands[0], operands[1], operands[2], operands[3]))
+ DONE;
else
- {
- temp = gen_reg_rtx (SFmode);
- emit_insn (gen_subsf3 (temp, op0, op1));
- emit_insn (gen_fselsfsf4 (operands[0], temp, operands[2], operands[3]));
- if (code == EQ)
- {
- emit_insn (gen_negsf2 (temp, temp));
- emit_insn (gen_fselsfsf4 (operands[0], temp, operands[0], operands[3]));
- }
- else if (code == NE)
- {
- emit_insn (gen_negsf2 (temp, temp));
- emit_insn (gen_fselsfsf4 (operands[0], temp, operands[3], operands[0]));
- }
- }
- DONE;
+ FAIL;
}")
-(define_insn "fselsfsf4"
+(define_insn "*fselsfsf4"
[(set (match_operand:SF 0 "gpc_reg_operand" "=f")
(if_then_else:SF (ge (match_operand:SF 1 "gpc_reg_operand" "f")
- (const_int 0))
+ (match_operand:SF 4 "zero_fp_constant" "F"))
(match_operand:SF 2 "gpc_reg_operand" "f")
(match_operand:SF 3 "gpc_reg_operand" "f")))]
"TARGET_PPC_GFXOPT && TARGET_HARD_FLOAT"
"fsel %0,%1,%2,%3"
[(set_attr "type" "fp")])
-(define_insn "fseldfsf4"
+(define_insn "*fseldfsf4"
[(set (match_operand:SF 0 "gpc_reg_operand" "=f")
(if_then_else:SF (ge (match_operand:DF 1 "gpc_reg_operand" "f")
- (const_int 0))
+ (match_operand:DF 4 "zero_fp_constant" "F"))
(match_operand:SF 2 "gpc_reg_operand" "f")
(match_operand:SF 3 "gpc_reg_operand" "f")))]
"TARGET_PPC_GFXOPT && TARGET_HARD_FLOAT"
@@ -5049,66 +4964,39 @@
"fsqrt %0,%1"
[(set_attr "type" "dsqrt")])
-;; For MIN, MAX, and conditional move, we use DEFINE_EXPAND's that involve a
-;; fsel instruction and some auxiliary computations. Then we just have a
-;; single DEFINE_INSN for fsel and the define_splits to make them if made by
-;; combine.
+;; The conditional move instructions allow us to perform max and min
+;; operations even when
(define_expand "maxdf3"
- [(set (match_dup 3)
- (minus:DF (match_operand:DF 1 "gpc_reg_operand" "")
- (match_operand:DF 2 "gpc_reg_operand" "")))
- (set (match_operand:DF 0 "gpc_reg_operand" "")
- (if_then_else:DF (ge (match_dup 3)
- (const_int 0))
- (match_dup 1)
- (match_dup 2)))]
- "TARGET_PPC_GFXOPT && TARGET_HARD_FLOAT"
- "
-{ operands[3] = gen_reg_rtx (DFmode); }")
-
-(define_split
[(set (match_operand:DF 0 "gpc_reg_operand" "")
- (smax:DF (match_operand:DF 1 "gpc_reg_operand" "")
- (match_operand:DF 2 "gpc_reg_operand" "")))
- (clobber (match_operand:DF 3 "gpc_reg_operand" ""))]
- "TARGET_PPC_GFXOPT && TARGET_HARD_FLOAT"
- [(set (match_dup 3)
- (minus:DF (match_dup 1) (match_dup 2)))
- (set (match_dup 0)
- (if_then_else:DF (ge (match_dup 3)
- (const_int 0))
+ (if_then_else:DF (ge (match_operand:DF 1 "gpc_reg_operand" "")
+ (match_operand:DF 2 "gpc_reg_operand" ""))
(match_dup 1)
(match_dup 2)))]
- "")
+ "TARGET_PPC_GFXOPT && TARGET_HARD_FLOAT"
+ "{ rs6000_emit_minmax (operands[0], SMAX, operands[1], operands[2]); DONE;}")
(define_expand "mindf3"
- [(set (match_dup 3)
- (minus:DF (match_operand:DF 2 "gpc_reg_operand" "")
- (match_operand:DF 1 "gpc_reg_operand" "")))
- (set (match_operand:DF 0 "gpc_reg_operand" "")
- (if_then_else:DF (ge (match_dup 3)
- (const_int 0))
- (match_dup 1)
- (match_dup 2)))]
+ [(set (match_operand:DF 0 "gpc_reg_operand" "")
+ (if_then_else:DF (ge (match_operand:DF 1 "gpc_reg_operand" "")
+ (match_operand:DF 2 "gpc_reg_operand" ""))
+ (match_dup 2)
+ (match_dup 1)))]
"TARGET_PPC_GFXOPT && TARGET_HARD_FLOAT"
- "
-{ operands[3] = gen_reg_rtx (DFmode); }")
+ "{ rs6000_emit_minmax (operands[0], SMIN, operands[1], operands[2]); DONE;}")
(define_split
[(set (match_operand:DF 0 "gpc_reg_operand" "")
- (smin:DF (match_operand:DF 1 "gpc_reg_operand" "")
- (match_operand:DF 2 "gpc_reg_operand" "")))
- (clobber (match_operand:DF 3 "gpc_reg_operand" ""))]
+ (match_operator:DF 3 "min_max_operator"
+ [(match_operand:DF 1 "gpc_reg_operand" "")
+ (match_operand:DF 2 "gpc_reg_operand" "")]))]
"TARGET_PPC_GFXOPT && TARGET_HARD_FLOAT"
- [(set (match_dup 3)
- (minus:DF (match_dup 2) (match_dup 1)))
- (set (match_dup 0)
- (if_then_else:DF (ge (match_dup 3)
- (const_int 0))
- (match_dup 1)
- (match_dup 2)))]
- "")
+ [(const_int 0)]
+ "
+{ rs6000_emit_minmax (operands[0], GET_CODE (operands[3]),
+ operands[1], operands[2]);
+ DONE;
+}")
(define_expand "movdfcc"
[(set (match_operand:DF 0 "gpc_reg_operand" "")
@@ -5118,82 +5006,26 @@
"TARGET_PPC_GFXOPT && TARGET_HARD_FLOAT"
"
{
- rtx temp, op0, op1;
- enum rtx_code code = GET_CODE (operands[1]);
- if (! rs6000_compare_fp_p)
- FAIL;
- switch (code)
- {
- case GE: case EQ: case NE:
- op0 = rs6000_compare_op0;
- op1 = rs6000_compare_op1;
- break;
- case GT:
- op0 = rs6000_compare_op1;
- op1 = rs6000_compare_op0;
- temp = operands[2]; operands[2] = operands[3]; operands[3] = temp;
- break;
- case LE:
- op0 = rs6000_compare_op1;
- op1 = rs6000_compare_op0;
- break;
- case LT:
- op0 = rs6000_compare_op0;
- op1 = rs6000_compare_op1;
- temp = operands[2]; operands[2] = operands[3]; operands[3] = temp;
- break;
- default:
- FAIL;
- }
- if (GET_MODE (rs6000_compare_op0) == DFmode)
- {
- temp = gen_reg_rtx (DFmode);
- emit_insn (gen_subdf3 (temp, op0, op1));
- emit_insn (gen_fseldfdf4 (operands[0], temp, operands[2], operands[3]));
- if (code == EQ)
- {
- emit_insn (gen_negdf2 (temp, temp));
- emit_insn (gen_fseldfdf4 (operands[0], temp, operands[0], operands[3]));
- }
- else if (code == NE)
- {
- emit_insn (gen_negdf2 (temp, temp));
- emit_insn (gen_fseldfdf4 (operands[0], temp, operands[3], operands[0]));
- }
- }
+ if (rs6000_emit_cmove (operands[0], operands[1], operands[2], operands[3]))
+ DONE;
else
- {
- temp = gen_reg_rtx (SFmode);
- emit_insn (gen_subsf3 (temp, op0, op1));
- emit_insn (gen_fselsfdf4 (operands[0], temp, operands[2], operands[3]));
- if (code == EQ)
- {
- emit_insn (gen_negsf2 (temp, temp));
- emit_insn (gen_fselsfdf4 (operands[0], temp, operands[0], operands[3]));
- }
- else if (code == NE)
- {
- emit_insn (gen_negsf2 (temp, temp));
- emit_insn (gen_fselsfdf4 (operands[0], temp, operands[3], operands[0]));
- }
- }
- DONE;
+ FAIL;
}")
-(define_insn "fseldfdf4"
+(define_insn "*fseldfdf4"
[(set (match_operand:DF 0 "gpc_reg_operand" "=f")
(if_then_else:DF (ge (match_operand:DF 1 "gpc_reg_operand" "f")
- (const_int 0))
+ (match_operand:DF 4 "zero_fp_constant" "F"))
(match_operand:DF 2 "gpc_reg_operand" "f")
(match_operand:DF 3 "gpc_reg_operand" "f")))]
"TARGET_PPC_GFXOPT && TARGET_HARD_FLOAT"
"fsel %0,%1,%2,%3"
[(set_attr "type" "fp")])
-(define_insn "fselsfdf4"
+(define_insn "*fselsfdf4"
[(set (match_operand:DF 0 "gpc_reg_operand" "=f")
(if_then_else:DF (ge (match_operand:SF 1 "gpc_reg_operand" "f")
- (const_int 0))
+ (match_operand:SF 4 "zero_fp_constant" "F"))
(match_operand:DF 2 "gpc_reg_operand" "f")
(match_operand:DF 3 "gpc_reg_operand" "f")))]
"TARGET_PPC_GFXOPT"
@@ -5739,7 +5571,7 @@
(define_expand "adddi3"
[(set (match_operand:DI 0 "gpc_reg_operand" "")
(plus:DI (match_operand:DI 1 "gpc_reg_operand" "")
- (match_operand:DI 2 "reg_or_arith_cint_operand" "")))]
+ (match_operand:DI 2 "reg_or_add_cint64_operand" "")))]
""
"
{
@@ -5755,13 +5587,17 @@
rtx tmp = ((no_new_pseudos || rtx_equal_p (operands[0], operands[1]))
? operands[0] : gen_reg_rtx (DImode));
- HOST_WIDE_INT low = INTVAL (operands[2]) & 0xffff;
- HOST_WIDE_INT high = INTVAL (operands[2]) & (~ (HOST_WIDE_INT) 0xffff);
+ HOST_WIDE_INT val = INTVAL (operands[2]);
+ HOST_WIDE_INT low = (val & 0xffff) - 2 * (val & 0x8000);
+ HOST_WIDE_INT rest = trunc_int_for_mode (val - low, DImode);
- if (low & 0x8000)
- high += 0x10000, low |= ((HOST_WIDE_INT) -1) << 16;
+ if (!CONST_OK_FOR_LETTER_P (rest, 'L'))
+ FAIL;
- emit_insn (gen_adddi3 (tmp, operands[1], GEN_INT (high)));
+ /* The ordering here is important for the prolog expander.
+ When space is allocated from the stack, adding 'low' first may
+ produce a temporary deallocation (which would be bad). */
+ emit_insn (gen_adddi3 (tmp, operands[1], GEN_INT (rest)));
emit_insn (gen_adddi3 (operands[0], tmp, GEN_INT (low)));
DONE;
}
@@ -5854,14 +5690,22 @@
(set (match_dup 0) (plus:DI (match_dup 0) (match_dup 4)))]
"
{
- HOST_WIDE_INT low = INTVAL (operands[2]) & 0xffff;
- HOST_WIDE_INT high = INTVAL (operands[2]) & (~ (HOST_WIDE_INT) 0xffff);
+ HOST_WIDE_INT val = INTVAL (operands[2]);
+ HOST_WIDE_INT low = (val & 0xffff) - 2 * (val & 0x8000);
+ HOST_WIDE_INT rest = trunc_int_for_mode (val - low, DImode);
- if (low & 0x8000)
- high+=0x10000, low |= ((HOST_WIDE_INT) -1) << 16;
-
- operands[3] = GEN_INT (high);
operands[4] = GEN_INT (low);
+ if (CONST_OK_FOR_LETTER_P (rest, 'L'))
+ operands[3] = GEN_INT (rest);
+ else if (! no_new_pseudos)
+ {
+ operands[3] = gen_reg_rtx (DImode);
+ emit_move_insn (operands[3], operands[2]);
+ emit_insn (gen_adddi3 (operands[0], operands[1], operands[3]));
+ DONE;
+ }
+ else
+ FAIL;
}")
(define_insn "one_cmpldi2"
@@ -5990,7 +5834,7 @@
(define_expand "subdi3"
[(set (match_operand:DI 0 "gpc_reg_operand" "")
(minus:DI (match_operand:DI 1 "reg_or_short_operand" "")
- (match_operand:DI 2 "reg_or_arith_cint_operand" "")))]
+ (match_operand:DI 2 "reg_or_sub_cint64_operand" "")))]
""
"
{
@@ -6149,6 +5993,7 @@
"
{
if (GET_CODE (operands[2]) == CONST_INT
+ && INTVAL (operands[2]) > 0
&& exact_log2 (INTVAL (operands[2])) >= 0)
;
else
@@ -6162,11 +6007,13 @@
"TARGET_POWERPC64"
"
{
- int i = exact_log2 (INTVAL (operands[2]));
+ int i;
rtx temp1;
rtx temp2;
- if (GET_CODE (operands[2]) != CONST_INT || i < 0)
+ if (GET_CODE (operands[2]) != CONST_INT
+ || INTVAL (operands[2]) <= 0
+ || (i = exact_log2 (INTVAL (operands[2]))) < 0)
FAIL;
temp1 = gen_reg_rtx (DImode);
@@ -6182,7 +6029,8 @@
[(set (match_operand:DI 0 "gpc_reg_operand" "=r")
(div:DI (match_operand:DI 1 "gpc_reg_operand" "r")
(match_operand:DI 2 "const_int_operand" "N")))]
- "TARGET_POWERPC64 && exact_log2 (INTVAL (operands[2])) >= 0"
+ "TARGET_POWERPC64 && INTVAL (operands[2]) > 0
+ && exact_log2 (INTVAL (operands[2])) >= 0"
"sradi %0,%1,%p2\;addze %0,%0"
[(set_attr "length" "8")])
@@ -6192,7 +6040,8 @@
(match_operand:DI 2 "const_int_operand" "N,N"))
(const_int 0)))
(clobber (match_scratch:DI 3 "=r,r"))]
- "TARGET_POWERPC64 && exact_log2 (INTVAL (operands[2])) >= 0"
+ "TARGET_POWERPC64 && INTVAL (operands[2]) > 0
+ && exact_log2 (INTVAL (operands[2])) >= 0"
"@
sradi %3,%1,%p2\;addze. %3,%3
#"
@@ -6205,7 +6054,8 @@
(match_operand:DI 2 "const_int_operand" ""))
(const_int 0)))
(clobber (match_scratch:DI 3 ""))]
- "TARGET_POWERPC64 && exact_log2 (INTVAL (operands[2])) >= 0 && reload_completed"
+ "TARGET_POWERPC64 && INTVAL (operands[2]) > 0
+ && exact_log2 (INTVAL (operands[2])) >= 0 && reload_completed"
[(set (match_dup 3)
(div:DI (match_dup 1) (match_dup 2)))
(set (match_dup 0)
@@ -6220,7 +6070,8 @@
(const_int 0)))
(set (match_operand:DI 0 "gpc_reg_operand" "=r,r")
(div:DI (match_dup 1) (match_dup 2)))]
- "TARGET_POWERPC64 && exact_log2 (INTVAL (operands[2])) >= 0"
+ "TARGET_POWERPC64 && INTVAL (operands[2]) > 0
+ && exact_log2 (INTVAL (operands[2])) >= 0"
"@
sradi %0,%1,%p2\;addze. %0,%0
#"
@@ -6234,7 +6085,8 @@
(const_int 0)))
(set (match_operand:DI 0 "gpc_reg_operand" "")
(div:DI (match_dup 1) (match_dup 2)))]
- "TARGET_POWERPC64 && exact_log2 (INTVAL (operands[2])) >= 0 && reload_completed"
+ "TARGET_POWERPC64 && INTVAL (operands[2]) > 0
+ && exact_log2 (INTVAL (operands[2])) >= 0 && reload_completed"
[(set (match_dup 0)
(div:DI (match_dup 1) (match_dup 2)))
(set (match_dup 3)
@@ -6706,8 +6558,8 @@
[(set (match_operand:DI 0 "gpc_reg_operand" "=r")
(and:DI (ashift:DI (match_operand:DI 1 "gpc_reg_operand" "r")
(match_operand:SI 2 "const_int_operand" "i"))
- (match_operand:DI 3 "rldic_operand" "n")))]
- "includes_lshift64_p (operands[2], operands[3])"
+ (match_operand:DI 3 "const_int_operand" "n")))]
+ "TARGET_POWERPC64 && includes_rldic_lshift_p (operands[2], operands[3])"
"rldic %0,%1,%H2,%W3")
(define_insn "ashldi3_internal5"
@@ -6715,10 +6567,10 @@
(compare:CC
(and:DI (ashift:DI (match_operand:DI 1 "gpc_reg_operand" "r,r")
(match_operand:SI 2 "const_int_operand" "i,i"))
- (match_operand:DI 3 "rldic_operand" "n,n"))
+ (match_operand:DI 3 "const_int_operand" "n,n"))
(const_int 0)))
(clobber (match_scratch:DI 4 "=r,r"))]
- "includes_lshift64_p (operands[2], operands[3])"
+ "TARGET_POWERPC64 && includes_rldic_lshift_p (operands[2], operands[3])"
"@
rldic. %4,%1,%H2,%W3
#"
@@ -6730,10 +6582,11 @@
(compare:CC
(and:DI (ashift:DI (match_operand:DI 1 "gpc_reg_operand" "")
(match_operand:SI 2 "const_int_operand" ""))
- (match_operand:DI 3 "rldic_operand" ""))
+ (match_operand:DI 3 "const_int_operand" ""))
(const_int 0)))
(clobber (match_scratch:DI 4 ""))]
- "includes_lshift64_p (operands[2], operands[3]) && reload_completed"
+ "TARGET_POWERPC64 && reload_completed
+ && includes_rldic_lshift_p (operands[2], operands[3])"
[(set (match_dup 4)
(and:DI (ashift:DI (match_dup 1) (match_dup 2))
(match_dup 3)))
@@ -6747,11 +6600,11 @@
(compare:CC
(and:DI (ashift:DI (match_operand:DI 1 "gpc_reg_operand" "r,r")
(match_operand:SI 2 "const_int_operand" "i,i"))
- (match_operand:DI 3 "rldic_operand" "n,n"))
+ (match_operand:DI 3 "const_int_operand" "n,n"))
(const_int 0)))
(set (match_operand:DI 0 "gpc_reg_operand" "=r,r")
(and:DI (ashift:DI (match_dup 1) (match_dup 2)) (match_dup 3)))]
- "includes_lshift64_p (operands[2], operands[3])"
+ "TARGET_POWERPC64 && includes_rldic_lshift_p (operands[2], operands[3])"
"@
rldic. %0,%1,%H2,%W3
#"
@@ -6763,11 +6616,88 @@
(compare:CC
(and:DI (ashift:DI (match_operand:DI 1 "gpc_reg_operand" "")
(match_operand:SI 2 "const_int_operand" ""))
- (match_operand:DI 3 "rldic_operand" ""))
+ (match_operand:DI 3 "const_int_operand" ""))
(const_int 0)))
(set (match_operand:DI 0 "gpc_reg_operand" "")
(and:DI (ashift:DI (match_dup 1) (match_dup 2)) (match_dup 3)))]
- "includes_lshift64_p (operands[2], operands[3]) && reload_completed"
+ "TARGET_POWERPC64 && reload_completed
+ && includes_rldic_lshift_p (operands[2], operands[3])"
+ [(set (match_dup 0)
+ (and:DI (ashift:DI (match_dup 1) (match_dup 2))
+ (match_dup 3)))
+ (set (match_dup 4)
+ (compare:CC (match_dup 0)
+ (const_int 0)))]
+ "")
+
+(define_insn "*ashldi3_internal7"
+ [(set (match_operand:DI 0 "gpc_reg_operand" "=r")
+ (and:DI (ashift:DI (match_operand:DI 1 "gpc_reg_operand" "r")
+ (match_operand:SI 2 "const_int_operand" "i"))
+ (match_operand:DI 3 "mask64_operand" "S")))]
+ "TARGET_POWERPC64 && includes_rldicr_lshift_p (operands[2], operands[3])"
+ "rldicr %0,%1,%H2,%S3")
+
+(define_insn "ashldi3_internal8"
+ [(set (match_operand:CC 0 "cc_reg_operand" "=x,?y")
+ (compare:CC
+ (and:DI (ashift:DI (match_operand:DI 1 "gpc_reg_operand" "r,r")
+ (match_operand:SI 2 "const_int_operand" "i,i"))
+ (match_operand:DI 3 "mask64_operand" "S,S"))
+ (const_int 0)))
+ (clobber (match_scratch:DI 4 "=r,r"))]
+ "TARGET_POWERPC64 && includes_rldicr_lshift_p (operands[2], operands[3])"
+ "@
+ rldicr. %4,%1,%H2,%S3
+ #"
+ [(set_attr "type" "delayed_compare")
+ (set_attr "length" "4,8")])
+
+(define_split
+ [(set (match_operand:CC 0 "cc_reg_not_cr0_operand" "")
+ (compare:CC
+ (and:DI (ashift:DI (match_operand:DI 1 "gpc_reg_operand" "")
+ (match_operand:SI 2 "const_int_operand" ""))
+ (match_operand:DI 3 "mask64_operand" ""))
+ (const_int 0)))
+ (clobber (match_scratch:DI 4 ""))]
+ "TARGET_POWERPC64 && reload_completed
+ && includes_rldicr_lshift_p (operands[2], operands[3])"
+ [(set (match_dup 4)
+ (and:DI (ashift:DI (match_dup 1) (match_dup 2))
+ (match_dup 3)))
+ (set (match_dup 0)
+ (compare:CC (match_dup 4)
+ (const_int 0)))]
+ "")
+
+(define_insn "*ashldi3_internal9"
+ [(set (match_operand:CC 4 "cc_reg_operand" "=x,?y")
+ (compare:CC
+ (and:DI (ashift:DI (match_operand:DI 1 "gpc_reg_operand" "r,r")
+ (match_operand:SI 2 "const_int_operand" "i,i"))
+ (match_operand:DI 3 "mask64_operand" "S,S"))
+ (const_int 0)))
+ (set (match_operand:DI 0 "gpc_reg_operand" "=r,r")
+ (and:DI (ashift:DI (match_dup 1) (match_dup 2)) (match_dup 3)))]
+ "TARGET_POWERPC64 && includes_rldicr_lshift_p (operands[2], operands[3])"
+ "@
+ rldicr. %0,%1,%H2,%S3
+ #"
+ [(set_attr "type" "delayed_compare")
+ (set_attr "length" "4,8")])
+
+(define_split
+ [(set (match_operand:CC 4 "cc_reg_not_cr0_operand" "")
+ (compare:CC
+ (and:DI (ashift:DI (match_operand:DI 1 "gpc_reg_operand" "")
+ (match_operand:SI 2 "const_int_operand" ""))
+ (match_operand:DI 3 "mask64_operand" ""))
+ (const_int 0)))
+ (set (match_operand:DI 0 "gpc_reg_operand" "")
+ (and:DI (ashift:DI (match_dup 1) (match_dup 2)) (match_dup 3)))]
+ "TARGET_POWERPC64 && reload_completed
+ && includes_rldicr_lshift_p (operands[2], operands[3])"
[(set (match_dup 0)
(and:DI (ashift:DI (match_dup 1) (match_dup 2))
(match_dup 3)))
@@ -9185,8 +9115,9 @@ operands[2] = GEN_INT (INTVAL (operands[1]) >> 32);
;; Code to initialize the TOC register...
(define_insn "load_toc_aix_si"
- [(set (match_operand:SI 0 "register_operand" "=r")
- (unspec:SI [(const_int 0)] 7))]
+ [(parallel [(set (match_operand:SI 0 "register_operand" "=r")
+ (unspec:SI [(const_int 0)] 7))
+ (use (reg:SI 2))])]
"! TARGET_ELF && TARGET_32BIT"
"*
{
@@ -9199,8 +9130,9 @@ operands[2] = GEN_INT (INTVAL (operands[1]) >> 32);
[(set_attr "type" "load")])
(define_insn "load_toc_aix_di"
- [(set (match_operand:DI 0 "register_operand" "=r")
- (unspec:DI [(const_int 0)] 7))]
+ [(parallel [(set (match_operand:DI 0 "register_operand" "=r")
+ (unspec:DI [(const_int 0)] 7))
+ (use (reg:DI 2))])]
"! TARGET_ELF && TARGET_64BIT"
"*
{
@@ -10330,7 +10262,7 @@ operands[2] = GEN_INT (INTVAL (operands[1]) >> 32);
(define_insn ""
[(set (match_operand:DI 0 "gpc_reg_operand" "=r,r,r,r,r")
(eq:DI (match_operand:DI 1 "gpc_reg_operand" "%r,r,r,r,r")
- (match_operand:DI 2 "reg_or_cint_operand" "r,O,K,J,I")))
+ (match_operand:DI 2 "scc_eq_operand" "r,O,K,J,I")))
(clobber (match_scratch:DI 3 "=r,&r,r,r,r"))]
"TARGET_POWERPC64"
"@
@@ -10387,7 +10319,7 @@ operands[2] = GEN_INT (INTVAL (operands[1]) >> 32);
[(set (match_operand:CC 4 "cc_reg_operand" "=x,x,x,x,x,?y,?y,?y,?y,?y")
(compare:CC
(eq:DI (match_operand:DI 1 "gpc_reg_operand" "%r,r,r,r,r,r,r,r,r,r")
- (match_operand:DI 2 "reg_or_cint_operand" "r,O,K,J,I,r,O,K,J,I"))
+ (match_operand:DI 2 "scc_eq_operand" "r,O,K,J,I,r,O,K,J,I"))
(const_int 0)))
(set (match_operand:DI 0 "gpc_reg_operand" "=r,r,r,r,r,r,r,r,r,r")
(eq:DI (match_dup 1) (match_dup 2)))
@@ -10411,7 +10343,7 @@ operands[2] = GEN_INT (INTVAL (operands[1]) >> 32);
[(set (match_operand:CC 4 "cc_reg_not_cr0_operand" "")
(compare:CC
(eq:DI (match_operand:DI 1 "gpc_reg_operand" "")
- (match_operand:DI 2 "reg_or_cint_operand" ""))
+ (match_operand:DI 2 "scc_eq_operand" ""))
(const_int 0)))
(set (match_operand:DI 0 "gpc_reg_operand" "")
(eq:DI (match_dup 1) (match_dup 2)))
@@ -12575,7 +12507,7 @@ operands[2] = GEN_INT (INTVAL (operands[1]) >> 32);
(const_int 0)])
(const_int 0)))]
""
- "crnot %E0,%j1"
+ "{crnor %E0,%j1,%j1|crnot %E0,%j1}"
[(set_attr "type" "cr_logical")])
;; If we are comparing the result of two comparisons, this can be done
@@ -12602,27 +12534,34 @@ operands[2] = GEN_INT (INTVAL (operands[1]) >> 32);
positive_2 = branch_positive_comparison_operator (operands[3], CCEQmode);
if (! positive_1)
- operands[1] = gen_rtx (SImode,
- rs6000_reverse_condition (GET_MODE (operands[2]),
+ operands[1] = gen_rtx (rs6000_reverse_condition (GET_MODE (operands[2]),
GET_CODE (operands[1])),
- operands[2]);
+ SImode,
+ operands[2], const0_rtx);
else if (GET_MODE (operands[1]) != SImode)
- operands[1] = gen_rtx (SImode,
- GET_CODE (operands[1]),
- operands[2]);
+ operands[1] = gen_rtx (GET_CODE (operands[1]),
+ SImode,
+ operands[2], const0_rtx);
if (! positive_2)
- operands[3] = gen_rtx (SImode,
- rs6000_reverse_condition (GET_MODE (operands[4]),
+ operands[3] = gen_rtx (rs6000_reverse_condition (GET_MODE (operands[4]),
GET_CODE (operands[3])),
- operands[4]);
+ SImode,
+ operands[4], const0_rtx);
else if (GET_MODE (operands[3]) != SImode)
- operands[3] = gen_rtx (SImode,
- GET_CODE (operands[3]),
- operands[4]);
+ operands[3] = gen_rtx (GET_CODE (operands[3]),
+ SImode,
+ operands[4], const0_rtx);
if (positive_1 == positive_2)
- operands[1] = gen_rtx_NOT (SImode, operands[1]);
+ {
+ operands[1] = gen_rtx_NOT (SImode, operands[1]);
+ operands[5] = constm1_rtx;
+ }
+ else
+ {
+ operands[5] = const1_rtx;
+ }
}")
;; Unconditional branch and return.
@@ -12807,7 +12746,7 @@ operands[2] = GEN_INT (INTVAL (operands[1]) >> 32);
{
if (which_alternative != 0)
return \"#\";
- else if (get_attr_length (insn) == 8)
+ else if (get_attr_length (insn) == 4)
return \"{bdn|bdnz} %l0\";
else
return \"bdz %$+8\;b %l0\";
@@ -12831,7 +12770,7 @@ operands[2] = GEN_INT (INTVAL (operands[1]) >> 32);
{
if (which_alternative != 0)
return \"#\";
- else if (get_attr_length (insn) == 8)
+ else if (get_attr_length (insn) == 4)
return \"bdz %l0\";
else
return \"{bdn|bdnz} %$+8\;b %l0\";
@@ -12855,7 +12794,7 @@ operands[2] = GEN_INT (INTVAL (operands[1]) >> 32);
{
if (which_alternative != 0)
return \"#\";
- else if (get_attr_length (insn) == 8)
+ else if (get_attr_length (insn) == 4)
return \"{bdn|bdnz} %l0\";
else
return \"bdz %$+8\;b %l0\";
@@ -12879,7 +12818,7 @@ operands[2] = GEN_INT (INTVAL (operands[1]) >> 32);
{
if (which_alternative != 0)
return \"#\";
- else if (get_attr_length (insn) == 8)
+ else if (get_attr_length (insn) == 4)
return \"bdz %l0\";
else
return \"{bdn|bdnz} %$+8\;b %l0\";
@@ -12905,7 +12844,7 @@ operands[2] = GEN_INT (INTVAL (operands[1]) >> 32);
{
if (which_alternative != 0)
return \"#\";
- else if (get_attr_length (insn) == 8)
+ else if (get_attr_length (insn) == 4)
return \"{bdn|bdnz} %l0\";
else
return \"bdz %$+8\;b %l0\";
@@ -12929,7 +12868,7 @@ operands[2] = GEN_INT (INTVAL (operands[1]) >> 32);
{
if (which_alternative != 0)
return \"#\";
- else if (get_attr_length (insn) == 8)
+ else if (get_attr_length (insn) == 4)
return \"bdz %l0\";
else
return \"{bdn|bdnz} %$+8\;b %l0\";
@@ -12953,7 +12892,7 @@ operands[2] = GEN_INT (INTVAL (operands[1]) >> 32);
{
if (which_alternative != 0)
return \"#\";
- else if (get_attr_length (insn) == 8)
+ else if (get_attr_length (insn) == 4)
return \"{bdn|bdnz} %l0\";
else
return \"bdz %$+8\;b %l0\";
@@ -12977,7 +12916,7 @@ operands[2] = GEN_INT (INTVAL (operands[1]) >> 32);
{
if (which_alternative != 0)
return \"#\";
- else if (get_attr_length (insn) == 8)
+ else if (get_attr_length (insn) == 4)
return \"bdz %l0\";
else
return \"{bdn|bdnz} %$+8\;b %l0\";
@@ -13003,7 +12942,7 @@ operands[2] = GEN_INT (INTVAL (operands[1]) >> 32);
{
if (which_alternative != 0)
return \"#\";
- else if (get_attr_length (insn) == 8)
+ else if (get_attr_length (insn) == 4)
return \"bdz %l0\";
else
return \"{bdn|bdnz} %$+8\;b %l0\";
@@ -13027,7 +12966,7 @@ operands[2] = GEN_INT (INTVAL (operands[1]) >> 32);
{
if (which_alternative != 0)
return \"#\";
- else if (get_attr_length (insn) == 8)
+ else if (get_attr_length (insn) == 4)
return \"{bdn|bdnz} %l0\";
else
return \"bdz %$+8\;b %l0\";
@@ -13051,7 +12990,7 @@ operands[2] = GEN_INT (INTVAL (operands[1]) >> 32);
{
if (which_alternative != 0)
return \"#\";
- else if (get_attr_length (insn) == 8)
+ else if (get_attr_length (insn) == 4)
return \"bdz %l0\";
else
return \"{bdn|bdnz} %$+8\;b %l0\";
@@ -13075,7 +13014,7 @@ operands[2] = GEN_INT (INTVAL (operands[1]) >> 32);
{
if (which_alternative != 0)
return \"#\";
- else if (get_attr_length (insn) == 8)
+ else if (get_attr_length (insn) == 4)
return \"{bdn|bdnz} %l0\";
else
return \"bdz %$+8\;b %l0\";
@@ -13374,118 +13313,67 @@ operands[2] = GEN_INT (INTVAL (operands[1]) >> 32);
"TARGET_64BIT"
"b %z2")
-; This is used in compiling the routines __throw and __rethrow.
-; It's a little different to the usual definition...
-
-(define_expand "eh_epilogue"
- [(use (match_operand 0 "general_operand" "r"))
- (use (match_operand 1 "general_operand" "r"))
- (use (match_operand 2 "general_operand" "c"))]
+; This is used in compiling the unwind routines.
+(define_expand "eh_return"
+ [(use (match_operand 0 "general_operand" ""))
+ (use (match_operand 1 "general_operand" ""))]
""
"
{
- rtx stack_reg = gen_rtx_REG (Pmode, STACK_POINTER_REGNUM);
- rtx insn;
-
- /* This is required for binary compatibility. If it's wrong,
- it probably means that eh_regs() in except.c is broken. */
- if (GET_CODE (operands[0]) != REG || REGNO (operands[0]) != 3)
- abort();
-
- /* These can be anything that doesn't interfere with the epilogue. */
- if (GET_CODE (operands[1]) != REG || REGNO (operands[1]) != 4)
- {
- rtx r = gen_rtx_REG (Pmode, 4);
- emit_move_insn (r, operands[1]);
- operands[1] = r;
- }
-
- if (GET_CODE (operands[2]) != REG
- || REGNO (operands[2]) != COUNT_REGISTER_REGNUM)
- {
- rtx r = gen_rtx_REG (Pmode, COUNT_REGISTER_REGNUM);
- emit_move_insn (r, operands[2]);
- operands[2] = r;
- }
-
#if TARGET_AIX
- rs6000_emit_eh_toc_restore (operands[1]);
+ rs6000_emit_eh_toc_restore (operands[0]);
#endif
-
- emit_insn (gen_eh_reg_restore ());
-
- if (Pmode == SImode)
- emit_insn (gen_addsi3 (stack_reg, stack_reg, operands[1]));
- else
- emit_insn (gen_adddi3 (stack_reg, stack_reg, operands[1]));
-
- if (Pmode == SImode)
- insn = emit_jump_insn (gen_return_eh_si (operands[2]));
+ if (TARGET_32BIT)
+ emit_insn (gen_eh_set_lr_si (operands[1]));
else
- insn = emit_jump_insn (gen_return_eh_di (operands[2]));
- emit_barrier_after (insn);
-
+ emit_insn (gen_eh_set_lr_di (operands[1]));
+ emit_move_insn (EH_RETURN_STACKADJ_RTX, operands[0]);
DONE;
}")
-; We can't expand this before we know which registers are restored,
-; but we do want to expand it before flow2 because that way flow2 can
-; remove the redundant loads of the link register.
-(define_expand "eh_reg_restore"
- [(unspec_volatile [(const_int 0)] 9)]
- ""
- "")
+; We can't expand this before we know where the link register is stored.
+(define_insn "eh_set_lr_si"
+ [(unspec_volatile [(match_operand:SI 0 "register_operand" "r")] 9)
+ (clobber (match_scratch:SI 1 "=&r"))]
+ "TARGET_32BIT"
+ "#")
+
+(define_insn "eh_set_lr_di"
+ [(unspec_volatile [(match_operand:DI 0 "register_operand" "r")] 9)
+ (clobber (match_scratch:DI 1 "=&r"))]
+ "TARGET_64BIT"
+ "#")
(define_split
- [(unspec_volatile [(const_int 0)] 9)]
- "reload_completed && TARGET_SCHED_PROLOG"
- [(unspec_volatile [(const_int 0)] 9)]
+ [(unspec_volatile [(match_operand 0 "register_operand" "")] 9)
+ (clobber (match_scratch 1 ""))]
+ "reload_completed"
+ [(const_int 0)]
"
{
- rs6000_emit_epilogue (TRUE);
- DONE;
-}")
-
-(define_insn ""
- [(unspec_volatile [(const_int 0)] 9)]
- ""
- "*
-{
- if (TARGET_SCHED_PROLOG)
- return \"#\";
-
- /* This is slightly ugly, but at least we don't have multiple
- copies of the epilogue-emitting code. */
- start_sequence ();
-
- /* A NOTE_INSN_DELETED is supposed to be at the start
- and end of the \"toplevel\" insn chain. */
- emit_note (0, NOTE_INSN_DELETED);
- rs6000_emit_epilogue (TRUE);
- emit_note (0, NOTE_INSN_DELETED);
-
- if (TARGET_DEBUG_STACK)
- debug_rtx_list (get_insns(), 100);
- final (get_insns(), asm_out_file, FALSE, FALSE);
- end_sequence ();
- return \"\";
-}")
+ rs6000_stack_t *info = rs6000_stack_info ();
+ if (info->lr_save_p)
+ {
+ rtx frame_rtx = stack_pointer_rtx;
+ int sp_offset = 0;
+ rtx tmp;
-(define_insn "return_eh_si"
- [(return)
- (use (match_operand:SI 0 "register_operand" "lc"))
- (use (reg:SI 2))
- (use (reg:SI 3))]
- "TARGET_32BIT"
- "b%T0"
- [(set_attr "type" "jmpreg")])
+ if (frame_pointer_needed
+ || current_function_calls_alloca
+ || info->total_size > 32767)
+ {
+ emit_move_insn (operands[1], gen_rtx_MEM (Pmode, frame_rtx));
+ frame_rtx = operands[1];
+ }
+ else if (info->push_p)
+ sp_offset = info->total_size;
-(define_insn "return_eh_di"
- [(return)
- (use (match_operand:DI 0 "register_operand" "lc"))
- (use (reg:DI 2))
- (use (reg:DI 3))]
- "TARGET_64BIT"
- "b%T0"
- [(set_attr "type" "jmpreg")])
+ tmp = plus_constant (frame_rtx, info->lr_save_offset + sp_offset);
+ tmp = gen_rtx_MEM (Pmode, tmp);
+ emit_move_insn (tmp, operands[0]);
+ }
+ else
+ emit_move_insn (gen_rtx_REG (Pmode, LINK_REGISTER_REGNUM), operands[0]);
+ DONE;
+}")