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

📄 v850.c

📁 Mac OS X 10.4.9 for x86 Source Code gcc 实现源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
/* Subroutines for insn-output.c for NEC V850 series   Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004   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, 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 "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 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	value		max		physical max */  { "tda",	(char *)0,	0,		256 },  { "sda",	(char *)0,	0,		65536 },  { "zda",	(char *)0,	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_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;/* Sometimes certain combinations of command options do not make   sense on a particular target machine.  You can define a macro   `OVERRIDE_OPTIONS' to take account of this.  This macro, if   defined, is executed once just after all the command options have   been parsed.   Don't use this macro to turn on various extra optimizations for   `-O'.  That is what `OPTIMIZATION_OPTIONS' is for.  */voidoverride_options (void){  int i;  extern int atoi (const char *);  /* Parse -m{s,t,z}da=nnn switches */  for (i = 0; i < (int)SMALL_MEMORY_max; i++)    {      if (small_memory[i].value)	{	  if (!ISDIGIT (*small_memory[i].value))	    error ("%s=%s is not numeric",		   small_memory[i].name,		   small_memory[i].value);	  else	    {	      small_memory[i].max = atoi (small_memory[i].value);	      if (small_memory[i].max > small_memory[i].physical_max)		error ("%s=%s is too large",		   small_memory[i].name,		   small_memory[i].value);	    }	}    }  /* Make sure that the US_BIT_SET mask has been correctly initialized.  */  if ((target_flags & MASK_US_MASK_SET) == 0)    {      target_flags |= MASK_US_MASK_SET;      target_flags &= ~MASK_US_BIT_SET;    }}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:	    fprintf (file, "h");	    break;	  case LEU:	    fprintf (file, "nh");	    break;	  case LTU:	    fprintf (file, "l");	    break;	  default:	    abort ();	}      break;    case 'F':			/* high word of CONST_DOUBLE */      if (GET_CODE (x) == CONST_INT)	fprintf (file, "%d", (INTVAL (x) >= 0) ? 0 : -1);      else if (GET_CODE (x) == CONST_DOUBLE)	{	  const_double_split (x, &high, &low);	  fprintf (file, "%ld", (long) high);	}      else	abort ();      break;    case 'G':			/* low word of CONST_DOUBLE */

⌨️ 快捷键说明

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