enum machine_mode mode ATTRIBUTE_UNUSED;
{
enum rtx_code code = GET_CODE (op);
- return code == EQ || code == LT || code == LE || code == UNORDERED;
+ switch (code)
+ {
+ /* Operations supported directly. */
+ case EQ:
+ case LT:
+ case LE:
+ case UNORDERED:
+ case NE:
+ case UNGE:
+ case UNGT:
+ case ORDERED:
+ return 1;
+ /* These are equivalent to ones above in non-IEEE comparisons. */
+ case UNEQ:
+ case UNLT:
+ case UNLE:
+ case LTGT:
+ case GE:
+ case GT:
+ return !TARGET_IEEE_FP;
+ default:
+ return 0;
+ }
}
/* Return 1 if OP is a valid comparison operator in valid mode. */
int
k -- likewise, print the SImode name of the register.
h -- print the QImode name for a "high" register, either ah, bh, ch or dh.
y -- print "st(0)" instead of "st" as a register.
- m -- print "st(n)" as an mmx register. */
+ m -- print "st(n)" as an mmx register.
+ D -- print condition for SSE cmp instruction.
+ */
void
print_operand (file, x, code)
}
return;
+ case 'D':
+ /* Little bit of braindamage here. The SSE compare instructions
+ does use completely different names for the comparisons that the
+ fp conditional moves. */
+ switch (GET_CODE (x))
+ {
+ case EQ:
+ case UNEQ:
+ fputs ("eq", file);
+ break;
+ case LT:
+ case UNLT:
+ fputs ("lt", file);
+ break;
+ case LE:
+ case UNLE:
+ fputs ("le", file);
+ break;
+ case UNORDERED:
+ fputs ("unord", file);
+ break;
+ case NE:
+ case LTGT:
+ fputs ("neq", file);
+ break;
+ case UNGE:
+ case GE:
+ fputs ("nlt", file);
+ break;
+ case UNGT:
+ case GT:
+ fputs ("nle", file);
+ break;
+ case ORDERED:
+ fputs ("ord", file);
+ break;
+ default:
+ abort ();
+ break;
+ }
+ return;
case 'C':
put_condition_code (GET_CODE (x), GET_MODE (XEXP (x, 0)), 0, 0, file);
return;
[(set_attr "type" "setcc")
(set_attr "mode" "QI")])
+;; The SSE store flag instructions saves 0 or 0xffffffff to the result.
+;; subsequent logical operations are used to imitate conditional moves.
+;; 0xffffffff is NaN, but not in normalized form, so we can't represent
+;; it directly. Futher holding this value in pseudo register might bring
+;; problem in implicit normalization in spill code.
+;; So we don't define FLOAT_STORE_FLAG_VALUE and create these
+;; instructions after reload by splitting the conditional move patterns.
+
+(define_insn "*sse_setccsf"
+ [(set (match_operand:SF 0 "register_operand" "=x")
+ (match_operator:SF 1 "sse_comparison_operator"
+ [(match_operand:SF 2 "register_operand" "0")
+ (match_operand:SF 3 "nonimmediate_operand" "xm")]))]
+ "TARGET_SSE && reload_completed"
+ "cmp%D1ss\\t{%3, %0|%0, %3}"
+ [(set_attr "type" "sse")
+ (set_attr "mode" "SF")])
+
+(define_insn "*sse_setccdf"
+ [(set (match_operand:DF 0 "register_operand" "=Y")
+ (match_operator:DF 1 "sse_comparison_operator"
+ [(match_operand:DF 2 "register_operand" "0")
+ (match_operand:DF 3 "nonimmediate_operand" "Ym")]))]
+ "TARGET_SSE2 && reload_completed"
+ "cmp%D1sd\\t{%3, %0|%0, %3}"
+ [(set_attr "type" "sse")
+ (set_attr "mode" "DF")])
\f
;; Basic conditional jump instructions.
;; We ignore the overflow flag for signed branch instructions.
[(match_operand:V4SF 1 "register_operand" "0")
(match_operand:V4SF 2 "nonimmediate_operand" "x")]))]
"TARGET_SSE"
- "*
-{
- switch (GET_CODE (operands[3]))
- {
- case EQ:
- return \"cmpeqps\\t{%2, %0|%0, %2}\";
- case LT:
- return \"cmpltps\\t{%2, %0|%0, %2}\";
- case LE:
- return \"cmpleps\\t{%2, %0|%0, %2}\";
- case UNORDERED:
- return \"cmpunordps\\t{%2, %0|%0, %2}\";
- default:
- abort ();
- }
-}"
+ "cmp%D3ps\\t{%2, %0|%0, %2}"
[(set_attr "type" "sse")])
(define_insn "maskncmpv4sf3"
[(match_operand:V4SF 1 "register_operand" "0")
(match_operand:V4SF 2 "nonimmediate_operand" "x")])))]
"TARGET_SSE"
- "*
-{
- switch (GET_CODE (operands[3]))
- {
- case EQ:
- return \"cmpneqps\\t{%2, %0|%0, %2}\";
- case LT:
- return \"cmpnltps\\t{%2, %0|%0, %2}\";
- case LE:
- return \"cmpnleps\\t{%2, %0|%0, %2}\";
- case UNORDERED:
- return \"cmpordps\\t{%2, %0|%0, %2}\";
- default:
- abort ();
- }
-}"
+ "cmpn%D3ps\\t{%2, %0|%0, %2}"
[(set_attr "type" "sse")])
(define_insn "vmmaskcmpv4sf3"
(match_dup 1)
(const_int 1)))]
"TARGET_SSE"
- "*
-{
- switch (GET_CODE (operands[3]))
- {
- case EQ:
- return \"cmpeqss\\t{%2, %0|%0, %2}\";
- case LT:
- return \"cmpltss\\t{%2, %0|%0, %2}\";
- case LE:
- return \"cmpless\\t{%2, %0|%0, %2}\";
- case UNORDERED:
- return \"cmpunordss\\t{%2, %0|%0, %2}\";
- default:
- abort ();
- }
-}"
+ "cmp%D3ss\\t{%2, %0|%0, %2}"
[(set_attr "type" "sse")])
(define_insn "vmmaskncmpv4sf3"
(subreg:V4SI (match_dup 1) 0)
(const_int 1)))]
"TARGET_SSE"
- "*
-{
- switch (GET_CODE (operands[3]))
- {
- case EQ:
- return \"cmpneqss\\t{%2, %0|%0, %2}\";
- case LT:
- return \"cmpnltss\\t{%2, %0|%0, %2}\";
- case LE:
- return \"cmpnless\\t{%2, %0|%0, %2}\";
- case UNORDERED:
- return \"cmpordss\\t{%2, %0|%0, %2}\";
- default:
- abort ();
- }
-}"
+ "cmp%D3ss\\t{%2, %0|%0, %2}"
[(set_attr "type" "sse")])
(define_insn "sse_comi"