re PR target/50447 ([avr] Better support of AND, OR, XOR and PLUS with constant integers for 16- and 32-bit values)
PR target/50447 PR target/50465 * config/avr/avr-protos.h (avr_out_bitop): New prototype. (avr_popcount_each_byte): New prototype. * config/avr/avr.c (avr_popcount): New static function. (avr_popcount_each_byte): New function. (avr_out_bitop): New function. (adjust_insn_length): ADJUST_LEN_OUT_BITOP dispatches to avr_out_bitop. Cleanup code. * config/avr/constraints.md (Ca2, Co2, Cx2): New constraints. (Ca4, Co4, Cx4): New constraints. * config/avr/avr.md (adjust_len): Add "out_bitop" insn attribute alternative. (andhi3, iorhi3, xorhi3): Rewrite insns using avr_out_bitop. (andsi3, iorsi3, xorsi3): Ditto. (*iorhi3_clobber, *iorsi3_clobber): Remove insns. From-SVN: r179081
This commit is contained in:
parent
58c1ae3667
commit
6ebe2d6cf6
@ -1,3 +1,22 @@
|
|||||||
|
2011-09-22 Georg-Johann Lay <avr@gjlay.de>
|
||||||
|
|
||||||
|
PR target/50447
|
||||||
|
PR target/50465
|
||||||
|
* config/avr/avr-protos.h (avr_out_bitop): New prototype.
|
||||||
|
(avr_popcount_each_byte): New prototype.
|
||||||
|
* config/avr/avr.c (avr_popcount): New static function.
|
||||||
|
(avr_popcount_each_byte): New function.
|
||||||
|
(avr_out_bitop): New function.
|
||||||
|
(adjust_insn_length): ADJUST_LEN_OUT_BITOP dispatches to
|
||||||
|
avr_out_bitop. Cleanup code.
|
||||||
|
* config/avr/constraints.md (Ca2, Co2, Cx2): New constraints.
|
||||||
|
(Ca4, Co4, Cx4): New constraints.
|
||||||
|
* config/avr/avr.md (adjust_len): Add "out_bitop" insn attribute
|
||||||
|
alternative.
|
||||||
|
(andhi3, iorhi3, xorhi3): Rewrite insns using avr_out_bitop.
|
||||||
|
(andsi3, iorsi3, xorsi3): Ditto.
|
||||||
|
(*iorhi3_clobber, *iorsi3_clobber): Remove insns.
|
||||||
|
|
||||||
2011-09-22 Ira Rosen <ira.rosen@linaro.org>
|
2011-09-22 Ira Rosen <ira.rosen@linaro.org>
|
||||||
|
|
||||||
PR tree-optimization/50451
|
PR tree-optimization/50451
|
||||||
|
@ -81,6 +81,8 @@ extern int avr_epilogue_uses (int regno);
|
|||||||
extern void avr_output_bld (rtx operands[], int bit_nr);
|
extern void avr_output_bld (rtx operands[], int bit_nr);
|
||||||
extern void avr_output_addr_vec_elt (FILE *stream, int value);
|
extern void avr_output_addr_vec_elt (FILE *stream, int value);
|
||||||
extern const char *avr_out_sbxx_branch (rtx insn, rtx operands[]);
|
extern const char *avr_out_sbxx_branch (rtx insn, rtx operands[]);
|
||||||
|
extern const char* avr_out_bitop (rtx, rtx*, int*);
|
||||||
|
extern bool avr_popcount_each_byte (rtx, int, int);
|
||||||
|
|
||||||
extern int extra_constraint_Q (rtx x);
|
extern int extra_constraint_Q (rtx x);
|
||||||
extern int adjust_insn_length (rtx insn, int len);
|
extern int adjust_insn_length (rtx insn, int len);
|
||||||
|
@ -303,6 +303,46 @@ avr_replace_prefix (const char *old_str,
|
|||||||
return (const char*) new_str;
|
return (const char*) new_str;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Custom function to count number of set bits. */
|
||||||
|
|
||||||
|
static inline int
|
||||||
|
avr_popcount (unsigned int val)
|
||||||
|
{
|
||||||
|
int pop = 0;
|
||||||
|
|
||||||
|
while (val)
|
||||||
|
{
|
||||||
|
val &= val-1;
|
||||||
|
pop++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return pop;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Constraint helper function. XVAL is an CONST_INT. Return true if the least
|
||||||
|
significant N_BYTES bytes of XVAL all have a popcount in POP_MASK and false,
|
||||||
|
otherwise. POP_MASK represents a subset of integers which contains an
|
||||||
|
integer N iff bit N of POP_MASK is set. */
|
||||||
|
|
||||||
|
bool
|
||||||
|
avr_popcount_each_byte (rtx xval, int n_bytes, int pop_mask)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < n_bytes; i++)
|
||||||
|
{
|
||||||
|
rtx xval8 = simplify_gen_subreg (QImode, xval, SImode, i);
|
||||||
|
unsigned int val8 = UINTVAL (xval8) & GET_MODE_MASK (QImode);
|
||||||
|
|
||||||
|
if (0 == (pop_mask & (1 << avr_popcount (val8))))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
avr_option_override (void)
|
avr_option_override (void)
|
||||||
{
|
{
|
||||||
@ -4462,6 +4502,157 @@ lshrsi3_out (rtx insn, rtx operands[], int *len)
|
|||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Output bit operation (IOR, AND, XOR) with register XOP[0] and compile
|
||||||
|
time constant XOP[2]:
|
||||||
|
|
||||||
|
XOP[0] = XOP[0] <op> XOP[2]
|
||||||
|
|
||||||
|
and return "". If PLEN == NULL, print assembler instructions to perform the
|
||||||
|
operation; otherwise, set *PLEN to the length of the instruction sequence
|
||||||
|
(in words) printed with PLEN == NULL. XOP[3] is either an 8-bit clobber
|
||||||
|
register or SCRATCH if no clobber register is needed for the operation. */
|
||||||
|
|
||||||
|
const char*
|
||||||
|
avr_out_bitop (rtx insn, rtx *xop, int *plen)
|
||||||
|
{
|
||||||
|
/* CODE and MODE of the operation. */
|
||||||
|
enum rtx_code code = GET_CODE (SET_SRC (single_set (insn)));
|
||||||
|
enum machine_mode mode = GET_MODE (xop[0]);
|
||||||
|
|
||||||
|
/* Number of bytes to operate on. */
|
||||||
|
int i, n_bytes = GET_MODE_SIZE (mode);
|
||||||
|
|
||||||
|
/* Value of T-flag (0 or 1) or -1 if unknow. */
|
||||||
|
int set_t = -1;
|
||||||
|
|
||||||
|
/* Value (0..0xff) held in clobber register op[3] or -1 if unknown. */
|
||||||
|
int clobber_val = -1;
|
||||||
|
|
||||||
|
/* op[0]: 8-bit destination register
|
||||||
|
op[1]: 8-bit const int
|
||||||
|
op[2]: 8-bit clobber register or SCRATCH
|
||||||
|
op[3]: 8-bit register containing 0xff or NULL_RTX */
|
||||||
|
rtx op[4];
|
||||||
|
|
||||||
|
op[2] = xop[3];
|
||||||
|
op[3] = NULL_RTX;
|
||||||
|
|
||||||
|
if (plen)
|
||||||
|
*plen = 0;
|
||||||
|
|
||||||
|
for (i = 0; i < n_bytes; i++)
|
||||||
|
{
|
||||||
|
/* We operate byte-wise on the destination. */
|
||||||
|
rtx reg8 = simplify_gen_subreg (QImode, xop[0], mode, i);
|
||||||
|
rtx xval8 = simplify_gen_subreg (QImode, xop[2], mode, i);
|
||||||
|
|
||||||
|
/* 8-bit value to operate with this byte. */
|
||||||
|
unsigned int val8 = UINTVAL (xval8) & GET_MODE_MASK (QImode);
|
||||||
|
|
||||||
|
/* Number of bits set in the current byte of the constant. */
|
||||||
|
int pop8 = avr_popcount (val8);
|
||||||
|
|
||||||
|
/* Registers R16..R31 can operate with immediate. */
|
||||||
|
bool ld_reg_p = test_hard_reg_class (LD_REGS, reg8);
|
||||||
|
|
||||||
|
op[0] = reg8;
|
||||||
|
op[1] = GEN_INT (val8);
|
||||||
|
|
||||||
|
switch (code)
|
||||||
|
{
|
||||||
|
case IOR:
|
||||||
|
|
||||||
|
if (0 == pop8)
|
||||||
|
continue;
|
||||||
|
else if (ld_reg_p)
|
||||||
|
avr_asm_len ("ori %0,%1", op, plen, 1);
|
||||||
|
else if (1 == pop8)
|
||||||
|
{
|
||||||
|
if (set_t != 1)
|
||||||
|
avr_asm_len ("set", op, plen, 1);
|
||||||
|
set_t = 1;
|
||||||
|
|
||||||
|
op[1] = GEN_INT (exact_log2 (val8));
|
||||||
|
avr_asm_len ("bld %0,%1", op, plen, 1);
|
||||||
|
}
|
||||||
|
else if (8 == pop8)
|
||||||
|
{
|
||||||
|
if (op[3] != NULL_RTX)
|
||||||
|
avr_asm_len ("mov %0,%3", op, plen, 1);
|
||||||
|
else
|
||||||
|
avr_asm_len ("clr %0" CR_TAB
|
||||||
|
"dec %0", op, plen, 2);
|
||||||
|
|
||||||
|
op[3] = op[0];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (clobber_val != (int) val8)
|
||||||
|
avr_asm_len ("ldi %2,%1", op, plen, 1);
|
||||||
|
clobber_val = (int) val8;
|
||||||
|
|
||||||
|
avr_asm_len ("or %0,%2", op, plen, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
continue; /* IOR */
|
||||||
|
|
||||||
|
case AND:
|
||||||
|
|
||||||
|
if (8 == pop8)
|
||||||
|
continue;
|
||||||
|
else if (0 == pop8)
|
||||||
|
avr_asm_len ("clr %0", op, plen, 1);
|
||||||
|
else if (ld_reg_p)
|
||||||
|
avr_asm_len ("andi %0,%1", op, plen, 1);
|
||||||
|
else if (7 == pop8)
|
||||||
|
{
|
||||||
|
if (set_t != 0)
|
||||||
|
avr_asm_len ("clt", op, plen, 1);
|
||||||
|
set_t = 0;
|
||||||
|
|
||||||
|
op[1] = GEN_INT (exact_log2 (GET_MODE_MASK (QImode) & ~val8));
|
||||||
|
avr_asm_len ("bld %0,%1", op, plen, 1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (clobber_val != (int) val8)
|
||||||
|
avr_asm_len ("ldi %2,%1", op, plen, 1);
|
||||||
|
clobber_val = (int) val8;
|
||||||
|
|
||||||
|
avr_asm_len ("and %0,%2", op, plen, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
continue; /* AND */
|
||||||
|
|
||||||
|
case XOR:
|
||||||
|
|
||||||
|
if (0 == pop8)
|
||||||
|
continue;
|
||||||
|
else if (8 == pop8)
|
||||||
|
avr_asm_len ("com %0", op, plen, 1);
|
||||||
|
else if (ld_reg_p && val8 == (1 << 7))
|
||||||
|
avr_asm_len ("subi %0,%1", op, plen, 1);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (clobber_val != (int) val8)
|
||||||
|
avr_asm_len ("ldi %2,%1", op, plen, 1);
|
||||||
|
clobber_val = (int) val8;
|
||||||
|
|
||||||
|
avr_asm_len ("eor %0,%2", op, plen, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
continue; /* XOR */
|
||||||
|
|
||||||
|
default:
|
||||||
|
/* Unknown rtx_code */
|
||||||
|
gcc_unreachable();
|
||||||
|
}
|
||||||
|
} /* for all sub-bytes */
|
||||||
|
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
/* Create RTL split patterns for byte sized rotate expressions. This
|
/* Create RTL split patterns for byte sized rotate expressions. This
|
||||||
produces a series of move instructions and considers overlap situations.
|
produces a series of move instructions and considers overlap situations.
|
||||||
Overlapping non-HImode operands need a scratch register. */
|
Overlapping non-HImode operands need a scratch register. */
|
||||||
@ -4656,6 +4847,10 @@ adjust_insn_length (rtx insn, int len)
|
|||||||
output_reload_insisf (insn, op, op[2], &len);
|
output_reload_insisf (insn, op, op[2], &len);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case ADJUST_LEN_OUT_BITOP:
|
||||||
|
avr_out_bitop (insn, op, &len);
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
gcc_unreachable();
|
gcc_unreachable();
|
||||||
}
|
}
|
||||||
@ -4700,36 +4895,6 @@ adjust_insn_length (rtx insn, int len)
|
|||||||
default: break;
|
default: break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (GET_CODE (op[1]) == AND)
|
|
||||||
{
|
|
||||||
if (GET_CODE (XEXP (op[1],1)) == CONST_INT)
|
|
||||||
{
|
|
||||||
HOST_WIDE_INT mask = INTVAL (XEXP (op[1],1));
|
|
||||||
if (GET_MODE (op[1]) == SImode)
|
|
||||||
len = (((mask & 0xff) != 0xff)
|
|
||||||
+ ((mask & 0xff00) != 0xff00)
|
|
||||||
+ ((mask & 0xff0000L) != 0xff0000L)
|
|
||||||
+ ((mask & 0xff000000L) != 0xff000000L));
|
|
||||||
else if (GET_MODE (op[1]) == HImode)
|
|
||||||
len = (((mask & 0xff) != 0xff)
|
|
||||||
+ ((mask & 0xff00) != 0xff00));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (GET_CODE (op[1]) == IOR)
|
|
||||||
{
|
|
||||||
if (GET_CODE (XEXP (op[1],1)) == CONST_INT)
|
|
||||||
{
|
|
||||||
HOST_WIDE_INT mask = INTVAL (XEXP (op[1],1));
|
|
||||||
if (GET_MODE (op[1]) == SImode)
|
|
||||||
len = (((mask & 0xff) != 0)
|
|
||||||
+ ((mask & 0xff00) != 0)
|
|
||||||
+ ((mask & 0xff0000L) != 0)
|
|
||||||
+ ((mask & 0xff000000L) != 0));
|
|
||||||
else if (GET_MODE (op[1]) == HImode)
|
|
||||||
len = (((mask & 0xff) != 0)
|
|
||||||
+ ((mask & 0xff00) != 0));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
set = single_set (insn);
|
set = single_set (insn);
|
||||||
if (set)
|
if (set)
|
||||||
|
@ -136,7 +136,7 @@
|
|||||||
;; Otherwise do special processing depending on the attribute.
|
;; Otherwise do special processing depending on the attribute.
|
||||||
|
|
||||||
(define_attr "adjust_len"
|
(define_attr "adjust_len"
|
||||||
"yes,no,reload_in32"
|
"yes,no,reload_in32,out_bitop"
|
||||||
(const_string "yes"))
|
(const_string "yes"))
|
||||||
|
|
||||||
;; Define mode iterators
|
;; Define mode iterators
|
||||||
@ -2238,71 +2238,41 @@
|
|||||||
(set_attr "cc" "set_zn,set_zn")])
|
(set_attr "cc" "set_zn,set_zn")])
|
||||||
|
|
||||||
(define_insn "andhi3"
|
(define_insn "andhi3"
|
||||||
[(set (match_operand:HI 0 "register_operand" "=r,d,r")
|
[(set (match_operand:HI 0 "register_operand" "=r,d,d,r ,r")
|
||||||
(and:HI (match_operand:HI 1 "register_operand" "%0,0,0")
|
(and:HI (match_operand:HI 1 "register_operand" "%0,0,0,0 ,0")
|
||||||
(match_operand:HI 2 "nonmemory_operand" "r,i,M")))
|
(match_operand:HI 2 "nonmemory_operand" "r,s,n,Ca2,n")))
|
||||||
(clobber (match_scratch:QI 3 "=X,X,&d"))]
|
(clobber (match_scratch:QI 3 "=X,X,X,X ,&d"))]
|
||||||
""
|
""
|
||||||
{
|
{
|
||||||
if (which_alternative==0)
|
if (which_alternative == 0)
|
||||||
return ("and %A0,%A2" CR_TAB
|
return "and %A0,%A2\;and %B0,%B2";
|
||||||
"and %B0,%B2");
|
else if (which_alternative == 1)
|
||||||
else if (which_alternative==1)
|
return "andi %A0,lo8(%2)\;andi %B0,hi8(%2)";
|
||||||
{
|
|
||||||
if (GET_CODE (operands[2]) == CONST_INT)
|
return avr_out_bitop (insn, operands, NULL);
|
||||||
{
|
}
|
||||||
int mask = INTVAL (operands[2]);
|
[(set_attr "length" "2,2,2,4,4")
|
||||||
if ((mask & 0xff) != 0xff)
|
(set_attr "adjust_len" "no,no,out_bitop,out_bitop,out_bitop")
|
||||||
output_asm_insn (AS2 (andi,%A0,lo8(%2)), operands);
|
(set_attr "cc" "set_n,set_n,clobber,clobber,clobber")])
|
||||||
if ((mask & 0xff00) != 0xff00)
|
|
||||||
output_asm_insn (AS2 (andi,%B0,hi8(%2)), operands);
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
return (AS2 (andi,%A0,lo8(%2)) CR_TAB
|
|
||||||
AS2 (andi,%B0,hi8(%2)));
|
|
||||||
}
|
|
||||||
return (AS2 (ldi,%3,lo8(%2)) CR_TAB
|
|
||||||
"and %A0,%3" CR_TAB
|
|
||||||
AS1 (clr,%B0));
|
|
||||||
}
|
|
||||||
[(set_attr "length" "2,2,3")
|
|
||||||
(set_attr "cc" "set_n,clobber,set_n")])
|
|
||||||
|
|
||||||
(define_insn "andsi3"
|
(define_insn "andsi3"
|
||||||
[(set (match_operand:SI 0 "register_operand" "=r,d")
|
[(set (match_operand:SI 0 "register_operand" "=r,d,r ,r")
|
||||||
(and:SI (match_operand:SI 1 "register_operand" "%0,0")
|
(and:SI (match_operand:SI 1 "register_operand" "%0,0,0 ,0")
|
||||||
(match_operand:SI 2 "nonmemory_operand" "r,i")))]
|
(match_operand:SI 2 "nonmemory_operand" "r,n,Ca4,n")))
|
||||||
|
(clobber (match_scratch:QI 3 "=X,X,X ,&d"))]
|
||||||
""
|
""
|
||||||
{
|
{
|
||||||
if (which_alternative==0)
|
if (which_alternative == 0)
|
||||||
return ("and %0,%2" CR_TAB
|
return "and %0,%2" CR_TAB
|
||||||
"and %B0,%B2" CR_TAB
|
"and %B0,%B2" CR_TAB
|
||||||
"and %C0,%C2" CR_TAB
|
"and %C0,%C2" CR_TAB
|
||||||
"and %D0,%D2");
|
"and %D0,%D2";
|
||||||
else if (which_alternative==1)
|
|
||||||
{
|
return avr_out_bitop (insn, operands, NULL);
|
||||||
if (GET_CODE (operands[2]) == CONST_INT)
|
}
|
||||||
{
|
[(set_attr "length" "4,4,8,8")
|
||||||
HOST_WIDE_INT mask = INTVAL (operands[2]);
|
(set_attr "adjust_len" "no,out_bitop,out_bitop,out_bitop")
|
||||||
if ((mask & 0xff) != 0xff)
|
(set_attr "cc" "set_n,clobber,clobber,clobber")])
|
||||||
output_asm_insn (AS2 (andi,%A0,lo8(%2)), operands);
|
|
||||||
if ((mask & 0xff00) != 0xff00)
|
|
||||||
output_asm_insn (AS2 (andi,%B0,hi8(%2)), operands);
|
|
||||||
if ((mask & 0xff0000L) != 0xff0000L)
|
|
||||||
output_asm_insn (AS2 (andi,%C0,hlo8(%2)), operands);
|
|
||||||
if ((mask & 0xff000000L) != 0xff000000L)
|
|
||||||
output_asm_insn (AS2 (andi,%D0,hhi8(%2)), operands);
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
return (AS2 (andi, %A0,lo8(%2)) CR_TAB
|
|
||||||
AS2 (andi, %B0,hi8(%2)) CR_TAB
|
|
||||||
AS2 (andi, %C0,hlo8(%2)) CR_TAB
|
|
||||||
AS2 (andi, %D0,hhi8(%2)));
|
|
||||||
}
|
|
||||||
return "bug";
|
|
||||||
}
|
|
||||||
[(set_attr "length" "4,4")
|
|
||||||
(set_attr "cc" "set_n,clobber")])
|
|
||||||
|
|
||||||
(define_peephole2 ; andi
|
(define_peephole2 ; andi
|
||||||
[(set (match_operand:QI 0 "d_register_operand" "")
|
[(set (match_operand:QI 0 "d_register_operand" "")
|
||||||
@ -2332,84 +2302,41 @@
|
|||||||
(set_attr "cc" "set_zn,set_zn")])
|
(set_attr "cc" "set_zn,set_zn")])
|
||||||
|
|
||||||
(define_insn "iorhi3"
|
(define_insn "iorhi3"
|
||||||
[(set (match_operand:HI 0 "register_operand" "=r,d")
|
[(set (match_operand:HI 0 "register_operand" "=r,d,d,r ,r")
|
||||||
(ior:HI (match_operand:HI 1 "register_operand" "%0,0")
|
(ior:HI (match_operand:HI 1 "register_operand" "%0,0,0,0 ,0")
|
||||||
(match_operand:HI 2 "nonmemory_operand" "r,i")))]
|
(match_operand:HI 2 "nonmemory_operand" "r,s,n,Co2,n")))
|
||||||
|
(clobber (match_scratch:QI 3 "=X,X,X,X ,&d"))]
|
||||||
""
|
""
|
||||||
{
|
{
|
||||||
if (which_alternative==0)
|
if (which_alternative == 0)
|
||||||
return ("or %A0,%A2" CR_TAB
|
return "or %A0,%A2\;or %B0,%B2";
|
||||||
"or %B0,%B2");
|
else if (which_alternative == 1)
|
||||||
if (GET_CODE (operands[2]) == CONST_INT)
|
return "ori %A0,lo8(%2)\;ori %B0,hi8(%2)";
|
||||||
{
|
|
||||||
int mask = INTVAL (operands[2]);
|
|
||||||
if (mask & 0xff)
|
|
||||||
output_asm_insn (AS2 (ori,%A0,lo8(%2)), operands);
|
|
||||||
if (mask & 0xff00)
|
|
||||||
output_asm_insn (AS2 (ori,%B0,hi8(%2)), operands);
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
return (AS2 (ori,%0,lo8(%2)) CR_TAB
|
|
||||||
AS2 (ori,%B0,hi8(%2)));
|
|
||||||
}
|
|
||||||
[(set_attr "length" "2,2")
|
|
||||||
(set_attr "cc" "set_n,clobber")])
|
|
||||||
|
|
||||||
(define_insn "*iorhi3_clobber"
|
return avr_out_bitop (insn, operands, NULL);
|
||||||
[(set (match_operand:HI 0 "register_operand" "=r,r")
|
}
|
||||||
(ior:HI (match_operand:HI 1 "register_operand" "%0,0")
|
[(set_attr "length" "2,2,2,4,4")
|
||||||
(match_operand:HI 2 "immediate_operand" "M,i")))
|
(set_attr "adjust_len" "no,no,out_bitop,out_bitop,out_bitop")
|
||||||
(clobber (match_scratch:QI 3 "=&d,&d"))]
|
(set_attr "cc" "set_n,set_n,clobber,clobber,clobber")])
|
||||||
""
|
|
||||||
"@
|
|
||||||
ldi %3,lo8(%2)\;or %A0,%3
|
|
||||||
ldi %3,lo8(%2)\;or %A0,%3\;ldi %3,hi8(%2)\;or %B0,%3"
|
|
||||||
[(set_attr "length" "2,4")
|
|
||||||
(set_attr "cc" "clobber,set_n")])
|
|
||||||
|
|
||||||
(define_insn "iorsi3"
|
(define_insn "iorsi3"
|
||||||
[(set (match_operand:SI 0 "register_operand" "=r,d")
|
[(set (match_operand:SI 0 "register_operand" "=r,d,r ,r")
|
||||||
(ior:SI (match_operand:SI 1 "register_operand" "%0,0")
|
(ior:SI (match_operand:SI 1 "register_operand" "%0,0,0 ,0")
|
||||||
(match_operand:SI 2 "nonmemory_operand" "r,i")))]
|
(match_operand:SI 2 "nonmemory_operand" "r,n,Co4,n")))
|
||||||
|
(clobber (match_scratch:QI 3 "=X,X,X ,&d"))]
|
||||||
""
|
""
|
||||||
{
|
{
|
||||||
if (which_alternative==0)
|
if (which_alternative == 0)
|
||||||
return ("or %0,%2" CR_TAB
|
return "or %0,%2" CR_TAB
|
||||||
"or %B0,%B2" CR_TAB
|
"or %B0,%B2" CR_TAB
|
||||||
"or %C0,%C2" CR_TAB
|
"or %C0,%C2" CR_TAB
|
||||||
"or %D0,%D2");
|
"or %D0,%D2";
|
||||||
if (GET_CODE (operands[2]) == CONST_INT)
|
|
||||||
{
|
|
||||||
HOST_WIDE_INT mask = INTVAL (operands[2]);
|
|
||||||
if (mask & 0xff)
|
|
||||||
output_asm_insn (AS2 (ori,%A0,lo8(%2)), operands);
|
|
||||||
if (mask & 0xff00)
|
|
||||||
output_asm_insn (AS2 (ori,%B0,hi8(%2)), operands);
|
|
||||||
if (mask & 0xff0000L)
|
|
||||||
output_asm_insn (AS2 (ori,%C0,hlo8(%2)), operands);
|
|
||||||
if (mask & 0xff000000L)
|
|
||||||
output_asm_insn (AS2 (ori,%D0,hhi8(%2)), operands);
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
return (AS2 (ori, %A0,lo8(%2)) CR_TAB
|
|
||||||
AS2 (ori, %B0,hi8(%2)) CR_TAB
|
|
||||||
AS2 (ori, %C0,hlo8(%2)) CR_TAB
|
|
||||||
AS2 (ori, %D0,hhi8(%2)));
|
|
||||||
}
|
|
||||||
[(set_attr "length" "4,4")
|
|
||||||
(set_attr "cc" "set_n,clobber")])
|
|
||||||
|
|
||||||
(define_insn "*iorsi3_clobber"
|
return avr_out_bitop (insn, operands, NULL);
|
||||||
[(set (match_operand:SI 0 "register_operand" "=r,r")
|
}
|
||||||
(ior:SI (match_operand:SI 1 "register_operand" "%0,0")
|
[(set_attr "length" "4,4,8,8")
|
||||||
(match_operand:SI 2 "immediate_operand" "M,i")))
|
(set_attr "adjust_len" "no,out_bitop,out_bitop,out_bitop")
|
||||||
(clobber (match_scratch:QI 3 "=&d,&d"))]
|
(set_attr "cc" "set_n,clobber,clobber,clobber")])
|
||||||
""
|
|
||||||
"@
|
|
||||||
ldi %3,lo8(%2)\;or %A0,%3
|
|
||||||
ldi %3,lo8(%2)\;or %A0,%3\;ldi %3,hi8(%2)\;or %B0,%3\;ldi %3,hlo8(%2)\;or %C0,%3\;ldi %3,hhi8(%2)\;or %D0,%3"
|
|
||||||
[(set_attr "length" "2,8")
|
|
||||||
(set_attr "cc" "clobber,set_n")])
|
|
||||||
|
|
||||||
;;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
;;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
;; xor
|
;; xor
|
||||||
@ -2424,26 +2351,39 @@
|
|||||||
(set_attr "cc" "set_zn")])
|
(set_attr "cc" "set_zn")])
|
||||||
|
|
||||||
(define_insn "xorhi3"
|
(define_insn "xorhi3"
|
||||||
[(set (match_operand:HI 0 "register_operand" "=r")
|
[(set (match_operand:HI 0 "register_operand" "=r,r ,r")
|
||||||
(xor:HI (match_operand:HI 1 "register_operand" "%0")
|
(xor:HI (match_operand:HI 1 "register_operand" "%0,0 ,0")
|
||||||
(match_operand:HI 2 "register_operand" "r")))]
|
(match_operand:HI 2 "nonmemory_operand" "r,Cx2,n")))
|
||||||
|
(clobber (match_scratch:QI 3 "=X,X ,&d"))]
|
||||||
""
|
""
|
||||||
"eor %0,%2
|
{
|
||||||
eor %B0,%B2"
|
if (which_alternative == 0)
|
||||||
[(set_attr "length" "2")
|
return "eor %A0,%A2\;eor %B0,%B2";
|
||||||
(set_attr "cc" "set_n")])
|
|
||||||
|
return avr_out_bitop (insn, operands, NULL);
|
||||||
|
}
|
||||||
|
[(set_attr "length" "2,2,4")
|
||||||
|
(set_attr "adjust_len" "no,out_bitop,out_bitop")
|
||||||
|
(set_attr "cc" "set_n,clobber,clobber")])
|
||||||
|
|
||||||
(define_insn "xorsi3"
|
(define_insn "xorsi3"
|
||||||
[(set (match_operand:SI 0 "register_operand" "=r")
|
[(set (match_operand:SI 0 "register_operand" "=r,r ,r")
|
||||||
(xor:SI (match_operand:SI 1 "register_operand" "%0")
|
(xor:SI (match_operand:SI 1 "register_operand" "%0,0 ,0")
|
||||||
(match_operand:SI 2 "register_operand" "r")))]
|
(match_operand:SI 2 "nonmemory_operand" "r,Cx4,n")))
|
||||||
|
(clobber (match_scratch:QI 3 "=X,X ,&d"))]
|
||||||
""
|
""
|
||||||
"eor %0,%2
|
{
|
||||||
eor %B0,%B2
|
if (which_alternative == 0)
|
||||||
eor %C0,%C2
|
return "eor %0,%2" CR_TAB
|
||||||
eor %D0,%D2"
|
"eor %B0,%B2" CR_TAB
|
||||||
[(set_attr "length" "4")
|
"eor %C0,%C2" CR_TAB
|
||||||
(set_attr "cc" "set_n")])
|
"eor %D0,%D2";
|
||||||
|
|
||||||
|
return avr_out_bitop (insn, operands, NULL);
|
||||||
|
}
|
||||||
|
[(set_attr "length" "4,8,8")
|
||||||
|
(set_attr "adjust_len" "no,out_bitop,out_bitop")
|
||||||
|
(set_attr "cc" "set_n,clobber,clobber")])
|
||||||
|
|
||||||
;; swap swap swap swap swap swap swap swap swap swap swap swap swap swap swap
|
;; swap swap swap swap swap swap swap swap swap swap swap swap swap swap swap
|
||||||
;; swap
|
;; swap
|
||||||
|
@ -112,3 +112,33 @@
|
|||||||
"Constant integer 4."
|
"Constant integer 4."
|
||||||
(and (match_code "const_int")
|
(and (match_code "const_int")
|
||||||
(match_test "ival == 4")))
|
(match_test "ival == 4")))
|
||||||
|
|
||||||
|
(define_constraint "Ca2"
|
||||||
|
"Constant 2-byte integer that allows AND without clobber register."
|
||||||
|
(and (match_code "const_int")
|
||||||
|
(match_test "avr_popcount_each_byte (op, 2, (1<<0) | (1<<7) | (1<<8))")))
|
||||||
|
|
||||||
|
(define_constraint "Ca4"
|
||||||
|
"Constant 4-byte integer that allows AND without clobber register."
|
||||||
|
(and (match_code "const_int")
|
||||||
|
(match_test "avr_popcount_each_byte (op, 4, (1<<0) | (1<<7) | (1<<8))")))
|
||||||
|
|
||||||
|
(define_constraint "Co2"
|
||||||
|
"Constant 2-byte integer that allows OR without clobber register."
|
||||||
|
(and (match_code "const_int")
|
||||||
|
(match_test "avr_popcount_each_byte (op, 2, (1<<0) | (1<<1) | (1<<8))")))
|
||||||
|
|
||||||
|
(define_constraint "Co4"
|
||||||
|
"Constant 4-byte integer that allows OR without clobber register."
|
||||||
|
(and (match_code "const_int")
|
||||||
|
(match_test "avr_popcount_each_byte (op, 4, (1<<0) | (1<<1) | (1<<8))")))
|
||||||
|
|
||||||
|
(define_constraint "Cx2"
|
||||||
|
"Constant 2-byte integer that allows XOR without clobber register."
|
||||||
|
(and (match_code "const_int")
|
||||||
|
(match_test "avr_popcount_each_byte (op, 2, (1<<0) | (1<<8))")))
|
||||||
|
|
||||||
|
(define_constraint "Cx4"
|
||||||
|
"Constant 4-byte integer that allows XOR without clobber register."
|
||||||
|
(and (match_code "const_int")
|
||||||
|
(match_test "avr_popcount_each_byte (op, 4, (1<<0) | (1<<8))")))
|
||||||
|
Loading…
Reference in New Issue
Block a user