mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-03-31 15:31:11 +08:00
arm.c (TARGET_ASM_TRAMPOLINE_TEMPLATE): New.
* config/arm/arm.c (TARGET_ASM_TRAMPOLINE_TEMPLATE): New. (TARGET_TRAMPOLINE_INIT, TARGET_TRAMPOLINE_ADJUST_ADDRESS): New. (arm_asm_trampoline_template): New. (arm_trampoline_init, arm_trampoline_adjust_address): New. * config/arm/arm.h (TRAMPOLINE_TEMPLATE, * ARM_TRAMPOLINE_TEMPLATE, THUMB2_TRAMPOLINE_TEMPLATE, THUMB1_TRAMPOLINE_TEMPLATE): Move all code to arm_asm_trampoline_template. (TRAMPOLINE_ADJUST_ADDRESS): Move code to arm_trampoline_adjust_address. (INITIALIZE_TRAMPOLINE): Move code to arm_trampoline_init; adjust for target hook parameters. From-SVN: r151986
This commit is contained in:
parent
672f0baaec
commit
0ef9304b22
@ -50,6 +50,18 @@
|
||||
* config/arc/arc.c (arc_trampoline_init): ... here.
|
||||
(TARGET_TRAMPOLINE_INIT): New.
|
||||
|
||||
* config/arm/arm.c (TARGET_ASM_TRAMPOLINE_TEMPLATE): New.
|
||||
(TARGET_TRAMPOLINE_INIT, TARGET_TRAMPOLINE_ADJUST_ADDRESS): New.
|
||||
(arm_asm_trampoline_template): New.
|
||||
(arm_trampoline_init, arm_trampoline_adjust_address): New.
|
||||
* config/arm/arm.h (TRAMPOLINE_TEMPLATE, ARM_TRAMPOLINE_TEMPLATE,
|
||||
THUMB2_TRAMPOLINE_TEMPLATE, THUMB1_TRAMPOLINE_TEMPLATE): Move all
|
||||
code to arm_asm_trampoline_template.
|
||||
(TRAMPOLINE_ADJUST_ADDRESS): Move code to
|
||||
arm_trampoline_adjust_address.
|
||||
(INITIALIZE_TRAMPOLINE): Move code to arm_trampoline_init;
|
||||
adjust for target hook parameters.
|
||||
|
||||
2009-09-22 Richard Guenther <rguenther@suse.de>
|
||||
|
||||
PR middle-end/41395
|
||||
|
@ -219,6 +219,9 @@ static tree arm_convert_to_type (tree type, tree expr);
|
||||
static bool arm_scalar_mode_supported_p (enum machine_mode);
|
||||
static bool arm_frame_pointer_required (void);
|
||||
static bool arm_can_eliminate (const int, const int);
|
||||
static void arm_asm_trampoline_template (FILE *);
|
||||
static void arm_trampoline_init (rtx, tree, rtx);
|
||||
static rtx arm_trampoline_adjust_address (rtx);
|
||||
|
||||
|
||||
/* Table of machine attributes. */
|
||||
@ -366,6 +369,13 @@ static const struct attribute_spec arm_attribute_table[] =
|
||||
#undef TARGET_ALLOCATE_STACK_SLOTS_FOR_ARGS
|
||||
#define TARGET_ALLOCATE_STACK_SLOTS_FOR_ARGS arm_allocate_stack_slots_for_args
|
||||
|
||||
#undef TARGET_ASM_TRAMPOLINE_TEMPLATE
|
||||
#define TARGET_ASM_TRAMPOLINE_TEMPLATE arm_asm_trampoline_template
|
||||
#undef TARGET_TRAMPOLINE_INIT
|
||||
#define TARGET_TRAMPOLINE_INIT arm_trampoline_init
|
||||
#undef TARGET_TRAMPOLINE_ADJUST_ADDRESS
|
||||
#define TARGET_TRAMPOLINE_ADJUST_ADDRESS arm_trampoline_adjust_address
|
||||
|
||||
#undef TARGET_DEFAULT_SHORT_ENUMS
|
||||
#define TARGET_DEFAULT_SHORT_ENUMS arm_default_short_enums
|
||||
|
||||
@ -1985,6 +1995,84 @@ arm_allocate_stack_slots_for_args (void)
|
||||
return !IS_NAKED (arm_current_func_type ());
|
||||
}
|
||||
|
||||
|
||||
/* Output assembler code for a block containing the constant parts
|
||||
of a trampoline, leaving space for the variable parts.
|
||||
|
||||
On the ARM, (if r8 is the static chain regnum, and remembering that
|
||||
referencing pc adds an offset of 8) the trampoline looks like:
|
||||
ldr r8, [pc, #0]
|
||||
ldr pc, [pc]
|
||||
.word static chain value
|
||||
.word function's address
|
||||
XXX FIXME: When the trampoline returns, r8 will be clobbered. */
|
||||
|
||||
static void
|
||||
arm_asm_trampoline_template (FILE *f)
|
||||
{
|
||||
if (TARGET_ARM)
|
||||
{
|
||||
asm_fprintf (f, "\tldr\t%r, [%r, #0]\n", STATIC_CHAIN_REGNUM, PC_REGNUM);
|
||||
asm_fprintf (f, "\tldr\t%r, [%r, #0]\n", PC_REGNUM, PC_REGNUM);
|
||||
}
|
||||
else if (TARGET_THUMB2)
|
||||
{
|
||||
/* The Thumb-2 trampoline is similar to the arm implementation.
|
||||
Unlike 16-bit Thumb, we enter the stub in thumb mode. */
|
||||
asm_fprintf (f, "\tldr.w\t%r, [%r, #4]\n",
|
||||
STATIC_CHAIN_REGNUM, PC_REGNUM);
|
||||
asm_fprintf (f, "\tldr.w\t%r, [%r, #4]\n", PC_REGNUM, PC_REGNUM);
|
||||
}
|
||||
else
|
||||
{
|
||||
ASM_OUTPUT_ALIGN (f, 2);
|
||||
fprintf (f, "\t.code\t16\n");
|
||||
fprintf (f, ".Ltrampoline_start:\n");
|
||||
asm_fprintf (f, "\tpush\t{r0, r1}\n");
|
||||
asm_fprintf (f, "\tldr\tr0, [%r, #8]\n", PC_REGNUM);
|
||||
asm_fprintf (f, "\tmov\t%r, r0\n", STATIC_CHAIN_REGNUM);
|
||||
asm_fprintf (f, "\tldr\tr0, [%r, #8]\n", PC_REGNUM);
|
||||
asm_fprintf (f, "\tstr\tr0, [%r, #4]\n", SP_REGNUM);
|
||||
asm_fprintf (f, "\tpop\t{r0, %r}\n", PC_REGNUM);
|
||||
}
|
||||
assemble_aligned_integer (UNITS_PER_WORD, const0_rtx);
|
||||
assemble_aligned_integer (UNITS_PER_WORD, const0_rtx);
|
||||
}
|
||||
|
||||
/* Emit RTL insns to initialize the variable parts of a trampoline. */
|
||||
|
||||
static void
|
||||
arm_trampoline_init (rtx m_tramp, tree fndecl, rtx chain_value)
|
||||
{
|
||||
rtx fnaddr, mem, a_tramp;
|
||||
|
||||
emit_block_move (m_tramp, assemble_trampoline_template (),
|
||||
GEN_INT (TRAMPOLINE_SIZE), BLOCK_OP_NORMAL);
|
||||
|
||||
mem = adjust_address (m_tramp, SImode, TARGET_32BIT ? 8 : 12);
|
||||
emit_move_insn (mem, chain_value);
|
||||
|
||||
mem = adjust_address (m_tramp, SImode, TARGET_32BIT ? 12 : 16);
|
||||
fnaddr = XEXP (DECL_RTL (fndecl), 0);
|
||||
emit_move_insn (mem, fnaddr);
|
||||
|
||||
a_tramp = XEXP (m_tramp, 0);
|
||||
emit_library_call (gen_rtx_SYMBOL_REF (Pmode, "__clear_cache"),
|
||||
LCT_NORMAL, VOIDmode, 2, a_tramp, Pmode,
|
||||
plus_constant (a_tramp, TRAMPOLINE_SIZE), Pmode);
|
||||
}
|
||||
|
||||
/* Thumb trampolines should be entered in thumb mode, so set
|
||||
the bottom bit of the address. */
|
||||
|
||||
static rtx
|
||||
arm_trampoline_adjust_address (rtx addr)
|
||||
{
|
||||
if (TARGET_THUMB)
|
||||
addr = expand_simple_binop (Pmode, IOR, addr, const1_rtx,
|
||||
NULL, 0, OPTAB_LIB_WIDEN);
|
||||
return addr;
|
||||
}
|
||||
|
||||
/* Return 1 if it is possible to return using a single instruction.
|
||||
If SIBLING is non-null, this is a test for a return before a sibling
|
||||
|
@ -1861,102 +1861,11 @@ typedef struct
|
||||
once for every function before code is generated. */
|
||||
#define INIT_EXPANDERS arm_init_expanders ()
|
||||
|
||||
/* Output assembler code for a block containing the constant parts
|
||||
of a trampoline, leaving space for the variable parts.
|
||||
|
||||
On the ARM, (if r8 is the static chain regnum, and remembering that
|
||||
referencing pc adds an offset of 8) the trampoline looks like:
|
||||
ldr r8, [pc, #0]
|
||||
ldr pc, [pc]
|
||||
.word static chain value
|
||||
.word function's address
|
||||
XXX FIXME: When the trampoline returns, r8 will be clobbered. */
|
||||
#define ARM_TRAMPOLINE_TEMPLATE(FILE) \
|
||||
{ \
|
||||
asm_fprintf (FILE, "\tldr\t%r, [%r, #0]\n", \
|
||||
STATIC_CHAIN_REGNUM, PC_REGNUM); \
|
||||
asm_fprintf (FILE, "\tldr\t%r, [%r, #0]\n", \
|
||||
PC_REGNUM, PC_REGNUM); \
|
||||
assemble_aligned_integer (UNITS_PER_WORD, const0_rtx); \
|
||||
assemble_aligned_integer (UNITS_PER_WORD, const0_rtx); \
|
||||
}
|
||||
|
||||
/* The Thumb-2 trampoline is similar to the arm implementation.
|
||||
Unlike 16-bit Thumb, we enter the stub in thumb mode. */
|
||||
#define THUMB2_TRAMPOLINE_TEMPLATE(FILE) \
|
||||
{ \
|
||||
asm_fprintf (FILE, "\tldr.w\t%r, [%r, #4]\n", \
|
||||
STATIC_CHAIN_REGNUM, PC_REGNUM); \
|
||||
asm_fprintf (FILE, "\tldr.w\t%r, [%r, #4]\n", \
|
||||
PC_REGNUM, PC_REGNUM); \
|
||||
assemble_aligned_integer (UNITS_PER_WORD, const0_rtx); \
|
||||
assemble_aligned_integer (UNITS_PER_WORD, const0_rtx); \
|
||||
}
|
||||
|
||||
#define THUMB1_TRAMPOLINE_TEMPLATE(FILE) \
|
||||
{ \
|
||||
ASM_OUTPUT_ALIGN(FILE, 2); \
|
||||
fprintf (FILE, "\t.code\t16\n"); \
|
||||
fprintf (FILE, ".Ltrampoline_start:\n"); \
|
||||
asm_fprintf (FILE, "\tpush\t{r0, r1}\n"); \
|
||||
asm_fprintf (FILE, "\tldr\tr0, [%r, #8]\n", \
|
||||
PC_REGNUM); \
|
||||
asm_fprintf (FILE, "\tmov\t%r, r0\n", \
|
||||
STATIC_CHAIN_REGNUM); \
|
||||
asm_fprintf (FILE, "\tldr\tr0, [%r, #8]\n", \
|
||||
PC_REGNUM); \
|
||||
asm_fprintf (FILE, "\tstr\tr0, [%r, #4]\n", \
|
||||
SP_REGNUM); \
|
||||
asm_fprintf (FILE, "\tpop\t{r0, %r}\n", \
|
||||
PC_REGNUM); \
|
||||
assemble_aligned_integer (UNITS_PER_WORD, const0_rtx); \
|
||||
assemble_aligned_integer (UNITS_PER_WORD, const0_rtx); \
|
||||
}
|
||||
|
||||
#define TRAMPOLINE_TEMPLATE(FILE) \
|
||||
if (TARGET_ARM) \
|
||||
ARM_TRAMPOLINE_TEMPLATE (FILE) \
|
||||
else if (TARGET_THUMB2) \
|
||||
THUMB2_TRAMPOLINE_TEMPLATE (FILE) \
|
||||
else \
|
||||
THUMB1_TRAMPOLINE_TEMPLATE (FILE)
|
||||
|
||||
/* Thumb trampolines should be entered in thumb mode, so set the bottom bit
|
||||
of the address. */
|
||||
#define TRAMPOLINE_ADJUST_ADDRESS(ADDR) do \
|
||||
{ \
|
||||
if (TARGET_THUMB) \
|
||||
(ADDR) = expand_simple_binop (Pmode, IOR, (ADDR), GEN_INT(1), \
|
||||
gen_reg_rtx (Pmode), 0, OPTAB_LIB_WIDEN); \
|
||||
} while(0)
|
||||
|
||||
/* Length in units of the trampoline for entering a nested function. */
|
||||
#define TRAMPOLINE_SIZE (TARGET_32BIT ? 16 : 20)
|
||||
|
||||
/* Alignment required for a trampoline in bits. */
|
||||
#define TRAMPOLINE_ALIGNMENT 32
|
||||
|
||||
|
||||
/* 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. */
|
||||
#ifndef INITIALIZE_TRAMPOLINE
|
||||
#define INITIALIZE_TRAMPOLINE(TRAMP, FNADDR, CXT) \
|
||||
{ \
|
||||
emit_move_insn (gen_rtx_MEM (SImode, \
|
||||
plus_constant (TRAMP, \
|
||||
TARGET_32BIT ? 8 : 12)), \
|
||||
CXT); \
|
||||
emit_move_insn (gen_rtx_MEM (SImode, \
|
||||
plus_constant (TRAMP, \
|
||||
TARGET_32BIT ? 12 : 16)), \
|
||||
FNADDR); \
|
||||
emit_library_call (gen_rtx_SYMBOL_REF (Pmode, "__clear_cache"), \
|
||||
LCT_NORMAL, VOIDmode, 2, TRAMP, Pmode, \
|
||||
plus_constant (TRAMP, TRAMPOLINE_SIZE), Pmode); \
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/* Addressing modes, and classification of registers for them. */
|
||||
#define HAVE_POST_INCREMENT 1
|
||||
|
Loading…
x
Reference in New Issue
Block a user