Commit 0ba1b2ff by Alan Modra Committed by Alan Modra

rs6000-protos.h (mask_operand_wrap): Declare.

	* config/rs6000/rs6000-protos.h (mask_operand_wrap): Declare.
	(mask64_2_operand): Declare.
	(build_mask64_2_operands): Declare.
	(and64_2_operand): Declare.
	(extract_MB): Declare.
	(extract_ME): Declare.
	* config/rs6000/rs6000.c (mask64_operand): Allow all ones.  Remove
	CONST_DOUBLE code.
	(mask_operand_wrap): New insn predicate.
	(mask64_2_operand): Likewise.
	(and64_2_operand): Likewise.
	(build_mask64_2_operands): New function.
	(extract_MB): New function.
	(extract_ME): New function.
	(print_operand <case m,M>): Use extract_MB and extract_ME.
	(print_operand <case S>): Allow all ones.  Remove CONST_DOUBLE support.
	* config/rs6000/rs6000.h (EXTRA_CONSTRAINT): Add 't'.
	(PREDICATE_CODES): Add and64_2_operand, mask_operand_wrap and
	mask64_2_operand.  Remove CONST_DOUBLE from mask64_operand.
	* config/rs6000/rs6000.md (andsi3_internal3): New
	(andsi3_internal3+1): Enable split for powerpc64.
	(andsi3_internal3+2): New split.
	(andsi3_internal4): Renamed old andsi3_internal3.
	(andsi3_internal5): New.
	(andsi3_internal5+1): Enable split for powerpc64.
	(andsi3_internal5+2): New split.
	(andsi3_internal6, andsi3_internal7, andsi3_internal8): New.
	(anddi3): Handle 't' constraint.
	(anddi3+1): New split.
	(anddi3_internal2): Handle 't' constraint.
	(anddi3_internal2+1): New split.
	(anddi3_internal3): Handle 't' constraint.
	(anddi3_internal3+1): New split.

From-SVN: r55701
parent 95630163
2002-07-24 Alan Modra <amodra@bigpond.net.au> 2002-07-24 Alan Modra <amodra@bigpond.net.au>
* config/rs6000/rs6000-protos.h (mask_operand_wrap): Declare.
(mask64_2_operand): Declare.
(build_mask64_2_operands): Declare.
(and64_2_operand): Declare.
(extract_MB): Declare.
(extract_ME): Declare.
* config/rs6000/rs6000.c (mask64_operand): Allow all ones. Remove
CONST_DOUBLE code.
(mask_operand_wrap): New insn predicate.
(mask64_2_operand): Likewise.
(and64_2_operand): Likewise.
(build_mask64_2_operands): New function.
(extract_MB): New function.
(extract_ME): New function.
(print_operand <case m,M>): Use extract_MB and extract_ME.
(print_operand <case S>): Allow all ones. Remove CONST_DOUBLE support.
* config/rs6000/rs6000.h (EXTRA_CONSTRAINT): Add 't'.
(PREDICATE_CODES): Add and64_2_operand, mask_operand_wrap and
mask64_2_operand. Remove CONST_DOUBLE from mask64_operand.
* config/rs6000/rs6000.md (andsi3_internal3): New
(andsi3_internal3+1): Enable split for powerpc64.
(andsi3_internal3+2): New split.
(andsi3_internal4): Renamed old andsi3_internal3.
(andsi3_internal5): New.
(andsi3_internal5+1): Enable split for powerpc64.
(andsi3_internal5+2): New split.
(andsi3_internal6, andsi3_internal7, andsi3_internal8): New.
(anddi3): Handle 't' constraint.
(anddi3+1): New split.
(anddi3_internal2): Handle 't' constraint.
(anddi3_internal2+1): New split.
(anddi3_internal3): Handle 't' constraint.
(anddi3_internal3+1): New split.
2002-07-24 Alan Modra <amodra@bigpond.net.au>
* config/rs6000/rs6000.md: Remove scratch reg on insns using * config/rs6000/rs6000.md: Remove scratch reg on insns using
addze and similar (plus (comparison r1 r2) r3) insns. Add addze and similar (plus (comparison r1 r2) r3) insns. Add
missing scratch reg in one case. Formatting fixes. missing scratch reg in one case. Formatting fixes.
......
...@@ -64,8 +64,12 @@ extern int non_add_cint_operand PARAMS ((rtx, enum machine_mode)); ...@@ -64,8 +64,12 @@ extern int non_add_cint_operand PARAMS ((rtx, enum machine_mode));
extern int non_logical_cint_operand PARAMS ((rtx, enum machine_mode)); extern int non_logical_cint_operand PARAMS ((rtx, enum machine_mode));
extern int logical_operand PARAMS ((rtx, enum machine_mode)); extern int logical_operand PARAMS ((rtx, enum machine_mode));
extern int mask_operand PARAMS ((rtx, enum machine_mode)); extern int mask_operand PARAMS ((rtx, enum machine_mode));
extern int mask_operand_wrap PARAMS ((rtx, enum machine_mode));
extern int mask64_operand PARAMS ((rtx, enum machine_mode)); extern int mask64_operand PARAMS ((rtx, enum machine_mode));
extern int mask64_2_operand PARAMS ((rtx, enum machine_mode));
extern void build_mask64_2_operands PARAMS ((rtx, rtx *));
extern int and64_operand PARAMS ((rtx, enum machine_mode)); extern int and64_operand PARAMS ((rtx, enum machine_mode));
extern int and64_2_operand PARAMS ((rtx, enum machine_mode));
extern int and_operand PARAMS ((rtx, enum machine_mode)); extern int and_operand PARAMS ((rtx, enum machine_mode));
extern int count_register_operand PARAMS ((rtx, enum machine_mode)); extern int count_register_operand PARAMS ((rtx, enum machine_mode));
extern int xer_operand PARAMS ((rtx, enum machine_mode)); extern int xer_operand PARAMS ((rtx, enum machine_mode));
...@@ -98,6 +102,8 @@ extern int addrs_ok_for_quad_peep PARAMS ((rtx, rtx)); ...@@ -98,6 +102,8 @@ extern int addrs_ok_for_quad_peep PARAMS ((rtx, rtx));
extern enum reg_class secondary_reload_class PARAMS ((enum reg_class, extern enum reg_class secondary_reload_class PARAMS ((enum reg_class,
enum machine_mode, rtx)); enum machine_mode, rtx));
extern int ccr_bit PARAMS ((rtx, int)); extern int ccr_bit PARAMS ((rtx, int));
extern int extract_MB PARAMS ((rtx));
extern int extract_ME PARAMS ((rtx));
extern void print_operand PARAMS ((FILE *, rtx, int)); extern void print_operand PARAMS ((FILE *, rtx, int));
extern void print_operand_address PARAMS ((FILE *, rtx)); extern void print_operand_address PARAMS ((FILE *, rtx));
extern enum rtx_code rs6000_reverse_condition PARAMS ((enum machine_mode, extern enum rtx_code rs6000_reverse_condition PARAMS ((enum machine_mode,
......
...@@ -1496,66 +1496,187 @@ mask_operand (op, mode) ...@@ -1496,66 +1496,187 @@ mask_operand (op, mode)
return c == -lsb; return c == -lsb;
} }
/* Return 1 for the PowerPC64 rlwinm corner case. */
int
mask_operand_wrap (op, mode)
rtx op;
enum machine_mode mode ATTRIBUTE_UNUSED;
{
HOST_WIDE_INT c, lsb;
if (GET_CODE (op) != CONST_INT)
return 0;
c = INTVAL (op);
if ((c & 0x80000001) != 0x80000001)
return 0;
c = ~c;
if (c == 0)
return 0;
lsb = c & -c;
c = ~c;
c &= -lsb;
lsb = c & -c;
return c == -lsb;
}
/* Return 1 if the operand is a constant that is a PowerPC64 mask. /* Return 1 if the operand is a constant that is a PowerPC64 mask.
It is if there are no more than one 1->0 or 0->1 transitions. It is if there are no more than one 1->0 or 0->1 transitions.
Reject all ones and all zeros, since these should have been optimized Reject all zeros, since zero should have been optimized away and
away and confuse the making of MB and ME. */ confuses the making of MB and ME. */
int int
mask64_operand (op, mode) mask64_operand (op, mode)
rtx op; rtx op;
enum machine_mode mode; enum machine_mode mode ATTRIBUTE_UNUSED;
{ {
if (GET_CODE (op) == CONST_INT) if (GET_CODE (op) == CONST_INT)
{ {
HOST_WIDE_INT c, lsb; HOST_WIDE_INT c, lsb;
/* We don't change the number of transitions by inverting,
so make sure we start with the LS bit zero. */
c = INTVAL (op); c = INTVAL (op);
if (c & 1)
c = ~c;
/* Reject all zeros or all ones. */ /* Reject all zeros. */
if (c == 0) if (c == 0)
return 0; return 0;
/* We don't change the number of transitions by inverting,
so make sure we start with the LS bit zero. */
if (c & 1)
c = ~c;
/* Find the transition, and check that all bits above are 1's. */ /* Find the transition, and check that all bits above are 1's. */
lsb = c & -c; lsb = c & -c;
return c == -lsb; return c == -lsb;
} }
else if (GET_CODE (op) == CONST_DOUBLE return 0;
&& (mode == VOIDmode || mode == DImode)) }
{
HOST_WIDE_INT low, high, lsb;
if (HOST_BITS_PER_WIDE_INT < 64) /* Like mask64_operand, but allow up to three transitions. This
high = CONST_DOUBLE_HIGH (op); predicate is used by insn patterns that generate two rldicl or
rldicr machine insns. */
low = CONST_DOUBLE_LOW (op); int
if (low & 1) mask64_2_operand (op, mode)
rtx op;
enum machine_mode mode ATTRIBUTE_UNUSED;
{
if (GET_CODE (op) == CONST_INT)
{ {
if (HOST_BITS_PER_WIDE_INT < 64) HOST_WIDE_INT c, lsb;
high = ~high;
low = ~low;
}
if (low == 0) c = INTVAL (op);
{
if (HOST_BITS_PER_WIDE_INT >= 64 || high == 0) /* Disallow all zeros. */
if (c == 0)
return 0; return 0;
lsb = high & -high; /* We don't change the number of transitions by inverting,
return high == -lsb; so make sure we start with the LS bit zero. */
} if (c & 1)
c = ~c;
lsb = low & -low; /* Find the first transition. */
return low == -lsb && (HOST_BITS_PER_WIDE_INT >= 64 || high == ~0); lsb = c & -c;
/* Invert to look for a second transition. */
c = ~c;
/* Erase first transition. */
c &= -lsb;
/* Find the second transition. */
lsb = c & -c;
/* Invert to look for a third transition. */
c = ~c;
/* Erase second transition. */
c &= -lsb;
/* Find the third transition (if any). */
lsb = c & -c;
/* Match if all the bits above are 1's (or c is zero). */
return c == -lsb;
} }
else
return 0; return 0;
} }
/* Generates shifts and masks for a pair of rldicl or rldicr insns to
implement ANDing by the mask IN. */
void
build_mask64_2_operands (in, out)
rtx in;
rtx *out;
{
#if HOST_BITS_PER_WIDE_INT >= 64
unsigned HOST_WIDE_INT c, lsb, m1, m2;
int shift;
if (GET_CODE (in) != CONST_INT)
abort ();
c = INTVAL (in);
if (c & 1)
{
/* Assume c initially something like 0x00fff000000fffff. The idea
is to rotate the word so that the middle ^^^^^^ group of zeros
is at the MS end and can be cleared with an rldicl mask. We then
rotate back and clear off the MS ^^ group of zeros with a
second rldicl. */
c = ~c; /* c == 0xff000ffffff00000 */
lsb = c & -c; /* lsb == 0x0000000000100000 */
m1 = -lsb; /* m1 == 0xfffffffffff00000 */
c = ~c; /* c == 0x00fff000000fffff */
c &= -lsb; /* c == 0x00fff00000000000 */
lsb = c & -c; /* lsb == 0x0000100000000000 */
c = ~c; /* c == 0xff000fffffffffff */
c &= -lsb; /* c == 0xff00000000000000 */
shift = 0;
while ((lsb >>= 1) != 0)
shift++; /* shift == 44 on exit from loop */
m1 <<= 64 - shift; /* m1 == 0xffffff0000000000 */
m1 = ~m1; /* m1 == 0x000000ffffffffff */
m2 = ~c; /* m2 == 0x00ffffffffffffff */
}
else
{
/* Assume c initially something like 0xff000f0000000000. The idea
is to rotate the word so that the ^^^ middle group of zeros
is at the LS end and can be cleared with an rldicr mask. We then
rotate back and clear off the LS group of ^^^^^^^^^^ zeros with
a second rldicr. */
lsb = c & -c; /* lsb == 0x0000010000000000 */
m2 = -lsb; /* m2 == 0xffffff0000000000 */
c = ~c; /* c == 0x00fff0ffffffffff */
c &= -lsb; /* c == 0x00fff00000000000 */
lsb = c & -c; /* lsb == 0x0000100000000000 */
c = ~c; /* c == 0xff000fffffffffff */
c &= -lsb; /* c == 0xff00000000000000 */
shift = 0;
while ((lsb >>= 1) != 0)
shift++; /* shift == 44 on exit from loop */
m1 = ~c; /* m1 == 0x00ffffffffffffff */
m1 >>= shift; /* m1 == 0x0000000000000fff */
m1 = ~m1; /* m1 == 0xfffffffffffff000 */
}
/* Note that when we only have two 0->1 and 1->0 transitions, one of the
masks will be all 1's. We are guaranteed more than one transition. */
out[0] = GEN_INT (64 - shift);
out[1] = GEN_INT (m1);
out[2] = GEN_INT (shift);
out[3] = GEN_INT (m2);
#else
abort ();
#endif
}
/* Return 1 if the operand is either a non-special register or a constant /* Return 1 if the operand is either a non-special register or a constant
that can be used as the operand of a PowerPC64 logical AND insn. */ that can be used as the operand of a PowerPC64 logical AND insn. */
...@@ -1570,6 +1691,20 @@ and64_operand (op, mode) ...@@ -1570,6 +1691,20 @@ and64_operand (op, mode)
return (logical_operand (op, mode) || mask64_operand (op, mode)); return (logical_operand (op, mode) || mask64_operand (op, mode));
} }
/* Like the above, but also match constants that can be implemented
with two rldicl or rldicr insns. */
int
and64_2_operand (op, mode)
rtx op;
enum machine_mode mode;
{
if (fixed_regs[CR0_REGNO]) /* CR0 not available, don't do andi./andis. */
return gpc_reg_operand (op, mode) || mask64_2_operand (op, mode);
return logical_operand (op, mode) || mask64_2_operand (op, mode);
}
/* Return 1 if the operand is either a non-special register or a /* Return 1 if the operand is either a non-special register or a
constant that can be used as the operand of an RS/6000 logical AND insn. */ constant that can be used as the operand of an RS/6000 logical AND insn. */
...@@ -6056,6 +6191,83 @@ rs6000_init_machine_status () ...@@ -6056,6 +6191,83 @@ rs6000_init_machine_status ()
return ggc_alloc_cleared (sizeof (machine_function)); return ggc_alloc_cleared (sizeof (machine_function));
} }
/* These macros test for integers and extract the low-order bits. */
#define INT_P(X) \
((GET_CODE (X) == CONST_INT || GET_CODE (X) == CONST_DOUBLE) \
&& GET_MODE (X) == VOIDmode)
#define INT_LOWPART(X) \
(GET_CODE (X) == CONST_INT ? INTVAL (X) : CONST_DOUBLE_LOW (X))
int
extract_MB (op)
rtx op;
{
int i;
unsigned long val = INT_LOWPART (op);
/* If the high bit is zero, the value is the first 1 bit we find
from the left. */
if ((val & 0x80000000) == 0)
{
if ((val & 0xffffffff) == 0)
abort ();
i = 1;
while (((val <<= 1) & 0x80000000) == 0)
++i;
return i;
}
/* If the high bit is set and the low bit is not, or the mask is all
1's, the value is zero. */
if ((val & 1) == 0 || (val & 0xffffffff) == 0xffffffff)
return 0;
/* Otherwise we have a wrap-around mask. Look for the first 0 bit
from the right. */
i = 31;
while (((val >>= 1) & 1) != 0)
--i;
return i;
}
int
extract_ME (op)
rtx op;
{
int i;
unsigned long val = INT_LOWPART (op);
/* If the low bit is zero, the value is the first 1 bit we find from
the right. */
if ((val & 1) == 0)
{
if ((val & 0xffffffff) == 0)
abort ();
i = 30;
while (((val >>= 1) & 1) == 0)
--i;
return i;
}
/* If the low bit is set and the high bit is not, or the mask is all
1's, the value is 31. */
if ((val & 0x80000000) == 0 || (val & 0xffffffff) == 0xffffffff)
return 31;
/* Otherwise we have a wrap-around mask. Look for the first 0 bit
from the left. */
i = 0;
while (((val <<= 1) & 0x80000000) != 0)
++i;
return i;
}
/* Print an operand. Recognize special options, documented below. */ /* Print an operand. Recognize special options, documented below. */
#if TARGET_ELF #if TARGET_ELF
...@@ -6074,14 +6286,7 @@ print_operand (file, x, code) ...@@ -6074,14 +6286,7 @@ print_operand (file, x, code)
{ {
int i; int i;
HOST_WIDE_INT val; HOST_WIDE_INT val;
unsigned HOST_WIDE_INT uval;
/* These macros test for integers and extract the low-order bits. */
#define INT_P(X) \
((GET_CODE (X) == CONST_INT || GET_CODE (X) == CONST_DOUBLE) \
&& GET_MODE (X) == VOIDmode)
#define INT_LOWPART(X) \
(GET_CODE (X) == CONST_INT ? INTVAL (X) : CONST_DOUBLE_LOW (X))
switch (code) switch (code)
{ {
...@@ -6297,34 +6502,7 @@ print_operand (file, x, code) ...@@ -6297,34 +6502,7 @@ print_operand (file, x, code)
if (! mask_operand (x, SImode)) if (! mask_operand (x, SImode))
output_operand_lossage ("invalid %%m value"); output_operand_lossage ("invalid %%m value");
val = INT_LOWPART (x); fprintf (file, "%d", extract_MB (x));
/* If the high bit is set and the low bit is not, the value is zero.
If the high bit is zero, the value is the first 1 bit we find from
the left. */
if ((val & 0x80000000) && ((val & 1) == 0))
{
putc ('0', file);
return;
}
else if ((val & 0x80000000) == 0)
{
for (i = 1; i < 32; i++)
if ((val <<= 1) & 0x80000000)
break;
fprintf (file, "%d", i);
return;
}
/* Otherwise, look for the first 0 bit from the right. The result is its
number plus 1. We know the low-order bit is one. */
for (i = 0; i < 32; i++)
if (((val >>= 1) & 1) == 0)
break;
/* If we ended in ...01, i would be 0. The correct value is 31, so
we want 31 - i. */
fprintf (file, "%d", 31 - i);
return; return;
case 'M': case 'M':
...@@ -6332,35 +6510,7 @@ print_operand (file, x, code) ...@@ -6332,35 +6510,7 @@ print_operand (file, x, code)
if (! mask_operand (x, SImode)) if (! mask_operand (x, SImode))
output_operand_lossage ("invalid %%M value"); output_operand_lossage ("invalid %%M value");
val = INT_LOWPART (x); fprintf (file, "%d", extract_ME (x));
/* If the low bit is set and the high bit is not, the value is 31.
If the low bit is zero, the value is the first 1 bit we find from
the right. */
if ((val & 1) && ((val & 0x80000000) == 0))
{
fputs ("31", file);
return;
}
else if ((val & 1) == 0)
{
for (i = 0; i < 32; i++)
if ((val >>= 1) & 1)
break;
/* If we had ....10, i would be 0. The result should be
30, so we need 30 - i. */
fprintf (file, "%d", 30 - i);
return;
}
/* Otherwise, look for the first 0 bit from the left. The result is its
number minus 1. We know the high-order bit is one. */
for (i = 0; i < 32; i++)
if (((val <<= 1) & 0x80000000) == 0)
break;
fprintf (file, "%d", i);
return; return;
/* %n outputs the negative of its operand. */ /* %n outputs the negative of its operand. */
...@@ -6456,68 +6606,31 @@ print_operand (file, x, code) ...@@ -6456,68 +6606,31 @@ print_operand (file, x, code)
return; return;
case 'S': case 'S':
/* PowerPC64 mask position. All 0's and all 1's are excluded. /* PowerPC64 mask position. All 0's is excluded.
CONST_INT 32-bit mask is considered sign-extended so any CONST_INT 32-bit mask is considered sign-extended so any
transition must occur within the CONST_INT, not on the boundary. */ transition must occur within the CONST_INT, not on the boundary. */
if (! mask64_operand (x, DImode)) if (! mask64_operand (x, DImode))
output_operand_lossage ("invalid %%S value"); output_operand_lossage ("invalid %%S value");
val = INT_LOWPART (x); uval = INT_LOWPART (x);
if (val & 1) /* Clear Left */ if (uval & 1) /* Clear Left */
{ {
for (i = 0; i < HOST_BITS_PER_WIDE_INT; i++) uval &= ((unsigned HOST_WIDE_INT) 1 << 63 << 1) - 1;
if (!((val >>= 1) & 1)) i = 64;
break;
#if HOST_BITS_PER_WIDE_INT == 32
if (GET_CODE (x) == CONST_DOUBLE && i == 32)
{
val = CONST_DOUBLE_HIGH (x);
if (val == 0)
--i;
else
for (i = 32; i < 64; i++)
if (!((val >>= 1) & 1))
break;
}
#endif
/* i = index of last set bit from right
mask begins at 63 - i from left */
if (i > 63)
output_operand_lossage ("%%S computed all 1's mask");
fprintf (file, "%d", 63 - i);
return;
} }
else /* Clear Right */ else /* Clear Right */
{ {
for (i = 0; i < HOST_BITS_PER_WIDE_INT; i++) uval = ~uval;
if ((val >>= 1) & 1) uval &= ((unsigned HOST_WIDE_INT) 1 << 63 << 1) - 1;
break; i = 63;
#if HOST_BITS_PER_WIDE_INT == 32
if (GET_CODE (x) == CONST_DOUBLE && i == 32)
{
val = CONST_DOUBLE_HIGH (x);
if (val == (HOST_WIDE_INT) -1)
--i;
else
for (i = 32; i < 64; i++)
if ((val >>= 1) & 1)
break;
} }
#endif while (uval != 0)
/* i = index of last clear bit from right --i, uval >>= 1;
mask ends at 62 - i from left */ if (i < 0)
if (i > 62) abort ();
output_operand_lossage ("%%S computed all 0's mask"); fprintf (file, "%d", i);
fprintf (file, "%d", 62 - i);
return; return;
}
case 'T': case 'T':
/* Print the symbolic name of a branch target register. */ /* Print the symbolic name of a branch target register. */
......
...@@ -1178,7 +1178,8 @@ enum reg_class ...@@ -1178,7 +1178,8 @@ enum reg_class
'R' is for AIX TOC entries. 'R' is for AIX TOC entries.
'S' is a constant that can be placed into a 64-bit mask operand 'S' is a constant that can be placed into a 64-bit mask operand
'T' is a constant that can be placed into a 32-bit mask operand 'T' is a constant that can be placed into a 32-bit mask operand
'U' is for V.4 small data references. */ 'U' is for V.4 small data references.
't' is for AND masks that can be performed by two rldic{l,r} insns. */
#define EXTRA_CONSTRAINT(OP, C) \ #define EXTRA_CONSTRAINT(OP, C) \
((C) == 'Q' ? GET_CODE (OP) == MEM && GET_CODE (XEXP (OP, 0)) == REG \ ((C) == 'Q' ? GET_CODE (OP) == MEM && GET_CODE (XEXP (OP, 0)) == REG \
...@@ -1187,6 +1188,10 @@ enum reg_class ...@@ -1187,6 +1188,10 @@ enum reg_class
: (C) == 'T' ? mask_operand (OP, SImode) \ : (C) == 'T' ? mask_operand (OP, SImode) \
: (C) == 'U' ? (DEFAULT_ABI == ABI_V4 \ : (C) == 'U' ? (DEFAULT_ABI == ABI_V4 \
&& small_data_operand (OP, GET_MODE (OP))) \ && small_data_operand (OP, GET_MODE (OP))) \
: (C) == 't' ? (mask64_2_operand (OP, DImode) \
&& (fixed_regs[CR0_REGNO] \
|| !logical_operand (OP, DImode)) \
&& !mask64_operand (OP, DImode)) \
: 0) : 0)
/* Given an rtx X being reloaded into a reg required to be /* Given an rtx X being reloaded into a reg required to be
...@@ -2749,10 +2754,13 @@ extern char rs6000_reg_names[][8]; /* register names (0 vs. %r0). */ ...@@ -2749,10 +2754,13 @@ extern char rs6000_reg_names[][8]; /* register names (0 vs. %r0). */
{"non_add_cint_operand", {CONST_INT}}, \ {"non_add_cint_operand", {CONST_INT}}, \
{"and_operand", {SUBREG, REG, CONST_INT}}, \ {"and_operand", {SUBREG, REG, CONST_INT}}, \
{"and64_operand", {SUBREG, REG, CONST_INT, CONST_DOUBLE}}, \ {"and64_operand", {SUBREG, REG, CONST_INT, CONST_DOUBLE}}, \
{"and64_2_operand", {SUBREG, REG, CONST_INT}}, \
{"logical_operand", {SUBREG, REG, CONST_INT, CONST_DOUBLE}}, \ {"logical_operand", {SUBREG, REG, CONST_INT, CONST_DOUBLE}}, \
{"non_logical_cint_operand", {CONST_INT, CONST_DOUBLE}}, \ {"non_logical_cint_operand", {CONST_INT, CONST_DOUBLE}}, \
{"mask_operand", {CONST_INT}}, \ {"mask_operand", {CONST_INT}}, \
{"mask64_operand", {CONST_INT, CONST_DOUBLE}}, \ {"mask_operand_wrap", {CONST_INT}}, \
{"mask64_operand", {CONST_INT}}, \
{"mask64_2_operand", {CONST_INT}}, \
{"count_register_operand", {REG}}, \ {"count_register_operand", {REG}}, \
{"xer_operand", {REG}}, \ {"xer_operand", {REG}}, \
{"symbol_ref_operand", {SYMBOL_REF}}, \ {"symbol_ref_operand", {SYMBOL_REF}}, \
......
...@@ -2885,7 +2885,7 @@ ...@@ -2885,7 +2885,7 @@
{andiu.|andis.} %0,%1,%u2") {andiu.|andis.} %0,%1,%u2")
;; Note to set cr's other than cr0 we do the and immediate and then ;; Note to set cr's other than cr0 we do the and immediate and then
;; the test again -- this avoids a mcrf which on the higher end ;; the test again -- this avoids a mfcr which on the higher end
;; machines causes an execution serialization ;; machines causes an execution serialization
(define_insn "*andsi3_internal2" (define_insn "*andsi3_internal2"
...@@ -2908,6 +2908,26 @@ ...@@ -2908,6 +2908,26 @@
[(set_attr "type" "compare,compare,compare,delayed_compare,compare,compare,compare,compare") [(set_attr "type" "compare,compare,compare,delayed_compare,compare,compare,compare,compare")
(set_attr "length" "4,4,4,4,8,8,8,8")]) (set_attr "length" "4,4,4,4,8,8,8,8")])
(define_insn "*andsi3_internal3"
[(set (match_operand:CC 0 "cc_reg_operand" "=x,x,x,x,?y,??y,??y,?y")
(compare:CC (and:SI (match_operand:SI 1 "gpc_reg_operand" "%r,r,r,r,r,r,r,r")
(match_operand:SI 2 "and_operand" "r,K,L,T,r,K,L,T"))
(const_int 0)))
(clobber (match_scratch:SI 3 "=r,r,r,r,r,r,r,r"))
(clobber (match_scratch:CC 4 "=X,X,X,X,X,x,x,X"))]
"TARGET_POWERPC64"
"@
#
{andil.|andi.} %3,%1,%b2
{andiu.|andis.} %3,%1,%u2
{rlinm.|rlwinm.} %3,%1,0,%m2,%M2
#
#
#
#"
[(set_attr "type" "compare,compare,compare,delayed_compare,compare,compare,compare,compare")
(set_attr "length" "8,4,4,4,8,8,8,8")])
(define_split (define_split
[(set (match_operand:CC 0 "cc_reg_not_cr0_operand" "") [(set (match_operand:CC 0 "cc_reg_not_cr0_operand" "")
(compare:CC (and:SI (match_operand:SI 1 "gpc_reg_operand" "") (compare:CC (and:SI (match_operand:SI 1 "gpc_reg_operand" "")
...@@ -2915,7 +2935,7 @@ ...@@ -2915,7 +2935,7 @@
(const_int 0))) (const_int 0)))
(clobber (match_scratch:SI 3 "")) (clobber (match_scratch:SI 3 ""))
(clobber (match_scratch:CC 4 ""))] (clobber (match_scratch:CC 4 ""))]
"! TARGET_POWERPC64 && reload_completed" "reload_completed"
[(parallel [(set (match_dup 3) [(parallel [(set (match_dup 3)
(and:SI (match_dup 1) (and:SI (match_dup 1)
(match_dup 2))) (match_dup 2)))
...@@ -2925,7 +2945,27 @@ ...@@ -2925,7 +2945,27 @@
(const_int 0)))] (const_int 0)))]
"") "")
(define_insn "*andsi3_internal3" ;; We don't have a 32 bit "and. rt,ra,rb" for ppc64. cr is set from the
;; whole 64 bit reg, and we don't know what is in the high 32 bits.
(define_split
[(set (match_operand:CC 0 "cc_reg_operand" "")
(compare:CC (and:SI (match_operand:SI 1 "gpc_reg_operand" "")
(match_operand:SI 2 "gpc_reg_operand" ""))
(const_int 0)))
(clobber (match_scratch:SI 3 ""))
(clobber (match_scratch:CC 4 ""))]
"TARGET_POWERPC64 && reload_completed"
[(parallel [(set (match_dup 3)
(and:SI (match_dup 1)
(match_dup 2)))
(clobber (match_dup 4))])
(set (match_dup 0)
(compare:CC (match_dup 3)
(const_int 0)))]
"")
(define_insn "*andsi3_internal4"
[(set (match_operand:CC 3 "cc_reg_operand" "=x,x,x,x,?y,??y,??y,?y") [(set (match_operand:CC 3 "cc_reg_operand" "=x,x,x,x,?y,??y,??y,?y")
(compare:CC (and:SI (match_operand:SI 1 "gpc_reg_operand" "%r,r,r,r,r,r,r,r") (compare:CC (and:SI (match_operand:SI 1 "gpc_reg_operand" "%r,r,r,r,r,r,r,r")
(match_operand:SI 2 "and_operand" "r,K,L,T,r,K,L,T")) (match_operand:SI 2 "and_operand" "r,K,L,T,r,K,L,T"))
...@@ -2947,6 +2987,28 @@ ...@@ -2947,6 +2987,28 @@
[(set_attr "type" "compare,compare,compare,delayed_compare,compare,compare,compare,compare") [(set_attr "type" "compare,compare,compare,delayed_compare,compare,compare,compare,compare")
(set_attr "length" "4,4,4,4,8,8,8,8")]) (set_attr "length" "4,4,4,4,8,8,8,8")])
(define_insn "*andsi3_internal5"
[(set (match_operand:CC 3 "cc_reg_operand" "=x,x,x,x,?y,??y,??y,?y")
(compare:CC (and:SI (match_operand:SI 1 "gpc_reg_operand" "%r,r,r,r,r,r,r,r")
(match_operand:SI 2 "and_operand" "r,K,L,T,r,K,L,T"))
(const_int 0)))
(set (match_operand:SI 0 "gpc_reg_operand" "=r,r,r,r,r,r,r,r")
(and:SI (match_dup 1)
(match_dup 2)))
(clobber (match_scratch:CC 4 "=X,X,X,X,X,x,x,X"))]
"TARGET_POWERPC64"
"@
#
{andil.|andi.} %0,%1,%b2
{andiu.|andis.} %0,%1,%u2
{rlinm.|rlwinm.} %0,%1,0,%m2,%M2
#
#
#
#"
[(set_attr "type" "compare,compare,compare,delayed_compare,compare,compare,compare,compare")
(set_attr "length" "8,4,4,4,8,8,8,8")])
(define_split (define_split
[(set (match_operand:CC 3 "cc_reg_not_cr0_operand" "") [(set (match_operand:CC 3 "cc_reg_not_cr0_operand" "")
(compare:CC (and:SI (match_operand:SI 1 "gpc_reg_operand" "") (compare:CC (and:SI (match_operand:SI 1 "gpc_reg_operand" "")
...@@ -2956,7 +3018,7 @@ ...@@ -2956,7 +3018,7 @@
(and:SI (match_dup 1) (and:SI (match_dup 1)
(match_dup 2))) (match_dup 2)))
(clobber (match_scratch:CC 4 ""))] (clobber (match_scratch:CC 4 ""))]
"! TARGET_POWERPC64 && reload_completed" "reload_completed"
[(parallel [(set (match_dup 0) [(parallel [(set (match_dup 0)
(and:SI (match_dup 1) (and:SI (match_dup 1)
(match_dup 2))) (match_dup 2)))
...@@ -2966,6 +3028,104 @@ ...@@ -2966,6 +3028,104 @@
(const_int 0)))] (const_int 0)))]
"") "")
(define_split
[(set (match_operand:CC 3 "cc_reg_operand" "")
(compare:CC (and:SI (match_operand:SI 1 "gpc_reg_operand" "")
(match_operand:SI 2 "gpc_reg_operand" ""))
(const_int 0)))
(set (match_operand:SI 0 "gpc_reg_operand" "")
(and:SI (match_dup 1)
(match_dup 2)))
(clobber (match_scratch:CC 4 ""))]
"TARGET_POWERPC64 && reload_completed"
[(parallel [(set (match_dup 0)
(and:SI (match_dup 1)
(match_dup 2)))
(clobber (match_dup 4))])
(set (match_dup 3)
(compare:CC (match_dup 0)
(const_int 0)))]
"")
;; Handle the PowerPC64 rlwinm corner case
(define_insn_and_split "*andsi3_internal6"
[(set (match_operand:SI 0 "gpc_reg_operand" "=r")
(and:SI (match_operand:SI 1 "gpc_reg_operand" "r")
(match_operand:SI 2 "mask_operand_wrap" "i")))]
"TARGET_POWERPC64"
"#"
"TARGET_POWERPC64"
[(set (match_dup 0)
(and:SI (rotate:SI (match_dup 1) (match_dup 3))
(match_dup 4)))
(set (match_dup 0)
(rotate:SI (match_dup 0) (match_dup 5)))]
"
{
int mb = extract_MB (operands[2]);
int me = extract_ME (operands[2]);
operands[3] = GEN_INT (me + 1);
operands[5] = GEN_INT (32 - (me + 1));
operands[4] = GEN_INT (~((HOST_WIDE_INT) -1 << (33 + me - mb)));
}"
[(set_attr "length" "8")])
(define_insn_and_split "*andsi3_internal7"
[(set (match_operand:CC 2 "cc_reg_operand" "=x,?y")
(compare:CC (and:SI (match_operand:SI 0 "gpc_reg_operand" "r,r")
(match_operand:SI 1 "mask_operand_wrap" "i,i"))
(const_int 0)))
(clobber (match_scratch:SI 3 "=r,r"))]
"TARGET_POWERPC64"
"#"
"TARGET_POWERPC64"
[(parallel [(set (match_dup 2)
(compare:CC (and:SI (rotate:SI (match_dup 0) (match_dup 4))
(match_dup 5))
(const_int 0)))
(clobber (match_dup 3))])]
"
{
int mb = extract_MB (operands[1]);
int me = extract_ME (operands[1]);
operands[4] = GEN_INT (me + 1);
operands[5] = GEN_INT (~((HOST_WIDE_INT) -1 << (33 + me - mb)));
}"
[(set_attr "type" "delayed_compare,compare")
(set_attr "length" "4,8")])
(define_insn_and_split "*andsi3_internal8"
[(set (match_operand:CC 3 "cc_reg_operand" "=x,??y")
(compare:CC (and:SI (match_operand:SI 1 "gpc_reg_operand" "r,r")
(match_operand:SI 2 "mask_operand_wrap" "i,i"))
(const_int 0)))
(set (match_operand:SI 0 "gpc_reg_operand" "=r,r")
(and:SI (match_dup 1)
(match_dup 2)))]
"TARGET_POWERPC64"
"#"
"TARGET_POWERPC64"
[(parallel [(set (match_dup 3)
(compare:CC (and:SI (rotate:SI (match_dup 1) (match_dup 4))
(match_dup 5))
(const_int 0)))
(set (match_dup 0)
(and:SI (rotate:SI (match_dup 1) (match_dup 4))
(match_dup 5)))])
(set (match_dup 0)
(rotate:SI (match_dup 0) (match_dup 6)))]
"
{
int mb = extract_MB (operands[2]);
int me = extract_ME (operands[2]);
operands[4] = GEN_INT (me + 1);
operands[6] = GEN_INT (32 - (me + 1));
operands[5] = GEN_INT (~((HOST_WIDE_INT) -1 << (33 + me - mb)));
}"
[(set_attr "type" "delayed_compare,compare")
(set_attr "length" "8,12")])
(define_expand "iorsi3" (define_expand "iorsi3"
[(set (match_operand:SI 0 "gpc_reg_operand" "") [(set (match_operand:SI 0 "gpc_reg_operand" "")
(ior:SI (match_operand:SI 1 "gpc_reg_operand" "") (ior:SI (match_operand:SI 1 "gpc_reg_operand" "")
...@@ -7235,24 +7395,47 @@ ...@@ -7235,24 +7395,47 @@
"") "")
(define_insn "anddi3" (define_insn "anddi3"
[(set (match_operand:DI 0 "gpc_reg_operand" "=r,r,r,r") [(set (match_operand:DI 0 "gpc_reg_operand" "=r,r,r,r,r")
(and:DI (match_operand:DI 1 "gpc_reg_operand" "%r,r,r,r") (and:DI (match_operand:DI 1 "gpc_reg_operand" "%r,r,r,r,r")
(match_operand:DI 2 "and64_operand" "?r,S,K,J"))) (match_operand:DI 2 "and64_2_operand" "?r,S,K,J,t")))
(clobber (match_scratch:CC 3 "=X,X,x,x"))] (clobber (match_scratch:CC 3 "=X,X,x,x,X"))]
"TARGET_POWERPC64" "TARGET_POWERPC64"
"@ "@
and %0,%1,%2 and %0,%1,%2
rldic%B2 %0,%1,0,%S2 rldic%B2 %0,%1,0,%S2
andi. %0,%1,%b2 andi. %0,%1,%b2
andis. %0,%1,%u2") andis. %0,%1,%u2
#"
[(set_attr "length" "4,4,4,4,8")])
(define_split
[(set (match_operand:DI 0 "gpc_reg_operand" "")
(and:DI (match_operand:DI 1 "gpc_reg_operand" "")
(match_operand:DI 2 "mask64_2_operand" "")))
(clobber (match_scratch:CC 3 ""))]
"TARGET_POWERPC64
&& (fixed_regs[CR0_REGNO] || !logical_operand (operands[2], DImode))
&& !mask64_operand (operands[2], DImode)"
[(set (match_dup 0)
(and:DI (rotate:DI (match_dup 1)
(match_dup 4))
(match_dup 5)))
(set (match_dup 0)
(and:DI (rotate:DI (match_dup 0)
(match_dup 6))
(match_dup 7)))]
"
{
build_mask64_2_operands (operands[2], &operands[4]);
}")
(define_insn "*anddi3_internal2" (define_insn "*anddi3_internal2"
[(set (match_operand:CC 0 "cc_reg_operand" "=x,x,x,x,?y,?y,??y,??y") [(set (match_operand:CC 0 "cc_reg_operand" "=x,x,x,x,x,?y,?y,??y,??y,?y")
(compare:CC (and:DI (match_operand:DI 1 "gpc_reg_operand" "%r,r,r,r,r,r,r,") (compare:CC (and:DI (match_operand:DI 1 "gpc_reg_operand" "%r,r,r,r,r,r,r,r,r,r")
(match_operand:DI 2 "and64_operand" "r,S,K,J,r,S,K,J")) (match_operand:DI 2 "and64_2_operand" "r,S,K,J,t,r,S,K,J,t"))
(const_int 0))) (const_int 0)))
(clobber (match_scratch:DI 3 "=r,r,r,r,r,r,r,r")) (clobber (match_scratch:DI 3 "=r,r,r,r,r,r,r,r,r,r"))
(clobber (match_scratch:CC 4 "=X,X,X,X,X,X,x,x"))] (clobber (match_scratch:CC 4 "=X,X,X,X,X,X,X,x,x,X"))]
"TARGET_POWERPC64" "TARGET_POWERPC64"
"@ "@
and. %3,%1,%2 and. %3,%1,%2
...@@ -7262,9 +7445,11 @@ ...@@ -7262,9 +7445,11 @@
# #
# #
# #
#
#
#" #"
[(set_attr "type" "compare,delayed_compare,compare,compare,compare,delayed_compare,compare,compare") [(set_attr "type" "compare,delayed_compare,compare,compare,delayed_compare,compare,compare,compare,compare,compare")
(set_attr "length" "4,4,4,4,8,8,8,8")]) (set_attr "length" "4,4,4,4,8,8,8,8,8,12")])
(define_split (define_split
[(set (match_operand:CC 0 "cc_reg_not_cr0_operand" "") [(set (match_operand:CC 0 "cc_reg_not_cr0_operand" "")
...@@ -7283,14 +7468,39 @@ ...@@ -7283,14 +7468,39 @@
(const_int 0)))] (const_int 0)))]
"") "")
(define_split
[(set (match_operand:CC 0 "cc_reg_operand" "")
(compare:CC (and:DI (match_operand:DI 1 "gpc_reg_operand" "")
(match_operand:DI 2 "mask64_2_operand" ""))
(const_int 0)))
(clobber (match_scratch:DI 3 ""))
(clobber (match_scratch:CC 4 ""))]
"TARGET_POWERPC64 && reload_completed
&& (fixed_regs[CR0_REGNO] || !logical_operand (operands[2], DImode))
&& !mask64_operand (operands[2], DImode)"
[(set (match_dup 3)
(and:DI (rotate:DI (match_dup 1)
(match_dup 5))
(match_dup 6)))
(parallel [(set (match_dup 0)
(compare:CC (and:DI (rotate:DI (match_dup 3)
(match_dup 7))
(match_dup 8))
(const_int 0)))
(clobber (match_dup 3))])]
"
{
build_mask64_2_operands (operands[2], &operands[5]);
}")
(define_insn "*anddi3_internal3" (define_insn "*anddi3_internal3"
[(set (match_operand:CC 3 "cc_reg_operand" "=x,x,x,x,?y,?y,??y,??y") [(set (match_operand:CC 3 "cc_reg_operand" "=x,x,x,x,x,?y,?y,??y,??y,?y")
(compare:CC (and:DI (match_operand:DI 1 "gpc_reg_operand" "%r,r,r,r,r,r,r,r") (compare:CC (and:DI (match_operand:DI 1 "gpc_reg_operand" "%r,r,r,r,r,r,r,r,r,r")
(match_operand:DI 2 "and64_operand" "r,S,K,J,r,S,K,J")) (match_operand:DI 2 "and64_2_operand" "r,S,K,J,t,r,S,K,J,t"))
(const_int 0))) (const_int 0)))
(set (match_operand:DI 0 "gpc_reg_operand" "=r,r,r,r,r,r,r,r") (set (match_operand:DI 0 "gpc_reg_operand" "=r,r,r,r,r,r,r,r,r,r")
(and:DI (match_dup 1) (match_dup 2))) (and:DI (match_dup 1) (match_dup 2)))
(clobber (match_scratch:CC 4 "=X,X,X,X,X,X,x,x"))] (clobber (match_scratch:CC 4 "=X,X,X,X,X,X,X,x,x,X"))]
"TARGET_POWERPC64" "TARGET_POWERPC64"
"@ "@
and. %0,%1,%2 and. %0,%1,%2
...@@ -7300,9 +7510,11 @@ ...@@ -7300,9 +7510,11 @@
# #
# #
# #
#
#
#" #"
[(set_attr "type" "compare,delayed_compare,compare,compare,compare,delayed_compare,compare,compare") [(set_attr "type" "compare,delayed_compare,compare,compare,delayed_compare,compare,compare,compare,compare,compare")
(set_attr "length" "4,4,4,4,8,8,8,8")]) (set_attr "length" "4,4,4,4,8,8,8,8,8,12")])
(define_split (define_split
[(set (match_operand:CC 3 "cc_reg_not_cr0_operand" "") [(set (match_operand:CC 3 "cc_reg_not_cr0_operand" "")
...@@ -7321,6 +7533,35 @@ ...@@ -7321,6 +7533,35 @@
(const_int 0)))] (const_int 0)))]
"") "")
(define_split
[(set (match_operand:CC 3 "cc_reg_operand" "")
(compare:CC (and:DI (match_operand:DI 1 "gpc_reg_operand" "")
(match_operand:DI 2 "mask64_2_operand" ""))
(const_int 0)))
(set (match_operand:DI 0 "gpc_reg_operand" "")
(and:DI (match_dup 1) (match_dup 2)))
(clobber (match_scratch:CC 4 ""))]
"TARGET_POWERPC64 && reload_completed
&& (fixed_regs[CR0_REGNO] || !logical_operand (operands[2], DImode))
&& !mask64_operand (operands[2], DImode)"
[(set (match_dup 0)
(and:DI (rotate:DI (match_dup 1)
(match_dup 5))
(match_dup 6)))
(parallel [(set (match_dup 3)
(compare:CC (and:DI (rotate:DI (match_dup 0)
(match_dup 7))
(match_dup 8))
(const_int 0)))
(set (match_dup 0)
(and:DI (rotate:DI (match_dup 0)
(match_dup 7))
(match_dup 8)))])]
"
{
build_mask64_2_operands (operands[2], &operands[5]);
}")
(define_expand "iordi3" (define_expand "iordi3"
[(set (match_operand:DI 0 "gpc_reg_operand" "") [(set (match_operand:DI 0 "gpc_reg_operand" "")
(ior:DI (match_operand:DI 1 "gpc_reg_operand" "") (ior:DI (match_operand:DI 1 "gpc_reg_operand" "")
......
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