Commit 38c37a0e by Jeff Law

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
parent 777fbf09
...@@ -49,27 +49,6 @@ asm_file_start (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 /* Print operand X using operand code CODE to assembly language output file
FILE. */ FILE. */
...@@ -134,6 +113,123 @@ print_operand (file, x, code) ...@@ -134,6 +113,123 @@ print_operand (file, x, code)
print_operand (file, x, 0); print_operand (file, x, 0);
break; break;
/* These are the least significant word in a 64bit value. */
case 'L':
switch (GET_CODE (x))
{
case MEM:
fputc ('(', file);
output_address (XEXP (x, 0));
fputc (')', file);
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;
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: default:
switch (GET_CODE (x)) switch (GET_CODE (x))
{ {
...@@ -143,6 +239,10 @@ print_operand (file, x, code) ...@@ -143,6 +239,10 @@ print_operand (file, x, code)
fputc (')', file); fputc (')', file);
break; break;
case PLUS:
output_address (x);
break;
case REG: case REG:
fprintf (file, "%s", reg_names[REGNO (x)]); fprintf (file, "%s", reg_names[REGNO (x)]);
break; break;
...@@ -152,6 +252,18 @@ print_operand (file, x, code) ...@@ -152,6 +252,18 @@ print_operand (file, x, code)
reg_names[REGNO (SUBREG_REG (x)) + SUBREG_WORD (x)]); reg_names[REGNO (SUBREG_REG (x)) + SUBREG_WORD (x)]);
break; 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 CONST_INT:
case SYMBOL_REF: case SYMBOL_REF:
case CONST: case CONST:
...@@ -208,6 +320,20 @@ print_operand_address (file, addr) ...@@ -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 void
expand_prologue () expand_prologue ()
{ {
...@@ -262,10 +388,16 @@ expand_epilogue () ...@@ -262,10 +388,16 @@ expand_epilogue ()
else else
{ {
if (size) if (size)
emit_insn (gen_addsi3 (stack_pointer_rtx, {
stack_pointer_rtx, emit_insn (gen_addsi3 (stack_pointer_rtx,
GEN_INT (size))); stack_pointer_rtx,
emit_jump_insn (gen_return_internal ()); GEN_INT (size)));
emit_jump_insn (gen_return_internal ());
}
else
{
emit_jump_insn (gen_return ());
}
} }
} }
......
...@@ -305,13 +305,15 @@ enum reg_class { ...@@ -305,13 +305,15 @@ enum reg_class {
#define CONST_OK_FOR_K(VALUE) ((VALUE) == 2) #define CONST_OK_FOR_K(VALUE) ((VALUE) == 2)
#define CONST_OK_FOR_L(VALUE) ((VALUE) == 4) #define CONST_OK_FOR_L(VALUE) ((VALUE) == 4)
#define CONST_OK_FOR_M(VALUE) ((VALUE) == 3) #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) \ #define CONST_OK_FOR_LETTER_P(VALUE, C) \
((C) == 'I' ? CONST_OK_FOR_I (VALUE) : \ ((C) == 'I' ? CONST_OK_FOR_I (VALUE) : \
(C) == 'J' ? CONST_OK_FOR_J (VALUE) : \ (C) == 'J' ? CONST_OK_FOR_J (VALUE) : \
(C) == 'K' ? CONST_OK_FOR_K (VALUE) : \ (C) == 'K' ? CONST_OK_FOR_K (VALUE) : \
(C) == 'L' ? CONST_OK_FOR_L (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. /* Similar, but for floating constants, and defining letters G and H.
...@@ -319,7 +321,9 @@ enum reg_class { ...@@ -319,7 +321,9 @@ enum reg_class {
`G' is a floating-point zero. */ `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. */ /* Stack layout; function entry, exit and calling. */
...@@ -565,8 +569,22 @@ enum reg_class { ...@@ -565,8 +569,22 @@ enum reg_class {
/* Extra constraints. */ /* 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) \ #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. */ /* Maximum number of registers that can appear in a valid memory address. */
...@@ -635,10 +653,11 @@ enum reg_class { ...@@ -635,10 +653,11 @@ enum reg_class {
base = XEXP (X, 1), index = XEXP (X, 0); \ base = XEXP (X, 1), index = XEXP (X, 0); \
if (base != 0 && index != 0) \ if (base != 0 && index != 0) \
{ \ { \
if (GET_CODE (index) == CONST_INT) \ if (CONSTANT_ADDRESS_P (index)) \
goto ADDR; \ goto ADDR; \
if (REG_P (index) \ 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; \ goto ADDR; \
} \ } \
} \ } \
...@@ -668,8 +687,7 @@ enum reg_class { ...@@ -668,8 +687,7 @@ enum reg_class {
/* Nonzero if the constant value X is a legitimate general operand. /* Nonzero if the constant value X is a legitimate general operand.
It is given that X satisfies CONSTANT_P or is a CONST_DOUBLE. */ It is given that X satisfies CONSTANT_P or is a CONST_DOUBLE. */
#define LEGITIMATE_CONSTANT_P(X) \ #define LEGITIMATE_CONSTANT_P(X) 1
(GET_MODE_CLASS (GET_MODE (X)) != MODE_FLOAT) \
/* Tell final.c how to eliminate redundant test instructions. */ /* Tell final.c how to eliminate redundant test instructions. */
...@@ -691,8 +709,31 @@ enum reg_class { ...@@ -691,8 +709,31 @@ enum reg_class {
return it with a return statement. Otherwise, break from the switch. */ return it with a return statement. Otherwise, break from the switch. */
#define CONST_COSTS(RTX,CODE,OUTER_CODE) \ #define CONST_COSTS(RTX,CODE,OUTER_CODE) \
default: { int _zxy= const_costs(RTX, CODE); \ case CONST_INT: \
if(_zxy) return _zxy; break;} /* 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) #define REGISTER_MOVE_COST(CLASS1, CLASS2) (CLASS1 != CLASS2 ? 4 : 0)
......
...@@ -119,10 +119,9 @@ ...@@ -119,10 +119,9 @@
operands[1] = copy_to_mode_reg (SImode, operand1); operands[1] = copy_to_mode_reg (SImode, operand1);
}") }")
;; We could improve loading of some constants with a little work.
(define_insn "" (define_insn ""
[(set (match_operand:SI 0 "general_operand" "=d,a,d,dm,dm,am,am,d,d,a,a,a,x") [(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,a"))] (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[0], SImode)
|| register_operand (operands[1], SImode)" || register_operand (operands[1], SImode)"
"@ "@
...@@ -153,7 +152,6 @@ ...@@ -153,7 +152,6 @@
operands[1] = copy_to_mode_reg (SFmode, operand1); operands[1] = copy_to_mode_reg (SFmode, operand1);
}") }")
;; We could improve loading of some constants with a little work.
(define_insn "" (define_insn ""
[(set (match_operand:SF 0 "general_operand" "=d,a,d,dam,da") [(set (match_operand:SF 0 "general_operand" "=d,a,d,dam,da")
(match_operand:SF 1 "general_operand" "0,0,G,da,daim"))] (match_operand:SF 1 "general_operand" "0,0,G,da,daim"))]
...@@ -167,6 +165,69 @@ ...@@ -167,6 +165,69 @@
mov %1,%0" mov %1,%0"
[(set_attr "cc" "none,none,clobber,none_0hit,none_0hit")]) [(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 ;; TEST INSTRUCTIONS
...@@ -182,8 +243,8 @@ ...@@ -182,8 +243,8 @@
(define_insn "cmpsi" (define_insn "cmpsi"
[(set (cc0) [(set (cc0)
(compare:SI (match_operand:SI 0 "register_operand" "da") (compare (match_operand:SI 0 "register_operand" "da")
(match_operand:SI 1 "register_operand" "dai")))] (match_operand:SI 1 "nonmemory_operand" "dai")))]
"" ""
"cmp %1,%0" "cmp %1,%0"
[(set_attr "cc" "compare")]) [(set_attr "cc" "compare")])
...@@ -193,9 +254,9 @@ ...@@ -193,9 +254,9 @@
;; ---------------------------------------------------------------------- ;; ----------------------------------------------------------------------
(define_expand "addsi3" (define_expand "addsi3"
[(set (match_operand:SI 0 "register_operand" "=da,a,da,x") [(set (match_operand:SI 0 "register_operand" "")
(plus:SI (match_operand:SI 1 "register_operand" "%0,0,0,0") (plus:SI (match_operand:SI 1 "register_operand" "")
(match_operand:SI 2 "nonmemory_operand" "J,L,dai,i")))] (match_operand:SI 2 "nonmemory_operand" "")))]
"" ""
" "
{ {
...@@ -225,6 +286,48 @@ ...@@ -225,6 +286,48 @@
add %2,%0" add %2,%0"
[(set_attr "cc" "set_zn_c0,none_0hit,none_0hit,set_zn_c0,none_0hit")]) [(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 ;; SUBTRACT INSTRUCTIONS
;; ---------------------------------------------------------------------- ;; ----------------------------------------------------------------------
...@@ -232,7 +335,7 @@ ...@@ -232,7 +335,7 @@
(define_insn "subsi3" (define_insn "subsi3"
[(set (match_operand:SI 0 "register_operand" "=da") [(set (match_operand:SI 0 "register_operand" "=da")
(minus:SI (match_operand:SI 1 "register_operand" "0") (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" "sub %2,%0"
[(set_attr "cc" "set_zn_c0")]) [(set_attr "cc" "set_zn_c0")])
...@@ -251,6 +354,19 @@ ...@@ -251,6 +354,19 @@
DONE; 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 ;; MULTIPLY INSTRUCTIONS
...@@ -304,12 +420,19 @@ ...@@ -304,12 +420,19 @@
;; ---------------------------------------------------------------------- ;; ----------------------------------------------------------------------
(define_insn "andsi3" (define_insn "andsi3"
[(set (match_operand:SI 0 "register_operand" "=d") [(set (match_operand:SI 0 "register_operand" "=d,d")
(and:SI (match_operand:SI 1 "register_operand" "%0") (and:SI (match_operand:SI 1 "register_operand" "%0,0")
(match_operand:SI 2 "nonmemory_operand" "di")))] (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 ;; OR INSTRUCTIONS
...@@ -349,9 +472,127 @@ ...@@ -349,9 +472,127 @@
;; ----------------------------------------------------------------- ;; -----------------------------------------------------------------
;; BIT FIELDS ;; 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 ;; Scc INSTRUCTIONS
;; ----------------------------------------------------------------- ;; -----------------------------------------------------------------
...@@ -602,7 +843,7 @@ ...@@ -602,7 +843,7 @@
"" ""
"@ "@
extb %0 extb %0
mov %1,%0" mov %1,%0\;extb %0"
[(set_attr "cc" "none_0hit")]) [(set_attr "cc" "none_0hit")])
(define_insn "extendhisi2" (define_insn "extendhisi2"
...@@ -612,9 +853,8 @@ ...@@ -612,9 +853,8 @@
"" ""
"@ "@
exth %0 exth %0
mov %1,%0" mov %1,%0\;exth %0"
[(set_attr "cc" "none_0hit")]) [(set_attr "cc" "none_0hit")])
;; ---------------------------------------------------------------------- ;; ----------------------------------------------------------------------
;; SHIFTS ;; SHIFTS
...@@ -694,6 +934,12 @@ ...@@ -694,6 +934,12 @@
"movm [d2,d3,a2,a3],(sp)" "movm [d2,d3,a2,a3],(sp)"
[(set_attr "cc" "clobber")]) [(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 ;; Try to combine consecutive updates of the stack pointer (or any
;; other register for that matter). ;; other register for that matter).
(define_peephole (define_peephole
...@@ -710,3 +956,48 @@ ...@@ -710,3 +956,48 @@
return \"add %1,%0\"; return \"add %1,%0\";
}" }"
[(set_attr "cc" "clobber")]) [(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")])
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