mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-03-18 14:30:42 +08:00
mn10300.c (const_costs): Remove unused function.
* mn10300/mn10300.c (const_costs): Remove unused function. * mn10300/mn10300.h (CONST_COSTS): Rework to generate better code. * mn10300/mn10300.c (print_operand): Handle 'H' and 'L' output modifers for high/low part of a 64bit value. * mn10300/mn10300.h (CONST_DOUBLE_OK_FOR_LETTER_P): Handle 'G' (LEGITIMATE_CONSTANT_P): Allow any constant. * mn10300/mn10300.md (movdi, movdf): Implement. (adddi3, subdi3): New expanders and patterns. * mn10300/mn10300.c (print_operand): Handle 'A' modifier for an address which can't be simple register indirect. * mn10300/mn10300.h (EXTRA_CONSTRAINT): Handle 'R' for bit ops. * mn10300/mn10300.md: Add several patterns to test, set and clear bitfields. * mn10300/mn10300.c (can_use_return_insn): New function. (expand_epilogue): Emit a RETURN insn if possible. * mn10300/mn10300.md (return): New pattern. * mn10300/mn10300.h (CONST_OK_FOR_LETTER_P): Handle 'N'. * mn10300/mn10300.md (andsi3): Catch "and 255,dn" and "and 65535,dn" which were not turned into zero_extend patterns. * mn10300/mn10300.h (GO_IF_LEGITIMATE_ADDRESS): Handle symbolic constant as an index/base too. * mn10300/mn10300.md (movsi): Allow SP to be loaded/saved with reg+d8 addresses. * mn10300/mn10300.md (cmpsi): Allow second operand to be a constant. (subsi3): Likewise. * mn10300/mn10300.md (sign extension patterns): Fix thinko when extending from memory. * mn10300/mn10300.md (tst peepholes): Add peepholes for test/branch based on N bit being set/clear and the data value being tested dies. From-SVN: r13701
This commit is contained in:
parent
777fbf098d
commit
38c37a0ef0
@ -49,27 +49,6 @@ asm_file_start (file)
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
const_costs (r, c)
|
||||
rtx r;
|
||||
enum rtx_code c;
|
||||
{
|
||||
switch (c)
|
||||
{
|
||||
case CONST_INT:
|
||||
if (INT_8_BITS (INTVAL (r)))
|
||||
return 0;
|
||||
else if (INT_16_BITS (INTVAL (r)))
|
||||
return 1;
|
||||
else
|
||||
return 2;
|
||||
case CONST_DOUBLE:
|
||||
return 8;
|
||||
default:
|
||||
return 4;
|
||||
}
|
||||
}
|
||||
|
||||
/* Print operand X using operand code CODE to assembly language output file
|
||||
FILE. */
|
||||
|
||||
@ -134,7 +113,8 @@ print_operand (file, x, code)
|
||||
print_operand (file, x, 0);
|
||||
break;
|
||||
|
||||
default:
|
||||
/* These are the least significant word in a 64bit value. */
|
||||
case 'L':
|
||||
switch (GET_CODE (x))
|
||||
{
|
||||
case MEM:
|
||||
@ -152,6 +132,138 @@ print_operand (file, x, code)
|
||||
reg_names[REGNO (SUBREG_REG (x)) + SUBREG_WORD (x)]);
|
||||
break;
|
||||
|
||||
case CONST_DOUBLE:
|
||||
{
|
||||
long val[2];
|
||||
REAL_VALUE_TYPE rv;
|
||||
|
||||
switch (GET_MODE (x))
|
||||
{
|
||||
case DFmode:
|
||||
REAL_VALUE_FROM_CONST_DOUBLE (rv, x);
|
||||
REAL_VALUE_TO_TARGET_DOUBLE (rv, val);
|
||||
print_operand_address (file, GEN_INT (val[0]));
|
||||
break;;
|
||||
case SFmode:
|
||||
REAL_VALUE_FROM_CONST_DOUBLE (rv, x);
|
||||
REAL_VALUE_TO_TARGET_SINGLE (rv, val[0]);
|
||||
print_operand_address (file, GEN_INT (val[0]));
|
||||
break;;
|
||||
case VOIDmode:
|
||||
case DImode:
|
||||
print_operand_address (file,
|
||||
GEN_INT (CONST_DOUBLE_LOW (x)));
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case CONST_INT:
|
||||
print_operand_address (file, x);
|
||||
break;
|
||||
|
||||
default:
|
||||
abort ();
|
||||
}
|
||||
break;
|
||||
|
||||
/* Similarly, but for the most significant word. */
|
||||
case 'H':
|
||||
switch (GET_CODE (x))
|
||||
{
|
||||
case MEM:
|
||||
fputc ('(', file);
|
||||
x = adj_offsettable_operand (x, 4);
|
||||
output_address (XEXP (x, 0));
|
||||
fputc (')', file);
|
||||
break;
|
||||
|
||||
case REG:
|
||||
fprintf (file, "%s", reg_names[REGNO (x) + 1]);
|
||||
break;
|
||||
|
||||
case SUBREG:
|
||||
fprintf (file, "%s",
|
||||
reg_names[REGNO (SUBREG_REG (x)) + SUBREG_WORD (x)] + 1);
|
||||
break;
|
||||
|
||||
case CONST_DOUBLE:
|
||||
{
|
||||
long val[2];
|
||||
REAL_VALUE_TYPE rv;
|
||||
|
||||
switch (GET_MODE (x))
|
||||
{
|
||||
case DFmode:
|
||||
REAL_VALUE_FROM_CONST_DOUBLE (rv, x);
|
||||
REAL_VALUE_TO_TARGET_DOUBLE (rv, val);
|
||||
print_operand_address (file, GEN_INT (val[1]));
|
||||
break;;
|
||||
case SFmode:
|
||||
abort ();
|
||||
case VOIDmode:
|
||||
case DImode:
|
||||
print_operand_address (file,
|
||||
GEN_INT (CONST_DOUBLE_HIGH (x)));
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case CONST_INT:
|
||||
if (INTVAL (x) < 0)
|
||||
print_operand_address (file, GEN_INT (-1));
|
||||
else
|
||||
print_operand_address (file, GEN_INT (0));
|
||||
break;
|
||||
default:
|
||||
abort ();
|
||||
}
|
||||
break;
|
||||
|
||||
case 'A':
|
||||
fputc ('(', file);
|
||||
if (GET_CODE (XEXP (x, 0)) == REG)
|
||||
output_address (gen_rtx (PLUS, SImode, XEXP (x, 0), GEN_INT (0)));
|
||||
else
|
||||
output_address (XEXP (x, 0));
|
||||
fputc (')', file);
|
||||
break;
|
||||
|
||||
default:
|
||||
switch (GET_CODE (x))
|
||||
{
|
||||
case MEM:
|
||||
fputc ('(', file);
|
||||
output_address (XEXP (x, 0));
|
||||
fputc (')', file);
|
||||
break;
|
||||
|
||||
case PLUS:
|
||||
output_address (x);
|
||||
break;
|
||||
|
||||
case REG:
|
||||
fprintf (file, "%s", reg_names[REGNO (x)]);
|
||||
break;
|
||||
|
||||
case SUBREG:
|
||||
fprintf (file, "%s",
|
||||
reg_names[REGNO (SUBREG_REG (x)) + SUBREG_WORD (x)]);
|
||||
break;
|
||||
|
||||
/* This will only be single precision.... */
|
||||
case CONST_DOUBLE:
|
||||
{
|
||||
unsigned long val;
|
||||
REAL_VALUE_TYPE rv;
|
||||
|
||||
REAL_VALUE_FROM_CONST_DOUBLE (rv, x);
|
||||
REAL_VALUE_TO_TARGET_SINGLE (rv, val);
|
||||
print_operand_address (file, GEN_INT (val));
|
||||
break;
|
||||
}
|
||||
|
||||
case CONST_INT:
|
||||
case SYMBOL_REF:
|
||||
case CONST:
|
||||
@ -208,6 +320,20 @@ print_operand_address (file, addr)
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
can_use_return_insn ()
|
||||
{
|
||||
int size = get_frame_size ();
|
||||
|
||||
return (reload_completed
|
||||
&& size == 0
|
||||
&& !regs_ever_live[2]
|
||||
&& !regs_ever_live[3]
|
||||
&& !regs_ever_live[6]
|
||||
&& !regs_ever_live[7]
|
||||
&& !frame_pointer_needed);
|
||||
}
|
||||
|
||||
void
|
||||
expand_prologue ()
|
||||
{
|
||||
@ -262,10 +388,16 @@ expand_epilogue ()
|
||||
else
|
||||
{
|
||||
if (size)
|
||||
emit_insn (gen_addsi3 (stack_pointer_rtx,
|
||||
stack_pointer_rtx,
|
||||
GEN_INT (size)));
|
||||
emit_jump_insn (gen_return_internal ());
|
||||
{
|
||||
emit_insn (gen_addsi3 (stack_pointer_rtx,
|
||||
stack_pointer_rtx,
|
||||
GEN_INT (size)));
|
||||
emit_jump_insn (gen_return_internal ());
|
||||
}
|
||||
else
|
||||
{
|
||||
emit_jump_insn (gen_return ());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -305,13 +305,15 @@ enum reg_class {
|
||||
#define CONST_OK_FOR_K(VALUE) ((VALUE) == 2)
|
||||
#define CONST_OK_FOR_L(VALUE) ((VALUE) == 4)
|
||||
#define CONST_OK_FOR_M(VALUE) ((VALUE) == 3)
|
||||
#define CONST_OK_FOR_N(VALUE) ((VALUE) == 255 || (VALUE) == 65535)
|
||||
|
||||
#define CONST_OK_FOR_LETTER_P(VALUE, C) \
|
||||
((C) == 'I' ? CONST_OK_FOR_I (VALUE) : \
|
||||
(C) == 'J' ? CONST_OK_FOR_J (VALUE) : \
|
||||
(C) == 'K' ? CONST_OK_FOR_K (VALUE) : \
|
||||
(C) == 'L' ? CONST_OK_FOR_L (VALUE) : \
|
||||
(C) == 'M' ? CONST_OK_FOR_M (VALUE) : 0)
|
||||
(C) == 'M' ? CONST_OK_FOR_M (VALUE) : \
|
||||
(C) == 'N' ? CONST_OK_FOR_N (VALUE) : 0)
|
||||
|
||||
|
||||
/* Similar, but for floating constants, and defining letters G and H.
|
||||
@ -319,7 +321,9 @@ enum reg_class {
|
||||
|
||||
`G' is a floating-point zero. */
|
||||
|
||||
#define CONST_DOUBLE_OK_FOR_LETTER_P(VALUE, C) 0
|
||||
#define CONST_DOUBLE_OK_FOR_LETTER_P(VALUE, C) \
|
||||
((C) == 'G' ? (GET_MODE_CLASS (GET_MODE (VALUE)) == MODE_FLOAT \
|
||||
&& (VALUE) == CONST0_RTX (GET_MODE (VALUE))) : 0)
|
||||
|
||||
|
||||
/* Stack layout; function entry, exit and calling. */
|
||||
@ -565,8 +569,22 @@ enum reg_class {
|
||||
|
||||
/* Extra constraints. */
|
||||
|
||||
#define OK_FOR_R(OP) \
|
||||
(GET_CODE (OP) == MEM \
|
||||
&& GET_MODE (OP) == QImode \
|
||||
&& (CONSTANT_ADDRESS_P (XEXP (OP, 0)) \
|
||||
|| (GET_CODE (XEXP (OP, 0)) == REG \
|
||||
&& REG_OK_FOR_BASE_P (XEXP (OP, 0)) \
|
||||
&& XEXP (OP, 0) != stack_pointer_rtx) \
|
||||
|| (GET_CODE (XEXP (OP, 0)) == PLUS \
|
||||
&& GET_CODE (XEXP (XEXP (OP, 0), 0)) == REG \
|
||||
&& REG_OK_FOR_BASE_P (XEXP (XEXP (OP, 0), 0)) \
|
||||
&& XEXP (XEXP (OP, 0), 0) != stack_pointer_rtx \
|
||||
&& GET_CODE (XEXP (XEXP (OP, 0), 1)) == CONST_INT \
|
||||
&& INT_8_BITS (INTVAL (XEXP (XEXP (OP, 0), 1))))))
|
||||
|
||||
#define EXTRA_CONSTRAINT(OP, C) \
|
||||
((C) == 'S' ? GET_CODE (OP) == SYMBOL_REF : 0)
|
||||
((C) == 'R' ? OK_FOR_R (OP) : (C) == 'S' ? GET_CODE (OP) == SYMBOL_REF : 0)
|
||||
|
||||
/* Maximum number of registers that can appear in a valid memory address. */
|
||||
|
||||
@ -635,10 +653,11 @@ enum reg_class {
|
||||
base = XEXP (X, 1), index = XEXP (X, 0); \
|
||||
if (base != 0 && index != 0) \
|
||||
{ \
|
||||
if (GET_CODE (index) == CONST_INT) \
|
||||
if (CONSTANT_ADDRESS_P (index)) \
|
||||
goto ADDR; \
|
||||
if (REG_P (index) \
|
||||
&& REG_OK_FOR_INDEX_P (index)) \
|
||||
&& REG_OK_FOR_INDEX_P (index) \
|
||||
&& GET_MODE_SIZE (mode) <= GET_MODE_SIZE (word_mode)) \
|
||||
goto ADDR; \
|
||||
} \
|
||||
} \
|
||||
@ -668,8 +687,7 @@ enum reg_class {
|
||||
/* Nonzero if the constant value X is a legitimate general operand.
|
||||
It is given that X satisfies CONSTANT_P or is a CONST_DOUBLE. */
|
||||
|
||||
#define LEGITIMATE_CONSTANT_P(X) \
|
||||
(GET_MODE_CLASS (GET_MODE (X)) != MODE_FLOAT) \
|
||||
#define LEGITIMATE_CONSTANT_P(X) 1
|
||||
|
||||
|
||||
/* Tell final.c how to eliminate redundant test instructions. */
|
||||
@ -691,8 +709,31 @@ enum reg_class {
|
||||
return it with a return statement. Otherwise, break from the switch. */
|
||||
|
||||
#define CONST_COSTS(RTX,CODE,OUTER_CODE) \
|
||||
default: { int _zxy= const_costs(RTX, CODE); \
|
||||
if(_zxy) return _zxy; break;}
|
||||
case CONST_INT: \
|
||||
/* Zeros are extremely cheap. */ \
|
||||
if (INTVAL (RTX) == 0 && OUTER_CODE == SET) \
|
||||
return 0; \
|
||||
/* If it fits in 8 bits, then it's still relatively cheap. */ \
|
||||
if (INT_8_BITS (INTVAL (RTX))) \
|
||||
return 1; \
|
||||
/* This is the "base" cost, includes constants where either the \
|
||||
upper or lower 16bits are all zeros. */ \
|
||||
if (INT_16_BITS (INTVAL (RTX)) \
|
||||
|| (INTVAL (RTX) & 0xffff) == 0 \
|
||||
|| (INTVAL (RTX) & 0xffff0000) == 0) \
|
||||
return 2; \
|
||||
return 4; \
|
||||
/* These are more costly than a CONST_INT, but we can relax them, \
|
||||
so they're less costly than a CONST_DOUBLE. */ \
|
||||
case CONST: \
|
||||
case LABEL_REF: \
|
||||
case SYMBOL_REF: \
|
||||
return 6; \
|
||||
/* We don't optimize CONST_DOUBLEs well nor do we relax them well, \
|
||||
so their cost is very high. */ \
|
||||
case CONST_DOUBLE: \
|
||||
return 8;
|
||||
|
||||
|
||||
#define REGISTER_MOVE_COST(CLASS1, CLASS2) (CLASS1 != CLASS2 ? 4 : 0)
|
||||
|
||||
|
@ -119,10 +119,9 @@
|
||||
operands[1] = copy_to_mode_reg (SImode, operand1);
|
||||
}")
|
||||
|
||||
;; We could improve loading of some constants with a little work.
|
||||
(define_insn ""
|
||||
[(set (match_operand:SI 0 "general_operand" "=d,a,d,dm,dm,am,am,d,d,a,a,a,x")
|
||||
(match_operand:SI 1 "general_operand" "0,0,I,d,a,d,a,dim,aim,dim,aim,x,a"))]
|
||||
[(set (match_operand:SI 0 "general_operand" "=d,a,d,dm,dm,am,am,d,d,a,a,aR,x")
|
||||
(match_operand:SI 1 "general_operand" "0,0,I,d,a,d,a,dim,aim,dim,aim,x,aR"))]
|
||||
"register_operand (operands[0], SImode)
|
||||
|| register_operand (operands[1], SImode)"
|
||||
"@
|
||||
@ -153,7 +152,6 @@
|
||||
operands[1] = copy_to_mode_reg (SFmode, operand1);
|
||||
}")
|
||||
|
||||
;; We could improve loading of some constants with a little work.
|
||||
(define_insn ""
|
||||
[(set (match_operand:SF 0 "general_operand" "=d,a,d,dam,da")
|
||||
(match_operand:SF 1 "general_operand" "0,0,G,da,daim"))]
|
||||
@ -167,6 +165,69 @@
|
||||
mov %1,%0"
|
||||
[(set_attr "cc" "none,none,clobber,none_0hit,none_0hit")])
|
||||
|
||||
(define_expand "movdi"
|
||||
[(set (match_operand:DI 0 "general_operand" "")
|
||||
(match_operand:DI 1 "general_operand" ""))]
|
||||
""
|
||||
"
|
||||
{
|
||||
/* One of the ops has to be in a register */
|
||||
if (!register_operand (operand1, DImode)
|
||||
&& !register_operand (operand0, DImode))
|
||||
operands[1] = copy_to_mode_reg (DImode, operand1);
|
||||
}")
|
||||
|
||||
(define_insn ""
|
||||
[(set (match_operand:DI 0 "general_operand" "=d,a,d,dm,dm,am,am,d,d,a,a")
|
||||
(match_operand:DI 1 "general_operand" "0,0,I,d,a,d,a,dim,aim,dim,aim"))]
|
||||
"register_operand (operands[0], DImode)
|
||||
|| register_operand (operands[1], DImode)"
|
||||
"@
|
||||
nop
|
||||
nop
|
||||
clr %L0\;clr %H0
|
||||
mov %L1,%L0\;mov %H1,%H0
|
||||
mov %L1,%L0\;mov %H1,%H0
|
||||
mov %L1,%L0\;mov %H1,%H0
|
||||
mov %L1,%L0\;mov %H1,%H0
|
||||
mov %L1,%L0\;mov %H1,%H0
|
||||
mov %L1,%L0\;mov %H1,%H0
|
||||
mov %L1,%L0\;mov %H1,%H0
|
||||
mov %L1,%L0\;mov %H1,%H0"
|
||||
[(set_attr "cc" "none,none,clobber,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit")])
|
||||
|
||||
(define_expand "movdf"
|
||||
[(set (match_operand:DF 0 "general_operand" "")
|
||||
(match_operand:DF 1 "general_operand" ""))]
|
||||
""
|
||||
"
|
||||
{
|
||||
/* One of the ops has to be in a register */
|
||||
if (!register_operand (operand1, DFmode)
|
||||
&& !register_operand (operand0, DFmode))
|
||||
operands[1] = copy_to_mode_reg (DFmode, operand1);
|
||||
}")
|
||||
|
||||
(define_insn ""
|
||||
[(set (match_operand:DF 0 "general_operand" "=d,a,d,dm,dm,am,am,d,d,a,a")
|
||||
(match_operand:DF 1 "general_operand" "0,0,G,d,a,d,a,dim,aim,dim,aim"))]
|
||||
"register_operand (operands[0], DFmode)
|
||||
|| register_operand (operands[1], DFmode)"
|
||||
"@
|
||||
nop
|
||||
nop
|
||||
clr %L0\;clr %H0
|
||||
mov %L1,%L0\;mov %H1,%H0
|
||||
mov %L1,%L0\;mov %H1,%H0
|
||||
mov %L1,%L0\;mov %H1,%H0
|
||||
mov %L1,%L0\;mov %H1,%H0
|
||||
mov %L1,%L0\;mov %H1,%H0
|
||||
mov %L1,%L0\;mov %H1,%H0
|
||||
mov %L1,%L0\;mov %H1,%H0
|
||||
mov %L1,%L0\;mov %H1,%H0"
|
||||
[(set_attr "cc" "none,none,clobber,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit")])
|
||||
|
||||
|
||||
|
||||
;; ----------------------------------------------------------------------
|
||||
;; TEST INSTRUCTIONS
|
||||
@ -182,8 +243,8 @@
|
||||
|
||||
(define_insn "cmpsi"
|
||||
[(set (cc0)
|
||||
(compare:SI (match_operand:SI 0 "register_operand" "da")
|
||||
(match_operand:SI 1 "register_operand" "dai")))]
|
||||
(compare (match_operand:SI 0 "register_operand" "da")
|
||||
(match_operand:SI 1 "nonmemory_operand" "dai")))]
|
||||
""
|
||||
"cmp %1,%0"
|
||||
[(set_attr "cc" "compare")])
|
||||
@ -193,9 +254,9 @@
|
||||
;; ----------------------------------------------------------------------
|
||||
|
||||
(define_expand "addsi3"
|
||||
[(set (match_operand:SI 0 "register_operand" "=da,a,da,x")
|
||||
(plus:SI (match_operand:SI 1 "register_operand" "%0,0,0,0")
|
||||
(match_operand:SI 2 "nonmemory_operand" "J,L,dai,i")))]
|
||||
[(set (match_operand:SI 0 "register_operand" "")
|
||||
(plus:SI (match_operand:SI 1 "register_operand" "")
|
||||
(match_operand:SI 2 "nonmemory_operand" "")))]
|
||||
""
|
||||
"
|
||||
{
|
||||
@ -225,6 +286,48 @@
|
||||
add %2,%0"
|
||||
[(set_attr "cc" "set_zn_c0,none_0hit,none_0hit,set_zn_c0,none_0hit")])
|
||||
|
||||
(define_expand "adddi3"
|
||||
[(set (reg:DI 0) (match_operand:DI 1 "register_operand" ""))
|
||||
(set (reg:DI 2) (match_operand:DI 2 "nonmemory_operand" ""))
|
||||
(set (reg:DI 0) (plus:DI (reg:DI 0) (reg:DI 2)))
|
||||
(set (match_operand:DI 0 "register_operand" "") (reg:DI 0))]
|
||||
""
|
||||
"
|
||||
{
|
||||
if (GET_CODE (operands[2]) == CONST_INT)
|
||||
{
|
||||
rtx reg0 = gen_rtx (REG, DImode, 0);
|
||||
|
||||
emit_move_insn (reg0, operands[1]);
|
||||
emit_insn (gen_adddi3_const (operands[2]));
|
||||
emit_move_insn (operands[0], reg0);
|
||||
DONE;
|
||||
}
|
||||
}")
|
||||
|
||||
;; The general adddi3 pattern.
|
||||
(define_insn ""
|
||||
[(set (reg:DI 0) (plus:DI (reg:DI 0) (reg:DI 2)))]
|
||||
""
|
||||
"add d2,d0\;addc d3,d1"
|
||||
[(set_attr "cc" "clobber")])
|
||||
|
||||
;; adddi3 with on operand being a constant.
|
||||
(define_insn "adddi3_const"
|
||||
[(set (reg:DI 0)
|
||||
(plus:DI (reg:DI 0) (match_operand:DI 0 "const_int_operand" "i")))
|
||||
(clobber (reg:DI 2))]
|
||||
""
|
||||
"*
|
||||
{
|
||||
long value = INTVAL (operands[0]);
|
||||
|
||||
if (value < 0)
|
||||
return \"mov -1,d2\;add %0,d0\;addc d2,d1\";
|
||||
else
|
||||
return \"clr d2\;add %0,d0\;addc d2,d1\";
|
||||
}"
|
||||
[(set_attr "cc" "clobber")])
|
||||
;; ----------------------------------------------------------------------
|
||||
;; SUBTRACT INSTRUCTIONS
|
||||
;; ----------------------------------------------------------------------
|
||||
@ -232,7 +335,7 @@
|
||||
(define_insn "subsi3"
|
||||
[(set (match_operand:SI 0 "register_operand" "=da")
|
||||
(minus:SI (match_operand:SI 1 "register_operand" "0")
|
||||
(match_operand:SI 2 "register_operand" "dai")))]
|
||||
(match_operand:SI 2 "nonmemory_operand" "dai")))]
|
||||
""
|
||||
"sub %2,%0"
|
||||
[(set_attr "cc" "set_zn_c0")])
|
||||
@ -251,6 +354,19 @@
|
||||
DONE;
|
||||
}")
|
||||
|
||||
(define_expand "subdi3"
|
||||
[(set (reg:DI 0) (match_operand:DI 1 "register_operand" ""))
|
||||
(set (reg:DI 2) (match_operand:DI 2 "nonmemory_operand" ""))
|
||||
(set (reg:DI 0) (minus:DI (reg:DI 0) (reg:DI 2)))
|
||||
(set (match_operand:DI 0 "register_operand" "") (reg:DI 0))]
|
||||
""
|
||||
"")
|
||||
|
||||
(define_insn ""
|
||||
[(set (reg:DI 0) (minus:DI (reg:DI 0) (reg:DI 2)))]
|
||||
""
|
||||
"sub d2,d0\;subc d3,d1"
|
||||
[(set_attr "cc" "clobber")])
|
||||
|
||||
;; ----------------------------------------------------------------------
|
||||
;; MULTIPLY INSTRUCTIONS
|
||||
@ -304,12 +420,19 @@
|
||||
;; ----------------------------------------------------------------------
|
||||
|
||||
(define_insn "andsi3"
|
||||
[(set (match_operand:SI 0 "register_operand" "=d")
|
||||
(and:SI (match_operand:SI 1 "register_operand" "%0")
|
||||
(match_operand:SI 2 "nonmemory_operand" "di")))]
|
||||
[(set (match_operand:SI 0 "register_operand" "=d,d")
|
||||
(and:SI (match_operand:SI 1 "register_operand" "%0,0")
|
||||
(match_operand:SI 2 "nonmemory_operand" "N,di")))]
|
||||
""
|
||||
"and %2,%0"
|
||||
[(set_attr "cc" "set_zn_c0")])
|
||||
"*
|
||||
{
|
||||
if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) == 0xff)
|
||||
return \"extbu %0\";
|
||||
if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) == 0xffff)
|
||||
return \"exthu %0\";
|
||||
return \"and %2,%0\";
|
||||
}"
|
||||
[(set_attr "cc" "none_0hit,set_zn_c0")])
|
||||
|
||||
;; ----------------------------------------------------------------------
|
||||
;; OR INSTRUCTIONS
|
||||
@ -349,9 +472,127 @@
|
||||
;; -----------------------------------------------------------------
|
||||
;; BIT FIELDS
|
||||
;; -----------------------------------------------------------------
|
||||
;; Is it worth defining insv and extv for the MN10300 series?!?
|
||||
;; probably so.
|
||||
|
||||
|
||||
;; These set/clear memory in byte sized chunks.
|
||||
;;
|
||||
;; They are no smaller/faster than loading the value into a register
|
||||
;; and storing the register, but they don't need a scratch register
|
||||
;; which may allow for better code generation.
|
||||
(define_insn ""
|
||||
[(set (match_operand:QI 0 "general_operand" "=R,d") (const_int 0))]
|
||||
""
|
||||
"@
|
||||
bclr 255,%A0
|
||||
clr %0"
|
||||
[(set_attr "cc" "clobber")])
|
||||
|
||||
(define_insn ""
|
||||
[(set (match_operand:QI 0 "general_operand" "=R,d") (const_int -1))]
|
||||
""
|
||||
"@
|
||||
bset 255,%A0
|
||||
mov -1,%0"
|
||||
[(set_attr "cc" "clobber,none_0hit")])
|
||||
|
||||
(define_insn ""
|
||||
[(set (match_operand:QI 0 "general_operand" "=R,d")
|
||||
(subreg:QI
|
||||
(and:SI (subreg:SI (match_dup 0) 0)
|
||||
(match_operand:SI 1 "const_int_operand" "i,i")) 0))]
|
||||
""
|
||||
"@
|
||||
bclr %N1,%A0
|
||||
and %1,%0"
|
||||
[(set_attr "cc" "clobber,set_zn_c0")])
|
||||
|
||||
(define_insn ""
|
||||
[(set (match_operand:QI 0 "general_operand" "=R,d")
|
||||
(subreg:QI
|
||||
(ior:SI (subreg:SI (match_dup 0) 0)
|
||||
(match_operand:SI 1 "const_int_operand" "i,i")) 0))]
|
||||
""
|
||||
"@
|
||||
bset %1,%A0
|
||||
or %1,%0"
|
||||
[(set_attr "cc" "clobber")])
|
||||
|
||||
(define_insn ""
|
||||
[(set (cc0)
|
||||
(zero_extract:SI (match_operand:SI 0 "register_operand" "d")
|
||||
(match_operand 1 "const_int_operand" "")
|
||||
(match_operand 2 "const_int_operand" "")))]
|
||||
""
|
||||
"*
|
||||
{
|
||||
int len = INTVAL (operands[1]);
|
||||
int bit = INTVAL (operands[2]);
|
||||
int mask = 0;
|
||||
rtx xoperands[2];
|
||||
|
||||
while (len > 0)
|
||||
{
|
||||
mask |= (1 << bit);
|
||||
bit++;
|
||||
len--;
|
||||
}
|
||||
|
||||
xoperands[0] = operands[0];
|
||||
xoperands[1] = GEN_INT (mask);
|
||||
output_asm_insn (\"btst %1,%0\", xoperands);
|
||||
return \"\";
|
||||
}"
|
||||
[(set_attr "cc" "set_zn_c0")])
|
||||
|
||||
(define_insn ""
|
||||
[(set (cc0)
|
||||
(zero_extract:SI (match_operand:QI 0 "general_operand" "R,d")
|
||||
(match_operand 1 "const_int_operand" "")
|
||||
(match_operand 2 "const_int_operand" "")))]
|
||||
"INTVAL (operands[1]) <= 8 && INTVAL (operands[2]) <= 7"
|
||||
"*
|
||||
{
|
||||
int len = INTVAL (operands[1]);
|
||||
int bit = INTVAL (operands[2]);
|
||||
int mask = 0;
|
||||
rtx xoperands[2];
|
||||
|
||||
while (len > 0)
|
||||
{
|
||||
mask |= (1 << bit);
|
||||
bit++;
|
||||
len--;
|
||||
}
|
||||
|
||||
xoperands[0] = operands[0];
|
||||
xoperands[1] = GEN_INT (mask);
|
||||
if (GET_CODE (operands[0]) == REG)
|
||||
output_asm_insn (\"btst %1,%0\", xoperands);
|
||||
else
|
||||
output_asm_insn (\"btst %1,%A0\", xoperands);
|
||||
return \"\";
|
||||
}"
|
||||
[(set_attr "cc" "set_zn_c0")])
|
||||
|
||||
(define_insn ""
|
||||
[(set (cc0) (and:SI (match_operand:SI 0 "register_operand" "d")
|
||||
(match_operand:SI 1 "const_int_operand" "")))]
|
||||
""
|
||||
"btst %1,%0"
|
||||
[(set_attr "cc" "set_zn_c0")])
|
||||
|
||||
(define_insn ""
|
||||
[(set (cc0)
|
||||
(and:SI
|
||||
(subreg:SI (match_operand:QI 0 "general_operand" "R,d") 0)
|
||||
(match_operand:SI 1 "const_int_operand" "")))]
|
||||
""
|
||||
"@
|
||||
btst %1,%A0
|
||||
btst %1,%0"
|
||||
[(set_attr "cc" "set_zn_c0")])
|
||||
|
||||
;; -----------------------------------------------------------------
|
||||
;; -----------------------------------------------------------------
|
||||
;; Scc INSTRUCTIONS
|
||||
;; -----------------------------------------------------------------
|
||||
@ -602,7 +843,7 @@
|
||||
""
|
||||
"@
|
||||
extb %0
|
||||
mov %1,%0"
|
||||
mov %1,%0\;extb %0"
|
||||
[(set_attr "cc" "none_0hit")])
|
||||
|
||||
(define_insn "extendhisi2"
|
||||
@ -612,9 +853,8 @@
|
||||
""
|
||||
"@
|
||||
exth %0
|
||||
mov %1,%0"
|
||||
mov %1,%0\;exth %0"
|
||||
[(set_attr "cc" "none_0hit")])
|
||||
|
||||
|
||||
;; ----------------------------------------------------------------------
|
||||
;; SHIFTS
|
||||
@ -694,6 +934,12 @@
|
||||
"movm [d2,d3,a2,a3],(sp)"
|
||||
[(set_attr "cc" "clobber")])
|
||||
|
||||
(define_insn "return"
|
||||
[(return)]
|
||||
"can_use_return_insn ()"
|
||||
"rets"
|
||||
[(set_attr "cc" "clobber")])
|
||||
|
||||
;; Try to combine consecutive updates of the stack pointer (or any
|
||||
;; other register for that matter).
|
||||
(define_peephole
|
||||
@ -710,3 +956,48 @@
|
||||
return \"add %1,%0\";
|
||||
}"
|
||||
[(set_attr "cc" "clobber")])
|
||||
|
||||
;;
|
||||
;; We had patterns to check eq/ne, but the they don't work because
|
||||
;; 0x80000000 + 0x80000000 = 0x0 with a carry out.
|
||||
;;
|
||||
;; The Z flag and C flag would be set, and we have no way to
|
||||
;; check for the Z flag set and C flag clear.
|
||||
;;
|
||||
;; This will work on the mn10200 because we can check the ZX flag
|
||||
;; if the comparison is in HImode.
|
||||
(define_peephole
|
||||
[(set (cc0) (match_operand:SI 0 "register_operand" "d"))
|
||||
(set (pc) (if_then_else (ge (cc0) (const_int 0))
|
||||
(match_operand 1 "" "")
|
||||
(pc)))]
|
||||
"dead_or_set_p (ins1, operands[0]) && REG_OK_FOR_INDEX_P (operands[0])"
|
||||
"add %0,%0\;bcc %1"
|
||||
[(set_attr "cc" "clobber")])
|
||||
|
||||
(define_peephole
|
||||
[(set (cc0) (match_operand:SI 0 "register_operand" "d"))
|
||||
(set (pc) (if_then_else (lt (cc0) (const_int 0))
|
||||
(match_operand 1 "" "")
|
||||
(pc)))]
|
||||
"dead_or_set_p (ins1, operands[0]) && REG_OK_FOR_INDEX_P (operands[0])"
|
||||
"add %0,%0\;bcs %1"
|
||||
[(set_attr "cc" "clobber")])
|
||||
|
||||
(define_peephole
|
||||
[(set (cc0) (match_operand:SI 0 "register_operand" "d"))
|
||||
(set (pc) (if_then_else (ge (cc0) (const_int 0))
|
||||
(pc)
|
||||
(match_operand 1 "" "")))]
|
||||
"dead_or_set_p (ins1, operands[0]) && REG_OK_FOR_INDEX_P (operands[0])"
|
||||
"add %0,%0\;bcs %1"
|
||||
[(set_attr "cc" "clobber")])
|
||||
|
||||
(define_peephole
|
||||
[(set (cc0) (match_operand:SI 0 "register_operand" "d"))
|
||||
(set (pc) (if_then_else (lt (cc0) (const_int 0))
|
||||
(pc)
|
||||
(match_operand 1 "" "")))]
|
||||
"dead_or_set_p (ins1, operands[0]) && REG_OK_FOR_INDEX_P (operands[0])"
|
||||
"add %0,%0\;bcc %1"
|
||||
[(set_attr "cc" "clobber")])
|
||||
|
Loading…
x
Reference in New Issue
Block a user