Commit c572e5ba by James Van Artsdalen

*** empty log message ***

From-SVN: r808
parent 5944b57e
...@@ -45,6 +45,7 @@ extern char *strcat (); ...@@ -45,6 +45,7 @@ extern char *strcat ();
char *singlemove_string (); char *singlemove_string ();
char *output_move_const_single (); char *output_move_const_single ();
char *output_fp_cc0_set ();
static char *hi_reg_name[] = HI_REGISTER_NAMES; static char *hi_reg_name[] = HI_REGISTER_NAMES;
static char *qi_reg_name[] = QI_REGISTER_NAMES; static char *qi_reg_name[] = QI_REGISTER_NAMES;
...@@ -66,6 +67,12 @@ enum reg_class regclass_map[FIRST_PSEUDO_REGISTER] = ...@@ -66,6 +67,12 @@ enum reg_class regclass_map[FIRST_PSEUDO_REGISTER] =
INDEX_REGS INDEX_REGS
}; };
/* Test and compare insns in i386.md store the information needed to
generate branch and scc insns here. */
struct rtx_def *i386_compare_op0, *i386_compare_op1;
struct rtx_def *(*i386_compare_gen)(), *(*i386_compare_gen_eq)();
/* Output an insn whose source is a 386 integer register. SRC is the /* Output an insn whose source is a 386 integer register. SRC is the
rtx for the register, and TEMPLATE is the op-code template. SRC may rtx for the register, and TEMPLATE is the op-code template. SRC may
be either SImode or DImode. be either SImode or DImode.
...@@ -1353,6 +1360,8 @@ notice_update_cc (exp) ...@@ -1353,6 +1360,8 @@ notice_update_cc (exp)
CC_STATUS_INIT; CC_STATUS_INIT;
if (! stack_regs_mentioned_p (SET_SRC (XVECEXP (exp, 0, 0)))) if (! stack_regs_mentioned_p (SET_SRC (XVECEXP (exp, 0, 0))))
cc_status.value1 = SET_SRC (XVECEXP (exp, 0, 0)); cc_status.value1 = SET_SRC (XVECEXP (exp, 0, 0));
cc_status.flags |= CC_IN_80387;
return; return;
} }
CC_STATUS_INIT; CC_STATUS_INIT;
...@@ -1679,7 +1688,8 @@ output_fix_trunc (insn, operands) ...@@ -1679,7 +1688,8 @@ output_fix_trunc (insn, operands)
/* Output code for INSN to compare OPERANDS. The two operands might /* Output code for INSN to compare OPERANDS. The two operands might
not have the same mode: one might be within a FLOAT or FLOAT_EXTEND not have the same mode: one might be within a FLOAT or FLOAT_EXTEND
expression. */ expression. If the compare is in mode CCFPEQmode, use an opcode that
will not fault if a qNaN is present. */
char * char *
output_float_compare (insn, operands) output_float_compare (insn, operands)
...@@ -1687,6 +1697,8 @@ output_float_compare (insn, operands) ...@@ -1687,6 +1697,8 @@ output_float_compare (insn, operands)
rtx *operands; rtx *operands;
{ {
int stack_top_dies; int stack_top_dies;
rtx body = XVECEXP (PATTERN (insn), 0, 0);
int unordered_compare = GET_MODE (SET_SRC (body)) == CCFPEQmode;
if (! STACK_TOP_P (operands[0])) if (! STACK_TOP_P (operands[0]))
abort (); abort ();
...@@ -1702,15 +1714,21 @@ output_float_compare (insn, operands) ...@@ -1702,15 +1714,21 @@ output_float_compare (insn, operands)
is also a stack register that dies, then this must be a is also a stack register that dies, then this must be a
`fcompp' float compare */ `fcompp' float compare */
if (unordered_compare)
output_asm_insn ("fucompp", operands);
else
output_asm_insn ("fcompp", operands); output_asm_insn ("fcompp", operands);
} }
else else
{ {
static char buf[100]; static char buf[100];
/* Decide if this is the integer or float compare opcode. */ /* Decide if this is the integer or float compare opcode, or the
unordered float compare. */
if (GET_MODE_CLASS (GET_MODE (operands[1])) == MODE_FLOAT) if (unordered_compare)
strcpy (buf, "fucom");
else if (GET_MODE_CLASS (GET_MODE (operands[1])) == MODE_FLOAT)
strcpy (buf, "fcom"); strcpy (buf, "fcom");
else else
strcpy (buf, "ficom"); strcpy (buf, "ficom");
...@@ -1728,10 +1746,102 @@ output_float_compare (insn, operands) ...@@ -1728,10 +1746,102 @@ output_float_compare (insn, operands)
/* Now retrieve the condition code. */ /* Now retrieve the condition code. */
output_asm_insn (AS1 (fnsts%W2,%2), operands); return output_fp_cc0_set (insn);
}
cc_status.flags |= CC_IN_80387; /* Output opcodes to transfer the results of FP compare or test INSN
from the FPU to the CPU flags. If TARGET_IEEE_FP, ensure that if the
result of the compare or test is unordered, no comparison operator
succeeds except NE. Return an output template, if any. */
char *
output_fp_cc0_set (insn)
rtx insn;
{
rtx xops[3];
rtx unordered_label;
rtx next;
enum rtx_code code;
xops[0] = gen_rtx (REG, HImode, 0);
output_asm_insn (AS1 (fnsts%W0,%0), xops);
if (! TARGET_IEEE_FP)
return "sahf"; return "sahf";
next = next_cc0_user (insn);
if (GET_CODE (next) == JUMP_INSN
&& GET_CODE (PATTERN (next)) == SET
&& SET_DEST (PATTERN (next)) == pc_rtx
&& GET_CODE (SET_SRC (PATTERN (next))) == IF_THEN_ELSE)
{
code = GET_CODE (XEXP (SET_SRC (PATTERN (next)), 0));
}
else if (GET_CODE (PATTERN (next)) == SET)
{
code = GET_CODE (SET_SRC (PATTERN (next)));
}
else
abort ();
xops[0] = gen_rtx (REG, QImode, 0);
switch (code)
{
case GT:
xops[1] = gen_rtx (CONST_INT, VOIDmode, 0x45);
output_asm_insn (AS2 (and%B0,%1,%h0), xops);
/* je label */
break;
case LT:
xops[1] = gen_rtx (CONST_INT, VOIDmode, 0x45);
xops[2] = gen_rtx (CONST_INT, VOIDmode, 0x01);
output_asm_insn (AS2 (and%B0,%1,%h0), xops);
output_asm_insn (AS2 (cmp%B0,%2,%h0), xops);
/* je label */
break;
case GE:
xops[1] = gen_rtx (CONST_INT, VOIDmode, 0x05);
output_asm_insn (AS2 (and%B0,%1,%h0), xops);
/* je label */
break;
case LE:
xops[1] = gen_rtx (CONST_INT, VOIDmode, 0x45);
xops[2] = gen_rtx (CONST_INT, VOIDmode, 0x40);
output_asm_insn (AS2 (and%B0,%1,%h0), xops);
output_asm_insn (AS1 (dec%B0,%h0), xops);
output_asm_insn (AS2 (cmp%B0,%2,%h0), xops);
/* jb label */
break;
case EQ:
xops[1] = gen_rtx (CONST_INT, VOIDmode, 0x45);
xops[2] = gen_rtx (CONST_INT, VOIDmode, 0x40);
output_asm_insn (AS2 (and%B0,%1,%h0), xops);
output_asm_insn (AS2 (cmp%B0,%2,%h0), xops);
/* je label */
break;
case NE:
xops[1] = gen_rtx (CONST_INT, VOIDmode, 0x44);
xops[2] = gen_rtx (CONST_INT, VOIDmode, 0x40);
output_asm_insn (AS2 (and%B0,%1,%h0), xops);
output_asm_insn (AS2 (xor%B0,%2,%h0), xops);
/* jne label */
break;
case GTU:
case LTU:
case GEU:
case LEU:
default:
abort ();
}
RET;
} }
#ifdef HANDLE_PRAGMA #ifdef HANDLE_PRAGMA
......
...@@ -61,6 +61,11 @@ extern int target_flags; ...@@ -61,6 +61,11 @@ extern int target_flags;
Meaningful only on svr3. */ Meaningful only on svr3. */
#define TARGET_SVR3_SHLIB (target_flags & 040) #define TARGET_SVR3_SHLIB (target_flags & 040)
/* Use IEEE floating point comparisons. These handle correctly the cases
where the result of a comparison is unordered. Normally SIGFPE is
generated in such cases, in which case this isn't needed. */
#define TARGET_IEEE_FP (target_flags & 0100)
/* Macro to define tables used to set the flags. /* Macro to define tables used to set the flags.
This is a list in braces of pairs in braces, This is a list in braces of pairs in braces,
each pair being { "NAME", VALUE } each pair being { "NAME", VALUE }
...@@ -79,6 +84,8 @@ extern int target_flags; ...@@ -79,6 +84,8 @@ extern int target_flags;
{ "noregparm", -020}, \ { "noregparm", -020}, \
{ "svr3-shlib", 040}, \ { "svr3-shlib", 040}, \
{ "nosvr3-shlib", -040}, \ { "nosvr3-shlib", -040}, \
{ "ieee-fp", 0100}, \
{ "noieee-fp", -0100}, \
{ "", TARGET_DEFAULT}} { "", TARGET_DEFAULT}}
/* target machine storage layout */ /* target machine storage layout */
...@@ -1146,6 +1153,33 @@ while (0) ...@@ -1146,6 +1153,33 @@ while (0)
: REG_P (RTX) ? 1 \ : REG_P (RTX) ? 1 \
: 2) : 2)
/* Add any extra modes needed to represent the condition code.
For the i386, we need separate modes when floating-point equality
comparisons are being done. */
#define EXTRA_CC_MODES CCFPEQmode
/* Define the names for the modes specified above. */
#define EXTRA_CC_NAMES "CCFPEQ"
/* Given a comparison code (EQ, NE, etc.) and the first operand of a COMPARE,
return the mode to be used for the comparison.
For floating-point equality comparisons, CCFPEQmode should be used.
VOIDmode should be used in all other cases. */
#define SELECT_CC_MODE(OP,X) \
(GET_MODE_CLASS (GET_MODE (X)) == MODE_FLOAT \
&& ((OP) == EQ || (OP) == NE) ? CCFPEQmode : CCmode)
/* Define the information needed to generate branch and scc insns. This is
stored from the compare operation. Note that we can't use "rtx" here
since it hasn't been defined! */
extern struct rtx_def *i386_compare_op0, *i386_compare_op1;
extern struct rtx_def *(*i386_compare_gen)(), *(*i386_compare_gen_eq)();
/* Tell final.c how to eliminate redundant test instructions. */ /* Tell final.c how to eliminate redundant test instructions. */
/* Here we define machine-dependent flags and fields in cc_status /* Here we define machine-dependent flags and fields in cc_status
......
...@@ -62,7 +62,11 @@ ...@@ -62,7 +62,11 @@
;; (set (cc0) (const_int foo)) has no mode information. Such insns will ;; (set (cc0) (const_int foo)) has no mode information. Such insns will
;; be folded while optimizing anyway. ;; be folded while optimizing anyway.
(define_insn "tstsi" ;; All test insns have expanders that save the operands away without
;; actually generating RTL. The bCOND or sCOND (emitted immediately
;; after the tstM or cmp) will actually emit the tstM or cmpM.
(define_insn "tstsi_cc"
[(set (cc0) [(set (cc0)
(match_operand:SI 0 "nonimmediate_operand" "rm"))] (match_operand:SI 0 "nonimmediate_operand" "rm"))]
"" ""
...@@ -75,7 +79,18 @@ ...@@ -75,7 +79,18 @@
return AS2 (cmp%L0,%1,%0); return AS2 (cmp%L0,%1,%0);
}") }")
(define_insn "tsthi" (define_expand "tstsi"
[(set (cc0)
(match_operand:SI 0 "nonimmediate_operand" ""))]
""
"
{
i386_compare_gen = gen_tstsi_cc;
i386_compare_op0 = operands[0];
DONE;
}")
(define_insn "tsthi_cc"
[(set (cc0) [(set (cc0)
(match_operand:HI 0 "nonimmediate_operand" "rm"))] (match_operand:HI 0 "nonimmediate_operand" "rm"))]
"" ""
...@@ -88,7 +103,18 @@ ...@@ -88,7 +103,18 @@
return AS2 (cmp%W0,%1,%0); return AS2 (cmp%W0,%1,%0);
}") }")
(define_insn "tstqi" (define_expand "tsthi"
[(set (cc0)
(match_operand:HI 0 "nonimmediate_operand" ""))]
""
"
{
i386_compare_gen = gen_tsthi_cc;
i386_compare_op0 = operands[0];
DONE;
}")
(define_insn "tstqi_cc"
[(set (cc0) [(set (cc0)
(match_operand:QI 0 "nonimmediate_operand" "qm"))] (match_operand:QI 0 "nonimmediate_operand" "qm"))]
"" ""
...@@ -101,53 +127,89 @@ ...@@ -101,53 +127,89 @@
return AS2 (cmp%B0,%1,%0); return AS2 (cmp%B0,%1,%0);
}") }")
(define_insn "tstsf" (define_expand "tstqi"
[(set (cc0)
(match_operand:QI 0 "nonimmediate_operand" ""))]
""
"
{
i386_compare_gen = gen_tstqi_cc;
i386_compare_op0 = operands[0];
DONE;
}")
(define_insn "tstsf_cc"
[(set (cc0) [(set (cc0)
(match_operand:SF 0 "register_operand" "f")) (match_operand:SF 0 "register_operand" "f"))
(clobber (match_scratch:HI 1 "=a"))] (clobber (match_scratch:HI 1 "=a"))]
"TARGET_80387" "TARGET_80387 && ! TARGET_IEEE_FP"
"* "*
{ {
if (! STACK_TOP_P (operands[0])) if (! STACK_TOP_P (operands[0]))
abort (); abort ();
output_asm_insn (\"ftst\", operands); output_asm_insn (\"ftst\", operands);
cc_status.flags |= CC_IN_80387;
if (find_regno_note (insn, REG_DEAD, FIRST_STACK_REG)) if (find_regno_note (insn, REG_DEAD, FIRST_STACK_REG))
output_asm_insn (AS1 (fstp,%y0), operands); output_asm_insn (AS1 (fstp,%y0), operands);
output_asm_insn (AS1 (fnsts%W1,%1), operands); return (char *) output_fp_cc0_set (insn);
}")
;; Don't generate tstsf if generating IEEE code, since the `ftst' opcode
;; isn't IEEE compliant.
return \"sahf\"; (define_expand "tstsf"
[(parallel [(set (cc0)
(match_operand:SF 0 "register_operand" ""))
(clobber (match_scratch:HI 1 ""))])]
"TARGET_80387 && ! TARGET_IEEE_FP"
"
{
i386_compare_gen = gen_tstsf_cc;
i386_compare_op0 = operands[0];
DONE;
}") }")
(define_insn "tstdf" (define_insn "tstdf_cc"
[(set (cc0) [(set (cc0)
(match_operand:DF 0 "register_operand" "f")) (match_operand:DF 0 "register_operand" "f"))
(clobber (match_scratch:HI 1 "=a"))] (clobber (match_scratch:HI 1 "=a"))]
"TARGET_80387" "TARGET_80387 && ! TARGET_IEEE_FP"
"* "*
{ {
if (! STACK_TOP_P (operands[0])) if (! STACK_TOP_P (operands[0]))
abort (); abort ();
output_asm_insn (\"ftst\", operands); output_asm_insn (\"ftst\", operands);
cc_status.flags |= CC_IN_80387;
if (find_regno_note (insn, REG_DEAD, FIRST_STACK_REG)) if (find_regno_note (insn, REG_DEAD, FIRST_STACK_REG))
output_asm_insn (AS1 (fstp,%y0), operands); output_asm_insn (AS1 (fstp,%y0), operands);
output_asm_insn (AS1 (fnsts%W1,%1), operands); return (char *) output_fp_cc0_set (insn);
}")
;; Don't generate tstdf if generating IEEE code, since the `ftst' opcode
;; isn't IEEE compliant.
return \"sahf\"; (define_expand "tstdf"
[(parallel [(set (cc0)
(match_operand:DF 0 "register_operand" ""))
(clobber (match_scratch:HI 1 ""))])]
"TARGET_80387 && ! TARGET_IEEE_FP"
"
{
i386_compare_gen = gen_tstdf_cc;
i386_compare_op0 = operands[0];
DONE;
}") }")
;;- compare instructions ;;- compare instructions. See comments above tstM patterns about
;; expansion of these insns.
(define_insn "cmpsi" (define_insn "cmpsi_cc"
[(set (cc0) [(set (cc0)
(compare (match_operand:SI 0 "nonimmediate_operand" "mr,ri") (compare:CC (match_operand:SI 0 "nonimmediate_operand" "mr,ri")
(match_operand:SI 1 "general_operand" "ri,mr")))] (match_operand:SI 1 "general_operand" "ri,mr")))]
"" ""
"* "*
...@@ -160,9 +222,22 @@ ...@@ -160,9 +222,22 @@
return AS2 (cmp%L0,%1,%0); return AS2 (cmp%L0,%1,%0);
}") }")
(define_insn "cmphi" (define_expand "cmpsi"
[(set (cc0)
(compare:CC (match_operand:SI 0 "nonimmediate_operand" "")
(match_operand:SI 1 "general_operand" "")))]
""
"
{
i386_compare_gen = gen_cmpsi_cc;
i386_compare_op0 = operands[0];
i386_compare_op1 = operands[1];
DONE;
}")
(define_insn "cmphi_cc"
[(set (cc0) [(set (cc0)
(compare (match_operand:HI 0 "nonimmediate_operand" "mr,ri") (compare:CC (match_operand:HI 0 "nonimmediate_operand" "mr,ri")
(match_operand:HI 1 "general_operand" "ri,mr")))] (match_operand:HI 1 "general_operand" "ri,mr")))]
"" ""
"* "*
...@@ -175,9 +250,22 @@ ...@@ -175,9 +250,22 @@
return AS2 (cmp%W0,%1,%0); return AS2 (cmp%W0,%1,%0);
}") }")
(define_insn "cmpqi" (define_expand "cmphi"
[(set (cc0)
(compare:CC (match_operand:HI 0 "nonimmediate_operand" "")
(match_operand:HI 1 "general_operand" "")))]
""
"
{
i386_compare_gen = gen_cmphi_cc;
i386_compare_op0 = operands[0];
i386_compare_op1 = operands[1];
DONE;
}")
(define_insn "cmpqi_cc"
[(set (cc0) [(set (cc0)
(compare (match_operand:QI 0 "nonimmediate_operand" "qn,mq") (compare:CC (match_operand:QI 0 "nonimmediate_operand" "qn,mq")
(match_operand:QI 1 "general_operand" "qm,nq")))] (match_operand:QI 1 "general_operand" "qm,nq")))]
"" ""
"* "*
...@@ -190,70 +278,143 @@ ...@@ -190,70 +278,143 @@
return AS2 (cmp%B0,%1,%0); return AS2 (cmp%B0,%1,%0);
}") }")
(define_expand "cmpqi"
[(set (cc0)
(compare:CC (match_operand:QI 0 "nonimmediate_operand" "")
(match_operand:QI 1 "general_operand" "")))]
""
"
{
i386_compare_gen = gen_cmpqi_cc;
i386_compare_op0 = operands[0];
i386_compare_op1 = operands[1];
DONE;
}")
;; These implement float point compares. For each of DFmode and ;; These implement float point compares. For each of DFmode and
;; SFmode, there is the normal insn, and an insn where the second operand ;; SFmode, there is the normal insn, and an insn where the second operand
;; is converted to the desired mode. ;; is converted to the desired mode.
(define_expand "cmpdf" (define_insn "cmpdf_cc"
[(parallel [(set (cc0) [(set (cc0)
(compare (match_operand:DF 0 "nonimmediate_operand" "") (compare:CC (match_operand:DF 0 "register_operand" "f")
(match_operand:DF 1 "nonimmediate_operand" ""))) (match_operand:DF 1 "nonimmediate_operand" "fm")))
(clobber (match_scratch:HI 2 ""))])] (clobber (match_scratch:HI 2 "=a"))]
"TARGET_80387" "TARGET_80387"
"") "* return (char *) output_float_compare (insn, operands);")
(define_expand "cmpsf" (define_insn ""
[(parallel [(set (cc0) [(set (cc0)
(compare (match_operand:SF 0 "nonimmediate_operand" "") (compare:CC (match_operand:DF 0 "register_operand" "f,f")
(match_operand:SF 1 "nonimmediate_operand" ""))) (float:DF
(clobber (match_scratch:HI 2 ""))])] (match_operand:SI 1 "nonimmediate_operand" "m,!*r"))))
(clobber (match_scratch:HI 2 "=a,a"))]
"TARGET_80387" "TARGET_80387"
"") "* return (char *) output_float_compare (insn, operands);")
;; The `ble' and `blt' patterns can reverse a compare, so we must allow
;; an immediate operand as operand 0 in the recognizers below.
(define_insn "" (define_insn ""
[(set (cc0) [(set (cc0)
(compare (match_operand:DF 0 "general_operand" "f") (compare:CC (match_operand:DF 0 "register_operand" "f,f")
(match_operand:DF 1 "general_operand" "fm"))) (float_extend:DF
(clobber (match_scratch:HI 2 "=a"))] (match_operand:SF 1 "nonimmediate_operand" "fm,!*r"))))
(clobber (match_scratch:HI 2 "=a,a"))]
"TARGET_80387" "TARGET_80387"
"* return (char *) output_float_compare (insn, operands);") "* return (char *) output_float_compare (insn, operands);")
(define_insn "" (define_insn ""
[(set (cc0) [(set (cc0)
(compare (match_operand:DF 0 "general_operand" "f,f") (compare:CCFPEQ (match_operand:DF 0 "register_operand" "f")
(float:DF (match_operand:SI 1 "general_operand" "m,!*r")))) (match_operand:DF 1 "register_operand" "f")))
(clobber (match_scratch:HI 2 "=a,a"))] (clobber (match_scratch:HI 2 "=a"))]
"TARGET_80387" "TARGET_80387"
"* return (char *) output_float_compare (insn, operands);") "* return (char *) output_float_compare (insn, operands);")
(define_insn "" (define_insn ""
[(set (cc0) [(set (cc0)
(compare (match_operand:DF 0 "general_operand" "f,f") (compare:CCFPEQ (match_operand:DF 0 "register_operand" "f")
(float_extend:DF (float_extend:DF
(match_operand:SF 1 "general_operand" "fm,!*r")))) (match_operand:SF 1 "register_operand" "f"))))
(clobber (match_scratch:HI 2 "=a,a"))] (clobber (match_scratch:HI 2 "=a"))]
"TARGET_80387" "TARGET_80387"
"* return (char *) output_float_compare (insn, operands);") "* return (char *) output_float_compare (insn, operands);")
(define_insn "" (define_insn "cmpsf_cc"
[(set (cc0) [(set (cc0)
(compare (match_operand:SF 0 "general_operand" "f") (compare:CC (match_operand:SF 0 "register_operand" "f")
(match_operand:SF 1 "general_operand" "fm"))) (match_operand:SF 1 "nonimmediate_operand" "fm")))
(clobber (match_scratch:HI 2 "=a"))] (clobber (match_scratch:HI 2 "=a"))]
"TARGET_80387" "TARGET_80387"
"* return (char *) output_float_compare (insn, operands);") "* return (char *) output_float_compare (insn, operands);")
(define_insn "" (define_insn ""
[(set (cc0) [(set (cc0)
(compare (match_operand:SF 0 "general_operand" "f,f") (compare:CC (match_operand:SF 0 "register_operand" "f,f")
(float:SF (match_operand:SI 1 "general_operand" "m,!*r")))) (float:SF
(match_operand:SI 1 "nonimmediate_operand" "m,!*r"))))
(clobber (match_scratch:HI 2 "=a,a"))] (clobber (match_scratch:HI 2 "=a,a"))]
"TARGET_80387" "TARGET_80387"
"* return (char *) output_float_compare (insn, operands);") "* return (char *) output_float_compare (insn, operands);")
(define_insn ""
[(set (cc0)
(compare:CCFPEQ (match_operand:SF 0 "register_operand" "f")
(match_operand:SF 1 "register_operand" "f")))
(clobber (match_scratch:HI 2 "=a"))]
"TARGET_80387"
"* return (char *) output_float_compare (insn, operands);")
(define_expand "cmpdf"
[(set (cc0)
(compare:CC (match_operand:DF 0 "register_operand" "")
(match_operand:DF 1 "nonimmediate_operand" "")))]
"TARGET_80387"
"
{
i386_compare_gen = gen_cmpdf_cc;
i386_compare_gen_eq = gen_cmpdf_ccfpeq;
i386_compare_op0 = operands[0];
i386_compare_op1 = operands[1];
DONE;
}")
(define_expand "cmpsf"
[(set (cc0)
(compare:CC (match_operand:SF 0 "register_operand" "")
(match_operand:SF 1 "nonimmediate_operand" "")))]
"TARGET_80387"
"
{
i386_compare_gen = gen_cmpsf_cc;
i386_compare_gen_eq = gen_cmpsf_ccfpeq;
i386_compare_op0 = operands[0];
i386_compare_op1 = operands[1];
DONE;
}")
(define_expand "cmpdf_ccfpeq"
[(parallel [(set (cc0)
(compare:CCFPEQ (match_operand:DF 0 "register_operand" "")
(match_operand:DF 1 "register_operand" "")))
(clobber (match_scratch:HI 2 ""))])]
"TARGET_80387"
"
{
if (! register_operand (operands[1], DFmode))
operands[1] = copy_to_mode_reg (DFmode, operands[1]);
}")
(define_expand "cmpsf_ccfpeq"
[(parallel [(set (cc0)
(compare:CCFPEQ (match_operand:SF 0 "register_operand" "")
(match_operand:SF 1 "register_operand" "")))
(clobber (match_scratch:HI 2 ""))])]
"TARGET_80387"
"
{
if (! register_operand (operands[1], SFmode))
operands[1] = copy_to_mode_reg (SFmode, operands[1]);
}")
;; logical compare ;; logical compare
(define_insn "" (define_insn ""
...@@ -1454,7 +1615,7 @@ ...@@ -1454,7 +1615,7 @@
return AS3 (imul%L0,%2,%1,%0); return AS3 (imul%L0,%2,%1,%0);
}") }")
(define_insn "mulqihi3_1" (define_insn ""
[(set (match_operand:HI 0 "general_operand" "=a") [(set (match_operand:HI 0 "general_operand" "=a")
(mult:SI (zero_extend:HI (mult:SI (zero_extend:HI
(match_operand:QI 1 "nonimmediate_operand" "%0")) (match_operand:QI 1 "nonimmediate_operand" "%0"))
...@@ -2645,7 +2806,24 @@ ...@@ -2645,7 +2806,24 @@
;; Store-flag instructions. ;; Store-flag instructions.
(define_insn "seq" ;; For all sCOND expanders, also expand the compare or test insn that
;; generates cc0. Generate an equality comparison if `seq' or `sne'.
(define_expand "seq"
[(match_dup 1)
(set (match_operand:QI 0 "general_operand" "")
(eq:QI (cc0) (const_int 0)))]
""
"
{
if (TARGET_IEEE_FP
&& GET_MODE_CLASS (GET_MODE (i386_compare_op0)) == MODE_FLOAT)
operands[1] = (*i386_compare_gen_eq)(i386_compare_op0, i386_compare_op1);
else
operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1);
}")
(define_insn ""
[(set (match_operand:QI 0 "general_operand" "=qm") [(set (match_operand:QI 0 "general_operand" "=qm")
(eq:QI (cc0) (const_int 0)))] (eq:QI (cc0) (const_int 0)))]
"" ""
...@@ -2655,10 +2833,23 @@ ...@@ -2655,10 +2833,23 @@
return AS1 (setnb,%0); return AS1 (setnb,%0);
else else
return AS1 (sete,%0); return AS1 (sete,%0);
} }")
")
(define_expand "sne"
[(match_dup 1)
(set (match_operand:QI 0 "general_operand" "")
(ne:QI (cc0) (const_int 0)))]
""
"
{
if (TARGET_IEEE_FP
&& GET_MODE_CLASS (GET_MODE (i386_compare_op0)) == MODE_FLOAT)
operands[1] = (*i386_compare_gen_eq)(i386_compare_op0, i386_compare_op1);
else
operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1);
}")
(define_insn "sne" (define_insn ""
[(set (match_operand:QI 0 "general_operand" "=qm") [(set (match_operand:QI 0 "general_operand" "=qm")
(ne:QI (cc0) (const_int 0)))] (ne:QI (cc0) (const_int 0)))]
"" ""
...@@ -2671,47 +2862,120 @@ ...@@ -2671,47 +2862,120 @@
} }
") ")
(define_insn "sgt" (define_expand "sgt"
[(match_dup 1)
(set (match_operand:QI 0 "general_operand" "")
(gt:QI (cc0) (const_int 0)))]
""
"operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1);")
(define_insn ""
[(set (match_operand:QI 0 "general_operand" "=qm") [(set (match_operand:QI 0 "general_operand" "=qm")
(gt:QI (cc0) (const_int 0)))] (gt:QI (cc0) (const_int 0)))]
"" ""
"* OUTPUT_JUMP (\"setg %0\", \"seta %0\", 0); ") "*
{
if (TARGET_IEEE_FP && (cc_prev_status.flags & CC_IN_80387))
return AS1 (sete,%0);
OUTPUT_JUMP (\"setg %0\", \"seta %0\", 0);
}")
(define_insn "sgtu" (define_expand "sgtu"
[(match_dup 1)
(set (match_operand:QI 0 "general_operand" "")
(gtu:QI (cc0) (const_int 0)))]
""
"operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1);")
(define_insn ""
[(set (match_operand:QI 0 "general_operand" "=qm") [(set (match_operand:QI 0 "general_operand" "=qm")
(gtu:QI (cc0) (const_int 0)))] (gtu:QI (cc0) (const_int 0)))]
"" ""
"* return \"seta %0\"; ") "* return \"seta %0\"; ")
(define_insn "slt" (define_expand "slt"
[(match_dup 1)
(set (match_operand:QI 0 "general_operand" "")
(lt:QI (cc0) (const_int 0)))]
""
"operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1);")
(define_insn ""
[(set (match_operand:QI 0 "general_operand" "=qm") [(set (match_operand:QI 0 "general_operand" "=qm")
(lt:QI (cc0) (const_int 0)))] (lt:QI (cc0) (const_int 0)))]
"" ""
"* OUTPUT_JUMP (\"setl %0\", \"setb %0\", \"sets %0\"); ") "*
{
if (TARGET_IEEE_FP && (cc_prev_status.flags & CC_IN_80387))
return AS1 (sete,%0);
OUTPUT_JUMP (\"setl %0\", \"setb %0\", \"sets %0\");
}")
(define_expand "sltu"
[(match_dup 1)
(set (match_operand:QI 0 "general_operand" "")
(ltu:QI (cc0) (const_int 0)))]
""
"operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1);")
(define_insn "sltu" (define_insn ""
[(set (match_operand:QI 0 "general_operand" "=qm") [(set (match_operand:QI 0 "general_operand" "=qm")
(ltu:QI (cc0) (const_int 0)))] (ltu:QI (cc0) (const_int 0)))]
"" ""
"* return \"setb %0\"; ") "* return \"setb %0\"; ")
(define_insn "sge" (define_expand "sge"
[(match_dup 1)
(set (match_operand:QI 0 "general_operand" "")
(ge:QI (cc0) (const_int 0)))]
""
"operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1);")
(define_insn ""
[(set (match_operand:QI 0 "general_operand" "=qm") [(set (match_operand:QI 0 "general_operand" "=qm")
(ge:QI (cc0) (const_int 0)))] (ge:QI (cc0) (const_int 0)))]
"" ""
"* OUTPUT_JUMP (\"setge %0\", \"setae %0\", \"setns %0\"); ") "*
{
if (TARGET_IEEE_FP && (cc_prev_status.flags & CC_IN_80387))
return AS1 (sete,%0);
OUTPUT_JUMP (\"setge %0\", \"setae %0\", \"setns %0\");
}")
(define_insn "sgeu" (define_expand "sgeu"
[(match_dup 1)
(set (match_operand:QI 0 "general_operand" "")
(geu:QI (cc0) (const_int 0)))]
""
"operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1);")
(define_insn ""
[(set (match_operand:QI 0 "general_operand" "=qm") [(set (match_operand:QI 0 "general_operand" "=qm")
(geu:QI (cc0) (const_int 0)))] (geu:QI (cc0) (const_int 0)))]
"" ""
"* return \"setae %0\"; ") "* return \"setae %0\"; ")
(define_insn "sle" (define_expand "sle"
[(match_dup 1)
(set (match_operand:QI 0 "general_operand" "")
(le:QI (cc0) (const_int 0)))]
""
"operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1);")
(define_insn ""
[(set (match_operand:QI 0 "general_operand" "=qm") [(set (match_operand:QI 0 "general_operand" "=qm")
(le:QI (cc0) (const_int 0)))] (le:QI (cc0) (const_int 0)))]
"" ""
"* OUTPUT_JUMP (\"setle %0\", \"setbe %0\", 0); ") "*
{
if (TARGET_IEEE_FP && (cc_prev_status.flags & CC_IN_80387))
return AS1 (setb,%0);
OUTPUT_JUMP (\"setle %0\", \"setbe %0\", 0);
}")
(define_insn "sleu" (define_insn "sleu"
[(set (match_operand:QI 0 "general_operand" "=qm") [(set (match_operand:QI 0 "general_operand" "=qm")
...@@ -2722,7 +2986,27 @@ ...@@ -2722,7 +2986,27 @@
;; Basic conditional jump instructions. ;; Basic conditional jump instructions.
;; We ignore the overflow flag for signed branch instructions. ;; We ignore the overflow flag for signed branch instructions.
(define_insn "beq" ;; For all bCOND expanders, also expand the compare or test insn that
;; generates cc0. Generate an equality comparison if `beq' or `bne'.
(define_expand "beq"
[(match_dup 1)
(set (pc)
(if_then_else (eq (cc0)
(const_int 0))
(label_ref (match_operand 0 "" ""))
(pc)))]
""
"
{
if (TARGET_IEEE_FP
&& GET_MODE_CLASS (GET_MODE (i386_compare_op0)) == MODE_FLOAT)
operands[1] = (*i386_compare_gen_eq)(i386_compare_op0, i386_compare_op1);
else
operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1);
}")
(define_insn ""
[(set (pc) [(set (pc)
(if_then_else (eq (cc0) (if_then_else (eq (cc0)
(const_int 0)) (const_int 0))
...@@ -2737,7 +3021,24 @@ ...@@ -2737,7 +3021,24 @@
return \"je %l0\"; return \"je %l0\";
}") }")
(define_insn "bne" (define_expand "bne"
[(match_dup 1)
(set (pc)
(if_then_else (ne (cc0)
(const_int 0))
(label_ref (match_operand 0 "" ""))
(pc)))]
""
"
{
if (TARGET_IEEE_FP
&& GET_MODE_CLASS (GET_MODE (i386_compare_op0)) == MODE_FLOAT)
operands[1] = (*i386_compare_gen_eq)(i386_compare_op0, i386_compare_op1);
else
operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1);
}")
(define_insn ""
[(set (pc) [(set (pc)
(if_then_else (ne (cc0) (if_then_else (ne (cc0)
(const_int 0)) (const_int 0))
...@@ -2752,16 +3053,42 @@ ...@@ -2752,16 +3053,42 @@
return \"jne %l0\"; return \"jne %l0\";
}") }")
(define_insn "bgt" (define_expand "bgt"
[(match_dup 1)
(set (pc)
(if_then_else (gt (cc0)
(const_int 0))
(label_ref (match_operand 0 "" ""))
(pc)))]
""
"operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1);")
(define_insn ""
[(set (pc) [(set (pc)
(if_then_else (gt (cc0) (if_then_else (gt (cc0)
(const_int 0)) (const_int 0))
(label_ref (match_operand 0 "" "")) (label_ref (match_operand 0 "" ""))
(pc)))] (pc)))]
"" ""
"*OUTPUT_JUMP (\"jg %l0\", \"ja %l0\", 0)") "*
{
if (TARGET_IEEE_FP && (cc_prev_status.flags & CC_IN_80387))
return AS1 (je,%l0);
(define_insn "bgtu" OUTPUT_JUMP (\"jg %l0\", \"ja %l0\", 0);
}")
(define_expand "bgtu"
[(match_dup 1)
(set (pc)
(if_then_else (gtu (cc0)
(const_int 0))
(label_ref (match_operand 0 "" ""))
(pc)))]
""
"operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1);")
(define_insn ""
[(set (pc) [(set (pc)
(if_then_else (gtu (cc0) (if_then_else (gtu (cc0)
(const_int 0)) (const_int 0))
...@@ -2770,46 +3097,42 @@ ...@@ -2770,46 +3097,42 @@
"" ""
"ja %l0") "ja %l0")
;; There is no jump insn to check for `<' on IEEE floats.
;; Page 17-80 in the 80387 manual says jb, but that's wrong;
;; jb checks for `not >='. So swap the operands and do `>'.
(define_expand "blt" (define_expand "blt"
[(match_dup 1)
(set (pc)
(if_then_else (lt (cc0)
(const_int 0))
(label_ref (match_operand 0 "" ""))
(pc)))]
""
"operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1);")
(define_insn ""
[(set (pc) [(set (pc)
(if_then_else (lt (cc0) (if_then_else (lt (cc0)
(const_int 0)) (const_int 0))
(label_ref (match_operand 0 "" "")) (label_ref (match_operand 0 "" ""))
(pc)))] (pc)))]
"" ""
" "*
{ {
rtx prev = get_last_insn_anywhere (); if (TARGET_IEEE_FP && (cc_prev_status.flags & CC_IN_80387))
rtx body = PATTERN (prev); return AS1 (je,%l0);
rtx comp;
if (GET_CODE (body) == SET)
comp = SET_SRC (body);
else
comp = SET_SRC (XVECEXP (body, 0, 0));
if (GET_CODE (comp) == COMPARE OUTPUT_JUMP (\"jl %l0\", \"jb %l0\", \"js %l0\");
? GET_MODE_CLASS (GET_MODE (XEXP (comp, 0))) == MODE_FLOAT
: GET_MODE_CLASS (GET_MODE (comp)) == MODE_FLOAT)
{
reverse_comparison (prev);
emit_insn (gen_bgt (operands[0]));
DONE;
}
}") }")
(define_insn "" (define_expand "bltu"
[(set (pc) [(match_dup 1)
(if_then_else (lt (cc0) (set (pc)
(if_then_else (ltu (cc0)
(const_int 0)) (const_int 0))
(label_ref (match_operand 0 "" "")) (label_ref (match_operand 0 "" ""))
(pc)))] (pc)))]
"" ""
"*OUTPUT_JUMP (\"jl %l0\", \"jb %l0\", \"js %l0\")") "operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1);")
(define_insn "bltu" (define_insn ""
[(set (pc) [(set (pc)
(if_then_else (ltu (cc0) (if_then_else (ltu (cc0)
(const_int 0)) (const_int 0))
...@@ -2818,16 +3141,42 @@ ...@@ -2818,16 +3141,42 @@
"" ""
"jb %l0") "jb %l0")
(define_insn "bge" (define_expand "bge"
[(match_dup 1)
(set (pc)
(if_then_else (ge (cc0)
(const_int 0))
(label_ref (match_operand 0 "" ""))
(pc)))]
""
"operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1);")
(define_insn ""
[(set (pc) [(set (pc)
(if_then_else (ge (cc0) (if_then_else (ge (cc0)
(const_int 0)) (const_int 0))
(label_ref (match_operand 0 "" "")) (label_ref (match_operand 0 "" ""))
(pc)))] (pc)))]
"" ""
"*OUTPUT_JUMP (\"jge %l0\", \"jae %l0\", \"jns %l0\")") "*
{
if (TARGET_IEEE_FP && (cc_prev_status.flags & CC_IN_80387))
return AS1 (je,%l0);
OUTPUT_JUMP (\"jge %l0\", \"jae %l0\", \"jns %l0\");
}")
(define_expand "bgeu"
[(match_dup 1)
(set (pc)
(if_then_else (geu (cc0)
(const_int 0))
(label_ref (match_operand 0 "" ""))
(pc)))]
""
"operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1);")
(define_insn "bgeu" (define_insn ""
[(set (pc) [(set (pc)
(if_then_else (geu (cc0) (if_then_else (geu (cc0)
(const_int 0)) (const_int 0))
...@@ -2836,44 +3185,42 @@ ...@@ -2836,44 +3185,42 @@
"" ""
"jae %l0") "jae %l0")
;; See comment on `blt', above.
(define_expand "ble" (define_expand "ble"
[(match_dup 1)
(set (pc)
(if_then_else (le (cc0)
(const_int 0))
(label_ref (match_operand 0 "" ""))
(pc)))]
""
"operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1);")
(define_insn ""
[(set (pc) [(set (pc)
(if_then_else (le (cc0) (if_then_else (le (cc0)
(const_int 0)) (const_int 0))
(label_ref (match_operand 0 "" "")) (label_ref (match_operand 0 "" ""))
(pc)))] (pc)))]
"" ""
" "*
{ {
rtx prev = get_last_insn_anywhere (); if (TARGET_IEEE_FP && (cc_prev_status.flags & CC_IN_80387))
rtx body = PATTERN (prev); return AS1 (jb,%l0);
rtx comp;
if (GET_CODE (body) == SET)
comp = SET_SRC (body);
else
comp = SET_SRC (XVECEXP (body, 0, 0));
if (GET_CODE (comp) == COMPARE OUTPUT_JUMP (\"jle %l0\", \"jbe %l0\", 0);
? GET_MODE_CLASS (GET_MODE (XEXP (comp, 0))) == MODE_FLOAT
: GET_MODE_CLASS (GET_MODE (comp)) == MODE_FLOAT)
{
reverse_comparison (prev);
emit_insn (gen_bge (operands[0]));
DONE;
}
}") }")
(define_insn "" (define_expand "bleu"
[(set (pc) [(match_dup 1)
(if_then_else (le (cc0) (set (pc)
(if_then_else (leu (cc0)
(const_int 0)) (const_int 0))
(label_ref (match_operand 0 "" "")) (label_ref (match_operand 0 "" ""))
(pc)))] (pc)))]
"" ""
"*OUTPUT_JUMP (\"jle %l0\", \"jbe %l0\", 0) ") "operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1);")
(define_insn "bleu" (define_insn ""
[(set (pc) [(set (pc)
(if_then_else (leu (cc0) (if_then_else (leu (cc0)
(const_int 0)) (const_int 0))
...@@ -2921,7 +3268,13 @@ ...@@ -2921,7 +3268,13 @@
(pc) (pc)
(label_ref (match_operand 0 "" ""))))] (label_ref (match_operand 0 "" ""))))]
"" ""
"*OUTPUT_JUMP (\"jle %l0\", \"jbe %l0\", 0) ") "*
{
if (TARGET_IEEE_FP && (cc_prev_status.flags & CC_IN_80387))
return AS1 (jne,%l0);
OUTPUT_JUMP (\"jle %l0\", \"jbe %l0\", 0);
}")
(define_insn "" (define_insn ""
[(set (pc) [(set (pc)
...@@ -2939,8 +3292,13 @@ ...@@ -2939,8 +3292,13 @@
(pc) (pc)
(label_ref (match_operand 0 "" ""))))] (label_ref (match_operand 0 "" ""))))]
"" ""
"*OUTPUT_JUMP (\"jge %l0\", \"jae %l0\", \"jns %l0\") "*
") {
if (TARGET_IEEE_FP && (cc_prev_status.flags & CC_IN_80387))
return AS1 (jne,%l0);
OUTPUT_JUMP (\"jge %l0\", \"jae %l0\", \"jns %l0\");
}")
(define_insn "" (define_insn ""
[(set (pc) [(set (pc)
...@@ -2958,7 +3316,13 @@ ...@@ -2958,7 +3316,13 @@
(pc) (pc)
(label_ref (match_operand 0 "" ""))))] (label_ref (match_operand 0 "" ""))))]
"" ""
"*OUTPUT_JUMP (\"jl %l0\", \"jb %l0\", \"js %l0\")") "*
{
if (TARGET_IEEE_FP && (cc_prev_status.flags & CC_IN_80387))
return AS1 (jne,%l0);
OUTPUT_JUMP (\"jl %l0\", \"jb %l0\", \"js %l0\");
}")
(define_insn "" (define_insn ""
[(set (pc) [(set (pc)
...@@ -2976,7 +3340,13 @@ ...@@ -2976,7 +3340,13 @@
(pc) (pc)
(label_ref (match_operand 0 "" ""))))] (label_ref (match_operand 0 "" ""))))]
"" ""
"*OUTPUT_JUMP (\"jg %l0\", \"ja %l0\", 0)") "*
{
if (TARGET_IEEE_FP && (cc_prev_status.flags & CC_IN_80387))
return AS1 (jae,%l0);
OUTPUT_JUMP (\"jg %l0\", \"ja %l0\", 0);
}")
(define_insn "" (define_insn ""
[(set (pc) [(set (pc)
...@@ -3015,7 +3385,7 @@ ...@@ -3015,7 +3385,7 @@
(minus:SI (match_operand:SI 0 "general_operand" "") (minus:SI (match_operand:SI 0 "general_operand" "")
(match_operand:SI 1 "general_operand" ""))) (match_operand:SI 1 "general_operand" "")))
(set (cc0) (set (cc0)
(compare (match_dup 5) (compare:CC (match_dup 5)
(match_operand:SI 2 "general_operand" ""))) (match_operand:SI 2 "general_operand" "")))
(set (pc) (set (pc)
(if_then_else (gtu (cc0) (if_then_else (gtu (cc0)
...@@ -3358,7 +3728,7 @@ ...@@ -3358,7 +3728,7 @@
(define_expand "cmpstrsi" (define_expand "cmpstrsi"
[(parallel [(set (match_operand:QI 0 "general_operand" "") [(parallel [(set (match_operand:QI 0 "general_operand" "")
(compare (compare:CC
(mem:BLK (match_operand:BLK 1 "general_operand" "")) (mem:BLK (match_operand:BLK 1 "general_operand" ""))
(mem:BLK (match_operand:BLK 2 "general_operand" "")))) (mem:BLK (match_operand:BLK 2 "general_operand" ""))))
(use (match_operand:SI 3 "general_operand" "")) (use (match_operand:SI 3 "general_operand" ""))
...@@ -3383,7 +3753,7 @@ ...@@ -3383,7 +3753,7 @@
(define_insn "" (define_insn ""
[(set (match_operand:QI 0 "general_operand" "=&q") [(set (match_operand:QI 0 "general_operand" "=&q")
(compare (mem:BLK (match_operand:SI 1 "general_operand" "S")) (compare:CC (mem:BLK (match_operand:SI 1 "general_operand" "S"))
(mem:BLK (match_operand:SI 2 "general_operand" "D")))) (mem:BLK (match_operand:SI 2 "general_operand" "D"))))
(use (match_operand:SI 3 "general_operand" "c")) (use (match_operand:SI 3 "general_operand" "c"))
(use (match_operand:SI 4 "immediate_operand" "i")) (use (match_operand:SI 4 "immediate_operand" "i"))
...@@ -3415,7 +3785,7 @@ ...@@ -3415,7 +3785,7 @@
(define_insn "" (define_insn ""
[(set (cc0) [(set (cc0)
(compare (mem:BLK (match_operand:SI 0 "general_operand" "S")) (compare:CC (mem:BLK (match_operand:SI 0 "general_operand" "S"))
(mem:BLK (match_operand:SI 1 "general_operand" "D")))) (mem:BLK (match_operand:SI 1 "general_operand" "D"))))
(use (match_operand:SI 2 "general_operand" "c")) (use (match_operand:SI 2 "general_operand" "c"))
(use (match_operand:SI 3 "immediate_operand" "i")) (use (match_operand:SI 3 "immediate_operand" "i"))
......
...@@ -1516,6 +1516,23 @@ prev_label (insn) ...@@ -1516,6 +1516,23 @@ prev_label (insn)
} }
#ifdef HAVE_cc0 #ifdef HAVE_cc0
/* INSN uses CC0 and is being moved into a delay slot. Set up REG_CC_SETTER
and REG_CC_USER notes so we can find it. */
void
link_cc0_insns (insn)
rtx insn;
{
rtx user = next_nonnote_insn (insn);
if (GET_CODE (user) == INSN && GET_CODE (PATTERN (user)) == SEQUENCE)
user = XVECEXP (PATTERN (user), 0, 0);
REG_NOTES (user) = gen_rtx (INSN_LIST, REG_CC_SETTER, insn,
REG_NOTES (user));
REG_NOTES (insn) = gen_rtx (INSN_LIST, REG_CC_USER, user, REG_NOTES (insn));
}
/* Return the next insn that uses CC0 after INSN, which is assumed to /* Return the next insn that uses CC0 after INSN, which is assumed to
set it. This is the inverse of prev_cc0_setter (i.e., prev_cc0_setter set it. This is the inverse of prev_cc0_setter (i.e., prev_cc0_setter
applied to the result of this function should yield INSN). applied to the result of this function should yield INSN).
......
...@@ -1825,6 +1825,8 @@ compare_for_stack_reg (insn, regstack, pat) ...@@ -1825,6 +1825,8 @@ compare_for_stack_reg (insn, regstack, pat)
the case handled above. In all other cases, emit a separate the case handled above. In all other cases, emit a separate
pop and remove the death note from here. */ pop and remove the death note from here. */
link_cc0_insns (insn);
remove_regno_note (insn, REG_DEAD, REGNO (XEXP (src2_note, 0))); remove_regno_note (insn, REG_DEAD, REGNO (XEXP (src2_note, 0)));
emit_pop_insn (insn, regstack, XEXP (src2_note, 0), emit_pop_insn (insn, regstack, XEXP (src2_note, 0),
......
...@@ -780,25 +780,6 @@ add_to_delay_list (insn, delay_list) ...@@ -780,25 +780,6 @@ add_to_delay_list (insn, delay_list)
return delay_list; return delay_list;
} }
#ifdef HAVE_cc0
/* INSN uses CC0 and is being moved into a delay slot. Set up REG_CC_SETTER
and REG_CC_USER notes so we can find it. */
static void
link_cc0_insns (insn)
rtx insn;
{
rtx user = next_nonnote_insn (insn);
if (GET_CODE (user) == INSN && GET_CODE (PATTERN (user)) == SEQUENCE)
user = XVECEXP (PATTERN (user), 0, 0);
REG_NOTES (user) = gen_rtx (INSN_LIST, REG_CC_SETTER, insn,
REG_NOTES (user));
REG_NOTES (insn) = gen_rtx (INSN_LIST, REG_CC_USER, user, REG_NOTES (insn));
}
#endif
/* Delete INSN from the the delay slot of the insn that it is in. This may /* Delete INSN from the the delay slot of the insn that it is in. This may
produce an insn without anything in its delay slots. */ produce an insn without anything in its delay slots. */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment