cris.c (TARGET_ASM_TRAMPOLINE_TEMPLATE, [...]): New.

* config/cris/cris.c (TARGET_ASM_TRAMPOLINE_TEMPLATE,
	TARGET_TRAMPOLINE_INIT, cris_asm_trampoline_template,
	cris_trampoline_init): New.
	* config/cris/cris.h (TRAMPOLINE_TEMPLATE): Move code to
	cris_asm_trampoline_template.
	(INITIALIZE_TRAMPOLINE): Move code to cris_trampoline_init;
	adjust for target hook parameters.

From-SVN: r151989
This commit is contained in:
Richard Henderson 2009-09-22 08:12:23 -07:00 committed by Richard Henderson
parent 92910d774d
commit 3e322b77d6
3 changed files with 114 additions and 98 deletions

View file

@ -79,6 +79,14 @@
bfin_asm_trampoline_template.
(INITIALIZE_TRAMPOLINE): Remove.
* config/cris/cris.c (TARGET_ASM_TRAMPOLINE_TEMPLATE,
TARGET_TRAMPOLINE_INIT, cris_asm_trampoline_template,
cris_trampoline_init): New.
* config/cris/cris.h (TRAMPOLINE_TEMPLATE): Move code to
cris_asm_trampoline_template.
(INITIALIZE_TRAMPOLINE): Move code to cris_trampoline_init;
adjust for target hook parameters.
2009-09-22 Jakub Jelinek <jakub@redhat.com>
* config/rs6000/rs6000.c (bdesc_2arg): Fix CODE_FOR_vector_gt* codes

View file

@ -127,6 +127,9 @@ static bool cris_handle_option (size_t, const char *, int);
static bool cris_frame_pointer_required (void);
static void cris_asm_trampoline_template (FILE *);
static void cris_trampoline_init (rtx, tree, rtx);
/* This is the parsed result of the "-max-stack-stackframe=" option. If
it (still) is zero, then there was no such option given. */
int cris_max_stackframe = 0;
@ -189,6 +192,11 @@ int cris_cpu_version = CRIS_DEFAULT_CPU_VERSION;
#undef TARGET_FRAME_POINTER_REQUIRED
#define TARGET_FRAME_POINTER_REQUIRED cris_frame_pointer_required
#undef TARGET_ASM_TRAMPOLINE_TEMPLATE
#define TARGET_ASM_TRAMPOLINE_TEMPLATE cris_asm_trampoline_template
#undef TARGET_TRAMPOLINE_INIT
#define TARGET_TRAMPOLINE_INIT cris_trampoline_init
struct gcc_target targetm = TARGET_INITIALIZER;
/* Helper for cris_load_multiple_op and cris_ret_movem_op. */
@ -3853,6 +3861,103 @@ cris_frame_pointer_required (void)
return !current_function_sp_is_unchanging;
}
/* Implement TARGET_ASM_TRAMPOLINE_TEMPLATE.
This looks too complicated, and it is. I assigned r7 to be the
static chain register, but it is call-saved, so we have to save it,
and come back to restore it after the call, so we have to save srp...
Anyway, trampolines are rare enough that we can cope with this
somewhat lack of elegance.
(Do not be tempted to "straighten up" whitespace in the asms; the
assembler #NO_APP state mandates strict spacing). */
/* ??? See the i386 regparm=3 implementation that pushes the static
chain value to the stack in the trampoline, and uses a call-saved
register when called directly. */
static void
cris_asm_trampoline_template (FILE *f)
{
if (TARGET_V32)
{
/* This normally-unused nop insn acts as an instruction to
the simulator to flush its instruction cache. None of
the other instructions in the trampoline template suits
as a trigger for V32. The pc-relative addressing mode
works nicely as a trigger for V10.
FIXME: Have specific V32 template (possibly avoiding the
use of a special instruction). */
fprintf (f, "\tclearf x\n");
/* We have to use a register as an intermediate, choosing
semi-randomly R1 (which has to not be the STATIC_CHAIN_REGNUM),
so we can use it for address indirection and jsr target. */
fprintf (f, "\tmove $r1,$mof\n");
/* +4 */
fprintf (f, "\tmove.d 0,$r1\n");
fprintf (f, "\tmove.d $%s,[$r1]\n", reg_names[STATIC_CHAIN_REGNUM]);
fprintf (f, "\taddq 6,$r1\n");
fprintf (f, "\tmove $mof,[$r1]\n");
fprintf (f, "\taddq 6,$r1\n");
fprintf (f, "\tmove $srp,[$r1]\n");
/* +20 */
fprintf (f, "\tmove.d 0,$%s\n", reg_names[STATIC_CHAIN_REGNUM]);
/* +26 */
fprintf (f, "\tmove.d 0,$r1\n");
fprintf (f, "\tjsr $r1\n");
fprintf (f, "\tsetf\n");
/* +36 */
fprintf (f, "\tmove.d 0,$%s\n", reg_names[STATIC_CHAIN_REGNUM]);
/* +42 */
fprintf (f, "\tmove.d 0,$r1\n");
/* +48 */
fprintf (f, "\tmove.d 0,$r9\n");
fprintf (f, "\tjump $r9\n");
fprintf (f, "\tsetf\n");
}
else
{
fprintf (f, "\tmove.d $%s,[$pc+20]\n", reg_names[STATIC_CHAIN_REGNUM]);
fprintf (f, "\tmove $srp,[$pc+22]\n");
fprintf (f, "\tmove.d 0,$%s\n", reg_names[STATIC_CHAIN_REGNUM]);
fprintf (f, "\tjsr 0\n");
fprintf (f, "\tmove.d 0,$%s\n", reg_names[STATIC_CHAIN_REGNUM]);
fprintf (f, "\tjump 0\n");
}
}
/* Implement TARGET_TRAMPOLINE_INIT. */
static void
cris_trampoline_init (rtx m_tramp, tree fndecl, rtx chain_value)
{
rtx fnaddr = XEXP (DECL_RTL (fndecl), 0);
rtx tramp = XEXP (m_tramp, 0);
rtx mem;
emit_block_move (m_tramp, assemble_trampoline_template (),
GEN_INT (TRAMPOLINE_SIZE), BLOCK_OP_NORMAL);
if (TARGET_V32)
{
mem = adjust_address (m_tramp, SImode, 6);
emit_move_insn (mem, plus_constant (tramp, 38));
mem = adjust_address (m_tramp, SImode, 22);
emit_move_insn (mem, chain_value);
mem = adjust_address (m_tramp, SImode, 28);
emit_move_insn (mem, fnaddr);
}
else
{
mem = adjust_address (m_tramp, SImode, 10);
emit_move_insn (mem, chain_value);
mem = adjust_address (m_tramp, SImode, 16);
emit_move_insn (mem, fnaddr);
}
/* Note that there is no need to do anything with the cache for
sake of a trampoline. */
}
#if 0
/* Various small functions to replace macros. Only called from a
debugger. They might collide with gcc functions or system functions,

View file

@ -935,108 +935,11 @@ struct cum_args {int regs;};
/* Node: Trampolines */
/* This looks too complicated, and it is. I assigned r7 to be the
static chain register, but it is call-saved, so we have to save it,
and come back to restore it after the call, so we have to save srp...
Anyway, trampolines are rare enough that we can cope with this
somewhat lack of elegance.
(Do not be tempted to "straighten up" whitespace in the asms; the
assembler #NO_APP state mandates strict spacing). */
#define TRAMPOLINE_TEMPLATE(FILE) \
do \
{ \
if (TARGET_V32) \
{ \
/* This normally-unused nop insn acts as an instruction to \
the simulator to flush its instruction cache. None of \
the other instructions in the trampoline template suits \
as a trigger for V32. The pc-relative addressing mode \
works nicely as a trigger for V10. \
FIXME: Have specific V32 template (possibly avoiding the \
use of a special instruction). */ \
fprintf (FILE, "\tclearf x\n"); \
/* We have to use a register as an intermediate, choosing \
semi-randomly R1 (which has to not be the \
STATIC_CHAIN_REGNUM), so we can use it for address \
indirection and jsr target. */ \
fprintf (FILE, "\tmove $r1,$mof\n"); \
/* +4 */ \
fprintf (FILE, "\tmove.d 0,$r1\n"); \
fprintf (FILE, "\tmove.d $%s,[$r1]\n", \
reg_names[STATIC_CHAIN_REGNUM]); \
fprintf (FILE, "\taddq 6,$r1\n"); \
fprintf (FILE, "\tmove $mof,[$r1]\n"); \
fprintf (FILE, "\taddq 6,$r1\n"); \
fprintf (FILE, "\tmove $srp,[$r1]\n"); \
/* +20 */ \
fprintf (FILE, "\tmove.d 0,$%s\n", \
reg_names[STATIC_CHAIN_REGNUM]); \
/* +26 */ \
fprintf (FILE, "\tmove.d 0,$r1\n"); \
fprintf (FILE, "\tjsr $r1\n"); \
fprintf (FILE, "\tsetf\n"); \
/* +36 */ \
fprintf (FILE, "\tmove.d 0,$%s\n", \
reg_names[STATIC_CHAIN_REGNUM]); \
/* +42 */ \
fprintf (FILE, "\tmove.d 0,$r1\n"); \
/* +48 */ \
fprintf (FILE, "\tmove.d 0,$r9\n"); \
fprintf (FILE, "\tjump $r9\n"); \
fprintf (FILE, "\tsetf\n"); \
} \
else \
{ \
fprintf (FILE, "\tmove.d $%s,[$pc+20]\n", \
reg_names[STATIC_CHAIN_REGNUM]); \
fprintf (FILE, "\tmove $srp,[$pc+22]\n"); \
fprintf (FILE, "\tmove.d 0,$%s\n", \
reg_names[STATIC_CHAIN_REGNUM]); \
fprintf (FILE, "\tjsr 0\n"); \
fprintf (FILE, "\tmove.d 0,$%s\n", \
reg_names[STATIC_CHAIN_REGNUM]); \
fprintf (FILE, "\tjump 0\n"); \
} \
} \
while (0)
#define TRAMPOLINE_SIZE (TARGET_V32 ? 58 : 32)
/* CRIS wants instructions on word-boundary.
Note that due to a bug (reported) in 2.7.2 and earlier, this is
actually treated as alignment in _bytes_, not _bits_. (Obviously
this is not fatal, only a slight waste of stack space). */
/* CRIS wants instructions on word-boundary. */
#define TRAMPOLINE_ALIGNMENT 16
#define INITIALIZE_TRAMPOLINE(TRAMP, FNADDR, CXT) \
do \
if (TARGET_V32) \
{ \
emit_move_insn (gen_rtx_MEM (SImode, \
plus_constant (TRAMP, 6)), \
plus_constant (TRAMP, 38)); \
emit_move_insn (gen_rtx_MEM (SImode, \
plus_constant (TRAMP, 22)), \
CXT); \
emit_move_insn (gen_rtx_MEM (SImode, \
plus_constant (TRAMP, 28)), \
FNADDR); \
} \
else \
{ \
emit_move_insn (gen_rtx_MEM (SImode, \
plus_constant (TRAMP, 10)), \
CXT); \
emit_move_insn (gen_rtx_MEM (SImode, \
plus_constant (TRAMP, 16)), \
FNADDR); \
} \
while (0)
/* Note that there is no need to do anything with the cache for sake of
a trampoline. */
/* Node: Library Calls */
/* If you change this, you have to check whatever libraries and systems