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

📄 vax.c

📁 linux下的gcc编译器
💻 C
📖 第 1 页 / 共 2 页
字号:
/* Subroutines for insn-output.c for VAX.   Copyright (C) 1987, 1994, 1995, 1997, 1998, 1999, 2000, 2001, 2002   Free Software Foundation, Inc.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 "function.h"#include "output.h"#include "insn-attr.h"#include "recog.h"#include "expr.h"#include "flags.h"#include "debug.h"#include "tm_p.h"#include "target.h"#include "target-def.h"static int follows_p PARAMS ((rtx, rtx));static void vax_output_function_prologue PARAMS ((FILE *, HOST_WIDE_INT));#if VMS_TARGETstatic void vms_asm_out_constructor PARAMS ((rtx, int));static void vms_asm_out_destructor PARAMS ((rtx, int));static void vms_select_section PARAMS ((tree, int, unsigned HOST_WIDE_INT));static void vms_encode_section_info PARAMS ((tree, int));static void vms_globalize_label PARAMS ((FILE *, const char *));#endifstatic void vax_output_mi_thunk PARAMS ((FILE *, tree, HOST_WIDE_INT,					 HOST_WIDE_INT, tree));/* Initialize the GCC target structure.  */#undef TARGET_ASM_ALIGNED_HI_OP#define TARGET_ASM_ALIGNED_HI_OP "\t.word\t"#undef TARGET_ASM_FUNCTION_PROLOGUE#define TARGET_ASM_FUNCTION_PROLOGUE vax_output_function_prologue#if VMS_TARGET#undef TARGET_ASM_SELECT_SECTION#define TARGET_ASM_SELECT_SECTION vms_select_section#undef TARGET_ENCODE_SECTION_INFO#define TARGET_ENCODE_SECTION_INFO vms_encode_section_info#undef TARGET_ASM_GLOBALIZE_LABEL#define TARGET_ASM_GLOBALIZE_LABEL vms_globalize_label#endif#undef TARGET_ASM_OUTPUT_MI_THUNK#define TARGET_ASM_OUTPUT_MI_THUNK vax_output_mi_thunk#undef TARGET_ASM_CAN_OUTPUT_MI_THUNK#define TARGET_ASM_CAN_OUTPUT_MI_THUNK default_can_output_mi_thunk_no_vcallstruct gcc_target targetm = TARGET_INITIALIZER;/* Set global variables as needed for the options enabled.  */voidoverride_options (){  /* We're VAX floating point, not IEEE floating point.  */  memset (real_format_for_mode, 0, sizeof real_format_for_mode);  real_format_for_mode[SFmode - QFmode] = &vax_f_format;  real_format_for_mode[DFmode - QFmode]    = (TARGET_G_FLOAT ? &vax_g_format : &vax_d_format);}/* Generate the assembly code for function entry.  FILE is a stdio   stream to output the code to.  SIZE is an int: how many units of   temporary storage to allocate.   Refer to the array `regs_ever_live' to determine which registers to   save; `regs_ever_live[I]' is nonzero if register number I is ever   used in the function.  This function is responsible for knowing   which registers should not be saved even if used.  */static voidvax_output_function_prologue (file, size)     FILE * file;     HOST_WIDE_INT size;{  register int regno;  register int mask = 0;  for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)    if (regs_ever_live[regno] && !call_used_regs[regno])      mask |= 1 << regno;  fprintf (file, "\t.word 0x%x\n", mask);  if (dwarf2out_do_frame ())    {      const char *label = dwarf2out_cfi_label ();      int offset = 0;      for (regno = FIRST_PSEUDO_REGISTER-1; regno >= 0; --regno)	if (regs_ever_live[regno] && !call_used_regs[regno])	  dwarf2out_reg_save (label, regno, offset -= 4);      dwarf2out_reg_save (label, PC_REGNUM, offset -= 4);      dwarf2out_reg_save (label, FRAME_POINTER_REGNUM, offset -= 4);      dwarf2out_reg_save (label, ARG_POINTER_REGNUM, offset -= 4);      dwarf2out_def_cfa (label, FRAME_POINTER_REGNUM, -(offset - 4));    }  if (VMS_TARGET)    {      /* Adjusting the stack pointer by 4 before calling C$MAIN_ARGS	 is required when linking with the VMS POSIX version of the C	 run-time library; using `subl2 $4,r0' is adequate but we use	 `clrl -(sp)' instead.  The extra 4 bytes could be removed	 after the call because STARTING_FRAME_OFFSET's setting of -4	 will end up adding them right back again, but don't bother.  */      if (MAIN_NAME_P (DECL_NAME (current_function_decl)))	asm_fprintf (file, "\tclrl -(%Rsp)\n\tjsb _C$MAIN_ARGS\n");    }  size -= STARTING_FRAME_OFFSET;  if (size >= 64)    asm_fprintf (file, "\tmovab %d(%Rsp),%Rsp\n", -size);  else if (size)    asm_fprintf (file, "\tsubl2 $%d,%Rsp\n", size);}/* This is like nonimmediate_operand with a restriction on the type of MEM.  */voidsplit_quadword_operands (operands, low, n)     rtx *operands, *low;     int n ATTRIBUTE_UNUSED;{  int i;  /* Split operands.  */  low[0] = low[1] = low[2] = 0;  for (i = 0; i < 3; i++)    {      if (low[i])	/* it's already been figured out */;      else if (GET_CODE (operands[i]) == MEM	       && (GET_CODE (XEXP (operands[i], 0)) == POST_INC))	{	  rtx addr = XEXP (operands[i], 0);	  operands[i] = low[i] = gen_rtx_MEM (SImode, addr);	  if (which_alternative == 0 && i == 0)	    {	      addr = XEXP (operands[i], 0);	      operands[i+1] = low[i+1] = gen_rtx_MEM (SImode, addr);	    }	}      else	{	  low[i] = operand_subword (operands[i], 0, 0, DImode);	  operands[i] = operand_subword (operands[i], 1, 0, DImode);	}    }}voidprint_operand_address (file, addr)     FILE *file;     register rtx addr;{  register rtx reg1, breg, ireg;  rtx offset; retry:  switch (GET_CODE (addr))    {    case MEM:      fprintf (file, "*");      addr = XEXP (addr, 0);      goto retry;    case REG:      fprintf (file, "(%s)", reg_names[REGNO (addr)]);      break;    case PRE_DEC:      fprintf (file, "-(%s)", reg_names[REGNO (XEXP (addr, 0))]);      break;    case POST_INC:      fprintf (file, "(%s)+", reg_names[REGNO (XEXP (addr, 0))]);      break;    case PLUS:      /* There can be either two or three things added here.  One must be a	 REG.  One can be either a REG or a MULT of a REG and an appropriate	 constant, and the third can only be a constant or a MEM.	 We get these two or three things and put the constant or MEM in	 OFFSET, the MULT or REG in IREG, and the REG in BREG.  If we have	 a register and can't tell yet if it is a base or index register,	 put it into REG1.  */      reg1 = 0; ireg = 0; breg = 0; offset = 0;      if (CONSTANT_ADDRESS_P (XEXP (addr, 0))	  || GET_CODE (XEXP (addr, 0)) == MEM)	{	  offset = XEXP (addr, 0);	  addr = XEXP (addr, 1);	}      else if (CONSTANT_ADDRESS_P (XEXP (addr, 1))	       || GET_CODE (XEXP (addr, 1)) == MEM)	{	  offset = XEXP (addr, 1);	  addr = XEXP (addr, 0);	}      else if (GET_CODE (XEXP (addr, 1)) == MULT)	{	  ireg = XEXP (addr, 1);	  addr = XEXP (addr, 0);	}      else if (GET_CODE (XEXP (addr, 0)) == MULT)	{	  ireg = XEXP (addr, 0);	  addr = XEXP (addr, 1);	}      else if (GET_CODE (XEXP (addr, 1)) == REG)	{	  reg1 = XEXP (addr, 1);	  addr = XEXP (addr, 0);	}      else if (GET_CODE (XEXP (addr, 0)) == REG)	{	  reg1 = XEXP (addr, 0);	  addr = XEXP (addr, 1);	}      else	abort ();      if (GET_CODE (addr) == REG)	{	  if (reg1)	    ireg = addr;	  else	    reg1 = addr;	}      else if (GET_CODE (addr) == MULT)	ireg = addr;      else if (GET_CODE (addr) == PLUS)	{	  if (CONSTANT_ADDRESS_P (XEXP (addr, 0))	      || GET_CODE (XEXP (addr, 0)) == MEM)	    {	      if (offset)		{		  if (GET_CODE (offset) == CONST_INT)		    offset = plus_constant (XEXP (addr, 0), INTVAL (offset));		  else if (GET_CODE (XEXP (addr, 0)) == CONST_INT)		    offset = plus_constant (offset, INTVAL (XEXP (addr, 0)));		  else		    abort ();		}	      offset = XEXP (addr, 0);	    }	  else if (GET_CODE (XEXP (addr, 0)) == REG)	    {	      if (reg1)		ireg = reg1, breg = XEXP (addr, 0), reg1 = 0;	      else		reg1 = XEXP (addr, 0);	    }	  else if (GET_CODE (XEXP (addr, 0)) == MULT)	    {	      if (ireg)		abort ();	      ireg = XEXP (addr, 0);	    }	  else	    abort ();	  if (CONSTANT_ADDRESS_P (XEXP (addr, 1))	      || GET_CODE (XEXP (addr, 1)) == MEM)	    {	      if (offset)		{		  if (GET_CODE (offset) == CONST_INT)		    offset = plus_constant (XEXP (addr, 1), INTVAL (offset));		  else if (GET_CODE (XEXP (addr, 1)) == CONST_INT)		    offset = plus_constant (offset, INTVAL (XEXP (addr, 1)));		  else		    abort ();		}	      offset = XEXP (addr, 1);	    }	  else if (GET_CODE (XEXP (addr, 1)) == REG)	    {	      if (reg1)		ireg = reg1, breg = XEXP (addr, 1), reg1 = 0;	      else		reg1 = XEXP (addr, 1);	    }	  else if (GET_CODE (XEXP (addr, 1)) == MULT)	    {	      if (ireg)		abort ();	      ireg = XEXP (addr, 1);	    }	  else	    abort ();	}      else	abort ();      /* If REG1 is nonzero, figure out if it is a base or index register.  */      if (reg1)	{	  if (breg != 0 || (offset && GET_CODE (offset) == MEM))	    {	      if (ireg)		abort ();	      ireg = reg1;	    }	  else	    breg = reg1;	}      if (offset != 0)	output_address (offset);      if (breg != 0)	fprintf (file, "(%s)", reg_names[REGNO (breg)]);      if (ireg != 0)	{	  if (GET_CODE (ireg) == MULT)	    ireg = XEXP (ireg, 0);	  if (GET_CODE (ireg) != REG)	    abort ();	  fprintf (file, "[%s]", reg_names[REGNO (ireg)]);	}      break;    default:      output_addr_const (file, addr);    }}const char *rev_cond_name (op)     rtx op;{  switch (GET_CODE (op))    {    case EQ:      return "neq";    case NE:      return "eql";    case LT:      return "geq";    case LE:      return "gtr";    case GT:      return "leq";    case GE:      return "lss";    case LTU:      return "gequ";    case LEU:      return "gtru";    case GTU:      return "lequ";    case GEU:      return "lssu";    default:      abort ();    }}intvax_float_literal(c)    register rtx c;{  register enum machine_mode mode;  REAL_VALUE_TYPE r, s;  int i;  if (GET_CODE (c) != CONST_DOUBLE)    return 0;  mode = GET_MODE (c);  if (c == const_tiny_rtx[(int) mode][0]      || c == const_tiny_rtx[(int) mode][1]      || c == const_tiny_rtx[(int) mode][2])    return 1;  REAL_VALUE_FROM_CONST_DOUBLE (r, c);  for (i = 0; i < 7; i++)    {      int x = 1 << i;      REAL_VALUE_FROM_INT (s, x, 0, mode);      if (REAL_VALUES_EQUAL (r, s))	return 1;      if (!exact_real_inverse (mode, &s))	abort ();      if (REAL_VALUES_EQUAL (r, s))	return 1;    }  return 0;}/* Return the cost in cycles of a memory address, relative to register   indirect.   Each of the following adds the indicated number of cycles:   1 - symbolic address   1 - pre-decrement   1 - indexing and/or offset(register)   2 - indirect */intvax_address_cost (addr)    register rtx addr;{  int reg = 0, indexed = 0, indir = 0, offset = 0, predec = 0;  rtx plus_op0 = 0, plus_op1 = 0; restart:  switch (GET_CODE (addr))    {    case PRE_DEC:      predec = 1;    case REG:    case SUBREG:    case POST_INC:      reg = 1;      break;    case MULT:      indexed = 1;	/* 2 on VAX 2 */      break;    case CONST_INT:      /* byte offsets cost nothing (on a VAX 2, they cost 1 cycle) */      if (offset == 0)	offset = (unsigned HOST_WIDE_INT)(INTVAL(addr)+128) > 256;      break;    case CONST:    case SYMBOL_REF:      offset = 1;	/* 2 on VAX 2 */      break;    case LABEL_REF:	/* this is probably a byte offset from the pc */      if (offset == 0)	offset = 1;      break;    case PLUS:      if (plus_op0)	plus_op1 = XEXP (addr, 0);      else	plus_op0 = XEXP (addr, 0);      addr = XEXP (addr, 1);      goto restart;    case MEM:      indir = 2;	/* 3 on VAX 2 */      addr = XEXP (addr, 0);      goto restart;    default:      break;    }  /* Up to 3 things can be added in an address.  They are stored in     plus_op0, plus_op1, and addr.  */  if (plus_op0)    {      addr = plus_op0;      plus_op0 = 0;      goto restart;    }  if (plus_op1)    {      addr = plus_op1;      plus_op1 = 0;      goto restart;    }  /* Indexing and register+offset can both be used (except on a VAX 2)     without increasing execution time over either one alone.  */  if (reg && indexed && offset)    return reg + indir + offset + predec;  return reg + indexed + indir + offset + predec;}

⌨️ 快捷键说明

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