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

📄 rs6000.c

📁 gcc库的原代码,对编程有很大帮助.
💻 C
📖 第 1 页 / 共 5 页
字号:
/* Subroutines used for code generation on IBM RS/6000.   Copyright (C) 1991, 1993, 1994, 1995 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 <stdio.h>#include <ctype.h>#include "config.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 "expr.h"#include "obstack.h"#include "tree.h"extern char *language_string;extern int profile_block_flag;#define min(A,B)	((A) < (B) ? (A) : (B))#define max(A,B)	((A) > (B) ? (A) : (B))/* Target cpu type */enum processor_type rs6000_cpu;char *rs6000_cpu_string;/* Set to non-zero by "fix" operation to indicate that itrunc and   uitrunc must be defined.  */int rs6000_trunc_used;/* Set to non-zero once they have been defined.  */static int trunc_defined;/* Set to non-zero once AIX common-mode calls have been defined.  */static int common_mode_defined;/* Save information from a "cmpxx" operation until the branch or scc is   emitted.  */rtx rs6000_compare_op0, rs6000_compare_op1;int rs6000_compare_fp_p;#ifdef USING_SVR4_H/* Label number of label created for -mrelocatable, to call to so we can   get the address of the GOT section */int rs6000_pic_labelno;#endif/* Whether a System V.4 varargs area was created.  */int rs6000_sysv_varargs_p;/* Temporary memory used to convert integer -> float */static rtx stack_temps[NUM_MACHINE_MODES];/* Print the options used in the assembly file.  */extern char *version_string, *language_string;struct asm_option{  char *string;  int *variable;  int on_value;};#define MAX_LINE 79static intoutput_option (file, type, name, pos)     FILE *file;     char *type;     char *name;     int pos;{  int type_len = strlen (type);  int name_len = strlen (name);  if (1 + type_len + name_len + pos > MAX_LINE)    {      fprintf (file, "\n # %s%s", type, name);      return 3 + type_len + name_len;    }  fprintf (file, " %s%s", type, name);  return pos + 1 + type_len + name_len;}static struct { char *name; int value; } m_options[] = TARGET_SWITCHES;voidoutput_options (file, f_options, f_len, W_options, W_len)     FILE *file;     struct asm_option *f_options;     int f_len;     struct asm_option *W_options;     int W_len;{  int j;  int flags = target_flags;  int pos = 32767;  fprintf (file, " # %s %s", language_string, version_string);  if (optimize)    {      char opt_string[20];      sprintf (opt_string, "%d", optimize);      pos = output_option (file, "-O", opt_string, pos);    }  if (profile_flag)    pos = output_option (file, "-p", "", pos);  if (profile_block_flag)    pos = output_option (file, "-a", "", pos);  if (inhibit_warnings)    pos = output_option (file, "-w", "", pos);  for (j = 0; j < f_len; j++)    {      if (*f_options[j].variable == f_options[j].on_value)	pos = output_option (file, "-f", f_options[j].string, pos);    }  for (j = 0; j < W_len; j++)    {      if (*W_options[j].variable == W_options[j].on_value)	pos = output_option (file, "-W", W_options[j].string, pos);    }  for (j = 0; j < sizeof m_options / sizeof m_options[0]; j++)    {      if (m_options[j].name[0] != '\0'	  && m_options[j].value > 0	  && ((m_options[j].value & flags) == m_options[j].value))	{	  pos = output_option (file, "-m", m_options[j].name, pos);	  flags &= ~ m_options[j].value;	}    }  if (rs6000_cpu_string != (char *)0)    pos = output_option (file, "-mcpu=", rs6000_cpu_string, pos);  fputs ("\n\n", file);}/* Override command line options.  Mostly we process the processor   type and sometimes adjust other TARGET_ options.  */voidrs6000_override_options (){  int i;  /* Simplify the entries below by making a mask for any POWER     variant and any PowerPC variant.  */#define POWER_MASKS (MASK_POWER | MASK_POWER2 | MASK_MULTIPLE | MASK_STRING)#define POWERPC_MASKS (MASK_POWERPC | MASK_PPC_GPOPT \		       | MASK_PPC_GFXOPT | MASK_POWERPC64)#define POWERPC_OPT_MASKS (MASK_PPC_GPOPT | MASK_PPC_GFXOPT)  static struct ptt    {      char *name;		/* Canonical processor name.  */      enum processor_type processor; /* Processor type enum value.  */      int target_enable;	/* Target flags to enable.  */      int target_disable;	/* Target flags to disable.  */    } processor_target_table[]      = {{"common", PROCESSOR_COMMON, 0, POWER_MASKS | POWERPC_MASKS},	 {"power", PROCESSOR_POWER,	    MASK_POWER | MASK_MULTIPLE | MASK_STRING,	    MASK_POWER2 | POWERPC_MASKS | MASK_NEW_MNEMONICS},	 {"powerpc", PROCESSOR_POWERPC,	    MASK_POWERPC | MASK_NEW_MNEMONICS,	    POWER_MASKS | POWERPC_OPT_MASKS | MASK_POWERPC64},	 {"rios", PROCESSOR_RIOS1,	    MASK_POWER | MASK_MULTIPLE | MASK_STRING,	    MASK_POWER2 | POWERPC_MASKS | MASK_NEW_MNEMONICS},	 {"rios1", PROCESSOR_RIOS1,	    MASK_POWER | MASK_MULTIPLE | MASK_STRING,	    MASK_POWER2 | POWERPC_MASKS | MASK_NEW_MNEMONICS},	 {"rsc", PROCESSOR_PPC601,	    MASK_POWER | MASK_MULTIPLE | MASK_STRING,	    MASK_POWER2 | POWERPC_MASKS | MASK_NEW_MNEMONICS},	 {"rsc1", PROCESSOR_PPC601,	    MASK_POWER | MASK_MULTIPLE | MASK_STRING,	    MASK_POWER2 | POWERPC_MASKS | MASK_NEW_MNEMONICS},	 {"rios2", PROCESSOR_RIOS2,	    MASK_POWER | MASK_MULTIPLE | MASK_STRING | MASK_POWER2,	    POWERPC_MASKS | MASK_NEW_MNEMONICS},	 {"403", PROCESSOR_PPC403,	    MASK_POWERPC | MASK_SOFT_FLOAT | MASK_NEW_MNEMONICS,	    POWER_MASKS | POWERPC_OPT_MASKS | MASK_POWERPC64},	 {"601", PROCESSOR_PPC601,	    MASK_POWER | MASK_POWERPC | MASK_NEW_MNEMONICS | MASK_MULTIPLE | MASK_STRING,	    MASK_POWER2 | POWERPC_OPT_MASKS | MASK_POWERPC64},	 {"603", PROCESSOR_PPC603,	    MASK_POWERPC | MASK_PPC_GFXOPT | MASK_NEW_MNEMONICS,	    POWER_MASKS | MASK_PPC_GPOPT | MASK_POWERPC64},	 {"604", PROCESSOR_PPC604,	    MASK_POWERPC | MASK_PPC_GFXOPT | MASK_NEW_MNEMONICS,	    POWER_MASKS | MASK_PPC_GPOPT | MASK_POWERPC64}};  int ptt_size = sizeof (processor_target_table) / sizeof (struct ptt);  int multiple = TARGET_MULTIPLE;	/* save current -mmultiple/-mno-multiple status */  int string   = TARGET_STRING;		/* save current -mstring/-mno-string status */  profile_block_flag = 0;  /* Identify the processor type */  if (rs6000_cpu_string == 0)    rs6000_cpu = PROCESSOR_DEFAULT;  else    {      for (i = 0; i < ptt_size; i++)	if (! strcmp (rs6000_cpu_string, processor_target_table[i].name))	  {	    rs6000_cpu = processor_target_table[i].processor;	    target_flags |= processor_target_table[i].target_enable;	    target_flags &= ~processor_target_table[i].target_disable;	    break;	  }      if (i == ptt_size)	{	  error ("bad value (%s) for -mcpu= switch", rs6000_cpu_string);	  rs6000_cpu_string = "default";	  rs6000_cpu = PROCESSOR_DEFAULT;	}    }  /* If -mmultiple or -mno-multiple was explicitly used, don't     override with the processor default */  if (TARGET_MULTIPLE_SET)    target_flags = (target_flags & ~MASK_MULTIPLE) | multiple;  /* If -mstring or -mno-string was explicitly used, don't     override with the processor default */  if (TARGET_STRING_SET)    target_flags = (target_flags & ~MASK_STRING) | string;  /* Don't allow -mmultiple or -mstring on little endian systems, because the     hardware doesn't support the instructions used in little endian mode */  if (!BYTES_BIG_ENDIAN)    {      if (TARGET_MULTIPLE)	{	  target_flags &= ~MASK_MULTIPLE;	  if (TARGET_MULTIPLE_SET)	    warning ("-mmultiple is not supported on little endian systems");	}      if (TARGET_STRING)	{	  target_flags &= ~MASK_STRING;	  if (TARGET_STRING_SET)	    warning ("-mstring is not supported on little endian systems");	}    }#ifdef SUBTARGET_OVERRIDE_OPTIONS  SUBTARGET_OVERRIDE_OPTIONS;#endif}/* Create a CONST_DOUBLE from a string.  */struct rtx_def *rs6000_float_const (string, mode)     char *string;     enum machine_mode mode;{  REAL_VALUE_TYPE value = REAL_VALUE_ATOF (string, mode);  return immed_real_const_1 (value, mode);}/* Create a CONST_DOUBLE like immed_double_const, except reverse the   two parts of the constant if the target is little endian.  */struct rtx_def *rs6000_immed_double_const (i0, i1, mode)     HOST_WIDE_INT i0, i1;     enum machine_mode mode;{  if (! WORDS_BIG_ENDIAN)    return immed_double_const (i1, i0, mode);  return immed_double_const (i0, i1, mode);}/* Return non-zero if this function is known to have a null epilogue.  */intdirect_return (){  if (reload_completed)    {      rs6000_stack_t *info = rs6000_stack_info ();      if (info->first_gp_reg_save == 32	  && info->first_fp_reg_save == 64	  && !info->lr_save_p	  && !info->cr_save_p	  && !info->push_p)	return 1;    }  return 0;}/* Returns 1 always.  */intany_operand (op, mode)     register rtx op;     enum machine_mode mode;{  return 1;}/* Return 1 if OP is a constant that can fit in a D field.  */intshort_cint_operand (op, mode)     register rtx op;     enum machine_mode mode;{  return (GET_CODE (op) == CONST_INT	  && (unsigned) (INTVAL (op) + 0x8000) < 0x10000);}/* Similar for a unsigned D field.  */intu_short_cint_operand (op, mode)     register rtx op;     enum machine_mode mode;{  return (GET_CODE (op) == CONST_INT && (INTVAL (op) & 0xffff0000) == 0);}/* Return 1 if OP is a CONST_INT that cannot fit in a signed D field.  */intnon_short_cint_operand (op, mode)     register rtx op;     enum machine_mode mode;{  return (GET_CODE (op) == CONST_INT	  && (unsigned) (INTVAL (op) + 0x8000) >= 0x10000);}/* Returns 1 if OP is a register that is not special (i.e., not MQ,   ctr, or lr).  */intgpc_reg_operand (op, mode)     register rtx op;     enum machine_mode mode;{  return (register_operand (op, mode)	  && (GET_CODE (op) != REG || REGNO (op) >= 67 || REGNO (op) < 64));}/* Returns 1 if OP is either a pseudo-register or a register denoting a   CR field.  */intcc_reg_operand (op, mode)     register rtx op;     enum machine_mode mode;{  return (register_operand (op, mode)	  && (GET_CODE (op) != REG	      || REGNO (op) >= FIRST_PSEUDO_REGISTER	      || CR_REGNO_P (REGNO (op))));}/* Returns 1 if OP is either a constant integer valid for a D-field or a   non-special register.  If a register, it must be in the proper mode unless   MODE is VOIDmode.  */intreg_or_short_operand (op, mode)      register rtx op;      enum machine_mode mode;{  return short_cint_operand (op, mode) || gpc_reg_operand (op, mode);}/* Similar, except check if the negation of the constant would be valid for   a D-field.  */intreg_or_neg_short_operand (op, mode)      register rtx op;      enum machine_mode mode;{  if (GET_CODE (op) == CONST_INT)    return CONST_OK_FOR_LETTER_P (INTVAL (op), 'P');  return gpc_reg_operand (op, mode);}/* Return 1 if the operand is either a register or an integer whose high-order   16 bits are zero.  */intreg_or_u_short_operand (op, mode)     register rtx op;     enum machine_mode mode;{  if (GET_CODE (op) == CONST_INT      && (INTVAL (op) & 0xffff0000) == 0)    return 1;  return gpc_reg_operand (op, mode);}/* Return 1 is the operand is either a non-special register or ANY   constant integer.  */intreg_or_cint_operand (op, mode)    register rtx op;    enum machine_mode mode;{     return GET_CODE (op) == CONST_INT || gpc_reg_operand (op, mode);}/* Return 1 if the operand is a CONST_DOUBLE and it can be put into a register   with one instruction per word.  We only do this if we can safely read   CONST_DOUBLE_{LOW,HIGH}.  */inteasy_fp_constant (op, mode)     register rtx op;     register enum machine_mode mode;{  rtx low, high;  if (GET_CODE (op) != CONST_DOUBLE      || GET_MODE (op) != mode      || GET_MODE_CLASS (mode) != MODE_FLOAT)    return 0;  high = operand_subword (op, 0, 0, mode);

⌨️ 快捷键说明

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