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

📄 alpha.c

📁 Mac OS X 10.4.9 for x86 Source Code gcc 实现源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
/* Subroutines used for code generation on the DEC Alpha.   Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,   2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.   Contributed by Richard Kenner (kenner@vlsi1.ultra.nyu.edu)This file is part of GCC.GCC 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.GCC 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 GCC; 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 "coretypes.h"#include "tm.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"#include <splay-tree.h>#include "cfglayout.h"#include "tree-gimple.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 GTY(()) int alpha_sr_alias_set;/* The assembler name of the current function.  */static const char *alpha_fnname;/* The next explicit relocation sequence number.  */extern GTY(()) int alpha_next_sequence_number;int alpha_next_sequence_number = 1;/* The literal and gpdisp sequence numbers for this insn, as printed   by %# and %* respectively.  */extern GTY(()) int alpha_this_literal_sequence_number;extern GTY(()) int alpha_this_gpdisp_sequence_number;int alpha_this_literal_sequence_number;int alpha_this_gpdisp_sequence_number;/* Costs of various operations on the different architectures.  */struct alpha_rtx_cost_data{  unsigned char fp_add;  unsigned char fp_mult;  unsigned char fp_div_sf;  unsigned char fp_div_df;  unsigned char int_mult_si;  unsigned char int_mult_di;  unsigned char int_shift;  unsigned char int_cmov;  unsigned short int_div;};static struct alpha_rtx_cost_data const alpha_rtx_cost_data[PROCESSOR_MAX] ={  { /* EV4 */    COSTS_N_INSNS (6),		/* fp_add */    COSTS_N_INSNS (6),		/* fp_mult */    COSTS_N_INSNS (34),		/* fp_div_sf */    COSTS_N_INSNS (63),		/* fp_div_df */    COSTS_N_INSNS (23),		/* int_mult_si */    COSTS_N_INSNS (23),		/* int_mult_di */    COSTS_N_INSNS (2),		/* int_shift */    COSTS_N_INSNS (2),		/* int_cmov */    COSTS_N_INSNS (97),		/* int_div */  },  { /* EV5 */    COSTS_N_INSNS (4),		/* fp_add */    COSTS_N_INSNS (4),		/* fp_mult */    COSTS_N_INSNS (15),		/* fp_div_sf */    COSTS_N_INSNS (22),		/* fp_div_df */    COSTS_N_INSNS (8),		/* int_mult_si */    COSTS_N_INSNS (12),		/* int_mult_di */    COSTS_N_INSNS (1) + 1,	/* int_shift */    COSTS_N_INSNS (1),		/* int_cmov */    COSTS_N_INSNS (83),		/* int_div */  },  { /* EV6 */    COSTS_N_INSNS (4),		/* fp_add */    COSTS_N_INSNS (4),		/* fp_mult */    COSTS_N_INSNS (12),		/* fp_div_sf */    COSTS_N_INSNS (15),		/* fp_div_df */    COSTS_N_INSNS (7),		/* int_mult_si */    COSTS_N_INSNS (7),		/* int_mult_di */    COSTS_N_INSNS (1),		/* int_shift */    COSTS_N_INSNS (2),		/* int_cmov */    COSTS_N_INSNS (86),		/* int_div */  },};/* Similar but tuned for code size instead of execution latency.  The   extra +N is fractional cost tuning based on latency.  It's used to   encourage use of cheaper insns like shift, but only if there's just   one of them.  */static struct alpha_rtx_cost_data const alpha_rtx_cost_size ={  COSTS_N_INSNS (1),		/* fp_add */  COSTS_N_INSNS (1),		/* fp_mult */  COSTS_N_INSNS (1),		/* fp_div_sf */  COSTS_N_INSNS (1) + 1,	/* fp_div_df */  COSTS_N_INSNS (1) + 1,	/* int_mult_si */  COSTS_N_INSNS (1) + 2,	/* int_mult_di */  COSTS_N_INSNS (1),		/* int_shift */  COSTS_N_INSNS (1),		/* int_cmov */  COSTS_N_INSNS (6),		/* int_div */};/* 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/* Declarations of static functions.  */static struct machine_function *alpha_init_machine_status (void);static rtx alpha_emit_xfloating_compare (enum rtx_code *, rtx, rtx);#if TARGET_ABI_OPEN_VMSstatic void alpha_write_linkage (FILE *, const char *, tree);#endifstatic void unicosmk_output_deferred_case_vectors (FILE *);static void unicosmk_gen_dsib (unsigned long *);static void unicosmk_output_ssib (FILE *, const char *);static int unicosmk_need_dex (rtx);/* Parse target option strings.  */voidoverride_options (void){  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 consistently 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 %qs 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 %qs 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 %qs 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 %qs 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 %qs 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 %qs 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;	}      if (target_flags_explicit & MASK_LONG_DOUBLE_128)	warning ("128-bit long double not supported for VAX floats");      target_flags &= ~MASK_LONG_DOUBLE_128;    }  {    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 %qs for -mmemory-latency", alpha_mlat_string);	lat = 3;      }    alpha_memory_latency = lat;

⌨️ 快捷键说明

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