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

📄 pa.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 5 页
字号:
/* Subroutines for insn-output.c for HPPA.   Copyright (C) 1992 Free Software Foundation, Inc.   Contributed by Tim Moore (moore@cs.utah.edu), based on sparc.cThis 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, 675 Mass Ave, Cambridge, MA 02139, USA.  */#include <stdio.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 "tree.h"#include "c-tree.h"#include "expr.h"#include "obstack.h"/* Save the operands last given to a compare for use when we   generate a scc or bcc insn.  */rtx hppa_compare_op0, hppa_compare_op1;enum cmp_type hppa_branch_type;/* Set by the FUNCTION_PROFILER macro. */int hp_profile_labelno;/* Name of where we pretend to think the frame pointer points.   Normally, this is "4", but if we are in a leaf procedure,   this is "something(30)".  Will this work? */char *frame_base_name;static rtx find_addr_reg ();/* Return non-zero only if OP is a register of mode MODE,   or const0_rtx.  */intreg_or_0_operand (op, mode)     rtx op;     enum machine_mode mode;{  return (op == const0_rtx || register_operand (op, mode));}intcall_operand_address (op, mode)     rtx op;     enum machine_mode mode;{  return (REG_P (op) 	  || (CONSTANT_P (op) && ! TARGET_LONG_CALLS));}intsymbolic_operand (op, mode)     register rtx op;     enum machine_mode mode;{  switch (GET_CODE (op))    {    case SYMBOL_REF:    case LABEL_REF:      return 1;    case CONST:      op = XEXP (op, 0);      return ((GET_CODE (XEXP (op, 0)) == SYMBOL_REF	       || GET_CODE (XEXP (op, 0)) == LABEL_REF)	      && GET_CODE (XEXP (op, 1)) == CONST_INT);    default:      return 0;    }}/* 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 1 if the operand is either a register or a memory operand that is   not symbolic.  */intreg_or_nonsymb_mem_operand (op, mode)    register rtx op;    enum machine_mode mode;{  if (register_operand (op, mode))    return 1;  if (memory_operand (op, mode) && ! symbolic_memory_operand (op, mode))    return 1;  return 0;}intmove_operand (op, mode)     rtx op;     enum machine_mode mode;{  if (register_operand (op, mode))    return 1;  if (op == CONST0_RTX (mode))    return 1;  if (GET_MODE (op) != mode)    return 0;  if (GET_CODE (op) == SUBREG)    op = SUBREG_REG (op);  if (GET_CODE (op) != MEM)    return 0;  op = XEXP (op, 0);  if (GET_CODE (op) == LO_SUM)    return (register_operand (XEXP (op, 0), Pmode)	    && CONSTANT_P (XEXP (op, 1)));  return memory_address_p (mode, op);}intpic_operand (op, mode)     rtx op;     enum machine_mode mode;{  return flag_pic && GET_CODE (op) == LABEL_REF;}intshort_memory_operand (op, mode)     rtx op;     enum machine_mode mode;{  if (GET_CODE (op) == MEM)    {      if (GET_CODE (XEXP (op, 0)) == REG)	return 1;      else if (GET_CODE (XEXP (op, 0)) == PLUS)	{	  rtx op1 = XEXP (XEXP (op, 0), 0);	  rtx op2 = XEXP (XEXP (op, 0), 1);	  if (GET_CODE (op1) == REG)	    return (GET_CODE (op2) == CONST_INT && INT_5_BITS (op2));	  else if (GET_CODE (op2) == REG)	    return (GET_CODE (op1) == CONST_INT && INT_5_BITS (op1));	}    }  return 0;}intregister_or_short_operand (op, mode)     rtx op;     enum machine_mode mode;{  if (register_operand (op, mode))    return 1;  if (GET_CODE (op) == SUBREG)    op = SUBREG_REG (op);  return short_memory_operand (op, mode);}intfp_reg_operand (op, mode)     rtx op;     enum machine_mode mode;{  return reg_renumber && FP_REG_P (op);}intcheck_fp_mov (operands)     rtx *operands;{  enum machine_mode mode = GET_MODE (operands[0]);  if (fp_reg_operand (operands[0], mode))    return (register_operand (operands[1], mode)	    || short_memory_operand (operands[1], mode));  else if (fp_reg_operand (operands[1], mode))    return (register_operand (operands[0], mode)	    || short_memory_operand (operands[0], mode));  else    return 1;}extern int current_function_uses_pic_offset_table;extern rtx force_reg (), validize_mem ();/* The rtx for the global offset table which is a special form   that *is* a position independent symbolic constant.  */rtx pic_pc_rtx;/* Ensure that we are not using patterns that are not OK with PIC.  */intcheck_pic (i)     int i;{  extern rtx recog_operand[];  switch (flag_pic)    {    case 1:      if (GET_CODE (recog_operand[i]) == SYMBOL_REF	  || (GET_CODE (recog_operand[i]) == CONST	      && ! rtx_equal_p (pic_pc_rtx, recog_operand[i])))	abort ();    case 2:    default:      return 1;    }}/* 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);}/* Return truth value of whether OP can be used as an operand in a   three operand arithmetic insn that accepts registers of mode MODE   or 14-bit signed integers.  */intarith_operand (op, mode)     rtx op;     enum machine_mode mode;{  return (register_operand (op, mode)	  || (GET_CODE (op) == CONST_INT && INT_14_BITS (op)));}/* Return truth value of whether OP can be used as an operand in a   three operand arithmetic insn that accepts registers of mode MODE   or 11-bit signed integers.  */intarith11_operand (op, mode)     rtx op;     enum machine_mode mode;{  return (register_operand (op, mode)	  || (GET_CODE (op) == CONST_INT && INT_11_BITS (op)));}intarith_double_operand (op, mode)     rtx op;     enum machine_mode mode;{  return (register_operand (op, mode)	  || (GET_CODE (op) == CONST_DOUBLE	      && GET_MODE (op) == mode	      && VAL_14_BITS_P (CONST_DOUBLE_LOW (op))	      && (CONST_DOUBLE_HIGH (op) >= 0		  == ((CONST_DOUBLE_LOW (op) & 0x1000) == 0))));}/* Return truth value of whether OP is a integer which fits the   range constraining immediate operands in three-address insns.  */intint5_operand (op, mode)     rtx op;     enum machine_mode mode;{  return (GET_CODE (op) == CONST_INT && INT_5_BITS (op));}intuint5_operand (op, mode)     rtx op;     enum machine_mode mode;{  return (GET_CODE (op) == CONST_INT && INT_U5_BITS (op));}  intint11_operand (op, mode)     rtx op;     enum machine_mode mode;{    return (GET_CODE (op) == CONST_INT && INT_11_BITS (op));}intarith5_operand (op, mode)     rtx op;     enum machine_mode mode;{  return register_operand (op, mode) || int5_operand (op, mode);}/* True iff zdepi can be used to generate this CONST_INT.  */intdepi_cint_operand (op, mode)     rtx op;     enum machine_mode mode;{  unsigned x;  unsigned lbmask, t;  if (GET_CODE (op) != CONST_INT)    return 0;  /* This might not be obvious, but it's at least fast.     This function is critcal; we don't have the time loops would take.  */  x = INTVAL (op);  lbmask = x & -x;  t = ((x >> 4) + lbmask) & ~(lbmask - 1);  return ((t & (t - 1)) == 0);}/* True iff depi or extru can be used to compute (reg & mask).  */intconsec_zeros_p (mask)     unsigned mask;{  mask = ~mask;  mask += mask & -mask;  return (mask & (mask - 1)) == 0;}/* True iff depi or extru can be used to compute (reg & OP).  */intand_operand (op, mode)     rtx op;     enum machine_mode mode;{  return (register_operand (op, mode)	  || (GET_CODE (op) == CONST_INT && consec_zeros_p (INTVAL (op))));}/* True iff depi can be used to compute (reg | MASK).  */intior_mask_p (mask)     unsigned mask;{  mask += mask & -mask;  return (mask & (mask - 1)) == 0;}/* True iff depi can be used to compute (reg | OP).  */intior_operand (op, mode)     rtx op;     enum machine_mode mode;{  return (register_operand (op, mode)	  || (GET_CODE (op) == CONST_INT && ior_mask_p (INTVAL (op))));}intarith32_operand (op, mode)     rtx op;     enum machine_mode mode;{  return register_operand (op, mode) || GET_CODE (op) == CONST_INT;}/* True iff OP can be the source of a move to a general register.  */intsrcsi_operand (op, mode)     rtx op;     enum machine_mode mode;{  /* Not intended for other modes than SImode.  */  if (mode != SImode)    return 0;  /* Accept any register or memory reference.  */  if (nonimmediate_operand (op, mode))    return 1;  if (depi_cint_operand (op, mode))    return 1;  /* OK if ldo or ldil can be used.  */  return (GET_CODE (op) == CONST_INT	  && (INT_14_BITS (op) || (INTVAL (op) & 0x7ff) == 0));}/* Legitimize PIC addresses.  If the address is already   position-independent, we return ORIG.  Newly generated   position-independent addresses go to REG.  If we need more   than one register, we lose.  */rtxlegitimize_pic_address (orig, mode, reg)     rtx orig, reg;     enum machine_mode mode;{  rtx pic_ref = orig;  if (GET_CODE (orig) == SYMBOL_REF)    {      if (reg == 0)	abort ();      if (flag_pic == 2)	{	  emit_insn (gen_rtx (SET, VOIDmode, reg,			      gen_rtx (HIGH, Pmode, orig)));	  emit_insn (gen_rtx (SET, VOIDmode, reg,			      gen_rtx (LO_SUM, Pmode, reg, orig)));	  orig = reg;	}      pic_ref = gen_rtx (MEM, Pmode,			 gen_rtx (PLUS, Pmode,				  pic_offset_table_rtx, orig));      current_function_uses_pic_offset_table = 1;      RTX_UNCHANGING_P (pic_ref) = 1;      emit_move_insn (reg, pic_ref);      return reg;    }  else if (GET_CODE (orig) == CONST)    {      rtx base, offset;      if (GET_CODE (XEXP (orig, 0)) == PLUS	  && XEXP (XEXP (orig, 0), 0) == pic_offset_table_rtx)	return orig;      if (reg == 0)	abort ();      if (GET_CODE (XEXP (orig, 0)) == PLUS)	{	  base = legitimize_pic_address (XEXP (XEXP (orig, 0), 0), Pmode, reg);	  orig = legitimize_pic_address (XEXP (XEXP (orig, 0), 1), Pmode,					 base == reg ? 0 : reg);	}      else abort ();      if (GET_CODE (orig) == CONST_INT)	{	  if (SMALL_INT (orig))	    return plus_constant_for_output (base, INTVAL (orig));	  orig = force_reg (Pmode, orig);	}      pic_ref = gen_rtx (PLUS, Pmode, base, orig);      /* Likewise, should we set special REG_NOTEs here?  */    }  return pic_ref;}/* Set up PIC-specific rtl.  This should not cause any insns   to be emitted.  */voidinitialize_pic (){}/* Emit special PIC prologues and epilogues.  */voidfinalize_pic (){  /* Need to emit this whether or not we obey regdecls,     since setjmp/longjmp can cause life info to screw up.  */  emit_insn (gen_rtx (USE, VOIDmode, pic_offset_table_rtx));}/* For the HPPA, REG and REG+CONST is cost 0   and addresses involving symbolic constants are cost 2.   PIC addresses are very expensive.   It is no coincidence that this has the same structure   as GO_IF_LEGITIMATE_ADDRESS.  */inthppa_address_cost (X)

⌨️ 快捷键说明

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