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

📄 i960.c

📁 gcc编译工具没有什么特别
💻 C
📖 第 1 页 / 共 5 页
字号:
/* Subroutines used for code generation on intel 80960.   Copyright (C) 1992, 1995, 1996, 1997, 1998 Free Software Foundation, Inc.   Contributed by Steven McGeady, Intel Corp.   Additional Work by Glenn Colon-Bonet, Jonathan Shapiro, Andy Wilson   Converted to GCC 2.0 by Jim Wilson and Michael Tiemann, Cygnus Support.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 <stdio.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 "tree.h"#include "insn-codes.h"#include "expr.h"#include "except.h"#include "function.h"#include "recog.h"#include <math.h>/* Save the operands last given to a compare for use when we   generate a scc or bcc insn.  */rtx i960_compare_op0, i960_compare_op1;/* Used to implement #pragma align/noalign.  Initialized by OVERRIDE_OPTIONS   macro in i960.h.  */static int i960_maxbitalignment;static int i960_last_maxbitalignment;/* Used to implement switching between MEM and ALU insn types, for better   C series performance.  */enum insn_types i960_last_insn_type;/* The leaf-procedure return register.  Set only if this is a leaf routine.  */static int i960_leaf_ret_reg;/* True if replacing tail calls with jumps is OK.  */static int tail_call_ok;/* A string containing a list of insns to emit in the epilogue so as to   restore all registers saved by the prologue.  Created by the prologue   code as it saves registers away.  */char epilogue_string[1000];/* A unique number (per function) for return labels.  */static int ret_label = 0;/* This is true if FNDECL is either a varargs or a stdarg function.   This is used to help identify functions that use an argument block.  */#define VARARGS_STDARG_FUNCTION(FNDECL)	\((TYPE_ARG_TYPES (TREE_TYPE (FNDECL)) != 0						      \  && (TREE_VALUE (tree_last (TYPE_ARG_TYPES (TREE_TYPE (FNDECL)))) != void_type_node))    \ || current_function_varargs)/* Handle pragmas for compatibility with Intel's compilers.  *//* ??? This is incomplete, since it does not handle all pragmas that the   intel compilers understand.  */intprocess_pragma (p_getc, p_ungetc, pname)     int (*  p_getc) PROTO ((void));     void (* p_ungetc) PROTO ((int));     char * pname;{  int i;  register int c;  char buf[20];  char *s = buf;  int align;  /* Should be pragma 'far' or equivalent for callx/balx here.  */  if (strcmp (pname, "align") != 0)    return 0;    do    {      c = p_getc ();    }  while (c == ' ' || c == '\t');  if (c == '(')    c = p_getc ();    while (c >= '0' && c <= '9')    {      if (s < buf + sizeof buf - 1)	*s++ = c;      c = p_getc ();    }    *s = '\0';  /* We had to read a non-numerical character to get out of the     while loop---often a newline.  So, we have to put it back to     make sure we continue to parse everything properly.  */    p_ungetc (c);  align = atoi (buf);  switch (align)    {    case 0:      /* Return to last alignment.  */      align = i960_last_maxbitalignment / 8;      /* Fall through.  */    case 16:    case 8:    case 4:    case 2:    case 1:      i960_last_maxbitalignment = i960_maxbitalignment;      i960_maxbitalignment = align * 8;      break;          default:      /* Silently ignore bad values.  */      break;    }    /* NOTE: ic960 R3.0 pragma align definition:          #pragma align [(size)] | (identifier=size[,...])     #pragma noalign [(identifier)[,...]]          (all parens are optional)          - size is [1,2,4,8,16]     - noalign means size==1     - applies only to component elements of a struct (and union?)     - identifier applies to structure tag (only)     - missing identifier means next struct          - alignment rules for bitfields need more investigation  */    return 1;}/* Initialize variables before compiling any files.  */voidi960_initialize (){  if (TARGET_IC_COMPAT2_0)    {      i960_maxbitalignment = 8;      i960_last_maxbitalignment = 128;    }  else    {      i960_maxbitalignment = 128;      i960_last_maxbitalignment = 8;    }}/* Return true if OP can be used as the source of an fp move insn.  */intfpmove_src_operand (op, mode)     rtx op;     enum machine_mode mode;{  return (GET_CODE (op) == CONST_DOUBLE || general_operand (op, mode));}#if 0/* Return true if OP is a register or zero.  */intreg_or_zero_operand (op, mode)     rtx op;     enum machine_mode mode;{  return register_operand (op, mode) || op == const0_rtx;}#endif/* Return truth value of whether OP can be used as an operands in a three   address arithmetic insn (such as add %o1,7,%l2) of mode MODE.  */intarith_operand (op, mode)     rtx op;     enum machine_mode mode;{  return (register_operand (op, mode) || literal (op, mode));}/* Return truth value of whether OP can be used as an operands in a three   address logic insn, possibly complementing OP, of mode MODE.  */intlogic_operand (op, mode)     rtx op;     enum machine_mode mode;{  return (register_operand (op, mode)	  || (GET_CODE (op) == CONST_INT	      && INTVAL(op) >= -32 && INTVAL(op) < 32));}/* Return true if OP is a register or a valid floating point literal.  */intfp_arith_operand (op, mode)     rtx op;     enum machine_mode mode;{  return (register_operand (op, mode) || fp_literal (op, mode));}/* Return true is OP is a register or a valid signed integer literal.  */intsigned_arith_operand (op, mode)     rtx op;     enum machine_mode mode;{  return (register_operand (op, mode) || signed_literal (op, mode));}/* Return truth value of whether OP is a integer which fits the   range constraining immediate operands in three-address insns.  */intliteral (op, mode)     rtx op;     enum machine_mode mode;{  return ((GET_CODE (op) == CONST_INT) && INTVAL(op) >= 0 && INTVAL(op) < 32);}/* Return true if OP is a float constant of 1.  */intfp_literal_one (op, mode)     rtx op;     enum machine_mode mode;{  return (TARGET_NUMERICS && mode == GET_MODE (op) && op == CONST1_RTX (mode));}/* Return true if OP is a float constant of 0.  */intfp_literal_zero (op, mode)     rtx op;     enum machine_mode mode;{  return (TARGET_NUMERICS && mode == GET_MODE (op) && op == CONST0_RTX (mode));}/* Return true if OP is a valid floating point literal.  */intfp_literal(op, mode)     rtx op;     enum machine_mode mode;{  return fp_literal_zero (op, mode) || fp_literal_one (op, mode);}/* Return true if OP is a valid signed immediate constant.  */intsigned_literal(op, mode)     rtx op;     enum machine_mode mode;{  return ((GET_CODE (op) == CONST_INT) && INTVAL(op) > -32 && INTVAL(op) < 32);}/* Return truth value of statement that OP is a symbolic memory   operand of mode MODE.  */intsymbolic_memory_operand (op, mode)     rtx op;     enum machine_mode mode;{  if (GET_CODE (op) == SUBREG)    op = SUBREG_REG (op);  if (GET_CODE (op) != MEM)    return 0;  op = XEXP (op, 0);  return (GET_CODE (op) == SYMBOL_REF || GET_CODE (op) == CONST	  || GET_CODE (op) == HIGH || GET_CODE (op) == LABEL_REF);}/* Return truth value of whether OP is EQ or NE.  */inteq_or_neq (op, mode)     rtx op;     enum machine_mode mode;{  return (GET_CODE (op) == EQ || GET_CODE (op) == NE);}/* OP is an integer register or a constant.  */intarith32_operand (op, mode)     rtx op;     enum machine_mode mode;{  if (register_operand (op, mode))    return 1;  return (CONSTANT_P (op));}/* Return true if OP is an integer constant which is a power of 2.  */intpower2_operand (op,mode)     rtx op;     enum machine_mode mode;{  if (GET_CODE (op) != CONST_INT)    return 0;  return exact_log2 (INTVAL (op)) >= 0;}/* Return true if OP is an integer constant which is the complement of a   power of 2.  */intcmplpower2_operand (op, mode)     rtx op;     enum machine_mode mode;{  if (GET_CODE (op) != CONST_INT)    return 0;  return exact_log2 (~ INTVAL (op)) >= 0;}/* If VAL has only one bit set, return the index of that bit.  Otherwise   return -1.  */intbitpos (val)     unsigned int val;{  register int i;  for (i = 0; val != 0; i++, val >>= 1)    {      if (val & 1)	{	  if (val != 1)	    return -1;	  return i;	}    }  return -1;}/* Return non-zero if OP is a mask, i.e. all one bits are consecutive.   The return value indicates how many consecutive non-zero bits exist   if this is a mask.  This is the same as the next function, except that   it does not indicate what the start and stop bit positions are.  */intis_mask (val)     unsigned int val;{  register int start, end, i;  start = -1;  for (i = 0; val != 0; val >>= 1, i++)    {      if (val & 1)	{	  if (start < 0)	    start = i;	  end = i;	  continue;	}      /* Still looking for the first bit.  */      if (start < 0)	continue;      /* We've seen the start of a bit sequence, and now a zero.  There	 must be more one bits, otherwise we would have exited the loop.	 Therefore, it is not a mask.  */      if (val)	return 0;    }  /* The bit string has ones from START to END bit positions only.  */  return end - start + 1;}/* If VAL is a mask, then return nonzero, with S set to the starting bit   position and E set to the ending bit position of the mask.  The return   value indicates how many consecutive bits exist in the mask.  This is   the same as the previous function, except that it also indicates the   start and end bit positions of the mask.  */intbitstr (val, s, e)     unsigned int val;     int *s, *e;{  register int start, end, i;  start = -1;  end = -1;  for (i = 0; val != 0; val >>= 1, i++)    {      if (val & 1)	{	  if (start < 0)	    start = i;	  end = i;	  continue;	}      /* Still looking for the first bit.  */      if (start < 0)	continue;      /* We've seen the start of a bit sequence, and now a zero.  There	 must be more one bits, otherwise we would have exited the loop.	 Therefor, it is not a mask.  */      if (val)	{	  start = -1;	  end = -1;	  break;	}    }  /* The bit string has ones from START to END bit positions only.  */  *s = start;  *e = end;  return ((start < 0) ? 0 : end - start + 1);}/* Return the machine mode to use for a comparison.  */enum machine_modeselect_cc_mode (op, x)     RTX_CODE op;     rtx x;{  if (op == GTU || op == LTU || op == GEU || op == LEU)    return CC_UNSmode;  return CCmode;}/* X and Y are two things to compare using CODE.  Emit the compare insn and   return the rtx for register 36 in the proper mode.  */rtxgen_compare_reg (code, x, y)     enum rtx_code code;     rtx x, y;{  rtx cc_reg;  enum machine_mode ccmode = SELECT_CC_MODE (code, x, y);  enum machine_mode mode    = GET_MODE (x) == VOIDmode ? GET_MODE (y) : GET_MODE (x);  if (mode == SImode)    {      if (! arith_operand (x, mode))	x = force_reg (SImode, x);      if (! arith_operand (y, mode))	y = force_reg (SImode, y);    }  cc_reg = gen_rtx (REG, ccmode, 36);  emit_insn (gen_rtx (SET, VOIDmode, cc_reg,		      gen_rtx (COMPARE, ccmode, x, y)));  return cc_reg;}/* For the i960, REG is cost 1, REG+immed CONST is cost 2, REG+REG is cost 2,   REG+nonimmed CONST is cost 4.  REG+SYMBOL_REF, SYMBOL_REF, and similar

⌨️ 快捷键说明

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