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

📄 mn10300.c

📁 linux下的gcc编译器
💻 C
📖 第 1 页 / 共 3 页
字号:
/* Subroutines for insn-output.c for Matsushita MN10300 series   Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003   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 "config.h"#include "system.h"#include "rtl.h"#include "tree.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 "optabs.h"#include "function.h"#include "obstack.h"#include "toplev.h"#include "tm_p.h"#include "target.h"#include "target-def.h"/* The size of the callee register save area.  Right now we save everything   on entry since it costs us nothing in code size.  It does cost us from a   speed standpoint, so we want to optimize this sooner or later.  */#define REG_SAVE_BYTES (4 * regs_ever_live[2] \			+ 4 * regs_ever_live[3] \		        + 4 * regs_ever_live[6] \			+ 4 * regs_ever_live[7] \			+ 16 * (regs_ever_live[14] || regs_ever_live[15] \				|| regs_ever_live[16] || regs_ever_live[17]))/* Initialize the GCC target structure.  */#undef TARGET_ASM_ALIGNED_HI_OP#define TARGET_ASM_ALIGNED_HI_OP "\t.hword\t"struct gcc_target targetm = TARGET_INITIALIZER;voidasm_file_start (file)     FILE *file;{  fprintf (file, "#\tGCC For the Matsushita MN10300\n");  if (optimize)    fprintf (file, "# -O%d\n", optimize);  else    fprintf (file, "\n\n");  if (TARGET_AM33)    fprintf (file, "\t.am33\n");  output_file_directive (file, main_input_filename);}/* Print operand X using operand code CODE to assembly language output file   FILE.  */voidprint_operand (file, x, code)     FILE *file;     rtx x;     int code;{  switch (code)    {      case 'b':      case 'B':	/* These are normal and reversed branches.  */	switch (code == 'b' ? GET_CODE (x) : reverse_condition (GET_CODE (x)))	  {	  case NE:	    fprintf (file, "ne");	    break;	  case EQ:	    fprintf (file, "eq");	    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, "cc");	    break;	  case GTU:	    fprintf (file, "hi");	    break;	  case LEU:	    fprintf (file, "ls");	    break;	  case LTU:	    fprintf (file, "cs");	    break;	  default:	    abort ();	  }	break;      case 'C':	/* This is used for the operand to a call instruction;	   if it's a REG, enclose it in parens, else output	   the operand normally.  */	if (GET_CODE (x) == REG)	  {	    fputc ('(', file);	    print_operand (file, x, 0);	    fputc (')', file);	  }	else	  print_operand (file, x, 0);	break;           /* These are the least significant word in a 64bit value.  */      case 'L':	switch (GET_CODE (x))	  {	  case MEM:	    fputc ('(', file);	    output_address (XEXP (x, 0));	    fputc (')', file);	    break;	  case REG:	    fprintf (file, "%s", reg_names[REGNO (x)]);	    break;	  case SUBREG:	    fprintf (file, "%s", reg_names[subreg_regno (x)]);	    break;	  case CONST_DOUBLE:	      {		long val[2];		REAL_VALUE_TYPE rv;		switch (GET_MODE (x))		  {		    case DFmode:		      REAL_VALUE_FROM_CONST_DOUBLE (rv, x);		      REAL_VALUE_TO_TARGET_DOUBLE (rv, val);		      fprintf (file, "0x%lx", val[0]);		      break;;		    case SFmode:		      REAL_VALUE_FROM_CONST_DOUBLE (rv, x);		      REAL_VALUE_TO_TARGET_SINGLE (rv, val[0]);		      fprintf (file, "0x%lx", val[0]);		      break;;		    case VOIDmode:		    case DImode:		      print_operand_address (file,					     GEN_INT (CONST_DOUBLE_LOW (x)));		      break;		    default:		      break;		  }		break;	      }	  case CONST_INT:	    {	      rtx low, high;	      split_double (x, &low, &high);	      fprintf (file, "%ld", (long)INTVAL (low));	      break;	    }	  default:	    abort ();	  }	break;      /* Similarly, but for the most significant word.  */      case 'H':	switch (GET_CODE (x))	  {	  case MEM:	    fputc ('(', file);	    x = adjust_address (x, SImode, 4);	    output_address (XEXP (x, 0));	    fputc (')', file);	    break;	  case REG:	    fprintf (file, "%s", reg_names[REGNO (x) + 1]);	    break;	  case SUBREG:	    fprintf (file, "%s", reg_names[subreg_regno (x) + 1]);	    break;	  case CONST_DOUBLE:	      {		long val[2];		REAL_VALUE_TYPE rv;		switch (GET_MODE (x))		  {		    case DFmode:		      REAL_VALUE_FROM_CONST_DOUBLE (rv, x);		      REAL_VALUE_TO_TARGET_DOUBLE (rv, val);		      fprintf (file, "0x%lx", val[1]);		      break;;		    case SFmode:		      abort ();		    case VOIDmode:		    case DImode:		      print_operand_address (file, 					     GEN_INT (CONST_DOUBLE_HIGH (x)));		      break;		    default:		      break;		  }		break;	      }	  case CONST_INT:	    {	      rtx low, high;	      split_double (x, &low, &high);	      fprintf (file, "%ld", (long)INTVAL (high));	      break;	    }	  default:	    abort ();	  }	break;      case 'A':	fputc ('(', file);	if (GET_CODE (XEXP (x, 0)) == REG)	  output_address (gen_rtx_PLUS (SImode, XEXP (x, 0), GEN_INT (0)));	else	  output_address (XEXP (x, 0));	fputc (')', file);	break;      case 'N':	if (INTVAL (x) < -128 || INTVAL (x) > 255)	  abort ();	fprintf (file, "%d", (int)((~INTVAL (x)) & 0xff));	break;      case 'U':	if (INTVAL (x) < -128 || INTVAL (x) > 255)	  abort ();	fprintf (file, "%d", (int)(INTVAL (x) & 0xff));	break;      /* For shift counts.  The hardware ignores the upper bits of	 any immediate, but the assembler will flag an out of range	 shift count as an error.  So we mask off the high bits	 of the immediate here.  */      case 'S':	if (GET_CODE (x) == CONST_INT)	  {	    fprintf (file, "%d", (int)(INTVAL (x) & 0x1f));	    break;	  }	/* FALL THROUGH */      default:	switch (GET_CODE (x))	  {	  case MEM:	    fputc ('(', file);	    output_address (XEXP (x, 0));	    fputc (')', file);	    break;	  case PLUS:	    output_address (x);	    break;	  case REG:	    fprintf (file, "%s", reg_names[REGNO (x)]);	    break;	  case SUBREG:	    fprintf (file, "%s", reg_names[subreg_regno (x)]);	    break;	  /* This will only be single precision....  */	  case CONST_DOUBLE:	    {	      unsigned long val;	      REAL_VALUE_TYPE rv;	      REAL_VALUE_FROM_CONST_DOUBLE (rv, x);	      REAL_VALUE_TO_TARGET_SINGLE (rv, val);	      fprintf (file, "0x%lx", val);	      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 POST_INC:      print_operand_address (file, XEXP (addr, 0));      fputc ('+', file);      break;    case REG:      print_operand (file, addr, 0);      break;    case PLUS:      {	rtx base, index;	if (REG_P (XEXP (addr, 0))	    && REG_OK_FOR_BASE_P (XEXP (addr, 0)))	  base = XEXP (addr, 0), index = XEXP (addr, 1);	else if (REG_P (XEXP (addr, 1))	    && REG_OK_FOR_BASE_P (XEXP (addr, 1)))	  base = XEXP (addr, 1), index = XEXP (addr, 0);      	else	  abort ();	print_operand (file, index, 0);	fputc (',', file);	print_operand (file, base, 0);;	break;      }    case SYMBOL_REF:      output_addr_const (file, addr);      break;    default:      output_addr_const (file, addr);      break;    }}/* Print a set of registers in the format required by "movm" and "ret".   Register K is saved if bit K of MASK is set.  The data and address   registers can be stored individually, but the extended registers cannot.   We assume that the mask alread takes that into account.  For instance,   bits 14 to 17 must have the same value. */voidmn10300_print_reg_list (file, mask)     FILE *file;     int mask;{  int need_comma;  int i;  need_comma = 0;  fputc ('[', file);  for (i = 0; i < FIRST_EXTENDED_REGNUM; i++)    if ((mask & (1 << i)) != 0)      {	if (need_comma)	  fputc (',', file);	fputs (reg_names [i], file);	need_comma = 1;      }  if ((mask & 0x3c000) != 0)    {      if ((mask & 0x3c000) != 0x3c000)	abort();      if (need_comma)	fputc (',', file);      fputs ("exreg1", file);      need_comma = 1;    }  fputc (']', file);}intcan_use_return_insn (){  /* size includes the fixed stack space needed for function calls.  */  int size = get_frame_size () + current_function_outgoing_args_size;  /* And space for the return pointer.  */  size += current_function_outgoing_args_size ? 4 : 0;  return (reload_completed	  && size == 0	  && !regs_ever_live[2]	  && !regs_ever_live[3]	  && !regs_ever_live[6]	  && !regs_ever_live[7]	  && !regs_ever_live[14]	  && !regs_ever_live[15]	  && !regs_ever_live[16]	  && !regs_ever_live[17]	  && !frame_pointer_needed);}/* Returns the set of live, callee-saved registers as a bitmask.  The   callee-saved extended registers cannot be stored individually, so   all of them will be included in the mask if any one of them is used. */intmn10300_get_live_callee_saved_regs (){  int mask;  int i;  mask = 0;  for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)    if (regs_ever_live[i] && ! call_used_regs[i])      mask |= (1 << i);  if ((mask & 0x3c000) != 0)    mask |= 0x3c000;  return mask;}

⌨️ 快捷键说明

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