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

📄 v850.c

📁 linux下编程用 编译软件
💻 C
📖 第 1 页 / 共 5 页
字号:
/* Subroutines for insn-output.c for NEC V850 series   Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005   Free Software Foundation, Inc.   Contributed by Jeff Law (law@cygnus.com).   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, 51 Franklin Street, Fifth Floor, Boston, MA   02110-1301, 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 "recog.h"#include "expr.h"#include "function.h"#include "toplev.h"#include "ggc.h"#include "integrate.h"#include "tm_p.h"#include "target.h"#include "target-def.h"#ifndef streq#define streq(a,b) (strcmp (a, b) == 0)#endif/* Function prototypes for stupid compilers:  */static bool v850_handle_option       (size_t, const char *, int);static void const_double_split       (rtx, HOST_WIDE_INT *, HOST_WIDE_INT *);static int  const_costs_int          (HOST_WIDE_INT, int);static int  const_costs		     (rtx, enum rtx_code);static bool v850_rtx_costs	     (rtx, int, int, int *);static void substitute_ep_register   (rtx, rtx, int, int, rtx *, rtx *);static void v850_reorg		     (void);static int  ep_memory_offset         (enum machine_mode, int);static void v850_set_data_area       (tree, v850_data_area);const struct attribute_spec v850_attribute_table[];static tree v850_handle_interrupt_attribute (tree *, tree, tree, int, bool *);static tree v850_handle_data_area_attribute (tree *, tree, tree, int, bool *);static void v850_insert_attributes   (tree, tree *);static void v850_select_section (tree, int, unsigned HOST_WIDE_INT);static void v850_encode_data_area    (tree, rtx);static void v850_encode_section_info (tree, rtx, int);static bool v850_return_in_memory    (tree, tree);static void v850_setup_incoming_varargs (CUMULATIVE_ARGS *, enum machine_mode,					 tree, int *, int);static bool v850_pass_by_reference (CUMULATIVE_ARGS *, enum machine_mode,				    tree, bool);static int v850_arg_partial_bytes (CUMULATIVE_ARGS *, enum machine_mode,				   tree, bool);/* Information about the various small memory areas.  */struct small_memory_info small_memory[ (int)SMALL_MEMORY_max ] ={  /* name	max	physical max */  { "tda",	0,		256 },  { "sda",	0,		65536 },  { "zda",	0,		32768 },};/* Names of the various data areas used on the v850.  */tree GHS_default_section_names [(int) COUNT_OF_GHS_SECTION_KINDS];tree GHS_current_section_names [(int) COUNT_OF_GHS_SECTION_KINDS];/* Track the current data area set by the data area pragma (which    can be nested).  Tested by check_default_data_area.  */data_area_stack_element * data_area_stack = NULL;/* True if we don't need to check any more if the current   function is an interrupt handler.  */static int v850_interrupt_cache_p = FALSE;/* Whether current function is an interrupt handler.  */static int v850_interrupt_p = FALSE;/* Initialize the GCC target structure.  */#undef TARGET_ASM_ALIGNED_HI_OP#define TARGET_ASM_ALIGNED_HI_OP "\t.hword\t"#undef TARGET_ATTRIBUTE_TABLE#define TARGET_ATTRIBUTE_TABLE v850_attribute_table#undef TARGET_INSERT_ATTRIBUTES#define TARGET_INSERT_ATTRIBUTES v850_insert_attributes#undef  TARGET_ASM_SELECT_SECTION#define TARGET_ASM_SELECT_SECTION  v850_select_section#undef TARGET_ENCODE_SECTION_INFO#define TARGET_ENCODE_SECTION_INFO v850_encode_section_info#undef TARGET_ASM_FILE_START_FILE_DIRECTIVE#define TARGET_ASM_FILE_START_FILE_DIRECTIVE true#undef TARGET_DEFAULT_TARGET_FLAGS#define TARGET_DEFAULT_TARGET_FLAGS (MASK_DEFAULT | MASK_APP_REGS)#undef TARGET_HANDLE_OPTION#define TARGET_HANDLE_OPTION v850_handle_option#undef TARGET_RTX_COSTS#define TARGET_RTX_COSTS v850_rtx_costs#undef TARGET_ADDRESS_COST#define TARGET_ADDRESS_COST hook_int_rtx_0#undef TARGET_MACHINE_DEPENDENT_REORG#define TARGET_MACHINE_DEPENDENT_REORG v850_reorg#undef TARGET_PROMOTE_PROTOTYPES#define TARGET_PROMOTE_PROTOTYPES hook_bool_tree_true#undef TARGET_RETURN_IN_MEMORY#define TARGET_RETURN_IN_MEMORY v850_return_in_memory#undef TARGET_PASS_BY_REFERENCE#define TARGET_PASS_BY_REFERENCE v850_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 v850_setup_incoming_varargs#undef TARGET_ARG_PARTIAL_BYTES#define TARGET_ARG_PARTIAL_BYTES v850_arg_partial_bytesstruct gcc_target targetm = TARGET_INITIALIZER;/* Set the maximum size of small memory area TYPE to the value given   by VALUE.  Return true if VALUE was syntactically correct.  VALUE   starts with the argument separator: either "-" or "=".  */static boolv850_handle_memory_option (enum small_memory_type type, const char *value){  int i, size;  if (*value != '-' && *value != '=')    return false;  value++;  for (i = 0; value[i]; i++)    if (!ISDIGIT (value[i]))      return false;  size = atoi (value);  if (size > small_memory[type].physical_max)    error ("value passed to %<-m%s%> is too large", small_memory[type].name);  else    small_memory[type].max = size;  return true;}/* Implement TARGET_HANDLE_OPTION.  */static boolv850_handle_option (size_t code, const char *arg, int value ATTRIBUTE_UNUSED){  switch (code)    {    case OPT_mspace:      target_flags |= MASK_EP | MASK_PROLOG_FUNCTION;      return true;    case OPT_mv850:      target_flags &= ~(MASK_CPU ^ MASK_V850);      return true;    case OPT_mv850e:    case OPT_mv850e1:      target_flags &= ~(MASK_CPU ^ MASK_V850E);      return true;    case OPT_mtda:      return v850_handle_memory_option (SMALL_MEMORY_TDA, arg);    case OPT_msda:      return v850_handle_memory_option (SMALL_MEMORY_SDA, arg);    case OPT_mzda:      return v850_handle_memory_option (SMALL_MEMORY_ZDA, arg);    default:      return true;    }}static boolv850_pass_by_reference (CUMULATIVE_ARGS *cum ATTRIBUTE_UNUSED,			enum machine_mode mode, tree type,			bool named ATTRIBUTE_UNUSED){  unsigned HOST_WIDE_INT size;  if (type)    size = int_size_in_bytes (type);  else    size = GET_MODE_SIZE (mode);  return size > 8;}/* Return an RTX to represent where a value with mode MODE will be returned   from a function.  If the result is 0, the argument is pushed.  */rtxfunction_arg (CUMULATIVE_ARGS * cum,              enum machine_mode mode,              tree type,              int named){  rtx result = 0;  int size, align;  if (TARGET_GHS && !named)    return NULL_RTX;  if (mode == BLKmode)    size = int_size_in_bytes (type);  else    size = GET_MODE_SIZE (mode);  if (size < 1)    return 0;  if (type)    align = TYPE_ALIGN (type) / BITS_PER_UNIT;  else    align = size;  cum->nbytes = (cum->nbytes + align - 1) &~(align - 1);  if (cum->nbytes > 4 * UNITS_PER_WORD)    return 0;  if (type == NULL_TREE      && cum->nbytes + size > 4 * UNITS_PER_WORD)    return 0;  switch (cum->nbytes / UNITS_PER_WORD)    {    case 0:      result = gen_rtx_REG (mode, 6);      break;    case 1:      result = gen_rtx_REG (mode, 7);      break;    case 2:      result = gen_rtx_REG (mode, 8);      break;    case 3:      result = gen_rtx_REG (mode, 9);      break;    default:      result = 0;    }  return result;}/* Return the number of bytes which must be put into registers   for values which are part in registers and part in memory.  */static intv850_arg_partial_bytes (CUMULATIVE_ARGS * cum, enum machine_mode mode,                        tree type, bool named){  int size, align;  if (TARGET_GHS && !named)    return 0;  if (mode == BLKmode)    size = int_size_in_bytes (type);  else    size = GET_MODE_SIZE (mode);  if (type)    align = TYPE_ALIGN (type) / BITS_PER_UNIT;  else    align = size;  cum->nbytes = (cum->nbytes + align - 1) &~(align - 1);  if (cum->nbytes > 4 * UNITS_PER_WORD)    return 0;  if (cum->nbytes + size <= 4 * UNITS_PER_WORD)    return 0;  if (type == NULL_TREE      && cum->nbytes + size > 4 * UNITS_PER_WORD)    return 0;  return 4 * UNITS_PER_WORD - cum->nbytes;}/* Return the high and low words of a CONST_DOUBLE */static voidconst_double_split (rtx x, HOST_WIDE_INT * p_high, HOST_WIDE_INT * p_low){  if (GET_CODE (x) == CONST_DOUBLE)    {      long t[2];      REAL_VALUE_TYPE rv;      switch (GET_MODE (x))	{	case DFmode:	  REAL_VALUE_FROM_CONST_DOUBLE (rv, x);	  REAL_VALUE_TO_TARGET_DOUBLE (rv, t);	  *p_high = t[1];	/* since v850 is little endian */	  *p_low = t[0];	/* high is second word */	  return;	case SFmode:	  REAL_VALUE_FROM_CONST_DOUBLE (rv, x);	  REAL_VALUE_TO_TARGET_SINGLE (rv, *p_high);	  *p_low = 0;	  return;	case VOIDmode:	case DImode:	  *p_high = CONST_DOUBLE_HIGH (x);	  *p_low  = CONST_DOUBLE_LOW (x);	  return;	default:	  break;	}    }  fatal_insn ("const_double_split got a bad insn:", x);}/* Return the cost of the rtx R with code CODE.  */static intconst_costs_int (HOST_WIDE_INT value, int zero_cost){  if (CONST_OK_FOR_I (value))      return zero_cost;  else if (CONST_OK_FOR_J (value))    return 1;  else if (CONST_OK_FOR_K (value))    return 2;  else    return 4;}static intconst_costs (rtx r, enum rtx_code c){  HOST_WIDE_INT high, low;  switch (c)    {    case CONST_INT:      return const_costs_int (INTVAL (r), 0);    case CONST_DOUBLE:      const_double_split (r, &high, &low);      if (GET_MODE (r) == SFmode)	return const_costs_int (high, 1);      else	return const_costs_int (high, 1) + const_costs_int (low, 1);    case SYMBOL_REF:    case LABEL_REF:    case CONST:      return 2;    case HIGH:      return 1;    default:      return 4;    }}static boolv850_rtx_costs (rtx x,                int code,                int outer_code ATTRIBUTE_UNUSED,                int * total){  switch (code)    {    case CONST_INT:    case CONST_DOUBLE:    case CONST:    case SYMBOL_REF:    case LABEL_REF:      *total = COSTS_N_INSNS (const_costs (x, code));      return true;    case MOD:    case DIV:    case UMOD:    case UDIV:      if (TARGET_V850E && optimize_size)        *total = 6;      else	*total = 60;      return true;    case MULT:      if (TARGET_V850E	  && (   GET_MODE (x) == SImode	      || GET_MODE (x) == HImode	      || GET_MODE (x) == QImode))        {	  if (GET_CODE (XEXP (x, 1)) == REG)	    *total = 4;	  else if (GET_CODE (XEXP (x, 1)) == CONST_INT)	    {	      if (CONST_OK_FOR_O (INTVAL (XEXP (x, 1))))	        *total = 6;	      else if (CONST_OK_FOR_K (INTVAL (XEXP (x, 1))))	        *total = 10;	    }        }      else	*total = 20;      return true;    default:      return false;    }}/* Print operand X using operand code CODE to assembly language output file   FILE.  */voidprint_operand (FILE * file, rtx x, int code){  HOST_WIDE_INT high, low;  switch (code)    {    case 'c':      /* We use 'c' operands with symbols for .vtinherit */      if (GET_CODE (x) == SYMBOL_REF)        {          output_addr_const(file, x);          break;        }      /* fall through */    case 'b':    case 'B':    case 'C':      switch ((code == 'B' || code == 'C')	      ? reverse_condition (GET_CODE (x)) : GET_CODE (x))	{	  case NE:	    if (code == 'c' || code == 'C')	      fprintf (file, "nz");	    else	      fprintf (file, "ne");	    break;	  case EQ:	    if (code == 'c' || code == 'C')	      fprintf (file, "z");	    else	      fprintf (file, "e");	    break;	  case GE:	    fprintf (file, "ge");	    break;	  case GT:	    fprintf (file, "gt");	    break;	  case LE:	    fprintf (file, "le");	    break;	  case LT:	    fprintf (file, "lt");	    break;	  case GEU:	    fprintf (file, "nl");	    break;	  case GTU:

⌨️ 快捷键说明

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