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

📄 alpha.c

📁 gcc-2.95.3 Linux下最常用的C编译器
💻 C
📖 第 1 页 / 共 5 页
字号:
/* Subroutines used for code generation on the DEC Alpha.   Copyright (C) 1992, 93-98, 1999 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 "regs.h"#include "hard-reg-set.h"#include "real.h"#include "insn-config.h"#include "conditions.h"#include "insn-flags.h"#include "output.h"#include "insn-attr.h"#include "flags.h"#include "recog.h"#include "reload.h"#include "tree.h"#include "expr.h"#include "obstack.h"#include "except.h"#include "function.h"#include "toplev.h"/* External data.  */extern char *version_string;extern int rtx_equal_function_value_matters;/* 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_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.  */rtx alpha_compare_op0, alpha_compare_op1;int alpha_compare_fp_p;/* Define the information needed to modify the epilogue for EH.  */rtx alpha_eh_epilogue_sp_ofs;/* Non-zero if inside of a function, because the Alpha asm can't   handle .files inside of functions.  */static int inside_function = FALSE;/* If non-null, this rtx holds the return address for the function.  */static rtx alpha_return_addr_rtx;/* 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;/* Declarations of static functions.  */static void alpha_set_memflags_1  PROTO((rtx, int, int, int));static rtx alpha_emit_set_const_1  PROTO((rtx, enum machine_mode, HOST_WIDE_INT, int));static void alpha_expand_unaligned_load_words  PROTO((rtx *out_regs, rtx smem, HOST_WIDE_INT words, HOST_WIDE_INT ofs));static void alpha_expand_unaligned_store_words  PROTO((rtx *out_regs, rtx smem, HOST_WIDE_INT words, HOST_WIDE_INT ofs));static void alpha_sa_mask  PROTO((unsigned long *imaskP, unsigned long *fmaskP));static int alpha_does_function_need_gp  PROTO((void));/* Get the number of args of a function in one of two ways.  */#ifdef OPEN_VMS#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/* Parse target option strings. */voidoverride_options (){  alpha_tp = ALPHA_TP_PROG;  alpha_fprm = ALPHA_FPRM_NORM;  alpha_fptm = ALPHA_FPTM_N;  if (TARGET_IEEE)    {      alpha_tp = ALPHA_TP_INSN;      alpha_fptm = ALPHA_FPTM_SU;    }  if (TARGET_IEEE_WITH_INEXACT)    {      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)    {      if (! strcmp (alpha_cpu_string, "ev4")	  || ! strcmp (alpha_cpu_string, "21064"))	{	  alpha_cpu = PROCESSOR_EV4;	  target_flags &= ~ (MASK_BWX | MASK_MAX | MASK_FIX | MASK_CIX);	}      else if (! strcmp (alpha_cpu_string, "ev5")	       || ! strcmp (alpha_cpu_string, "21164"))	{	  alpha_cpu = PROCESSOR_EV5;	  target_flags &= ~ (MASK_BWX | MASK_MAX | MASK_FIX | MASK_CIX);	}      else if (! strcmp (alpha_cpu_string, "ev56")	       || ! strcmp (alpha_cpu_string, "21164a"))	{	  alpha_cpu = PROCESSOR_EV5;	  target_flags |= MASK_BWX;	  target_flags &= ~ (MASK_MAX | MASK_FIX | MASK_CIX);	}      else if (! strcmp (alpha_cpu_string, "pca56")	       || ! strcmp (alpha_cpu_string, "21164PC")	       || ! strcmp (alpha_cpu_string, "21164pc"))	{	  alpha_cpu = PROCESSOR_EV5;	  target_flags |= MASK_BWX | MASK_MAX;	  target_flags &= ~ (MASK_FIX | MASK_CIX);	}      else if (! strcmp (alpha_cpu_string, "ev6")	       || ! strcmp (alpha_cpu_string, "21264"))	{	  alpha_cpu = PROCESSOR_EV6;	  target_flags |= MASK_BWX | MASK_MAX | MASK_FIX;	  target_flags &= ~ (MASK_CIX);	}      else	error ("bad value `%s' for -mcpu switch", alpha_cpu_string);    }  /* Do some sanity checks on the above options. */  if ((alpha_fptm == ALPHA_FPTM_SU || alpha_fptm == ALPHA_FPTM_SUI)      && alpha_tp != ALPHA_TP_INSN && alpha_cpu != PROCESSOR_EV6)    {      warning ("fp software completion requires -mtrap-precision=i");      alpha_tp = ALPHA_TP_INSN;    }  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, 13, -1 },	/* ev6 -- Ho hum, doesn't exist yet */	};	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;  /* Acquire a unique set number for our register saves and restores.  */  alpha_sr_alias_set = new_alias_set ();}/* Returns 1 if VALUE is a mask that contains full bytes of zero or ones.  */intzap_mask (value)     HOST_WIDE_INT value;{  int i;  for (i = 0; i < HOST_BITS_PER_WIDE_INT / HOST_BITS_PER_CHAR;       i++, value >>= 8)    if ((value & 0xff) != 0 && (value & 0xff) != 0xff)      return 0;  return 1;}/* Returns 1 if OP is either the constant zero or a register.  If a   register, it must be in the proper mode unless MODE is VOIDmode.  */intreg_or_0_operand (op, mode)      register rtx op;      enum machine_mode mode;{  return op == const0_rtx || register_operand (op, mode);}/* Return 1 if OP is a constant in the range of 0-63 (for a shift) or   any register.  */intreg_or_6bit_operand (op, mode)     register rtx op;     enum machine_mode mode;{  return ((GET_CODE (op) == CONST_INT	   && (unsigned HOST_WIDE_INT) INTVAL (op) < 64)	  || register_operand (op, mode));}/* Return 1 if OP is an 8-bit constant or any register.  */intreg_or_8bit_operand (op, mode)     register rtx op;     enum machine_mode mode;{  return ((GET_CODE (op) == CONST_INT	   && (unsigned HOST_WIDE_INT) INTVAL (op) < 0x100)	  || register_operand (op, mode));}/* Return 1 if OP is an 8-bit constant.  */intcint8_operand (op, mode)     register rtx op;     enum machine_mode mode ATTRIBUTE_UNUSED;{  return ((GET_CODE (op) == CONST_INT	   && (unsigned HOST_WIDE_INT) INTVAL (op) < 0x100));}/* Return 1 if the operand is a valid second operand to an add insn.  */intadd_operand (op, mode)     register rtx op;     enum machine_mode mode;{  if (GET_CODE (op) == CONST_INT)    /* Constraints I, J, O and P are covered by K.  */    return (CONST_OK_FOR_LETTER_P (INTVAL (op), 'K')	    || CONST_OK_FOR_LETTER_P (INTVAL (op), 'L'));  return register_operand (op, mode);}/* Return 1 if the operand is a valid second operand to a sign-extending   add insn.  */intsext_add_operand (op, mode)     register rtx op;     enum machine_mode mode;{  if (GET_CODE (op) == CONST_INT)    return (CONST_OK_FOR_LETTER_P (INTVAL (op), 'I')	    || CONST_OK_FOR_LETTER_P (INTVAL (op), 'O'));  return register_operand (op, mode);}/* Return 1 if OP is the constant 4 or 8.  */intconst48_operand (op, mode)     register rtx op;     enum machine_mode mode ATTRIBUTE_UNUSED;{  return (GET_CODE (op) == CONST_INT	  && (INTVAL (op) == 4 || INTVAL (op) == 8));}/* Return 1 if OP is a valid first operand to an AND insn.  */intand_operand (op, mode)     register rtx op;     enum machine_mode mode;{  if (GET_CODE (op) == CONST_DOUBLE && GET_MODE (op) == VOIDmode)    return (zap_mask (CONST_DOUBLE_LOW (op))	    && zap_mask (CONST_DOUBLE_HIGH (op)));  if (GET_CODE (op) == CONST_INT)    return ((unsigned HOST_WIDE_INT) INTVAL (op) < 0x100	    || (unsigned HOST_WIDE_INT) ~ INTVAL (op) < 0x100	    || zap_mask (INTVAL (op)));  return register_operand (op, mode);}/* Return 1 if OP is a valid first operand to an IOR or XOR insn.  */intor_operand (op, mode)     register rtx op;     enum machine_mode mode;{  if (GET_CODE (op) == CONST_INT)    return ((unsigned HOST_WIDE_INT) INTVAL (op) < 0x100	    || (unsigned HOST_WIDE_INT) ~ INTVAL (op) < 0x100);  return register_operand (op, mode);}/* Return 1 if OP is a constant that is the width, in bits, of an integral   mode smaller than DImode.  */intmode_width_operand (op, mode)     register rtx op;     enum machine_mode mode ATTRIBUTE_UNUSED;{  return (GET_CODE (op) == CONST_INT	  && (INTVAL (op) == 8 || INTVAL (op) == 16	      || INTVAL (op) == 32 || INTVAL (op) == 64));}/* Return 1 if OP is a constant that is the width of an integral machine mode   smaller than an integer.  */intmode_mask_operand (op, mode)     register rtx op;     enum machine_mode mode ATTRIBUTE_UNUSED;{#if HOST_BITS_PER_WIDE_INT == 32  if (GET_CODE (op) == CONST_DOUBLE)    return (CONST_DOUBLE_LOW (op) == -1	    && (CONST_DOUBLE_HIGH (op) == -1		|| CONST_DOUBLE_HIGH (op) == 0));#else  if (GET_CODE (op) == CONST_DOUBLE)    return (CONST_DOUBLE_LOW (op) == -1 && CONST_DOUBLE_HIGH (op) == 0);#endif  return (GET_CODE (op) == CONST_INT	  && (INTVAL (op) == 0xff	      || INTVAL (op) == 0xffff	      || INTVAL (op) == (HOST_WIDE_INT)0xffffffff

⌨️ 快捷键说明

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