aboutsummaryrefslogtreecommitdiff
path: root/gcc/config/arm
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/config/arm')
-rw-r--r--gcc/config/arm/arm.c88
-rw-r--r--gcc/config/arm/arm.h91
2 files changed, 88 insertions, 91 deletions
diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c
index 1cc9557..efc329b 100644
--- a/gcc/config/arm/arm.c
+++ b/gcc/config/arm/arm.c
@@ -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
@@ -1986,6 +1996,84 @@ arm_allocate_stack_slots_for_args (void)
}
+/* 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
call. SIBLING is the call insn, so we can examine its register usage. */
diff --git a/gcc/config/arm/arm.h b/gcc/config/arm/arm.h
index 215c9fb..9272ca5 100644
--- a/gcc/config/arm/arm.h
+++ b/gcc/config/arm/arm.h
@@ -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