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)
}
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,6 +113,123 @@ print_operand (file, x, code)
print_operand (file, x, 0);
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:
switch (GET_CODE (x))
{
......@@ -143,6 +239,10 @@ print_operand (file, x, code)
fputc (')', file);
break;
case PLUS:
output_address (x);
break;
case REG:
fprintf (file, "%s", reg_names[REGNO (x)]);
break;
......@@ -152,6 +252,18 @@ print_operand (file, x, code)
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)
......
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