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

📄 rs6000.c

📁 GCC编译器源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
/* Subroutines used for code generation on IBM RS/6000.   Copyright (C) 1991, 93, 94, 95, 96, 1997 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"#include "except.h"#include "function.h"#ifndef TARGET_NO_PROTOTYPE#define TARGET_NO_PROTOTYPE 0#endifextern 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;struct rs6000_cpu_select rs6000_select[3] ={  /* switch	name,			tune	arch */  { (char *)0,	"--with-cpu=",		1,	1 },  { (char *)0,	"-mcpu=",		1,	1 },  { (char *)0,	"-mtune=",		1,	0 },};/* 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;int rs6000_pic_func_labelno;/* Which abi to adhere to */char *rs6000_abi_name = RS6000_ABI_NAME;/* Semantics of the small data area */enum rs6000_sdata_type rs6000_sdata = SDATA_DATA;/* Which small data model to use */char *rs6000_sdata_name = (char *)0;#endif/* Whether a System V.4 varargs area was created.  */int rs6000_sysv_varargs_p;/* ABI enumeration available for subtarget to use.  */enum rs6000_abi rs6000_current_abi;/* Offset & size for fpmem stack locations used for converting between   float and integral types.  */int rs6000_fpmem_offset;int rs6000_fpmem_size;/* Debug flags */char *rs6000_debug_name;int rs6000_debug_stack;		/* debug stack applications */int rs6000_debug_arg;		/* debug argument handling *//* Flag to say the TOC is initialized */int toc_initialized;/* Default register names.  */char rs6000_reg_names[][8] ={      "0",  "1",  "2",  "3",  "4",  "5",  "6",  "7",      "8",  "9", "10", "11", "12", "13", "14", "15",     "16", "17", "18", "19", "20", "21", "22", "23",     "24", "25", "26", "27", "28", "29", "30", "31",      "0",  "1",  "2",  "3",  "4",  "5",  "6",  "7",      "8",  "9", "10", "11", "12", "13", "14", "15",     "16", "17", "18", "19", "20", "21", "22", "23",     "24", "25", "26", "27", "28", "29", "30", "31",     "mq", "lr", "ctr","ap",      "0",  "1",  "2",  "3",  "4",  "5",  "6",  "7",  "fpmem"};#ifdef TARGET_REGNAMESstatic char alt_reg_names[][8] ={   "%r0",   "%r1",  "%r2",  "%r3",  "%r4",  "%r5",  "%r6",  "%r7",   "%r8",   "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15",  "%r16",  "%r17", "%r18", "%r19", "%r20", "%r21", "%r22", "%r23",  "%r24",  "%r25", "%r26", "%r27", "%r28", "%r29", "%r30", "%r31",   "%f0",   "%f1",  "%f2",  "%f3",  "%f4",  "%f5",  "%f6",  "%f7",   "%f8",   "%f9", "%f10", "%f11", "%f12", "%f13", "%f14", "%f15",  "%f16",  "%f17", "%f18", "%f19", "%f20", "%f21", "%f22", "%f23",  "%f24",  "%f25", "%f26", "%f27", "%f28", "%f29", "%f30", "%f31",    "mq",    "lr",  "ctr",   "ap",  "%cr0",  "%cr1", "%cr2", "%cr3", "%cr4", "%cr5", "%cr6", "%cr7", "fpmem"};#endif#ifndef MASK_STRICT_ALIGN#define MASK_STRICT_ALIGN 0#endif/* Override command line options.  Mostly we process the processor   type and sometimes adjust other TARGET_ options.  */voidrs6000_override_options (default_cpu)     char *default_cpu;{  int i, j;  struct rs6000_cpu_select *ptr;  /* 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, MASK_NEW_MNEMONICS,	    POWER_MASKS | POWERPC_MASKS},	 {"power", PROCESSOR_POWER,	    MASK_POWER | MASK_MULTIPLE | MASK_STRING,	    MASK_POWER2 | POWERPC_MASKS | MASK_NEW_MNEMONICS},	 {"power2", PROCESSOR_POWER,	    MASK_POWER | MASK_POWER2 | MASK_MULTIPLE | MASK_STRING,	    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 | MASK_STRICT_ALIGN,	    POWER_MASKS | POWERPC_OPT_MASKS | MASK_POWERPC64},	 {"505", PROCESSOR_MPCCORE,	    MASK_POWERPC | 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},	 {"602", PROCESSOR_PPC603,	    MASK_POWERPC | MASK_PPC_GFXOPT | MASK_NEW_MNEMONICS,	    POWER_MASKS | MASK_PPC_GPOPT | MASK_POWERPC64},	 {"603", PROCESSOR_PPC603,	    MASK_POWERPC | MASK_PPC_GFXOPT | MASK_NEW_MNEMONICS,	    POWER_MASKS | MASK_PPC_GPOPT | MASK_POWERPC64},	 {"603e", 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},	 {"604e", PROCESSOR_PPC604,	    MASK_POWERPC | MASK_PPC_GFXOPT | MASK_NEW_MNEMONICS,	    POWER_MASKS | MASK_PPC_GPOPT | MASK_POWERPC64},	 {"620", PROCESSOR_PPC620,	    MASK_POWERPC | MASK_PPC_GFXOPT | MASK_NEW_MNEMONICS,	    POWER_MASKS | MASK_PPC_GPOPT | MASK_POWERPC64},	 {"801", PROCESSOR_MPCCORE,	    MASK_POWERPC | MASK_SOFT_FLOAT | MASK_NEW_MNEMONICS,	    POWER_MASKS | POWERPC_OPT_MASKS | MASK_POWERPC64},	 {"821", PROCESSOR_MPCCORE,	    MASK_POWERPC | MASK_SOFT_FLOAT | MASK_NEW_MNEMONICS,	    POWER_MASKS | POWERPC_OPT_MASKS | MASK_POWERPC64},	 {"823", PROCESSOR_MPCCORE,	    MASK_POWERPC | MASK_SOFT_FLOAT | MASK_NEW_MNEMONICS,	    POWER_MASKS | POWERPC_OPT_MASKS | MASK_POWERPC64},	 {"860", PROCESSOR_MPCCORE,	    MASK_POWERPC | MASK_SOFT_FLOAT | MASK_NEW_MNEMONICS,	    POWER_MASKS | POWERPC_OPT_MASKS | 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 */  rs6000_select[0].string = default_cpu;  rs6000_cpu = PROCESSOR_DEFAULT;  for (i = 0; i < sizeof (rs6000_select) / sizeof (rs6000_select[0]); i++)    {      ptr = &rs6000_select[i];      if (ptr->string != (char *)0 && ptr->string[0] != '\0')	{	  for (j = 0; j < ptt_size; j++)	    if (! strcmp (ptr->string, processor_target_table[j].name))	      {		if (ptr->set_tune_p)		  rs6000_cpu = processor_target_table[j].processor;		if (ptr->set_arch_p)		  {		    target_flags |= processor_target_table[j].target_enable;		    target_flags &= ~processor_target_table[j].target_disable;		  }		break;	      }	  if (i == ptt_size)	    error ("bad value (%s) for %s switch", ptr->string, ptr->name);	}    }  /* 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");	}    }  /* Set debug flags */  if (rs6000_debug_name)    {      if (!strcmp (rs6000_debug_name, "all"))	rs6000_debug_stack = rs6000_debug_arg = 1;      else if (!strcmp (rs6000_debug_name, "stack"))	rs6000_debug_stack = 1;      else if (!strcmp (rs6000_debug_name, "arg"))	rs6000_debug_arg = 1;      else	error ("Unknown -mdebug-%s switch", rs6000_debug_name);    }#ifdef TARGET_REGNAMES  /* If the user desires alternate register names, copy in the alternate names     now.  */  if (TARGET_REGNAMES)    bcopy ((char *)alt_reg_names, (char *)rs6000_reg_names, sizeof (rs6000_reg_names));#endif#ifdef SUBTARGET_OVERRIDE_OPTIONS  SUBTARGET_OVERRIDE_OPTIONS;#endif}/* Do anything needed at the start of the asm file.  */voidrs6000_file_start (file, default_cpu)     FILE *file;     char *default_cpu;{  int i;  char buffer[80];  char *start = buffer;  struct rs6000_cpu_select *ptr;  if (flag_verbose_asm)    {      sprintf (buffer, "\n%s rs6000/powerpc options:", ASM_COMMENT_START);      rs6000_select[0].string = default_cpu;      for (i = 0; i < sizeof (rs6000_select) / sizeof (rs6000_select[0]); i++)	{	  ptr = &rs6000_select[i];	  if (ptr->string != (char *)0 && ptr->string[0] != '\0')	    {	      fprintf (file, "%s %s%s", start, ptr->name, ptr->string);	      start = "";	    }	}#ifdef USING_SVR4_H      switch (rs6000_sdata)	{	case SDATA_NONE: fprintf (file, "%s -msdata=none", start); start = ""; break;	case SDATA_DATA: fprintf (file, "%s -msdata=data", start); start = ""; break;	case SDATA_SYSV: fprintf (file, "%s -msdata=sysv", start); start = ""; break;	case SDATA_EABI: fprintf (file, "%s -msdata=eabi", start); start = ""; break;	}      if (rs6000_sdata && g_switch_value)	{	  fprintf (file, "%s -G %d", start, g_switch_value);	  start = "";	}#endif      if (*start == '\0')	fputs ("\n", file);    }}/* 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;}/* Returns 1 if op is the count register */intcount_register_operand(op, mode)     register rtx op;     enum machine_mode mode;{  if (GET_CODE (op) != REG)    return 0;  if (REGNO (op) == COUNT_REGISTER_REGNUM)    return 1;  if (REGNO (op) > FIRST_PSEUDO_REGISTER)    return 1;  return 0;}/* Returns 1 if op is memory location for float/int conversions that masquerades   as a register.  */intfpmem_operand(op, mode)     register rtx op;     enum machine_mode mode;{  if (GET_CODE (op) != REG)    return 0;  if (FPMEM_REGNO_P (REGNO (op)))    return 1;#if 0  if (REGNO (op) > FIRST_PSEUDO_REGISTER)    return 1;

⌨️ 快捷键说明

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