mirror of
git://gcc.gnu.org/git/gcc.git
synced 2024-12-21 14:09:44 +08:00
sparc-protos.h (select_cc_mode): Declare.
* sparc-protos.h (select_cc_mode): Declare. * sparc.c (select_cc_mode): New. Handle unordered compares. (output_cbranch): Always reverse via code change. Handle unordered compares. Factor tests and string updates. * sparc.h (SELECT_CC_MODE): Split out to select_cc_mode. (REVERSIBLE_CC_MODE): Also exclude CCFPmode. * sparc.md (bunordered, bordered): New. (bungt, bunlt, buneq, bunge, bunle): New. From-SVN: r31609
This commit is contained in:
parent
ddcc7cf6c8
commit
e267e17731
gcc
@ -1,3 +1,14 @@
|
||||
2000-01-25 Richard Henderson <rth@cygnus.com>
|
||||
|
||||
* sparc-protos.h (select_cc_mode): Declare.
|
||||
* sparc.c (select_cc_mode): New. Handle unordered compares.
|
||||
(output_cbranch): Always reverse via code change. Handle
|
||||
unordered compares. Factor tests and string updates.
|
||||
* sparc.h (SELECT_CC_MODE): Split out to select_cc_mode.
|
||||
(REVERSIBLE_CC_MODE): Also exclude CCFPmode.
|
||||
* sparc.md (bunordered, bordered): New.
|
||||
(bungt, bunlt, buneq, bunge, bunle): New.
|
||||
|
||||
2000-01-25 Richard Henderson <rth@cygnus.com>
|
||||
|
||||
* dwarf2out.c (dwarf2out_init): Use ggc_add_rtx_varray_root.
|
||||
|
@ -77,6 +77,7 @@ extern void sparc_flat_save_restore PARAMS ((FILE *, const char *,
|
||||
const char *, unsigned long));
|
||||
|
||||
#ifdef RTX_CODE
|
||||
extern enum machine_mode select_cc_mode PARAMS ((enum rtx_code, rtx, rtx));
|
||||
/* Define the function that build the compare insn for scc and bcc. */
|
||||
extern rtx gen_compare_reg PARAMS ((enum rtx_code code, rtx, rtx));
|
||||
extern void sparc_emit_float_lib_cmp PARAMS ((rtx, rtx, enum rtx_code));
|
||||
|
@ -2072,6 +2072,61 @@ sparc_emit_set_const64 (op0, op1)
|
||||
sparc_emit_set_const64_longway (op0, temp, high_bits, low_bits);
|
||||
}
|
||||
|
||||
/* 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,
|
||||
CCFP[E]mode is used. CC_NOOVmode should be used when the first operand
|
||||
is a PLUS, MINUS, NEG, or ASHIFT. CCmode should be used when no special
|
||||
processing is needed. */
|
||||
|
||||
enum machine_mode
|
||||
select_cc_mode (op, x, y)
|
||||
enum rtx_code op;
|
||||
rtx x;
|
||||
rtx y ATTRIBUTE_UNUSED;
|
||||
{
|
||||
if (GET_MODE_CLASS (GET_MODE (x)) == MODE_FLOAT)
|
||||
{
|
||||
switch (op)
|
||||
{
|
||||
case EQ:
|
||||
case NE:
|
||||
case UNORDERED:
|
||||
case ORDERED:
|
||||
case UNLT:
|
||||
case UNLE:
|
||||
case UNGT:
|
||||
case UNGE:
|
||||
case UNEQ:
|
||||
case UNNE:
|
||||
return CCFPmode;
|
||||
|
||||
case LT:
|
||||
case LE:
|
||||
case GT:
|
||||
case GE:
|
||||
return CCFPEmode;
|
||||
|
||||
default:
|
||||
abort ();
|
||||
}
|
||||
}
|
||||
else if (GET_CODE (x) == PLUS || GET_CODE (x) == MINUS
|
||||
|| GET_CODE (x) == NEG || GET_CODE (x) == ASHIFT)
|
||||
{
|
||||
if (TARGET_ARCH64 && GET_MODE (x) == DImode)
|
||||
return CCX_NOOVmode;
|
||||
else
|
||||
return CC_NOOVmode;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (TARGET_ARCH64 && GET_MODE (x) == DImode)
|
||||
return CCXmode;
|
||||
else
|
||||
return CCmode;
|
||||
}
|
||||
}
|
||||
|
||||
/* X and Y are two things to compare using CODE. Emit the compare insn and
|
||||
return the rtx for the cc reg in the proper mode. */
|
||||
|
||||
@ -4583,6 +4638,7 @@ output_cbranch (op, label, reversed, annul, noop, insn)
|
||||
static char v9_xcc_labelno[] = "%%xcc, %lX";
|
||||
static char v9_fcc_labelno[] = "%%fccX, %lY";
|
||||
char *labelno;
|
||||
const char *branch;
|
||||
int labeloff, spaces = 8;
|
||||
|
||||
/* ??? !v9: FP branches cannot be preceded by another floating point insn.
|
||||
@ -4594,147 +4650,158 @@ output_cbranch (op, label, reversed, annul, noop, insn)
|
||||
else
|
||||
string[0] = '\0';
|
||||
|
||||
/* If not floating-point or if EQ or NE, we can just reverse the code. */
|
||||
if (reversed
|
||||
&& ((mode != CCFPmode && mode != CCFPEmode) || code == EQ || code == NE))
|
||||
code = reverse_condition (code), reversed = 0;
|
||||
if (reversed)
|
||||
{
|
||||
/* Reversal of FP compares takes care -- an ordered compare
|
||||
becomes an unordered compare and vice versa. */
|
||||
if (mode == CCFPmode || mode == CCFPEmode)
|
||||
{
|
||||
switch (code)
|
||||
{
|
||||
case EQ:
|
||||
code = NE;
|
||||
break;
|
||||
case NE:
|
||||
code = EQ;
|
||||
break;
|
||||
case GE:
|
||||
code = UNLT;
|
||||
break;
|
||||
case GT:
|
||||
code = UNLE;
|
||||
break;
|
||||
case LE:
|
||||
code = UNGT;
|
||||
break;
|
||||
case LT:
|
||||
code = UNGE;
|
||||
break;
|
||||
case UNORDERED:
|
||||
code = ORDERED;
|
||||
break;
|
||||
case ORDERED:
|
||||
code = UNORDERED;
|
||||
break;
|
||||
case UNGT:
|
||||
code = LE;
|
||||
break;
|
||||
case UNLT:
|
||||
code = GE;
|
||||
break;
|
||||
case UNEQ:
|
||||
/* ??? We don't have a "less or greater" rtx code. */
|
||||
code = UNKNOWN;
|
||||
break;
|
||||
case UNGE:
|
||||
code = LT;
|
||||
break;
|
||||
case UNLE:
|
||||
code = GT;
|
||||
break;
|
||||
|
||||
default:
|
||||
abort ();
|
||||
}
|
||||
}
|
||||
else
|
||||
code = reverse_condition (code);
|
||||
}
|
||||
|
||||
/* Start by writing the branch condition. */
|
||||
switch (code)
|
||||
{
|
||||
case NE:
|
||||
if (mode == CCFPmode || mode == CCFPEmode)
|
||||
{
|
||||
strcat (string, "fbne");
|
||||
spaces -= 4;
|
||||
}
|
||||
else
|
||||
{
|
||||
strcpy (string, "bne");
|
||||
spaces -= 3;
|
||||
}
|
||||
break;
|
||||
if (mode == CCFPmode || mode == CCFPEmode)
|
||||
switch (code)
|
||||
{
|
||||
case NE:
|
||||
branch = "fbne";
|
||||
break;
|
||||
case EQ:
|
||||
branch = "fbe";
|
||||
break;
|
||||
case GE:
|
||||
branch = "fbge";
|
||||
break;
|
||||
case GT:
|
||||
branch = "fbg";
|
||||
break;
|
||||
case LE:
|
||||
branch = "fble";
|
||||
break;
|
||||
case LT:
|
||||
branch = "fbl";
|
||||
break;
|
||||
case UNORDERED:
|
||||
branch = "fbu";
|
||||
break;
|
||||
case ORDERED:
|
||||
branch = "fbo";
|
||||
break;
|
||||
case UNGT:
|
||||
branch = "fbug";
|
||||
break;
|
||||
case UNLT:
|
||||
branch = "fbul";
|
||||
break;
|
||||
case UNEQ:
|
||||
branch = "fbue";
|
||||
break;
|
||||
case UNGE:
|
||||
branch = "fbuge";
|
||||
break;
|
||||
case UNLE:
|
||||
branch = "fbule";
|
||||
break;
|
||||
case UNKNOWN:
|
||||
branch = "fblg";
|
||||
break;
|
||||
|
||||
case EQ:
|
||||
if (mode == CCFPmode || mode == CCFPEmode)
|
||||
{
|
||||
strcat (string, "fbe");
|
||||
spaces -= 3;
|
||||
}
|
||||
else
|
||||
{
|
||||
strcpy (string, "be");
|
||||
spaces -= 2;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
abort ();
|
||||
}
|
||||
else
|
||||
switch (code)
|
||||
{
|
||||
case NE:
|
||||
branch = "bne";
|
||||
break;
|
||||
case EQ:
|
||||
branch = "be";
|
||||
break;
|
||||
case GE:
|
||||
if (mode == CC_NOOVmode)
|
||||
branch = "bpos";
|
||||
else
|
||||
branch = "bge";
|
||||
break;
|
||||
case GT:
|
||||
branch = "bg";
|
||||
break;
|
||||
case LE:
|
||||
branch = "ble";
|
||||
break;
|
||||
case LT:
|
||||
if (mode == CC_NOOVmode)
|
||||
branch = "bneg";
|
||||
else
|
||||
branch = "bl";
|
||||
break;
|
||||
case GEU:
|
||||
branch = "bgeu";
|
||||
break;
|
||||
case GTU:
|
||||
branch = "bgu";
|
||||
break;
|
||||
case LEU:
|
||||
branch = "bleu";
|
||||
break;
|
||||
case LTU:
|
||||
branch = "blu";
|
||||
break;
|
||||
|
||||
case GE:
|
||||
if (mode == CCFPmode || mode == CCFPEmode)
|
||||
{
|
||||
if (reversed)
|
||||
strcat (string, "fbul");
|
||||
else
|
||||
strcat (string, "fbge");
|
||||
spaces -= 4;
|
||||
}
|
||||
else if (mode == CC_NOOVmode)
|
||||
{
|
||||
strcpy (string, "bpos");
|
||||
spaces -= 4;
|
||||
}
|
||||
else
|
||||
{
|
||||
strcpy (string, "bge");
|
||||
spaces -= 3;
|
||||
}
|
||||
break;
|
||||
|
||||
case GT:
|
||||
if (mode == CCFPmode || mode == CCFPEmode)
|
||||
{
|
||||
if (reversed)
|
||||
{
|
||||
strcat (string, "fbule");
|
||||
spaces -= 5;
|
||||
}
|
||||
else
|
||||
{
|
||||
strcat (string, "fbg");
|
||||
spaces -= 3;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
strcpy (string, "bg");
|
||||
spaces -= 2;
|
||||
}
|
||||
break;
|
||||
|
||||
case LE:
|
||||
if (mode == CCFPmode || mode == CCFPEmode)
|
||||
{
|
||||
if (reversed)
|
||||
strcat (string, "fbug");
|
||||
else
|
||||
strcat (string, "fble");
|
||||
spaces -= 4;
|
||||
}
|
||||
else
|
||||
{
|
||||
strcpy (string, "ble");
|
||||
spaces -= 3;
|
||||
}
|
||||
break;
|
||||
|
||||
case LT:
|
||||
if (mode == CCFPmode || mode == CCFPEmode)
|
||||
{
|
||||
if (reversed)
|
||||
{
|
||||
strcat (string, "fbuge");
|
||||
spaces -= 5;
|
||||
}
|
||||
else
|
||||
{
|
||||
strcat (string, "fbl");
|
||||
spaces -= 3;
|
||||
}
|
||||
}
|
||||
else if (mode == CC_NOOVmode)
|
||||
{
|
||||
strcpy (string, "bneg");
|
||||
spaces -= 4;
|
||||
}
|
||||
else
|
||||
{
|
||||
strcpy (string, "bl");
|
||||
spaces -= 2;
|
||||
}
|
||||
break;
|
||||
|
||||
case GEU:
|
||||
strcpy (string, "bgeu");
|
||||
spaces -= 4;
|
||||
break;
|
||||
|
||||
case GTU:
|
||||
strcpy (string, "bgu");
|
||||
spaces -= 3;
|
||||
break;
|
||||
|
||||
case LEU:
|
||||
strcpy (string, "bleu");
|
||||
spaces -= 4;
|
||||
break;
|
||||
|
||||
case LTU:
|
||||
strcpy (string, "blu");
|
||||
spaces -= 3;
|
||||
break;
|
||||
|
||||
default:
|
||||
abort ();
|
||||
}
|
||||
default:
|
||||
abort ();
|
||||
}
|
||||
strcpy (string, branch);
|
||||
spaces -= strlen (branch);
|
||||
|
||||
/* Now add the annulling, the label, and a possible noop. */
|
||||
if (annul)
|
||||
|
@ -2672,18 +2672,12 @@ do { \
|
||||
CCFP[E]mode is used. CC_NOOVmode should be used when the first operand is a
|
||||
PLUS, MINUS, NEG, or ASHIFT. CCmode should be used when no special
|
||||
processing is needed. */
|
||||
#define SELECT_CC_MODE(OP,X,Y) \
|
||||
(GET_MODE_CLASS (GET_MODE (X)) == MODE_FLOAT \
|
||||
? ((OP == EQ || OP == NE) ? CCFPmode : CCFPEmode) \
|
||||
: ((GET_CODE (X) == PLUS || GET_CODE (X) == MINUS \
|
||||
|| GET_CODE (X) == NEG || GET_CODE (X) == ASHIFT) \
|
||||
? (TARGET_ARCH64 && GET_MODE (X) == DImode ? CCX_NOOVmode : CC_NOOVmode) \
|
||||
: ((TARGET_ARCH64 || TARGET_V8PLUS) && GET_MODE (X) == DImode ? CCXmode : CCmode)))
|
||||
#define SELECT_CC_MODE(OP,X,Y) select_cc_mode ((OP), (X), (Y))
|
||||
|
||||
/* Return non-zero if SELECT_CC_MODE will never return MODE for a
|
||||
floating point inequality comparison. */
|
||||
|
||||
#define REVERSIBLE_CC_MODE(MODE) ((MODE) != CCFPEmode)
|
||||
#define REVERSIBLE_CC_MODE(MODE) ((MODE) != CCFPEmode && (MODE) != CCFPmode)
|
||||
|
||||
/* A function address in a call instruction
|
||||
is a byte address (for indexing purposes)
|
||||
|
@ -1794,6 +1794,135 @@
|
||||
"
|
||||
{ operands[1] = gen_compare_reg (LEU, sparc_compare_op0, sparc_compare_op1);
|
||||
}")
|
||||
|
||||
(define_expand "bunordered"
|
||||
[(set (pc)
|
||||
(if_then_else (unordered (match_dup 1) (const_int 0))
|
||||
(label_ref (match_operand 0 "" ""))
|
||||
(pc)))]
|
||||
""
|
||||
"
|
||||
{
|
||||
if (GET_MODE (sparc_compare_op0) == TFmode
|
||||
&& TARGET_ARCH64 && ! TARGET_HARD_QUAD)
|
||||
{
|
||||
sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1,
|
||||
UNORDERED);
|
||||
emit_jump_insn (gen_bne (operands[0]));
|
||||
DONE;
|
||||
}
|
||||
operands[1] = gen_compare_reg (UNORDERED, sparc_compare_op0,
|
||||
sparc_compare_op1);
|
||||
}")
|
||||
|
||||
(define_expand "bordered"
|
||||
[(set (pc)
|
||||
(if_then_else (ordered (match_dup 1) (const_int 0))
|
||||
(label_ref (match_operand 0 "" ""))
|
||||
(pc)))]
|
||||
""
|
||||
"
|
||||
{
|
||||
if (GET_MODE (sparc_compare_op0) == TFmode
|
||||
&& TARGET_ARCH64 && ! TARGET_HARD_QUAD)
|
||||
{
|
||||
sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, ORDERED);
|
||||
emit_jump_insn (gen_bne (operands[0]));
|
||||
DONE;
|
||||
}
|
||||
operands[1] = gen_compare_reg (ORDERED, sparc_compare_op0,
|
||||
sparc_compare_op1);
|
||||
}")
|
||||
|
||||
(define_expand "bungt"
|
||||
[(set (pc)
|
||||
(if_then_else (ungt (match_dup 1) (const_int 0))
|
||||
(label_ref (match_operand 0 "" ""))
|
||||
(pc)))]
|
||||
""
|
||||
"
|
||||
{
|
||||
if (GET_MODE (sparc_compare_op0) == TFmode
|
||||
&& TARGET_ARCH64 && ! TARGET_HARD_QUAD)
|
||||
{
|
||||
sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, UNGT);
|
||||
emit_jump_insn (gen_bne (operands[0]));
|
||||
DONE;
|
||||
}
|
||||
operands[1] = gen_compare_reg (UNGT, sparc_compare_op0, sparc_compare_op1);
|
||||
}")
|
||||
|
||||
(define_expand "bunlt"
|
||||
[(set (pc)
|
||||
(if_then_else (unlt (match_dup 1) (const_int 0))
|
||||
(label_ref (match_operand 0 "" ""))
|
||||
(pc)))]
|
||||
""
|
||||
"
|
||||
{
|
||||
if (GET_MODE (sparc_compare_op0) == TFmode
|
||||
&& TARGET_ARCH64 && ! TARGET_HARD_QUAD)
|
||||
{
|
||||
sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, UNLT);
|
||||
emit_jump_insn (gen_bne (operands[0]));
|
||||
DONE;
|
||||
}
|
||||
operands[1] = gen_compare_reg (UNLT, sparc_compare_op0, sparc_compare_op1);
|
||||
}")
|
||||
|
||||
(define_expand "buneq"
|
||||
[(set (pc)
|
||||
(if_then_else (uneq (match_dup 1) (const_int 0))
|
||||
(label_ref (match_operand 0 "" ""))
|
||||
(pc)))]
|
||||
""
|
||||
"
|
||||
{
|
||||
if (GET_MODE (sparc_compare_op0) == TFmode
|
||||
&& TARGET_ARCH64 && ! TARGET_HARD_QUAD)
|
||||
{
|
||||
sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, UNEQ);
|
||||
emit_jump_insn (gen_bne (operands[0]));
|
||||
DONE;
|
||||
}
|
||||
operands[1] = gen_compare_reg (UNEQ, sparc_compare_op0, sparc_compare_op1);
|
||||
}")
|
||||
|
||||
(define_expand "bunge"
|
||||
[(set (pc)
|
||||
(if_then_else (unge (match_dup 1) (const_int 0))
|
||||
(label_ref (match_operand 0 "" ""))
|
||||
(pc)))]
|
||||
""
|
||||
"
|
||||
{
|
||||
if (GET_MODE (sparc_compare_op0) == TFmode
|
||||
&& TARGET_ARCH64 && ! TARGET_HARD_QUAD)
|
||||
{
|
||||
sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, UNGE);
|
||||
emit_jump_insn (gen_bne (operands[0]));
|
||||
DONE;
|
||||
}
|
||||
operands[1] = gen_compare_reg (UNGE, sparc_compare_op0, sparc_compare_op1);
|
||||
}")
|
||||
|
||||
(define_expand "bunle"
|
||||
[(set (pc)
|
||||
(if_then_else (unle (match_dup 1) (const_int 0))
|
||||
(label_ref (match_operand 0 "" ""))
|
||||
(pc)))]
|
||||
""
|
||||
"
|
||||
{
|
||||
if (GET_MODE (sparc_compare_op0) == TFmode
|
||||
&& TARGET_ARCH64 && ! TARGET_HARD_QUAD)
|
||||
{
|
||||
sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, UNLE);
|
||||
emit_jump_insn (gen_bne (operands[0]));
|
||||
DONE;
|
||||
}
|
||||
operands[1] = gen_compare_reg (UNLE, sparc_compare_op0, sparc_compare_op1);
|
||||
}")
|
||||
|
||||
;; Now match both normal and inverted jump.
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user