(TARGET_WHEN_DEBUGGING): Delete.
(MODES_TIEABLE_P): All modes of the same class are tieable. (CONST_OK_FOR_LETTER_P): Add 'M' for constants valid in a shift. (FUNCTION_PROFILER): Don't call arm_increase_location. (INITIAL_ELIMINATION_OFFSET): Call saved regs are no-longer pushed for functions that don't return. (LEGITIMIZE_ADDRESS): Push constants that will never be legitimate -- symbols and labels -- into registers. Handle DImode better. (DEFAULT_SIGNED_CHAR): Use unsigned unless already defined. (RTX_COSTS): Call arm_rtx_costs. (ADDRESS_COST): Since most operations have the same rtx cost, make the more complex addresses cheaper. (PREDICATE_CODES): Add ROTATERT to shift_operator; and new predicates for reg_or_int_operand and multi_register_push. (DBX_CONTIN_LENGTH): Only define if not already done. (PRINT_OPERAND_ADDRESS): Let arm_print operand output the ", " for shifts. From-SVN: r7536
This commit is contained in:
parent
e8da7c0237
commit
3967692c7e
@ -136,9 +136,6 @@ extern enum processor_type arm_cpu;
|
||||
- if floating point is done by emulation, forget about instruction
|
||||
scheduling. Note that this only saves compilation time; it doesn't
|
||||
matter for the final code. */
|
||||
#ifndef TARGET_WHEN_DEBUGGING
|
||||
#define TARGET_WHEN_DEBUGGING 1
|
||||
#endif
|
||||
|
||||
#define OVERRIDE_OPTIONS \
|
||||
{ \
|
||||
@ -374,8 +371,7 @@ extern enum processor_type arm_cpu;
|
||||
If HARD_REGNO_MODE_OK could produce different values for MODE1 and MODE2,
|
||||
for any hard reg, then this must be 0 for correct output. */
|
||||
#define MODES_TIEABLE_P(MODE1, MODE2) \
|
||||
(((MODE1) == SFmode || (MODE1) == DFmode) \
|
||||
== ((MODE2) == SFmode || (MODE2) == DFmode))
|
||||
(GET_MODE_CLASS (MODE1) == GET_MODE_CLASS (MODE2))
|
||||
|
||||
/* Specify the registers used for certain standard purposes.
|
||||
The values of these macros are register numbers. */
|
||||
@ -494,12 +490,16 @@ enum reg_class
|
||||
I: immediate arithmetic operand (i.e. 8 bits shifted as required).
|
||||
J: valid indexing constants.
|
||||
K: ~value ok in rhs argument of data operand.
|
||||
L: -value ok in rhs argument of data operand. */
|
||||
L: -value ok in rhs argument of data operand.
|
||||
M: 0..32, or a power of 2 (for shifts, or mult done by shift). */
|
||||
#define CONST_OK_FOR_LETTER_P(VALUE, C) \
|
||||
((C) == 'I' ? const_ok_for_arm (VALUE) : \
|
||||
(C) == 'J' ? ((VALUE) < 4096 && (VALUE) > -4096) : \
|
||||
(C) == 'K' ? (const_ok_for_arm (~(VALUE))) : \
|
||||
(C) == 'L' ? (const_ok_for_arm (-(VALUE))) : 0)
|
||||
(C) == 'L' ? (const_ok_for_arm (-(VALUE))) : \
|
||||
(C) == 'M' ? (((VALUE >= 0 && VALUE <= 32)) \
|
||||
|| (((VALUE) & ((VALUE) - 1)) == 0)) \
|
||||
: 0)
|
||||
|
||||
/* For the ARM, `Q' means that this is a memory operand that is just
|
||||
an offset from a register.
|
||||
@ -696,7 +696,6 @@ enum reg_class
|
||||
fprintf(STREAM, "\tmov\t%sip, %slr\n", ARM_REG_PREFIX, ARM_REG_PREFIX); \
|
||||
fprintf(STREAM, "\tbl\tmcount\n"); \
|
||||
fprintf(STREAM, "\t.word\tLP%d\n", (LABELNO)); \
|
||||
arm_increase_location (12); \
|
||||
}
|
||||
|
||||
/* EXIT_IGNORE_STACK should be nonzero if, when returning from a function,
|
||||
@ -749,6 +748,7 @@ enum reg_class
|
||||
its replacement, at the start of a routine. */
|
||||
#define INITIAL_ELIMINATION_OFFSET(FROM, TO, OFFSET) \
|
||||
{ \
|
||||
int volatile_func = arm_volatile_func (); \
|
||||
if ((FROM) == ARG_POINTER_REGNUM && (TO) == HARD_FRAME_POINTER_REGNUM)\
|
||||
(OFFSET) = 0; \
|
||||
else if ((FROM) == FRAME_POINTER_REGNUM && (TO) == STACK_POINTER_REGNUM)\
|
||||
@ -759,19 +759,22 @@ enum reg_class
|
||||
int offset = 12; \
|
||||
int saved_hard_reg = 0; \
|
||||
\
|
||||
for (regno = 0; regno <= 10; regno++) \
|
||||
if (regs_ever_live[regno] && ! call_used_regs[regno]) \
|
||||
saved_hard_reg = 1, offset += 4; \
|
||||
for (regno = 16; regno <=23; regno++) \
|
||||
if (regs_ever_live[regno] && ! call_used_regs[regno]) \
|
||||
offset += 12; \
|
||||
if (! volatile_func) \
|
||||
{ \
|
||||
for (regno = 0; regno <= 10; regno++) \
|
||||
if (regs_ever_live[regno] && ! call_used_regs[regno]) \
|
||||
saved_hard_reg = 1, offset += 4; \
|
||||
for (regno = 16; regno <=23; regno++) \
|
||||
if (regs_ever_live[regno] && ! call_used_regs[regno]) \
|
||||
offset += 12; \
|
||||
} \
|
||||
if ((FROM) == FRAME_POINTER_REGNUM) \
|
||||
(OFFSET) = -offset; \
|
||||
else \
|
||||
{ \
|
||||
if (! regs_ever_live[HARD_FRAME_POINTER_REGNUM]) \
|
||||
offset -= 16; \
|
||||
if (regs_ever_live[14] || saved_hard_reg) \
|
||||
if (! volatile_func && (regs_ever_live[14] || saved_hard_reg)) \
|
||||
offset += 4; \
|
||||
(OFFSET) = (get_frame_size () + 3 & ~3) + offset; \
|
||||
} \
|
||||
@ -1049,48 +1052,66 @@ do \
|
||||
On the ARM, try to convert [REG, #BIGCONST]
|
||||
into ADD BASE, REG, #UPPERCONST and [BASE, #VALIDCONST],
|
||||
where VALIDCONST == 0 in case of TImode. */
|
||||
#define LEGITIMIZE_ADDRESS(X, OLDX, MODE, WIN) \
|
||||
{ \
|
||||
if (GET_CODE (X) == PLUS) \
|
||||
{ \
|
||||
rtx xop0 = XEXP (X, 0); \
|
||||
rtx xop1 = XEXP (X, 1); \
|
||||
\
|
||||
if (BASE_REGISTER_RTX_P (xop0) && GET_CODE (xop1) == CONST_INT) \
|
||||
{ \
|
||||
int n = INTVAL (xop1); \
|
||||
int low_n = ((MODE) == TImode ? 0 \
|
||||
: n >= 0 ? (n & 0xFFF) : -((-n) & 0xFFF)); \
|
||||
rtx base_reg = gen_reg_rtx (SImode); \
|
||||
rtx val = force_operand (gen_rtx (PLUS, SImode, xop0, \
|
||||
gen_rtx (CONST_INT, \
|
||||
VOIDmode, n - low_n)), \
|
||||
0); \
|
||||
emit_move_insn (base_reg, val); \
|
||||
(X) = (low_n == 0 ? base_reg \
|
||||
: gen_rtx (PLUS, SImode, base_reg, \
|
||||
gen_rtx (CONST_INT, VOIDmode, low_n))); \
|
||||
} \
|
||||
else if (BASE_REGISTER_RTX_P (xop1) && GET_CODE (xop0) == CONST_INT) \
|
||||
{ \
|
||||
int n = INTVAL (xop0); \
|
||||
int low_n = ((MODE) == TImode ? 0 \
|
||||
: n >= 0 ? (n & 0xFFF) : -((-n) & 0xFFF)); \
|
||||
rtx base_reg = gen_reg_rtx (SImode); \
|
||||
rtx val = force_operand (gen_rtx (PLUS, SImode, xop1, \
|
||||
gen_rtx (CONST_INT, \
|
||||
VOIDmode, n - low_n)), \
|
||||
0); \
|
||||
emit_move_insn (base_reg, val); \
|
||||
(X) = (low_n == 0 ? base_reg \
|
||||
: gen_rtx (PLUS, SImode, base_reg, \
|
||||
gen_rtx (CONST_INT, VOIDmode, low_n))); \
|
||||
} \
|
||||
} \
|
||||
if (memory_address_p (MODE, X)) \
|
||||
goto win; \
|
||||
#define LEGITIMIZE_ADDRESS(X, OLDX, MODE, WIN) \
|
||||
{ \
|
||||
if (GET_CODE (X) == PLUS) \
|
||||
{ \
|
||||
rtx xop0 = XEXP (X, 0); \
|
||||
rtx xop1 = XEXP (X, 1); \
|
||||
\
|
||||
if (CONSTANT_P (xop0) && ! LEGITIMATE_CONSTANT_P (xop0)) \
|
||||
xop0 = force_reg (SImode, xop0); \
|
||||
if (CONSTANT_P (xop1) && ! LEGITIMATE_CONSTANT_P (xop1)) \
|
||||
xop1 = force_reg (SImode, xop1); \
|
||||
if (BASE_REGISTER_RTX_P (xop0) && GET_CODE (xop1) == CONST_INT) \
|
||||
{ \
|
||||
HOST_WIDE_INT n, low_n; \
|
||||
rtx base_reg, val; \
|
||||
n = INTVAL (xop1); \
|
||||
\
|
||||
if (MODE == DImode) \
|
||||
{ \
|
||||
low_n = n & 0x0f; \
|
||||
n &= ~0x0f; \
|
||||
if (low_n > 4) \
|
||||
{ \
|
||||
n += 16; \
|
||||
low_n -= 16; \
|
||||
} \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
low_n = ((MODE) == TImode ? 0 \
|
||||
: n >= 0 ? (n & 0xfff) : -((-n) & 0xfff)); \
|
||||
n -= low_n; \
|
||||
} \
|
||||
base_reg = gen_reg_rtx (SImode); \
|
||||
val = force_operand (gen_rtx (PLUS, SImode, xop0, \
|
||||
GEN_INT (n)), NULL_RTX); \
|
||||
emit_move_insn (base_reg, val); \
|
||||
(X) = (low_n == 0 ? base_reg \
|
||||
: gen_rtx (PLUS, SImode, base_reg, GEN_INT (low_n))); \
|
||||
} \
|
||||
else if (xop0 != XEXP (X, 0) || xop1 != XEXP (x, 1)) \
|
||||
(X) = gen_rtx (PLUS, SImode, xop0, xop1); \
|
||||
} \
|
||||
else if (GET_CODE (X) == MINUS) \
|
||||
{ \
|
||||
rtx xop0 = XEXP (X, 0); \
|
||||
rtx xop1 = XEXP (X, 1); \
|
||||
\
|
||||
if (CONSTANT_P (xop0)) \
|
||||
xop0 = force_reg (SImode, xop0); \
|
||||
if (CONSTANT_P (xop1) && ! LEGITIMATE_CONSTANT_P (xop1)) \
|
||||
xop1 = force_reg (SImode, xop1); \
|
||||
if (xop0 != XEXP (X, 0) || xop1 != XEXP (X, 1)) \
|
||||
(X) = gen_rtx (MINUS, SImode, xop0, xop1); \
|
||||
} \
|
||||
if (memory_address_p (MODE, X)) \
|
||||
goto WIN; \
|
||||
}
|
||||
|
||||
|
||||
/* Go to LABEL if ADDR (a legitimate address expression)
|
||||
has an effect that depends on the machine mode it is used for. */
|
||||
#define GO_IF_MODE_DEPENDENT_ADDRESS(ADDR,LABEL) \
|
||||
@ -1118,7 +1139,7 @@ do \
|
||||
/* signed 'char' is most compatible, but RISC OS wants it unsigned.
|
||||
unsigned is probably best, but may break some code. */
|
||||
#ifndef DEFAULT_SIGNED_CHAR
|
||||
#define DEFAULT_SIGNED_CHAR 1
|
||||
#define DEFAULT_SIGNED_CHAR 0
|
||||
#endif
|
||||
|
||||
/* Don't cse the address of the function being compiled. */
|
||||
@ -1204,91 +1225,38 @@ do \
|
||||
return -1; \
|
||||
return(7);
|
||||
|
||||
#define ARM_FRAME_RTX(X) \
|
||||
((X) == frame_pointer_rtx || (X) == stack_pointer_rtx \
|
||||
|| (X) == arg_pointer_rtx)
|
||||
|
||||
#define RTX_COSTS(X,CODE,OUTER_CODE) \
|
||||
case MEM: \
|
||||
{ \
|
||||
int num_words = (GET_MODE_SIZE (GET_MODE (X)) > UNITS_PER_WORD) ? 2 : 1;\
|
||||
return (COSTS_N_INSNS (10*num_words)); \
|
||||
} \
|
||||
case MULT: \
|
||||
if (GET_CODE (XEXP (X, 1)) == CONST_INT \
|
||||
&& exact_log2 (INTVAL (XEXP (X, 1))) >= 0) \
|
||||
return rtx_cost (XEXP (X, 0), GET_CODE (X))+1; \
|
||||
return COSTS_N_INSNS (9); \
|
||||
case ASHIFT: \
|
||||
case LSHIFTRT: \
|
||||
case ASHIFTRT: \
|
||||
if (GET_CODE (XEXP (X, 1)) == CONST_INT) \
|
||||
return rtx_cost (XEXP (X, 0), GET_CODE (X))+1; \
|
||||
break; \
|
||||
case MINUS: \
|
||||
{ \
|
||||
enum rtx_code code = GET_CODE (XEXP (X, 1)); \
|
||||
if (code == MULT) \
|
||||
{ \
|
||||
if (GET_CODE (XEXP (XEXP (X, 1), 1)) == CONST_INT \
|
||||
&& exact_log2 (INTVAL (XEXP (XEXP (X, 0), 1))) >= 0) \
|
||||
return COSTS_N_INSNS (1); \
|
||||
break; \
|
||||
} \
|
||||
else if (code == ASHIFT || code == ASHIFTRT || code == LSHIFTRT) \
|
||||
return COSTS_N_INSNS (1); \
|
||||
} /* fall through */ \
|
||||
case PLUS: \
|
||||
case IOR: \
|
||||
case XOR: \
|
||||
case AND: \
|
||||
{ \
|
||||
enum rtx_code code = GET_CODE (XEXP (X, 0)); \
|
||||
if (code == MULT) \
|
||||
{ \
|
||||
if (GET_CODE (XEXP (XEXP (X, 0), 1)) == CONST_INT \
|
||||
&& exact_log2 (INTVAL (XEXP (XEXP (X, 0), 1))) >= 0) \
|
||||
return COSTS_N_INSNS (1); \
|
||||
if (GET_CODE (X) == PLUS) \
|
||||
return COSTS_N_INSNS (12); \
|
||||
break; \
|
||||
} \
|
||||
else if (code == ASHIFT || code == ASHIFTRT || code == LSHIFTRT) \
|
||||
return COSTS_N_INSNS (1); \
|
||||
break; \
|
||||
} \
|
||||
case NOT: \
|
||||
return rtx_cost (XEXP (X, 0), GET_CODE (XEXP (X, 0))); \
|
||||
case IF_THEN_ELSE: \
|
||||
{ \
|
||||
if (GET_CODE (XEXP(X,1)) == PC || GET_CODE (XEXP(X,2)) == PC) \
|
||||
return COSTS_N_INSNS (4); \
|
||||
return COSTS_N_INSNS (1); \
|
||||
} \
|
||||
case SIGN_EXTEND: \
|
||||
return COSTS_N_INSNS (2); \
|
||||
case ZERO_EXTEND: \
|
||||
if (GET_MODE (XEXP (X, 0)) == QImode) \
|
||||
{ \
|
||||
if (GET_CODE (XEXP (X, 0)) == MEM) \
|
||||
return COSTS_N_INSNS (10); \
|
||||
return COSTS_N_INSNS (1); \
|
||||
} \
|
||||
break; \
|
||||
case COMPARE: \
|
||||
if (GET_CODE (XEXP (X, 1)) == REG) \
|
||||
return 4; \
|
||||
case SMIN: \
|
||||
case SMAX: \
|
||||
case UMIN: \
|
||||
case UMAX: \
|
||||
return COSTS_N_INSNS (3); \
|
||||
case ABS: \
|
||||
if (GET_MODE (X) == SImode) \
|
||||
return COSTS_N_INSNS (2); \
|
||||
return COSTS_N_INSNS (1);
|
||||
default: \
|
||||
return arm_rtx_costs (X, CODE, OUTER_CODE);
|
||||
|
||||
/* Moves to and from memory are quite expensive */
|
||||
#define MEMORY_MOVE_COST(MODE) 10
|
||||
|
||||
/* All address computations that can be done are free */
|
||||
#define ADDRESS_COST(x) 2
|
||||
/* All address computations that can be done are free, but rtx cost returns
|
||||
the same for practically all of them. So we weight the differnt types
|
||||
of address here in the order (most pref first):
|
||||
PRE/POST_INC/DEC, SHIFT or NON-INT sum, INT sum, REG, MEM or LABEL. */
|
||||
#define ADDRESS_COST(X) \
|
||||
(10 - ((GET_CODE (X) == MEM || GET_CODE (X) == LABEL_REF \
|
||||
|| GET_CODE (X) == SYMBOL_REF) \
|
||||
? 0 \
|
||||
: ((GET_CODE (X) == PRE_INC || GET_CODE (X) == PRE_DEC \
|
||||
|| GET_CODE (X) == POST_INC || GET_CODE (X) == POST_DEC) \
|
||||
? 10 \
|
||||
: (((GET_CODE (X) == PLUS || GET_CODE (X) == MINUS) \
|
||||
? 6 + (GET_CODE (XEXP (X, 1)) == CONST_INT ? 2 \
|
||||
: ((GET_RTX_CLASS (GET_CODE (XEXP (X, 0))) == '2' \
|
||||
|| GET_RTX_CLASS (GET_CODE (XEXP (X, 0))) == 'c' \
|
||||
|| GET_RTX_CLASS (GET_CODE (XEXP (X, 1))) == '2' \
|
||||
|| GET_RTX_CLASS (GET_CODE (XEXP (X, 1))) == 'c') \
|
||||
? 1 : 0)) \
|
||||
: 4)))))
|
||||
|
||||
|
||||
|
||||
/* Try to generate sequences that don't involve branches, we can then use
|
||||
conditional instructions */
|
||||
@ -1342,7 +1310,7 @@ extern int arm_compare_fp;
|
||||
{"arm_not_operand", {SUBREG, REG, CONST_INT}}, \
|
||||
{"shiftable_operator", {PLUS, MINUS, AND, IOR, XOR}}, \
|
||||
{"minmax_operator", {SMIN, SMAX, UMIN, UMAX}}, \
|
||||
{"shift_operator", {ASHIFT, ASHIFTRT, LSHIFTRT, MULT}}, \
|
||||
{"shift_operator", {ASHIFT, ASHIFTRT, LSHIFTRT, ROTATERT, MULT}}, \
|
||||
{"di_operand", {SUBREG, REG, CONST_INT, CONST_DOUBLE, MEM}}, \
|
||||
{"load_multiple_operation", {PARALLEL}}, \
|
||||
{"store_multiple_operation", {PARALLEL}}, \
|
||||
@ -1350,6 +1318,8 @@ extern int arm_compare_fp;
|
||||
{"arm_rhsm_operand", {SUBREG, REG, CONST_INT, MEM}}, \
|
||||
{"const_shift_operand", {CONST_INT}}, \
|
||||
{"index_operand", {SUBREG, REG, CONST_INT}}, \
|
||||
{"reg_or_int_operand", {SUBREG, REG, CONST_INT}}, \
|
||||
{"multi_register_push", {PARALLEL}}, \
|
||||
{"cc_register", {REG}},
|
||||
|
||||
|
||||
@ -1430,7 +1400,9 @@ extern int arm_compare_fp;
|
||||
#define DBX_DEBUGGING_INFO 1
|
||||
|
||||
/* Acorn dbx moans about continuation chars, so don't use any. */
|
||||
#ifndef DBX_CONTIN_LENGTH
|
||||
#define DBX_CONTIN_LENGTH 0
|
||||
#endif
|
||||
|
||||
/* Output a source filename for the debugger. RISCiX dbx insists that the
|
||||
``desc'' field is set to compiler version number >= 315 (sic). */
|
||||
@ -1709,7 +1681,7 @@ do { char dstr[30]; \
|
||||
case ASHIFT: \
|
||||
case ROTATERT: \
|
||||
{ \
|
||||
fprintf (STREAM, "[%s%s, %s%s%s, ", ARM_REG_PREFIX, \
|
||||
fprintf (STREAM, "[%s%s, %s%s%s", ARM_REG_PREFIX, \
|
||||
base_reg_name, is_minus ? "-" : "", ARM_REG_PREFIX,\
|
||||
reg_names[REGNO (XEXP (index, 0))]); \
|
||||
arm_print_operand (STREAM, index, 'S'); \
|
||||
|
Loading…
Reference in New Issue
Block a user