mirror of
git://gcc.gnu.org/git/gcc.git
synced 2024-12-24 05:18:55 +08:00
c4x.c (c4x_emit_move_sequence): Use loadqi_big_constant and loadhi_big_constant if applicable.
* config/c4x/c4x.c (c4x_emit_move_sequence): Use loadqi_big_constant and loadhi_big_constant if applicable. * config/c4x/c4x.md (loadqi_big_constant, loadhi_big_constant): Tweak and add new splitter.s From-SVN: r35339
This commit is contained in:
parent
b864825e85
commit
8d485e2d2f
@ -1,3 +1,10 @@
|
||||
2000-07-30 Michael Hayes <m.hayes@elec.canterbury.ac.nz>
|
||||
|
||||
* config/c4x/c4x.c (c4x_emit_move_sequence): Use loadqi_big_constant
|
||||
and loadhi_big_constant if applicable.
|
||||
* config/c4x/c4x.md (loadqi_big_constant, loadhi_big_constant): Tweak
|
||||
and add new splitter.s
|
||||
|
||||
2000-07-30 Michael Hayes <m.hayes@elec.canterbury.ac.nz>
|
||||
|
||||
* config/c4x/c4x.c (c4x_rptb_insert): Make more robust.
|
||||
|
@ -60,7 +60,7 @@ rtx floatunshihf2_libfunc;
|
||||
|
||||
static int c4x_leaf_function;
|
||||
|
||||
static char *float_reg_names[] = FLOAT_REGISTER_NAMES;
|
||||
static const char *float_reg_names[] = FLOAT_REGISTER_NAMES;
|
||||
|
||||
/* Array of the smallest class containing reg number REGNO, indexed by
|
||||
REGNO. Used by REGNO_REG_CLASS in c4x.h. We assume that all these
|
||||
@ -161,6 +161,27 @@ static tree pure_tree = NULL_TREE;
|
||||
static tree noreturn_tree = NULL_TREE;
|
||||
static tree interrupt_tree = NULL_TREE;
|
||||
|
||||
/* Forward declarations */
|
||||
static void c4x_add_gc_roots PARAMS ((void));
|
||||
static int c4x_isr_reg_used_p PARAMS ((unsigned int));
|
||||
static int c4x_leaf_function_p PARAMS ((void));
|
||||
static int c4x_assembler_function_p PARAMS ((void));
|
||||
static int c4x_immed_float_p PARAMS ((rtx));
|
||||
static int c4x_a_register PARAMS ((rtx));
|
||||
static int c4x_x_register PARAMS ((rtx));
|
||||
static int c4x_immed_int_constant PARAMS ((rtx));
|
||||
static int c4x_immed_float_constant PARAMS ((rtx));
|
||||
static int c4x_K_constant PARAMS ((rtx));
|
||||
static int c4x_N_constant PARAMS ((rtx));
|
||||
static int c4x_O_constant PARAMS ((rtx));
|
||||
static int c4x_R_indirect PARAMS ((rtx));
|
||||
static int c4x_S_indirect PARAMS ((rtx));
|
||||
static void c4x_S_address_parse PARAMS ((rtx , int *, int *, int *, int *));
|
||||
static int c4x_valid_operands PARAMS ((enum rtx_code, rtx *,
|
||||
enum machine_mode, int));
|
||||
static int c4x_arn_reg_operand PARAMS ((rtx, enum machine_mode, unsigned int));
|
||||
static int c4x_arn_mem_operand PARAMS ((rtx, enum machine_mode, unsigned int));
|
||||
static void c4x_check_attribute PARAMS ((const char *, tree, tree, tree *));
|
||||
|
||||
/* Called to register all of our global variables with the garbage
|
||||
collector. */
|
||||
@ -374,7 +395,7 @@ c4x_output_ascii (stream, ptr, len)
|
||||
|
||||
int
|
||||
c4x_hard_regno_mode_ok (regno, mode)
|
||||
int regno;
|
||||
unsigned int regno;
|
||||
enum machine_mode mode;
|
||||
{
|
||||
switch (mode)
|
||||
@ -688,7 +709,7 @@ c4x_va_arg (valist, type)
|
||||
|
||||
static int
|
||||
c4x_isr_reg_used_p (regno)
|
||||
int regno;
|
||||
unsigned int regno;
|
||||
{
|
||||
/* Don't save/restore FP or ST, we handle them separately. */
|
||||
if (regno == FRAME_POINTER_REGNUM
|
||||
@ -752,7 +773,7 @@ c4x_assembler_function_p ()
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
int
|
||||
c4x_interrupt_function_p ()
|
||||
{
|
||||
if (lookup_attribute ("interrupt",
|
||||
@ -769,55 +790,75 @@ c4x_interrupt_function_p ()
|
||||
&& ISDIGIT (current_function_name[6]);
|
||||
}
|
||||
|
||||
|
||||
/* Write function prologue. */
|
||||
|
||||
void
|
||||
c4x_function_prologue (file, size)
|
||||
FILE *file;
|
||||
int size;
|
||||
c4x_expand_prologue ()
|
||||
{
|
||||
int regno;
|
||||
unsigned int regno;
|
||||
int size = get_frame_size ();
|
||||
rtx insn;
|
||||
|
||||
/* In functions where ar3 is not used but frame pointers are still
|
||||
specified, frame pointers are not adjusted (if >= -O2) and this is
|
||||
used so it won't be needlessly push the frame pointer. */
|
||||
/* In functions where ar3 is not used but frame pointers are still
|
||||
specified, frame pointers are not adjusted (if >= -O2) and this
|
||||
is used so it won't needlessly push the frame pointer. */
|
||||
int dont_push_ar3;
|
||||
|
||||
/* For __assembler__ function don't build a prologue. */
|
||||
if (c4x_assembler_function_p ())
|
||||
{
|
||||
fprintf (file, "; *** Assembler Function ***\n");
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef FUNCTION_BLOCK_PROFILER_EXIT
|
||||
if (profile_block_flag == 2)
|
||||
{
|
||||
FUNCTION_BLOCK_PROFILER_EXIT
|
||||
}
|
||||
#endif
|
||||
|
||||
/* For __interrupt__ function build specific prologue. */
|
||||
if (c4x_interrupt_function_p ())
|
||||
{
|
||||
c4x_leaf_function = c4x_leaf_function_p ();
|
||||
fprintf (file, "; *** Interrupt Entry %s ***\n",
|
||||
c4x_leaf_function ? "(leaf)" : "");
|
||||
|
||||
fprintf (file, "\tpush\tst\n");
|
||||
|
||||
insn = emit_insn (gen_push_st ());
|
||||
RTX_FRAME_RELATED_P (insn) = 1;
|
||||
if (size)
|
||||
{
|
||||
fprintf (file, "\tpush\tar3\n\tldi\tsp,ar3\n");
|
||||
insn = emit_insn (gen_pushqi ( gen_rtx_REG (QImode, AR3_REGNO)));
|
||||
RTX_FRAME_RELATED_P (insn) = 1;
|
||||
insn = emit_insn (gen_movqi (gen_rtx_REG (QImode, AR3_REGNO),
|
||||
gen_rtx_REG (QImode, SP_REGNO)));
|
||||
RTX_FRAME_RELATED_P (insn) = 1;
|
||||
/* FIXME: Assume ISR doesn't require more than 32767 words
|
||||
of local variables. */
|
||||
if (size > 32767)
|
||||
error ("ISR %s requires %d words of local variables, "
|
||||
"maximum is 32767.", current_function_name, size);
|
||||
fprintf (file, "\taddi\t%d,sp\n", size);
|
||||
insn = emit_insn (gen_addqi3 (gen_rtx_REG (QImode, SP_REGNO),
|
||||
gen_rtx_REG (QImode, SP_REGNO),
|
||||
GEN_INT(size)));
|
||||
RTX_FRAME_RELATED_P (insn) = 1;
|
||||
}
|
||||
for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
|
||||
{
|
||||
if (c4x_isr_reg_used_p (regno))
|
||||
{
|
||||
fprintf (file, "\tpush\t%s\n", reg_names[regno]);
|
||||
if (IS_EXT_REGNO (regno)) /* Save 32MSB of R0--R11. */
|
||||
fprintf (file, "\tpushf\t%s\n",
|
||||
TARGET_TI ? reg_names[regno]
|
||||
: float_reg_names[regno]);
|
||||
if (regno == DP_REGNO)
|
||||
{
|
||||
insn = emit_insn (gen_push_dp ());
|
||||
RTX_FRAME_RELATED_P (insn) = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
insn = emit_insn (gen_pushqi (gen_rtx_REG (QImode, regno)));
|
||||
RTX_FRAME_RELATED_P (insn) = 1;
|
||||
if (IS_EXT_REGNO (regno))
|
||||
{
|
||||
insn = emit_insn (gen_pushqf
|
||||
(gen_rtx_REG (QFmode, regno)));
|
||||
RTX_FRAME_RELATED_P (insn) = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/* We need to clear the repeat mode flag if the ISR is
|
||||
@ -826,14 +867,20 @@ c4x_function_prologue (file, size)
|
||||
if (regs_ever_live[RC_REGNO]
|
||||
|| regs_ever_live[RS_REGNO]
|
||||
|| regs_ever_live[RE_REGNO])
|
||||
fprintf (file, "\tandn\t0100h,st\n");
|
||||
{
|
||||
insn = emit_insn (gen_andn_st (GEN_INT(~0x100)));
|
||||
RTX_FRAME_RELATED_P (insn) = 1;
|
||||
}
|
||||
|
||||
/* Reload DP reg if we are paranoid about some turkey
|
||||
violating small memory model rules. */
|
||||
if (TARGET_SMALL && TARGET_PARANOID)
|
||||
fprintf (file, TARGET_C3X ?
|
||||
"\tldp\t@data_sec\n" :
|
||||
"\tldpk\t@data_sec\n");
|
||||
{
|
||||
insn = emit_insn (gen_set_ldp_prologue
|
||||
(gen_rtx_REG (QImode, DP_REGNO),
|
||||
gen_rtx_SYMBOL_REF (QImode, "data_sec")));
|
||||
RTX_FRAME_RELATED_P (insn) = 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -843,8 +890,11 @@ c4x_function_prologue (file, size)
|
||||
|| (current_function_args_size != 0)
|
||||
|| (optimize < 2))
|
||||
{
|
||||
fprintf (file, "\tpush\tar3\n");
|
||||
fprintf (file, "\tldi\tsp,ar3\n");
|
||||
insn = emit_insn (gen_pushqi ( gen_rtx_REG (QImode, AR3_REGNO)));
|
||||
RTX_FRAME_RELATED_P (insn) = 1;
|
||||
insn = emit_insn (gen_movqi (gen_rtx_REG (QImode, AR3_REGNO),
|
||||
gen_rtx_REG (QImode, SP_REGNO)));
|
||||
RTX_FRAME_RELATED_P (insn) = 1;
|
||||
dont_push_ar3 = 1;
|
||||
}
|
||||
else
|
||||
@ -865,28 +915,46 @@ c4x_function_prologue (file, size)
|
||||
size += 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (size > 32767)
|
||||
{
|
||||
/* Local vars are too big, it will take multiple operations
|
||||
to increment SP. */
|
||||
if (TARGET_C3X)
|
||||
{
|
||||
fprintf (file, "\tldi\t%d,r1\n", size >> 16);
|
||||
fprintf (file, "\tlsh\t16,r1\n");
|
||||
insn = emit_insn (gen_movqi (gen_rtx_REG (QImode, R1_REGNO),
|
||||
GEN_INT(size >> 16)));
|
||||
RTX_FRAME_RELATED_P (insn) = 1;
|
||||
insn = emit_insn (gen_lshrqi3 (gen_rtx_REG (QImode, R1_REGNO),
|
||||
gen_rtx_REG (QImode, R1_REGNO),
|
||||
GEN_INT(-16)));
|
||||
RTX_FRAME_RELATED_P (insn) = 1;
|
||||
}
|
||||
else
|
||||
fprintf (file, "\tldhi\t%d,r1\n", size >> 16);
|
||||
fprintf (file, "\tor\t%d,r1\n", size & 0xffff);
|
||||
fprintf (file, "\taddi\tr1,sp\n");
|
||||
{
|
||||
insn = emit_insn (gen_movqi (gen_rtx_REG (QImode, R1_REGNO),
|
||||
GEN_INT(size & ~0xffff)));
|
||||
RTX_FRAME_RELATED_P (insn) = 1;
|
||||
}
|
||||
insn = emit_insn (gen_iorqi3 (gen_rtx_REG (QImode, R1_REGNO),
|
||||
gen_rtx_REG (QImode, R1_REGNO),
|
||||
GEN_INT(size & 0xffff)));
|
||||
RTX_FRAME_RELATED_P (insn) = 1;
|
||||
insn = emit_insn (gen_addqi3 (gen_rtx_REG (QImode, SP_REGNO),
|
||||
gen_rtx_REG (QImode, SP_REGNO),
|
||||
gen_rtx_REG (QImode, R1_REGNO)));
|
||||
RTX_FRAME_RELATED_P (insn) = 1;
|
||||
}
|
||||
else if (size != 0)
|
||||
{
|
||||
/* Local vars take up less than 32767 words, so we can directly
|
||||
add the number. */
|
||||
fprintf (file, "\taddi\t%d,sp\n", size);
|
||||
insn = emit_insn (gen_addqi3 (gen_rtx_REG (QImode, SP_REGNO),
|
||||
gen_rtx_REG (QImode, SP_REGNO),
|
||||
GEN_INT (size)));
|
||||
RTX_FRAME_RELATED_P (insn) = 1;
|
||||
}
|
||||
|
||||
|
||||
for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
|
||||
{
|
||||
if (regs_ever_live[regno] && ! call_used_regs[regno])
|
||||
@ -895,14 +963,18 @@ c4x_function_prologue (file, size)
|
||||
{
|
||||
/* R6 and R7 are saved as floating point. */
|
||||
if (TARGET_PRESERVE_FLOAT)
|
||||
fprintf (file, "\tpush\t%s\n", reg_names[regno]);
|
||||
fprintf (file, "\tpushf\t%s\n",
|
||||
TARGET_TI ? reg_names[regno]
|
||||
: float_reg_names[regno]);
|
||||
{
|
||||
insn = emit_insn (gen_pushqi
|
||||
(gen_rtx_REG (QImode, regno)));
|
||||
RTX_FRAME_RELATED_P (insn) = 1;
|
||||
}
|
||||
insn = emit_insn (gen_pushqf (gen_rtx_REG (QFmode, regno)));
|
||||
RTX_FRAME_RELATED_P (insn) = 1;
|
||||
}
|
||||
else if ((! dont_push_ar3) || (regno != AR3_REGNO))
|
||||
{
|
||||
fprintf (file, "\tpush\t%s\n", reg_names[regno]);
|
||||
insn = emit_insn (gen_pushqi ( gen_rtx_REG (QImode, regno)));
|
||||
RTX_FRAME_RELATED_P (insn) = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -910,40 +982,23 @@ c4x_function_prologue (file, size)
|
||||
}
|
||||
|
||||
|
||||
/* Write function epilogue. */
|
||||
|
||||
void
|
||||
c4x_function_epilogue (file, size)
|
||||
FILE *file;
|
||||
int size;
|
||||
c4x_expand_epilogue()
|
||||
{
|
||||
int regno;
|
||||
int restore_count = 0;
|
||||
int delayed_jump = 0;
|
||||
int jump = 0;
|
||||
int dont_pop_ar3;
|
||||
rtx insn;
|
||||
|
||||
insn = get_last_insn ();
|
||||
if (insn && GET_CODE (insn) == NOTE)
|
||||
insn = prev_nonnote_insn (insn);
|
||||
|
||||
if (insn && GET_CODE (insn) == BARRIER)
|
||||
return;
|
||||
|
||||
int size = get_frame_size ();
|
||||
|
||||
/* For __assembler__ function build no epilogue. */
|
||||
if (c4x_assembler_function_p ())
|
||||
{
|
||||
fprintf (file, "\trets\n"); /* Play it safe. */
|
||||
insn = emit_jump_insn (gen_return_from_epilogue ());
|
||||
RTX_FRAME_RELATED_P (insn) = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef FUNCTION_BLOCK_PROFILER_EXIT
|
||||
if (profile_block_flag == 2)
|
||||
{
|
||||
FUNCTION_BLOCK_PROFILER_EXIT (file);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* For __interrupt__ function build specific epilogue. */
|
||||
if (c4x_interrupt_function_p ())
|
||||
{
|
||||
@ -951,19 +1006,39 @@ c4x_function_epilogue (file, size)
|
||||
{
|
||||
if (! c4x_isr_reg_used_p (regno))
|
||||
continue;
|
||||
if (IS_EXT_REGNO (regno))
|
||||
fprintf (file, "\tpopf\t%s\n",
|
||||
TARGET_TI ? reg_names[regno]
|
||||
: float_reg_names[regno]);
|
||||
fprintf (file, "\tpop\t%s\n", reg_names[regno]);
|
||||
if (regno == DP_REGNO)
|
||||
{
|
||||
insn = emit_insn (gen_pop_dp ());
|
||||
RTX_FRAME_RELATED_P (insn) = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* We have to use unspec because the compiler will delete insns
|
||||
that are not call-saved. */
|
||||
if (IS_EXT_REGNO (regno))
|
||||
{
|
||||
insn = emit_insn (gen_popqf_unspec
|
||||
(gen_rtx_REG (QFmode, regno)));
|
||||
RTX_FRAME_RELATED_P (insn) = 1;
|
||||
}
|
||||
insn = emit_insn (gen_popqi_unspec (gen_rtx_REG (QImode, regno)));
|
||||
RTX_FRAME_RELATED_P (insn) = 1;
|
||||
}
|
||||
}
|
||||
if (size)
|
||||
{
|
||||
fprintf (file, "\tsubi\t%d,sp\n", size);
|
||||
fprintf (file, "\tpop\tar3\n");
|
||||
insn = emit_insn (gen_subqi3 (gen_rtx_REG (QImode, SP_REGNO),
|
||||
gen_rtx_REG (QImode, SP_REGNO),
|
||||
GEN_INT(size)));
|
||||
RTX_FRAME_RELATED_P (insn) = 1;
|
||||
insn = emit_insn (gen_popqi
|
||||
(gen_rtx_REG (QImode, AR3_REGNO)));
|
||||
RTX_FRAME_RELATED_P (insn) = 1;
|
||||
}
|
||||
fprintf (file, "\tpop\tst\n");
|
||||
fprintf (file, "\treti\n");
|
||||
insn = emit_insn (gen_pop_st ());
|
||||
RTX_FRAME_RELATED_P (insn) = 1;
|
||||
insn = emit_jump_insn (gen_return_from_interrupt_epilogue ());
|
||||
RTX_FRAME_RELATED_P (insn) = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -973,14 +1048,19 @@ c4x_function_epilogue (file, size)
|
||||
|| (current_function_args_size != 0)
|
||||
|| (optimize < 2))
|
||||
{
|
||||
/* R2 holds the return value. */
|
||||
fprintf (file, "\tldi\t*-ar3(1),r2\n");
|
||||
|
||||
insn = emit_insn
|
||||
(gen_movqi (gen_rtx_REG (QImode, R2_REGNO),
|
||||
gen_rtx_MEM (QImode,
|
||||
gen_rtx_PLUS
|
||||
(QImode, gen_rtx_REG (QImode,
|
||||
AR3_REGNO),
|
||||
GEN_INT(-1)))));
|
||||
RTX_FRAME_RELATED_P (insn) = 1;
|
||||
|
||||
/* We already have the return value and the fp,
|
||||
so we need to add those to the stack. */
|
||||
size += 2;
|
||||
delayed_jump = 1;
|
||||
restore_count = 1;
|
||||
jump = 1;
|
||||
dont_pop_ar3 = 1;
|
||||
}
|
||||
else
|
||||
@ -1001,41 +1081,7 @@ c4x_function_epilogue (file, size)
|
||||
size += 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Now get the number of instructions required to restore the
|
||||
registers. */
|
||||
for (regno = FIRST_PSEUDO_REGISTER - 1; regno >= 0; regno--)
|
||||
{
|
||||
if ((regs_ever_live[regno] && ! call_used_regs[regno])
|
||||
&& ((! dont_pop_ar3) || (regno != AR3_REGNO)))
|
||||
{
|
||||
restore_count++;
|
||||
if (TARGET_PRESERVE_FLOAT
|
||||
&& ((regno == R6_REGNO) || (regno == R7_REGNO)))
|
||||
restore_count++;
|
||||
}
|
||||
}
|
||||
|
||||
/* Get the number of instructions required to restore the stack. */
|
||||
if (size > 32767)
|
||||
restore_count += (TARGET_C3X ? 4 : 3);
|
||||
else if (size != 0)
|
||||
restore_count += 1;
|
||||
|
||||
if (delayed_jump && (restore_count < 3))
|
||||
{
|
||||
/* We don't have enough instructions to account for the delayed
|
||||
branch, so put some nops in. */
|
||||
|
||||
fprintf (file, "\tbud\tr2\n");
|
||||
while (restore_count < 3)
|
||||
{
|
||||
fprintf (file, "\tnop\n");
|
||||
restore_count++;
|
||||
}
|
||||
restore_count = 0;
|
||||
}
|
||||
|
||||
|
||||
/* Now restore the saved registers, putting in the delayed branch
|
||||
where required. */
|
||||
for (regno = FIRST_PSEUDO_REGISTER - 1; regno >= 0; regno--)
|
||||
@ -1044,33 +1090,28 @@ c4x_function_epilogue (file, size)
|
||||
{
|
||||
if (regno == AR3_REGNO && dont_pop_ar3)
|
||||
continue;
|
||||
|
||||
if (delayed_jump && (restore_count == 3))
|
||||
fprintf (file, "\tbud\tr2\n");
|
||||
|
||||
|
||||
/* R6 and R7 are saved as floating point. */
|
||||
if ((regno == R6_REGNO) || (regno == R7_REGNO))
|
||||
{
|
||||
fprintf (file, "\tpopf\t%s\n",
|
||||
TARGET_TI ? reg_names[regno]
|
||||
: float_reg_names[regno]);
|
||||
insn = emit_insn (gen_popqf_unspec
|
||||
(gen_rtx_REG (QFmode, regno)));
|
||||
RTX_FRAME_RELATED_P (insn) = 1;
|
||||
if (TARGET_PRESERVE_FLOAT)
|
||||
{
|
||||
restore_count--;
|
||||
if (delayed_jump && (restore_count == 3))
|
||||
fprintf (file, "\tbud\tr2\n");
|
||||
fprintf (file, "\tpop\t%s\n", reg_names[regno]);
|
||||
insn = emit_insn (gen_popqi_unspec
|
||||
(gen_rtx_REG (QImode, regno)));
|
||||
RTX_FRAME_RELATED_P (insn) = 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
fprintf (file, "\tpop\t%s\n", reg_names[regno]);
|
||||
restore_count--;
|
||||
{
|
||||
insn = emit_insn (gen_popqi (gen_rtx_REG (QImode, regno)));
|
||||
RTX_FRAME_RELATED_P (insn) = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (delayed_jump && (restore_count == 3))
|
||||
fprintf (file, "\tbud\tr2\n");
|
||||
|
||||
|
||||
if (frame_pointer_needed)
|
||||
{
|
||||
if ((size != 0)
|
||||
@ -1078,42 +1119,69 @@ c4x_function_epilogue (file, size)
|
||||
|| (optimize < 2))
|
||||
{
|
||||
/* Restore the old FP. */
|
||||
fprintf (file, "\tldi\t*ar3,ar3\n");
|
||||
restore_count--;
|
||||
|
||||
if (delayed_jump && (restore_count == 3))
|
||||
fprintf (file, "\tbud\tr2\n");
|
||||
insn = emit_insn
|
||||
(gen_movqi
|
||||
(gen_rtx_REG (QImode, AR3_REGNO),
|
||||
gen_rtx_MEM (QImode, gen_rtx_REG (QImode, AR3_REGNO))));
|
||||
|
||||
RTX_FRAME_RELATED_P (insn) = 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (size > 32767)
|
||||
{
|
||||
/* Local vars are too big, it will take multiple operations
|
||||
to decrement SP. */
|
||||
if (TARGET_C3X)
|
||||
{
|
||||
fprintf (file, "\tldi\t%d,r3\n", size >> 16);
|
||||
if (delayed_jump)
|
||||
fprintf (file, "\tbud\tr2\n");
|
||||
fprintf (file, "\tlsh\t16,r3\n");
|
||||
insn = emit_insn (gen_movqi (gen_rtx_REG (QImode, R3_REGNO),
|
||||
GEN_INT(size >> 16)));
|
||||
RTX_FRAME_RELATED_P (insn) = 1;
|
||||
insn = emit_insn (gen_lshrqi3 (gen_rtx_REG (QImode, R3_REGNO),
|
||||
gen_rtx_REG (QImode, R3_REGNO),
|
||||
GEN_INT(-16)));
|
||||
RTX_FRAME_RELATED_P (insn) = 1;
|
||||
}
|
||||
else
|
||||
fprintf (file, "\tldhi\t%d,r3\n", size >> 16);
|
||||
fprintf (file, "\tor\t%d,r3\n", size & 0xffff);
|
||||
fprintf (file, "\tsubi\tr3,sp\n");
|
||||
{
|
||||
insn = emit_insn (gen_movqi (gen_rtx_REG (QImode, R3_REGNO),
|
||||
GEN_INT(size & ~0xffff)));
|
||||
RTX_FRAME_RELATED_P (insn) = 1;
|
||||
}
|
||||
insn = emit_insn (gen_iorqi3 (gen_rtx_REG (QImode, R3_REGNO),
|
||||
gen_rtx_REG (QImode, R3_REGNO),
|
||||
GEN_INT(size & 0xffff)));
|
||||
RTX_FRAME_RELATED_P (insn) = 1;
|
||||
insn = emit_insn (gen_subqi3 (gen_rtx_REG (QImode, SP_REGNO),
|
||||
gen_rtx_REG (QImode, SP_REGNO),
|
||||
gen_rtx_REG (QImode, R3_REGNO)));
|
||||
RTX_FRAME_RELATED_P (insn) = 1;
|
||||
}
|
||||
else if (size != 0)
|
||||
{
|
||||
/* Local vars take up less than 32768 words, so we can directly
|
||||
subtract the number. */
|
||||
fprintf (file, "\tsubi\t%d,sp\n", size);
|
||||
insn = emit_insn (gen_subqi3 (gen_rtx_REG (QImode, SP_REGNO),
|
||||
gen_rtx_REG (QImode, SP_REGNO),
|
||||
GEN_INT(size)));
|
||||
RTX_FRAME_RELATED_P (insn) = 1;
|
||||
}
|
||||
|
||||
if (jump)
|
||||
{
|
||||
insn = emit_insn (gen_indirect_jump (
|
||||
gen_rtx_REG (QImode, R2_REGNO)));
|
||||
RTX_FRAME_RELATED_P (insn) = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
insn = emit_jump_insn (gen_return_from_epilogue ());
|
||||
RTX_FRAME_RELATED_P (insn) = 1;
|
||||
}
|
||||
|
||||
if (! delayed_jump)
|
||||
fprintf (file, "\trets\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
c4x_null_epilogue_p ()
|
||||
{
|
||||
@ -1137,6 +1205,7 @@ c4x_null_epilogue_p ()
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
c4x_emit_move_sequence (operands, mode)
|
||||
rtx *operands;
|
||||
@ -1259,6 +1328,42 @@ c4x_emit_move_sequence (operands, mode)
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (mode == QImode
|
||||
&& reg_operand (op0, mode)
|
||||
&& const_int_operand (op1, mode)
|
||||
&& ! IS_INT16_CONST (INTVAL (op1))
|
||||
&& ! IS_HIGH_CONST (INTVAL (op1)))
|
||||
{
|
||||
emit_insn (gen_loadqi_big_constant (op0, op1));
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (mode == HImode
|
||||
&& reg_operand (op0, mode)
|
||||
&& const_int_operand (op1, mode))
|
||||
{
|
||||
emit_insn (gen_loadhi_big_constant (op0, op1));
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (mode == QImode
|
||||
&& reg_operand (op0, mode)
|
||||
&& const_int_operand (op1, mode)
|
||||
&& ! IS_INT16_CONST (INTVAL (op1))
|
||||
&& ! IS_HIGH_CONST (INTVAL (op1)))
|
||||
{
|
||||
emit_insn (gen_loadqi_big_constant (op0, op1));
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (mode == HImode
|
||||
&& reg_operand (op0, mode)
|
||||
&& const_int_operand (op1, mode))
|
||||
{
|
||||
emit_insn (gen_loadhi_big_constant (op0, op1));
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Adjust operands in case we have modified them. */
|
||||
operands[0] = op0;
|
||||
operands[1] = op1;
|
||||
@ -1313,7 +1418,7 @@ c4x_emit_libcall3 (libcall, code, mode, operands)
|
||||
enum machine_mode mode;
|
||||
rtx *operands;
|
||||
{
|
||||
return c4x_emit_libcall (libcall, code, mode, mode, 3, operands);
|
||||
c4x_emit_libcall (libcall, code, mode, mode, 3, operands);
|
||||
}
|
||||
|
||||
|
||||
@ -1738,7 +1843,7 @@ c4x_gen_compare_reg (code, x, y)
|
||||
|
||||
char *
|
||||
c4x_output_cbranch (form, seq)
|
||||
char *form;
|
||||
const char *form;
|
||||
rtx seq;
|
||||
{
|
||||
int delayed = 0;
|
||||
@ -3684,7 +3789,7 @@ static int
|
||||
c4x_valid_operands (code, operands, mode, force)
|
||||
enum rtx_code code;
|
||||
rtx *operands;
|
||||
enum machine_mode mode;
|
||||
enum machine_mode mode ATTRIBUTE_UNUSED;
|
||||
int force;
|
||||
{
|
||||
rtx op1;
|
||||
@ -3716,9 +3821,9 @@ c4x_valid_operands (code, operands, mode, force)
|
||||
|
||||
if (code1 == MEM && code2 == MEM)
|
||||
{
|
||||
if (c4x_S_indirect (op1, mode) && c4x_S_indirect (op2, mode))
|
||||
if (c4x_S_indirect (op1) && c4x_S_indirect (op2))
|
||||
return 1;
|
||||
return c4x_R_indirect (op1, mode) && c4x_R_indirect (op2, mode);
|
||||
return c4x_R_indirect (op1) && c4x_R_indirect (op2);
|
||||
}
|
||||
|
||||
if (code1 == code2)
|
||||
@ -3972,7 +4077,7 @@ static int
|
||||
c4x_arn_reg_operand (op, mode, regno)
|
||||
rtx op;
|
||||
enum machine_mode mode;
|
||||
int regno;
|
||||
unsigned int regno;
|
||||
{
|
||||
if (mode != VOIDmode && mode != GET_MODE (op))
|
||||
return 0;
|
||||
@ -3986,7 +4091,7 @@ static int
|
||||
c4x_arn_mem_operand (op, mode, regno)
|
||||
rtx op;
|
||||
enum machine_mode mode;
|
||||
int regno;
|
||||
unsigned int regno;
|
||||
{
|
||||
if (mode != VOIDmode && mode != GET_MODE (op))
|
||||
return 0;
|
||||
@ -4523,7 +4628,7 @@ c4x_file_end (fp)
|
||||
|
||||
static void
|
||||
c4x_check_attribute (attrib, list, decl, attributes)
|
||||
char *attrib;
|
||||
const char *attrib;
|
||||
tree list, decl, *attributes;
|
||||
{
|
||||
while (list != NULL_TREE
|
||||
|
@ -1131,6 +1131,23 @@
|
||||
(set (match_dup 0) (lo_sum:QI (match_dup 0) (match_dup 1)))]
|
||||
"")
|
||||
|
||||
(define_split
|
||||
[(set (match_operand:QI 0 "reg_operand" "")
|
||||
(match_operand:QI 1 "const_int_operand" ""))
|
||||
(clobber (reg:QI 16))]
|
||||
"! TARGET_C3X
|
||||
&& ! IS_INT16_CONST (INTVAL (operands[1]))
|
||||
&& ! IS_HIGH_CONST (INTVAL (operands[1]))
|
||||
&& reload_completed
|
||||
&& std_reg_operand (operands[0], QImode)"
|
||||
[(set (match_dup 0) (match_dup 2))
|
||||
(set (match_dup 0) (ior:QI (match_dup 0) (match_dup 3)))]
|
||||
"
|
||||
{
|
||||
operands[2] = gen_rtx (CONST_INT, VOIDmode, INTVAL (operands[1]) & ~0xffff);
|
||||
operands[3] = gen_rtx (CONST_INT, VOIDmode, INTVAL (operands[1]) & 0xffff);
|
||||
}")
|
||||
|
||||
(define_split
|
||||
[(set (match_operand:QI 0 "reg_operand" "")
|
||||
(match_operand:QI 1 "const_int_operand" ""))]
|
||||
@ -1147,6 +1164,28 @@
|
||||
operands[3] = gen_rtx (CONST_INT, VOIDmode, INTVAL (operands[1]) & 0xffff);
|
||||
}")
|
||||
|
||||
(define_split
|
||||
[(set (match_operand:QI 0 "reg_operand" "")
|
||||
(match_operand:QI 1 "const_int_operand" ""))
|
||||
(clobber (reg:QI 16))]
|
||||
"TARGET_C3X && ! TARGET_SMALL
|
||||
&& ! IS_INT16_CONST (INTVAL (operands[1]))
|
||||
&& reload_completed
|
||||
&& std_reg_operand (operands[0], QImode)
|
||||
&& c4x_shiftable_constant (operands[1]) < 0"
|
||||
[(set (match_dup 0) (match_dup 2))
|
||||
(set (match_dup 0) (ashift:QI (match_dup 0) (match_dup 4)))
|
||||
(set (match_dup 0) (ior:QI (match_dup 0) (match_dup 3)))]
|
||||
"
|
||||
{
|
||||
/* Generate two's complement value of 16 MSBs. */
|
||||
operands[2] = gen_rtx (CONST_INT, VOIDmode,
|
||||
(((INTVAL (operands[1]) >> 16) & 0xffff)
|
||||
- 0x8000) ^ ~0x7fff);
|
||||
operands[3] = gen_rtx (CONST_INT, VOIDmode, INTVAL (operands[1]) & 0xffff);
|
||||
operands[4] = gen_rtx (CONST_INT, VOIDmode, 16);
|
||||
}")
|
||||
|
||||
(define_split
|
||||
[(set (match_operand:QI 0 "reg_operand" "")
|
||||
(match_operand:QI 1 "const_int_operand" ""))]
|
||||
@ -1168,6 +1207,28 @@
|
||||
operands[4] = gen_rtx (CONST_INT, VOIDmode, 16);
|
||||
}")
|
||||
|
||||
(define_split
|
||||
[(set (match_operand:QI 0 "reg_operand" "")
|
||||
(match_operand:QI 1 "const_int_operand" ""))
|
||||
(clobber (reg:QI 16))]
|
||||
"TARGET_C3X
|
||||
&& ! IS_INT16_CONST (INTVAL (operands[1]))
|
||||
&& reload_completed
|
||||
&& std_reg_operand (operands[0], QImode)
|
||||
&& c4x_shiftable_constant (operands[1]) >= 0"
|
||||
[(set (match_dup 0) (match_dup 2))
|
||||
(set (match_dup 0) (ashift:QI (match_dup 0) (match_dup 3)))]
|
||||
"
|
||||
{
|
||||
/* Generate two's complement value of MSBs. */
|
||||
int shift = c4x_shiftable_constant (operands[1]);
|
||||
|
||||
operands[2] = gen_rtx (CONST_INT, VOIDmode,
|
||||
(((INTVAL (operands[1]) >> shift) & 0xffff)
|
||||
- 0x8000) ^ ~0x7fff);
|
||||
operands[3] = gen_rtx (CONST_INT, VOIDmode, shift);
|
||||
}")
|
||||
|
||||
(define_split
|
||||
[(set (match_operand:QI 0 "reg_operand" "")
|
||||
(match_operand:QI 1 "const_int_operand" ""))]
|
||||
@ -1189,6 +1250,29 @@
|
||||
operands[3] = gen_rtx (CONST_INT, VOIDmode, shift);
|
||||
}")
|
||||
|
||||
(define_split
|
||||
[(set (match_operand:QI 0 "reg_operand" "")
|
||||
(match_operand:QI 1 "const_int_operand" ""))
|
||||
(clobber (reg:QI 16))]
|
||||
"! TARGET_SMALL
|
||||
&& ! IS_INT16_CONST (INTVAL (operands[1]))
|
||||
&& ! IS_HIGH_CONST (INTVAL (operands[1]))
|
||||
&& reload_completed
|
||||
&& ! std_reg_operand (operands[0], QImode)"
|
||||
[(set (match_dup 2) (high:QI (match_dup 3)))
|
||||
(set (match_dup 0) (match_dup 4))
|
||||
(use (match_dup 1))]
|
||||
"
|
||||
{
|
||||
rtx dp_reg = gen_rtx_REG (Pmode, DP_REGNO);
|
||||
operands[2] = dp_reg;
|
||||
operands[3] = force_const_mem (Pmode, operands[1]);
|
||||
operands[4] = change_address (operands[3], QImode,
|
||||
gen_rtx_LO_SUM (Pmode, dp_reg,
|
||||
XEXP (operands[3], 0)));
|
||||
operands[3] = XEXP (operands[3], 0);
|
||||
}")
|
||||
|
||||
(define_split
|
||||
[(set (match_operand:QI 0 "reg_operand" "")
|
||||
(match_operand:QI 1 "const_int_operand" ""))]
|
||||
@ -1211,6 +1295,27 @@
|
||||
operands[3] = XEXP (operands[3], 0);
|
||||
}")
|
||||
|
||||
(define_split
|
||||
[(set (match_operand:QI 0 "reg_operand" "")
|
||||
(match_operand:QI 1 "const_int_operand" ""))
|
||||
(clobber (reg:QI 16))]
|
||||
"TARGET_SMALL
|
||||
&& ! IS_INT16_CONST (INTVAL (operands[1]))
|
||||
&& ! IS_HIGH_CONST (INTVAL (operands[1]))
|
||||
&& reload_completed
|
||||
&& ((TARGET_C3X && c4x_shiftable_constant (operands[1]) < 0)
|
||||
|| ! std_reg_operand (operands[0], QImode))"
|
||||
[(set (match_dup 0) (match_dup 2))
|
||||
(use (match_dup 1))]
|
||||
"
|
||||
{
|
||||
rtx dp_reg = gen_rtx_REG (Pmode, DP_REGNO);
|
||||
operands[2] = force_const_mem (Pmode, operands[1]);
|
||||
operands[2] = change_address (operands[2], QImode,
|
||||
gen_rtx_LO_SUM (Pmode, dp_reg,
|
||||
XEXP (operands[2], 0)));
|
||||
}")
|
||||
|
||||
(define_split
|
||||
[(set (match_operand:QI 0 "reg_operand" "")
|
||||
(match_operand:QI 1 "const_int_operand" ""))]
|
||||
@ -1233,7 +1338,8 @@
|
||||
|
||||
(define_split
|
||||
[(set (match_operand:HI 0 "reg_operand" "")
|
||||
(match_operand:HI 1 "const_int_operand" ""))]
|
||||
(match_operand:HI 1 "const_int_operand" ""))
|
||||
(clobber (reg:QI 16))]
|
||||
"reload_completed"
|
||||
[(set (match_dup 2) (match_dup 4))
|
||||
(set (match_dup 3) (match_dup 5))]
|
||||
@ -1315,7 +1421,8 @@
|
||||
|
||||
(define_insn "loadhi_big_constant"
|
||||
[(set (match_operand:HI 0 "reg_operand" "=c*d")
|
||||
(match_operand:HI 1 "const_int_operand" ""))]
|
||||
(match_operand:HI 1 "const_int_operand" ""))
|
||||
(clobber (reg:QI 16))]
|
||||
""
|
||||
"#"
|
||||
[(set_attr "type" "multi")])
|
||||
@ -1336,7 +1443,8 @@
|
||||
|
||||
(define_insn "loadqi_big_constant"
|
||||
[(set (match_operand:QI 0 "reg_operand" "=c*d")
|
||||
(match_operand:QI 1 "const_int_operand" ""))]
|
||||
(match_operand:QI 1 "const_int_operand" ""))
|
||||
(clobber (reg:QI 16))]
|
||||
"! IS_INT16_CONST (INTVAL (operands[1]))
|
||||
&& ! IS_HIGH_CONST (INTVAL (operands[1]))"
|
||||
"#"
|
||||
|
Loading…
Reference in New Issue
Block a user