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

📄 arc.c

📁 Mac OS X 10.4.9 for x86 Source Code gcc 实现源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
/* Subroutines used for code generation on the Argonaut ARC cpu.   Copyright (C) 1994, 1995, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004   Free Software Foundation, Inc.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.  *//* ??? This is an old port, and is undoubtedly suffering from bit rot.  */#include "config.h"#include "system.h"#include "coretypes.h"#include "tm.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 "recog.h"#include "toplev.h"#include "tm_p.h"#include "target.h"#include "target-def.h"/* Which cpu we're compiling for (NULL(=base), ???).  */const char *arc_cpu_string;int arc_cpu_type;/* Name of mangle string to add to symbols to separate code compiled for each   cpu (or NULL).  */const char *arc_mangle_cpu;/* Save the operands last given to a compare for use when we   generate a scc or bcc insn.  */rtx arc_compare_op0, arc_compare_op1;/* Name of text, data, and rodata sections, as specified on command line.   Selected by -m{text,data,rodata} flags.  */const char *arc_text_string = ARC_DEFAULT_TEXT_SECTION;const char *arc_data_string = ARC_DEFAULT_DATA_SECTION;const char *arc_rodata_string = ARC_DEFAULT_RODATA_SECTION;/* Name of text, data, and rodata sections used in varasm.c.  */const char *arc_text_section;const char *arc_data_section;const char *arc_rodata_section;/* Array of valid operand punctuation characters.  */char arc_punct_chars[256];/* Variables used by arc_final_prescan_insn to implement conditional   execution.  */static int arc_ccfsm_state;static int arc_ccfsm_current_cc;static rtx arc_ccfsm_target_insn;static int arc_ccfsm_target_label;/* The maximum number of insns skipped which will be conditionalised if   possible.  */#define MAX_INSNS_SKIPPED 3/* A nop is needed between a 4 byte insn that sets the condition codes and   a branch that uses them (the same isn't true for an 8 byte insn that sets   the condition codes).  Set by arc_final_prescan_insn.  Used by   arc_print_operand.  */static int last_insn_set_cc_p;static int current_insn_set_cc_p;static void record_cc_ref (rtx);static void arc_init_reg_tables (void);static int get_arc_condition_code (rtx);const struct attribute_spec arc_attribute_table[];static tree arc_handle_interrupt_attribute (tree *, tree, tree, int, bool *);static bool arc_assemble_integer (rtx, unsigned int, int);static void arc_output_function_prologue (FILE *, HOST_WIDE_INT);static void arc_output_function_epilogue (FILE *, HOST_WIDE_INT);static void arc_file_start (void);static void arc_internal_label (FILE *, const char *, unsigned long);static void arc_setup_incoming_varargs (CUMULATIVE_ARGS *, enum machine_mode,					tree, int *, int);static bool arc_rtx_costs (rtx, int, int, int *);static int arc_address_cost (rtx);static void arc_external_libcall (rtx);static bool arc_return_in_memory (tree, tree);static bool arc_pass_by_reference (CUMULATIVE_ARGS *, enum machine_mode,				   tree, bool);/* Initialize the GCC target structure.  */#undef TARGET_ASM_ALIGNED_HI_OP#define TARGET_ASM_ALIGNED_HI_OP "\t.hword\t"#undef TARGET_ASM_ALIGNED_SI_OP#define TARGET_ASM_ALIGNED_SI_OP "\t.word\t"#undef TARGET_ASM_INTEGER#define TARGET_ASM_INTEGER arc_assemble_integer#undef TARGET_ASM_FUNCTION_PROLOGUE#define TARGET_ASM_FUNCTION_PROLOGUE arc_output_function_prologue#undef TARGET_ASM_FUNCTION_EPILOGUE#define TARGET_ASM_FUNCTION_EPILOGUE arc_output_function_epilogue#undef TARGET_ASM_FILE_START#define TARGET_ASM_FILE_START arc_file_start#undef TARGET_ATTRIBUTE_TABLE#define TARGET_ATTRIBUTE_TABLE arc_attribute_table#undef TARGET_ASM_INTERNAL_LABEL#define TARGET_ASM_INTERNAL_LABEL arc_internal_label#undef TARGET_ASM_EXTERNAL_LIBCALL#define TARGET_ASM_EXTERNAL_LIBCALL arc_external_libcall#undef TARGET_RTX_COSTS#define TARGET_RTX_COSTS arc_rtx_costs#undef TARGET_ADDRESS_COST#define TARGET_ADDRESS_COST arc_address_cost#undef TARGET_PROMOTE_FUNCTION_ARGS#define TARGET_PROMOTE_FUNCTION_ARGS hook_bool_tree_true#undef TARGET_PROMOTE_FUNCTION_RETURN#define TARGET_PROMOTE_FUNCTION_RETURN hook_bool_tree_true#undef TARGET_PROMOTE_PROTOTYPES#define TARGET_PROMOTE_PROTOTYPES hook_bool_tree_true#undef TARGET_RETURN_IN_MEMORY#define TARGET_RETURN_IN_MEMORY arc_return_in_memory#undef TARGET_PASS_BY_REFERENCE#define TARGET_PASS_BY_REFERENCE arc_pass_by_reference#undef TARGET_CALLEE_COPIES#define TARGET_CALLEE_COPIES hook_bool_CUMULATIVE_ARGS_mode_tree_bool_true#undef TARGET_SETUP_INCOMING_VARARGS#define TARGET_SETUP_INCOMING_VARARGS arc_setup_incoming_varargsstruct gcc_target targetm = TARGET_INITIALIZER;/* Called by OVERRIDE_OPTIONS to initialize various things.  */voidarc_init (void){  char *tmp;    if (arc_cpu_string == 0      || !strcmp (arc_cpu_string, "base"))    {      /* Ensure we have a printable value for the .cpu pseudo-op.  */      arc_cpu_string = "base";      arc_cpu_type = 0;      arc_mangle_cpu = NULL;    }  else if (ARC_EXTENSION_CPU (arc_cpu_string))    ; /* nothing to do */  else    {      error ("bad value (%s) for -mcpu switch", arc_cpu_string);      arc_cpu_string = "base";      arc_cpu_type = 0;      arc_mangle_cpu = NULL;    }  /* Set the pseudo-ops for the various standard sections.  */  arc_text_section = tmp = xmalloc (strlen (arc_text_string) + sizeof (ARC_SECTION_FORMAT) + 1);  sprintf (tmp, ARC_SECTION_FORMAT, arc_text_string);  arc_data_section = tmp = xmalloc (strlen (arc_data_string) + sizeof (ARC_SECTION_FORMAT) + 1);  sprintf (tmp, ARC_SECTION_FORMAT, arc_data_string);  arc_rodata_section = tmp = xmalloc (strlen (arc_rodata_string) + sizeof (ARC_SECTION_FORMAT) + 1);  sprintf (tmp, ARC_SECTION_FORMAT, arc_rodata_string);  arc_init_reg_tables ();  /* Initialize array for PRINT_OPERAND_PUNCT_VALID_P.  */  memset (arc_punct_chars, 0, sizeof (arc_punct_chars));  arc_punct_chars['#'] = 1;  arc_punct_chars['*'] = 1;  arc_punct_chars['?'] = 1;  arc_punct_chars['!'] = 1;  arc_punct_chars['~'] = 1;}/* The condition codes of the ARC, and the inverse function.  */static const char *const arc_condition_codes[] ={  "al", 0, "eq", "ne", "p", "n", "c", "nc", "v", "nv",  "gt", "le", "ge", "lt", "hi", "ls", "pnz", 0};#define ARC_INVERSE_CONDITION_CODE(X)  ((X) ^ 1)/* Returns the index of the ARC condition code string in   `arc_condition_codes'.  COMPARISON should be an rtx like   `(eq (...) (...))'.  */static intget_arc_condition_code (rtx comparison){  switch (GET_CODE (comparison))    {    case EQ : return 2;    case NE : return 3;    case GT : return 10;    case LE : return 11;    case GE : return 12;    case LT : return 13;    case GTU : return 14;    case LEU : return 15;    case LTU : return 6;    case GEU : return 7;    default : abort ();    }  /*NOTREACHED*/  return (42);}/* Given a comparison code (EQ, NE, etc.) and the first operand of a COMPARE,   return the mode to be used for the comparison.  */enum machine_modearc_select_cc_mode (enum rtx_code op,	            rtx x ATTRIBUTE_UNUSED,                    rtx y ATTRIBUTE_UNUSED){  switch (op)    {    case EQ :    case NE :      return CCZNmode;    default :      switch (GET_CODE (x))	{	case AND :	case IOR :	case XOR :	case SIGN_EXTEND :	case ZERO_EXTEND :	  return CCZNmode;	case ASHIFT :	case ASHIFTRT :	case LSHIFTRT :	  return CCZNCmode;	default:	  break;	}    }  return CCmode;}/* Vectors to keep interesting information about registers where it can easily   be got.  We use to use the actual mode value as the bit number, but there   is (or may be) more than 32 modes now.  Instead we use two tables: one   indexed by hard register number, and one indexed by mode.  *//* The purpose of arc_mode_class is to shrink the range of modes so that   they all fit (as bit numbers) in a 32 bit word (again).  Each real mode is   mapped into one arc_mode_class mode.  */enum arc_mode_class {  C_MODE,  S_MODE, D_MODE, T_MODE, O_MODE,  SF_MODE, DF_MODE, TF_MODE, OF_MODE};/* Modes for condition codes.  */#define C_MODES (1 << (int) C_MODE)/* Modes for single-word and smaller quantities.  */#define S_MODES ((1 << (int) S_MODE) | (1 << (int) SF_MODE))/* Modes for double-word and smaller quantities.  */#define D_MODES (S_MODES | (1 << (int) D_MODE) | (1 << DF_MODE))/* Modes for quad-word and smaller quantities.  */#define T_MODES (D_MODES | (1 << (int) T_MODE) | (1 << (int) TF_MODE))/* Value is 1 if register/mode pair is acceptable on arc.  */const unsigned int arc_hard_regno_mode_ok[] = {  T_MODES, T_MODES, T_MODES, T_MODES, T_MODES, T_MODES, T_MODES, T_MODES,  T_MODES, T_MODES, T_MODES, T_MODES, T_MODES, T_MODES, T_MODES, T_MODES,  T_MODES, T_MODES, T_MODES, T_MODES, T_MODES, T_MODES, T_MODES, D_MODES,  D_MODES, S_MODES, S_MODES, S_MODES, S_MODES, S_MODES, S_MODES, S_MODES,  /* ??? Leave these as S_MODES for now.  */  S_MODES, S_MODES, S_MODES, S_MODES, S_MODES, S_MODES, S_MODES, S_MODES,  S_MODES, S_MODES, S_MODES, S_MODES, S_MODES, S_MODES, S_MODES, S_MODES,  S_MODES, S_MODES, S_MODES, S_MODES, S_MODES, S_MODES, S_MODES, S_MODES,  S_MODES, S_MODES, S_MODES, S_MODES, S_MODES, C_MODES};unsigned int arc_mode_class [NUM_MACHINE_MODES];enum reg_class arc_regno_reg_class[FIRST_PSEUDO_REGISTER];static voidarc_init_reg_tables (void){  int i;  for (i = 0; i < NUM_MACHINE_MODES; i++)    {      switch (GET_MODE_CLASS (i))	{	case MODE_INT:	case MODE_PARTIAL_INT:	case MODE_COMPLEX_INT:	  if (GET_MODE_SIZE (i) <= 4)	    arc_mode_class[i] = 1 << (int) S_MODE;	  else if (GET_MODE_SIZE (i) == 8)	    arc_mode_class[i] = 1 << (int) D_MODE;	  else if (GET_MODE_SIZE (i) == 16)	    arc_mode_class[i] = 1 << (int) T_MODE;	  else if (GET_MODE_SIZE (i) == 32)	    arc_mode_class[i] = 1 << (int) O_MODE;	  else 	    arc_mode_class[i] = 0;	  break;	case MODE_FLOAT:	case MODE_COMPLEX_FLOAT:	  if (GET_MODE_SIZE (i) <= 4)	    arc_mode_class[i] = 1 << (int) SF_MODE;	  else if (GET_MODE_SIZE (i) == 8)	    arc_mode_class[i] = 1 << (int) DF_MODE;	  else if (GET_MODE_SIZE (i) == 16)	    arc_mode_class[i] = 1 << (int) TF_MODE;	  else if (GET_MODE_SIZE (i) == 32)	    arc_mode_class[i] = 1 << (int) OF_MODE;	  else 	    arc_mode_class[i] = 0;	  break;	case MODE_CC:	  arc_mode_class[i] = 1 << (int) C_MODE;	  break;	default:	  arc_mode_class[i] = 0;	  break;	}    }  for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)    {      if (i < 60)	arc_regno_reg_class[i] = GENERAL_REGS;      else if (i == 60)	arc_regno_reg_class[i] = LPCOUNT_REG;      else if (i == 61)	arc_regno_reg_class[i] = NO_REGS /* CC_REG: must be NO_REGS */;      else	arc_regno_reg_class[i] = NO_REGS;    }}/* ARC specific attribute support.   The ARC has these attributes:   interrupt - for interrupt functions*/const struct attribute_spec arc_attribute_table[] ={  /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */  { "interrupt", 1, 1, true,  false, false, arc_handle_interrupt_attribute },  { NULL,        0, 0, false, false, false, NULL }};/* Handle an "interrupt" attribute; arguments as in   struct attribute_spec.handler.  */static treearc_handle_interrupt_attribute (tree *node ATTRIBUTE_UNUSED,                                tree name,                                tree args,                                int flags ATTRIBUTE_UNUSED,                                bool *no_add_attrs){  tree value = TREE_VALUE (args);  if (TREE_CODE (value) != STRING_CST)    {      warning ("argument of %qs attribute is not a string constant",	       IDENTIFIER_POINTER (name));      *no_add_attrs = true;    }  else if (strcmp (TREE_STRING_POINTER (value), "ilink1")	   && strcmp (TREE_STRING_POINTER (value), "ilink2"))    {      warning ("argument of %qs attribute is not \"ilink1\" or \"ilink2\"",	       IDENTIFIER_POINTER (name));      *no_add_attrs = true;    }  return NULL_TREE;}/* Acceptable arguments to the call insn.  */intcall_address_operand (rtx op, enum machine_mode mode){  return (symbolic_operand (op, mode)	  || (GET_CODE (op) == CONST_INT && LEGITIMATE_CONSTANT_P (op))	  || (GET_CODE (op) == REG));}intcall_operand (rtx op, enum machine_mode mode){  if (GET_CODE (op) != MEM)    return 0;  op = XEXP (op, 0);  return call_address_operand (op, mode);}/* Returns 1 if OP is a symbol reference.  */

⌨️ 快捷键说明

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