summaryrefslogtreecommitdiff
path: root/gcc/config/fr30/fr30.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/config/fr30/fr30.c')
-rw-r--r--gcc/config/fr30/fr30.c51
1 files changed, 51 insertions, 0 deletions
diff --git a/gcc/config/fr30/fr30.c b/gcc/config/fr30/fr30.c
index 431af8f63f9..faa637cddec 100644
--- a/gcc/config/fr30/fr30.c
+++ b/gcc/config/fr30/fr30.c
@@ -121,6 +121,8 @@ static int fr30_arg_partial_bytes (CUMULATIVE_ARGS *, enum machine_mode,
tree, bool);
static bool fr30_frame_pointer_required (void);
static bool fr30_can_eliminate (const int, const int);
+static void fr30_asm_trampoline_template (FILE *);
+static void fr30_trampoline_init (rtx, tree, rtx);
#define FRAME_POINTER_MASK (1 << (FRAME_POINTER_REGNUM))
#define RETURN_POINTER_MASK (1 << (RETURN_POINTER_REGNUM))
@@ -165,6 +167,11 @@ static bool fr30_can_eliminate (const int, const int);
#undef TARGET_CAN_ELIMINATE
#define TARGET_CAN_ELIMINATE fr30_can_eliminate
+#undef TARGET_ASM_TRAMPOLINE_TEMPLATE
+#define TARGET_ASM_TRAMPOLINE_TEMPLATE fr30_asm_trampoline_template
+#undef TARGET_TRAMPOLINE_INIT
+#define TARGET_TRAMPOLINE_INIT fr30_trampoline_init
+
struct gcc_target targetm = TARGET_INITIALIZER;
@@ -924,6 +931,50 @@ fr30_frame_pointer_required (void)
}
/*}}}*/
+/*{{{ Trampoline Output Routines */
+
+/* Implement TARGET_ASM_TRAMPOLINE_TEMPLATE.
+ On the FR30, the trampoline is:
+
+ nop
+ ldi:32 STATIC, r12
+ nop
+ ldi:32 FUNCTION, r0
+ jmp @r0
+
+ The no-ops are to guarantee that the static chain and final
+ target are 32 bit aligned within the trampoline. That allows us to
+ initialize those locations with simple SImode stores. The alternative
+ would be to use HImode stores. */
+
+static void
+fr30_asm_trampoline_template (FILE *f)
+{
+ fprintf (f, "\tnop\n");
+ fprintf (f, "\tldi:32\t#0, %s\n", reg_names [STATIC_CHAIN_REGNUM]);
+ fprintf (f, "\tnop\n");
+ fprintf (f, "\tldi:32\t#0, %s\n", reg_names [COMPILER_SCRATCH_REGISTER]);
+ fprintf (f, "\tjmp\t@%s\n", reg_names [COMPILER_SCRATCH_REGISTER]);
+}
+
+/* Implement TARGET_TRAMPOLINE_INIT. */
+
+static void
+fr30_trampoline_init (rtx m_tramp, tree fndecl, rtx chain_value)
+{
+ rtx fnaddr = XEXP (DECL_RTL (fndecl), 0);
+ rtx mem;
+
+ emit_block_move (m_tramp, assemble_trampoline_template (),
+ GEN_INT (TRAMPOLINE_SIZE), BLOCK_OP_NORMAL);
+
+ mem = adjust_address (m_tramp, SImode, 4);
+ emit_move_insn (mem, chain_value);
+ mem = adjust_address (m_tramp, SImode, 12);
+ emit_move_insn (mem, fnaddr);
+}
+
+/*}}}*/
/* Local Variables: */
/* folded-file: t */
/* End: */