diff options
author | bstarynk <bstarynk@138bc75d-0d04-0410-961f-82ee72b054a4> | 2010-09-27 11:57:01 +0000 |
---|---|---|
committer | bstarynk <bstarynk@138bc75d-0d04-0410-961f-82ee72b054a4> | 2010-09-27 11:57:01 +0000 |
commit | 8560c588b8e703a936e09b8b1c5381289b6fe2a8 (patch) | |
tree | 6551aaedcd3c7893355d5933f81fbb2dce9863de /gcc/config | |
parent | c3986c7ab5d242067928f202cc5f7c661242ce2a (diff) | |
download | gcc-8560c588b8e703a936e09b8b1c5381289b6fe2a8.tar.gz |
2010-09-27 Basile Starynkevitch <basile@starynkevitch.net>
MELT branch merged with trunk rev 164647
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/branches/melt-branch@164648 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/config')
54 files changed, 1769 insertions, 1409 deletions
diff --git a/gcc/config/alpha/alpha.c b/gcc/config/alpha/alpha.c index 4db554cbfbe..49c86fd9310 100644 --- a/gcc/config/alpha/alpha.c +++ b/gcc/config/alpha/alpha.c @@ -10029,6 +10029,7 @@ alpha_use_linkage (rtx func, tree cfundecl, int lflag, int rflag) al = ggc_alloc_alpha_links (); al->num = cfaf->num; + al->target = NULL; node = splay_tree_lookup (alpha_links_tree, (splay_tree_key) name); if (node) diff --git a/gcc/config/alpha/alpha.h b/gcc/config/alpha/alpha.h index f0d8b9dba4d..be885c1235d 100644 --- a/gcc/config/alpha/alpha.h +++ b/gcc/config/alpha/alpha.h @@ -916,7 +916,7 @@ extern int alpha_memory_latency; #define NONSTRICT_REG_OK_FP_BASE_P(X) \ (REGNO (X) == 31 || REGNO (X) == 63 \ || (REGNO (X) >= FIRST_PSEUDO_REGISTER \ - && REGNO (X) < LAST_VIRTUAL_REGISTER)) + && REGNO (X) < LAST_VIRTUAL_POINTER_REGISTER)) /* Nonzero if X is a hard reg that can be used as a base reg. */ #define STRICT_REG_OK_FOR_BASE_P(X) REGNO_OK_FOR_BASE_P (REGNO (X)) diff --git a/gcc/config/arm/arm-protos.h b/gcc/config/arm/arm-protos.h index 59e1c5024ec..c861bb6a361 100644 --- a/gcc/config/arm/arm-protos.h +++ b/gcc/config/arm/arm-protos.h @@ -86,6 +86,8 @@ extern int arm_coproc_mem_operand (rtx, bool); extern int neon_vector_mem_operand (rtx, int); extern int neon_struct_mem_operand (rtx); extern int arm_no_early_store_addr_dep (rtx, rtx); +extern int arm_early_store_addr_dep (rtx, rtx); +extern int arm_early_load_addr_dep (rtx, rtx); extern int arm_no_early_alu_shift_dep (rtx, rtx); extern int arm_no_early_alu_shift_value_dep (rtx, rtx); extern int arm_no_early_mul_dep (rtx, rtx); @@ -127,6 +129,7 @@ extern const char *output_move_quad (rtx *); extern const char *output_move_vfp (rtx *operands); extern const char *output_move_neon (rtx *operands); extern int arm_attr_length_move_neon (rtx); +extern int arm_address_offset_is_imm (rtx); extern const char *output_add_immediate (rtx *); extern const char *arithmetic_instr (rtx, int); extern void output_ascii_pseudo_op (FILE *, const unsigned char *, int); @@ -148,8 +151,6 @@ extern const char *arm_output_memory_barrier (rtx *); extern const char *arm_output_sync_insn (rtx, rtx *); extern unsigned int arm_sync_loop_insns (rtx , rtx *); -extern bool arm_output_addr_const_extra (FILE *, rtx); - #if defined TREE_CODE extern void arm_init_cumulative_args (CUMULATIVE_ARGS *, tree, rtx, tree); extern bool arm_pad_arg_upward (enum machine_mode, const_tree); diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c index 206e06cac52..44cbc8e1353 100644 --- a/gcc/config/arm/arm.c +++ b/gcc/config/arm/arm.c @@ -224,6 +224,7 @@ static bool arm_cannot_copy_insn_p (rtx); static bool arm_tls_symbol_p (rtx x); static int arm_issue_rate (void); static void arm_output_dwarf_dtprel (FILE *, int, rtx) ATTRIBUTE_UNUSED; +static bool arm_output_addr_const_extra (FILE *, rtx); static bool arm_allocate_stack_slots_for_args (void); static const char *arm_invalid_parameter_type (const_tree t); static const char *arm_invalid_return_type (const_tree t); @@ -239,6 +240,7 @@ static rtx arm_pic_static_addr (rtx orig, rtx reg); static bool cortex_a9_sched_adjust_cost (rtx, rtx, rtx, int *); static bool xscale_sched_adjust_cost (rtx, rtx, rtx, int *); static unsigned int arm_units_per_simd_word (enum machine_mode); +static bool arm_class_likely_spilled_p (reg_class_t); /* Table of machine attributes. */ @@ -308,6 +310,9 @@ static const struct attribute_spec arm_attribute_table[] = #undef TARGET_PRINT_OPERAND_PUNCT_VALID_P #define TARGET_PRINT_OPERAND_PUNCT_VALID_P arm_print_operand_punct_valid_p +#undef TARGET_ASM_OUTPUT_ADDR_CONST_EXTRA +#define TARGET_ASM_OUTPUT_ADDR_CONST_EXTRA arm_output_addr_const_extra + #undef TARGET_ASM_FUNCTION_PROLOGUE #define TARGET_ASM_FUNCTION_PROLOGUE arm_output_function_prologue @@ -545,6 +550,9 @@ static const struct attribute_spec arm_attribute_table[] = #undef TARGET_CAN_ELIMINATE #define TARGET_CAN_ELIMINATE arm_can_eliminate +#undef TARGET_CLASS_LIKELY_SPILLED_P +#define TARGET_CLASS_LIKELY_SPILLED_P arm_class_likely_spilled_p + struct gcc_target targetm = TARGET_INITIALIZER; /* Obstack for minipool constant handling. */ @@ -5847,7 +5855,8 @@ thumb1_legitimate_address_p (enum machine_mode mode, rtx x, int strict_p) && (REGNO (XEXP (x, 0)) == FRAME_POINTER_REGNUM || REGNO (XEXP (x, 0)) == ARG_POINTER_REGNUM || (REGNO (XEXP (x, 0)) >= FIRST_VIRTUAL_REGISTER - && REGNO (XEXP (x, 0)) <= LAST_VIRTUAL_REGISTER)) + && REGNO (XEXP (x, 0)) + <= LAST_VIRTUAL_POINTER_REGISTER)) && GET_MODE_SIZE (mode) >= 4 && GET_CODE (XEXP (x, 1)) == CONST_INT && (INTVAL (XEXP (x, 1)) & 3) == 0) @@ -13345,6 +13354,34 @@ arm_attr_length_move_neon (rtx insn) return 4; } +/* Return nonzero if the offset in the address is an immediate. Otherwise, + return zero. */ + +int +arm_address_offset_is_imm (rtx insn) +{ + rtx mem, addr; + + extract_insn_cached (insn); + + if (REG_P (recog_data.operand[0])) + return 0; + + mem = recog_data.operand[0]; + + gcc_assert (MEM_P (mem)); + + addr = XEXP (mem, 0); + + if (GET_CODE (addr) == REG + || (GET_CODE (addr) == PLUS + && GET_CODE (XEXP (addr, 0)) == REG + && GET_CODE (XEXP (addr, 1)) == CONST_INT)) + return 1; + else + return 0; +} + /* Output an ADD r, s, #n where n may be too big for one instruction. If adding zero to one register, output nothing. */ const char * @@ -21503,6 +21540,38 @@ arm_no_early_store_addr_dep (rtx producer, rtx consumer) return !reg_overlap_mentioned_p (value, addr); } +/* Return nonzero if the CONSUMER instruction (a store) does need + PRODUCER's value to calculate the address. */ + +int +arm_early_store_addr_dep (rtx producer, rtx consumer) +{ + return !arm_no_early_store_addr_dep (producer, consumer); +} + +/* Return nonzero if the CONSUMER instruction (a load) does need + PRODUCER's value to calculate the address. */ + +int +arm_early_load_addr_dep (rtx producer, rtx consumer) +{ + rtx value = PATTERN (producer); + rtx addr = PATTERN (consumer); + + if (GET_CODE (value) == COND_EXEC) + value = COND_EXEC_CODE (value); + if (GET_CODE (value) == PARALLEL) + value = XVECEXP (value, 0, 0); + value = XEXP (value, 0); + if (GET_CODE (addr) == COND_EXEC) + addr = COND_EXEC_CODE (addr); + if (GET_CODE (addr) == PARALLEL) + addr = XVECEXP (addr, 0, 0); + addr = XEXP (addr, 1); + + return reg_overlap_mentioned_p (value, addr); +} + /* Return nonzero if the CONSUMER instruction (an ALU op) does not have an early register shift value or amount dependency on the result of PRODUCER. */ @@ -21892,6 +21961,22 @@ arm_units_per_simd_word (enum machine_mode mode ATTRIBUTE_UNUSED) ? (TARGET_NEON_VECTORIZE_QUAD ? 16 : 8) : UNITS_PER_WORD); } +/* Implement TARGET_CLASS_LIKELY_SPILLED_P. + + We need to define this for LO_REGS on thumb. Otherwise we can end up + using r0-r4 for function arguments, r7 for the stack frame and don't + have enough left over to do doubleword arithmetic. */ + +static bool +arm_class_likely_spilled_p (reg_class_t rclass) +{ + if ((TARGET_THUMB && rclass == LO_REGS) + || rclass == CC_REG) + return true; + + return false; +} + /* Implements target hook small_register_classes_for_mode_p. */ bool arm_small_register_classes_for_mode_p (enum machine_mode mode ATTRIBUTE_UNUSED) @@ -22371,7 +22456,9 @@ arm_output_dwarf_dtprel (FILE *file, int size, rtx x) fputs ("(tlsldo)", file); } -bool +/* Implement TARGET_ASM_OUTPUT_ADDR_CONST_EXTRA. */ + +static bool arm_output_addr_const_extra (FILE *fp, rtx x) { if (GET_CODE (x) == UNSPEC && XINT (x, 1) == UNSPEC_TLS) diff --git a/gcc/config/arm/arm.h b/gcc/config/arm/arm.h index 8727305a6e2..9bd1c69e849 100644 --- a/gcc/config/arm/arm.h +++ b/gcc/config/arm/arm.h @@ -1284,13 +1284,6 @@ enum reg_class || reg_classes_intersect_p (VFP_REGS, (CLASS)) \ : 0) -/* We need to define this for LO_REGS on thumb. Otherwise we can end up - using r0-r4 for function arguments, r7 for the stack frame and don't - have enough left over to do doubleword arithmetic. */ -#define CLASS_LIKELY_SPILLED_P(CLASS) \ - ((TARGET_THUMB && (CLASS) == LO_REGS) \ - || (CLASS) == CC_REG) - /* The class value for index registers, and the one for base regs. */ #define INDEX_REG_CLASS (TARGET_THUMB1 ? LO_REGS : GENERAL_REGS) #define BASE_REG_CLASS (TARGET_THUMB1 ? LO_REGS : CORE_REGS) @@ -2426,10 +2419,6 @@ extern int making_const_table; & ~ (unsigned HOST_WIDE_INT) 0xffffffff) \ : 0)))) -#define OUTPUT_ADDR_CONST_EXTRA(file, x, fail) \ - if (arm_output_addr_const_extra (file, x) == FALSE) \ - goto fail - /* A C expression whose value is RTL representing the value of the return address for the frame COUNT steps up from the current frame. */ diff --git a/gcc/config/arm/arm.md b/gcc/config/arm/arm.md index 61b95e3ee00..c54bb2a1f37 100644 --- a/gcc/config/arm/arm.md +++ b/gcc/config/arm/arm.md @@ -497,16 +497,16 @@ ;; True if the generic scheduling description should be used. (define_attr "generic_sched" "yes,no" - (const (if_then_else - (ior (eq_attr "tune" "arm926ejs,arm1020e,arm1026ejs,arm1136js,arm1136jfs,cortexa5,cortexa8,cortexa9") - (eq_attr "tune_cortexr4" "yes")) + (const (if_then_else + (ior (eq_attr "tune" "arm926ejs,arm1020e,arm1026ejs,arm1136js,arm1136jfs,cortexa5,cortexa8,cortexa9,cortexm4") + (eq_attr "tune_cortexr4" "yes")) (const_string "no") (const_string "yes")))) (define_attr "generic_vfp" "yes,no" (const (if_then_else (and (eq_attr "fpu" "vfp") - (eq_attr "tune" "!arm1020e,arm1022e,cortexa5,cortexa8,cortexa9") + (eq_attr "tune" "!arm1020e,arm1022e,cortexa5,cortexa8,cortexa9,cortexm4") (eq_attr "tune_cortexr4" "no")) (const_string "yes") (const_string "no")))) @@ -521,6 +521,8 @@ (include "cortex-a9.md") (include "cortex-r4.md") (include "cortex-r4f.md") +(include "cortex-m4.md") +(include "cortex-m4-fpu.md") (include "vfp11.md") @@ -4040,7 +4042,8 @@ (define_insn "zero_extend<mode>di2" [(set (match_operand:DI 0 "s_register_operand" "=r") - (zero_extend:DI (match_operand:QHSI 1 "nonimmediate_operand" "rm")))] + (zero_extend:DI (match_operand:QHSI 1 "<qhs_extenddi_op>" + "<qhs_extenddi_cstr>")))] "TARGET_32BIT <qhs_zextenddi_cond>" "#" [(set_attr "length" "8") @@ -4050,7 +4053,8 @@ (define_insn "extend<mode>di2" [(set (match_operand:DI 0 "s_register_operand" "=r") - (sign_extend:DI (match_operand:QHSI 1 "nonimmediate_operand" "rm")))] + (sign_extend:DI (match_operand:QHSI 1 "<qhs_extenddi_op>" + "<qhs_extenddi_cstr>")))] "TARGET_32BIT <qhs_sextenddi_cond>" "#" [(set_attr "length" "8") @@ -5117,7 +5121,7 @@ [(set (match_operand:SI 0 "nonimmediate_operand" "=r") (lo_sum:SI (match_operand:SI 1 "nonimmediate_operand" "0") (match_operand:SI 2 "general_operand" "i")))] - "TARGET_32BIT" + "arm_arch_thumb2" "movt%?\t%0, #:upper16:%c2" [(set_attr "predicable" "yes") (set_attr "length" "4")] @@ -10577,7 +10581,7 @@ (const_int 16) (const_int 16)) (match_operand:SI 1 "const_int_operand" ""))] - "TARGET_32BIT" + "arm_arch_thumb2" "movt%?\t%0, %c1" [(set_attr "predicable" "yes") (set_attr "length" "4")] diff --git a/gcc/config/arm/cortex-m4-fpu.md b/gcc/config/arm/cortex-m4-fpu.md new file mode 100644 index 00000000000..7de115c5209 --- /dev/null +++ b/gcc/config/arm/cortex-m4-fpu.md @@ -0,0 +1,111 @@ +;; ARM Cortex-M4 FPU pipeline description +;; Copyright (C) 2010 Free Software Foundation, Inc. +;; Contributed by CodeSourcery. +;; +;; This file is part of GCC. +;; +;; GCC is free software; you can redistribute it and/or modify it +;; under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 3, or (at your option) +;; any later version. +;; +;; GCC is distributed in the hope that it will be useful, but +;; WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +;; General Public License for more details. +;; +;; You should have received a copy of the GNU General Public License +;; along with GCC; see the file COPYING3. If not see +;; <http://www.gnu.org/licenses/>. + +;; Use an artifial unit to model FPU. +(define_cpu_unit "cortex_m4_v" "cortex_m4") + +(define_reservation "cortex_m4_ex_v" "cortex_m4_ex+cortex_m4_v") + +;; Integer instructions following VDIV or VSQRT complete out-of-order. +(define_insn_reservation "cortex_m4_fdivs" 15 + (and (eq_attr "tune" "cortexm4") + (eq_attr "type" "fdivs")) + "cortex_m4_ex_v,cortex_m4_v*13") + +(define_insn_reservation "cortex_m4_vmov_1" 1 + (and (eq_attr "tune" "cortexm4") + (eq_attr "type" "fcpys,fconsts")) + "cortex_m4_ex_v") + +(define_insn_reservation "cortex_m4_vmov_2" 2 + (and (eq_attr "tune" "cortexm4") + (eq_attr "type" "f_2_r,r_2_f")) + "cortex_m4_ex_v*2") + +(define_insn_reservation "cortex_m4_fmuls" 2 + (and (eq_attr "tune" "cortexm4") + (eq_attr "type" "fmuls")) + "cortex_m4_ex_v") + +(define_insn_reservation "cortex_m4_fmacs" 4 + (and (eq_attr "tune" "cortexm4") + (eq_attr "type" "fmacs")) + "cortex_m4_ex_v*3") + +(define_insn_reservation "cortex_m4_ffariths" 1 + (and (eq_attr "tune" "cortexm4") + (eq_attr "type" "ffariths")) + "cortex_m4_ex_v") + +(define_insn_reservation "cortex_m4_fadds" 2 + (and (eq_attr "tune" "cortexm4") + (eq_attr "type" "fadds")) + "cortex_m4_ex_v") + +(define_insn_reservation "cortex_m4_fcmps" 1 + (and (eq_attr "tune" "cortexm4") + (eq_attr "type" "fcmps")) + "cortex_m4_ex_v") + +(define_insn_reservation "cortex_m4_f_flag" 1 + (and (eq_attr "tune" "cortexm4") + (eq_attr "type" "f_flag")) + "cortex_m4_ex_v") + +(define_insn_reservation "cortex_m4_f_cvt" 2 + (and (eq_attr "tune" "cortexm4") + (eq_attr "type" "f_cvt")) + "cortex_m4_ex_v") + +(define_insn_reservation "cortex_m4_f_load" 2 + (and (eq_attr "tune" "cortexm4") + (eq_attr "type" "f_load")) + "cortex_m4_ex_v*2") + +(define_insn_reservation "cortex_m4_f_store" 2 + (and (eq_attr "tune" "cortexm4") + (eq_attr "type" "f_store")) + "cortex_m4_ex_v*2") + +(define_insn_reservation "cortex_m4_f_loadd" 3 + (and (eq_attr "tune" "cortexm4") + (eq_attr "type" "f_loadd")) + "cortex_m4_ex_v*3") + +(define_insn_reservation "cortex_m4_f_stored" 3 + (and (eq_attr "tune" "cortexm4") + (eq_attr "type" "f_stored")) + "cortex_m4_ex_v*3") + +;; MAC instructions consume their addend one cycle later. If the result +;; of an arithmetic instruction is consumed as the addend of the following +;; MAC instruction, the latency can be decreased by one. + +(define_bypass 1 "cortex_m4_fadds,cortex_m4_fmuls,cortex_m4_f_cvt" + "cortex_m4_fmacs" + "arm_no_early_mul_dep") + +(define_bypass 3 "cortex_m4_fmacs" + "cortex_m4_fmacs" + "arm_no_early_mul_dep") + +(define_bypass 14 "cortex_m4_fdivs" + "cortex_m4_fmacs" + "arm_no_early_mul_dep") diff --git a/gcc/config/arm/cortex-m4.md b/gcc/config/arm/cortex-m4.md new file mode 100644 index 00000000000..b71037585d0 --- /dev/null +++ b/gcc/config/arm/cortex-m4.md @@ -0,0 +1,111 @@ +;; ARM Cortex-M4 pipeline description +;; Copyright (C) 2010 Free Software Foundation, Inc. +;; Contributed by CodeSourcery. +;; +;; This file is part of GCC. +;; +;; GCC is free software; you can redistribute it and/or modify it +;; under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 3, or (at your option) +;; any later version. +;; +;; GCC is distributed in the hope that it will be useful, but +;; WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +;; General Public License for more details. +;; +;; You should have received a copy of the GNU General Public License +;; along with GCC; see the file COPYING3. If not see +;; <http://www.gnu.org/licenses/>. + +(define_automaton "cortex_m4") + +;; We model the pipelining of LDR instructions by using two artificial units. + +(define_cpu_unit "cortex_m4_a" "cortex_m4") + +(define_cpu_unit "cortex_m4_b" "cortex_m4") + +(define_reservation "cortex_m4_ex" "cortex_m4_a+cortex_m4_b") + +;; ALU and multiply is one cycle. +(define_insn_reservation "cortex_m4_alu" 1 + (and (eq_attr "tune" "cortexm4") + (eq_attr "type" "alu,alu_shift,alu_shift_reg,mult")) + "cortex_m4_ex") + +;; Byte, half-word and word load is two cycles. +(define_insn_reservation "cortex_m4_load1" 2 + (and (eq_attr "tune" "cortexm4") + (eq_attr "type" "load_byte,load1")) + "cortex_m4_a, cortex_m4_b") + +;; str rx, [ry, #imm] is always one cycle. +(define_insn_reservation "cortex_m4_store1_1" 1 + (and (and (eq_attr "tune" "cortexm4") + (eq_attr "type" "store1")) + (ne (symbol_ref ("arm_address_offset_is_imm (insn)")) (const_int 0))) + "cortex_m4_a") + +;; Other byte, half-word and word load is two cycles. +(define_insn_reservation "cortex_m4_store1_2" 2 + (and (and (eq_attr "tune" "cortexm4") + (eq_attr "type" "store1")) + (eq (symbol_ref ("arm_address_offset_is_imm (insn)")) (const_int 0))) + "cortex_m4_a*2") + +(define_insn_reservation "cortex_m4_load2" 3 + (and (eq_attr "tune" "cortexm4") + (eq_attr "type" "load2")) + "cortex_m4_ex*3") + +(define_insn_reservation "cortex_m4_store2" 3 + (and (eq_attr "tune" "cortexm4") + (eq_attr "type" "store2")) + "cortex_m4_ex*3") + +(define_insn_reservation "cortex_m4_load3" 4 + (and (eq_attr "tune" "cortexm4") + (eq_attr "type" "load3")) + "cortex_m4_ex*4") + +(define_insn_reservation "cortex_m4_store3" 4 + (and (eq_attr "tune" "cortexm4") + (eq_attr "type" "store3")) + "cortex_m4_ex*4") + +(define_insn_reservation "cortex_m4_load4" 5 + (and (eq_attr "tune" "cortexm4") + (eq_attr "type" "load4")) + "cortex_m4_ex*5") + +(define_insn_reservation "cortex_m4_store4" 5 + (and (eq_attr "tune" "cortexm4") + (eq_attr "type" "store4")) + "cortex_m4_ex*5") + +;; If the address of load or store depends on the result of the preceding +;; instruction, the latency is increased by one. + +(define_bypass 2 "cortex_m4_alu" + "cortex_m4_load1" + "arm_early_load_addr_dep") + +(define_bypass 2 "cortex_m4_alu" + "cortex_m4_store1_1,cortex_m4_store1_2" + "arm_early_store_addr_dep") + +(define_insn_reservation "cortex_m4_branch" 3 + (and (eq_attr "tune" "cortexm4") + (eq_attr "type" "branch")) + "cortex_m4_ex*3") + +(define_insn_reservation "cortex_m4_call" 3 + (and (eq_attr "tune" "cortexm4") + (eq_attr "type" "call")) + "cortex_m4_ex*3") + +(define_insn_reservation "cortex_m4_block" 1 + (and (eq_attr "tune" "cortexm4") + (eq_attr "type" "block")) + "cortex_m4_ex") diff --git a/gcc/config/arm/iterators.md b/gcc/config/arm/iterators.md index 8e9f1001aba..887c962baeb 100644 --- a/gcc/config/arm/iterators.md +++ b/gcc/config/arm/iterators.md @@ -381,6 +381,10 @@ (define_mode_attr qhs_zextenddi_cond [(SI "") (HI "&& arm_arch6") (QI "")]) (define_mode_attr qhs_sextenddi_cond [(SI "") (HI "&& arm_arch6") (QI "&& arm_arch6")]) +(define_mode_attr qhs_extenddi_op [(SI "s_register_operand") + (HI "nonimmediate_operand") + (QI "nonimmediate_operand")]) +(define_mode_attr qhs_extenddi_cstr [(SI "r") (HI "rm") (QI "rm")]) ;;---------------------------------------------------------------------------- ;; Code attributes diff --git a/gcc/config/avr/avr-protos.h b/gcc/config/avr/avr-protos.h index aa0c6614c50..83de685e76c 100644 --- a/gcc/config/avr/avr-protos.h +++ b/gcc/config/avr/avr-protos.h @@ -24,7 +24,6 @@ extern int function_arg_regno_p (int r); extern void avr_cpu_cpp_builtins (struct cpp_reader * pfile); extern int avr_ret_register (void); -extern bool class_likely_spilled_p (int c); extern enum reg_class avr_regno_reg_class (int r); extern void asm_globalize_label (FILE *file, const char *name); extern void avr_asm_declare_function_name (FILE *, const char *, tree); diff --git a/gcc/config/avr/avr.c b/gcc/config/avr/avr.c index cabf678d8f9..2c7a8ad0204 100644 --- a/gcc/config/avr/avr.c +++ b/gcc/config/avr/avr.c @@ -92,6 +92,7 @@ static bool avr_hard_regno_scratch_ok (unsigned int); static unsigned int avr_case_values_threshold (void); static bool avr_frame_pointer_required_p (void); static bool avr_can_eliminate (const int, const int); +static bool avr_class_likely_spilled_p (reg_class_t c); /* Allocate registers from r25 to r8 for parameters for function calls. */ #define FIRST_CUM_REG 26 @@ -193,6 +194,9 @@ static const struct attribute_spec avr_attribute_table[] = #undef TARGET_CAN_ELIMINATE #define TARGET_CAN_ELIMINATE avr_can_eliminate +#undef TARGET_CLASS_LIKELY_SPILLED_P +#define TARGET_CLASS_LIKELY_SPILLED_P avr_class_likely_spilled_p + #undef TARGET_OPTION_OVERRIDE #define TARGET_OPTION_OVERRIDE avr_option_override @@ -4762,8 +4766,8 @@ gas_output_ascii(FILE *file, const char *str, size_t length) assigned to registers of class CLASS would likely be spilled because registers of CLASS are needed for spill registers. */ -bool -class_likely_spilled_p (int c) +static bool +avr_class_likely_spilled_p (reg_class_t c) { return (c != ALL_REGS && c != ADDW_REGS); } diff --git a/gcc/config/avr/avr.h b/gcc/config/avr/avr.h index 92c197a6ab9..60a58993517 100644 --- a/gcc/config/avr/avr.h +++ b/gcc/config/avr/avr.h @@ -333,8 +333,6 @@ enum reg_class { #define TARGET_SMALL_REGISTER_CLASSES_FOR_MODE_P hook_bool_mode_true -#define CLASS_LIKELY_SPILLED_P(c) class_likely_spilled_p(c) - #define CLASS_MAX_NREGS(CLASS, MODE) class_max_nregs (CLASS, MODE) #define STACK_PUSH_CODE POST_DEC diff --git a/gcc/config/bfin/bfin.c b/gcc/config/bfin/bfin.c index 8ff9e2fd0a7..da5a8eef237 100644 --- a/gcc/config/bfin/bfin.c +++ b/gcc/config/bfin/bfin.c @@ -2543,6 +2543,29 @@ bfin_secondary_reload (bool in_p, rtx x, reg_class_t rclass_i, return NO_REGS; } + +/* Implement TARGET_CLASS_LIKELY_SPILLED_P. */ + +static bool +bfin_class_likely_spilled_p (reg_class_t rclass) +{ + switch (rclass) + { + case PREGS_CLOBBERED: + case PROLOGUE_REGS: + case P0REGS: + case D0REGS: + case D1REGS: + case D2REGS: + case CCREGS: + return true; + + default: + break; + } + + return false; +} /* Implement TARGET_HANDLE_OPTION. */ @@ -6635,6 +6658,9 @@ bfin_expand_builtin (tree exp, rtx target ATTRIBUTE_UNUSED, #undef TARGET_SECONDARY_RELOAD #define TARGET_SECONDARY_RELOAD bfin_secondary_reload +#undef TARGET_CLASS_LIKELY_SPILLED_P +#define TARGET_CLASS_LIKELY_SPILLED_P bfin_class_likely_spilled_p + #undef TARGET_DELEGITIMIZE_ADDRESS #define TARGET_DELEGITIMIZE_ADDRESS bfin_delegitimize_address diff --git a/gcc/config/bfin/bfin.h b/gcc/config/bfin/bfin.h index 037e5be20f7..30b298d76e1 100644 --- a/gcc/config/bfin/bfin.h +++ b/gcc/config/bfin/bfin.h @@ -750,15 +750,6 @@ enum reg_class registers. */ #define TARGET_SMALL_REGISTER_CLASSES_FOR_MODE_P hook_bool_mode_true -#define CLASS_LIKELY_SPILLED_P(CLASS) \ - ((CLASS) == PREGS_CLOBBERED \ - || (CLASS) == PROLOGUE_REGS \ - || (CLASS) == P0REGS \ - || (CLASS) == D0REGS \ - || (CLASS) == D1REGS \ - || (CLASS) == D2REGS \ - || (CLASS) == CCREGS) - /* Do not allow to store a value in REG_CC for any mode */ /* Do not allow to store value in pregs if mode is not SI*/ #define HARD_REGNO_MODE_OK(REGNO, MODE) hard_regno_mode_ok((REGNO), (MODE)) diff --git a/gcc/config/darwin-driver.c b/gcc/config/darwin-driver.c index b23efc50c0a..1123aa37c43 100644 --- a/gcc/config/darwin-driver.c +++ b/gcc/config/darwin-driver.c @@ -24,6 +24,7 @@ along with GCC; see the file COPYING3. If not see #include "coretypes.h" #include "tm.h" #include "gcc.h" +#include "opts.h" #include <sys/sysctl.h> #include "xregex.h" @@ -32,11 +33,12 @@ along with GCC; see the file COPYING3. If not see of the system on which the compiler is running. */ void -darwin_default_min_version (int * argc_p, char *** argv_p) +darwin_default_min_version (unsigned int *decoded_options_count, + struct cl_decoded_option **decoded_options) { - const int argc = *argc_p; - char ** const argv = *argv_p; - int i; + const unsigned int argc = *decoded_options_count; + struct cl_decoded_option *const argv = *decoded_options; + unsigned int i; char osversion[32]; size_t osversion_len = sizeof (osversion) - 1; static int osversion_name[2] = { CTL_KERN, KERN_OSRELEASE }; @@ -44,34 +46,17 @@ darwin_default_min_version (int * argc_p, char *** argv_p) char * version_pend; int major_vers; char minor_vers[6]; - static char new_flag[sizeof ("-mmacosx-version-min=10.0.0") + 6]; + static char new_flag[sizeof ("10.0.0") + 6]; /* If the command-line is empty, just return. */ if (argc <= 1) return; - /* Don't do this if the user has specified -b or -V at the start - of the command-line. */ - if (argv[1][0] == '-' - && (argv[1][1] == 'V' || - ((argv[1][1] == 'b') && (NULL != strchr(argv[1] + 2,'-'))))) - return; /* Don't do this if the user specified -mmacosx-version-min= or -mno-macosx-version-min. */ for (i = 1; i < argc; i++) - if (argv[i][0] == '-') - { - const char * const p = argv[i]; - if (strncmp (p, "-mno-macosx-version-min", 23) == 0 - || strncmp (p, "-mmacosx-version-min", 20) == 0) - return; - - /* It doesn't count if it's an argument to a different switch. */ - if (p[0] == '-' - && ((SWITCH_TAKES_ARG (p[1]) > (p[2] != 0)) - || WORD_SWITCH_TAKES_ARG (p + 1))) - i++; - } + if (argv[i].opt_index == OPT_mmacosx_version_min_) + return; /* Retrieve the deployment target from the environment and insert it as a flag. */ @@ -84,12 +69,14 @@ darwin_default_min_version (int * argc_p, char *** argv_p) to ignore the environment variable, as if it was never set. */ && macosx_deployment_target[0]) { - ++*argc_p; - *argv_p = XNEWVEC (char *, *argc_p); - (*argv_p)[0] = argv[0]; - (*argv_p)[1] = concat ("-mmacosx-version-min=", - macosx_deployment_target, NULL); - memcpy (*argv_p + 2, argv + 1, (argc - 1) * sizeof (char *)); + ++*decoded_options_count; + *decoded_options = XNEWVEC (struct cl_decoded_option, + *decoded_options_count); + (*decoded_options)[0] = argv[0]; + generate_option (OPT_mmacosx_version_min_, macosx_deployment_target, + 1, CL_DRIVER, &(*decoded_options)[1]); + memcpy (*decoded_options + 2, argv + 1, + (argc - 1) * sizeof (struct cl_decoded_option)); return; } } @@ -128,17 +115,20 @@ darwin_default_min_version (int * argc_p, char *** argv_p) if (major_vers - 4 <= 4) /* On 10.4 and earlier, the old linker is used which does not support three-component system versions. */ - sprintf (new_flag, "-mmacosx-version-min=10.%d", major_vers - 4); + sprintf (new_flag, "10.%d", major_vers - 4); else - sprintf (new_flag, "-mmacosx-version-min=10.%d.%s", major_vers - 4, + sprintf (new_flag, "10.%d.%s", major_vers - 4, minor_vers); /* Add the new flag. */ - ++*argc_p; - *argv_p = XNEWVEC (char *, *argc_p); - (*argv_p)[0] = argv[0]; - (*argv_p)[1] = new_flag; - memcpy (*argv_p + 2, argv + 1, (argc - 1) * sizeof (char *)); + ++*decoded_options_count; + *decoded_options = XNEWVEC (struct cl_decoded_option, + *decoded_options_count); + (*decoded_options)[0] = argv[0]; + generate_option (OPT_mmacosx_version_min_, new_flag, + 1, CL_DRIVER, &(*decoded_options)[1]); + memcpy (*decoded_options + 2, argv + 1, + (argc - 1) * sizeof (struct cl_decoded_option)); return; parse_failed: diff --git a/gcc/config/darwin.h b/gcc/config/darwin.h index 3314acb1912..f0ff9010b93 100644 --- a/gcc/config/darwin.h +++ b/gcc/config/darwin.h @@ -1059,9 +1059,10 @@ extern int flag_apple_kext; #define TARGET_HAS_TARGETCM 1 #ifndef CROSS_DIRECTORY_STRUCTURE -extern void darwin_default_min_version (int * argc, char *** argv); +extern void darwin_default_min_version (unsigned int *decoded_options_count, + struct cl_decoded_option **decoded_options); #define GCC_DRIVER_HOST_INITIALIZATION \ - darwin_default_min_version (&argc, &argv) + darwin_default_min_version (&decoded_options_count, &decoded_options) #endif /* CROSS_DIRECTORY_STRUCTURE */ /* The Apple assembler and linker do not support constructor priorities. */ diff --git a/gcc/config/frv/frv.c b/gcc/config/frv/frv.c index 0730e32d9a4..42d0b1d9d0e 100644 --- a/gcc/config/frv/frv.c +++ b/gcc/config/frv/frv.c @@ -4067,7 +4067,7 @@ frv_emit_movsi (rtx dest, rtx src) || (GET_CODE (src) == REG && IN_RANGE_P (REGNO (src), FIRST_VIRTUAL_REGISTER, - LAST_VIRTUAL_REGISTER)))) + LAST_VIRTUAL_POINTER_REGISTER)))) { emit_insn (gen_rtx_SET (VOIDmode, dest, copy_to_mode_reg (SImode, src))); return TRUE; diff --git a/gcc/config/i386/cygwin.asm b/gcc/config/i386/cygwin.asm index 588c12ee701..a6cc94d160a 100644 --- a/gcc/config/i386/cygwin.asm +++ b/gcc/config/i386/cygwin.asm @@ -1,6 +1,7 @@ /* stuff needed for libgcc on win32. * - * Copyright (C) 1996, 1998, 2001, 2003, 2008, 2009 Free Software Foundation, Inc. + * Copyright (C) 1996, 1998, 2001, 2003, 2008, 2009 + * Free Software Foundation, Inc. * Written By Steve Chamberlain * * This file is free software; you can redistribute it and/or modify it @@ -23,104 +24,165 @@ * <http://www.gnu.org/licenses/>. */ -#ifdef L_chkstk +#include "auto-host.h" + +#ifdef HAVE_GAS_CFI_SECTIONS_DIRECTIVE + .cfi_sections .debug_frame +# define cfi_startproc() .cfi_startproc +# define cfi_endproc() .cfi_endproc +# define cfi_adjust_cfa_offset(X) .cfi_adjust_cfa_offset X +# define cfi_def_cfa_register(X) .cfi_def_cfa_register X +# define cfi_register(D,S) .cfi_register D, S +# ifdef _WIN64 +# define cfi_push(X) .cfi_adjust_cfa_offset 8; .cfi_rel_offset X, 0 +# define cfi_pop(X) .cfi_adjust_cfa_offset -8; .cfi_restore X +# else +# define cfi_push(X) .cfi_adjust_cfa_offset 4; .cfi_rel_offset X, 0 +# define cfi_pop(X) .cfi_adjust_cfa_offset -4; .cfi_restore X +# endif +#else +# define cfi_startproc() +# define cfi_endproc() +# define cfi_adjust_cfa_offset(X) +# define cfi_def_cfa_register(X) +# define cfi_register(D,S) +# define cfi_push(X) +# define cfi_pop(X) +#endif /* HAVE_GAS_CFI_SECTIONS_DIRECTIVE */ -/* Function prologue calls _alloca to probe the stack when allocating more +#ifdef L_chkstk +/* Function prologue calls __chkstk to probe the stack when allocating more than CHECK_STACK_LIMIT bytes in one go. Touching the stack at 4K increments is necessary to ensure that the guard pages used by the OS virtual memory manger are allocated in correct sequence. */ .global ___chkstk .global __alloca -#ifndef _WIN64 -___chkstk: +#ifdef _WIN64 +/* __alloca is a normal function call, which uses %rcx as the argument. */ + cfi_startproc() __alloca: - pushl %ecx /* save temp */ - leal 8(%esp), %ecx /* point past return addr */ - cmpl $0x1000, %eax /* > 4k ?*/ - jb Ldone + movq %rcx, %rax + /* FALLTHRU */ -Lprobe: - subl $0x1000, %ecx /* yes, move pointer down 4k*/ - orl $0x0, (%ecx) /* probe there */ - subl $0x1000, %eax /* decrement count */ - cmpl $0x1000, %eax - ja Lprobe /* and do it again */ +/* ___chkstk is a *special* function call, which uses %rax as the argument. + We avoid clobbering the 4 integer argument registers, %rcx, %rdx, + %r8 and %r9, which leaves us with %rax, %r10, and %r11 to use. */ + .align 4 +___chkstk: + popq %r11 /* pop return address */ + cfi_adjust_cfa_offset(-8) /* indicate return address in r11 */ + cfi_register(%rip, %r11) + movq %rsp, %r10 + cmpq $0x1000, %rax /* > 4k ?*/ + jb 2f -Ldone: - subl %eax, %ecx - orl $0x0, (%ecx) /* less than 4k, just peek here */ +1: subq $0x1000, %r10 /* yes, move pointer down 4k*/ + orl $0x0, (%r10) /* probe there */ + subq $0x1000, %rax /* decrement count */ + cmpq $0x1000, %rax + ja 1b /* and do it again */ - movl %esp, %eax /* save old stack pointer */ - movl %ecx, %esp /* decrement stack */ - movl (%eax), %ecx /* recover saved temp */ - movl 4(%eax), %eax /* recover return address */ +2: subq %rax, %r10 + movq %rsp, %rax /* hold CFA until return */ + cfi_def_cfa_register(%rax) + orl $0x0, (%r10) /* less than 4k, just peek here */ + movq %r10, %rsp /* decrement stack */ /* Push the return value back. Doing this instead of just - jumping to %eax preserves the cached call-return stack + jumping to %r11 preserves the cached call-return stack used by most modern processors. */ - pushl %eax + pushq %r11 ret + cfi_endproc() #else -/* __alloca is a normal function call, which uses %rcx as the argument. And stack space - for the argument is saved. */ + cfi_startproc() +___chkstk: __alloca: - movq %rcx, %rax - addq $0x7, %rax - andq $0xfffffffffffffff8, %rax - popq %rcx /* pop return address */ - popq %r10 /* Pop the reserved stack space. */ - movq %rsp, %r10 /* get sp */ - cmpq $0x1000, %rax /* > 4k ?*/ - jb Ldone_alloca - -Lprobe_alloca: - subq $0x1000, %r10 /* yes, move pointer down 4k*/ - orq $0x0, (%r10) /* probe there */ - subq $0x1000, %rax /* decrement count */ - cmpq $0x1000, %rax - ja Lprobe_alloca /* and do it again */ + pushl %ecx /* save temp */ + cfi_push(%eax) + leal 8(%esp), %ecx /* point past return addr */ + cmpl $0x1000, %eax /* > 4k ?*/ + jb 2f + +1: subl $0x1000, %ecx /* yes, move pointer down 4k*/ + orl $0x0, (%ecx) /* probe there */ + subl $0x1000, %eax /* decrement count */ + cmpl $0x1000, %eax + ja 1b /* and do it again */ -Ldone_alloca: - subq %rax, %r10 - orq $0x0, (%r10) /* less than 4k, just peek here */ - movq %r10, %rax - subq $0x8, %r10 /* Reserve argument stack space. */ - movq %r10, %rsp /* decrement stack */ +2: subl %eax, %ecx + orl $0x0, (%ecx) /* less than 4k, just peek here */ + movl %esp, %eax /* save current stack pointer */ + cfi_def_cfa_register(%eax) + movl %ecx, %esp /* decrement stack */ + movl (%eax), %ecx /* recover saved temp */ - /* Push the return value back. Doing this instead of just - jumping to %rcx preserves the cached call-return stack - used by most modern processors. */ - pushq %rcx + /* Copy the return register. Doing this instead of just jumping to + the address preserves the cached call-return stack used by most + modern processors. */ + pushl 4(%eax) ret + cfi_endproc() +#endif /* _WIN64 */ +#endif /* L_chkstk */ -/* ___chkstk is a *special* function call, which uses %rax as the argument. - We avoid clobbering the 4 integer argument registers, %rcx, %rdx, - %r8 and %r9, which leaves us with %rax, %r10, and %r11 to use. */ -___chkstk: - addq $0x7, %rax /* Make sure stack is on alignment of 8. */ - andq $0xfffffffffffffff8, %rax - popq %r11 /* pop return address */ - movq %rsp, %r10 /* get sp */ - cmpq $0x1000, %rax /* > 4k ?*/ - jb Ldone - -Lprobe: - subq $0x1000, %r10 /* yes, move pointer down 4k*/ - orl $0x0, (%r10) /* probe there */ +#ifdef L_chkstk_ms +/* ___chkstk_ms is a *special* function call, which uses %rax as the argument. + We avoid clobbering any registers. Unlike ___chkstk, it just probes the + stack and does no stack allocation. */ + .global ___chkstk_ms +#ifdef _WIN64 + cfi_startproc() +___chkstk_ms: + pushq %rcx /* save temps */ + cfi_push(%rcx) + pushq %rax + cfi_push(%rax) + cmpq $0x1000, %rax /* > 4k ?*/ + leaq 24(%rsp), %rcx /* point past return addr */ + jb 2f + +1: subq $0x1000, %rcx /* yes, move pointer down 4k */ + orq $0x0, (%rcx) /* probe there */ subq $0x1000, %rax /* decrement count */ cmpq $0x1000, %rax - ja Lprobe /* and do it again */ + ja 1b /* and do it again */ -Ldone: - subq %rax, %r10 - orl $0x0, (%r10) /* less than 4k, just peek here */ - movq %r10, %rsp /* decrement stack */ +2: subq %rax, %rcx + orq $0x0, (%rcx) /* less than 4k, just peek here */ - /* Push the return value back. Doing this instead of just - jumping to %r11 preserves the cached call-return stack - used by most modern processors. */ - pushq %r11 + popq %rax + cfi_pop(%rax) + popq %rcx + cfi_pop(%rcx) + ret + cfi_endproc() +#else + cfi_startproc() +___chkstk_ms: + pushl %ecx /* save temp */ + cfi_push(%ecx) + pushl %eax + cfi_push(%eax) + cmpl $0x1000, %eax /* > 4k ?*/ + leal 12(%esp), %ecx /* point past return addr */ + jb 2f + +1: subl $0x1000, %ecx /* yes, move pointer down 4k*/ + orl $0x0, (%ecx) /* probe there */ + subl $0x1000, %eax /* decrement count */ + cmpl $0x1000, %eax + ja 1b /* and do it again */ + +2: subl %eax, %ecx + orl $0x0, (%ecx) /* less than 4k, just peek here */ + + popl %eax + cfi_pop(%eax) + popl %ecx + cfi_pop(%ecx) ret -#endif -#endif + cfi_endproc() +#endif /* _WIN64 */ +#endif /* L_chkstk_ms */ diff --git a/gcc/config/i386/cygwin.h b/gcc/config/i386/cygwin.h index a8d26e9558d..67308fc7dff 100644 --- a/gcc/config/i386/cygwin.h +++ b/gcc/config/i386/cygwin.h @@ -252,12 +252,13 @@ char *cvt_to_mingw[] = #undef GEN_CVT_ARRAY #endif /*GEN_CVT_ARRAY*/ -void mingw_scan (int, const char * const *, const char **); +void mingw_scan (unsigned int, const struct cl_decoded_option *, + const char **); #if 1 #define GCC_DRIVER_HOST_INITIALIZATION \ do \ { \ - mingw_scan(argc, (const char * const *) argv, &spec_machine); \ + mingw_scan (decoded_options_count, decoded_options, &spec_machine); \ } \ while (0) #else @@ -277,7 +278,7 @@ do \ add_prefix (&startfile_prefixes,\ concat (standard_startfile_prefix, "w32api", NULL),\ "GCC", PREFIX_PRIORITY_LAST, 0, NULL);\ - mingw_scan(argc, (const char * const *) argv, &spec_machine); \ + mingw_scan (decoded_options_count, decoded_options, &spec_machine); \ } \ while (0) #endif diff --git a/gcc/config/i386/cygwin1.c b/gcc/config/i386/cygwin1.c index 7de34d24b7a..99d9d8f8243 100644 --- a/gcc/config/i386/cygwin1.c +++ b/gcc/config/i386/cygwin1.c @@ -22,32 +22,42 @@ along with GCC; see the file COPYING3. If not see #include "system.h" #include "coretypes.h" #include "tm.h" +#include "opts.h" #include <string.h> void -mingw_scan (int argc ATTRIBUTE_UNUSED, - const char *const *argv, +mingw_scan (unsigned int decoded_options_count, + const struct cl_decoded_option *decoded_options, const char **spec_machine) { + unsigned int i; putenv (xstrdup ("GCC_CYGWIN_MINGW=0")); - while (*++argv) - if (strcmp (*argv, "-mno-win32") == 0) - putenv (xstrdup ("GCC_CYGWIN_WIN32=0")); - else if (strcmp (*argv, "-mwin32") == 0) - putenv (xstrdup ("GCC_CYGWIN_WIN32=1")); - else if (strcmp (*argv, "-mno-cygwin") == 0) + for (i = 1; i < decoded_options_count; i++) + switch (decoded_options[i].opt_index) { - char *p = strstr (*spec_machine, "-cygwin"); - if (p) + case OPT_mwin32: + if (decoded_options[i].value == 0) + putenv (xstrdup ("GCC_CYGWIN_WIN32=0")); + else + putenv (xstrdup ("GCC_CYGWIN_WIN32=1")); + break; + + case OPT_mcygwin: + if (decoded_options[i].value == 0) { - int len = p - *spec_machine; - char *s = XNEWVEC (char, strlen (*spec_machine) + 3); - memcpy (s, *spec_machine, len); - strcpy (s + len, "-mingw32"); - *spec_machine = s; + char *p = strstr (*spec_machine, "-cygwin"); + if (p) + { + int len = p - *spec_machine; + char *s = XNEWVEC (char, strlen (*spec_machine) + 3); + memcpy (s, *spec_machine, len); + strcpy (s + len, "-mingw32"); + *spec_machine = s; + } + putenv (xstrdup ("GCC_CYGWIN_MINGW=1")); } - putenv (xstrdup ("GCC_CYGWIN_MINGW=1")); + break; } return; } diff --git a/gcc/config/i386/freebsd.h b/gcc/config/i386/freebsd.h index 94b657ec295..1ec5ee0d27d 100644 --- a/gcc/config/i386/freebsd.h +++ b/gcc/config/i386/freebsd.h @@ -147,3 +147,8 @@ along with GCC; see the file COPYING3. If not see /* Static stack checking is supported by means of probes. */ #define STACK_CHECK_STATIC_BUILTIN 1 + +/* Support for i386 has been removed from FreeBSD 6.0 onward. */ +#if FBSD_MAJOR >= 6 +#define SUBTARGET32_DEFAULT_CPU "i486" +#endif diff --git a/gcc/config/i386/i386-protos.h b/gcc/config/i386/i386-protos.h index 909adb9c2b1..fd31e9917f5 100644 --- a/gcc/config/i386/i386-protos.h +++ b/gcc/config/i386/i386-protos.h @@ -64,8 +64,7 @@ extern bool legitimate_pic_address_disp_p (rtx); extern void print_reg (rtx, int, FILE*); extern void ix86_print_operand (FILE *, rtx, int); -extern void split_di (rtx[], int, rtx[], rtx[]); -extern void split_ti (rtx[], int, rtx[], rtx[]); +extern void split_double_mode (enum machine_mode, rtx[], int, rtx[], rtx[]); extern const char *output_set_got (rtx, rtx); extern const char *output_387_binary_op (rtx, rtx*); diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c index dcf887502bc..627d8d20ea0 100644 --- a/gcc/config/i386/i386.c +++ b/gcc/config/i386/i386.c @@ -1576,6 +1576,9 @@ static unsigned int initial_ix86_tune_features[X86_TUNE_LAST] = { /* X86_TUNE_PAD_RETURNS */ m_AMD_MULTIPLE | m_CORE2 | m_GENERIC, + /* X86_TUNE_PAD_SHORT_FUNCTION: Pad short funtion. */ + m_ATOM, + /* X86_TUNE_EXT_80387_CONSTANTS */ m_K6_GEODE | m_ATHLON_K8 | m_ATOM | m_PENT4 | m_NOCONA | m_PPRO | m_CORE2 | m_GENERIC, @@ -2025,9 +2028,6 @@ static enum calling_abi ix86_function_abi (const_tree); static int ix86_tune_defaulted; static int ix86_arch_specified; -/* Bit flags that specify the ISA we are compiling for. */ -int ix86_isa_flags = TARGET_64BIT_DEFAULT | TARGET_SUBTARGET_ISA_DEFAULT; - /* A mask of ix86_isa_flags that includes bit X if X was set or cleared on the command line. */ static int ix86_isa_flags_explicit; @@ -3661,7 +3661,7 @@ ix86_option_override_internal (bool main_args_p) ix86_gen_one_cmpl2 = gen_one_cmpldi2; ix86_gen_monitor = gen_sse3_monitor64; ix86_gen_andsp = gen_anddi3; - ix86_gen_allocate_stack_worker = gen_allocate_stack_worker_64; + ix86_gen_allocate_stack_worker = gen_allocate_stack_worker_probe_di; ix86_gen_adjust_stack_and_probe = gen_adjust_stack_and_probedi; ix86_gen_probe_stack_range = gen_probe_stack_rangedi; } @@ -3674,7 +3674,7 @@ ix86_option_override_internal (bool main_args_p) ix86_gen_one_cmpl2 = gen_one_cmplsi2; ix86_gen_monitor = gen_sse3_monitor; ix86_gen_andsp = gen_andsi3; - ix86_gen_allocate_stack_worker = gen_allocate_stack_worker_32; + ix86_gen_allocate_stack_worker = gen_allocate_stack_worker_probe_si; ix86_gen_adjust_stack_and_probe = gen_adjust_stack_and_probesi; ix86_gen_probe_stack_range = gen_probe_stack_rangesi; } @@ -7964,12 +7964,12 @@ ix86_code_end (void) rtx xops[2]; int regno; - for (regno = 0; regno < 8; ++regno) + for (regno = AX_REG; regno <= SP_REG; regno++) { char name[32]; tree decl; - if (! ((pic_labels_used >> regno) & 1)) + if (!(pic_labels_used & (1 << regno))) continue; get_pc_thunk_name (name, regno); @@ -8022,10 +8022,20 @@ ix86_code_end (void) /* Make sure unwind info is emitted for the thunk if needed. */ final_start_function (emit_barrier (), asm_out_file, 1); + /* Pad stack IP move with 4 instructions (two NOPs count + as one instruction). */ + if (TARGET_PAD_SHORT_FUNCTION) + { + int i = 8; + + while (i--) + fputs ("\tnop\n", asm_out_file); + } + xops[0] = gen_rtx_REG (Pmode, regno); xops[1] = gen_rtx_MEM (Pmode, stack_pointer_rtx); output_asm_insn ("mov%z0\t{%1, %0|%0, %1}", xops); - output_asm_insn ("ret", xops); + fputs ("\tret\n", asm_out_file); final_end_function (); init_insn_lengths (); free_after_compilation (cfun); @@ -8767,9 +8777,9 @@ pro_epilogue_adjust_stack (rtx dest, rtx src, rtx offset, rtx insn; if (! TARGET_64BIT) - insn = emit_insn (gen_pro_epilogue_adjust_stack_si_1 (dest, src, offset)); + insn = gen_pro_epilogue_adjust_stack_si_add (dest, src, offset); else if (x86_64_immediate_operand (offset, DImode)) - insn = emit_insn (gen_pro_epilogue_adjust_stack_di_1 (dest, src, offset)); + insn = gen_pro_epilogue_adjust_stack_di_add (dest, src, offset); else { rtx tmp; @@ -8786,10 +8796,11 @@ pro_epilogue_adjust_stack (rtx dest, rtx src, rtx offset, insn = emit_insn (gen_rtx_SET (DImode, tmp, offset)); if (style < 0) RTX_FRAME_RELATED_P (insn) = 1; - insn = emit_insn (gen_pro_epilogue_adjust_stack_di_2 (dest, src, tmp, - offset)); + + insn = gen_pro_epilogue_adjust_stack_di_add (dest, src, tmp); } + insn = emit_insn (insn); if (style >= 0) ix86_add_queued_cfa_restore_notes (insn); @@ -9688,38 +9699,64 @@ ix86_expand_prologue (void) else { rtx eax = gen_rtx_REG (Pmode, AX_REG); - bool eax_live; + rtx r10 = NULL; + rtx (*adjust_stack_insn)(rtx, rtx, rtx); - if (cfun->machine->call_abi == MS_ABI) - eax_live = false; - else - eax_live = ix86_eax_live_at_start_p (); + bool eax_live = false; + bool r10_live = false; + + if (TARGET_64BIT) + r10_live = (DECL_STATIC_CHAIN (current_function_decl) != 0); + if (!TARGET_64BIT_MS_ABI) + eax_live = ix86_eax_live_at_start_p (); if (eax_live) { emit_insn (gen_push (eax)); allocate -= UNITS_PER_WORD; } + if (r10_live) + { + r10 = gen_rtx_REG (Pmode, R10_REG); + emit_insn (gen_push (r10)); + allocate -= UNITS_PER_WORD; + } emit_move_insn (eax, GEN_INT (allocate)); + emit_insn (ix86_gen_allocate_stack_worker (eax, eax)); - insn = emit_insn (ix86_gen_allocate_stack_worker (eax, eax)); + /* Use the fact that AX still contains ALLOCATE. */ + adjust_stack_insn = (TARGET_64BIT + ? gen_pro_epilogue_adjust_stack_di_sub + : gen_pro_epilogue_adjust_stack_si_sub); + + insn = emit_insn (adjust_stack_insn (stack_pointer_rtx, + stack_pointer_rtx, eax)); if (m->fs.cfa_reg == stack_pointer_rtx) { m->fs.cfa_offset += allocate; - t = gen_rtx_PLUS (Pmode, stack_pointer_rtx, GEN_INT (-allocate)); - t = gen_rtx_SET (VOIDmode, stack_pointer_rtx, t); - add_reg_note (insn, REG_CFA_ADJUST_CFA, t); + RTX_FRAME_RELATED_P (insn) = 1; + add_reg_note (insn, REG_CFA_ADJUST_CFA, + gen_rtx_SET (VOIDmode, stack_pointer_rtx, + plus_constant (stack_pointer_rtx, + -allocate))); } m->fs.sp_offset += allocate; - if (eax_live) - { + if (r10_live && eax_live) + { t = choose_baseaddr (m->fs.sp_offset - allocate); + emit_move_insn (r10, gen_frame_mem (Pmode, t)); + t = choose_baseaddr (m->fs.sp_offset - allocate - UNITS_PER_WORD); emit_move_insn (eax, gen_frame_mem (Pmode, t)); } + else if (eax_live || r10_live) + { + t = choose_baseaddr (m->fs.sp_offset - allocate); + emit_move_insn ((eax_live ? eax : r10), gen_frame_mem (Pmode, t)); + } } gcc_assert (m->fs.sp_offset == frame.stack_pointer_offset); @@ -13243,15 +13280,33 @@ i386_asm_output_addr_const_extra (FILE *file, rtx x) return true; } -/* Split one or more DImode RTL references into pairs of SImode +/* Split one or more double-mode RTL references into pairs of half-mode references. The RTL can be REG, offsettable MEM, integer constant, or - CONST_DOUBLE. "operands" is a pointer to an array of DImode RTL to + CONST_DOUBLE. "operands" is a pointer to an array of double-mode RTLs to split and "num" is its length. lo_half and hi_half are output arrays that parallel "operands". */ void -split_di (rtx operands[], int num, rtx lo_half[], rtx hi_half[]) +split_double_mode (enum machine_mode mode, rtx operands[], + int num, rtx lo_half[], rtx hi_half[]) { + enum machine_mode half_mode; + unsigned int byte; + + switch (mode) + { + case TImode: + half_mode = DImode; + break; + case DImode: + half_mode = SImode; + break; + default: + gcc_unreachable (); + } + + byte = GET_MODE_SIZE (half_mode); + while (num--) { rtx op = operands[num]; @@ -13260,44 +13315,17 @@ split_di (rtx operands[], int num, rtx lo_half[], rtx hi_half[]) but we still have to handle it. */ if (MEM_P (op)) { - lo_half[num] = adjust_address (op, SImode, 0); - hi_half[num] = adjust_address (op, SImode, 4); + lo_half[num] = adjust_address (op, half_mode, 0); + hi_half[num] = adjust_address (op, half_mode, byte); } else { - lo_half[num] = simplify_gen_subreg (SImode, op, + lo_half[num] = simplify_gen_subreg (half_mode, op, GET_MODE (op) == VOIDmode - ? DImode : GET_MODE (op), 0); - hi_half[num] = simplify_gen_subreg (SImode, op, + ? mode : GET_MODE (op), 0); + hi_half[num] = simplify_gen_subreg (half_mode, op, GET_MODE (op) == VOIDmode - ? DImode : GET_MODE (op), 4); - } - } -} -/* Split one or more TImode RTL references into pairs of DImode - references. The RTL can be REG, offsettable MEM, integer constant, or - CONST_DOUBLE. "operands" is a pointer to an array of DImode RTL to - split and "num" is its length. lo_half and hi_half are output arrays - that parallel "operands". */ - -void -split_ti (rtx operands[], int num, rtx lo_half[], rtx hi_half[]) -{ - while (num--) - { - rtx op = operands[num]; - - /* simplify_subreg refuse to split volatile memory addresses, but we - still have to handle it. */ - if (MEM_P (op)) - { - lo_half[num] = adjust_address (op, DImode, 0); - hi_half[num] = adjust_address (op, DImode, 8); - } - else - { - lo_half[num] = simplify_gen_subreg (DImode, op, TImode, 0); - hi_half[num] = simplify_gen_subreg (DImode, op, TImode, 8); + ? mode : GET_MODE (op), byte); } } } @@ -16268,9 +16296,10 @@ ix86_expand_compare (enum rtx_code code, rtx op0, rtx op1) void ix86_expand_branch (enum rtx_code code, rtx op0, rtx op1, rtx label) { + enum machine_mode mode = GET_MODE (op0); rtx tmp; - switch (GET_MODE (op0)) + switch (mode) { case SFmode: case DFmode: @@ -16301,18 +16330,11 @@ ix86_expand_branch (enum rtx_code code, rtx op0, rtx op1, rtx label) tmp = op0, op0 = op1, op1 = tmp; code = swap_condition (code); } - if (GET_MODE (op0) == DImode) - { - split_di (&op0, 1, lo+0, hi+0); - split_di (&op1, 1, lo+1, hi+1); - submode = SImode; - } - else - { - split_ti (&op0, 1, lo+0, hi+0); - split_ti (&op1, 1, lo+1, hi+1); - submode = DImode; - } + + split_double_mode (mode, &op0, 1, lo+0, hi+0); + split_double_mode (mode, &op1, 1, lo+1, hi+1); + + submode = mode == DImode ? SImode : DImode; /* When comparing for equality, we can use (hi0^hi1)|(lo0^lo1) to avoid two branches. This costs one extra insn, so disable when @@ -16469,7 +16491,7 @@ ix86_expand_carry_flag_compare (enum rtx_code code, rtx op0, rtx op1, rtx *pop) enum machine_mode mode = GET_MODE (op0) != VOIDmode ? GET_MODE (op0) : GET_MODE (op1); - /* Do not handle DImode compares that go through special path. */ + /* Do not handle double-mode compares that go through special path. */ if (mode == (TARGET_64BIT ? TImode : DImode)) return false; @@ -17681,8 +17703,8 @@ ix86_expand_int_addcc (rtx operands[]) } -/* Split operands 0 and 1 into SImode parts. Similar to split_di, but - works for floating pointer parameters and nonoffsetable memories. +/* Split operands 0 and 1 into half-mode parts. Similar to split_double_mode, + but works for floating pointer parameters and nonoffsetable memories. For pushes, it returns just stack offsets; the values will be saved in the right order. Maximally three parts are generated. */ @@ -17735,7 +17757,7 @@ ix86_split_to_parts (rtx operand, rtx *parts, enum machine_mode mode) if (!TARGET_64BIT) { if (mode == DImode) - split_di (&operand, 1, &parts[0], &parts[1]); + split_double_mode (mode, &operand, 1, &parts[0], &parts[1]); else { int i; @@ -17786,7 +17808,7 @@ ix86_split_to_parts (rtx operand, rtx *parts, enum machine_mode mode) else { if (mode == TImode) - split_ti (&operand, 1, &parts[0], &parts[1]); + split_double_mode (mode, &operand, 1, &parts[0], &parts[1]); if (mode == XFmode || mode == TFmode) { enum machine_mode upper_mode = mode==XFmode ? SImode : DImode; @@ -17857,7 +17879,7 @@ ix86_split_long_move (rtx operands[]) /* The DFmode expanders may ask us to move double. For 64bit target this is single move. By hiding the fact here we simplify i386.md splitters. */ - if (GET_MODE_SIZE (GET_MODE (operands[0])) == 8 && TARGET_64BIT) + if (TARGET_64BIT && GET_MODE_SIZE (GET_MODE (operands[0])) == 8) { /* Optimize constant pool reference to immediates. This is used by fp moves, that force all constants to memory to allow combining. */ @@ -18067,62 +18089,62 @@ ix86_split_long_move (rtx operands[]) static void ix86_expand_ashl_const (rtx operand, int count, enum machine_mode mode) { - if (count == 1) + rtx (*insn)(rtx, rtx, rtx); + + if (count == 1 + || (count * ix86_cost->add <= ix86_cost->shift_const + && !optimize_insn_for_size_p ())) { - emit_insn ((mode == DImode - ? gen_addsi3 - : gen_adddi3) (operand, operand, operand)); + insn = mode == DImode ? gen_addsi3 : gen_adddi3; + while (count-- > 0) + emit_insn (insn (operand, operand, operand)); } - else if (!optimize_insn_for_size_p () - && count * ix86_cost->add <= ix86_cost->shift_const) + else { - int i; - for (i=0; i<count; i++) - { - emit_insn ((mode == DImode - ? gen_addsi3 - : gen_adddi3) (operand, operand, operand)); - } + insn = mode == DImode ? gen_ashlsi3 : gen_ashldi3; + emit_insn (insn (operand, operand, GEN_INT (count))); } - else - emit_insn ((mode == DImode - ? gen_ashlsi3 - : gen_ashldi3) (operand, operand, GEN_INT (count))); } void ix86_split_ashl (rtx *operands, rtx scratch, enum machine_mode mode) { + rtx (*gen_ashl3)(rtx, rtx, rtx); + rtx (*gen_shld)(rtx, rtx, rtx); + int half_width = GET_MODE_BITSIZE (mode) >> 1; + rtx low[2], high[2]; int count; - const int single_width = mode == DImode ? 32 : 64; if (CONST_INT_P (operands[2])) { - (mode == DImode ? split_di : split_ti) (operands, 2, low, high); - count = INTVAL (operands[2]) & (single_width * 2 - 1); + split_double_mode (mode, operands, 2, low, high); + count = INTVAL (operands[2]) & (GET_MODE_BITSIZE (mode) - 1); - if (count >= single_width) + if (count >= half_width) { emit_move_insn (high[0], low[1]); emit_move_insn (low[0], const0_rtx); - if (count > single_width) - ix86_expand_ashl_const (high[0], count - single_width, mode); + if (count > half_width) + ix86_expand_ashl_const (high[0], count - half_width, mode); } else { + gen_shld = mode == DImode ? gen_x86_shld : gen_x86_64_shld; + if (!rtx_equal_p (operands[0], operands[1])) emit_move_insn (operands[0], operands[1]); - emit_insn ((mode == DImode - ? gen_x86_shld - : gen_x86_64_shld) (high[0], low[0], GEN_INT (count))); + + emit_insn (gen_shld (high[0], low[0], GEN_INT (count))); ix86_expand_ashl_const (low[0], count, mode); } return; } - (mode == DImode ? split_di : split_ti) (operands, 1, low, high); + split_double_mode (mode, operands, 1, low, high); + + gen_ashl3 = mode == DImode ? gen_ashlsi3 : gen_ashldi3; if (operands[1] == const1_rtx) { @@ -18134,7 +18156,7 @@ ix86_split_ashl (rtx *operands, rtx scratch, enum machine_mode mode) ix86_expand_clear (low[0]); ix86_expand_clear (high[0]); - emit_insn (gen_testqi_ccz_1 (operands[2], GEN_INT (single_width))); + emit_insn (gen_testqi_ccz_1 (operands[2], GEN_INT (half_width))); d = gen_lowpart (QImode, low[0]); d = gen_rtx_STRICT_LOW_PART (VOIDmode, d); @@ -18154,33 +18176,44 @@ ix86_split_ashl (rtx *operands, rtx scratch, enum machine_mode mode) pentium4 a bit; no one else seems to care much either way. */ else { + enum machine_mode half_mode; + rtx (*gen_lshr3)(rtx, rtx, rtx); + rtx (*gen_and3)(rtx, rtx, rtx); + rtx (*gen_xor3)(rtx, rtx, rtx); + HOST_WIDE_INT bits; rtx x; + if (mode == DImode) + { + half_mode = SImode; + gen_lshr3 = gen_lshrsi3; + gen_and3 = gen_andsi3; + gen_xor3 = gen_xorsi3; + bits = 5; + } + else + { + half_mode = DImode; + gen_lshr3 = gen_lshrdi3; + gen_and3 = gen_anddi3; + gen_xor3 = gen_xordi3; + bits = 6; + } + if (TARGET_PARTIAL_REG_STALL && !optimize_insn_for_size_p ()) - x = gen_rtx_ZERO_EXTEND (mode == DImode ? SImode : DImode, operands[2]); + x = gen_rtx_ZERO_EXTEND (half_mode, operands[2]); else - x = gen_lowpart (mode == DImode ? SImode : DImode, operands[2]); + x = gen_lowpart (half_mode, operands[2]); emit_insn (gen_rtx_SET (VOIDmode, high[0], x)); - emit_insn ((mode == DImode - ? gen_lshrsi3 - : gen_lshrdi3) (high[0], high[0], - GEN_INT (mode == DImode ? 5 : 6))); - emit_insn ((mode == DImode - ? gen_andsi3 - : gen_anddi3) (high[0], high[0], const1_rtx)); + emit_insn (gen_lshr3 (high[0], high[0], GEN_INT (bits))); + emit_insn (gen_and3 (high[0], high[0], const1_rtx)); emit_move_insn (low[0], high[0]); - emit_insn ((mode == DImode - ? gen_xorsi3 - : gen_xordi3) (low[0], low[0], const1_rtx)); + emit_insn (gen_xor3 (low[0], low[0], const1_rtx)); } - emit_insn ((mode == DImode - ? gen_ashlsi3 - : gen_ashldi3) (low[0], low[0], operands[2])); - emit_insn ((mode == DImode - ? gen_ashlsi3 - : gen_ashldi3) (high[0], high[0], operands[2])); + emit_insn (gen_ashl3 (low[0], low[0], operands[2])); + emit_insn (gen_ashl3 (high[0], high[0], operands[2])); return; } @@ -18196,176 +18229,177 @@ ix86_split_ashl (rtx *operands, rtx scratch, enum machine_mode mode) } else { + gen_shld = mode == DImode ? gen_x86_shld : gen_x86_64_shld; + if (!rtx_equal_p (operands[0], operands[1])) emit_move_insn (operands[0], operands[1]); - (mode == DImode ? split_di : split_ti) (operands, 1, low, high); - emit_insn ((mode == DImode - ? gen_x86_shld - : gen_x86_64_shld) (high[0], low[0], operands[2])); + split_double_mode (mode, operands, 1, low, high); + emit_insn (gen_shld (high[0], low[0], operands[2])); } - emit_insn ((mode == DImode - ? gen_ashlsi3 - : gen_ashldi3) (low[0], low[0], operands[2])); + emit_insn (gen_ashl3 (low[0], low[0], operands[2])); if (TARGET_CMOVE && scratch) { + rtx (*gen_x86_shift_adj_1)(rtx, rtx, rtx, rtx) + = mode == DImode ? gen_x86_shiftsi_adj_1 : gen_x86_shiftdi_adj_1; + ix86_expand_clear (scratch); - emit_insn ((mode == DImode - ? gen_x86_shiftsi_adj_1 - : gen_x86_shiftdi_adj_1) (high[0], low[0], operands[2], - scratch)); + emit_insn (gen_x86_shift_adj_1 (high[0], low[0], operands[2], scratch)); } else - emit_insn ((mode == DImode - ? gen_x86_shiftsi_adj_2 - : gen_x86_shiftdi_adj_2) (high[0], low[0], operands[2])); + { + rtx (*gen_x86_shift_adj_2)(rtx, rtx, rtx) + = mode == DImode ? gen_x86_shiftsi_adj_2 : gen_x86_shiftdi_adj_2; + + emit_insn (gen_x86_shift_adj_2 (high[0], low[0], operands[2])); + } } void ix86_split_ashr (rtx *operands, rtx scratch, enum machine_mode mode) { + rtx (*gen_ashr3)(rtx, rtx, rtx) + = mode == DImode ? gen_ashrsi3 : gen_ashrdi3; + rtx (*gen_shrd)(rtx, rtx, rtx); + int half_width = GET_MODE_BITSIZE (mode) >> 1; + rtx low[2], high[2]; int count; - const int single_width = mode == DImode ? 32 : 64; if (CONST_INT_P (operands[2])) { - (mode == DImode ? split_di : split_ti) (operands, 2, low, high); - count = INTVAL (operands[2]) & (single_width * 2 - 1); + split_double_mode (mode, operands, 2, low, high); + count = INTVAL (operands[2]) & (GET_MODE_BITSIZE (mode) - 1); - if (count == single_width * 2 - 1) + if (count == GET_MODE_BITSIZE (mode) - 1) { emit_move_insn (high[0], high[1]); - emit_insn ((mode == DImode - ? gen_ashrsi3 - : gen_ashrdi3) (high[0], high[0], - GEN_INT (single_width - 1))); + emit_insn (gen_ashr3 (high[0], high[0], + GEN_INT (half_width - 1))); emit_move_insn (low[0], high[0]); } - else if (count >= single_width) + else if (count >= half_width) { emit_move_insn (low[0], high[1]); emit_move_insn (high[0], low[0]); - emit_insn ((mode == DImode - ? gen_ashrsi3 - : gen_ashrdi3) (high[0], high[0], - GEN_INT (single_width - 1))); - if (count > single_width) - emit_insn ((mode == DImode - ? gen_ashrsi3 - : gen_ashrdi3) (low[0], low[0], - GEN_INT (count - single_width))); + emit_insn (gen_ashr3 (high[0], high[0], + GEN_INT (half_width - 1))); + + if (count > half_width) + emit_insn (gen_ashr3 (low[0], low[0], + GEN_INT (count - half_width))); } else { + gen_shrd = mode == DImode ? gen_x86_shrd : gen_x86_64_shrd; + if (!rtx_equal_p (operands[0], operands[1])) emit_move_insn (operands[0], operands[1]); - emit_insn ((mode == DImode - ? gen_x86_shrd - : gen_x86_64_shrd) (low[0], high[0], GEN_INT (count))); - emit_insn ((mode == DImode - ? gen_ashrsi3 - : gen_ashrdi3) (high[0], high[0], GEN_INT (count))); + + emit_insn (gen_shrd (low[0], high[0], GEN_INT (count))); + emit_insn (gen_ashr3 (high[0], high[0], GEN_INT (count))); } } else { - if (!rtx_equal_p (operands[0], operands[1])) + gen_shrd = mode == DImode ? gen_x86_shrd : gen_x86_64_shrd; + + if (!rtx_equal_p (operands[0], operands[1])) emit_move_insn (operands[0], operands[1]); - (mode == DImode ? split_di : split_ti) (operands, 1, low, high); + split_double_mode (mode, operands, 1, low, high); - emit_insn ((mode == DImode - ? gen_x86_shrd - : gen_x86_64_shrd) (low[0], high[0], operands[2])); - emit_insn ((mode == DImode - ? gen_ashrsi3 - : gen_ashrdi3) (high[0], high[0], operands[2])); + emit_insn (gen_shrd (low[0], high[0], operands[2])); + emit_insn (gen_ashr3 (high[0], high[0], operands[2])); if (TARGET_CMOVE && scratch) { + rtx (*gen_x86_shift_adj_1)(rtx, rtx, rtx, rtx) + = mode == DImode ? gen_x86_shiftsi_adj_1 : gen_x86_shiftdi_adj_1; + emit_move_insn (scratch, high[0]); - emit_insn ((mode == DImode - ? gen_ashrsi3 - : gen_ashrdi3) (scratch, scratch, - GEN_INT (single_width - 1))); - emit_insn ((mode == DImode - ? gen_x86_shiftsi_adj_1 - : gen_x86_shiftdi_adj_1) (low[0], high[0], operands[2], - scratch)); + emit_insn (gen_ashr3 (scratch, scratch, + GEN_INT (half_width - 1))); + emit_insn (gen_x86_shift_adj_1 (low[0], high[0], operands[2], + scratch)); } else - emit_insn ((mode == DImode - ? gen_x86_shiftsi_adj_3 - : gen_x86_shiftdi_adj_3) (low[0], high[0], operands[2])); + { + rtx (*gen_x86_shift_adj_3)(rtx, rtx, rtx) + = mode == DImode ? gen_x86_shiftsi_adj_3 : gen_x86_shiftdi_adj_3; + + emit_insn (gen_x86_shift_adj_3 (low[0], high[0], operands[2])); + } } } void ix86_split_lshr (rtx *operands, rtx scratch, enum machine_mode mode) { + rtx (*gen_lshr3)(rtx, rtx, rtx) + = mode == DImode ? gen_lshrsi3 : gen_lshrdi3; + rtx (*gen_shrd)(rtx, rtx, rtx); + int half_width = GET_MODE_BITSIZE (mode) >> 1; + rtx low[2], high[2]; int count; - const int single_width = mode == DImode ? 32 : 64; if (CONST_INT_P (operands[2])) { - (mode == DImode ? split_di : split_ti) (operands, 2, low, high); - count = INTVAL (operands[2]) & (single_width * 2 - 1); + split_double_mode (mode, operands, 2, low, high); + count = INTVAL (operands[2]) & (GET_MODE_BITSIZE (mode) - 1); - if (count >= single_width) + if (count >= half_width) { emit_move_insn (low[0], high[1]); ix86_expand_clear (high[0]); - if (count > single_width) - emit_insn ((mode == DImode - ? gen_lshrsi3 - : gen_lshrdi3) (low[0], low[0], - GEN_INT (count - single_width))); + if (count > half_width) + emit_insn (gen_lshr3 (low[0], low[0], + GEN_INT (count - half_width))); } else { + gen_shrd = mode == DImode ? gen_x86_shrd : gen_x86_64_shrd; + if (!rtx_equal_p (operands[0], operands[1])) emit_move_insn (operands[0], operands[1]); - emit_insn ((mode == DImode - ? gen_x86_shrd - : gen_x86_64_shrd) (low[0], high[0], GEN_INT (count))); - emit_insn ((mode == DImode - ? gen_lshrsi3 - : gen_lshrdi3) (high[0], high[0], GEN_INT (count))); + + emit_insn (gen_shrd (low[0], high[0], GEN_INT (count))); + emit_insn (gen_lshr3 (high[0], high[0], GEN_INT (count))); } } else { + gen_shrd = mode == DImode ? gen_x86_shrd : gen_x86_64_shrd; + if (!rtx_equal_p (operands[0], operands[1])) emit_move_insn (operands[0], operands[1]); - (mode == DImode ? split_di : split_ti) (operands, 1, low, high); + split_double_mode (mode, operands, 1, low, high); - emit_insn ((mode == DImode - ? gen_x86_shrd - : gen_x86_64_shrd) (low[0], high[0], operands[2])); - emit_insn ((mode == DImode - ? gen_lshrsi3 - : gen_lshrdi3) (high[0], high[0], operands[2])); + emit_insn (gen_shrd (low[0], high[0], operands[2])); + emit_insn (gen_lshr3 (high[0], high[0], operands[2])); - /* Heh. By reversing the arguments, we can reuse this pattern. */ if (TARGET_CMOVE && scratch) { + rtx (*gen_x86_shift_adj_1)(rtx, rtx, rtx, rtx) + = mode == DImode ? gen_x86_shiftsi_adj_1 : gen_x86_shiftdi_adj_1; + ix86_expand_clear (scratch); - emit_insn ((mode == DImode - ? gen_x86_shiftsi_adj_1 - : gen_x86_shiftdi_adj_1) (low[0], high[0], operands[2], - scratch)); + emit_insn (gen_x86_shift_adj_1 (low[0], high[0], operands[2], + scratch)); } else - emit_insn ((mode == DImode - ? gen_x86_shiftsi_adj_2 - : gen_x86_shiftdi_adj_2) (low[0], high[0], operands[2])); + { + rtx (*gen_x86_shift_adj_2)(rtx, rtx, rtx) + = mode == DImode ? gen_x86_shiftsi_adj_2 : gen_x86_shiftdi_adj_2; + + emit_insn (gen_x86_shift_adj_2 (low[0], high[0], operands[2])); + } } } @@ -18402,10 +18436,10 @@ ix86_expand_aligntest (rtx variable, int value, bool epilogue) static void ix86_adjust_counter (rtx countreg, HOST_WIDE_INT value) { - if (GET_MODE (countreg) == DImode) - emit_insn (gen_adddi3 (countreg, countreg, GEN_INT (-value))); - else - emit_insn (gen_addsi3 (countreg, countreg, GEN_INT (-value))); + rtx (*gen_add)(rtx, rtx, rtx) + = GET_MODE (countreg) == DImode ? gen_adddi3 : gen_addsi3; + + emit_insn (gen_add (countreg, countreg, GEN_INT (-value))); } /* Zero extend possibly SImode EXP to Pmode register. */ @@ -19221,7 +19255,7 @@ decide_alg (HOST_WIDE_INT count, HOST_WIDE_INT expected_size, bool memset, { unsigned int i; enum stringop_alg alg = libcall; - for (i = 0; i < NAX_STRINGOP_ALGS; i++) + for (i = 0; i < MAX_STRINGOP_ALGS; i++) { /* We get here if the algorithms that were not libcall-based were rep-prefix based and we are unable to use rep prefixes @@ -19267,7 +19301,7 @@ decide_alg (HOST_WIDE_INT count, HOST_WIDE_INT expected_size, bool memset, int i; bool any_alg_usable_p = true; - for (i = 0; i < NAX_STRINGOP_ALGS; i++) + for (i = 0; i < MAX_STRINGOP_ALGS; i++) { enum stringop_alg candidate = algs->size[i].alg; any_alg_usable_p = any_alg_usable_p && ALG_USABLE_P (candidate); @@ -26139,7 +26173,7 @@ ix86_force_to_memory (enum machine_mode mode, rtx operand) case DImode: { rtx operands[2]; - split_di (&operand, 1, operands, operands + 1); + split_double_mode (mode, &operand, 1, operands, operands + 1); emit_insn ( gen_rtx_SET (VOIDmode, gen_rtx_MEM (SImode, @@ -27885,6 +27919,120 @@ ix86_pad_returns (void) } } +/* Count the minimum number of instructions in BB. Return 4 if the + number of instructions >= 4. */ + +static int +ix86_count_insn_bb (basic_block bb) +{ + rtx insn; + int insn_count = 0; + + /* Count number of instructions in this block. Return 4 if the number + of instructions >= 4. */ + FOR_BB_INSNS (bb, insn) + { + /* Only happen in exit blocks. */ + if (JUMP_P (insn) + && GET_CODE (PATTERN (insn)) == RETURN) + break; + + if (NONDEBUG_INSN_P (insn) + && GET_CODE (PATTERN (insn)) != USE + && GET_CODE (PATTERN (insn)) != CLOBBER) + { + insn_count++; + if (insn_count >= 4) + return insn_count; + } + } + + return insn_count; +} + + +/* Count the minimum number of instructions in code path in BB. + Return 4 if the number of instructions >= 4. */ + +static int +ix86_count_insn (basic_block bb) +{ + edge e; + edge_iterator ei; + int min_prev_count; + + /* Only bother counting instructions along paths with no + more than 2 basic blocks between entry and exit. Given + that BB has an edge to exit, determine if a predecessor + of BB has an edge from entry. If so, compute the number + of instructions in the predecessor block. If there + happen to be multiple such blocks, compute the minimum. */ + min_prev_count = 4; + FOR_EACH_EDGE (e, ei, bb->preds) + { + edge prev_e; + edge_iterator prev_ei; + + if (e->src == ENTRY_BLOCK_PTR) + { + min_prev_count = 0; + break; + } + FOR_EACH_EDGE (prev_e, prev_ei, e->src->preds) + { + if (prev_e->src == ENTRY_BLOCK_PTR) + { + int count = ix86_count_insn_bb (e->src); + if (count < min_prev_count) + min_prev_count = count; + break; + } + } + } + + if (min_prev_count < 4) + min_prev_count += ix86_count_insn_bb (bb); + + return min_prev_count; +} + +/* Pad short funtion to 4 instructions. */ + +static void +ix86_pad_short_function (void) +{ + edge e; + edge_iterator ei; + + FOR_EACH_EDGE (e, ei, EXIT_BLOCK_PTR->preds) + { + rtx ret = BB_END (e->src); + if (JUMP_P (ret) && GET_CODE (PATTERN (ret)) == RETURN) + { + int insn_count = ix86_count_insn (e->src); + + /* Pad short function. */ + if (insn_count < 4) + { + rtx insn = ret; + + /* Find epilogue. */ + while (insn + && (!NOTE_P (insn) + || NOTE_KIND (insn) != NOTE_INSN_EPILOGUE_BEG)) + insn = PREV_INSN (insn); + + if (!insn) + insn = ret; + + /* Two NOPs are counted as one instruction. */ + insn_count = 2 * (4 - insn_count); + emit_insn_before (gen_nops (GEN_INT (insn_count)), insn); + } + } + } +} + /* Implement machine specific optimizations. We implement padding of returns for K8 CPUs and pass to avoid 4 jumps in the single 16 byte window. */ static void @@ -27892,7 +28040,9 @@ ix86_reorg (void) { if (optimize && optimize_function_for_speed_p (cfun)) { - if (TARGET_PAD_RETURNS) + if (TARGET_PAD_SHORT_FUNCTION) + ix86_pad_short_function (); + else if (TARGET_PAD_RETURNS) ix86_pad_returns (); #ifdef ASM_OUTPUT_MAX_SKIP_PAD if (TARGET_FOUR_JUMP_LIMIT) diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h index 22dd02b0bb8..b3439bc9f0c 100644 --- a/gcc/config/i386/i386.h +++ b/gcc/config/i386/i386.h @@ -90,7 +90,7 @@ enum stringop_alg unrolled_loop }; -#define NAX_STRINGOP_ALGS 4 +#define MAX_STRINGOP_ALGS 4 /* Specify what algorithm to use for stringops on known size. When size is unknown, the UNKNOWN_SIZE alg is used. When size is @@ -107,7 +107,7 @@ struct stringop_algs const struct stringop_strategy { const int max; const enum stringop_alg alg; - } size [NAX_STRINGOP_ALGS]; + } size [MAX_STRINGOP_ALGS]; }; /* Define the specific costs for a given cpu */ @@ -299,6 +299,7 @@ enum ix86_tune_indices { X86_TUNE_USE_BT, X86_TUNE_USE_INCDEC, X86_TUNE_PAD_RETURNS, + X86_TUNE_PAD_SHORT_FUNCTION, X86_TUNE_EXT_80387_CONSTANTS, X86_TUNE_SHORTEN_X87_SSE, X86_TUNE_AVOID_VECTOR_DECODE, @@ -385,6 +386,8 @@ extern unsigned char ix86_tune_features[X86_TUNE_LAST]; #define TARGET_USE_BT ix86_tune_features[X86_TUNE_USE_BT] #define TARGET_USE_INCDEC ix86_tune_features[X86_TUNE_USE_INCDEC] #define TARGET_PAD_RETURNS ix86_tune_features[X86_TUNE_PAD_RETURNS] +#define TARGET_PAD_SHORT_FUNCTION \ + ix86_tune_features[X86_TUNE_PAD_SHORT_FUNCTION] #define TARGET_EXT_80387_CONSTANTS \ ix86_tune_features[X86_TUNE_EXT_80387_CONSTANTS] #define TARGET_SHORTEN_X87_SSE ix86_tune_features[X86_TUNE_SHORTEN_X87_SSE] @@ -671,9 +674,8 @@ enum target_cpu_default /* Width of a word, in units (bytes). */ #define UNITS_PER_WORD (TARGET_64BIT ? 8 : 4) -#ifdef IN_LIBGCC2 -#define MIN_UNITS_PER_WORD (TARGET_64BIT ? 8 : 4) -#else + +#ifndef IN_LIBGCC2 #define MIN_UNITS_PER_WORD 4 #endif @@ -860,8 +862,8 @@ enum target_cpu_default #define STACK_REGS #define IS_STACK_MODE(MODE) \ - (((MODE) == SFmode && (!TARGET_SSE || !TARGET_SSE_MATH)) \ - || ((MODE) == DFmode && (!TARGET_SSE2 || !TARGET_SSE_MATH)) \ + (((MODE) == SFmode && !(TARGET_SSE && TARGET_SSE_MATH)) \ + || ((MODE) == DFmode && !(TARGET_SSE2 && TARGET_SSE_MATH)) \ || (MODE) == XFmode) /* Cover class containing the stack registers. */ @@ -976,8 +978,7 @@ enum target_cpu_default Actually there are no two word move instructions for consecutive registers. And only registers 0-3 may have mov byte instructions - applied to them. - */ + applied to them. */ #define HARD_REGNO_NREGS(REGNO, MODE) \ (FP_REGNO_P (REGNO) || SSE_REGNO_P (REGNO) || MMX_REGNO_P (REGNO) \ @@ -1184,7 +1185,8 @@ enum reg_class NON_Q_REGS, /* %esi %edi %ebp %esp */ INDEX_REGS, /* %eax %ebx %ecx %edx %esi %edi %ebp */ LEGACY_REGS, /* %eax %ebx %ecx %edx %esi %edi %ebp %esp */ - GENERAL_REGS, /* %eax %ebx %ecx %edx %esi %edi %ebp %esp %r8 - %r15*/ + GENERAL_REGS, /* %eax %ebx %ecx %edx %esi %edi %ebp %esp + %r8 %r9 %r10 %r11 %r12 %r13 %r14 %r15 */ FP_TOP_REG, FP_SECOND_REG, /* %st(0) %st(1) */ FLOAT_REGS, SSE_FIRST_REG, @@ -1413,10 +1415,13 @@ enum reg_class /* On the 80386, this is the size of MODE in words, except in the FP regs, where a single reg is always enough. */ #define CLASS_MAX_NREGS(CLASS, MODE) \ - (!MAYBE_INTEGER_CLASS_P (CLASS) \ - ? (COMPLEX_MODE_P (MODE) ? 2 : 1) \ - : (((((MODE) == XFmode ? 12 : GET_MODE_SIZE (MODE))) \ - + UNITS_PER_WORD - 1) / UNITS_PER_WORD)) + (MAYBE_INTEGER_CLASS_P (CLASS) \ + ? ((MODE) == XFmode \ + ? (TARGET_64BIT ? 2 : 3) \ + : (MODE) == XCmode \ + ? (TARGET_64BIT ? 4 : 6) \ + : ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)) \ + : (COMPLEX_MODE_P (MODE) ? 2 : 1)) /* Return a class of registers that cannot change FROM mode to TO mode. */ @@ -1750,7 +1755,7 @@ typedef struct ix86_args { /* MOVE_MAX_PIECES is the number of bytes at a time which we can move efficiently, as opposed to MOVE_MAX which is the maximum number of bytes we can move with a single instruction. */ -#define MOVE_MAX_PIECES (TARGET_64BIT ? 8 : 4) +#define MOVE_MAX_PIECES UNITS_PER_WORD /* If a memory-to-memory move would take MOVE_RATIO or more simple move-instruction pairs, we will do a movmem or libcall instead. @@ -1995,18 +2000,12 @@ do { \ #define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, BODY, VALUE, REL) \ ix86_output_addr_diff_elt ((FILE), (VALUE), (REL)) -/* When we see %v, we will print the 'v' prefix if TARGET_AVX is - true. */ +/* When we see %v, we will print the 'v' prefix if TARGET_AVX is true. */ #define ASM_OUTPUT_AVX_PREFIX(STREAM, PTR) \ { \ if ((PTR)[0] == '%' && (PTR)[1] == 'v') \ - { \ - if (TARGET_AVX) \ - (PTR) += 1; \ - else \ - (PTR) += 2; \ - } \ + (PTR) += TARGET_AVX ? 1 : 2; \ } /* A C statement or statements which output an assembler instruction diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md index ec43793b951..c541c1485c4 100644 --- a/gcc/config/i386/i386.md +++ b/gcc/config/i386/i386.md @@ -247,6 +247,7 @@ UNSPECV_LOCK UNSPECV_PROLOGUE_USE UNSPECV_CLD + UNSPECV_NOPS UNSPECV_VZEROALL UNSPECV_VZEROUPPER UNSPECV_RDTSC @@ -1639,7 +1640,7 @@ [(set (match_dup 0) (match_dup 1)) (set (match_dup 2) (match_dup 3))] { - split_di (&operands[1], 1, &operands[2], &operands[3]); + split_double_mode (DImode, &operands[1], 1, &operands[2], &operands[3]); operands[1] = gen_lowpart (DImode, operands[2]); operands[2] = gen_rtx_MEM (SImode, gen_rtx_PLUS (DImode, stack_pointer_rtx, @@ -1656,7 +1657,7 @@ [(set (match_dup 0) (match_dup 1)) (set (match_dup 2) (match_dup 3))] { - split_di (&operands[1], 1, &operands[2], &operands[3]); + split_double_mode (DImode, &operands[1], 1, &operands[2], &operands[3]); operands[1] = gen_lowpart (DImode, operands[2]); operands[2] = gen_rtx_MEM (SImode, gen_rtx_PLUS (DImode, stack_pointer_rtx, @@ -2049,7 +2050,7 @@ && !x86_64_immediate_operand (operands[1], DImode) && 1" [(set (match_dup 2) (match_dup 3)) (set (match_dup 4) (match_dup 5))] - "split_di (&operands[0], 2, &operands[2], &operands[4]);") + "split_double_mode (DImode, &operands[0], 2, &operands[2], &operands[4]);") (define_split [(set (match_operand:DI 0 "memory_operand" "") @@ -2060,7 +2061,7 @@ && !x86_64_immediate_operand (operands[1], DImode)" [(set (match_dup 2) (match_dup 3)) (set (match_dup 4) (match_dup 5))] - "split_di (&operands[0], 2, &operands[2], &operands[4]);") + "split_double_mode (DImode, &operands[0], 2, &operands[2], &operands[4]);") (define_insn "*movdi_internal" [(set (match_operand:DI 0 "nonimmediate_operand" @@ -3597,7 +3598,7 @@ (zero_extend:DI (match_dup 0)))] "TARGET_64BIT" [(set (match_dup 4) (const_int 0))] - "split_di (&operands[0], 1, &operands[3], &operands[4]);") + "split_double_mode (DImode, &operands[0], 1, &operands[3], &operands[4]);") ;; %%% Kill me once multi-word ops are sane. (define_insn "zero_extendsidi2_1" @@ -3625,7 +3626,7 @@ "!TARGET_64BIT && reload_completed && true_regnum (operands[0]) == true_regnum (operands[1])" [(set (match_dup 4) (const_int 0))] - "split_di (&operands[0], 1, &operands[3], &operands[4]);") + "split_double_mode (DImode, &operands[0], 1, &operands[3], &operands[4]);") (define_split [(set (match_operand:DI 0 "nonimmediate_operand" "") @@ -3635,7 +3636,7 @@ && !(MMX_REG_P (operands[0]) || SSE_REG_P (operands[0]))" [(set (match_dup 3) (match_dup 1)) (set (match_dup 4) (const_int 0))] - "split_di (&operands[0], 1, &operands[3], &operands[4]);") + "split_double_mode (DImode, &operands[0], 1, &operands[3], &operands[4]);") (define_insn "zero_extend<mode>di2" [(set (match_operand:DI 0 "register_operand" "=r") @@ -3800,7 +3801,7 @@ (parallel [(set (match_dup 1) (ashiftrt:SI (match_dup 1) (const_int 31))) (clobber (reg:CC FLAGS_REG))]) (set (match_dup 4) (match_dup 1))] - "split_di (&operands[0], 1, &operands[3], &operands[4]);") + "split_double_mode (DImode, &operands[0], 1, &operands[3], &operands[4]);") ;; Extend to memory case when source register does not die. (define_split @@ -3811,7 +3812,7 @@ "reload_completed" [(const_int 0)] { - split_di (&operands[0], 1, &operands[3], &operands[4]); + split_double_mode (DImode, &operands[0], 1, &operands[3], &operands[4]); emit_move_insn (operands[3], operands[1]); @@ -3841,7 +3842,7 @@ "reload_completed" [(const_int 0)] { - split_di (&operands[0], 1, &operands[3], &operands[4]); + split_double_mode (DImode, &operands[0], 1, &operands[3], &operands[4]); if (true_regnum (operands[3]) != true_regnum (operands[1])) emit_move_insn (operands[3], operands[1]); @@ -5569,7 +5570,7 @@ (ltu:DWIH (reg:CC FLAGS_REG) (const_int 0)) (match_dup 5)))) (clobber (reg:CC FLAGS_REG))])] - "split_<dwi> (&operands[0], 3, &operands[0], &operands[3]);") + "split_double_mode (<DWI>mode, &operands[0], 3, &operands[0], &operands[3]);") (define_insn "*add<mode>3_cc" [(set (reg:CC FLAGS_REG) @@ -6599,7 +6600,7 @@ (ltu:DWIH (reg:CC FLAGS_REG) (const_int 0)) (match_dup 5)))) (clobber (reg:CC FLAGS_REG))])] - "split_<dwi> (&operands[0], 3, &operands[0], &operands[3]);") + "split_double_mode (<DWI>mode, &operands[0], 3, &operands[0], &operands[3]);") (define_insn "*sub<mode>_1" [(set (match_operand:SWI 0 "nonimmediate_operand" "=<r>m,<r>") @@ -8592,7 +8593,7 @@ [(set (match_dup 2) (neg:DWIH (match_dup 2))) (clobber (reg:CC FLAGS_REG))])] - "split_<dwi> (&operands[0], 2, &operands[0], &operands[2]);") + "split_double_mode (<DWI>mode, &operands[0], 2, &operands[0], &operands[2]);") (define_insn "*neg<mode>2_1" [(set (match_operand:SWI 0 "nonimmediate_operand" "=<r>m") @@ -10071,7 +10072,7 @@ { operands[6] = GEN_INT (GET_MODE_BITSIZE (<MODE>mode)); - split_<dwi> (&operands[0], 1, &operands[4], &operands[5]); + split_double_mode (<DWI>mode, &operands[0], 1, &operands[4], &operands[5]); }) (define_insn_and_split "ix86_rotr<dwi>3_doubleword" @@ -10099,7 +10100,7 @@ { operands[6] = GEN_INT (GET_MODE_BITSIZE (<MODE>mode)); - split_<dwi> (&operands[0], 1, &operands[4], &operands[5]); + split_double_mode (<DWI>mode, &operands[0], 1, &operands[4], &operands[5]); }) (define_insn "*<rotate_insn><mode>3_1" @@ -11465,6 +11466,25 @@ (set_attr "length_immediate" "0") (set_attr "modrm" "0")]) +;; Generate nops. Operand 0 is the number of nops, up to 8. +(define_insn "nops" + [(unspec_volatile [(match_operand 0 "const_int_operand" "")] + UNSPECV_NOPS)] + "reload_completed" +{ + int num = INTVAL (operands[0]); + + gcc_assert (num >= 1 && num <= 8); + + while (num--) + fputs ("\tnop\n", asm_out_file); + + return ""; +} + [(set (attr "length") (symbol_ref "INTVAL (operands[0])")) + (set_attr "length_immediate" "0") + (set_attr "modrm" "0")]) + ;; Pad to 16-byte boundary, max skip in op0. Used to avoid ;; branch prediction penalty for the third jump in a 16-byte ;; block on K8. @@ -11495,7 +11515,7 @@ (unspec:SI [(const_int 0)] UNSPEC_SET_GOT)) (clobber (reg:CC FLAGS_REG))] "!TARGET_64BIT" - { return output_set_got (operands[0], NULL_RTX); } + "* return output_set_got (operands[0], NULL_RTX);" [(set_attr "type" "multi") (set_attr "length" "12")]) @@ -11505,7 +11525,7 @@ UNSPEC_SET_GOT)) (clobber (reg:CC FLAGS_REG))] "!TARGET_64BIT" - { return output_set_got (operands[0], operands[1]); } + "* return output_set_got (operands[0], operands[1]);" [(set_attr "type" "multi") (set_attr "length" "12")]) @@ -14960,18 +14980,65 @@ DONE; }) -(define_expand "signbit<mode>2" +(define_expand "signbitxf2" + [(use (match_operand:SI 0 "register_operand" "")) + (use (match_operand:XF 1 "register_operand" ""))] + "TARGET_USE_FANCY_MATH_387" +{ + rtx scratch = gen_reg_rtx (HImode); + + emit_insn (gen_fxamxf2_i387 (scratch, operands[1])); + emit_insn (gen_andsi3 (operands[0], + gen_lowpart (SImode, scratch), GEN_INT (0x200))); + DONE; +}) + +(define_insn "movmsk_df" + [(set (match_operand:SI 0 "register_operand" "=r") + (unspec:SI + [(match_operand:DF 1 "register_operand" "x")] + UNSPEC_MOVMSK))] + "SSE_FLOAT_MODE_P (DFmode) && TARGET_SSE_MATH" + "%vmovmskpd\t{%1, %0|%0, %1}" + [(set_attr "type" "ssemov") + (set_attr "prefix" "maybe_vex") + (set_attr "mode" "DF")]) + +;; Use movmskpd in SSE mode to avoid store forwarding stall +;; for 32bit targets and movq+shrq sequence for 64bit targets. +(define_expand "signbitdf2" [(use (match_operand:SI 0 "register_operand" "")) - (use (match_operand:X87MODEF 1 "register_operand" ""))] + (use (match_operand:DF 1 "register_operand" ""))] "TARGET_USE_FANCY_MATH_387 - && !(SSE_FLOAT_MODE_P (<MODE>mode) && TARGET_SSE_MATH)" + || (SSE_FLOAT_MODE_P (DFmode) && TARGET_SSE_MATH)" { - rtx mask = GEN_INT (0x0200); + if (SSE_FLOAT_MODE_P (DFmode) && TARGET_SSE_MATH) + { + emit_insn (gen_movmsk_df (operands[0], operands[1])); + emit_insn (gen_andsi3 (operands[0], operands[0], const1_rtx)); + } + else + { + rtx scratch = gen_reg_rtx (HImode); + emit_insn (gen_fxamdf2_i387 (scratch, operands[1])); + emit_insn (gen_andsi3 (operands[0], + gen_lowpart (SImode, scratch), GEN_INT (0x200))); + } + DONE; +}) + +(define_expand "signbitsf2" + [(use (match_operand:SI 0 "register_operand" "")) + (use (match_operand:SF 1 "register_operand" ""))] + "TARGET_USE_FANCY_MATH_387 + && !(SSE_FLOAT_MODE_P (SFmode) && TARGET_SSE_MATH)" +{ rtx scratch = gen_reg_rtx (HImode); - emit_insn (gen_fxam<mode>2_i387 (scratch, operands[1])); - emit_insn (gen_andsi3 (operands[0], gen_lowpart (SImode, scratch), mask)); + emit_insn (gen_fxamsf2_i387 (scratch, operands[1])); + emit_insn (gen_andsi3 (operands[0], + gen_lowpart (SImode, scratch), GEN_INT (0x200))); DONE; }) @@ -16021,8 +16088,8 @@ (match_dup 7) (match_dup 8)))] { - split_di (&operands[2], 2, &operands[5], &operands[7]); - split_di (&operands[0], 1, &operands[2], &operands[3]); + split_double_mode (DImode, &operands[2], 2, &operands[5], &operands[7]); + split_double_mode (DImode, &operands[0], 1, &operands[2], &operands[3]); }) (define_insn "*movxfcc_1" @@ -16179,10 +16246,10 @@ ;; ;; in proper program order. -(define_insn "pro_epilogue_adjust_stack_<mode>_1" +(define_insn "pro_epilogue_adjust_stack_<mode>_add" [(set (match_operand:P 0 "register_operand" "=r,r") (plus:P (match_operand:P 1 "register_operand" "0,r") - (match_operand:P 2 "<immediate_operand>" "<i>,<i>"))) + (match_operand:P 2 "<nonmemory_operand>" "r<i>,l<i>"))) (clobber (reg:CC FLAGS_REG)) (clobber (mem:BLK (scratch)))] "" @@ -16222,52 +16289,24 @@ (const_string "*"))) (set_attr "mode" "<MODE>")]) -(define_insn "pro_epilogue_adjust_stack_di_2" - [(set (match_operand:DI 0 "register_operand" "=r,r") - (plus:DI (match_operand:DI 1 "register_operand" "0,r") - (match_operand:DI 3 "immediate_operand" "i,i"))) - (use (match_operand:DI 2 "register_operand" "r,l")) +(define_insn "pro_epilogue_adjust_stack_<mode>_sub" + [(set (match_operand:P 0 "register_operand" "=r") + (minus:P (match_operand:P 1 "register_operand" "0") + (match_operand:P 2 "register_operand" "r"))) (clobber (reg:CC FLAGS_REG)) (clobber (mem:BLK (scratch)))] - "TARGET_64BIT" -{ - switch (get_attr_type (insn)) - { - case TYPE_ALU: - return "add{q}\t{%2, %0|%0, %2}"; - - case TYPE_LEA: - operands[2] = gen_rtx_PLUS (DImode, operands[1], operands[2]); - return "lea{q}\t{%a2, %0|%0, %a2}"; - - default: - gcc_unreachable (); - } -} - [(set_attr "type" "alu,lea") - (set_attr "mode" "DI")]) - -(define_insn "allocate_stack_worker_32" - [(set (match_operand:SI 0 "register_operand" "=a") - (unspec_volatile:SI [(match_operand:SI 1 "register_operand" "0")] - UNSPECV_STACK_PROBE)) - (set (reg:SI SP_REG) (minus:SI (reg:SI SP_REG) (match_dup 1))) - (clobber (reg:CC FLAGS_REG))] - "!TARGET_64BIT && ix86_target_stack_probe ()" - "call\t___chkstk" - [(set_attr "type" "multi") - (set_attr "length" "5")]) + "" + "sub{<imodesuffix>}\t{%2, %0|%0, %2}" + [(set_attr "type" "alu") + (set_attr "mode" "<MODE>")]) -(define_insn "allocate_stack_worker_64" - [(set (match_operand:DI 0 "register_operand" "=a") - (unspec_volatile:DI [(match_operand:DI 1 "register_operand" "0")] +(define_insn "allocate_stack_worker_probe_<mode>" + [(set (match_operand:P 0 "register_operand" "=a") + (unspec_volatile:P [(match_operand:P 1 "register_operand" "0")] UNSPECV_STACK_PROBE)) - (set (reg:DI SP_REG) (minus:DI (reg:DI SP_REG) (match_dup 1))) - (clobber (reg:DI R10_REG)) - (clobber (reg:DI R11_REG)) (clobber (reg:CC FLAGS_REG))] - "TARGET_64BIT && ix86_target_stack_probe ()" - "call\t___chkstk" + "ix86_target_stack_probe ()" + "call\t___chkstk_ms" [(set_attr "type" "multi") (set_attr "length" "5")]) @@ -16292,15 +16331,15 @@ } else { - rtx (*gen_allocate_stack_worker) (rtx, rtx); - + x = copy_to_mode_reg (Pmode, operands[1]); if (TARGET_64BIT) - gen_allocate_stack_worker = gen_allocate_stack_worker_64; + emit_insn (gen_allocate_stack_worker_probe_di (x, x)); else - gen_allocate_stack_worker = gen_allocate_stack_worker_32; - - x = copy_to_mode_reg (Pmode, operands[1]); - emit_insn (gen_allocate_stack_worker (x, x)); + emit_insn (gen_allocate_stack_worker_probe_si (x, x)); + x = expand_simple_binop (Pmode, MINUS, stack_pointer_rtx, x, + stack_pointer_rtx, 0, OPTAB_DIRECT); + if (x != stack_pointer_rtx) + emit_move_insn (stack_pointer_rtx, x); } emit_move_insn (operands[0], virtual_stack_dynamic_rtx); diff --git a/gcc/config/i386/i386.opt b/gcc/config/i386/i386.opt index aa78cdfaa26..38a53f616c7 100644 --- a/gcc/config/i386/i386.opt +++ b/gcc/config/i386/i386.opt @@ -19,6 +19,10 @@ ; along with GCC; see the file COPYING3. If not see ; <http://www.gnu.org/licenses/>. +; Bit flags that specify the ISA we are compiling for. +Variable +int ix86_isa_flags = TARGET_64BIT_DEFAULT | TARGET_SUBTARGET_ISA_DEFAULT + ;; Definitions to add to the cl_target_option structure ;; -march= processor TargetSave diff --git a/gcc/config/i386/t-cygming b/gcc/config/i386/t-cygming index 0a65ffd99d9..183e545d8eb 100644 --- a/gcc/config/i386/t-cygming +++ b/gcc/config/i386/t-cygming @@ -17,7 +17,7 @@ # <http://www.gnu.org/licenses/>. LIB1ASMSRC = i386/cygwin.asm -LIB1ASMFUNCS = _chkstk +LIB1ASMFUNCS = _chkstk _chkstk_ms # cygwin and mingw always have a limits.h, but, depending upon how we are # doing the build, it may not be installed yet. diff --git a/gcc/config/i386/t-cygwin b/gcc/config/i386/t-cygwin index af91aa5cdb6..a01219cfb9d 100644 --- a/gcc/config/i386/t-cygwin +++ b/gcc/config/i386/t-cygwin @@ -1,4 +1,4 @@ -# Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2008, 2009 +# Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2008, 2009, 2010 # Free Software Foundation, Inc. # # This file is part of GCC. @@ -24,7 +24,7 @@ LIBGCC2_INCLUDES += -I$(srcdir)/../winsup/include \ -I$(srcdir)/../winsup/cygwin/include cygwin1.o: $(srcdir)/config/i386/cygwin1.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \ - $(TM_H) $(TM_P_H) + $(TM_H) $(TM_P_H) opts.h $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \ $(srcdir)/config/i386/cygwin1.c diff --git a/gcc/config/i386/t-interix b/gcc/config/i386/t-interix index 9a25831f135..30539e2e13f 100644 --- a/gcc/config/i386/t-interix +++ b/gcc/config/i386/t-interix @@ -1,5 +1,5 @@ LIB1ASMSRC = i386/cygwin.asm -LIB1ASMFUNCS = _chkstk +LIB1ASMFUNCS = _chkstk _chkstk_ms winnt.o: $(srcdir)/config/i386/winnt.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \ $(TM_H) $(RTL_H) $(REGS_H) hard-reg-set.h output.h $(TREE_H) flags.h \ diff --git a/gcc/config/i386/vx-common.h b/gcc/config/i386/vx-common.h index cc7ea75ce40..f4547f08848 100644 --- a/gcc/config/i386/vx-common.h +++ b/gcc/config/i386/vx-common.h @@ -24,3 +24,9 @@ along with GCC; see the file COPYING3. If not see #define SUBTARGET_RETURN_IN_MEMORY(TYPE, FNTYPE) \ ix86_solaris_return_in_memory (TYPE, FNTYPE) + +/* Provide our target specific DBX_REGISTER_NUMBER, as advertised by the + common svr4.h. VxWorks relies on the SVR4 numbering. */ + +#undef DBX_REGISTER_NUMBER +#define DBX_REGISTER_NUMBER(n) svr4_dbx_register_map[n] diff --git a/gcc/config/ia64/ia64.c b/gcc/config/ia64/ia64.c index d02d2b8fc3f..61be5a45bbe 100644 --- a/gcc/config/ia64/ia64.c +++ b/gcc/config/ia64/ia64.c @@ -230,7 +230,6 @@ static void emit_predicate_relation_info (void); static void ia64_reorg (void); static bool ia64_in_small_data_p (const_tree); static void process_epilogue (FILE *, rtx, bool, bool); -static int process_set (FILE *, rtx, rtx, bool, bool); static bool ia64_assemble_integer (rtx, unsigned int, int); static void ia64_output_function_prologue (FILE *, HOST_WIDE_INT); @@ -318,6 +317,8 @@ static enum machine_mode ia64_promote_function_mode (const_tree, int); static void ia64_trampoline_init (rtx, tree, rtx); static void ia64_override_options_after_change (void); + +static void ia64_dwarf_handle_frame_unspec (const char *, rtx, int); /* Table of valid machine attributes. */ static const struct attribute_spec ia64_attribute_table[] = @@ -527,6 +528,8 @@ static const struct attribute_spec ia64_attribute_table[] = #undef TARGET_GIMPLIFY_VA_ARG_EXPR #define TARGET_GIMPLIFY_VA_ARG_EXPR ia64_gimplify_va_arg +#undef TARGET_DWARF_HANDLE_FRAME_UNSPEC +#define TARGET_DWARF_HANDLE_FRAME_UNSPEC ia64_dwarf_handle_frame_unspec #undef TARGET_ASM_UNWIND_EMIT #define TARGET_ASM_UNWIND_EMIT ia64_asm_unwind_emit #undef TARGET_ASM_EMIT_EXCEPT_PERSONALITY @@ -3035,7 +3038,7 @@ do_spill (rtx (*move_fn) (rtx, rtx, rtx), rtx reg, HOST_WIDE_INT cfa_off, off = current_frame_info.total_size - cfa_off; } - add_reg_note (insn, REG_FRAME_RELATED_EXPR, + add_reg_note (insn, REG_CFA_OFFSET, gen_rtx_SET (VOIDmode, gen_rtx_MEM (GET_MODE (reg), plus_constant (base, off)), @@ -3219,6 +3222,10 @@ ia64_expand_prologue (void) { insn = emit_move_insn (hard_frame_pointer_rtx, stack_pointer_rtx); RTX_FRAME_RELATED_P (insn) = 1; + + /* Force the unwind info to recognize this as defining a new CFA, + rather than some temp register setup. */ + add_reg_note (insn, REG_CFA_ADJUST_CFA, NULL_RTX); } if (current_frame_info.total_size != 0) @@ -3241,13 +3248,12 @@ ia64_expand_prologue (void) if (! frame_pointer_needed) { RTX_FRAME_RELATED_P (insn) = 1; - if (GET_CODE (offset) != CONST_INT) - add_reg_note (insn, REG_FRAME_RELATED_EXPR, - gen_rtx_SET (VOIDmode, - stack_pointer_rtx, - gen_rtx_PLUS (DImode, - stack_pointer_rtx, - frame_size_rtx))); + add_reg_note (insn, REG_CFA_ADJUST_CFA, + gen_rtx_SET (VOIDmode, + stack_pointer_rtx, + gen_rtx_PLUS (DImode, + stack_pointer_rtx, + frame_size_rtx))); } /* ??? At this point we must generate a magic insn that appears to @@ -3275,7 +3281,11 @@ ia64_expand_prologue (void) reg = gen_rtx_REG (DImode, AR_UNAT_REGNUM); insn = emit_move_insn (ar_unat_save_reg, reg); - RTX_FRAME_RELATED_P (insn) = (current_frame_info.r[reg_save_ar_unat] != 0); + if (current_frame_info.r[reg_save_ar_unat]) + { + RTX_FRAME_RELATED_P (insn) = 1; + add_reg_note (insn, REG_CFA_REGISTER, NULL_RTX); + } /* Even if we're not going to generate an epilogue, we still need to save the register so that EH works. */ @@ -3314,8 +3324,7 @@ ia64_expand_prologue (void) /* ??? Denote pr spill/fill by a DImode move that modifies all 64 hard registers. */ RTX_FRAME_RELATED_P (insn) = 1; - add_reg_note (insn, REG_FRAME_RELATED_EXPR, - gen_rtx_SET (VOIDmode, alt_reg, reg)); + add_reg_note (insn, REG_CFA_REGISTER, NULL_RTX); /* Even if we're not going to generate an epilogue, we still need to save the register so that EH works. */ @@ -3361,6 +3370,7 @@ ia64_expand_prologue (void) reg_emitted (reg_save_ar_lc); insn = emit_move_insn (alt_reg, reg); RTX_FRAME_RELATED_P (insn) = 1; + add_reg_note (insn, REG_CFA_REGISTER, NULL_RTX); /* Even if we're not going to generate an epilogue, we still need to save the register so that EH works. */ @@ -3387,6 +3397,7 @@ ia64_expand_prologue (void) reg_emitted (reg_save_b0); insn = emit_move_insn (alt_reg, reg); RTX_FRAME_RELATED_P (insn) = 1; + add_reg_note (insn, REG_CFA_REGISTER, NULL_RTX); /* Even if we're not going to generate an epilogue, we still need to save the register so that EH works. */ @@ -3677,6 +3688,7 @@ ia64_expand_epilogue (int sibcall_p) { insn = emit_move_insn (stack_pointer_rtx, hard_frame_pointer_rtx); RTX_FRAME_RELATED_P (insn) = 1; + add_reg_note (insn, REG_CFA_ADJUST_CFA, NULL); } else if (current_frame_info.total_size) { @@ -3696,13 +3708,12 @@ ia64_expand_epilogue (int sibcall_p) offset)); RTX_FRAME_RELATED_P (insn) = 1; - if (GET_CODE (offset) != CONST_INT) - add_reg_note (insn, REG_FRAME_RELATED_EXPR, - gen_rtx_SET (VOIDmode, - stack_pointer_rtx, - gen_rtx_PLUS (DImode, - stack_pointer_rtx, - frame_size_rtx))); + add_reg_note (insn, REG_CFA_ADJUST_CFA, + gen_rtx_SET (VOIDmode, + stack_pointer_rtx, + gen_rtx_PLUS (DImode, + stack_pointer_rtx, + frame_size_rtx))); } if (cfun->machine->ia64_eh_epilogue_bsp) @@ -3713,11 +3724,12 @@ ia64_expand_epilogue (int sibcall_p) else { int fp = GR_REG (2); - /* We need a throw away register here, r0 and r1 are reserved, so r2 is the - first available call clobbered register. If there was a frame_pointer - register, we may have swapped the names of r2 and HARD_FRAME_POINTER_REGNUM, - so we have to make sure we're using the string "r2" when emitting - the register name for the assembler. */ + /* We need a throw away register here, r0 and r1 are reserved, + so r2 is the first available call clobbered register. If + there was a frame_pointer register, we may have swapped the + names of r2 and HARD_FRAME_POINTER_REGNUM, so we have to make + sure we're using the string "r2" when emitting the register + name for the assembler. */ if (current_frame_info.r[reg_fp] && current_frame_info.r[reg_fp] == GR_REG (2)) fp = HARD_FRAME_POINTER_REGNUM; @@ -9590,6 +9602,17 @@ ia64_dwarf2out_def_steady_cfa (rtx insn, bool frame) + ARG_POINTER_CFA_OFFSET (current_function_decl)); } +/* All we need to do here is avoid a crash in the generic dwarf2 + processing. The real CFA definition is set up above. */ + +static void +ia64_dwarf_handle_frame_unspec (const char * ARG_UNUSED (label), + rtx ARG_UNUSED (pattern), + int index) +{ + gcc_assert (index == UNSPECV_ALLOC); +} + /* The generic dwarf2 frame debug info generator does not define a separate region for the very end of the epilogue, so refrain from doing so in the IA64-specific code as well. */ @@ -9619,53 +9642,19 @@ process_epilogue (FILE *asm_out_file, rtx insn, bool unwind, bool frame) STACK_POINTER_REGNUM, INCOMING_FRAME_SP_OFFSET); } -/* This function processes a SET pattern looking for specific patterns - which result in emitting an assembly directive required for unwinding. */ +/* This function processes a SET pattern for REG_CFA_ADJUST_CFA. */ -static int -process_set (FILE *asm_out_file, rtx pat, rtx insn, bool unwind, bool frame) +static void +process_cfa_adjust_cfa (FILE *asm_out_file, rtx pat, rtx insn, + bool unwind, bool frame) { - rtx src = SET_SRC (pat); rtx dest = SET_DEST (pat); - int src_regno, dest_regno; - - /* Look for the ALLOC insn. */ - if (GET_CODE (src) == UNSPEC_VOLATILE - && XINT (src, 1) == UNSPECV_ALLOC - && GET_CODE (dest) == REG) - { - dest_regno = REGNO (dest); - - /* If this is the final destination for ar.pfs, then this must - be the alloc in the prologue. */ - if (dest_regno == current_frame_info.r[reg_save_ar_pfs]) - { - if (unwind) - fprintf (asm_out_file, "\t.save ar.pfs, r%d\n", - ia64_dbx_register_number (dest_regno)); - } - else - { - /* This must be an alloc before a sibcall. We must drop the - old frame info. The easiest way to drop the old frame - info is to ensure we had a ".restore sp" directive - followed by a new prologue. If the procedure doesn't - have a memory-stack frame, we'll issue a dummy ".restore - sp" now. */ - if (current_frame_info.total_size == 0 && !frame_pointer_needed) - /* if haven't done process_epilogue() yet, do it now */ - process_epilogue (asm_out_file, insn, unwind, frame); - if (unwind) - fprintf (asm_out_file, "\t.prologue\n"); - } - return 1; - } + rtx src = SET_SRC (pat); - /* Look for SP = .... */ - if (GET_CODE (dest) == REG && REGNO (dest) == STACK_POINTER_REGNUM) + if (dest == stack_pointer_rtx) { if (GET_CODE (src) == PLUS) - { + { rtx op0 = XEXP (src, 0); rtx op1 = XEXP (src, 1); @@ -9675,7 +9664,8 @@ process_set (FILE *asm_out_file, rtx pat, rtx insn, bool unwind, bool frame) { gcc_assert (!frame_pointer_needed); if (unwind) - fprintf (asm_out_file, "\t.fframe "HOST_WIDE_INT_PRINT_DEC"\n", + fprintf (asm_out_file, + "\t.fframe "HOST_WIDE_INT_PRINT_DEC"\n", -INTVAL (op1)); ia64_dwarf2out_def_steady_cfa (insn, frame); } @@ -9684,240 +9674,303 @@ process_set (FILE *asm_out_file, rtx pat, rtx insn, bool unwind, bool frame) } else { - gcc_assert (GET_CODE (src) == REG - && REGNO (src) == HARD_FRAME_POINTER_REGNUM); + gcc_assert (src == hard_frame_pointer_rtx); process_epilogue (asm_out_file, insn, unwind, frame); } + } + else if (dest == hard_frame_pointer_rtx) + { + gcc_assert (src == stack_pointer_rtx); + gcc_assert (frame_pointer_needed); - return 1; + if (unwind) + fprintf (asm_out_file, "\t.vframe r%d\n", + ia64_dbx_register_number (REGNO (dest))); + ia64_dwarf2out_def_steady_cfa (insn, frame); } + else + gcc_unreachable (); +} - /* Register move we need to look at. */ - if (GET_CODE (dest) == REG && GET_CODE (src) == REG) - { - src_regno = REGNO (src); - dest_regno = REGNO (dest); +/* This function processes a SET pattern for REG_CFA_REGISTER. */ - switch (src_regno) - { - case BR_REG (0): - /* Saving return address pointer. */ - gcc_assert (dest_regno == current_frame_info.r[reg_save_b0]); - if (unwind) - fprintf (asm_out_file, "\t.save rp, r%d\n", - ia64_dbx_register_number (dest_regno)); - return 1; +static void +process_cfa_register (FILE *asm_out_file, rtx pat, bool unwind) +{ + rtx dest = SET_DEST (pat); + rtx src = SET_SRC (pat); - case PR_REG (0): - gcc_assert (dest_regno == current_frame_info.r[reg_save_pr]); - if (unwind) - fprintf (asm_out_file, "\t.save pr, r%d\n", - ia64_dbx_register_number (dest_regno)); - return 1; + int dest_regno = REGNO (dest); + int src_regno = REGNO (src); - case AR_UNAT_REGNUM: - gcc_assert (dest_regno == current_frame_info.r[reg_save_ar_unat]); - if (unwind) - fprintf (asm_out_file, "\t.save ar.unat, r%d\n", - ia64_dbx_register_number (dest_regno)); - return 1; + switch (src_regno) + { + case BR_REG (0): + /* Saving return address pointer. */ + gcc_assert (dest_regno == current_frame_info.r[reg_save_b0]); + if (unwind) + fprintf (asm_out_file, "\t.save rp, r%d\n", + ia64_dbx_register_number (dest_regno)); + break; - case AR_LC_REGNUM: - gcc_assert (dest_regno == current_frame_info.r[reg_save_ar_lc]); - if (unwind) - fprintf (asm_out_file, "\t.save ar.lc, r%d\n", - ia64_dbx_register_number (dest_regno)); - return 1; + case PR_REG (0): + gcc_assert (dest_regno == current_frame_info.r[reg_save_pr]); + if (unwind) + fprintf (asm_out_file, "\t.save pr, r%d\n", + ia64_dbx_register_number (dest_regno)); + break; - case STACK_POINTER_REGNUM: - gcc_assert (dest_regno == HARD_FRAME_POINTER_REGNUM - && frame_pointer_needed); - if (unwind) - fprintf (asm_out_file, "\t.vframe r%d\n", - ia64_dbx_register_number (dest_regno)); - ia64_dwarf2out_def_steady_cfa (insn, frame); - return 1; + case AR_UNAT_REGNUM: + gcc_assert (dest_regno == current_frame_info.r[reg_save_ar_unat]); + if (unwind) + fprintf (asm_out_file, "\t.save ar.unat, r%d\n", + ia64_dbx_register_number (dest_regno)); + break; - default: - /* Everything else should indicate being stored to memory. */ - gcc_unreachable (); - } + case AR_LC_REGNUM: + gcc_assert (dest_regno == current_frame_info.r[reg_save_ar_lc]); + if (unwind) + fprintf (asm_out_file, "\t.save ar.lc, r%d\n", + ia64_dbx_register_number (dest_regno)); + break; + + default: + /* Everything else should indicate being stored to memory. */ + gcc_unreachable (); } +} - /* Memory store we need to look at. */ - if (GET_CODE (dest) == MEM && GET_CODE (src) == REG) - { - long off; - rtx base; - const char *saveop; +/* This function processes a SET pattern for REG_CFA_OFFSET. */ - if (GET_CODE (XEXP (dest, 0)) == REG) - { - base = XEXP (dest, 0); - off = 0; - } - else - { - gcc_assert (GET_CODE (XEXP (dest, 0)) == PLUS - && GET_CODE (XEXP (XEXP (dest, 0), 1)) == CONST_INT); - base = XEXP (XEXP (dest, 0), 0); - off = INTVAL (XEXP (XEXP (dest, 0), 1)); - } +static void +process_cfa_offset (FILE *asm_out_file, rtx pat, bool unwind) +{ + rtx dest = SET_DEST (pat); + rtx src = SET_SRC (pat); + int src_regno = REGNO (src); + const char *saveop; + HOST_WIDE_INT off; + rtx base; - if (base == hard_frame_pointer_rtx) - { - saveop = ".savepsp"; - off = - off; - } - else - { - gcc_assert (base == stack_pointer_rtx); - saveop = ".savesp"; - } + gcc_assert (MEM_P (dest)); + if (GET_CODE (XEXP (dest, 0)) == REG) + { + base = XEXP (dest, 0); + off = 0; + } + else + { + gcc_assert (GET_CODE (XEXP (dest, 0)) == PLUS + && GET_CODE (XEXP (XEXP (dest, 0), 1)) == CONST_INT); + base = XEXP (XEXP (dest, 0), 0); + off = INTVAL (XEXP (XEXP (dest, 0), 1)); + } - src_regno = REGNO (src); - switch (src_regno) - { - case BR_REG (0): - gcc_assert (!current_frame_info.r[reg_save_b0]); - if (unwind) - fprintf (asm_out_file, "\t%s rp, %ld\n", saveop, off); - return 1; + if (base == hard_frame_pointer_rtx) + { + saveop = ".savepsp"; + off = - off; + } + else + { + gcc_assert (base == stack_pointer_rtx); + saveop = ".savesp"; + } - case PR_REG (0): - gcc_assert (!current_frame_info.r[reg_save_pr]); - if (unwind) - fprintf (asm_out_file, "\t%s pr, %ld\n", saveop, off); - return 1; + src_regno = REGNO (src); + switch (src_regno) + { + case BR_REG (0): + gcc_assert (!current_frame_info.r[reg_save_b0]); + if (unwind) + fprintf (asm_out_file, "\t%s rp, " HOST_WIDE_INT_PRINT_DEC "\n", + saveop, off); + break; - case AR_LC_REGNUM: - gcc_assert (!current_frame_info.r[reg_save_ar_lc]); - if (unwind) - fprintf (asm_out_file, "\t%s ar.lc, %ld\n", saveop, off); - return 1; + case PR_REG (0): + gcc_assert (!current_frame_info.r[reg_save_pr]); + if (unwind) + fprintf (asm_out_file, "\t%s pr, " HOST_WIDE_INT_PRINT_DEC "\n", + saveop, off); + break; - case AR_PFS_REGNUM: - gcc_assert (!current_frame_info.r[reg_save_ar_pfs]); - if (unwind) - fprintf (asm_out_file, "\t%s ar.pfs, %ld\n", saveop, off); - return 1; + case AR_LC_REGNUM: + gcc_assert (!current_frame_info.r[reg_save_ar_lc]); + if (unwind) + fprintf (asm_out_file, "\t%s ar.lc, " HOST_WIDE_INT_PRINT_DEC "\n", + saveop, off); + break; - case AR_UNAT_REGNUM: - gcc_assert (!current_frame_info.r[reg_save_ar_unat]); - if (unwind) - fprintf (asm_out_file, "\t%s ar.unat, %ld\n", saveop, off); - return 1; + case AR_PFS_REGNUM: + gcc_assert (!current_frame_info.r[reg_save_ar_pfs]); + if (unwind) + fprintf (asm_out_file, "\t%s ar.pfs, " HOST_WIDE_INT_PRINT_DEC "\n", + saveop, off); + break; - case GR_REG (4): - case GR_REG (5): - case GR_REG (6): - case GR_REG (7): - if (unwind) - fprintf (asm_out_file, "\t.save.g 0x%x\n", - 1 << (src_regno - GR_REG (4))); - return 1; + case AR_UNAT_REGNUM: + gcc_assert (!current_frame_info.r[reg_save_ar_unat]); + if (unwind) + fprintf (asm_out_file, "\t%s ar.unat, " HOST_WIDE_INT_PRINT_DEC "\n", + saveop, off); + break; - case BR_REG (1): - case BR_REG (2): - case BR_REG (3): - case BR_REG (4): - case BR_REG (5): - if (unwind) - fprintf (asm_out_file, "\t.save.b 0x%x\n", - 1 << (src_regno - BR_REG (1))); - return 1; + case GR_REG (4): + case GR_REG (5): + case GR_REG (6): + case GR_REG (7): + if (unwind) + fprintf (asm_out_file, "\t.save.g 0x%x\n", + 1 << (src_regno - GR_REG (4))); + break; - case FR_REG (2): - case FR_REG (3): - case FR_REG (4): - case FR_REG (5): - if (unwind) - fprintf (asm_out_file, "\t.save.f 0x%x\n", - 1 << (src_regno - FR_REG (2))); - return 1; + case BR_REG (1): + case BR_REG (2): + case BR_REG (3): + case BR_REG (4): + case BR_REG (5): + if (unwind) + fprintf (asm_out_file, "\t.save.b 0x%x\n", + 1 << (src_regno - BR_REG (1))); + break; - case FR_REG (16): case FR_REG (17): case FR_REG (18): case FR_REG (19): - case FR_REG (20): case FR_REG (21): case FR_REG (22): case FR_REG (23): - case FR_REG (24): case FR_REG (25): case FR_REG (26): case FR_REG (27): - case FR_REG (28): case FR_REG (29): case FR_REG (30): case FR_REG (31): - if (unwind) - fprintf (asm_out_file, "\t.save.gf 0x0, 0x%x\n", - 1 << (src_regno - FR_REG (12))); - return 1; + case FR_REG (2): + case FR_REG (3): + case FR_REG (4): + case FR_REG (5): + if (unwind) + fprintf (asm_out_file, "\t.save.f 0x%x\n", + 1 << (src_regno - FR_REG (2))); + break; - default: - return 0; - } - } + case FR_REG (16): case FR_REG (17): case FR_REG (18): case FR_REG (19): + case FR_REG (20): case FR_REG (21): case FR_REG (22): case FR_REG (23): + case FR_REG (24): case FR_REG (25): case FR_REG (26): case FR_REG (27): + case FR_REG (28): case FR_REG (29): case FR_REG (30): case FR_REG (31): + if (unwind) + fprintf (asm_out_file, "\t.save.gf 0x0, 0x%x\n", + 1 << (src_regno - FR_REG (12))); + break; - return 0; + default: + /* ??? For some reason we mark other general registers, even those + we can't represent in the unwind info. Ignore them. */ + break; + } } - /* This function looks at a single insn and emits any directives required to unwind this insn. */ + static void ia64_asm_unwind_emit (FILE *asm_out_file, rtx insn) { bool unwind = (flag_unwind_tables || (flag_exceptions && !USING_SJLJ_EXCEPTIONS)); bool frame = dwarf2out_do_frame (); + rtx note, pat; + bool handled_one; + + if (!unwind && !frame) + return; - if (unwind || frame) + if (NOTE_INSN_BASIC_BLOCK_P (insn)) { - rtx pat; + last_block = NOTE_BASIC_BLOCK (insn)->next_bb == EXIT_BLOCK_PTR; - if (NOTE_INSN_BASIC_BLOCK_P (insn)) + /* Restore unwind state from immediately before the epilogue. */ + if (need_copy_state) { - last_block = NOTE_BASIC_BLOCK (insn)->next_bb == EXIT_BLOCK_PTR; - - /* Restore unwind state from immediately before the epilogue. */ - if (need_copy_state) + if (unwind) { - if (unwind) - { - fprintf (asm_out_file, "\t.body\n"); - fprintf (asm_out_file, "\t.copy_state %d\n", - cfun->machine->state_num); - } - if (IA64_CHANGE_CFA_IN_EPILOGUE) - ia64_dwarf2out_def_steady_cfa (insn, frame); - need_copy_state = false; + fprintf (asm_out_file, "\t.body\n"); + fprintf (asm_out_file, "\t.copy_state %d\n", + cfun->machine->state_num); } + if (IA64_CHANGE_CFA_IN_EPILOGUE) + ia64_dwarf2out_def_steady_cfa (insn, frame); + need_copy_state = false; } + } - if (GET_CODE (insn) == NOTE || ! RTX_FRAME_RELATED_P (insn)) - return; + if (GET_CODE (insn) == NOTE || ! RTX_FRAME_RELATED_P (insn)) + return; + + /* Look for the ALLOC insn. */ + if (INSN_CODE (insn) == CODE_FOR_alloc) + { + rtx dest = SET_DEST (XVECEXP (PATTERN (insn), 0, 0)); + int dest_regno = REGNO (dest); - pat = find_reg_note (insn, REG_FRAME_RELATED_EXPR, NULL_RTX); - if (pat) - pat = XEXP (pat, 0); + /* If this is the final destination for ar.pfs, then this must + be the alloc in the prologue. */ + if (dest_regno == current_frame_info.r[reg_save_ar_pfs]) + { + if (unwind) + fprintf (asm_out_file, "\t.save ar.pfs, r%d\n", + ia64_dbx_register_number (dest_regno)); + } else - pat = PATTERN (insn); + { + /* This must be an alloc before a sibcall. We must drop the + old frame info. The easiest way to drop the old frame + info is to ensure we had a ".restore sp" directive + followed by a new prologue. If the procedure doesn't + have a memory-stack frame, we'll issue a dummy ".restore + sp" now. */ + if (current_frame_info.total_size == 0 && !frame_pointer_needed) + /* if haven't done process_epilogue() yet, do it now */ + process_epilogue (asm_out_file, insn, unwind, frame); + if (unwind) + fprintf (asm_out_file, "\t.prologue\n"); + } + return; + } - switch (GET_CODE (pat)) - { - case SET: - process_set (asm_out_file, pat, insn, unwind, frame); - break; + handled_one = false; + for (note = REG_NOTES (insn); note; note = XEXP (note, 1)) + switch (REG_NOTE_KIND (note)) + { + case REG_CFA_ADJUST_CFA: + pat = XEXP (note, 0); + if (pat == NULL) + pat = PATTERN (insn); + process_cfa_adjust_cfa (asm_out_file, pat, insn, unwind, frame); + handled_one = true; + break; - case PARALLEL: - { - int par_index; - int limit = XVECLEN (pat, 0); - for (par_index = 0; par_index < limit; par_index++) - { - rtx x = XVECEXP (pat, 0, par_index); - if (GET_CODE (x) == SET) - process_set (asm_out_file, x, insn, unwind, frame); - } - break; - } + case REG_CFA_OFFSET: + pat = XEXP (note, 0); + if (pat == NULL) + pat = PATTERN (insn); + process_cfa_offset (asm_out_file, pat, unwind); + handled_one = true; + break; - default: - gcc_unreachable (); - } - } + case REG_CFA_REGISTER: + pat = XEXP (note, 0); + if (pat == NULL) + pat = PATTERN (insn); + process_cfa_register (asm_out_file, pat, unwind); + handled_one = true; + break; + + case REG_FRAME_RELATED_EXPR: + case REG_CFA_DEF_CFA: + case REG_CFA_EXPRESSION: + case REG_CFA_RESTORE: + case REG_CFA_SET_VDRAP: + /* Not used in the ia64 port. */ + gcc_unreachable (); + + default: + /* Not a frame-related note. */ + break; + } + + /* All REG_FRAME_RELATED_P insns, besides ALLOC, are marked with the + explicit action to take. No guessing required. */ + gcc_assert (handled_one); } /* Implement TARGET_ASM_EMIT_EXCEPT_PERSONALITY. */ diff --git a/gcc/config/mcore/mcore.c b/gcc/config/mcore/mcore.c index b81a8b939e5..ce58827de3e 100644 --- a/gcc/config/mcore/mcore.c +++ b/gcc/config/mcore/mcore.c @@ -46,11 +46,6 @@ #include "target-def.h" #include "df.h" -/* Maximum size we are allowed to grow the stack in a single operation. - If we want more, we must do it in increments of at most this size. - If this value is 0, we don't check at all. */ -int mcore_stack_increment = STACK_UNITS_MAXSTEP; - /* For dumping information about frame sizes. */ char * mcore_current_function_name = 0; long mcore_current_compilation_timestamp = 0; diff --git a/gcc/config/mcore/mcore.opt b/gcc/config/mcore/mcore.opt index c445237301a..8e465d3a08c 100644 --- a/gcc/config/mcore/mcore.opt +++ b/gcc/config/mcore/mcore.opt @@ -63,8 +63,11 @@ mslow-bytes Target Report Mask(SLOW_BYTES) Prefer word accesses over byte accesses +; Maximum size we are allowed to grow the stack in a single operation. +; If we want more, we must do it in increments of at most this size. +; If this value is 0, we don't check at all. mstack-increment= -Target RejectNegative Joined UInteger Var(mcore_stack_increment) VarExists +Target RejectNegative Joined UInteger Var(mcore_stack_increment) Init(STACK_UNITS_MAXSTEP) Set the maximum amount for a single stack increment operation mwide-bitfields diff --git a/gcc/config/mips/mips.c b/gcc/config/mips/mips.c index d26990e593b..56e4f2da16f 100644 --- a/gcc/config/mips/mips.c +++ b/gcc/config/mips/mips.c @@ -13025,6 +13025,10 @@ static const struct mips_builtin_description mips_builtins[] = { DIRECT_NO_TARGET_BUILTIN (cache, MIPS_VOID_FTYPE_SI_CVPOINTER, cache) }; +/* Index I is the function declaration for mips_builtins[I], or null if the + function isn't defined on this target. */ +static GTY(()) tree mips_builtin_decls[ARRAY_SIZE (mips_builtins)]; + /* MODE is a vector mode whose elements have type TYPE. Return the type of the vector itself. */ @@ -13141,12 +13145,23 @@ mips_init_builtins (void) { d = &mips_builtins[i]; if (d->avail ()) - add_builtin_function (d->name, - mips_build_function_type (d->function_type), - i, BUILT_IN_MD, NULL, NULL); + mips_builtin_decls[i] + = add_builtin_function (d->name, + mips_build_function_type (d->function_type), + i, BUILT_IN_MD, NULL, NULL); } } +/* Implement TARGET_BUILTIN_DECL. */ + +static tree +mips_builtin_decl (unsigned int code, bool initialize_p ATTRIBUTE_UNUSED) +{ + if (code >= ARRAY_SIZE (mips_builtins)) + return error_mark_node; + return mips_builtin_decls[code]; +} + /* Take argument ARGNO from EXP's argument list and convert it into a form suitable for input operand OPNO of instruction ICODE. Return the value. */ @@ -16519,6 +16534,8 @@ mips_shift_truncation_mask (enum machine_mode mode) #undef TARGET_INIT_BUILTINS #define TARGET_INIT_BUILTINS mips_init_builtins +#undef TARGET_BUILTIN_DECL +#define TARGET_BUILTIN_DECL mips_builtin_decl #undef TARGET_EXPAND_BUILTIN #define TARGET_EXPAND_BUILTIN mips_expand_builtin diff --git a/gcc/config/picochip/picochip.md b/gcc/config/picochip/picochip.md index 6186eaa880b..b274c1ac77e 100644 --- a/gcc/config/picochip/picochip.md +++ b/gcc/config/picochip/picochip.md @@ -622,7 +622,7 @@ ; Match a branch instruction, created from a tstport/cbranch split. ; We use a "use" clause so GCC doesnt try to use this pattern generally. -(define_insn "*branch" +(define_insn "branch" [(set (pc) (if_then_else (match_operator 2 "comparison_operator" @@ -2511,22 +2511,38 @@ ;;============================================================================ ;; Define expand seems to consider the resulting two instructions to be -;; independent. It was moving the actual copy instruction further down -;; with a call instruction in between. The call was clobbering the CC -;; and hence the cond_copy was wrong. With a split, it works correctly. +;; independent. With a split, guarded by reload, it works correctly. (define_expand "movhicc" - [(set (reg:CC CC_REGNUM) (match_operand 1 "comparison_operator" "")) - (parallel [(set (match_operand:HI 0 "register_operand" "=r,r") - (if_then_else:HI (match_op_dup:HI 1 [(reg:CC CC_REGNUM) (const_int 0)]) - (match_operand:HI 2 "picochip_register_or_immediate_operand" "0,0") - (match_operand:HI 3 "picochip_register_or_immediate_operand" "r,i"))) - (use (match_dup 4))])] + [(set (match_operand:HI 0 "register_operand" "=r,r") + (if_then_else:HI (match_operand:HI 1 "" "") + (match_operand:HI 2 "register_operand" "0,0") + (match_operand:HI 3 "picochip_register_or_immediate_operand" "r,i")))] "" {if (!picochip_check_conditional_copy (operands)) FAIL; operands[4] = GEN_INT(GET_CODE(operands[1])); }) +(define_insn_and_split "*checked_movhicc" + [(set (match_operand:HI 0 "register_operand" "=r,r") + (if_then_else:HI (match_operator 1 "picochip_peephole_comparison_operator" + [(match_operand:HI 4 "register_operand" "r,r") + (match_operand:HI 5 "picochip_comparison_operand" "r,i")]) + (match_operand:HI 2 "register_operand" "0,0") + (match_operand:HI 3 "picochip_register_or_immediate_operand" "r,i")))] + "" + "#" + "reload_completed" + [(set (reg:CC CC_REGNUM) (match_dup 1)) + (parallel [(set (match_operand:HI 0 "register_operand" "=r,r") + (if_then_else:HI (match_op_dup:HI 1 [(reg:CC CC_REGNUM) (const_int 0)]) + (match_operand:HI 2 "picochip_register_or_immediate_operand" "0,0") + (match_operand:HI 3 "picochip_register_or_immediate_operand" "r,i"))) + (use (match_dup 6))])] + "{ + operands[6] = GEN_INT(GET_CODE(operands[0])); + }") + ;; We dont do any checks here. But this pattern is used only when movhicc ;; was checked. Put a "use" clause to make sure. (define_insn "*conditional_copy" @@ -2534,7 +2550,7 @@ (if_then_else:HI (match_operator:HI 4 "picochip_peephole_comparison_operator" [(reg:CC CC_REGNUM) (const_int 0)]) - (match_operand:HI 1 "picochip_register_or_immediate_operand" "0,0") + (match_operand:HI 1 "register_operand" "0,0") (match_operand:HI 2 "picochip_register_or_immediate_operand" "r,i"))) (use (match_operand:HI 3 "const_int_operand" ""))] "" diff --git a/gcc/config/rs6000/rs6000-protos.h b/gcc/config/rs6000/rs6000-protos.h index c18899448ee..a5e055ed3cf 100644 --- a/gcc/config/rs6000/rs6000-protos.h +++ b/gcc/config/rs6000/rs6000-protos.h @@ -87,7 +87,6 @@ extern int extract_ME (rtx); extern void rs6000_output_function_entry (FILE *, const char *); extern void print_operand (FILE *, rtx, int); extern void print_operand_address (FILE *, rtx); -extern bool rs6000_output_addr_const_extra (FILE *, rtx); extern enum rtx_code rs6000_reverse_condition (enum machine_mode, enum rtx_code); extern void rs6000_emit_sISEL (enum machine_mode, rtx[]); diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c index 4b874399ac7..5a3e333ffbe 100644 --- a/gcc/config/rs6000/rs6000.c +++ b/gcc/config/rs6000/rs6000.c @@ -996,6 +996,7 @@ static tree rs6000_builtin_vectorized_libmass (tree, tree, tree); static tree rs6000_builtin_vectorized_function (tree, tree, tree); static int rs6000_savres_strategy (rs6000_stack_t *, bool, int, int); static void rs6000_restore_saved_cr (rtx, int); +static bool rs6000_output_addr_const_extra (FILE *, rtx); static void rs6000_output_function_prologue (FILE *, HOST_WIDE_INT); static void rs6000_output_function_epilogue (FILE *, HOST_WIDE_INT); static void rs6000_output_mi_thunk (FILE *, tree, HOST_WIDE_INT, HOST_WIDE_INT, @@ -1432,6 +1433,9 @@ static const struct attribute_spec rs6000_attribute_table[] = #undef TARGET_ASM_FUNCTION_EPILOGUE #define TARGET_ASM_FUNCTION_EPILOGUE rs6000_output_function_epilogue +#undef TARGET_ASM_OUTPUT_ADDR_CONST_EXTRA +#define TARGET_ASM_OUTPUT_ADDR_CONST_EXTRA rs6000_output_addr_const_extra + #undef TARGET_LEGITIMIZE_ADDRESS #define TARGET_LEGITIMIZE_ADDRESS rs6000_legitimize_address @@ -5485,7 +5489,7 @@ virtual_stack_registers_memory_p (rtx op) return false; return (regnum >= FIRST_VIRTUAL_REGISTER - && regnum <= LAST_VIRTUAL_REGISTER); + && regnum <= LAST_VIRTUAL_POINTER_REGISTER); } static bool @@ -7028,46 +7032,6 @@ rs6000_eliminate_indexed_memrefs (rtx operands[2]) copy_addr_to_reg (XEXP (operands[1], 0))); } -/* Return true if OP, a SYMBOL_REF, should be considered local when - generating -mcmodel=medium code. */ - -static bool -toc_relative_ok (rtx op) -{ - tree decl; - - if (!SYMBOL_REF_LOCAL_P (op)) - return false; - - /* This is a bit hard to explain. When building shared libraries, - you are supposed to pass -fpic or -fPIC to the compiler. - -fpic/-fPIC not only generate position independent code but also - generate code that supports ELF shared library global function - or variable overriding. ppc64 is always PIC and at least some of - the ELF shared libaray semantics of global variables happen to be - supported without -fpic/-fPIC. So people may not be careful - about using -fPIC for shared libs. - With -mcmodel=medium this situation changes. A shared library - built without -fpic/-fPIC requires text relocs for global var - access (and would fail to load since glibc ld.so doesn't support - the required dynamic relocs). So avoid this potential - problem by using -mcmodel=large access for global vars, unless - we know we are compiling for an executable. */ - if (flag_pie) - return true; - - decl = SYMBOL_REF_DECL (op); - if (!decl || !DECL_P (decl)) - return true; - if (!TREE_PUBLIC (decl)) - return true; - if (DECL_VISIBILITY (decl) != VISIBILITY_DEFAULT) - return true; - - /* If we get here we must have a global var. See binds_local_p. */ - return flag_whole_program; -} - /* Return true if memory accesses to DECL are known to never straddle a 32k boundary. */ @@ -7423,7 +7387,7 @@ rs6000_emit_move (rtx dest, rtx source, enum machine_mode mode) || (TARGET_CMODEL == CMODEL_MEDIUM && GET_CODE (operands[1]) == SYMBOL_REF && !CONSTANT_POOL_ADDRESS_P (operands[1]) - && toc_relative_ok (operands[1]) + && SYMBOL_REF_LOCAL_P (operands[1]) && offsettable_ok_by_alignment (SYMBOL_REF_DECL (operands[1])))) { rtx reg = NULL_RTX; @@ -16026,9 +15990,9 @@ print_operand_address (FILE *file, rtx x) gcc_unreachable (); } -/* Implement OUTPUT_ADDR_CONST_EXTRA for address X. */ +/* Implement TARGET_OUTPUT_ADDR_CONST_EXTRA. */ -bool +static bool rs6000_output_addr_const_extra (FILE *file, rtx x) { if (GET_CODE (x) == UNSPEC) diff --git a/gcc/config/rs6000/rs6000.h b/gcc/config/rs6000/rs6000.h index b12ed819ab8..24edf6cb98c 100644 --- a/gcc/config/rs6000/rs6000.h +++ b/gcc/config/rs6000/rs6000.h @@ -2411,12 +2411,6 @@ extern char rs6000_reg_names[][8]; /* register names (0 vs. %r0). */ #define PRINT_OPERAND_ADDRESS(FILE, ADDR) print_operand_address (FILE, ADDR) -#define OUTPUT_ADDR_CONST_EXTRA(STREAM, X, FAIL) \ - do \ - if (!rs6000_output_addr_const_extra (STREAM, X)) \ - goto FAIL; \ - while (0) - /* uncomment for disabling the corresponding default options */ /* #define MACHINE_no_sched_interblock */ /* #define MACHINE_no_sched_speculative */ diff --git a/gcc/config/rs6000/vxworks.h b/gcc/config/rs6000/vxworks.h index c1198141088..1b23835959f 100644 --- a/gcc/config/rs6000/vxworks.h +++ b/gcc/config/rs6000/vxworks.h @@ -44,7 +44,9 @@ along with GCC; see the file COPYING3. If not see \ /* C89 namespace violation! */ \ builtin_define ("CPU_FAMILY=PPC"); \ - } \ + \ + VXWORKS_OS_CPP_BUILTINS (); \ + } \ while (0) /* Only big endian PPC is supported by VxWorks. */ diff --git a/gcc/config/rx/rx.c b/gcc/config/rx/rx.c index 22992732c9a..a932eb5bef0 100644 --- a/gcc/config/rx/rx.c +++ b/gcc/config/rx/rx.c @@ -1905,7 +1905,7 @@ rx_expand_builtin_mvtipl (rtx arg) if (rx_cpu_type == RX610) return NULL_RTX; - if (! CONST_INT_P (arg) || ! IN_RANGE (arg, 0, (1 << 4) - 1)) + if (! CONST_INT_P (arg) || ! IN_RANGE (INTVAL (arg), 0, (1 << 4) - 1)) return NULL_RTX; emit_insn (gen_mvtipl (arg)); @@ -1974,6 +1974,31 @@ rx_expand_builtin_round (rtx arg, rtx target) return target; } +static int +valid_psw_flag (rtx op, char *which) +{ + static int mvtc_inform_done = 0; + + if (GET_CODE (op) == CONST_INT) + switch (INTVAL (op)) + { + case 0: case 'c': case 'C': + case 1: case 'z': case 'Z': + case 2: case 's': case 'S': + case 3: case 'o': case 'O': + case 8: case 'i': case 'I': + case 9: case 'u': case 'U': + return 1; + } + + error ("__builtin_rx_%s takes 'C', 'Z', 'S', 'O', 'I', or 'U'", which); + if (!mvtc_inform_done) + error ("use __builtin_rx_mvtc (0, ... ) to write arbitrary values to PSW"); + mvtc_inform_done = 1; + + return 0; +} + static rtx rx_expand_builtin (tree exp, rtx target, @@ -1989,10 +2014,14 @@ rx_expand_builtin (tree exp, switch (fcode) { case RX_BUILTIN_BRK: emit_insn (gen_brk ()); return NULL_RTX; - case RX_BUILTIN_CLRPSW: return rx_expand_void_builtin_1_arg - (op, gen_clrpsw, false); - case RX_BUILTIN_SETPSW: return rx_expand_void_builtin_1_arg - (op, gen_setpsw, false); + case RX_BUILTIN_CLRPSW: + if (!valid_psw_flag (op, "clrpsw")) + return NULL_RTX; + return rx_expand_void_builtin_1_arg (op, gen_clrpsw, false); + case RX_BUILTIN_SETPSW: + if (!valid_psw_flag (op, "setpsw")) + return NULL_RTX; + return rx_expand_void_builtin_1_arg (op, gen_setpsw, false); case RX_BUILTIN_INT: return rx_expand_void_builtin_1_arg (op, gen_int, false); case RX_BUILTIN_MACHI: return rx_expand_builtin_mac (exp, gen_machi); diff --git a/gcc/config/rx/rx.md b/gcc/config/rx/rx.md index 0ad53637596..e0271d66322 100644 --- a/gcc/config/rx/rx.md +++ b/gcc/config/rx/rx.md @@ -1369,7 +1369,7 @@ ) (define_insn "bitclr" - [(set:SI (match_operand:SI 0 "register_operand" "+r") + [(set:SI (match_operand:SI 0 "register_operand" "=r") (and:SI (match_operand:SI 1 "register_operand" "0") (not:SI (ashift:SI (const_int 1) (match_operand:SI 2 "nonmemory_operand" "ri")))))] @@ -1379,7 +1379,7 @@ ) (define_insn "bitclr_in_memory" - [(set:QI (match_operand:QI 0 "memory_operand" "+m") + [(set:QI (match_operand:QI 0 "memory_operand" "=m") (and:QI (match_operand:QI 1 "memory_operand" "0") (not:QI (ashift:QI (const_int 1) (match_operand:QI 2 "nonmemory_operand" "ri")))))] @@ -1803,7 +1803,7 @@ ;; Clear Processor Status Word (define_insn "clrpsw" - [(unspec:SI [(match_operand:SI 0 "immediate_operand" "i")] + [(unspec_volatile:SI [(match_operand:SI 0 "immediate_operand" "i")] UNSPEC_BUILTIN_CLRPSW) (clobber (reg:CC CC_REG))] "" @@ -1813,7 +1813,7 @@ ;; Set Processor Status Word (define_insn "setpsw" - [(unspec:SI [(match_operand:SI 0 "immediate_operand" "i")] + [(unspec_volatile:SI [(match_operand:SI 0 "immediate_operand" "i")] UNSPEC_BUILTIN_SETPSW) (clobber (reg:CC CC_REG))] "" @@ -1824,7 +1824,7 @@ ;; Move from control register (define_insn "mvfc" [(set (match_operand:SI 0 "register_operand" "=r") - (unspec:SI [(match_operand:SI 1 "immediate_operand" "i")] + (unspec_volatile:SI [(match_operand:SI 1 "immediate_operand" "i")] UNSPEC_BUILTIN_MVFC))] "" "mvfc\t%C1, %0" @@ -1833,7 +1833,7 @@ ;; Move to control register (define_insn "mvtc" - [(unspec:SI [(match_operand:SI 0 "immediate_operand" "i,i") + [(unspec_volatile:SI [(match_operand:SI 0 "immediate_operand" "i,i") (match_operand:SI 1 "nonmemory_operand" "r,i")] UNSPEC_BUILTIN_MVTC)] "" @@ -1848,7 +1848,7 @@ ;; Move to interrupt priority level (define_insn "mvtipl" - [(unspec:SI [(match_operand:SI 0 "immediate_operand" "Uint04")] + [(unspec_volatile:SI [(match_operand:SI 0 "immediate_operand" "Uint04")] UNSPEC_BUILTIN_MVTIPL)] "" "mvtipl\t%0" diff --git a/gcc/config/sparc/constraints.md b/gcc/config/sparc/constraints.md index ee0fbbda69a..73c4087d904 100644 --- a/gcc/config/sparc/constraints.md +++ b/gcc/config/sparc/constraints.md @@ -35,10 +35,10 @@ ;; In the non-V9 case, coerce V9 'e' class to 'f', so we can use 'e' in the ;; MD file for V8 and V9. -(define_register_constraint "e" "TARGET_V9 ? EXTRA_FP_REGS : FP_REGS" +(define_register_constraint "e" "(TARGET_FPU ? (TARGET_V9 ? EXTRA_FP_REGS : FP_REGS) : NO_REGS)" "Any floating-point register") -(define_register_constraint "f" "FP_REGS" +(define_register_constraint "f" "(TARGET_FPU ? FP_REGS : NO_REGS)" "Lower floating-point register") (define_register_constraint "h" "(TARGET_V9 && TARGET_V8PLUS ? I64_REGS : NO_REGS)" diff --git a/gcc/config/sparc/linux.h b/gcc/config/sparc/linux.h index 530a6ae7065..1272d2aba7d 100644 --- a/gcc/config/sparc/linux.h +++ b/gcc/config/sparc/linux.h @@ -107,7 +107,8 @@ along with GCC; see the file COPYING3. If not see %{Ym,*} \ %{Wa,*:%*} \ -s \ -%{fpic|fPIC|fpie|fPIE|findirect-dispatch:-K PIC} \ +%{fpic|fPIC|fpie|fPIE:-K PIC} \ +%{!.c:%{findirect-dispatch:-K PIC}} \ %(asm_cpu) %(asm_relax)" #undef ASM_OUTPUT_ALIGNED_LOCAL diff --git a/gcc/config/sparc/linux64.h b/gcc/config/sparc/linux64.h index 369c13c8e3c..d8a242758dd 100644 --- a/gcc/config/sparc/linux64.h +++ b/gcc/config/sparc/linux64.h @@ -236,7 +236,8 @@ along with GCC; see the file COPYING3. If not see %{Ym,*} \ %{Wa,*:%*} \ -s \ -%{fpic|fPIC|fpie|fPIE|findirect-dispatch:-K PIC} \ +%{fpic|fPIC|fpie|fPIE:-K PIC} \ +%{!.c:%{findirect-dispatch:-K PIC}} \ %{mlittle-endian:-EL} \ %(asm_cpu) %(asm_arch) %(asm_relax)" diff --git a/gcc/config/t-darwin b/gcc/config/t-darwin index b538ccfa405..70c0da54bbc 100644 --- a/gcc/config/t-darwin +++ b/gcc/config/t-darwin @@ -36,7 +36,7 @@ darwin-f.o: $(srcdir)/config/darwin-f.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(srcdir)/config/darwin-f.c $(PREPROCESSOR_DEFINES) darwin-driver.o: $(srcdir)/config/darwin-driver.c \ - $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(GCC_H) + $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(GCC_H) opts.h $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \ $(srcdir)/config/darwin-driver.c diff --git a/gcc/config/v850/v850.c b/gcc/config/v850/v850.c index 49b8e756e92..dc047a2056c 100644 --- a/gcc/config/v850/v850.c +++ b/gcc/config/v850/v850.c @@ -48,49 +48,12 @@ #define streq(a,b) (strcmp (a, b) == 0) #endif -/* Function prototypes for stupid compilers: */ -static bool v850_handle_option (size_t, const char *, int); -static void v850_option_optimization (int, int); -static void const_double_split (rtx, HOST_WIDE_INT *, HOST_WIDE_INT *); -static int const_costs_int (HOST_WIDE_INT, int); -static int const_costs (rtx, enum rtx_code); -static bool v850_rtx_costs (rtx, int, int, int *, bool); -static void substitute_ep_register (rtx, rtx, int, int, rtx *, rtx *); -static void v850_reorg (void); -static int ep_memory_offset (enum machine_mode, int); -static void v850_set_data_area (tree, v850_data_area); -static tree v850_handle_interrupt_attribute (tree *, tree, tree, int, bool *); -static tree v850_handle_data_area_attribute (tree *, tree, tree, int, bool *); -static void v850_insert_attributes (tree, tree *); -static void v850_asm_init_sections (void); -static section *v850_select_section (tree, int, unsigned HOST_WIDE_INT); -static void v850_encode_data_area (tree, rtx); -static void v850_encode_section_info (tree, rtx, int); -static int v850_issue_rate (void); -static bool v850_return_in_memory (const_tree, const_tree); -static rtx v850_function_value (const_tree, const_tree, bool); -static void v850_setup_incoming_varargs (CUMULATIVE_ARGS *, enum machine_mode, - tree, int *, int); -static bool v850_pass_by_reference (CUMULATIVE_ARGS *, enum machine_mode, - const_tree, bool); -static int v850_arg_partial_bytes (CUMULATIVE_ARGS *, enum machine_mode, - tree, bool); -static bool v850_strict_argument_naming (CUMULATIVE_ARGS *); -static rtx v850_function_arg (CUMULATIVE_ARGS *, enum machine_mode, - const_tree, bool); -static void v850_function_arg_advance (CUMULATIVE_ARGS *, enum machine_mode, - const_tree, bool); -static bool v850_can_eliminate (const int, const int); -static void v850_asm_trampoline_template (FILE *); -static void v850_trampoline_init (rtx, tree, rtx); -static void v850_print_operand (FILE *, rtx, int); static void v850_print_operand_address (FILE *, rtx); -static bool v850_print_operand_punct_valid_p (unsigned char code); /* Information about the various small memory areas. */ struct small_memory_info small_memory[ (int)SMALL_MEMORY_max ] = { - /* name max physical max */ + /* Name Max Physical max. */ { "tda", 0, 256 }, { "sda", 0, 65536 }, { "zda", 0, 32768 }, @@ -113,116 +76,11 @@ rtx v850_compare_op0, v850_compare_op1; /* Whether current function is an interrupt handler. */ static int v850_interrupt_p = FALSE; -static GTY(()) section *rosdata_section; -static GTY(()) section *rozdata_section; -static GTY(()) section *tdata_section; -static GTY(()) section *zdata_section; -static GTY(()) section *zbss_section; - -/* V850 specific attributes. */ - -static const struct attribute_spec v850_attribute_table[] = -{ - /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */ - { "interrupt_handler", 0, 0, true, false, false, v850_handle_interrupt_attribute }, - { "interrupt", 0, 0, true, false, false, v850_handle_interrupt_attribute }, - { "sda", 0, 0, true, false, false, v850_handle_data_area_attribute }, - { "tda", 0, 0, true, false, false, v850_handle_data_area_attribute }, - { "zda", 0, 0, true, false, false, v850_handle_data_area_attribute }, - { NULL, 0, 0, false, false, false, NULL } -}; - - -/* Initialize the GCC target structure. */ -#undef TARGET_ASM_ALIGNED_HI_OP -#define TARGET_ASM_ALIGNED_HI_OP "\t.hword\t" - -#undef TARGET_PRINT_OPERAND -#define TARGET_PRINT_OPERAND v850_print_operand -#undef TARGET_PRINT_OPERAND_ADDRESS -#define TARGET_PRINT_OPERAND_ADDRESS v850_print_operand_address -#undef TARGET_PRINT_OPERAND_PUNCT_VALID_P -#define TARGET_PRINT_OPERAND_PUNCT_VALID_P v850_print_operand_punct_valid_p - -#undef TARGET_ATTRIBUTE_TABLE -#define TARGET_ATTRIBUTE_TABLE v850_attribute_table - -#undef TARGET_INSERT_ATTRIBUTES -#define TARGET_INSERT_ATTRIBUTES v850_insert_attributes - -#undef TARGET_ASM_SELECT_SECTION -#define TARGET_ASM_SELECT_SECTION v850_select_section - -/* The assembler supports switchable .bss sections, but - v850_select_section doesn't yet make use of them. */ -#undef TARGET_HAVE_SWITCHABLE_BSS_SECTIONS -#define TARGET_HAVE_SWITCHABLE_BSS_SECTIONS false - -#undef TARGET_ENCODE_SECTION_INFO -#define TARGET_ENCODE_SECTION_INFO v850_encode_section_info - -#undef TARGET_ASM_FILE_START_FILE_DIRECTIVE -#define TARGET_ASM_FILE_START_FILE_DIRECTIVE true - -#undef TARGET_DEFAULT_TARGET_FLAGS -#define TARGET_DEFAULT_TARGET_FLAGS (MASK_DEFAULT | MASK_APP_REGS) -#undef TARGET_HANDLE_OPTION -#define TARGET_HANDLE_OPTION v850_handle_option - -#undef TARGET_RTX_COSTS -#define TARGET_RTX_COSTS v850_rtx_costs - -#undef TARGET_ADDRESS_COST -#define TARGET_ADDRESS_COST hook_int_rtx_bool_0 - -#undef TARGET_MACHINE_DEPENDENT_REORG -#define TARGET_MACHINE_DEPENDENT_REORG v850_reorg - -#undef TARGET_SCHED_ISSUE_RATE -#define TARGET_SCHED_ISSUE_RATE v850_issue_rate - -#undef TARGET_PROMOTE_PROTOTYPES -#define TARGET_PROMOTE_PROTOTYPES hook_bool_const_tree_true - -#undef TARGET_RETURN_IN_MEMORY -#define TARGET_RETURN_IN_MEMORY v850_return_in_memory - -#undef TARGET_FUNCTION_VALUE -#define TARGET_FUNCTION_VALUE v850_function_value - -#undef TARGET_PASS_BY_REFERENCE -#define TARGET_PASS_BY_REFERENCE v850_pass_by_reference - -#undef TARGET_CALLEE_COPIES -#define TARGET_CALLEE_COPIES hook_bool_CUMULATIVE_ARGS_mode_tree_bool_true - -#undef TARGET_SETUP_INCOMING_VARARGS -#define TARGET_SETUP_INCOMING_VARARGS v850_setup_incoming_varargs - -#undef TARGET_ARG_PARTIAL_BYTES -#define TARGET_ARG_PARTIAL_BYTES v850_arg_partial_bytes - -#undef TARGET_FUNCTION_ARG -#define TARGET_FUNCTION_ARG v850_function_arg - -#undef TARGET_FUNCTION_ARG_ADVANCE -#define TARGET_FUNCTION_ARG_ADVANCE v850_function_arg_advance - -#undef TARGET_CAN_ELIMINATE -#define TARGET_CAN_ELIMINATE v850_can_eliminate - -#undef TARGET_ASM_TRAMPOLINE_TEMPLATE -#define TARGET_ASM_TRAMPOLINE_TEMPLATE v850_asm_trampoline_template -#undef TARGET_TRAMPOLINE_INIT -#define TARGET_TRAMPOLINE_INIT v850_trampoline_init - -#undef TARGET_STRICT_ARGUMENT_NAMING -#define TARGET_STRICT_ARGUMENT_NAMING v850_strict_argument_naming - -#undef TARGET_OPTION_OPTIMIZATION -#define TARGET_OPTION_OPTIMIZATION v850_option_optimization - -struct gcc_target targetm = TARGET_INITIALIZER; +static GTY(()) section * rosdata_section; +static GTY(()) section * rozdata_section; +static GTY(()) section * tdata_section; +static GTY(()) section * zdata_section; +static GTY(()) section * zbss_section; /* Set the maximum size of small memory area TYPE to the value given by VALUE. Return true if VALUE was syntactically correct. VALUE @@ -1120,7 +978,7 @@ v850_float_nz_comparison_operator (rtx op, enum machine_mode mode) } enum machine_mode -v850_select_cc_mode (enum rtx_code cond, rtx op0, rtx op1) +v850_select_cc_mode (enum rtx_code cond, rtx op0, rtx op1 ATTRIBUTE_UNUSED) { if (GET_MODE_CLASS (GET_MODE (op0)) == MODE_FLOAT) { @@ -2022,8 +1880,6 @@ expand_epilogue (void) && !interrupt_handler) { int alloc_stack = (4 * num_restore); - int restore_func_len; - int restore_normal_len; /* Don't bother checking if we don't actually save any space. */ if (use_prolog_function (num_restore, actual_fsize)) @@ -2222,6 +2078,9 @@ notice_update_cc (rtx body, rtx insn) /* Insn doesn't leave CC in a usable state. */ CC_STATUS_INIT; break; + + default: + break; } } @@ -3157,6 +3016,14 @@ v850_select_section (tree exp, return readonly_data_section; } +/* Worker function for TARGET_FUNCTION_VALUE_REGNO_P. */ + +static bool +v850_function_value_regno_p (const unsigned int regno) +{ + return (regno == 10); +} + /* Worker function for TARGET_RETURN_IN_MEMORY. */ static bool @@ -3168,7 +3035,7 @@ v850_return_in_memory (const_tree type, const_tree fntype ATTRIBUTE_UNUSED) /* Worker function for TARGET_FUNCTION_VALUE. */ -rtx +static rtx v850_function_value (const_tree valtype, const_tree fn_decl_or_type ATTRIBUTE_UNUSED, bool outgoing ATTRIBUTE_UNUSED) @@ -3233,4 +3100,111 @@ v850_issue_rate (void) { return (TARGET_V850E2_ALL? 2 : 1); } + +/* V850 specific attributes. */ + +static const struct attribute_spec v850_attribute_table[] = +{ + /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */ + { "interrupt_handler", 0, 0, true, false, false, v850_handle_interrupt_attribute }, + { "interrupt", 0, 0, true, false, false, v850_handle_interrupt_attribute }, + { "sda", 0, 0, true, false, false, v850_handle_data_area_attribute }, + { "tda", 0, 0, true, false, false, v850_handle_data_area_attribute }, + { "zda", 0, 0, true, false, false, v850_handle_data_area_attribute }, + { NULL, 0, 0, false, false, false, NULL } +}; + +/* Initialize the GCC target structure. */ +#undef TARGET_ASM_ALIGNED_HI_OP +#define TARGET_ASM_ALIGNED_HI_OP "\t.hword\t" + +#undef TARGET_PRINT_OPERAND +#define TARGET_PRINT_OPERAND v850_print_operand +#undef TARGET_PRINT_OPERAND_ADDRESS +#define TARGET_PRINT_OPERAND_ADDRESS v850_print_operand_address +#undef TARGET_PRINT_OPERAND_PUNCT_VALID_P +#define TARGET_PRINT_OPERAND_PUNCT_VALID_P v850_print_operand_punct_valid_p + +#undef TARGET_ATTRIBUTE_TABLE +#define TARGET_ATTRIBUTE_TABLE v850_attribute_table + +#undef TARGET_INSERT_ATTRIBUTES +#define TARGET_INSERT_ATTRIBUTES v850_insert_attributes + +#undef TARGET_ASM_SELECT_SECTION +#define TARGET_ASM_SELECT_SECTION v850_select_section + +/* The assembler supports switchable .bss sections, but + v850_select_section doesn't yet make use of them. */ +#undef TARGET_HAVE_SWITCHABLE_BSS_SECTIONS +#define TARGET_HAVE_SWITCHABLE_BSS_SECTIONS false + +#undef TARGET_ENCODE_SECTION_INFO +#define TARGET_ENCODE_SECTION_INFO v850_encode_section_info + +#undef TARGET_ASM_FILE_START_FILE_DIRECTIVE +#define TARGET_ASM_FILE_START_FILE_DIRECTIVE true + +#undef TARGET_DEFAULT_TARGET_FLAGS +#define TARGET_DEFAULT_TARGET_FLAGS (MASK_DEFAULT | MASK_APP_REGS) +#undef TARGET_HANDLE_OPTION +#define TARGET_HANDLE_OPTION v850_handle_option + +#undef TARGET_RTX_COSTS +#define TARGET_RTX_COSTS v850_rtx_costs + +#undef TARGET_ADDRESS_COST +#define TARGET_ADDRESS_COST hook_int_rtx_bool_0 + +#undef TARGET_MACHINE_DEPENDENT_REORG +#define TARGET_MACHINE_DEPENDENT_REORG v850_reorg + +#undef TARGET_SCHED_ISSUE_RATE +#define TARGET_SCHED_ISSUE_RATE v850_issue_rate + +#undef TARGET_FUNCTION_VALUE_REGNO_P +#define TARGET_FUNCTION_VALUE_REGNO_P v850_function_value_regno_p +#undef TARGET_FUNCTION_VALUE +#define TARGET_FUNCTION_VALUE v850_function_value + +#undef TARGET_PROMOTE_PROTOTYPES +#define TARGET_PROMOTE_PROTOTYPES hook_bool_const_tree_true + +#undef TARGET_RETURN_IN_MEMORY +#define TARGET_RETURN_IN_MEMORY v850_return_in_memory + +#undef TARGET_PASS_BY_REFERENCE +#define TARGET_PASS_BY_REFERENCE v850_pass_by_reference + +#undef TARGET_CALLEE_COPIES +#define TARGET_CALLEE_COPIES hook_bool_CUMULATIVE_ARGS_mode_tree_bool_true + +#undef TARGET_SETUP_INCOMING_VARARGS +#define TARGET_SETUP_INCOMING_VARARGS v850_setup_incoming_varargs + +#undef TARGET_ARG_PARTIAL_BYTES +#define TARGET_ARG_PARTIAL_BYTES v850_arg_partial_bytes + +#undef TARGET_FUNCTION_ARG +#define TARGET_FUNCTION_ARG v850_function_arg + +#undef TARGET_FUNCTION_ARG_ADVANCE +#define TARGET_FUNCTION_ARG_ADVANCE v850_function_arg_advance + +#undef TARGET_CAN_ELIMINATE +#define TARGET_CAN_ELIMINATE v850_can_eliminate + +#undef TARGET_ASM_TRAMPOLINE_TEMPLATE +#define TARGET_ASM_TRAMPOLINE_TEMPLATE v850_asm_trampoline_template +#undef TARGET_TRAMPOLINE_INIT +#define TARGET_TRAMPOLINE_INIT v850_trampoline_init + +#undef TARGET_STRICT_ARGUMENT_NAMING +#define TARGET_STRICT_ARGUMENT_NAMING v850_strict_argument_naming + +#undef TARGET_OPTION_OPTIMIZATION +#define TARGET_OPTION_OPTIMIZATION v850_option_optimization + +struct gcc_target targetm = TARGET_INITIALIZER; + #include "gt-v850.h" diff --git a/gcc/config/v850/v850.h b/gcc/config/v850/v850.h index 9ae0784af56..2afa3cb22a6 100644 --- a/gcc/config/v850/v850.h +++ b/gcc/config/v850/v850.h @@ -596,10 +596,6 @@ struct cum_arg { int nbytes; int anonymous_args; }; #define LIBCALL_VALUE(MODE) \ gen_rtx_REG (MODE, 10) -/* 1 if N is a possible register number for a function value. */ - -#define FUNCTION_VALUE_REGNO_P(N) ((N) == 10) - #define DEFAULT_PCC_STRUCT_RETURN 0 /* EXIT_IGNORE_STACK should be nonzero if, when returning from a function, @@ -1071,6 +1067,10 @@ extern union tree_node * GHS_current_section_names [(int) COUNT_OF_GHS_SECTION_K #define TARGET_ASM_INIT_SECTIONS v850_asm_init_sections -#endif /* ! GCC_V850_H */ - +/* Define this so that the cc1plus will not think that system header files + need an implicit 'extern "C" { ... }' assumed. This breaks testing C++ + in a build directory where the libstdc++ header files are found via a + -isystem <path-to-build-dir>. */ +#define NO_IMPLICIT_EXTERN_C +#endif /* ! GCC_V850_H */ diff --git a/gcc/config/vms/t-vms b/gcc/config/vms/t-vms index 132a53b205c..75756a234d9 100644 --- a/gcc/config/vms/t-vms +++ b/gcc/config/vms/t-vms @@ -24,15 +24,14 @@ LIMITS_H_TEST = false # Under VMS, directory names cannot contain dots. version:=$(shell echo $(BASEVER_c) | sed -e 's/\./_/g') -# Temporary restriction: VMS_EXTRA_PARTS must be compiled by DEC C. -#VMS_EXTRA_PARTS=vcrt0.o pcrt0.o -VMS_EXTRA_PARTS= - -DECC=`echo $(CC) | sed -e 's/xgcc -B.*/decc$(exeext)/' -e 's/^gcc/decc/' -e 's/^decc/.\/decc/' -e 's/\(.*\)-gcc/\1-decc/'` +VMS_EXTRA_PARTS=vcrt0.o pcrt0.o # Assemble startup files. -$(T)vcrt0.o: $(CRT0_S) $(GCC_PASSES) - $(DECC) -c /names=as_is $(srcdir)/config/vms/vms-crt0.c -o $(T)vcrt0.o +$(T)vcrt0.o: $(srcdir)/config/vms/vms-ucrt0.c $(GCC_PASSES) + $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(MULTILIB_CFLAGS) $(INCLUDES) \ + -c -o $(T)vcrt0.o $(srcdir)/config/vms/vms-ucrt0.c + +$(T)pcrt0.o: $(srcdir)/config/vms/vms-ucrt0.c $(GCC_PASSES) + $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(MULTILIB_CFLAGS) $(INCLUDES) \ + -c -o $(T)pcrt0.o -DCRT0_POSIX_EXIT $(srcdir)/config/vms/vms-ucrt0.c -$(T)pcrt0.o: $(CRT0_S) $(GCC_PASSES) - $(DECC) -c /names=as_is $(srcdir)/config/vms/vms-psxcrt0.c -o $(T)pcrt0.o diff --git a/gcc/config/vms/t-vms64 b/gcc/config/vms/t-vms64 deleted file mode 100644 index 2fe00692fb5..00000000000 --- a/gcc/config/vms/t-vms64 +++ /dev/null @@ -1,27 +0,0 @@ -# Copyright (C) 2009 -# Free Software Foundation, Inc. -# -# This file is part of GCC. -# -# GCC is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 3, or (at your option) -# any later version. -# -# GCC is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with GCC; see the file COPYING3. If not see -# <http://www.gnu.org/licenses/>. - -# Assemble startup files. -$(T)vcrt0.o: $(CRT0_S) $(GCC_PASSES) - $(DECC) -c /names=as_is /pointer_size=64 \ - $(srcdir)/config/vms/vms-crt0-64.c -o $(T)vcrt0.o - -$(T)pcrt0.o: $(CRT0_S) $(GCC_PASSES) - $(DECC) -c /names=as_is /pointer_size=64 \ - $(srcdir)/config/vms/vms-psxcrt0-64.c -o $(T)pcrt0.o diff --git a/gcc/config/vms/vms-crt0-64.c b/gcc/config/vms/vms-crt0-64.c deleted file mode 100644 index ec59d81d6af..00000000000 --- a/gcc/config/vms/vms-crt0-64.c +++ /dev/null @@ -1,95 +0,0 @@ -/* VMS 64bit crt0 returning VMS style condition codes . - Copyright (C) 2001, 2009 Free Software Foundation, Inc. - Contributed by Douglas B. Rupp (rupp@gnat.com). - - This file is part of GCC. - - GCC is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3, or (at your option) - any later version. - - GCC is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - Under Section 7 of GPL version 3, you are granted additional - permissions described in the GCC Runtime Library Exception, version - 3.1, as published by the Free Software Foundation. - - You should have received a copy of the GNU General Public License and - a copy of the GCC Runtime Library Exception along with this program; - see the files COPYING3 and COPYING.RUNTIME respectively. If not, see - <http://www.gnu.org/licenses/>. */ - -#if !defined(__DECC) -You Lose! This file can only be compiled with DEC C. -#else - -/* This file can only be compiled with DEC C, due to the call to - lib$establish and the pragmas pointer_size. */ - -#pragma __pointer_size short - -#include <stdlib.h> -#include <string.h> -#include <ssdef.h> - -extern void decc$main (); - -extern int main (); - -static int -handler (sigargs, mechargs) - void *sigargs; - void *mechargs; -{ - return SS$_RESIGNAL; -} - -int -__main (arg1, arg2, arg3, image_file_desc, arg5, arg6) - void *arg1, *arg2, *arg3; - void *image_file_desc; - void *arg5, *arg6; -{ - int argc; - char **argv; - char **envp; - -#pragma __pointer_size long - - int i; - char **long_argv; - char **long_envp; - -#pragma __pointer_size short - - lib$establish (handler); - decc$main (arg1, arg2, arg3, image_file_desc, - arg5, arg6, &argc, &argv, &envp); - -#pragma __pointer_size long - - /* Reallocate argv with 64 bit pointers. */ - long_argv = (char **) _malloc32 (sizeof (char *) * (argc + 1)); - - for (i = 0; i < argc; i++) - long_argv[i] = (char *) _strdup32 (argv[i]); - - long_argv[argc] = (char *) 0; - - for (i = 0; envp[i]; i++); - long_envp = (char **) _malloc32 (sizeof (char *) * (i + 1)); - - for (i = 0; envp[i]; i++) - long_envp[i] = (char *) _strdup32 (envp[i]); - - long_envp[i] = (char *) 0; - -#pragma __pointer_size short - - return main (argc, long_argv, long_envp); -} -#endif diff --git a/gcc/config/vms/vms-crt0.c b/gcc/config/vms/vms-crt0.c deleted file mode 100644 index c0fdaaf16c6..00000000000 --- a/gcc/config/vms/vms-crt0.c +++ /dev/null @@ -1,66 +0,0 @@ -/* VMS crt0 returning VMS style condition codes . - Copyright (C) 2001, 2009 Free Software Foundation, Inc. - Contributed by Douglas B. Rupp (rupp@gnat.com). - - This file is part of GCC. - - GCC is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3, or (at your option) - any later version. - - GCC is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - Under Section 7 of GPL version 3, you are granted additional - permissions described in the GCC Runtime Library Exception, version - 3.1, as published by the Free Software Foundation. - - You should have received a copy of the GNU General Public License and - a copy of the GCC Runtime Library Exception along with this program; - see the files COPYING3 and COPYING.RUNTIME respectively. If not, see - <http://www.gnu.org/licenses/>. */ - -#if !defined(__DECC) -You Lose! This file can only be compiled with DEC C. -#else - -/* This file can only be compiled with DEC C, due to the call to - lib$establish. */ - -#include <stdlib.h> -#include <string.h> -#include <ssdef.h> - -extern void decc$main (); - -extern int main (); - -static int -handler (sigargs, mechargs) - void *sigargs; - void *mechargs; -{ - return SS$_RESIGNAL; -} - -int -__main (arg1, arg2, arg3, image_file_desc, arg5, arg6) - void *arg1, *arg2, *arg3; - void *image_file_desc; - void *arg5, *arg6; -{ - int argc; - char **argv; - char **envp; - - lib$establish (handler); - - decc$main(arg1, arg2, arg3, image_file_desc, arg5, arg6, - &argc, &argv, &envp); - - return main (argc, argv, envp); -} -#endif diff --git a/gcc/config/vms/vms-psxcrt0-64.c b/gcc/config/vms/vms-psxcrt0-64.c deleted file mode 100644 index 45afbc9a03d..00000000000 --- a/gcc/config/vms/vms-psxcrt0-64.c +++ /dev/null @@ -1,124 +0,0 @@ -/* VMS 64bit crt0 returning Unix style condition codes . - Copyright (C) 2001, 2009 Free Software Foundation, Inc. - Contributed by Douglas B. Rupp (rupp@gnat.com). - - This file is part of GCC. - - GCC is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3, or (at your option) - any later version. - - GCC is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - Under Section 7 of GPL version 3, you are granted additional - permissions described in the GCC Runtime Library Exception, version - 3.1, as published by the Free Software Foundation. - - You should have received a copy of the GNU General Public License and - a copy of the GCC Runtime Library Exception along with this program; - see the files COPYING3 and COPYING.RUNTIME respectively. If not, see - <http://www.gnu.org/licenses/>. */ - -#if !defined(__DECC) -You Lose! This file can only be compiled with DEC C. -#else - -/* This file can only be compiled with DEC C, due to the call to - lib$establish and the pragmas pointer_size. */ - -#pragma __pointer_size short - -#include <stdlib.h> -#include <string.h> -#include <ssdef.h> -#include <stsdef.h> -#include <errnodef.h> - -extern void decc$main (); -extern int main (); - -static int -handler (sigargs, mechargs) - void *sigargs; - void *mechargs; -{ - return SS$_RESIGNAL; -} - -int -__main (arg1, arg2, arg3, image_file_desc, arg5, arg6) - void *arg1, *arg2, *arg3; - void *image_file_desc; - void *arg5, *arg6; -{ - int argc; - char **argv; - char **envp; - -#pragma __pointer_size long - - int i; - char **long_argv; - char **long_envp; - int status; - -#pragma __pointer_size short - - lib$establish (handler); - decc$main (arg1, arg2, arg3, image_file_desc, - arg5, arg6, &argc, &argv, &envp); - -#pragma __pointer_size long - - /* Reallocate argv with 64 bit pointers. */ - long_argv = (char **) _malloc32 (sizeof (char *) * (argc + 1)); - - for (i = 0; i < argc; i++) - long_argv[i] = (char *) _strdup32 (argv[i]); - - long_argv[argc] = (char *) 0; - - for (i = 0; envp[i]; i++); - long_envp = (char **) _malloc32 (sizeof (char *) * (i + 1)); - - for (i = 0; envp[i]; i++) - long_envp[i] = (char *) _strdup32 (envp[i]); - - long_envp[i] = (char *) 0; - -#pragma __pointer_size short - - status = main (argc, long_argv, long_envp); - - /* Map into a range of 0 - 255. */ - status = status & 255; - - if (status > 0) - { - int save_status = status; - - status = C$_EXIT1 + ((status - 1) << STS$V_MSG_NO); - - /* An exit failure status requires a "severe" error. All status values - are defined in errno with a successful (1) severity but can be - changed to an error (2) severity by adding 1. In addition for - compatibility with UNIX exit() routines we inhibit a run-time error - message from being generated on exit(1). */ - - if (save_status == 1) - { - status++; - status |= STS$M_INHIB_MSG; - } - } - - if (status == 0) - status = SS$_NORMAL; - - return status; -} -#endif diff --git a/gcc/config/vms/vms-psxcrt0.c b/gcc/config/vms/vms-psxcrt0.c deleted file mode 100644 index 5ad5ddb0fd8..00000000000 --- a/gcc/config/vms/vms-psxcrt0.c +++ /dev/null @@ -1,94 +0,0 @@ -/* VMS crt0 returning Unix style condition codes . - Copyright (C) 2001, 2009 Free Software Foundation, Inc. - Contributed by Douglas B. Rupp (rupp@gnat.com). - - This file is part of GCC. - - GCC is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3, or (at your option) - any later version. - - GCC is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - Under Section 7 of GPL version 3, you are granted additional - permissions described in the GCC Runtime Library Exception, version - 3.1, as published by the Free Software Foundation. - - You should have received a copy of the GNU General Public License and - a copy of the GCC Runtime Library Exception along with this program; - see the files COPYING3 and COPYING.RUNTIME respectively. If not, see - <http://www.gnu.org/licenses/>. */ - -#if !defined(__DECC) -You Lose! This file can only be compiled with DEC C. -#else - -/* This file can only be compiled with DEC C, due to the call to - lib$establish. */ - -#include <stdlib.h> -#include <string.h> -#include <ssdef.h> -#include <stsdef.h> -#include <errnodef.h> - -extern void decc$main (); -extern int main (); - -static int -handler (sigargs, mechargs) - void *sigargs; - void *mechargs; -{ - return SS$_RESIGNAL; -} - -int -__main (arg1, arg2, arg3, image_file_desc, arg5, arg6) - void *arg1, *arg2, *arg3; - void *image_file_desc; - void *arg5, *arg6; -{ - int argc; - char **argv; - char **envp; - int status; - - lib$establish (handler); - decc$main (arg1, arg2, arg3, image_file_desc, arg5, arg6, - &argc, &argv, &envp); - - status = main (argc, argv, envp); - - /* Map into a range of 0 - 255. */ - status = status & 255; - - if (status > 0) - { - int save_status = status; - - status = C$_EXIT1 + ((status - 1) << STS$V_MSG_NO); - - /* An exit failure status requires a "severe" error - All status values are defined in errno with a successful - (1) severity but can be changed to an error (2) severity by adding 1. - In addition for compatibility with UNIX exit() routines we inhibit - a run-time error message from being generated on exit(1). */ - - if (save_status == 1) - { - status++; - status |= STS$M_INHIB_MSG; - } - } - - if (status == 0) - status = SS$_NORMAL; - - return status; -} -#endif diff --git a/gcc/config/vms/vms-ucrt0.c b/gcc/config/vms/vms-ucrt0.c new file mode 100644 index 00000000000..344b59520e0 --- /dev/null +++ b/gcc/config/vms/vms-ucrt0.c @@ -0,0 +1,127 @@ +/* VMS crt0 returning Unix style condition codes. + Copyright (C) 2001, 2009, 2010 Free Software Foundation, Inc. + Contributed by Douglas B. Rupp (rupp@gnat.com). + + This file is part of GCC. + + GCC is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + GCC is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + Under Section 7 of GPL version 3, you are granted additional + permissions described in the GCC Runtime Library Exception, version + 3.1, as published by the Free Software Foundation. + + You should have received a copy of the GNU General Public License and + a copy of the GCC Runtime Library Exception along with this program; + see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + <http://www.gnu.org/licenses/>. */ + +#include <stdlib.h> + +/* Lots of cheat to handle 32bits/64bits pointer conversions. + We use 'long long' for 64 bits pointers and 'int' for 32 bits pointers. */ + +extern void decc$main (void *arg1, void *arg2, void *arg3, + void *image_file_desc, void *arg5, void *arg6, + int *, int *, int *); +extern int main (int, char **, char **); +extern int _malloc32 (int); + +#ifdef __ia64__ +#define MAIN_ASM_NAME asm ("ELF$TFRADR") +#else +#define MAIN_ASM_NAME +#endif + +int __main (void *arg1, void *arg2, void *arg3, + void *image_file_desc, void *arg5, void *arg6) MAIN_ASM_NAME; + +/* From errnodef.h, but we need to emulate the globalval. */ +extern int C$_EXIT1; + +/* From stsdef.h */ +#define STS$V_MSG_NO 0x03 +#define STS$M_INHIB_MSG 0x10000000 + +/* From ssdef.h */ +#define SS$_NORMAL 1 + +int +__main (void *arg1, void *arg2, void *arg3, + void *image_file_desc, void *arg5, void *arg6) +{ + int argc; + int argv; + int envp; + int status; + int i; + long long *long_argv; + long long *long_envp; + + /* The argv and envp arrays are 32 bits pointers to 32 bits pointers. */ + decc$main (arg1, arg2, arg3, image_file_desc, + arg5, arg6, &argc, &argv, &envp); + + if (sizeof (void *) == 8) + { + /* Reallocate argv and envp with 64 bit pointers. */ + long_argv = (long long *) + (long long) _malloc32 (sizeof (long long) * (argc + 1)); + + for (i = 0; i < argc; i++) + long_argv[i] = ((int *) (long long) argv)[i]; + + long_argv[argc] = 0; + + for (i = 0; ((int *) (long long) envp)[i]; i++) + ; + long_envp = (long long *) + (long long) _malloc32 (sizeof (long long) * (i + 1)); + + for (i = 0; ((int *) (long long) envp)[i]; i++) + long_envp[i] = ((int *) (long long) envp)[i]; + + long_envp[i] = 0; + } + else + { + long_argv = (long long *) argv; + long_envp = (long long *) envp; + } + status = main (argc, (char **)long_argv, (char **)long_envp); + +#ifdef CRT0_POSIX_EXIT + /* Map into a range of 0 - 255. */ + status = status & 255; + + if (status > 0) + { + int save_status = status; + + status = (long) &C$_EXIT1 + ((status - 1) << STS$V_MSG_NO); + + /* An exit failure status requires a "severe" error. All status values + are defined in errno with a successful (1) severity but can be + changed to an error (2) severity by adding 1. In addition for + compatibility with UNIX exit() routines we inhibit a run-time error + message from being generated on exit(1). */ + + if (save_status == 1) + { + status++; + status |= STS$M_INHIB_MSG; + } + } + else + status = SS$_NORMAL; +#endif /* CRT0_POSIX_EXIT */ + + return status; +} |