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

📄 sparc.c

📁 linux下的gcc编译器
💻 C
📖 第 1 页 / 共 5 页
字号:
/* Subroutines for insn-output.c for Sun SPARC.   Copyright (C) 1987, 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,   1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.   Contributed by Michael Tiemann (tiemann@cygnus.com)   64-bit SPARC-V9 support by Michael Tiemann, Jim Wilson, and Doug Evans,   at Cygnus Support.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 "tree.h"#include "rtl.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 "function.h"#include "expr.h"#include "optabs.h"#include "libfuncs.h"#include "recog.h"#include "toplev.h"#include "ggc.h"#include "tm_p.h"#include "debug.h"#include "target.h"#include "target-def.h"/* 1 if the caller has placed an "unimp" insn immediately after the call.   This is used in v8 code when calling a function that returns a structure.   v9 doesn't have this.  Be careful to have this test be the same as that   used on the call.  */#define SKIP_CALLERS_UNIMP_P  \(!TARGET_ARCH64 && current_function_returns_struct			\ && ! integer_zerop (DECL_SIZE (DECL_RESULT (current_function_decl)))	\ && (TREE_CODE (DECL_SIZE (DECL_RESULT (current_function_decl)))	\     == INTEGER_CST))/* Global variables for machine-dependent things.  *//* Size of frame.  Need to know this to emit return insns from leaf procedures.   ACTUAL_FSIZE is set by compute_frame_size() which is called during the   reload pass.  This is important as the value is later used in insn   scheduling (to see what can go in a delay slot).   APPARENT_FSIZE is the size of the stack less the register save area and less   the outgoing argument area.  It is used when saving call preserved regs.  */static int apparent_fsize;static int actual_fsize;/* Number of live general or floating point registers needed to be   saved (as 4-byte quantities).  */static int num_gfregs;/* Save the operands last given to a compare for use when we   generate a scc or bcc insn.  */rtx sparc_compare_op0, sparc_compare_op1;/* Coordinate with the md file wrt special insns created by   sparc_nonflat_function_epilogue.  */bool sparc_emitting_epilogue;/* Vector to say how input registers are mapped to output registers.   HARD_FRAME_POINTER_REGNUM cannot be remapped by this function to   eliminate it.  You must use -fomit-frame-pointer to get that.  */char leaf_reg_remap[] ={ 0, 1, 2, 3, 4, 5, 6, 7,  -1, -1, -1, -1, -1, -1, 14, -1,  -1, -1, -1, -1, -1, -1, -1, -1,  8, 9, 10, 11, 12, 13, -1, 15,  32, 33, 34, 35, 36, 37, 38, 39,  40, 41, 42, 43, 44, 45, 46, 47,  48, 49, 50, 51, 52, 53, 54, 55,  56, 57, 58, 59, 60, 61, 62, 63,  64, 65, 66, 67, 68, 69, 70, 71,  72, 73, 74, 75, 76, 77, 78, 79,  80, 81, 82, 83, 84, 85, 86, 87,  88, 89, 90, 91, 92, 93, 94, 95,  96, 97, 98, 99, 100};/* Vector, indexed by hard register number, which contains 1   for a register that is allowable in a candidate for leaf   function treatment.  */char sparc_leaf_regs[] ={ 1, 1, 1, 1, 1, 1, 1, 1,  0, 0, 0, 0, 0, 0, 1, 0,  0, 0, 0, 0, 0, 0, 0, 0,  1, 1, 1, 1, 1, 1, 0, 1,  1, 1, 1, 1, 1, 1, 1, 1,  1, 1, 1, 1, 1, 1, 1, 1,  1, 1, 1, 1, 1, 1, 1, 1,  1, 1, 1, 1, 1, 1, 1, 1,  1, 1, 1, 1, 1, 1, 1, 1,  1, 1, 1, 1, 1, 1, 1, 1,  1, 1, 1, 1, 1, 1, 1, 1,  1, 1, 1, 1, 1, 1, 1, 1,  1, 1, 1, 1, 1};/* Name of where we pretend to think the frame pointer points.   Normally, this is "%fp", but if we are in a leaf procedure,   this is "%sp+something".  We record "something" separately as it may be   too big for reg+constant addressing.  */static const char *frame_base_name;static int frame_base_offset;static void sparc_init_modes	PARAMS ((void));static int save_regs		PARAMS ((FILE *, int, int, const char *,				       int, int, int));static int restore_regs		PARAMS ((FILE *, int, int, const char *, int, int));static void build_big_number	PARAMS ((FILE *, int, const char *));static int function_arg_slotno	PARAMS ((const CUMULATIVE_ARGS *,				       enum machine_mode, tree, int, int,				       int *, int *));static int supersparc_adjust_cost PARAMS ((rtx, rtx, rtx, int));static int hypersparc_adjust_cost PARAMS ((rtx, rtx, rtx, int));static void sparc_output_addr_vec PARAMS ((rtx));static void sparc_output_addr_diff_vec PARAMS ((rtx));static void sparc_output_deferred_case_vectors PARAMS ((void));static int check_return_regs PARAMS ((rtx));static int epilogue_renumber PARAMS ((rtx *, int));static bool sparc_assemble_integer PARAMS ((rtx, unsigned int, int));static int set_extends PARAMS ((rtx));static void output_restore_regs PARAMS ((FILE *, int));static void sparc_output_function_prologue PARAMS ((FILE *, HOST_WIDE_INT));static void sparc_output_function_epilogue PARAMS ((FILE *, HOST_WIDE_INT));static void sparc_flat_function_epilogue PARAMS ((FILE *, HOST_WIDE_INT));static void sparc_flat_function_prologue PARAMS ((FILE *, HOST_WIDE_INT));static void sparc_nonflat_function_epilogue PARAMS ((FILE *, HOST_WIDE_INT,						     int));static void sparc_nonflat_function_prologue PARAMS ((FILE *, HOST_WIDE_INT,						     int));#ifdef OBJECT_FORMAT_ELFstatic void sparc_elf_asm_named_section PARAMS ((const char *, unsigned int));#endifstatic void sparc_aout_select_section PARAMS ((tree, int,					       unsigned HOST_WIDE_INT))     ATTRIBUTE_UNUSED;static void sparc_aout_select_rtx_section PARAMS ((enum machine_mode, rtx,						   unsigned HOST_WIDE_INT))     ATTRIBUTE_UNUSED;static int sparc_adjust_cost PARAMS ((rtx, rtx, rtx, int));static int sparc_issue_rate PARAMS ((void));static void sparc_sched_init PARAMS ((FILE *, int, int));static int sparc_use_dfa_pipeline_interface PARAMS ((void));static int sparc_use_sched_lookahead PARAMS ((void));static void emit_soft_tfmode_libcall PARAMS ((const char *, int, rtx *));static void emit_soft_tfmode_binop PARAMS ((enum rtx_code, rtx *));static void emit_soft_tfmode_unop PARAMS ((enum rtx_code, rtx *));static void emit_soft_tfmode_cvt PARAMS ((enum rtx_code, rtx *));static void emit_hard_tfmode_operation PARAMS ((enum rtx_code, rtx *));static void sparc_encode_section_info PARAMS ((tree, int));static void sparc_output_mi_thunk PARAMS ((FILE *, tree, HOST_WIDE_INT,					   HOST_WIDE_INT, tree));static bool sparc_can_output_mi_thunk PARAMS ((tree, HOST_WIDE_INT,					       HOST_WIDE_INT, tree));/* Option handling.  *//* Code model option as passed by user.  */const char *sparc_cmodel_string;/* Parsed value.  */enum cmodel sparc_cmodel;char sparc_hard_reg_printed[8];struct sparc_cpu_select sparc_select[] ={  /* switch	name,		tune	arch */  { (char *)0,	"default",	1,	1 },  { (char *)0,	"-mcpu=",	1,	1 },  { (char *)0,	"-mtune=",	1,	0 },  { 0, 0, 0, 0 }};/* CPU type.  This is set from TARGET_CPU_DEFAULT and -m{cpu,tune}=xxx.  */enum processor_type sparc_cpu;/* Initialize the GCC target structure.  *//* The sparc default is to use .half rather than .short for aligned   HI objects.  Use .word instead of .long on non-ELF systems.  */#undef TARGET_ASM_ALIGNED_HI_OP#define TARGET_ASM_ALIGNED_HI_OP "\t.half\t"#ifndef OBJECT_FORMAT_ELF#undef TARGET_ASM_ALIGNED_SI_OP#define TARGET_ASM_ALIGNED_SI_OP "\t.word\t"#endif#undef TARGET_ASM_UNALIGNED_HI_OP#define TARGET_ASM_UNALIGNED_HI_OP "\t.uahalf\t"#undef TARGET_ASM_UNALIGNED_SI_OP#define TARGET_ASM_UNALIGNED_SI_OP "\t.uaword\t"#undef TARGET_ASM_UNALIGNED_DI_OP#define TARGET_ASM_UNALIGNED_DI_OP "\t.uaxword\t"/* The target hook has to handle DI-mode values.  */#undef TARGET_ASM_INTEGER#define TARGET_ASM_INTEGER sparc_assemble_integer#undef TARGET_ASM_FUNCTION_PROLOGUE#define TARGET_ASM_FUNCTION_PROLOGUE sparc_output_function_prologue#undef TARGET_ASM_FUNCTION_EPILOGUE#define TARGET_ASM_FUNCTION_EPILOGUE sparc_output_function_epilogue#undef TARGET_SCHED_ADJUST_COST#define TARGET_SCHED_ADJUST_COST sparc_adjust_cost#undef TARGET_SCHED_ISSUE_RATE#define TARGET_SCHED_ISSUE_RATE sparc_issue_rate#undef TARGET_SCHED_INIT#define TARGET_SCHED_INIT sparc_sched_init#undef TARGET_SCHED_USE_DFA_PIPELINE_INTERFACE#define TARGET_SCHED_USE_DFA_PIPELINE_INTERFACE sparc_use_dfa_pipeline_interface#undef TARGET_SCHED_FIRST_CYCLE_MULTIPASS_DFA_LOOKAHEAD#define TARGET_SCHED_FIRST_CYCLE_MULTIPASS_DFA_LOOKAHEAD sparc_use_sched_lookahead#undef TARGET_ENCODE_SECTION_INFO#define TARGET_ENCODE_SECTION_INFO sparc_encode_section_info#undef TARGET_ASM_OUTPUT_MI_THUNK#define TARGET_ASM_OUTPUT_MI_THUNK sparc_output_mi_thunk#undef TARGET_ASM_CAN_OUTPUT_MI_THUNK#define TARGET_ASM_CAN_OUTPUT_MI_THUNK sparc_can_output_mi_thunkstruct gcc_target targetm = TARGET_INITIALIZER;/* Validate and override various options, and do some machine dependent   initialization.  */voidsparc_override_options (){  static struct code_model {    const char *const name;    const int value;  } const cmodels[] = {    { "32", CM_32 },    { "medlow", CM_MEDLOW },    { "medmid", CM_MEDMID },    { "medany", CM_MEDANY },    { "embmedany", CM_EMBMEDANY },    { 0, 0 }  };  const struct code_model *cmodel;  /* Map TARGET_CPU_DEFAULT to value for -m{arch,tune}=.  */  static struct cpu_default {    const int cpu;    const char *const name;  } const cpu_default[] = {    /* There must be one entry here for each TARGET_CPU value.  */    { TARGET_CPU_sparc, "cypress" },    { TARGET_CPU_sparclet, "tsc701" },    { TARGET_CPU_sparclite, "f930" },    { TARGET_CPU_v8, "v8" },    { TARGET_CPU_hypersparc, "hypersparc" },    { TARGET_CPU_sparclite86x, "sparclite86x" },    { TARGET_CPU_supersparc, "supersparc" },    { TARGET_CPU_v9, "v9" },    { TARGET_CPU_ultrasparc, "ultrasparc" },    { TARGET_CPU_ultrasparc3, "ultrasparc3" },    { 0, 0 }  };  const struct cpu_default *def;  /* Table of values for -m{cpu,tune}=.  */  static struct cpu_table {    const char *const name;    const enum processor_type processor;    const int disable;    const int enable;  } const cpu_table[] = {    { "v7",         PROCESSOR_V7, MASK_ISA, 0 },    { "cypress",    PROCESSOR_CYPRESS, MASK_ISA, 0 },    { "v8",         PROCESSOR_V8, MASK_ISA, MASK_V8 },    /* TI TMS390Z55 supersparc */    { "supersparc", PROCESSOR_SUPERSPARC, MASK_ISA, MASK_V8 },    { "sparclite",  PROCESSOR_SPARCLITE, MASK_ISA, MASK_SPARCLITE },    /* The Fujitsu MB86930 is the original sparclite chip, with no fpu.       The Fujitsu MB86934 is the recent sparclite chip, with an fpu.  */    { "f930",       PROCESSOR_F930, MASK_ISA|MASK_FPU, MASK_SPARCLITE },    { "f934",       PROCESSOR_F934, MASK_ISA, MASK_SPARCLITE|MASK_FPU },    { "hypersparc", PROCESSOR_HYPERSPARC, MASK_ISA, MASK_V8|MASK_FPU },    { "sparclite86x",  PROCESSOR_SPARCLITE86X, MASK_ISA|MASK_FPU,      MASK_SPARCLITE },    { "sparclet",   PROCESSOR_SPARCLET, MASK_ISA, MASK_SPARCLET },    /* TEMIC sparclet */    { "tsc701",     PROCESSOR_TSC701, MASK_ISA, MASK_SPARCLET },    { "v9",         PROCESSOR_V9, MASK_ISA, MASK_V9 },    /* TI ultrasparc I, II, IIi */    { "ultrasparc", PROCESSOR_ULTRASPARC, MASK_ISA, MASK_V9    /* Although insns using %y are deprecated, it is a clear win on current       ultrasparcs.  */    						    |MASK_DEPRECATED_V8_INSNS},    /* TI ultrasparc III */    /* ??? Check if %y issue still holds true in ultra3.  */    { "ultrasparc3", PROCESSOR_ULTRASPARC3, MASK_ISA, MASK_V9|MASK_DEPRECATED_V8_INSNS},    { 0, 0, 0, 0 }  };  const struct cpu_table *cpu;  const struct sparc_cpu_select *sel;  int fpu;  #ifndef SPARC_BI_ARCH  /* Check for unsupported architecture size.  */  if (! TARGET_64BIT != DEFAULT_ARCH32_P)    error ("%s is not supported by this configuration",	   DEFAULT_ARCH32_P ? "-m64" : "-m32");#endif  /* We force all 64bit archs to use 128 bit long double */  if (TARGET_64BIT && ! TARGET_LONG_DOUBLE_128)    {      error ("-mlong-double-64 not allowed with -m64");      target_flags |= MASK_LONG_DOUBLE_128;    }  /* Code model selection.  */  sparc_cmodel = SPARC_DEFAULT_CMODEL;  #ifdef SPARC_BI_ARCH  if (TARGET_ARCH32)    sparc_cmodel = CM_32;#endif  if (sparc_cmodel_string != NULL)    {      if (TARGET_ARCH64)	{	  for (cmodel = &cmodels[0]; cmodel->name; cmodel++)	    if (strcmp (sparc_cmodel_string, cmodel->name) == 0)	      break;	  if (cmodel->name == NULL)	    error ("bad value (%s) for -mcmodel= switch", sparc_cmodel_string);	  else	    sparc_cmodel = cmodel->value;	}      else	error ("-mcmodel= is not supported on 32 bit systems");    }  fpu = TARGET_FPU; /* save current -mfpu status */  /* Set the default CPU.  */  for (def = &cpu_default[0]; def->name; ++def)    if (def->cpu == TARGET_CPU_DEFAULT)      break;  if (! def->name)    abort ();  sparc_select[0].string = def->name;  for (sel = &sparc_select[0]; sel->name; ++sel)    {      if (sel->string)	{	  for (cpu = &cpu_table[0]; cpu->name; ++cpu)	    if (! strcmp (sel->string, cpu->name))	      {		if (sel->set_tune_p)		  sparc_cpu = cpu->processor;		if (sel->set_arch_p)		  {		    target_flags &= ~cpu->disable;		    target_flags |= cpu->enable;		  }		break;	      }	  if (! cpu->name)	    error ("bad value (%s) for %s switch", sel->string, sel->name);	}    }  /* If -mfpu or -mno-fpu was explicitly used, don't override with     the processor default.  Clear MASK_FPU_SET to avoid confusing     the reverse mapping from switch values to names.  */  if (TARGET_FPU_SET)    {      target_flags = (target_flags & ~MASK_FPU) | fpu;      target_flags &= ~MASK_FPU_SET;    }  /* Don't allow -mvis if FPU is disabled.  */  if (! TARGET_FPU)    target_flags &= ~MASK_VIS;  /* -mvis assumes UltraSPARC+, so we are sure v9 instructions     are available.     -m64 also implies v9.  */  if (TARGET_VIS || TARGET_ARCH64)    {      target_flags |= MASK_V9;      target_flags &= ~(MASK_V8 | MASK_SPARCLET | MASK_SPARCLITE);    }  /* Use the deprecated v8 insns for sparc64 in 32 bit mode.  */  if (TARGET_V9 && TARGET_ARCH32)    target_flags |= MASK_DEPRECATED_V8_INSNS;  /* V8PLUS requires V9, makes no sense in 64 bit mode.  */  if (! TARGET_V9 || TARGET_ARCH64)    target_flags &= ~MASK_V8PLUS;  /* Don't use stack biasing in 32 bit mode.  */  if (TARGET_ARCH32)    target_flags &= ~MASK_STACK_BIAS;      /* Supply a default value for align_functions.  */  if (align_functions == 0      && (sparc_cpu == PROCESSOR_ULTRASPARC	  || sparc_cpu == PROCESSOR_ULTRASPARC3))    align_functions = 32;  /* Validate PCC_STRUCT_RETURN.  */  if (flag_pcc_struct_return == DEFAULT_PCC_STRUCT_RETURN)    flag_pcc_struct_return = (TARGET_ARCH64 ? 0 : 1);  /* Only use .uaxword when compiling for a 64-bit target.  */  if (!TARGET_ARCH64)    targetm.asm_out.unaligned_op.di = NULL;  /* Do various machine dependent initializations.  */  sparc_init_modes ();}/* Miscellaneous utilities.  *//* Nonzero if CODE, a comparison, is suitable for use in v9 conditional move   or branch on register contents instructions.  */intv9_regcmp_p (code)     enum rtx_code code;{  return (code == EQ || code == NE || code == GE || code == LT	  || code == LE || code == GT);}/* Operand constraints.  *//* Return nonzero only if OP is a register of mode MODE,

⌨️ 快捷键说明

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