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

📄 m32r.c

📁 Mac OS X 10.4.9 for x86 Source Code gcc 实现源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
/* Subroutines used for code generation on the Renesas M32R cpu.   Copyright (C) 1996, 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 modify it   under the terms of the GNU General Public License as published   by the 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 of MERCHANTABILITY   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public   License for more details.   You should have received a copy of the GNU General Public License   along with GCC; see the file COPYING.  If not, write to   the Free Software Foundation, 59 Temple Place - Suite 330,   Boston, MA 02111-1307, USA.  */#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 "expr.h"#include "function.h"#include "recog.h"#include "toplev.h"#include "ggc.h"#include "integrate.h"#include "tm_p.h"#include "target.h"#include "target-def.h"/* Save the operands last given to a compare for use when we   generate a scc or bcc insn.  */rtx m32r_compare_op0, m32r_compare_op1;/* Array of valid operand punctuation characters.  */char m32r_punct_chars[256];/* Selected code model.  */const char * m32r_model_string = M32R_MODEL_DEFAULT;enum m32r_model m32r_model;/* Selected SDA support.  */const char * m32r_sdata_string = M32R_SDATA_DEFAULT;enum m32r_sdata m32r_sdata;/* Machine-specific symbol_ref flags.  */#define SYMBOL_FLAG_MODEL_SHIFT		SYMBOL_FLAG_MACH_DEP_SHIFT#define SYMBOL_REF_MODEL(X) \  ((enum m32r_model) ((SYMBOL_REF_FLAGS (X) >> SYMBOL_FLAG_MODEL_SHIFT) & 3))/* For string literals, etc.  */#define LIT_NAME_P(NAME) ((NAME)[0] == '*' && (NAME)[1] == '.')/* Cache-flush support. Cache-flush is used at trampoline.   Default cache-flush is "trap 12".    default cache-flush function is "_flush_cache"  (CACHE_FLUSH_FUNC)    default cache-flush trap-interrupt number is "12". (CACHE_FLUSH_TRAP)   You can change how to generate code of cache-flush with following options.   -flush-func=FLUSH-FUNC-NAME   -no-flush-func   -fluch-trap=TRAP-NUMBER   -no-flush-trap.  */const char *m32r_cache_flush_func = CACHE_FLUSH_FUNC;const char *m32r_cache_flush_trap_string = CACHE_FLUSH_TRAP;int m32r_cache_flush_trap = 12;/* Forward declaration.  */static void  init_reg_tables (void);static void  block_move_call (rtx, rtx, rtx);static int   m32r_is_insn (rtx);const struct attribute_spec m32r_attribute_table[];static tree  m32r_handle_model_attribute (tree *, tree, tree, int, bool *);static void  m32r_output_function_prologue (FILE *, HOST_WIDE_INT);static void  m32r_output_function_epilogue (FILE *, HOST_WIDE_INT);static void  m32r_file_start (void);static int    m32r_adjust_priority (rtx, int);static int    m32r_issue_rate (void);static void m32r_encode_section_info (tree, rtx, int);static bool m32r_in_small_data_p (tree);static bool m32r_return_in_memory (tree, tree);static void m32r_setup_incoming_varargs (CUMULATIVE_ARGS *, enum machine_mode,					 tree, int *, int);static void init_idents (void);static bool m32r_rtx_costs (rtx, int, int, int *);static bool m32r_pass_by_reference (CUMULATIVE_ARGS *, enum machine_mode,				    tree, bool);static int m32r_arg_partial_bytes (CUMULATIVE_ARGS *, enum machine_mode,				   tree, bool);/* Initialize the GCC target structure.  */#undef  TARGET_ATTRIBUTE_TABLE#define TARGET_ATTRIBUTE_TABLE m32r_attribute_table#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_FUNCTION_PROLOGUE#define TARGET_ASM_FUNCTION_PROLOGUE m32r_output_function_prologue#undef  TARGET_ASM_FUNCTION_EPILOGUE#define TARGET_ASM_FUNCTION_EPILOGUE m32r_output_function_epilogue#undef  TARGET_ASM_FILE_START#define TARGET_ASM_FILE_START m32r_file_start#undef  TARGET_SCHED_ADJUST_PRIORITY#define TARGET_SCHED_ADJUST_PRIORITY m32r_adjust_priority#undef  TARGET_SCHED_ISSUE_RATE#define TARGET_SCHED_ISSUE_RATE m32r_issue_rate#undef  TARGET_ENCODE_SECTION_INFO#define TARGET_ENCODE_SECTION_INFO m32r_encode_section_info#undef  TARGET_IN_SMALL_DATA_P#define TARGET_IN_SMALL_DATA_P m32r_in_small_data_p#undef  TARGET_RTX_COSTS#define TARGET_RTX_COSTS m32r_rtx_costs#undef  TARGET_ADDRESS_COST#define TARGET_ADDRESS_COST hook_int_rtx_0#undef  TARGET_PROMOTE_PROTOTYPES#define TARGET_PROMOTE_PROTOTYPES hook_bool_tree_true#undef  TARGET_RETURN_IN_MEMORY#define TARGET_RETURN_IN_MEMORY m32r_return_in_memory#undef  TARGET_SETUP_INCOMING_VARARGS#define TARGET_SETUP_INCOMING_VARARGS m32r_setup_incoming_varargs#undef  TARGET_MUST_PASS_IN_STACK#define TARGET_MUST_PASS_IN_STACK must_pass_in_stack_var_size#undef  TARGET_PASS_BY_REFERENCE#define TARGET_PASS_BY_REFERENCE m32r_pass_by_reference#undef  TARGET_ARG_PARTIAL_BYTES#define TARGET_ARG_PARTIAL_BYTES m32r_arg_partial_bytesstruct gcc_target targetm = TARGET_INITIALIZER;/* Called by OVERRIDE_OPTIONS to initialize various things.  */voidm32r_init (void){  init_reg_tables ();  /* Initialize array for PRINT_OPERAND_PUNCT_VALID_P.  */  memset (m32r_punct_chars, 0, sizeof (m32r_punct_chars));  m32r_punct_chars['#'] = 1;  m32r_punct_chars['@'] = 1; /* ??? no longer used */  /* Provide default value if not specified.  */  if (!g_switch_set)    g_switch_value = SDATA_DEFAULT_SIZE;  if (strcmp (m32r_model_string, "small") == 0)    m32r_model = M32R_MODEL_SMALL;  else if (strcmp (m32r_model_string, "medium") == 0)    m32r_model = M32R_MODEL_MEDIUM;  else if (strcmp (m32r_model_string, "large") == 0)    m32r_model = M32R_MODEL_LARGE;  else    error ("bad value (%s) for -mmodel switch", m32r_model_string);  if (strcmp (m32r_sdata_string, "none") == 0)    m32r_sdata = M32R_SDATA_NONE;  else if (strcmp (m32r_sdata_string, "sdata") == 0)    m32r_sdata = M32R_SDATA_SDATA;  else if (strcmp (m32r_sdata_string, "use") == 0)    m32r_sdata = M32R_SDATA_USE;  else    error ("bad value (%s) for -msdata switch", m32r_sdata_string);  if (m32r_cache_flush_trap_string)    {      /* Change trap-number (12) for cache-flush to the others (0 - 15).  */      m32r_cache_flush_trap = atoi (m32r_cache_flush_trap_string);      if (m32r_cache_flush_trap < 0 || m32r_cache_flush_trap > 15)        error ("bad value (%s) for -flush-trap=n (0=<n<=15)",               m32r_cache_flush_trap_string);    }}/* 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 m32r_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 m32r_mode_class mode.  */enum m32r_mode_class{  C_MODE,  S_MODE, D_MODE, T_MODE, O_MODE,  SF_MODE, DF_MODE, TF_MODE, OF_MODE, A_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))/* Modes for accumulators.  */#define A_MODES (1 << (int) A_MODE)/* Value is 1 if register/mode pair is acceptable on arc.  */const unsigned int m32r_hard_regno_mode_ok[FIRST_PSEUDO_REGISTER] ={  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, S_MODES, S_MODES, S_MODES,  S_MODES, C_MODES, A_MODES, A_MODES};unsigned int m32r_mode_class [NUM_MACHINE_MODES];enum reg_class m32r_regno_reg_class[FIRST_PSEUDO_REGISTER];static voidinit_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)	    m32r_mode_class[i] = 1 << (int) S_MODE;	  else if (GET_MODE_SIZE (i) == 8)	    m32r_mode_class[i] = 1 << (int) D_MODE;	  else if (GET_MODE_SIZE (i) == 16)	    m32r_mode_class[i] = 1 << (int) T_MODE;	  else if (GET_MODE_SIZE (i) == 32)	    m32r_mode_class[i] = 1 << (int) O_MODE;	  else 	    m32r_mode_class[i] = 0;	  break;	case MODE_FLOAT:	case MODE_COMPLEX_FLOAT:	  if (GET_MODE_SIZE (i) <= 4)	    m32r_mode_class[i] = 1 << (int) SF_MODE;	  else if (GET_MODE_SIZE (i) == 8)	    m32r_mode_class[i] = 1 << (int) DF_MODE;	  else if (GET_MODE_SIZE (i) == 16)	    m32r_mode_class[i] = 1 << (int) TF_MODE;	  else if (GET_MODE_SIZE (i) == 32)	    m32r_mode_class[i] = 1 << (int) OF_MODE;	  else 	    m32r_mode_class[i] = 0;	  break;	case MODE_CC:	  m32r_mode_class[i] = 1 << (int) C_MODE;	  break;	default:	  m32r_mode_class[i] = 0;	  break;	}    }  for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)    {      if (GPR_P (i))	m32r_regno_reg_class[i] = GENERAL_REGS;      else if (i == ARG_POINTER_REGNUM)	m32r_regno_reg_class[i] = GENERAL_REGS;      else	m32r_regno_reg_class[i] = NO_REGS;    }}/* M32R specific attribute support.   interrupt - for interrupt functions   model - select code model used to access object	small: addresses use 24 bits, use bl to make calls	medium: addresses use 32 bits, use bl to make calls	large: addresses use 32 bits, use seth/add3/jl to make calls	Grep for MODEL in m32r.h for more info.  */static tree small_ident1;static tree small_ident2;static tree medium_ident1;static tree medium_ident2;static tree large_ident1;static tree large_ident2;static voidinit_idents (void){  if (small_ident1 == 0)    {      small_ident1 = get_identifier ("small");      small_ident2 = get_identifier ("__small__");      medium_ident1 = get_identifier ("medium");      medium_ident2 = get_identifier ("__medium__");      large_ident1 = get_identifier ("large");      large_ident2 = get_identifier ("__large__");    }}const struct attribute_spec m32r_attribute_table[] ={  /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */  { "interrupt", 0, 0, true,  false, false, NULL },  { "model",     1, 1, true,  false, false, m32r_handle_model_attribute },  { NULL,        0, 0, false, false, false, NULL }};/* Handle an "model" attribute; arguments as in   struct attribute_spec.handler.  */static treem32r_handle_model_attribute (tree *node ATTRIBUTE_UNUSED, tree name,			     tree args, int flags ATTRIBUTE_UNUSED,			     bool *no_add_attrs){  tree arg;  init_idents ();  arg = TREE_VALUE (args);  if (arg != small_ident1      && arg != small_ident2      && arg != medium_ident1      && arg != medium_ident2      && arg != large_ident1      && arg != large_ident2)    {      warning ("invalid argument of %qs attribute",	       IDENTIFIER_POINTER (name));      *no_add_attrs = true;    }  return NULL_TREE;}/* Encode section information of DECL, which is either a VAR_DECL,   FUNCTION_DECL, STRING_CST, CONSTRUCTOR, or ???.   For the M32R we want to record:   - whether the object lives in .sdata/.sbss.   - what code model should be used to access the object*/static voidm32r_encode_section_info (tree decl, rtx rtl, int first){  int extra_flags = 0;  tree model_attr;  enum m32r_model model;  default_encode_section_info (decl, rtl, first);  if (!DECL_P (decl))    return;  model_attr = lookup_attribute ("model", DECL_ATTRIBUTES (decl));  if (model_attr)    {      tree id;      init_idents ();      id = TREE_VALUE (TREE_VALUE (model_attr));      if (id == small_ident1 || id == small_ident2)	model = M32R_MODEL_SMALL;      else if (id == medium_ident1 || id == medium_ident2)	model = M32R_MODEL_MEDIUM;      else if (id == large_ident1 || id == large_ident2)	model = M32R_MODEL_LARGE;      else	abort (); /* shouldn't happen */    }  else    {      if (TARGET_MODEL_SMALL)	model = M32R_MODEL_SMALL;      else if (TARGET_MODEL_MEDIUM)	model = M32R_MODEL_MEDIUM;      else if (TARGET_MODEL_LARGE)	model = M32R_MODEL_LARGE;      else	abort (); /* shouldn't happen */    }  extra_flags |= model << SYMBOL_FLAG_MODEL_SHIFT;  if (extra_flags)    SYMBOL_REF_FLAGS (XEXP (rtl, 0)) |= extra_flags;}/* Only mark the object as being small data area addressable if   it hasn't been explicitly marked with a code model.   The user can explicitly put an object in the small data area with the   section attribute.  If the object is in sdata/sbss and marked with a   code model do both [put the object in .sdata and mark it as being   addressed with a specific code model - don't mark it as being addressed   with an SDA reloc though].  This is ok and might be useful at times.  If   the object doesn't fit the linker will give an error.  */static boolm32r_in_small_data_p (tree decl){  tree section;  if (TREE_CODE (decl) != VAR_DECL)    return false;  if (lookup_attribute ("model", DECL_ATTRIBUTES (decl)))    return false;  section = DECL_SECTION_NAME (decl);  if (section)    {      char *name = (char *) TREE_STRING_POINTER (section);      if (strcmp (name, ".sdata") == 0 || strcmp (name, ".sbss") == 0)	return true;    }  else    {      if (! TREE_READONLY (decl) && ! TARGET_SDATA_NONE)	{	  int size = int_size_in_bytes (TREE_TYPE (decl));	  if (size > 0 && (unsigned HOST_WIDE_INT) size <= g_switch_value)	    return true;	}    }

⌨️ 快捷键说明

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