parent
6fcc9690b3
commit
d3ae8277eb
|
@ -95,13 +95,13 @@ enum reg_class reg_class_from_letter[] =
|
|||
#define REG_ODD \
|
||||
( (1 << (int) QImode) | (1 << (int) HImode) | (1 << (int) SImode) \
|
||||
| (1 << (int) QFmode) | (1 << (int) HFmode) | (1 << (int) SFmode) \
|
||||
| (1 << (int) CQImode) | (1 << (int) CHImode))
|
||||
| (1 << (int) CQImode) | (1 << (int) CHImode)| (1<< (int)DFmode) | (1<<(int)DImode))
|
||||
|
||||
#define REG_EVEN \
|
||||
(REG_ODD | (1 << (int) DImode) | (1 << (int) DFmode) \
|
||||
| (1 << (int) CSImode) | (1 << (int) SCmode))
|
||||
(REG_ODD | (1 << (int) CSImode) | (1 << (int) SCmode))
|
||||
|
||||
#define SI_ONLY (1<<(int)SImode)
|
||||
|
||||
int hard_regno_mode_ok[] =
|
||||
{
|
||||
REG_EVEN, REG_ODD, REG_EVEN, REG_ODD,
|
||||
|
@ -327,6 +327,7 @@ print_operand_address (stream, x)
|
|||
'^' increment the local label number
|
||||
'!' dump the constant table
|
||||
'#' output a nop if there is nothing to put in the delay slot
|
||||
'@' print rte or rts depending upon pragma interruptness
|
||||
'R' print the next register or memory location along, ie the lsw in
|
||||
a double word value
|
||||
'O' print a constant without the #
|
||||
|
@ -351,11 +352,17 @@ print_operand (stream, x, code)
|
|||
case '^':
|
||||
lf++;
|
||||
break;
|
||||
case '@':
|
||||
if (pragma_interrupt)
|
||||
fprintf (stream,"rte");
|
||||
else
|
||||
fprintf (stream,"rts");
|
||||
break;
|
||||
case '#':
|
||||
/* Output a nop if there's nothing in the delay slot */
|
||||
if (dbr_sequence_length () == 0)
|
||||
{
|
||||
fprintf (stream, "\n\tor r0,r0\t!wasted slot");
|
||||
fprintf (stream, "\n\tnop");
|
||||
}
|
||||
break;
|
||||
case 'O':
|
||||
|
@ -445,10 +452,22 @@ synth_constant (operands, mode)
|
|||
rtx dst;
|
||||
int i = INTVAL (operands[1]) & 0xffffffff;
|
||||
|
||||
if (CONST_OK_FOR_I (i))
|
||||
if (CONST_OK_FOR_I (i))
|
||||
return 0;
|
||||
|
||||
dst = mode == SImode ? operands[0] : gen_reg_rtx (SImode);
|
||||
if (TARGET_CLEN0 && mode != QImode)
|
||||
return 0;
|
||||
|
||||
if (mode != SImode)
|
||||
{
|
||||
if (reload_in_progress)
|
||||
return 0;
|
||||
dst = gen_reg_rtx (SImode);
|
||||
}
|
||||
else
|
||||
{
|
||||
dst = operands[0];
|
||||
}
|
||||
|
||||
/* 00000000 00000000 11111111 1NNNNNNNN load and zero extend word */
|
||||
if ((i & 0xffffff80) == 0x0000ff80)
|
||||
|
@ -531,10 +550,16 @@ expand_block_move (operands)
|
|||
int constp = (GET_CODE (operands[2]) == CONST_INT);
|
||||
int bytes = (constp ? INTVAL (operands[2]) : 0);
|
||||
enum machine_mode mode;
|
||||
|
||||
/* IF odd then fail */
|
||||
if (!constp || bytes <= 0)
|
||||
return 0;
|
||||
|
||||
/* Don't expand if we'd make the code bigger and we don't want big code */
|
||||
|
||||
if (bytes > 8 && TARGET_SMALLCODE)
|
||||
return 0;
|
||||
|
||||
switch (align)
|
||||
{
|
||||
case 1:
|
||||
|
@ -547,6 +572,7 @@ expand_block_move (operands)
|
|||
mode = SImode;
|
||||
align = 4;
|
||||
}
|
||||
|
||||
if (mode == SImode && constp && bytes < 64 && (bytes % 4 == 0))
|
||||
{
|
||||
char entry[30];
|
||||
|
@ -623,8 +649,8 @@ expand_block_move (operands)
|
|||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Prepare operands for a move define_expand; specifically, one of the
|
||||
|
@ -669,7 +695,6 @@ prepare_move_operands (operands, mode)
|
|||
REGNO (dst) >= FIRST_PSEUDO_REGISTER)
|
||||
return 0;
|
||||
|
||||
|
||||
if (push_operand (dst, mode))
|
||||
return 0;
|
||||
|
||||
|
@ -711,56 +736,6 @@ prepare_move_operands (operands, mode)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* Work out the subword parts to split up a double move
|
||||
into two SI moves - take care to do it in the right order
|
||||
*/
|
||||
|
||||
int
|
||||
prepare_split_double_ops (operands, mode)
|
||||
rtx operands[];
|
||||
enum machine_mode mode;
|
||||
{
|
||||
if (GET_CODE (operands[1]) == REG
|
||||
&& REGNO (operands[1]) > FIRST_PSEUDO_REGISTER)
|
||||
return 0;
|
||||
|
||||
if (GET_CODE (operands[0]) == REG
|
||||
&& REGNO (operands[0]) > FIRST_PSEUDO_REGISTER)
|
||||
return 0;
|
||||
|
||||
/* If we split move insns from memory, it confuses scheduling
|
||||
later on. */
|
||||
if (GET_CODE (operands[1]) == MEM)
|
||||
return 0;
|
||||
if (GET_CODE (operands[0]) == MEM)
|
||||
return 0;
|
||||
|
||||
if (GET_CODE (operands[0]) != REG
|
||||
|| !refers_to_regno_p (REGNO (operands[0]),
|
||||
REGNO (operands[0]) + 1, operands[1], 0))
|
||||
{
|
||||
operands[2] = operand_subword (operands[0], 0, 0, mode);
|
||||
operands[3] = operand_subword (operands[1], 0, 0, mode);
|
||||
operands[4] = operand_subword (operands[0], 1, 0, mode);
|
||||
operands[5] = operand_subword (operands[1], 1, 0, mode);
|
||||
}
|
||||
else
|
||||
{
|
||||
operands[2] = operand_subword (operands[0], 1, 0, mode);
|
||||
operands[3] = operand_subword (operands[1], 1, 0, mode);
|
||||
operands[4] = operand_subword (operands[0], 0, 0, mode);
|
||||
operands[5] = operand_subword (operands[1], 0, 0, mode);
|
||||
}
|
||||
|
||||
if (operands[2] == 0 || operands[3] == 0
|
||||
|| operands[4] == 0 || operands[5] == 0)
|
||||
return 0;
|
||||
|
||||
emit_move_insn (operands[2], operands[3]);
|
||||
emit_move_insn (operands[4], operands[5]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Prepare the operands for an scc instruction; make sure that the
|
||||
compare has been done. */
|
||||
rtx
|
||||
|
@ -824,8 +799,8 @@ output_movedouble (insn, operands, mode)
|
|||
rtx dst = operands[0];
|
||||
rtx src = operands[1];
|
||||
|
||||
fprintf (asm_out_file, "! move double \n");
|
||||
fprintf (asm_out_file, "! pc %04x\n", insn_addresses[INSN_UID (insn)]);
|
||||
/* fprintf (asm_out_file, "! move double \n");
|
||||
fprintf (asm_out_file, "! pc %04x\n", insn_addresses[INSN_UID (insn)]);*/
|
||||
if (GET_CODE (dst) == MEM
|
||||
&& GET_CODE (XEXP (dst, 0)) == POST_INC)
|
||||
{
|
||||
|
@ -1022,8 +997,7 @@ function_epilogue (stream, size)
|
|||
FILE *stream;
|
||||
int size;
|
||||
{
|
||||
fprintf (stream, "\trts\n");
|
||||
fprintf (stream, "\tor r0,r0\n");
|
||||
pragma_interrupt = pragma_trapa = 0;
|
||||
}
|
||||
|
||||
|
||||
|
@ -1085,8 +1059,8 @@ output_far_jump (insn, op)
|
|||
output_asm_insn ("mov.l @r15+,r13", 0);
|
||||
}
|
||||
|
||||
ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L", CODE_LABEL_NUMBER (thislab));
|
||||
output_asm_insn (".align 2", 0);
|
||||
ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L", CODE_LABEL_NUMBER (thislab));
|
||||
output_asm_insn (".long %O0", &op);
|
||||
return "";
|
||||
}
|
||||
|
@ -1100,7 +1074,7 @@ output_branch (logic, insn)
|
|||
int label = lf++;
|
||||
int rn = -1;
|
||||
int need_save;
|
||||
fprintf (asm_out_file, "! pc %04x\n", insn_addresses[INSN_UID (insn)]);
|
||||
/* fprintf (asm_out_file, "! pc %04x\n", insn_addresses[INSN_UID (insn)]);*/
|
||||
|
||||
switch (get_attr_length (insn))
|
||||
{
|
||||
|
@ -1391,7 +1365,7 @@ output_file_start (file, f_options, f_len, W_options, W_len)
|
|||
data_section ();
|
||||
|
||||
|
||||
pos = fprintf (file, "\n! Hitachi SH cc1 (%s) arguments:", version_string);
|
||||
pos = fprintf (file, "\n! Hitachi SH cc1 (%s) (release D-1) arguments:", version_string);
|
||||
output_options (file, f_options, f_len, W_options, W_len,
|
||||
pos, 75, " ", "\n! ", "\n\n");
|
||||
}
|
||||
|
@ -1416,7 +1390,7 @@ shiftcosts (RTX)
|
|||
/* otherwise it will be several insns, but we pretend that it will be more than
|
||||
just the components, so that combine doesn't glue together a load of shifts into
|
||||
one shift which has to be emitted as a bunch anyway - breaking scheduling */
|
||||
return 100;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
|
@ -1435,19 +1409,73 @@ andcosts (RTX)
|
|||
return 3;
|
||||
return 5;
|
||||
}
|
||||
|
||||
int howshift (i)
|
||||
int i;
|
||||
{
|
||||
int total = 0;
|
||||
while (i > 0)
|
||||
{
|
||||
if (i >= 16) {
|
||||
total++;
|
||||
i -= 16;
|
||||
}
|
||||
else if (i >= 8) {
|
||||
total++;
|
||||
i -= 8;
|
||||
}
|
||||
else if (i >= 2) {
|
||||
total++;
|
||||
i -= 2;
|
||||
}
|
||||
else if (i>=1) {
|
||||
total++;
|
||||
i--;
|
||||
}
|
||||
}
|
||||
return total;
|
||||
}
|
||||
|
||||
/* Return the cost of a multiply */
|
||||
int
|
||||
multcosts (RTX)
|
||||
rtx RTX;
|
||||
{
|
||||
/* If mult by a power of 2 then work out how we'd shift to make it */
|
||||
int insn_cost;
|
||||
|
||||
if (GET_CODE (XEXP (RTX, 1)) == CONST_INT)
|
||||
{
|
||||
int i = exact_log2 (INTVAL (XEXP (RTX, 1)));
|
||||
if (i >= 0)
|
||||
insn_cost = howshift (i);
|
||||
else
|
||||
insn_cost = 100000;
|
||||
}
|
||||
if (TARGET_SH2)
|
||||
return 2;
|
||||
{
|
||||
/* We have a mul insn, so we can never take more than the mul and the
|
||||
read of the mac reg, but count more because of the latency and extra reg
|
||||
usage */
|
||||
if (TARGET_SMALLCODE)
|
||||
return 2;
|
||||
if (insn_cost > 5)
|
||||
return 5;
|
||||
return insn_cost;
|
||||
}
|
||||
|
||||
/* If we we're aiming at small code, then just count the number of
|
||||
insns in a multiply call sequence, otherwise, count all the insnsn
|
||||
inside the call. */
|
||||
if (TARGET_SMALLCODE)
|
||||
return 3;
|
||||
return 30;
|
||||
insns in a multiply call sequence */
|
||||
|
||||
if (TARGET_SMALLCODE)
|
||||
{
|
||||
if (insn_cost > 6)
|
||||
return 6;
|
||||
return insn_cost;
|
||||
}
|
||||
|
||||
/* Otherwise count all the insns in the routine we'd be calling too */
|
||||
return 20;
|
||||
}
|
||||
|
||||
/* Code to expand a shift */
|
||||
|
@ -1498,7 +1526,7 @@ gen_shifty_op (code, operands)
|
|||
}
|
||||
|
||||
/* Expand a short sequence inline, longer call a magic routine */
|
||||
if (value < 4)
|
||||
if (value <= 5)
|
||||
{
|
||||
emit_move_insn (wrk, operands[1]);
|
||||
while (value--)
|
||||
|
@ -1621,7 +1649,6 @@ dump_table (scan)
|
|||
}
|
||||
need_align = 1;
|
||||
|
||||
|
||||
for (i = 0; i < pool_size; i++)
|
||||
{
|
||||
pool_node *p = pool_vector + i;
|
||||
|
@ -1634,6 +1661,7 @@ dump_table (scan)
|
|||
if (need_align)
|
||||
{
|
||||
need_align = 0;
|
||||
scan = emit_label_after (gen_label_rtx (), scan);
|
||||
scan = emit_insn_after (gen_align_4 (), scan);
|
||||
}
|
||||
scan = emit_label_after (p->label, scan);
|
||||
|
@ -1643,6 +1671,7 @@ dump_table (scan)
|
|||
if (need_align)
|
||||
{
|
||||
need_align = 0;
|
||||
scan = emit_label_after (gen_label_rtx (), scan);
|
||||
scan = emit_insn_after (gen_align_4 (), scan);
|
||||
}
|
||||
scan = emit_label_after (p->label, scan);
|
||||
|
@ -1694,6 +1723,15 @@ int
|
|||
hi_const (src)
|
||||
rtx src;
|
||||
{
|
||||
if (GET_CODE (src) == CONST
|
||||
&& GET_CODE (XEXP (src, 0)) == SIGN_EXTEND
|
||||
&& GET_CODE (XEXP (XEXP (src, 0), 0)) == SYMBOL_REF)
|
||||
return 1;
|
||||
|
||||
if (TARGET_SHORTADDR
|
||||
&& GET_CODE (src) == SYMBOL_REF)
|
||||
return 1;
|
||||
|
||||
return (GET_CODE (src) == CONST_INT
|
||||
&& INTVAL (src) >= -32768
|
||||
&& INTVAL (src) <= 32767);
|
||||
|
@ -1826,6 +1864,8 @@ machine_dependent_reorg (first)
|
|||
{
|
||||
/* This is an HI source, clobber the dest to get the mode right too */
|
||||
mode = HImode;
|
||||
while (GET_CODE (dst) == SUBREG)
|
||||
dst = SUBREG_REG (dst);
|
||||
dst = gen_rtx (REG, HImode, REGNO (dst));
|
||||
}
|
||||
lab = add_constant (src, mode);
|
||||
|
@ -1860,9 +1900,15 @@ from_compare (operands, code)
|
|||
rtx *operands;
|
||||
int code;
|
||||
{
|
||||
if (code != EQ && code != NE)
|
||||
{
|
||||
/* Force args into regs, since we can't use constants here */
|
||||
sh_compare_op0 = force_reg (SImode, sh_compare_op0);
|
||||
if (sh_compare_op1 != const0_rtx)
|
||||
sh_compare_op1 = force_reg (SImode, sh_compare_op1);
|
||||
}
|
||||
operands[1] = sh_compare_op0;
|
||||
operands[2] = force_reg (SImode, sh_compare_op1);
|
||||
operands[1] = force_reg (SImode, operands[1]);
|
||||
operands[2] = sh_compare_op1;
|
||||
}
|
||||
|
||||
/* Non-zero if x is EQ or NE */
|
||||
|
@ -1973,6 +2019,7 @@ sh_expand_epilogue ()
|
|||
current_function_anonymous_args = 0;
|
||||
for (i = 0; i < 32; i++)
|
||||
shiftsyms[i] = 0;
|
||||
|
||||
}
|
||||
|
||||
/* Define the offset between two registers, one to be eliminated, and
|
||||
|
@ -2041,7 +2088,8 @@ handle_pragma (file)
|
|||
|
||||
/* insn expand helpers */
|
||||
|
||||
/* Emit insns to perform a call. If TARGET_SMALLCALL, then load the
|
||||
/* Emit insns to perform a call.
|
||||
If TARGET_SHORTADDR then use a bsr. If TARGET_SMALLCALL, then load the
|
||||
target address into r1 and call __saveargs, otherwise
|
||||
perform the standard call sequence */
|
||||
|
||||
|
@ -2055,23 +2103,29 @@ expand_acall (isa_retval, operands)
|
|||
rtx call_target = operands[isa_retval + 0];
|
||||
rtx numargs = operands[isa_retval + 1];
|
||||
|
||||
if (GET_CODE (call_target) == MEM)
|
||||
if (TARGET_BSR)
|
||||
{
|
||||
call_target = force_reg (Pmode,
|
||||
XEXP (call_target, 0));
|
||||
}
|
||||
if (TARGET_SMALLCALL)
|
||||
{
|
||||
rtx tmp = gen_reg_rtx (SImode);
|
||||
rtx r1 = gen_rtx (REG, SImode, 1);
|
||||
emit_move_insn (tmp, gen_rtx (SYMBOL_REF, SImode, "__saveargs"));
|
||||
emit_move_insn (r1, call_target);
|
||||
emit_insn (gen_rtx (USE, VOIDmode, r1));
|
||||
call_target = tmp;
|
||||
call = gen_rtx (CALL, VOIDmode, call_target, numargs);
|
||||
}
|
||||
else {
|
||||
|
||||
call = gen_rtx (CALL, VOIDmode, gen_rtx (MEM, SImode, call_target), numargs);
|
||||
if (GET_CODE (call_target) == MEM)
|
||||
{
|
||||
call_target = force_reg (Pmode,
|
||||
XEXP (call_target, 0));
|
||||
}
|
||||
if (TARGET_SMALLCALL)
|
||||
{
|
||||
rtx tmp = gen_reg_rtx (SImode);
|
||||
rtx r1 = gen_rtx (REG, SImode, 1);
|
||||
emit_move_insn (tmp, gen_rtx (SYMBOL_REF, SImode, "__saveargs"));
|
||||
emit_move_insn (r1, call_target);
|
||||
emit_insn (gen_rtx (USE, VOIDmode, r1));
|
||||
call_target = tmp;
|
||||
}
|
||||
|
||||
call = gen_rtx (CALL, VOIDmode, gen_rtx (MEM, SImode, call_target), numargs);
|
||||
}
|
||||
if (isa_retval)
|
||||
{
|
||||
call = gen_rtx (SET, VOIDmode, ret, call);
|
||||
|
@ -2080,7 +2134,7 @@ expand_acall (isa_retval, operands)
|
|||
emit_call_insn (gen_rtx (PARALLEL, VOIDmode,
|
||||
gen_rtvec (2,
|
||||
call,
|
||||
gen_rtx (CLOBBER, VOIDmode, gen_rtx (REG, SImode, 17)))));
|
||||
gen_rtx (CLOBBER, VOIDmode, gen_rtx (REG, SImode, 17)))));
|
||||
|
||||
}
|
||||
|
||||
|
@ -2132,12 +2186,28 @@ general_movdst_operand (op, mode)
|
|||
enum machine_mode mode;
|
||||
{
|
||||
if (GET_CODE (op) == MEM
|
||||
&& GET_CODE (XEXP (op, 0)) == PRE_INC)
|
||||
&& (GET_CODE (XEXP (op, 0)) == PRE_INC
|
||||
|| GET_CODE (XEXP (op, 0)) == POST_INC
|
||||
|| GET_CODE (XEXP (op, 0)) == POST_DEC))
|
||||
return 0;
|
||||
|
||||
return general_operand (op, mode);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Returns 1 if OP is valid destination for a bsr. */
|
||||
|
||||
int
|
||||
bsr_operand (op, mode)
|
||||
rtx op;
|
||||
enum machine_mode mode;
|
||||
{
|
||||
if (GET_CODE (op) == SYMBOL_REF)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Returns 1 if OP is an immediate ok for a byte index. */
|
||||
|
||||
int
|
||||
|
@ -2247,3 +2317,88 @@ logical_operand (op, mode)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* Returns 1 if OP is a valid operand for a MAC instruction,
|
||||
either a register or indirect memory. For now we don't
|
||||
try and recognise a mac insn */
|
||||
|
||||
int
|
||||
mac_operand (op, mode)
|
||||
rtx op;
|
||||
enum machine_mode mode;
|
||||
{
|
||||
if (arith_reg_operand (op, mode))
|
||||
return 1;
|
||||
#if 0
|
||||
Turned off till mac is understood
|
||||
if (GET_CODE (op) == MEM)
|
||||
return 1;
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Determine where to put an argument to a function.
|
||||
Value is zero to push the argument on the stack,
|
||||
or a hard register in which to store the argument.
|
||||
|
||||
MODE is the argument's machine mode.
|
||||
TYPE is the data type of the argument (as a tree).
|
||||
This is null for libcalls where that information may
|
||||
not be available.
|
||||
CUM is a variable of type CUMULATIVE_ARGS which gives info about
|
||||
the preceding args and about the function being called.
|
||||
NAMED is nonzero if this argument is a named parameter
|
||||
(otherwise it is an extra parameter matching an ellipsis). */
|
||||
|
||||
rtx
|
||||
sh_function_arg (cum, mode, type, named)
|
||||
CUMULATIVE_ARGS cum;
|
||||
enum machine_mode mode;
|
||||
tree type;
|
||||
int named;
|
||||
{
|
||||
if (named)
|
||||
{
|
||||
int rr = (ROUND_REG ((cum), (mode)));
|
||||
|
||||
if (rr < NPARM_REGS)
|
||||
{
|
||||
return ((((mode) != BLKmode
|
||||
&& ((type)==0 || ! TREE_ADDRESSABLE ((tree)(type)))
|
||||
&& ((type)==0 || (mode) != BLKmode
|
||||
|| (TYPE_ALIGN ((type)) % PARM_BOUNDARY == 0))
|
||||
? gen_rtx (REG, (mode),
|
||||
(FIRST_PARM_REG + rr)): 0)));
|
||||
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* For an arg passed partly in registers and partly in memory,
|
||||
this is the number of registers used.
|
||||
For args passed entirely in registers or entirely in memory, zero.
|
||||
Any arg that starts in the first 4 regs but won't entirely fit in them
|
||||
needs partial registers on the SH. */
|
||||
|
||||
int
|
||||
sh_function_arg_partial_nregs (CUM, MODE, TYPE, NAMED)
|
||||
CUMULATIVE_ARGS CUM;
|
||||
enum machine_mode MODE;
|
||||
tree TYPE;
|
||||
int NAMED;
|
||||
{
|
||||
if ((CUM) < NPARM_REGS)
|
||||
{
|
||||
if (((TYPE)==0 || ! TREE_ADDRESSABLE ((tree)(TYPE)))
|
||||
&& ((TYPE)==0 || (MODE) != BLKmode
|
||||
|| (TYPE_ALIGN ((TYPE)) % PARM_BOUNDARY == 0))
|
||||
&& ((CUM) + ((MODE) == BLKmode
|
||||
? ROUND_ADVANCE (int_size_in_bytes (TYPE))
|
||||
: ROUND_ADVANCE (GET_MODE_SIZE (MODE))) - NPARM_REGS > 0))
|
||||
{
|
||||
return NPARM_REGS - CUM;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -78,6 +78,11 @@ extern int target_flags;
|
|||
#define CONSTLEN_2_BIT (1<<20)
|
||||
#define CONSTLEN_3_BIT (1<<21)
|
||||
#define HITACHI_BIT (1<<22)
|
||||
#define PARANOID_BIT (1<<23)
|
||||
#define RETR2_BIT (1<<24)
|
||||
#define CONSTLEN_0_BIT (1<<25)
|
||||
#define BSR_BIT (1<<26)
|
||||
#define SHORTADDR_BIT (1<<27)
|
||||
|
||||
/* Nonzero if we should generate code using type 0 insns */
|
||||
#define TARGET_SH0 (target_flags & SH0_BIT)
|
||||
|
@ -131,8 +136,16 @@ extern int target_flags;
|
|||
/* Select max size of computed constant code sequences to be 3 insns */
|
||||
#define TARGET_CLEN3 (target_flags & CONSTLEN_3_BIT)
|
||||
|
||||
/* Select max size of computed constant code sequences to be 0 insns - ie don't do it */
|
||||
#define TARGET_CLEN0 (target_flags & CONSTLEN_0_BIT)
|
||||
|
||||
/* Nonzero if using Hitachi's calling convention */
|
||||
#define TARGET_HITACHI (target_flags & HITACHI_BIT)
|
||||
#define TARGET_HITACHI (target_flags & HITACHI_BIT)
|
||||
#define TARGET_PARANOID (target_flags & PARANOID_BIT)
|
||||
#define TARGET_RETR2 (target_flags & RETR2_BIT)
|
||||
#define TARGET_SHORTADDR (target_flags & SHORTADDR_BIT)
|
||||
#define TARGET_BSR (target_flags & BSR_BIT)
|
||||
|
||||
|
||||
#define TARGET_SWITCHES \
|
||||
{ {"isize", ( ISIZE_BIT) }, \
|
||||
|
@ -150,8 +163,13 @@ extern int target_flags;
|
|||
{"R", ( R_BIT) }, \
|
||||
{"nosave", ( NOSAVE_BIT) }, \
|
||||
{"clen3", ( CONSTLEN_3_BIT) }, \
|
||||
{"clen0", ( CONSTLEN_0_BIT) }, \
|
||||
{"smallcall", ( SMALLCALL_BIT) }, \
|
||||
{"hitachi", ( HITACHI_BIT) }, \
|
||||
{"paranoid", ( PARANOID_BIT) }, \
|
||||
{"r2", ( RETR2_BIT) }, \
|
||||
{"shortaddr", ( SHORTADDR_BIT) }, \
|
||||
{"bsr", ( BSR_BIT) }, \
|
||||
{"", TARGET_DEFAULT} \
|
||||
}
|
||||
|
||||
|
@ -177,7 +195,10 @@ do { \
|
|||
\
|
||||
optimize = 1; \
|
||||
flag_delayed_branch = 1; \
|
||||
\
|
||||
/* But never run scheduling before reload, since than can \
|
||||
break global alloc, and generates slower code anyway due \
|
||||
to the pressure on R0. */ \
|
||||
flag_schedule_insns = 0; \
|
||||
if (max_si) \
|
||||
max_count_si = atoi (max_si); \
|
||||
else \
|
||||
|
@ -186,6 +207,8 @@ do { \
|
|||
max_count_hi = atoi (max_hi); \
|
||||
else \
|
||||
max_count_hi = 505; \
|
||||
if (TARGET_BSR) \
|
||||
flag_no_function_cse = 1; \
|
||||
} while (0)
|
||||
|
||||
|
||||
|
@ -296,7 +319,10 @@ do { \
|
|||
#define FIRST_PSEUDO_REGISTER 22
|
||||
|
||||
/* 1 for registers that have pervasive standard uses
|
||||
and are not available for the register allocator. */
|
||||
and are not available for the register allocator.
|
||||
|
||||
mach register is fixed 'cause it's only 10 bits wide */
|
||||
|
||||
/* r0 r1 r2 r3
|
||||
r4 r5 r6 r7
|
||||
r8 r9 r10 r11
|
||||
|
@ -312,6 +338,7 @@ do { \
|
|||
1, 1, 1, 1, \
|
||||
1, 1}
|
||||
|
||||
|
||||
/* 1 for registers not available across function calls.
|
||||
These must include the FIXED_REGISTERS and also any
|
||||
registers that can be used without being saved.
|
||||
|
@ -591,7 +618,7 @@ extern enum reg_class reg_class_from_letter[];
|
|||
These two macros are used only in other macro definitions below. */
|
||||
#define NPARM_REGS 4
|
||||
#define FIRST_PARM_REG 4
|
||||
#define FIRST_RET_REG 0
|
||||
#define FIRST_RET_REG (TARGET_RETR2 ? 2 : 0)
|
||||
|
||||
/* Define this if pushing a word on the stack
|
||||
makes the stack pointer a smaller address. */
|
||||
|
@ -671,7 +698,8 @@ extern enum reg_class reg_class_from_letter[];
|
|||
/* Round a register number up to a proper boundary for an arg of mode
|
||||
MODE.
|
||||
|
||||
We round to an even reg for things larger than a word */
|
||||
The SH doesn't care about double alignment, so we only
|
||||
round doubles to even regs when asked to explicitly. */
|
||||
|
||||
#define ROUND_REG(X, MODE) \
|
||||
((TARGET_ALIGN_DOUBLE \
|
||||
|
@ -718,23 +746,20 @@ extern enum reg_class reg_class_from_letter[];
|
|||
NPARM_REGS words is at least partially passed in a register unless
|
||||
its data type forbids. */
|
||||
|
||||
#define FUNCTION_ARG(CUM, MODE, TYPE, NAMED) \
|
||||
(NAMED && ROUND_REG ((CUM), (MODE)) < NPARM_REGS \
|
||||
&& (MODE) != BLKmode \
|
||||
&& ((TYPE)==0 || ! TREE_ADDRESSABLE ((tree)(TYPE))) \
|
||||
&& ((TYPE)==0 || (MODE) != BLKmode \
|
||||
|| (TYPE_ALIGN ((TYPE)) % PARM_BOUNDARY == 0)) \
|
||||
? gen_rtx (REG, (MODE), \
|
||||
(FIRST_PARM_REG + ROUND_REG ((CUM), (MODE)))) \
|
||||
: 0)
|
||||
|
||||
#define FUNCTION_ARG(CUM, MODE, TYPE, NAMED) \
|
||||
sh_function_arg (CUM, MODE, TYPE, NAMED)
|
||||
|
||||
extern struct rtx_def *sh_function_arg();
|
||||
|
||||
/* For an arg passed partly in registers and partly in memory,
|
||||
this is the number of registers used.
|
||||
For args passed entirely in registers or entirely in memory, zero.
|
||||
|
||||
We never split args */
|
||||
We sometimes split args */
|
||||
|
||||
#define FUNCTION_ARG_PARTIAL_NREGS(CUM, MODE, TYPE, NAMED) 0
|
||||
#define FUNCTION_ARG_PARTIAL_NREGS(CUM, MODE, TYPE, NAMED) \
|
||||
sh_function_arg_partial_nregs (CUM, MODE, TYPE, NAMED)
|
||||
|
||||
extern int current_function_anonymous_args;
|
||||
|
||||
|
@ -809,10 +834,10 @@ extern int current_function_anonymous_args;
|
|||
|
||||
|
||||
/* Addressing modes, and classification of registers for them. */
|
||||
/*#define HAVE_POST_INCREMENT 1*/
|
||||
#define HAVE_POST_INCREMENT 1
|
||||
/*#define HAVE_PRE_INCREMENT 1*/
|
||||
/*#define HAVE_POST_DECREMENT 1*/
|
||||
/*#define HAVE_PRE_DECREMENT 1*/
|
||||
#define HAVE_PRE_DECREMENT 1
|
||||
|
||||
/* Macros to check register numbers against specific register classes. */
|
||||
|
||||
|
@ -853,6 +878,7 @@ extern int current_function_anonymous_args;
|
|||
The symbol REG_OK_STRICT causes the latter definition to be used. */
|
||||
|
||||
#define MODE_DISP_OK_4(X,MODE) ((GET_MODE_SIZE(MODE)==4) && ((unsigned)INTVAL(X)<64))
|
||||
#define MODE_DISP_OK_8(X,MODE) ((GET_MODE_SIZE(MODE)==8) && ((unsigned)INTVAL(X)<60))
|
||||
#define MODE_DISP_OK_2(X,MODE) ((GET_MODE_SIZE(MODE)==2) && ((unsigned)INTVAL(X)<32) && TARGET_TRYR0)
|
||||
#define MODE_DISP_OK_1(X,MODE) ((GET_MODE_SIZE(MODE)==1) && ((unsigned)INTVAL(X)<16) && TARGET_TRYR0)
|
||||
|
||||
|
@ -870,7 +896,7 @@ extern int current_function_anonymous_args;
|
|||
(REGNO (X) == 0 || REGNO(X) >= FIRST_PSEUDO_REGISTER)
|
||||
|
||||
#define REG_OK_FOR_PRE_POST_P(X) \
|
||||
(REGNO (X) <= 16)
|
||||
(REG_OK_FOR_INDEX_P (X))
|
||||
|
||||
#else
|
||||
/* Nonzero if X is a hard reg that can be used as a base reg. */
|
||||
|
@ -882,7 +908,7 @@ extern int current_function_anonymous_args;
|
|||
REGNO_OK_FOR_INDEX_P (REGNO (X))
|
||||
|
||||
#define REG_OK_FOR_PRE_POST_P(X) \
|
||||
(REGNO (X) <= 16)
|
||||
(REGNO_OK_FOR_INDEX_P (REGNO (X)))
|
||||
#endif
|
||||
|
||||
/* The Q is a pc relative load operand */
|
||||
|
@ -943,6 +969,7 @@ extern int current_function_anonymous_args;
|
|||
if (GET_CODE (OP) == CONST_INT) \
|
||||
{ \
|
||||
if (MODE_DISP_OK_4 (OP, MODE)) goto LABEL; \
|
||||
if (MODE_DISP_OK_8 (OP, MODE)) goto LABEL; \
|
||||
if (MODE_DISP_OK_2 (OP, MODE)) goto LABEL; \
|
||||
if (MODE_DISP_OK_1 (OP, MODE)) goto LABEL; \
|
||||
} \
|
||||
|
@ -961,11 +988,11 @@ extern int current_function_anonymous_args;
|
|||
{ \
|
||||
rtx xop0 = XEXP(X,0); \
|
||||
rtx xop1 = XEXP(X,1); \
|
||||
if (GET_MODE_SIZE(MODE) <= 4 && BASE_REGISTER_RTX_P (xop0)) \
|
||||
if (GET_MODE_SIZE(MODE) <= 8 && BASE_REGISTER_RTX_P (xop0)) \
|
||||
GO_IF_LEGITIMATE_INDEX (MODE, REGNO (xop0), xop1, LABEL); \
|
||||
if (GET_MODE_SIZE(MODE) <= 4 && BASE_REGISTER_RTX_P (xop1)) \
|
||||
if (GET_MODE_SIZE(MODE) <= 8 && BASE_REGISTER_RTX_P (xop1)) \
|
||||
GO_IF_LEGITIMATE_INDEX (MODE, REGNO (xop1), xop0, LABEL); \
|
||||
if (GET_MODE_SIZE(MODE)<=4) { \
|
||||
if (GET_MODE_SIZE(MODE)<= 4) { \
|
||||
if(BASE_REGISTER_RTX_P(xop1) && \
|
||||
INDEX_REGISTER_RTX_P(xop0)) goto LABEL; \
|
||||
if(INDEX_REGISTER_RTX_P(xop1) && \
|
||||
|
@ -992,9 +1019,9 @@ extern int current_function_anonymous_args;
|
|||
It is always safe for this macro to do nothing. It exists to recognize
|
||||
opportunities to optimize the output.
|
||||
|
||||
On the SH we don't try anything */
|
||||
*/
|
||||
|
||||
#define LEGITIMIZE_ADDRESS(X, OLDX, MODE, WIN) ;
|
||||
#define LEGITIMIZE_ADDRESS(X,OLDX,MODE,WIN) ;
|
||||
|
||||
/* Go to LABEL if ADDR (a legitimate address expression)
|
||||
has an effect that depends on the machine mode it is used for. */
|
||||
|
@ -1102,7 +1129,6 @@ extern int current_function_anonymous_args;
|
|||
return COSTS_N_INSNS (multcosts (X)); \
|
||||
case ASHIFT: \
|
||||
case ASHIFTRT: \
|
||||
case LSHIFTRT: \
|
||||
return COSTS_N_INSNS (shiftcosts (X)) ; \
|
||||
case DIV: \
|
||||
case UDIV: \
|
||||
|
@ -1174,13 +1200,6 @@ extern int current_function_anonymous_args;
|
|||
#define CTORS_SECTION_ASM_OP "\t.section\t.ctors\n"
|
||||
#define DTORS_SECTION_ASM_OP "\t.section\t.dtors\n"
|
||||
#define INIT_SECTION_ASM_OP "\t.section\t.init\n"
|
||||
|
||||
/* Assemble generic sections.
|
||||
This is currently only used to support section attributes. */
|
||||
|
||||
#define ASM_OUTPUT_SECTION_NAME(FILE, NAME) \
|
||||
fprintf (FILE, ".section\t%s\n", NAME)
|
||||
|
||||
#define EXTRA_SECTIONS in_ctors, in_dtors
|
||||
|
||||
#define EXTRA_SECTION_FUNCTIONS \
|
||||
|
@ -1203,6 +1222,12 @@ dtors_section() \
|
|||
} \
|
||||
}
|
||||
|
||||
/* Assemble generic sections.
|
||||
This is currently only used to support section attributes. */
|
||||
|
||||
#define ASM_OUTPUT_SECTION_NAME(FILE, NAME) \
|
||||
do { fprintf (FILE, ".section\t%s\n", NAME); } while (0)
|
||||
|
||||
#define ASM_OUTPUT_CONSTRUCTOR(FILE,NAME) \
|
||||
do { ctors_section(); fprintf(FILE,"\t.long\t_%s\n", NAME); } while (0)
|
||||
|
||||
|
@ -1410,7 +1435,7 @@ do { char dstr[30]; \
|
|||
#define PRINT_OPERAND_ADDRESS(STREAM,X) print_operand_address (STREAM, X)
|
||||
|
||||
#define PRINT_OPERAND_PUNCT_VALID_P(CHAR) \
|
||||
((CHAR)=='.' || (CHAR) == '#' || (CHAR) == '*' || (CHAR) == '^' || (CHAR)=='!')
|
||||
((CHAR)=='.' || (CHAR) == '#' || (CHAR) == '*' || (CHAR) == '^' || (CHAR)=='!' || (CHAR)=='@')
|
||||
|
||||
|
||||
extern struct rtx_def *sh_compare_op0;
|
||||
|
@ -1418,6 +1443,7 @@ extern struct rtx_def *sh_compare_op1;
|
|||
extern struct rtx_def *prepare_scc_operands();
|
||||
extern struct rtx_def *table_lab;
|
||||
|
||||
|
||||
extern enum attr_cpu sh_cpu; /* target cpu */
|
||||
|
||||
/* Declare functions defined in sh.c and used in templates. */
|
||||
|
@ -1441,7 +1467,7 @@ extern char *output_far_jump();
|
|||
/* Set when processing a function with pragma interrupt turned on. */
|
||||
|
||||
extern int pragma_interrupt;
|
||||
#define MOVE_RATIO 16
|
||||
#define MOVE_RATIO (TARGET_SMALLCODE ? 4 : 16)
|
||||
|
||||
char *max_si;
|
||||
char *max_hi;
|
||||
|
|
Loading…
Reference in New Issue