diff options
Diffstat (limited to 'gcc/config/arm')
-rw-r--r-- | gcc/config/arm/arm.c | 88 | ||||
-rw-r--r-- | gcc/config/arm/arm.h | 91 |
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 |