📄 alpha.c
字号:
/* Subroutines used for code generation on the DEC Alpha. Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc. Contributed by Richard Kenner (kenner@vlsi1.ultra.nyu.edu)This file is part of GNU CC.GNU CC is free software; you can redistribute it and/or modifyit under the terms of the GNU General Public License as published bythe Free Software Foundation; either version 2, or (at your option)any later version.GNU CC is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; without even the implied warranty ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See theGNU General Public License for more details.You should have received a copy of the GNU General Public Licensealong with GNU CC; see the file COPYING. If not, write tothe Free Software Foundation, 59 Temple Place - Suite 330,Boston, MA 02111-1307, USA. */#include "config.h"#include "system.h"#include "rtl.h"#include "tree.h"#include "regs.h"#include "hard-reg-set.h"#include "real.h"#include "insn-config.h"#include "conditions.h"#include "output.h"#include "insn-attr.h"#include "flags.h"#include "recog.h"#include "expr.h"#include "optabs.h"#include "reload.h"#include "obstack.h"#include "except.h"#include "function.h"#include "toplev.h"#include "ggc.h"#include "integrate.h"#include "tm_p.h"#include "target.h"#include "target-def.h"#include "debug.h"#include "langhooks.h"/* Specify which cpu to schedule for. */enum processor_type alpha_cpu;static const char * const alpha_cpu_name[] = { "ev4", "ev5", "ev6"};/* Specify how accurate floating-point traps need to be. */enum alpha_trap_precision alpha_tp;/* Specify the floating-point rounding mode. */enum alpha_fp_rounding_mode alpha_fprm;/* Specify which things cause traps. */enum alpha_fp_trap_mode alpha_fptm;/* Specify bit size of immediate TLS offsets. */int alpha_tls_size = 32;/* Strings decoded into the above options. */const char *alpha_cpu_string; /* -mcpu= */const char *alpha_tune_string; /* -mtune= */const char *alpha_tp_string; /* -mtrap-precision=[p|s|i] */const char *alpha_fprm_string; /* -mfp-rounding-mode=[n|m|c|d] */const char *alpha_fptm_string; /* -mfp-trap-mode=[n|u|su|sui] */const char *alpha_mlat_string; /* -mmemory-latency= */const char *alpha_tls_size_string; /* -mtls-size=[16|32|64] *//* Save information from a "cmpxx" operation until the branch or scc is emitted. */struct alpha_compare alpha_compare;/* Nonzero if inside of a function, because the Alpha asm can't handle .files inside of functions. */static int inside_function = FALSE;/* The number of cycles of latency we should assume on memory reads. */int alpha_memory_latency = 3;/* Whether the function needs the GP. */static int alpha_function_needs_gp;/* The alias set for prologue/epilogue register save/restore. */static int alpha_sr_alias_set;/* The assembler name of the current function. */static const char *alpha_fnname;/* The next explicit relocation sequence number. */int alpha_next_sequence_number = 1;/* The literal and gpdisp sequence numbers for this insn, as printed by %# and %* respectively. */int alpha_this_literal_sequence_number;int alpha_this_gpdisp_sequence_number;/* Declarations of static functions. */static int tls_symbolic_operand_1 PARAMS ((rtx, enum machine_mode, int, int));static enum tls_model tls_symbolic_operand_type PARAMS ((rtx));static bool decl_in_text_section PARAMS ((tree));static bool alpha_in_small_data_p PARAMS ((tree));static void alpha_encode_section_info PARAMS ((tree, int));static const char *alpha_strip_name_encoding PARAMS ((const char *));static int some_small_symbolic_operand_1 PARAMS ((rtx *, void *));static int split_small_symbolic_operand_1 PARAMS ((rtx *, void *));static void alpha_set_memflags_1 PARAMS ((rtx, int, int, int));static rtx alpha_emit_set_const_1 PARAMS ((rtx, enum machine_mode, HOST_WIDE_INT, int));static void alpha_expand_unaligned_load_words PARAMS ((rtx *out_regs, rtx smem, HOST_WIDE_INT words, HOST_WIDE_INT ofs));static void alpha_expand_unaligned_store_words PARAMS ((rtx *out_regs, rtx smem, HOST_WIDE_INT words, HOST_WIDE_INT ofs));static void alpha_init_builtins PARAMS ((void));static rtx alpha_expand_builtin PARAMS ((tree, rtx, rtx, enum machine_mode, int));static void alpha_sa_mask PARAMS ((unsigned long *imaskP, unsigned long *fmaskP));static int find_lo_sum_using_gp PARAMS ((rtx *, void *));static int alpha_does_function_need_gp PARAMS ((void));static int alpha_ra_ever_killed PARAMS ((void));static const char *get_trap_mode_suffix PARAMS ((void));static const char *get_round_mode_suffix PARAMS ((void));static const char *get_some_local_dynamic_name PARAMS ((void));static int get_some_local_dynamic_name_1 PARAMS ((rtx *, void *));static rtx set_frame_related_p PARAMS ((void));static const char *alpha_lookup_xfloating_lib_func PARAMS ((enum rtx_code));static int alpha_compute_xfloating_mode_arg PARAMS ((enum rtx_code, enum alpha_fp_rounding_mode));static void alpha_emit_xfloating_libcall PARAMS ((const char *, rtx, rtx[], int, rtx));static rtx alpha_emit_xfloating_compare PARAMS ((enum rtx_code, rtx, rtx));static void alpha_output_function_end_prologue PARAMS ((FILE *));static int alpha_adjust_cost PARAMS ((rtx, rtx, rtx, int));static int alpha_issue_rate PARAMS ((void));static int alpha_use_dfa_pipeline_interface PARAMS ((void));static int alpha_multipass_dfa_lookahead PARAMS ((void));#ifdef OBJECT_FORMAT_ELFstatic void alpha_elf_select_rtx_section PARAMS ((enum machine_mode, rtx, unsigned HOST_WIDE_INT));#endif#if TARGET_ABI_OPEN_VMSstatic bool alpha_linkage_symbol_p PARAMS ((const char *symname));static void alpha_write_linkage PARAMS ((FILE *, const char *, tree));#endif#if TARGET_ABI_OSFstatic void alpha_output_mi_thunk_osf PARAMS ((FILE *, tree, HOST_WIDE_INT, HOST_WIDE_INT, tree));#endifstatic struct machine_function * alpha_init_machine_status PARAMS ((void));static void unicosmk_output_deferred_case_vectors PARAMS ((FILE *));static void unicosmk_gen_dsib PARAMS ((unsigned long *imaskP));static void unicosmk_output_ssib PARAMS ((FILE *, const char *));static int unicosmk_need_dex PARAMS ((rtx));/* Get the number of args of a function in one of two ways. */#if TARGET_ABI_OPEN_VMS || TARGET_ABI_UNICOSMK#define NUM_ARGS current_function_args_info.num_args#else#define NUM_ARGS current_function_args_info#endif#define REG_PV 27#define REG_RA 26/* Initialize the GCC target structure. */#if TARGET_ABI_OPEN_VMSconst struct attribute_spec vms_attribute_table[];static unsigned int vms_section_type_flags PARAMS ((tree, const char *, int));static void vms_asm_named_section PARAMS ((const char *, unsigned int));static void vms_asm_out_constructor PARAMS ((rtx, int));static void vms_asm_out_destructor PARAMS ((rtx, int));# undef TARGET_ATTRIBUTE_TABLE# define TARGET_ATTRIBUTE_TABLE vms_attribute_table# undef TARGET_SECTION_TYPE_FLAGS# define TARGET_SECTION_TYPE_FLAGS vms_section_type_flags#endif#undef TARGET_IN_SMALL_DATA_P#define TARGET_IN_SMALL_DATA_P alpha_in_small_data_p#undef TARGET_ENCODE_SECTION_INFO#define TARGET_ENCODE_SECTION_INFO alpha_encode_section_info#undef TARGET_STRIP_NAME_ENCODING#define TARGET_STRIP_NAME_ENCODING alpha_strip_name_encoding#if TARGET_ABI_UNICOSMKstatic void unicosmk_asm_named_section PARAMS ((const char *, unsigned int));static void unicosmk_insert_attributes PARAMS ((tree, tree *));static unsigned int unicosmk_section_type_flags PARAMS ((tree, const char *, int));static void unicosmk_unique_section PARAMS ((tree, int));# undef TARGET_INSERT_ATTRIBUTES# define TARGET_INSERT_ATTRIBUTES unicosmk_insert_attributes# undef TARGET_SECTION_TYPE_FLAGS# define TARGET_SECTION_TYPE_FLAGS unicosmk_section_type_flags# undef TARGET_ASM_UNIQUE_SECTION# define TARGET_ASM_UNIQUE_SECTION unicosmk_unique_section# undef TARGET_ASM_GLOBALIZE_LABEL# define TARGET_ASM_GLOBALIZE_LABEL hook_FILEptr_constcharptr_void#endif#undef TARGET_ASM_ALIGNED_HI_OP#define TARGET_ASM_ALIGNED_HI_OP "\t.word\t"#undef TARGET_ASM_ALIGNED_DI_OP#define TARGET_ASM_ALIGNED_DI_OP "\t.quad\t"/* Default unaligned ops are provided for ELF systems. To get unaligned data for non-ELF systems, we have to turn off auto alignment. */#ifndef OBJECT_FORMAT_ELF#undef TARGET_ASM_UNALIGNED_HI_OP#define TARGET_ASM_UNALIGNED_HI_OP "\t.align 0\n\t.word\t"#undef TARGET_ASM_UNALIGNED_SI_OP#define TARGET_ASM_UNALIGNED_SI_OP "\t.align 0\n\t.long\t"#undef TARGET_ASM_UNALIGNED_DI_OP#define TARGET_ASM_UNALIGNED_DI_OP "\t.align 0\n\t.quad\t"#endif#ifdef OBJECT_FORMAT_ELF#undef TARGET_ASM_SELECT_RTX_SECTION#define TARGET_ASM_SELECT_RTX_SECTION alpha_elf_select_rtx_section#endif#undef TARGET_ASM_FUNCTION_END_PROLOGUE#define TARGET_ASM_FUNCTION_END_PROLOGUE alpha_output_function_end_prologue#undef TARGET_SCHED_ADJUST_COST#define TARGET_SCHED_ADJUST_COST alpha_adjust_cost#undef TARGET_SCHED_ISSUE_RATE#define TARGET_SCHED_ISSUE_RATE alpha_issue_rate#undef TARGET_SCHED_USE_DFA_PIPELINE_INTERFACE#define TARGET_SCHED_USE_DFA_PIPELINE_INTERFACE \ alpha_use_dfa_pipeline_interface#undef TARGET_SCHED_FIRST_CYCLE_MULTIPASS_DFA_LOOKAHEAD#define TARGET_SCHED_FIRST_CYCLE_MULTIPASS_DFA_LOOKAHEAD \ alpha_multipass_dfa_lookahead#undef TARGET_HAVE_TLS#define TARGET_HAVE_TLS HAVE_AS_TLS#undef TARGET_INIT_BUILTINS#define TARGET_INIT_BUILTINS alpha_init_builtins#undef TARGET_EXPAND_BUILTIN#define TARGET_EXPAND_BUILTIN alpha_expand_builtin#if TARGET_ABI_OSF#undef TARGET_ASM_OUTPUT_MI_THUNK#define TARGET_ASM_OUTPUT_MI_THUNK alpha_output_mi_thunk_osf#undef TARGET_ASM_CAN_OUTPUT_MI_THUNK#define TARGET_ASM_CAN_OUTPUT_MI_THUNK hook_bool_tree_hwi_hwi_tree_true#endifstruct gcc_target targetm = TARGET_INITIALIZER;/* Parse target option strings. */voidoverride_options (){ int i; static const struct cpu_table { const char *const name; const enum processor_type processor; const int flags; } cpu_table[] = {#define EV5_MASK (MASK_CPU_EV5)#define EV6_MASK (MASK_CPU_EV6|MASK_BWX|MASK_MAX|MASK_FIX) { "ev4", PROCESSOR_EV4, 0 }, { "ev45", PROCESSOR_EV4, 0 }, { "21064", PROCESSOR_EV4, 0 }, { "ev5", PROCESSOR_EV5, EV5_MASK }, { "21164", PROCESSOR_EV5, EV5_MASK }, { "ev56", PROCESSOR_EV5, EV5_MASK|MASK_BWX }, { "21164a", PROCESSOR_EV5, EV5_MASK|MASK_BWX }, { "pca56", PROCESSOR_EV5, EV5_MASK|MASK_BWX|MASK_MAX }, { "21164PC",PROCESSOR_EV5, EV5_MASK|MASK_BWX|MASK_MAX }, { "21164pc",PROCESSOR_EV5, EV5_MASK|MASK_BWX|MASK_MAX }, { "ev6", PROCESSOR_EV6, EV6_MASK }, { "21264", PROCESSOR_EV6, EV6_MASK }, { "ev67", PROCESSOR_EV6, EV6_MASK|MASK_CIX }, { "21264a", PROCESSOR_EV6, EV6_MASK|MASK_CIX }, { 0, 0, 0 } }; /* Unicos/Mk doesn't have shared libraries. */ if (TARGET_ABI_UNICOSMK && flag_pic) { warning ("-f%s ignored for Unicos/Mk (not supported)", (flag_pic > 1) ? "PIC" : "pic"); flag_pic = 0; } /* On Unicos/Mk, the native compiler consistenly generates /d suffices for floating-point instructions. Make that the default for this target. */ if (TARGET_ABI_UNICOSMK) alpha_fprm = ALPHA_FPRM_DYN; else alpha_fprm = ALPHA_FPRM_NORM; alpha_tp = ALPHA_TP_PROG; alpha_fptm = ALPHA_FPTM_N; /* We cannot use su and sui qualifiers for conversion instructions on Unicos/Mk. I'm not sure if this is due to assembler or hardware limitations. Right now, we issue a warning if -mieee is specified and then ignore it; eventually, we should either get it right or disable the option altogether. */ if (TARGET_IEEE) { if (TARGET_ABI_UNICOSMK) warning ("-mieee not supported on Unicos/Mk"); else { alpha_tp = ALPHA_TP_INSN; alpha_fptm = ALPHA_FPTM_SU; } } if (TARGET_IEEE_WITH_INEXACT) { if (TARGET_ABI_UNICOSMK) warning ("-mieee-with-inexact not supported on Unicos/Mk"); else { alpha_tp = ALPHA_TP_INSN; alpha_fptm = ALPHA_FPTM_SUI; } } if (alpha_tp_string) { if (! strcmp (alpha_tp_string, "p")) alpha_tp = ALPHA_TP_PROG; else if (! strcmp (alpha_tp_string, "f")) alpha_tp = ALPHA_TP_FUNC; else if (! strcmp (alpha_tp_string, "i")) alpha_tp = ALPHA_TP_INSN; else error ("bad value `%s' for -mtrap-precision switch", alpha_tp_string); } if (alpha_fprm_string) { if (! strcmp (alpha_fprm_string, "n")) alpha_fprm = ALPHA_FPRM_NORM; else if (! strcmp (alpha_fprm_string, "m")) alpha_fprm = ALPHA_FPRM_MINF; else if (! strcmp (alpha_fprm_string, "c")) alpha_fprm = ALPHA_FPRM_CHOP; else if (! strcmp (alpha_fprm_string,"d")) alpha_fprm = ALPHA_FPRM_DYN; else error ("bad value `%s' for -mfp-rounding-mode switch", alpha_fprm_string); } if (alpha_fptm_string) { if (strcmp (alpha_fptm_string, "n") == 0) alpha_fptm = ALPHA_FPTM_N; else if (strcmp (alpha_fptm_string, "u") == 0) alpha_fptm = ALPHA_FPTM_U; else if (strcmp (alpha_fptm_string, "su") == 0) alpha_fptm = ALPHA_FPTM_SU; else if (strcmp (alpha_fptm_string, "sui") == 0) alpha_fptm = ALPHA_FPTM_SUI; else error ("bad value `%s' for -mfp-trap-mode switch", alpha_fptm_string); } if (alpha_tls_size_string) { if (strcmp (alpha_tls_size_string, "16") == 0) alpha_tls_size = 16; else if (strcmp (alpha_tls_size_string, "32") == 0) alpha_tls_size = 32; else if (strcmp (alpha_tls_size_string, "64") == 0) alpha_tls_size = 64; else error ("bad value `%s' for -mtls-size switch", alpha_tls_size_string); } alpha_cpu = TARGET_CPU_DEFAULT & MASK_CPU_EV6 ? PROCESSOR_EV6 : (TARGET_CPU_DEFAULT & MASK_CPU_EV5 ? PROCESSOR_EV5 : PROCESSOR_EV4); if (alpha_cpu_string) { for (i = 0; cpu_table [i].name; i++) if (! strcmp (alpha_cpu_string, cpu_table [i].name)) { alpha_cpu = cpu_table [i].processor; target_flags &= ~ (MASK_BWX | MASK_MAX | MASK_FIX | MASK_CIX | MASK_CPU_EV5 | MASK_CPU_EV6); target_flags |= cpu_table [i].flags; break; } if (! cpu_table [i].name) error ("bad value `%s' for -mcpu switch", alpha_cpu_string); } if (alpha_tune_string) { for (i = 0; cpu_table [i].name; i++) if (! strcmp (alpha_tune_string, cpu_table [i].name)) { alpha_cpu = cpu_table [i].processor; break; } if (! cpu_table [i].name) error ("bad value `%s' for -mcpu switch", alpha_tune_string); } /* Do some sanity checks on the above options. */ if (TARGET_ABI_UNICOSMK && alpha_fptm != ALPHA_FPTM_N) { warning ("trap mode not supported on Unicos/Mk"); alpha_fptm = ALPHA_FPTM_N; } if ((alpha_fptm == ALPHA_FPTM_SU || alpha_fptm == ALPHA_FPTM_SUI) && alpha_tp != ALPHA_TP_INSN && ! TARGET_CPU_EV6) { warning ("fp software completion requires -mtrap-precision=i"); alpha_tp = ALPHA_TP_INSN; } if (TARGET_CPU_EV6) { /* Except for EV6 pass 1 (not released), we always have precise arithmetic traps. Which means we can do software completion without minding trap shadows. */ alpha_tp = ALPHA_TP_PROG; } if (TARGET_FLOAT_VAX)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -