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

📄 v850.c

📁 GCC编译器源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
/* Subroutines for insn-output.c for NEC V850 series   Copyright (C) 1996, 1997 Free Software Foundation, Inc.   Contributed by Jeff Law (law@cygnus.com).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 <stdio.h>#include <ctype.h>#include "config.h"#include "rtl.h"#include "regs.h"#include "hard-reg-set.h"#include "real.h"#include "insn-config.h"#include "conditions.h"#include "insn-flags.h"#include "output.h"#include "insn-attr.h"#include "flags.h"#include "recog.h"#include "expr.h"#include "tree.h"#include "obstack.h"/* True if the current function has anonymous arguments.  */int current_function_anonymous_args;/* 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 },};/* 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;/* 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 (){  int i;  extern int atoi ();  /* 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);	    }	}    }}/* Output assembly code for the start of the file.  */voidasm_file_start (file)     FILE *file;{  output_file_directive (file, main_input_filename);}/* 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 (cum, mode, type, named)     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 (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 words which must be put into registers   for values which are part in registers and part in memory.  */intfunction_arg_partial_nregs (cum, mode, type, named)     CUMULATIVE_ARGS *cum;     enum machine_mode mode;     tree type;     int 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) / UNITS_PER_WORD;}/* Return the high and low words of a CONST_DOUBLE */static voidconst_double_split (x, p_high, p_low)     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;	}    }  fatal_insn ("const_double_split got a bad insn:", x);}/* Return the cost of the rtx R with code CODE.  */static intconst_costs_int (value, zero_cost)     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;}intconst_costs (r, c)     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;    }}/* Print operand X using operand code CODE to assembly language output file   FILE.  */voidprint_operand (file, x, code)     FILE *file;     rtx x;     int code;{  HOST_WIDE_INT high, low;  switch (code)    {    case 'b':    case 'B':    case 'c':    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 */      if (GET_CODE (x) == CONST_INT)	fprintf (file, "%ld", (long) INTVAL (x));      else if (GET_CODE (x) == CONST_DOUBLE)	{	  const_double_split (x, &high, &low);	  fprintf (file, "%ld", (long) low);	}      else	abort ();      break;    case 'L':      fprintf (file, "%d\n", INTVAL (x) & 0xffff);      break;    case 'M':      fprintf (file, "%d", exact_log2 (INTVAL (x)));      break;    case 'O':      if (special_symbolref_operand (x, VOIDmode))        {          char* name;	  if (GET_CODE (x) == SYMBOL_REF)	    name = XSTR (x, 0);	  else if (GET_CODE (x) == CONST)	    name = XSTR (XEXP (XEXP (x, 0), 0), 0);	  else	    abort ();          if (ZDA_NAME_P (name))            fprintf (file, "zdaoff");          else if (SDA_NAME_P (name))            fprintf (file, "sdaoff");          else if (TDA_NAME_P (name))            fprintf (file, "tdaoff");          else            abort();        }      else        abort();      break;    case 'P':      if (special_symbolref_operand (x, VOIDmode))        output_addr_const (file, x);      else        abort();      break;    case 'Q':      if (special_symbolref_operand (x, VOIDmode))        {          char* name;	  if (GET_CODE (x) == SYMBOL_REF)	    name = XSTR (x, 0);	  else if (GET_CODE (x) == CONST)	    name = XSTR (XEXP (XEXP (x, 0), 0), 0);	  else	    abort ();          if (ZDA_NAME_P (name))            fprintf (file, "r0");          else if (SDA_NAME_P (name))            fprintf (file, "gp");          else if (TDA_NAME_P (name))            fprintf (file, "ep");          else            abort();        }      else        abort();      break;    case 'R':		/* 2nd word of a double.  */      switch (GET_CODE (x))	{	  case REG:	    fprintf (file, reg_names[REGNO (x) + 1]);	    break;	  case MEM:	    print_operand_address (file,				   XEXP (adj_offsettable_operand (x, 4), 0));	    break;	}      break;    case 'S':      {        /* if it's a reference to a TDA variable, use sst/sld vs. st/ld */        if (GET_CODE (x) == MEM && ep_memory_operand (x, GET_MODE (x), FALSE))          fputs ("s", file);        break;      }    case 'T':      {	/* Like an 'S' operand above, but for unsigned loads only.  */        if (GET_CODE (x) == MEM && ep_memory_operand (x, GET_MODE (x), TRUE))          fputs ("s", file);        break;      }    case 'W':			/* print the instruction suffix */      switch (GET_MODE (x))	{	default:	  abort ();	case QImode: fputs (".b", file); break;	case HImode: fputs (".h", file); break;	case SImode: fputs (".w", file); break;	case SFmode: fputs (".w", file); break;	}      break;    case '.':			/* register r0 */      fputs (reg_names[0], file);      break;    case 'z':			/* reg or zero */      if (x == const0_rtx)	fputs (reg_names[0], file);      else if (GET_CODE (x) == REG)	fputs (reg_names[REGNO (x)], file);      else	abort ();      break;    default:      switch (GET_CODE (x))	{	case MEM:	  if (GET_CODE (XEXP (x, 0)) == CONST_INT)	    output_address (gen_rtx (PLUS, SImode,				     gen_rtx (REG, SImode, 0),				     XEXP (x, 0)));	  else	    output_address (XEXP (x, 0));	  break;	case REG:	  fputs (reg_names[REGNO (x)], file);	  break;	case SUBREG:	  fputs (reg_names[REGNO (SUBREG_REG (x)) + SUBREG_WORD (x)], file);	  break;	case CONST_INT:	case SYMBOL_REF:	case CONST:	case LABEL_REF:	case CODE_LABEL:	  print_operand_address (file, x);	  break;	default:	  abort ();	}      break;    }}/* Output assembly language output for the address ADDR to FILE.  */voidprint_operand_address (file, addr)     FILE *file;     rtx addr;{  switch (GET_CODE (addr))    {    case REG:      fprintf (file, "0[");      print_operand (file, addr, 0);      fprintf (file, "]");      break;    case LO_SUM:      if (GET_CODE (XEXP (addr, 0)) == REG)	{	  /* reg,foo */	  fprintf (file, "lo(");	  print_operand (file, XEXP (addr, 1), 0);	  fprintf (file, ")[");	  print_operand (file, XEXP (addr, 0), 0);	  fprintf (file, "]");	}      break;    case PLUS:      if (GET_CODE (XEXP (addr, 0)) == REG	  || GET_CODE (XEXP (addr, 0)) == SUBREG)	{	  /* reg,foo */	  print_operand (file, XEXP (addr, 1), 0);	  fprintf (file, "[");	  print_operand (file, XEXP (addr, 0), 0);	  fprintf (file, "]");	}      else	{	  print_operand (file, XEXP (addr, 0), 0);	  fprintf (file, "+");	  print_operand (file, XEXP (addr, 1), 0);	}      break;    case SYMBOL_REF:      if (ENCODED_NAME_P (XSTR (addr, 0)))        {          char* name = XSTR (addr, 0);          char* off_name;          char* reg_name;          if (ZDA_NAME_P (name))            {

⌨️ 快捷键说明

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