diff options
author | pbrook <pbrook@138bc75d-0d04-0410-961f-82ee72b054a4> | 2007-01-03 23:48:10 +0000 |
---|---|---|
committer | pbrook <pbrook@138bc75d-0d04-0410-961f-82ee72b054a4> | 2007-01-03 23:48:10 +0000 |
commit | 25f905c239ab087a017c1c1d393de92f2f1eb301 (patch) | |
tree | e7fbd881338bffa6ed838d87847ff2484257e411 /gcc/config/arm/arm.h | |
parent | 5032e5f8188169c7051ab89c4dd15d4280e50de4 (diff) | |
download | gcc-25f905c239ab087a017c1c1d393de92f2f1eb301.tar.gz |
2007-01-03 Paul Brook <paul@codesourcery.com>
Merge from sourcerygxx-4_1.
gcc/
* config/arm/thumb2.md: New file.
* config/arm/elf.h (JUMP_TABLES_IN_TEXT_SECTION): Return True for
Thumb-2.
* config/arm/coff.h (JUMP_TABLES_IN_TEXT_SECTION): Ditto.
* config/arm/aout.h (ASM_OUTPUT_ADDR_VEC_ELT): Add !Thumb-2 assertion.
(ASM_OUTPUT_ADDR_DIFF_ELT): Output Thumb-2 jump tables.
* config/arm/aof.h (ASM_OUTPUT_ADDR_DIFF_ELT): Output Thumb-2 jump
tables.
(ASM_OUTPUT_ADDR_VEC_ELT): Add !Thumb-2 assertion.
* config/arm/ieee754-df.S: Use macros for Thumb-2/Unified asm
comptibility.
* config/arm/ieee754-sf.S: Ditto.
* config/arm/arm.c (thumb_base_register_rtx_p): Rename...
(thumb1_base_register_rtx_p): ... to this.
(thumb_index_register_rtx_p): Rename...
(thumb1_index_register_rtx_p): ... to this.
(thumb_output_function_prologue): Rename...
(thumb1_output_function_prologue): ... to this.
(thumb_legitimate_address_p): Rename...
(thumb1_legitimate_address_p): ... to this.
(thumb_rtx_costs): Rename...
(thumb1_rtx_costs): ... to this.
(thumb_compute_save_reg_mask): Rename...
(thumb1_compute_save_reg_mask): ... to this.
(thumb_final_prescan_insn): Rename...
(thumb1_final_prescan_insn): ... to this.
(thumb_expand_epilogue): Rename...
(thumb1_expand_epilogue): ... to this.
(arm_unwind_emit_stm): Rename...
(arm_unwind_emit_sequence): ... to this.
(thumb2_legitimate_index_p, thumb2_legitimate_address_p,
thumb1_compute_save_reg_mask, arm_dwarf_handle_frame_unspec,
thumb2_index_mul_operand, output_move_vfp, arm_shift_nmem,
arm_save_coproc_regs, thumb_set_frame_pointer, arm_print_condition,
thumb2_final_prescan_insn, thumb2_asm_output_opcode, arm_output_shift,
thumb2_output_casesi): New functions.
(TARGET_DWARF_HANDLE_FRAME_UNSPEC): Define.
(FL_THUMB2, FL_NOTM, FL_DIV, FL_FOR_ARCH6T2, FL_FOR_ARCH7,
FL_FOR_ARCH7A, FL_FOR_ARCH7R, FL_FOR_ARCH7M, ARM_LSL_NAME,
THUMB2_WORK_REGS): Define.
(arm_arch_notm, arm_arch_thumb2, arm_arch_hwdiv, arm_condexec_count,
arm_condexec_mask, arm_condexec_masklen)): New variables.
(all_architectures): Add armv6t2, armv7, armv7a, armv7r and armv7m.
(arm_override_options): Check new CPU capabilities.
Set new architecture flag variables.
(arm_isr_value): Handle v7m interrupt functions.
(user_return_insn): Return 0 for v7m interrupt functions. Handle
Thumb-2.
(const_ok_for_arm): Handle Thumb-2 constants.
(arm_gen_constant): Ditto. Use movw when available.
(arm_function_ok_for_sibcall): Return false for v7m interrupt
functions.
(legitimize_pic_address, arm_call_tls_get_addr): Handle Thumb-2.
(thumb_find_work_register, arm_load_pic_register,
legitimize_tls_address, arm_address_cost, load_multiple_sequence,
emit_ldm_seq, emit_stm_seq, arm_select_cc_mode, get_jump_table_size,
print_multi_reg, output_mov_long_double_fpa_from_arm,
output_mov_long_double_arm_from_fpa, output_mov_double_fpa_from_arm,
output_mov_double_fpa_from_arm, output_move_double,
arm_compute_save_reg_mask, arm_compute_save_reg0_reg12_mask,
output_return_instruction, arm_output_function_prologue,
arm_output_epilogue, arm_get_frame_offsets, arm_regno_class,
arm_output_mi_thunk, thumb_set_return_address): Ditto.
(arm_expand_prologue): Handle Thumb-2. Use arm_save_coproc_regs.
(arm_coproc_mem_operand): Allow POST_INC/PRE_DEC.
(arithmetic_instr, shift_op): Use arm_shift_nmem.
(arm_print_operand): Use arm_print_condition. Handle '(', ')', '.',
'!' and 'L'.
(arm_final_prescan_insn): Use extract_constrain_insn_cached.
(thumb_expand_prologue): Use thumb_set_frame_pointer.
(arm_file_start): Output directive for unified syntax.
(arm_unwind_emit_set): Handle stack alignment instruction.
* config/arm/lib1funcs.asm: Remove default for __ARM_ARCH__.
Add v6t2, v7, v7a, v7r and v7m.
(RETLDM): Add Thumb-2 code.
(do_it, shift1, do_push, do_pop, COND, THUMB_SYNTAX): New macros.
* config/arm/arm.h (TARGET_CPU_CPP_BUILTINS): Define __thumb2__.
(TARGET_THUMB1, TARGET_32BIT, TARGET_THUMB2, TARGET_DSP_MULTIPLY,
TARGET_INT_SIMD, TARGET_UNIFIED_ASM, ARM_FT_STACKALIGN, IS_STACKALIGN,
THUMB2_TRAMPOLINE_TEMPLATE, TRAMPOLINE_ADJUST_ADDRESS,
ASM_OUTPUT_OPCODE, THUMB2_GO_IF_LEGITIMATE_ADDRESS,
THUMB2_LEGITIMIZE_ADDRESS, CASE_VECTOR_PC_RELATIVE,
CASE_VECTOR_SHORTEN_MODE, ADDR_VEC_ALIGN, ASM_OUTPUT_CASE_END,
ADJUST_INSN_LENGTH): Define.
(TARGET_REALLY_IWMMXT, TARGET_IWMMXT_ABI, CONDITIONAL_REGISTER_USAGE,
STATIC_CHAIN_REGNUM, HARD_REGNO_NREGS, INDEX_REG_CLASS,
BASE_REG_CLASS, MODE_BASE_REG_CLASS, SMALL_REGISTER_CLASSES,
PREFERRED_RELOAD_CLASS, SECONDARY_OUTPUT_RELOAD_CLASS,
SECONDARY_INPUT_RELOAD_CLASS, LIBCALL_VALUE, FUNCTION_VALUE_REGNO_P,
TRAMPOLINE_SIZE, INITIALIZE_TRAMPOLINE, HAVE_PRE_INCREMENT,
HAVE_POST_DECREMENT, HAVE_PRE_DECREMENT, HAVE_PRE_MODIFY_DISP,
HAVE_POST_MODIFY_DISP, HAVE_PRE_MODIFY_REG, HAVE_POST_MODIFY_REG,
REGNO_MODE_OK_FOR_BASE_P, LEGITIMATE_CONSTANT_P,
REG_MODE_OK_FOR_BASE_P, REG_OK_FOR_INDEX_P, GO_IF_LEGITIMATE_ADDRESS,
LEGITIMIZE_ADDRESS, THUMB2_LEGITIMIZE_ADDRESS,
GO_IF_MODE_DEPENDENT_ADDRESS, MEMORY_MOVE_COST, BRANCH_COST,
ASM_APP_OFF, ASM_OUTPUT_CASE_LABEL, ARM_DECLARE_FUNCTION_NAME,
FINAL_PRESCAN_INSN, PRINT_OPERAND_PUNCT_VALID_P,
PRINT_OPERAND_ADDRESS): Adjust for Thumb-2.
(arm_arch_notm, arm_arch_thumb2, arm_arch_hwdiv): New declarations.
* config/arm/arm-cores.def: Add arm1156t2-s, cortex-a8, cortex-r4 and
cortex-m3.
* config/arm/arm-tune.md: Regenerate.
* config/arm/arm-protos.h: Update prototypes.
* config/arm/vfp.md: Enable patterns for Thumb-2.
(arm_movsi_vfp): Add movw alternative. Use output_move_vfp.
(arm_movdi_vfp, movsf_vfp, movdf_vfp): Use output_move_vfp.
(thumb2_movsi_vfp, thumb2_movdi_vfp, thumb2_movsf_vfp,
thumb2_movdf_vfp, thumb2_movsfcc_vfp, thumb2_movdfcc_vfp): New.
* config/arm/libunwind.S: Add Thumb-2 code.
* config/arm/constraints.md: Update include Thumb-2.
* config/arm/ieee754-sf.S: Add Thumb-2/Unified asm support.
* config/arm/ieee754-df.S: Ditto.
* config/arm/bpabi.S: Ditto.
* config/arm/t-arm (MD_INCLUDES): Add thumb2.md.
* config/arm/predicates.md (low_register_operand,
low_reg_or_int_operand, thumb_16bit_operator): New.
(thumb_cmp_operand, thumb_cmpneg_operand): Rename...
(thumb1_cmp_operand, thumb1_cmpneg_operand): ... to this.
* config/arm/t-arm-elf: Add armv7 multilib.
* config/arm/arm.md: Update patterns for Thumb-2 and Unified asm.
Include thumb2.md.
(UNSPEC_STACK_ALIGN, ce_count): New.
(arm_incscc, arm_decscc, arm_umaxsi3, arm_uminsi3,
arm_zero_extendsidi2, arm_zero_extendqidi2): New
insns/expanders.
* config/arm/fpa.md: Update patterns for Thumb-2 and Unified asm.
(thumb2_movsf_fpa, thumb2_movdf_fpa, thumb2_movxf_fpa,
thumb2_movsfcc_fpa, thumb2_movdfcc_fpa): New insns.
* config/arm/cirrus.md: Update patterns for Thumb-2 and Unified asm.
(cirrus_thumb2_movdi, cirrus_thumb2_movsi_insn,
thumb2_cirrus_movsf_hard_insn, thumb2_cirrus_movdf_hard_insn): New
insns.
* doc/extend.texi: Document ARMv7-M interrupt functions.
* doc/invoke.texi: Document Thumb-2 new cores+architectures.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@120408 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/config/arm/arm.h')
-rw-r--r-- | gcc/config/arm/arm.h | 305 |
1 files changed, 209 insertions, 96 deletions
diff --git a/gcc/config/arm/arm.h b/gcc/config/arm/arm.h index 468b5b31507..d2f493b6fed 100644 --- a/gcc/config/arm/arm.h +++ b/gcc/config/arm/arm.h @@ -1,6 +1,6 @@ /* Definitions of target machine for GNU compiler, for ARM. Copyright (C) 1991, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, - 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc. + 2001, 2002, 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc. Contributed by Pieter `Tiggr' Schoenmakers (rcpieter@win.tue.nl) and Martin Simmons (@harleqn.co.uk). More major hacks by Richard Earnshaw (rearnsha@arm.com) @@ -39,6 +39,8 @@ extern char arm_arch_name[]; builtin_define ("__APCS_32__"); \ if (TARGET_THUMB) \ builtin_define ("__thumb__"); \ + if (TARGET_THUMB2) \ + builtin_define ("__thumb2__"); \ \ if (TARGET_BIG_END) \ { \ @@ -181,8 +183,8 @@ extern GTY(()) rtx aof_pic_label; #define TARGET_MAVERICK (arm_fp_model == ARM_FP_MODEL_MAVERICK) #define TARGET_VFP (arm_fp_model == ARM_FP_MODEL_VFP) #define TARGET_IWMMXT (arm_arch_iwmmxt) -#define TARGET_REALLY_IWMMXT (TARGET_IWMMXT && TARGET_ARM) -#define TARGET_IWMMXT_ABI (TARGET_ARM && arm_abi == ARM_ABI_IWMMXT) +#define TARGET_REALLY_IWMMXT (TARGET_IWMMXT && TARGET_32BIT) +#define TARGET_IWMMXT_ABI (TARGET_32BIT && arm_abi == ARM_ABI_IWMMXT) #define TARGET_ARM (! TARGET_THUMB) #define TARGET_EITHER 1 /* (TARGET_ARM | TARGET_THUMB) */ #define TARGET_BACKTRACE (leaf_function_p () \ @@ -195,6 +197,25 @@ extern GTY(()) rtx aof_pic_label; #define TARGET_HARD_TP (target_thread_pointer == TP_CP15) #define TARGET_SOFT_TP (target_thread_pointer == TP_SOFT) +/* Only 16-bit thumb code. */ +#define TARGET_THUMB1 (TARGET_THUMB && !arm_arch_thumb2) +/* Arm or Thumb-2 32-bit code. */ +#define TARGET_32BIT (TARGET_ARM || arm_arch_thumb2) +/* 32-bit Thumb-2 code. */ +#define TARGET_THUMB2 (TARGET_THUMB && arm_arch_thumb2) + +/* "DSP" multiply instructions, eg. SMULxy. */ +#define TARGET_DSP_MULTIPLY \ + (TARGET_32BIT && arm_arch5e && arm_arch_notm) +/* Integer SIMD instructions, and extend-accumulate instructions. */ +#define TARGET_INT_SIMD \ + (TARGET_32BIT && arm_arch6 && arm_arch_notm) + +/* We could use unified syntax for arm mode, but for now we just use it + for Thumb-2. */ +#define TARGET_UNIFIED_ASM TARGET_THUMB2 + + /* True iff the full BPABI is being used. If TARGET_BPABI is true, then TARGET_AAPCS_BASED must be true -- but the converse does not hold. TARGET_BPABI implies the use of the BPABI runtime library, @@ -320,6 +341,9 @@ extern int arm_arch5e; /* Nonzero if this chip supports the ARM Architecture 6 extensions. */ extern int arm_arch6; +/* Nonzero if instructions not present in the 'M' profile can be used. */ +extern int arm_arch_notm; + /* Nonzero if this chip can benefit from load scheduling. */ extern int arm_ld_sched; @@ -351,6 +375,12 @@ extern int arm_tune_wbuf; interworking clean. */ extern int arm_cpp_interwork; +/* Nonzero if chip supports Thumb 2. */ +extern int arm_arch_thumb2; + +/* Nonzero if chip supports integer division instruction. */ +extern int arm_arch_hwdiv; + #ifndef TARGET_DEFAULT #define TARGET_DEFAULT (MASK_APCS_FRAME) #endif @@ -648,7 +678,7 @@ extern int arm_structure_size_boundary; { \ int regno; \ \ - if (TARGET_SOFT_FLOAT || TARGET_THUMB || !TARGET_FPA) \ + if (TARGET_SOFT_FLOAT || TARGET_THUMB1 || !TARGET_FPA) \ { \ for (regno = FIRST_FPA_REGNUM; \ regno <= LAST_FPA_REGNUM; ++regno) \ @@ -660,6 +690,7 @@ extern int arm_structure_size_boundary; /* When optimizing for size, it's better not to use \ the HI regs, because of the overhead of stacking \ them. */ \ + /* ??? Is this still true for thumb2? */ \ for (regno = FIRST_HI_REGNUM; \ regno <= LAST_HI_REGNUM; ++regno) \ fixed_regs[regno] = call_used_regs[regno] = 1; \ @@ -668,10 +699,10 @@ extern int arm_structure_size_boundary; /* The link register can be clobbered by any branch insn, \ but we have no way to track that at present, so mark \ it as unavailable. */ \ - if (TARGET_THUMB) \ + if (TARGET_THUMB1) \ fixed_regs[LR_REGNUM] = call_used_regs[LR_REGNUM] = 1; \ \ - if (TARGET_ARM && TARGET_HARD_FLOAT) \ + if (TARGET_32BIT && TARGET_HARD_FLOAT) \ { \ if (TARGET_MAVERICK) \ { \ @@ -807,7 +838,7 @@ extern int arm_structure_size_boundary; /* The native (Norcroft) Pascal compiler for the ARM passes the static chain as an invisible last argument (possible since varargs don't exist in Pascal), so the following is not true. */ -#define STATIC_CHAIN_REGNUM (TARGET_ARM ? 12 : 9) +#define STATIC_CHAIN_REGNUM 12 /* Define this to be where the real frame pointer is if it is not possible to work out the offset between the frame pointer and the automatic variables @@ -901,7 +932,7 @@ extern int arm_structure_size_boundary; On the ARM regs are UNITS_PER_WORD bits wide; FPA regs can hold any FP mode. */ #define HARD_REGNO_NREGS(REGNO, MODE) \ - ((TARGET_ARM \ + ((TARGET_32BIT \ && REGNO >= FIRST_FPA_REGNUM \ && REGNO != FRAME_POINTER_REGNUM \ && REGNO != ARG_POINTER_REGNUM) \ @@ -1042,14 +1073,14 @@ enum reg_class || (CLASS) == CC_REG) /* The class value for index registers, and the one for base regs. */ -#define INDEX_REG_CLASS (TARGET_THUMB ? LO_REGS : GENERAL_REGS) -#define BASE_REG_CLASS (TARGET_THUMB ? LO_REGS : GENERAL_REGS) +#define INDEX_REG_CLASS (TARGET_THUMB1 ? LO_REGS : GENERAL_REGS) +#define BASE_REG_CLASS (TARGET_THUMB1 ? LO_REGS : GENERAL_REGS) /* For the Thumb the high registers cannot be used as base registers when addressing quantities in QI or HI mode; if we don't know the mode, then we must be conservative. */ #define MODE_BASE_REG_CLASS(MODE) \ - (TARGET_ARM ? GENERAL_REGS : \ + (TARGET_32BIT ? GENERAL_REGS : \ (((MODE) == SImode) ? BASE_REGS : LO_REGS)) /* For Thumb we can not support SP+reg addressing, so we return LO_REGS @@ -1060,15 +1091,16 @@ enum reg_class registers explicitly used in the rtl to be used as spill registers but prevents the compiler from extending the lifetime of these registers. */ -#define SMALL_REGISTER_CLASSES TARGET_THUMB +#define SMALL_REGISTER_CLASSES TARGET_THUMB1 /* Given an rtx X being reloaded into a reg required to be in class CLASS, return the class of reg to actually use. - In general this is just CLASS, but for the Thumb we prefer - a LO_REGS class or a subset. */ -#define PREFERRED_RELOAD_CLASS(X, CLASS) \ - (TARGET_ARM ? (CLASS) : \ - ((CLASS) == BASE_REGS ? (CLASS) : LO_REGS)) + In general this is just CLASS, but for the Thumb core registers and + immediate constants we prefer a LO_REGS class or a subset. */ +#define PREFERRED_RELOAD_CLASS(X, CLASS) \ + (TARGET_ARM ? (CLASS) : \ + ((CLASS) == GENERAL_REGS || (CLASS) == HI_REGS \ + || (CLASS) == NO_REGS ? LO_REGS : (CLASS))) /* Must leave BASE_REGS reloads alone */ #define THUMB_SECONDARY_INPUT_RELOAD_CLASS(CLASS, MODE, X) \ @@ -1093,7 +1125,7 @@ enum reg_class ((TARGET_VFP && TARGET_HARD_FLOAT \ && (CLASS) == VFP_REGS) \ ? vfp_secondary_reload_class (MODE, X) \ - : TARGET_ARM \ + : TARGET_32BIT \ ? (((MODE) == HImode && ! arm_arch4 && true_regnum (X) == -1) \ ? GENERAL_REGS : NO_REGS) \ : THUMB_SECONDARY_OUTPUT_RELOAD_CLASS (CLASS, MODE, X)) @@ -1109,7 +1141,7 @@ enum reg_class && (CLASS) == CIRRUS_REGS \ && (CONSTANT_P (X) || GET_CODE (X) == SYMBOL_REF)) \ ? GENERAL_REGS : \ - (TARGET_ARM ? \ + (TARGET_32BIT ? \ (((CLASS) == IWMMXT_REGS || (CLASS) == IWMMXT_GR_REGS) \ && CONSTANT_P (X)) \ ? GENERAL_REGS : \ @@ -1188,6 +1220,7 @@ enum reg_class /* We could probably achieve better results by defining PROMOTE_MODE to help cope with the variances between the Thumb's signed and unsigned byte and halfword load instructions. */ +/* ??? This should be safe for thumb2, but we may be able to do better. */ #define THUMB_LEGITIMIZE_RELOAD_ADDRESS(X, MODE, OPNUM, TYPE, IND_L, WIN) \ do { \ rtx new_x = thumb_legitimize_reload_address (&X, MODE, OPNUM, TYPE, IND_L); \ @@ -1215,7 +1248,7 @@ do { \ /* Moves between FPA_REGS and GENERAL_REGS are two memory insns. */ #define REGISTER_MOVE_COST(MODE, FROM, TO) \ - (TARGET_ARM ? \ + (TARGET_32BIT ? \ ((FROM) == FPA_REGS && (TO) != FPA_REGS ? 20 : \ (FROM) != FPA_REGS && (TO) == FPA_REGS ? 20 : \ (FROM) == VFP_REGS && (TO) != VFP_REGS ? 10 : \ @@ -1289,10 +1322,10 @@ do { \ /* Define how to find the value returned by a library function assuming the value has mode MODE. */ #define LIBCALL_VALUE(MODE) \ - (TARGET_ARM && TARGET_HARD_FLOAT_ABI && TARGET_FPA \ + (TARGET_32BIT && TARGET_HARD_FLOAT_ABI && TARGET_FPA \ && GET_MODE_CLASS (MODE) == MODE_FLOAT \ ? gen_rtx_REG (MODE, FIRST_FPA_REGNUM) \ - : TARGET_ARM && TARGET_HARD_FLOAT_ABI && TARGET_MAVERICK \ + : TARGET_32BIT && TARGET_HARD_FLOAT_ABI && TARGET_MAVERICK \ && GET_MODE_CLASS (MODE) == MODE_FLOAT \ ? gen_rtx_REG (MODE, FIRST_CIRRUS_FP_REGNUM) \ : TARGET_IWMMXT_ABI && arm_vector_mode_supported_p (MODE) \ @@ -1311,10 +1344,10 @@ do { \ /* On a Cirrus chip, mvf0 can return results. */ #define FUNCTION_VALUE_REGNO_P(REGNO) \ ((REGNO) == ARG_REGISTER (1) \ - || (TARGET_ARM && ((REGNO) == FIRST_CIRRUS_FP_REGNUM) \ + || (TARGET_32BIT && ((REGNO) == FIRST_CIRRUS_FP_REGNUM) \ && TARGET_HARD_FLOAT_ABI && TARGET_MAVERICK) \ || ((REGNO) == FIRST_IWMMXT_REGNUM && TARGET_IWMMXT_ABI) \ - || (TARGET_ARM && ((REGNO) == FIRST_FPA_REGNUM) \ + || (TARGET_32BIT && ((REGNO) == FIRST_FPA_REGNUM) \ && TARGET_HARD_FLOAT_ABI && TARGET_FPA)) /* Amount of memory needed for an untyped call to save all possible return @@ -1362,6 +1395,7 @@ do { \ #define ARM_FT_NAKED (1 << 3) /* No prologue or epilogue. */ #define ARM_FT_VOLATILE (1 << 4) /* Does not return. */ #define ARM_FT_NESTED (1 << 5) /* Embedded inside another func. */ +#define ARM_FT_STACKALIGN (1 << 6) /* Called with misaligned stack. */ /* Some macros to test these flags. */ #define ARM_FUNC_TYPE(t) (t & ARM_FT_TYPE_MASK) @@ -1369,6 +1403,7 @@ do { \ #define IS_VOLATILE(t) (t & ARM_FT_VOLATILE) #define IS_NAKED(t) (t & ARM_FT_NAKED) #define IS_NESTED(t) (t & ARM_FT_NESTED) +#define IS_STACKALIGN(t) (t & ARM_FT_STACKALIGN) /* Structure used to hold the function stack frame layout. Offsets are @@ -1570,6 +1605,8 @@ typedef struct /* Determine if the epilogue should be output as RTL. You should override this if you define FUNCTION_EXTRA_EPILOGUE. */ +/* This is disabled for Thumb-2 because it will confuse the + conditional insn counter. */ #define USE_RETURN_INSN(ISCOND) \ (TARGET_ARM ? use_return_insn (ISCOND, NULL) : 0) @@ -1646,37 +1683,57 @@ typedef struct assemble_aligned_integer (UNITS_PER_WORD, const0_rtx); \ } -/* On the Thumb we always switch into ARM mode to execute the trampoline. - Why - because it is easier. This code will always be branched to via - a BX instruction and since the compiler magically generates the address - of the function the linker has no opportunity to ensure that the - bottom bit is set. Thus the processor will be in ARM mode when it - reaches this code. So we duplicate the ARM trampoline code and add - a switch into Thumb mode as well. */ -#define THUMB_TRAMPOLINE_TEMPLATE(FILE) \ +/* 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) \ { \ - fprintf (FILE, "\t.code 32\n"); \ + ASM_OUTPUT_ALIGN(FILE, 2); \ + fprintf (FILE, "\t.code\t16\n"); \ fprintf (FILE, ".Ltrampoline_start:\n"); \ - asm_fprintf (FILE, "\tldr\t%r, [%r, #8]\n", \ - STATIC_CHAIN_REGNUM, PC_REGNUM); \ - asm_fprintf (FILE, "\tldr\t%r, [%r, #8]\n", \ - IP_REGNUM, PC_REGNUM); \ - asm_fprintf (FILE, "\torr\t%r, %r, #1\n", \ - IP_REGNUM, IP_REGNUM); \ - asm_fprintf (FILE, "\tbx\t%r\n", IP_REGNUM); \ - fprintf (FILE, "\t.word\t0\n"); \ - fprintf (FILE, "\t.word\t0\n"); \ - fprintf (FILE, "\t.code 16\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 \ - THUMB_TRAMPOLINE_TEMPLATE (FILE) + 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_ARM ? 16 : 24) +#define TRAMPOLINE_SIZE (TARGET_32BIT ? 16 : 20) /* Alignment required for a trampoline in bits. */ #define TRAMPOLINE_ALIGNMENT 32 @@ -1690,11 +1747,11 @@ typedef struct { \ emit_move_insn (gen_rtx_MEM (SImode, \ plus_constant (TRAMP, \ - TARGET_ARM ? 8 : 16)), \ + TARGET_32BIT ? 8 : 12)), \ CXT); \ emit_move_insn (gen_rtx_MEM (SImode, \ plus_constant (TRAMP, \ - TARGET_ARM ? 12 : 20)), \ + TARGET_32BIT ? 12 : 16)), \ FNADDR); \ emit_library_call (gen_rtx_SYMBOL_REF (Pmode, "__clear_cache"), \ 0, VOIDmode, 2, TRAMP, Pmode, \ @@ -1705,13 +1762,13 @@ typedef struct /* Addressing modes, and classification of registers for them. */ #define HAVE_POST_INCREMENT 1 -#define HAVE_PRE_INCREMENT TARGET_ARM -#define HAVE_POST_DECREMENT TARGET_ARM -#define HAVE_PRE_DECREMENT TARGET_ARM -#define HAVE_PRE_MODIFY_DISP TARGET_ARM -#define HAVE_POST_MODIFY_DISP TARGET_ARM -#define HAVE_PRE_MODIFY_REG TARGET_ARM -#define HAVE_POST_MODIFY_REG TARGET_ARM +#define HAVE_PRE_INCREMENT TARGET_32BIT +#define HAVE_POST_DECREMENT TARGET_32BIT +#define HAVE_PRE_DECREMENT TARGET_32BIT +#define HAVE_PRE_MODIFY_DISP TARGET_32BIT +#define HAVE_POST_MODIFY_DISP TARGET_32BIT +#define HAVE_PRE_MODIFY_REG TARGET_32BIT +#define HAVE_POST_MODIFY_REG TARGET_32BIT /* Macros to check register numbers against specific register classes. */ @@ -1723,20 +1780,20 @@ typedef struct #define TEST_REGNO(R, TEST, VALUE) \ ((R TEST VALUE) || ((unsigned) reg_renumber[R] TEST VALUE)) -/* On the ARM, don't allow the pc to be used. */ +/* Don't allow the pc to be used. */ #define ARM_REGNO_OK_FOR_BASE_P(REGNO) \ (TEST_REGNO (REGNO, <, PC_REGNUM) \ || TEST_REGNO (REGNO, ==, FRAME_POINTER_REGNUM) \ || TEST_REGNO (REGNO, ==, ARG_POINTER_REGNUM)) -#define THUMB_REGNO_MODE_OK_FOR_BASE_P(REGNO, MODE) \ +#define THUMB1_REGNO_MODE_OK_FOR_BASE_P(REGNO, MODE) \ (TEST_REGNO (REGNO, <=, LAST_LO_REGNUM) \ || (GET_MODE_SIZE (MODE) >= 4 \ && TEST_REGNO (REGNO, ==, STACK_POINTER_REGNUM))) #define REGNO_MODE_OK_FOR_BASE_P(REGNO, MODE) \ - (TARGET_THUMB \ - ? THUMB_REGNO_MODE_OK_FOR_BASE_P (REGNO, MODE) \ + (TARGET_THUMB1 \ + ? THUMB1_REGNO_MODE_OK_FOR_BASE_P (REGNO, MODE) \ : ARM_REGNO_OK_FOR_BASE_P (REGNO)) /* Nonzero if X can be the base register in a reg+reg addressing mode. @@ -1763,6 +1820,7 @@ typedef struct #else +/* ??? Should the TARGET_ARM here also apply to thumb2? */ #define CONSTANT_ADDRESS_P(X) \ (GET_CODE (X) == SYMBOL_REF \ && (CONSTANT_POOL_ADDRESS_P (X) \ @@ -1788,8 +1846,8 @@ typedef struct #define LEGITIMATE_CONSTANT_P(X) \ (!arm_tls_referenced_p (X) \ - && (TARGET_ARM ? ARM_LEGITIMATE_CONSTANT_P (X) \ - : THUMB_LEGITIMATE_CONSTANT_P (X))) + && (TARGET_32BIT ? ARM_LEGITIMATE_CONSTANT_P (X) \ + : THUMB_LEGITIMATE_CONSTANT_P (X))) /* Special characters prefixed to function names in order to encode attribute like information. @@ -1823,6 +1881,11 @@ typedef struct #define ASM_OUTPUT_LABELREF(FILE, NAME) \ arm_asm_output_labelref (FILE, NAME) +/* Output IT instructions for conditonally executed Thumb-2 instructions. */ +#define ASM_OUTPUT_OPCODE(STREAM, PTR) \ + if (TARGET_THUMB2) \ + thumb2_asm_output_opcode (STREAM); + /* The EABI specifies that constructors should go in .init_array. Other targets use .ctors for compatibility. */ #ifndef ARM_EABI_CTORS_SECTION_OP @@ -1898,7 +1961,8 @@ typedef struct We have two alternate definitions for each of them. The usual definition accepts all pseudo regs; the other rejects them unless they have been allocated suitable hard regs. - The symbol REG_OK_STRICT causes the latter definition to be used. */ + The symbol REG_OK_STRICT causes the latter definition to be used. + Thumb-2 has the same restictions as arm. */ #ifndef REG_OK_STRICT #define ARM_REG_OK_FOR_BASE_P(X) \ @@ -1907,7 +1971,7 @@ typedef struct || REGNO (X) == FRAME_POINTER_REGNUM \ || REGNO (X) == ARG_POINTER_REGNUM) -#define THUMB_REG_MODE_OK_FOR_BASE_P(X, MODE) \ +#define THUMB1_REG_MODE_OK_FOR_BASE_P(X, MODE) \ (REGNO (X) <= LAST_LO_REGNUM \ || REGNO (X) >= FIRST_PSEUDO_REGISTER \ || (GET_MODE_SIZE (MODE) >= 4 \ @@ -1922,8 +1986,8 @@ typedef struct #define ARM_REG_OK_FOR_BASE_P(X) \ ARM_REGNO_OK_FOR_BASE_P (REGNO (X)) -#define THUMB_REG_MODE_OK_FOR_BASE_P(X, MODE) \ - THUMB_REGNO_MODE_OK_FOR_BASE_P (REGNO (X), MODE) +#define THUMB1_REG_MODE_OK_FOR_BASE_P(X, MODE) \ + THUMB1_REGNO_MODE_OK_FOR_BASE_P (REGNO (X), MODE) #define REG_STRICT_P 1 @@ -1932,22 +1996,23 @@ typedef struct /* Now define some helpers in terms of the above. */ #define REG_MODE_OK_FOR_BASE_P(X, MODE) \ - (TARGET_THUMB \ - ? THUMB_REG_MODE_OK_FOR_BASE_P (X, MODE) \ + (TARGET_THUMB1 \ + ? THUMB1_REG_MODE_OK_FOR_BASE_P (X, MODE) \ : ARM_REG_OK_FOR_BASE_P (X)) #define ARM_REG_OK_FOR_INDEX_P(X) ARM_REG_OK_FOR_BASE_P (X) -/* For Thumb, a valid index register is anything that can be used in +/* For 16-bit Thumb, a valid index register is anything that can be used in a byte load instruction. */ -#define THUMB_REG_OK_FOR_INDEX_P(X) THUMB_REG_MODE_OK_FOR_BASE_P (X, QImode) +#define THUMB1_REG_OK_FOR_INDEX_P(X) \ + THUMB1_REG_MODE_OK_FOR_BASE_P (X, QImode) /* Nonzero if X is a hard reg that can be used as an index or if it is a pseudo reg. On the Thumb, the stack pointer is not suitable. */ #define REG_OK_FOR_INDEX_P(X) \ - (TARGET_THUMB \ - ? THUMB_REG_OK_FOR_INDEX_P (X) \ + (TARGET_THUMB1 \ + ? THUMB1_REG_OK_FOR_INDEX_P (X) \ : ARM_REG_OK_FOR_INDEX_P (X)) /* Nonzero if X can be the base register in a reg+reg addressing mode. @@ -1972,17 +2037,25 @@ typedef struct goto WIN; \ } -#define THUMB_GO_IF_LEGITIMATE_ADDRESS(MODE,X,WIN) \ +#define THUMB2_GO_IF_LEGITIMATE_ADDRESS(MODE,X,WIN) \ { \ - if (thumb_legitimate_address_p (MODE, X, REG_STRICT_P)) \ + if (thumb2_legitimate_address_p (MODE, X, REG_STRICT_P)) \ + goto WIN; \ + } + +#define THUMB1_GO_IF_LEGITIMATE_ADDRESS(MODE,X,WIN) \ + { \ + if (thumb1_legitimate_address_p (MODE, X, REG_STRICT_P)) \ goto WIN; \ } #define GO_IF_LEGITIMATE_ADDRESS(MODE, X, WIN) \ if (TARGET_ARM) \ ARM_GO_IF_LEGITIMATE_ADDRESS (MODE, X, WIN) \ - else /* if (TARGET_THUMB) */ \ - THUMB_GO_IF_LEGITIMATE_ADDRESS (MODE, X, WIN) + else if (TARGET_THUMB2) \ + THUMB2_GO_IF_LEGITIMATE_ADDRESS (MODE, X, WIN) \ + else /* if (TARGET_THUMB1) */ \ + THUMB1_GO_IF_LEGITIMATE_ADDRESS (MODE, X, WIN) /* Try machine-dependent ways of modifying an illegitimate address @@ -1992,7 +2065,12 @@ do { \ X = arm_legitimize_address (X, OLDX, MODE); \ } while (0) -#define THUMB_LEGITIMIZE_ADDRESS(X, OLDX, MODE, WIN) \ +/* ??? Implement LEGITIMIZE_ADDRESS for thumb2. */ +#define THUMB2_LEGITIMIZE_ADDRESS(X, OLDX, MODE, WIN) \ +do { \ +} while (0) + +#define THUMB1_LEGITIMIZE_ADDRESS(X, OLDX, MODE, WIN) \ do { \ X = thumb_legitimize_address (X, OLDX, MODE); \ } while (0) @@ -2001,8 +2079,10 @@ do { \ do { \ if (TARGET_ARM) \ ARM_LEGITIMIZE_ADDRESS (X, OLDX, MODE, WIN); \ + else if (TARGET_THUMB2) \ + THUMB2_LEGITIMIZE_ADDRESS (X, OLDX, MODE, WIN); \ else \ - THUMB_LEGITIMIZE_ADDRESS (X, OLDX, MODE, WIN); \ + THUMB1_LEGITIMIZE_ADDRESS (X, OLDX, MODE, WIN); \ \ if (memory_address_p (MODE, X)) \ goto WIN; \ @@ -2019,7 +2099,7 @@ do { \ /* Nothing helpful to do for the Thumb */ #define GO_IF_MODE_DEPENDENT_ADDRESS(ADDR, LABEL) \ - if (TARGET_ARM) \ + if (TARGET_32BIT) \ ARM_GO_IF_MODE_DEPENDENT_ADDRESS (ADDR, LABEL) @@ -2027,6 +2107,13 @@ do { \ for the index in the tablejump instruction. */ #define CASE_VECTOR_MODE Pmode +#define CASE_VECTOR_PC_RELATIVE TARGET_THUMB2 + +#define CASE_VECTOR_SHORTEN_MODE(min, max, body) \ + ((min < 0 || max >= 0x2000 || !TARGET_THUMB2) ? SImode \ + : (max >= 0x200) ? HImode \ + : QImode) + /* signed 'char' is most compatible, but RISC OS wants it unsigned. unsigned is probably best, but may break some code. */ #ifndef DEFAULT_SIGNED_CHAR @@ -2085,14 +2172,14 @@ do { \ /* Moves to and from memory are quite expensive */ #define MEMORY_MOVE_COST(M, CLASS, IN) \ - (TARGET_ARM ? 10 : \ + (TARGET_32BIT ? 10 : \ ((GET_MODE_SIZE (M) < 4 ? 8 : 2 * GET_MODE_SIZE (M)) \ * (CLASS == LO_REGS ? 1 : 2))) /* Try to generate sequences that don't involve branches, we can then use conditional instructions */ #define BRANCH_COST \ - (TARGET_ARM ? 4 : (optimize > 0 ? 2 : 0)) + (TARGET_32BIT ? 4 : (optimize > 0 ? 2 : 0)) /* Position Independent Code. */ /* We decide which register to use based on the compilation options and @@ -2160,7 +2247,8 @@ extern int making_const_table; #define CLZ_DEFINED_VALUE_AT_ZERO(MODE, VALUE) ((VALUE) = 32, 1) #undef ASM_APP_OFF -#define ASM_APP_OFF (TARGET_THUMB ? "\t.code\t16\n" : "") +#define ASM_APP_OFF (TARGET_THUMB1 ? "\t.code\t16\n" : \ + TARGET_THUMB2 ? "\t.thumb\n" : "") /* Output a push or a pop instruction (only used when profiling). */ #define ASM_OUTPUT_REG_PUSH(STREAM, REGNO) \ @@ -2184,16 +2272,28 @@ extern int making_const_table; asm_fprintf (STREAM, "\tpop {%r}\n", REGNO); \ } while (0) +/* Jump table alignment is explicit in ASM_OUTPUT_CASE_LABEL. */ +#define ADDR_VEC_ALIGN(JUMPTABLE) 0 + /* This is how to output a label which precedes a jumptable. Since Thumb instructions are 2 bytes, we may need explicit alignment here. */ #undef ASM_OUTPUT_CASE_LABEL -#define ASM_OUTPUT_CASE_LABEL(FILE, PREFIX, NUM, JUMPTABLE) \ - do \ - { \ - if (TARGET_THUMB) \ - ASM_OUTPUT_ALIGN (FILE, 2); \ - (*targetm.asm_out.internal_label) (FILE, PREFIX, NUM); \ - } \ +#define ASM_OUTPUT_CASE_LABEL(FILE, PREFIX, NUM, JUMPTABLE) \ + do \ + { \ + if (TARGET_THUMB && GET_MODE (PATTERN (JUMPTABLE)) == SImode) \ + ASM_OUTPUT_ALIGN (FILE, 2); \ + (*targetm.asm_out.internal_label) (FILE, PREFIX, NUM); \ + } \ + while (0) + +/* Make sure subsequent insns are aligned after a TBB. */ +#define ASM_OUTPUT_CASE_END(FILE, NUM, JUMPTABLE) \ + do \ + { \ + if (GET_MODE (PATTERN (JUMPTABLE)) == QImode) \ + ASM_OUTPUT_ALIGN (FILE, 1); \ + } \ while (0) #define ARM_DECLARE_FUNCTION_NAME(STREAM, NAME, DECL) \ @@ -2201,11 +2301,13 @@ extern int making_const_table; { \ if (TARGET_THUMB) \ { \ - if (is_called_in_ARM_mode (DECL) \ - || current_function_is_thunk) \ + if (is_called_in_ARM_mode (DECL) \ + || (TARGET_THUMB1 && current_function_is_thunk)) \ fprintf (STREAM, "\t.code 32\n") ; \ + else if (TARGET_THUMB1) \ + fprintf (STREAM, "\t.code\t16\n\t.thumb_func\n") ; \ else \ - fprintf (STREAM, "\t.code 16\n\t.thumb_func\n") ; \ + fprintf (STREAM, "\t.thumb\n\t.thumb_func\n") ; \ } \ if (TARGET_POKE_FUNCTION_NAME) \ arm_poke_function_name (STREAM, (char *) NAME); \ @@ -2247,17 +2349,28 @@ extern int making_const_table; } #endif +/* Add two bytes to the length of conditionally executed Thumb-2 + instructions for the IT instruction. */ +#define ADJUST_INSN_LENGTH(insn, length) \ + if (TARGET_THUMB2 && GET_CODE (PATTERN (insn)) == COND_EXEC) \ + length += 2; + /* Only perform branch elimination (by making instructions conditional) if - we're optimizing. Otherwise it's of no use anyway. */ + we're optimizing. For Thumb-2 check if any IT instructions need + outputting. */ #define FINAL_PRESCAN_INSN(INSN, OPVEC, NOPERANDS) \ if (TARGET_ARM && optimize) \ arm_final_prescan_insn (INSN); \ - else if (TARGET_THUMB) \ - thumb_final_prescan_insn (INSN) + else if (TARGET_THUMB2) \ + thumb2_final_prescan_insn (INSN); \ + else if (TARGET_THUMB1) \ + thumb1_final_prescan_insn (INSN) #define PRINT_OPERAND_PUNCT_VALID_P(CODE) \ - (CODE == '@' || CODE == '|' \ - || (TARGET_ARM && (CODE == '?')) \ + (CODE == '@' || CODE == '|' || CODE == '.' \ + || CODE == '(' || CODE == ')' \ + || (TARGET_32BIT && (CODE == '?')) \ + || (TARGET_THUMB2 && (CODE == '!')) \ || (TARGET_THUMB && (CODE == '_'))) /* Output an operand of an instruction. */ @@ -2390,7 +2503,7 @@ extern int making_const_table; } #define PRINT_OPERAND_ADDRESS(STREAM, X) \ - if (TARGET_ARM) \ + if (TARGET_32BIT) \ ARM_PRINT_OPERAND_ADDRESS (STREAM, X) \ else \ THUMB_PRINT_OPERAND_ADDRESS (STREAM, X) |