static bool m68k_return_in_memory (const_tree, const_tree);
#endif
static void m68k_output_dwarf_dtprel (FILE *, int, rtx) ATTRIBUTE_UNUSED;
+static void m68k_trampoline_init (rtx, tree, rtx);
\f
/* Specify the identification number of the library being built */
#undef TARGET_CAN_ELIMINATE
#define TARGET_CAN_ELIMINATE m68k_can_eliminate
+#undef TARGET_TRAMPOLINE_INIT
+#define TARGET_TRAMPOLINE_INIT m68k_trampoline_init
+
static const struct attribute_spec m68k_attribute_table[] =
{
/* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */
HOST_WIDE_INT delta, HOST_WIDE_INT vcall_offset,
tree function)
{
- rtx this_slot, offset, addr, mem, insn;
+ rtx this_slot, offset, addr, mem, insn, tmp;
+
+ /* Avoid clobbering the struct value reg by using the
+ static chain reg as a temporary. */
+ tmp = gen_rtx_REG (Pmode, STATIC_CHAIN_REGNUM);
/* Pretend to be a post-reload pass while generating rtl. */
reload_completed = 1;
if (vcall_offset != 0)
{
/* Set the static chain register to *THIS. */
- emit_move_insn (static_chain_rtx, this_slot);
- emit_move_insn (static_chain_rtx, gen_rtx_MEM (Pmode, static_chain_rtx));
+ emit_move_insn (tmp, this_slot);
+ emit_move_insn (tmp, gen_rtx_MEM (Pmode, tmp));
/* Set ADDR to a legitimate address for *THIS + VCALL_OFFSET. */
- addr = plus_constant (static_chain_rtx, vcall_offset);
+ addr = plus_constant (tmp, vcall_offset);
if (!m68k_legitimate_address_p (Pmode, addr, true))
{
- emit_insn (gen_rtx_SET (VOIDmode, static_chain_rtx, addr));
- addr = static_chain_rtx;
+ emit_insn (gen_rtx_SET (VOIDmode, tmp, addr));
+ addr = tmp;
}
/* Load the offset into %d0 and add it to THIS. */
SET_REGNO (pic_offset_table_rtx, STATIC_CHAIN_REGNUM);
emit_insn (gen_load_got (pic_offset_table_rtx));
}
- legitimize_pic_address (XEXP (mem, 0), Pmode, static_chain_rtx);
- mem = replace_equiv_address (mem, static_chain_rtx);
+ legitimize_pic_address (XEXP (mem, 0), Pmode, tmp);
+ mem = replace_equiv_address (mem, tmp);
}
insn = emit_call_insn (gen_sibcall (mem, const0_rtx));
SIBLING_CALL_P (insn) = 1;
}
}
+/* We generate a two-instructions program at M_TRAMP :
+ movea.l &CHAIN_VALUE,%a0
+ jmp FNADDR
+ where %a0 can be modified by changing STATIC_CHAIN_REGNUM. */
+
+static void
+m68k_trampoline_init (rtx m_tramp, tree fndecl, rtx chain_value)
+{
+ rtx fnaddr = XEXP (DECL_RTL (fndecl), 0);
+ rtx mem;
+
+ gcc_assert (ADDRESS_REGNO_P (STATIC_CHAIN_REGNUM));
+
+ mem = adjust_address (m_tramp, HImode, 0);
+ emit_move_insn (mem, GEN_INT(0x207C + ((STATIC_CHAIN_REGNUM-8) << 9)));
+ mem = adjust_address (m_tramp, SImode, 2);
+ emit_move_insn (mem, chain_value);
+
+ mem = adjust_address (m_tramp, HImode, 6);
+ emit_move_insn (mem, GEN_INT(0x4EF9));
+ mem = adjust_address (m_tramp, SImode, 8);
+ emit_move_insn (mem, fnaddr);
+
+ FINALIZE_TRAMPOLINE (XEXP (m_tramp, 0));
+}
+
#include "gt-m68k.h"
#define FINALIZE_TRAMPOLINE(TRAMP)
#endif
-/* We generate a two-instructions program at address TRAMP :
- movea.l &CXT,%a0
- jmp FNADDR */
-#define INITIALIZE_TRAMPOLINE(TRAMP, FNADDR, CXT) \
-{ \
- emit_move_insn (gen_rtx_MEM (HImode, TRAMP), \
- GEN_INT(0x207C + ((STATIC_CHAIN_REGNUM-8) << 9))); \
- emit_move_insn (gen_rtx_MEM (SImode, plus_constant (TRAMP, 2)), CXT); \
- emit_move_insn (gen_rtx_MEM (HImode, plus_constant (TRAMP, 6)), \
- GEN_INT(0x4EF9)); \
- emit_move_insn (gen_rtx_MEM (SImode, plus_constant (TRAMP, 8)), FNADDR); \
- FINALIZE_TRAMPOLINE(TRAMP); \
-}
-
/* This is the library routine that is used to transfer control from the
trampoline to the actual nested function. It is defined for backward
compatibility, for linking with object code that used the old trampoline
#undef DEFAULT_PCC_STRUCT_RETURN
#define DEFAULT_PCC_STRUCT_RETURN 1
-/* Output assembler code for a block containing the constant parts
- of a trampoline, leaving space for the variable parts. */
-
-/* On m68k svr4, the trampoline is different from the generic version
- in that we use a1 as the static call chain. */
-
-#undef TRAMPOLINE_TEMPLATE
-#define TRAMPOLINE_TEMPLATE(FILE) \
-{ \
- assemble_aligned_integer (2, GEN_INT (0x227a)); \
- assemble_aligned_integer (2, GEN_INT (8)); \
- assemble_aligned_integer (2, GEN_INT (0x2f3a)); \
- assemble_aligned_integer (2, GEN_INT (8)); \
- assemble_aligned_integer (2, GEN_INT (0x4e75)); \
- assemble_aligned_integer (4, const0_rtx); \
- assemble_aligned_integer (4, const0_rtx); \
-}
-
-/* Redefine since we are using a different trampoline */
-#undef TRAMPOLINE_SIZE
-#define TRAMPOLINE_SIZE 18
-
-/* Emit RTL insns to initialize the variable parts of a trampoline.
- FNADDR is an RTX for the address of the function's pure code.
- CXT is an RTX for the static chain value for the function. */
-
-#undef INITIALIZE_TRAMPOLINE
-#define INITIALIZE_TRAMPOLINE(TRAMP, FNADDR, CXT) \
-{ \
- emit_move_insn (gen_rtx_MEM (SImode, plus_constant (TRAMP, 10)), CXT); \
- emit_move_insn (gen_rtx_MEM (SImode, plus_constant (TRAMP, 14)), FNADDR); \
-}
-
-
/* XXX
This is the end of the chunk lifted from m68kv4.h */