⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 alpha.c

📁 gcc3.2.1源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
/* Subroutines used for code generation on the DEC Alpha.   Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,   2000, 2001 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"/* 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;/* 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= *//* Save information from a "cmpxx" operation until the branch or scc is   emitted.  */struct alpha_compare alpha_compare;/* Non-zero 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 bool decl_in_text_section  PARAMS ((tree));static int some_small_symbolic_operand_1  PARAMS ((rtx *, void *));static int split_small_symbolic_operand_1  PARAMS ((rtx *, void *));static bool local_symbol_p  PARAMS ((rtx));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_sa_mask  PARAMS ((unsigned long *imaskP, unsigned long *fmaskP));static int find_lo_sum  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 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_variable_issue  PARAMS ((FILE *, int, rtx, int));#if TARGET_ABI_UNICOSMKstatic void alpha_init_machine_status  PARAMS ((struct function *p));static void alpha_mark_machine_status  PARAMS ((struct function *p));static void alpha_free_machine_status  PARAMS ((struct function *p));#endifstatic 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#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));# 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#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#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_VARIABLE_ISSUE#define TARGET_SCHED_VARIABLE_ISSUE alpha_variable_issuestruct 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);    }  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)    {      if (alpha_fprm == ALPHA_FPRM_MINF || alpha_fprm == ALPHA_FPRM_DYN)	{	  warning ("rounding mode not supported for VAX floats");	  alpha_fprm = ALPHA_FPRM_NORM;	}      if (alpha_fptm == ALPHA_FPTM_SUI)	{	  warning ("trap mode not supported for VAX floats");	  alpha_fptm = ALPHA_FPTM_SU;	}    }  {    char *end;    int lat;    if (!alpha_mlat_string)      alpha_mlat_string = "L1";    if (ISDIGIT ((unsigned char)alpha_mlat_string[0])	&& (lat = strtol (alpha_mlat_string, &end, 10), *end == '\0'))      ;    else if ((alpha_mlat_string[0] == 'L' || alpha_mlat_string[0] == 'l')	     && ISDIGIT ((unsigned char)alpha_mlat_string[1])	     && alpha_mlat_string[2] == '\0')      {	static int const cache_latency[][4] = 	{	  { 3, 30, -1 },	/* ev4 -- Bcache is a guess */	  { 2, 12, 38 },	/* ev5 -- Bcache from PC164 LMbench numbers */	  { 3, 12, 30 },	/* ev6 -- Bcache from DS20 LMbench.  */	};	lat = alpha_mlat_string[1] - '0';	if (lat <= 0 || lat > 3 || cache_latency[alpha_cpu][lat-1] == -1)	  {	    warning ("L%d cache latency unknown for %s",		     lat, alpha_cpu_name[alpha_cpu]);	    lat = 3;	  }	else	  lat = cache_latency[alpha_cpu][lat-1];      }    else if (! strcmp (alpha_mlat_string, "main"))      {	/* Most current memories have about 370ns latency.  This is	   a reasonable guess for a fast cpu.  */	lat = 150;      }    else      {	warning ("bad value `%s' for -mmemory-latency", alpha_mlat_string);	lat = 3;      }    alpha_memory_latency = lat;  }  /* Default the definition of "small data" to 8 bytes.  */  if (!g_switch_set)    g_switch_value = 8;  /* Infer TARGET_SMALL_DATA from -fpic/-fPIC.  */  if (flag_pic == 1)    target_flags |= MASK_SMALL_DATA;  else if (flag_pic == 2)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -