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:
Jeff Law 1997-03-14 10:32:36 -07:00
parent 777fbf098d
commit 38c37a0ef0
3 changed files with 519 additions and 55 deletions

View File

@ -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 ());
}
}
}

View File

@ -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)

View File

@ -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")])