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

📄 sparc.c

📁 gcc库的原代码,对编程有很大帮助.
💻 C
📖 第 1 页 / 共 5 页
字号:
intmove_pic_label (op, mode)     rtx op;     enum machine_mode mode;{  /* Special case for PIC.  */  if (flag_pic && GET_CODE (op) == LABEL_REF)    return 1;  return 0;}intsplittable_symbolic_memory_operand (op, mode)     rtx op;     enum machine_mode mode;{  if (GET_CODE (op) != MEM)    return 0;  if (! symbolic_operand (XEXP (op, 0), Pmode))    return 0;  return 1;}intsplittable_immediate_memory_operand (op, mode)     rtx op;     enum machine_mode mode;{  if (GET_CODE (op) != MEM)    return 0;  if (! immediate_operand (XEXP (op, 0), Pmode))    return 0;  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 1 if this is a comparison operator, but not an EQ, NE, GEU,   or LTU for non-floating-point.  We handle those specially.  */intnormal_comp_operator (op, mode)     rtx op;     enum machine_mode mode;{  enum rtx_code code = GET_CODE (op);  if (GET_RTX_CLASS (code) != '<')    return 0;  if (GET_MODE (XEXP (op, 0)) == CCFPmode      || GET_MODE (XEXP (op, 0)) == CCFPEmode)    return 1;  return (code != NE && code != EQ && code != GEU && code != LTU);}/* Return 1 if this is a comparison operator.  This allows the use of   MATCH_OPERATOR to recognize all the branch insns.  */intnoov_compare_op (op, mode)    register rtx op;    enum machine_mode mode;{  enum rtx_code code = GET_CODE (op);  if (GET_RTX_CLASS (code) != '<')    return 0;  if (GET_MODE (XEXP (op, 0)) == CC_NOOVmode)    /* These are the only branches which work with CC_NOOVmode.  */    return (code == EQ || code == NE || code == GE || code == LT);  return 1;}/* Nonzero if OP is a comparison operator suitable for use in v9   conditional move or branch on register contents instructions.  */intv9_regcmp_op (op, mode)     register rtx op;     enum machine_mode mode;{  enum rtx_code code = GET_CODE (op);  if (GET_RTX_CLASS (code) != '<')    return 0;  return v9_regcmp_p (code);}/* Return 1 if this is a SIGN_EXTEND or ZERO_EXTEND operation.  */intextend_op (op, mode)     rtx op;     enum machine_mode mode;{  return GET_CODE (op) == SIGN_EXTEND || GET_CODE (op) == ZERO_EXTEND;}/* Return nonzero if OP is an operator of mode MODE which can set   the condition codes explicitly.  We do not include PLUS and MINUS   because these require CC_NOOVmode, which we handle explicitly.  */intcc_arithop (op, mode)     rtx op;     enum machine_mode mode;{  if (GET_CODE (op) == AND      || GET_CODE (op) == IOR      || GET_CODE (op) == XOR)    return 1;  return 0;}/* Return nonzero if OP is an operator of mode MODE which can bitwise   complement its second operand and set the condition codes explicitly.  */intcc_arithopn (op, mode)     rtx op;     enum machine_mode mode;{  /* XOR is not here because combine canonicalizes (xor (not ...) ...)     and (xor ... (not ...)) to (not (xor ...)).   */  return (GET_CODE (op) == AND	  || GET_CODE (op) == IOR);}/* Return true if OP is a register, or is a CONST_INT that can fit in a 13   bit immediate field.  This is an acceptable SImode operand for most 3   address instructions.  */intarith_operand (op, mode)     rtx op;     enum machine_mode mode;{  return (register_operand (op, mode)	  || (GET_CODE (op) == CONST_INT && SMALL_INT (op)));}/* Return true if OP is a register, or is a CONST_INT that can fit in an 11   bit immediate field.  This is an acceptable SImode operand for the movcc   instructions.  */intarith11_operand (op, mode)     rtx op;     enum machine_mode mode;{  return (register_operand (op, mode)	  || (GET_CODE (op) == CONST_INT	      && ((unsigned) (INTVAL (op) + 0x400) < 0x800)));}/* Return true if OP is a register, or is a CONST_INT that can fit in an 10   bit immediate field.  This is an acceptable SImode operand for the movrcc   instructions.  */intarith10_operand (op, mode)     rtx op;     enum machine_mode mode;{  return (register_operand (op, mode)	  || (GET_CODE (op) == CONST_INT	      && ((unsigned) (INTVAL (op) + 0x200) < 0x400)));}/* Return true if OP is a register, is a CONST_INT that fits in a 13 bit   immediate field, or is a CONST_DOUBLE whose both parts fit in a 13 bit   immediate field.   v9: Return true if OP is a register, or is a CONST_INT or CONST_DOUBLE that   can fit in a 13 bit immediate field.  This is an acceptable DImode operand   for most 3 address instructions.  */intarith_double_operand (op, mode)     rtx op;     enum machine_mode mode;{  return (register_operand (op, mode)	  || (GET_CODE (op) == CONST_INT && SMALL_INT (op))	  || (! TARGET_V9	      && GET_CODE (op) == CONST_DOUBLE	      && (unsigned) (CONST_DOUBLE_LOW (op) + 0x1000) < 0x2000	      && (unsigned) (CONST_DOUBLE_HIGH (op) + 0x1000) < 0x2000)	  || (TARGET_V9	      && GET_CODE (op) == CONST_DOUBLE	      && (unsigned) (CONST_DOUBLE_LOW (op) + 0x1000) < 0x2000	      && ((CONST_DOUBLE_HIGH (op) == -1		   && (CONST_DOUBLE_LOW (op) & 0x1000) == 0x1000)		  || (CONST_DOUBLE_HIGH (op) == 0		      && (CONST_DOUBLE_LOW (op) & 0x1000) == 0))));}/* Return true if OP is a register, or is a CONST_INT or CONST_DOUBLE that   can fit in an 11 bit immediate field.  This is an acceptable DImode   operand for the movcc instructions.  *//* ??? Replace with arith11_operand?  */intarith11_double_operand (op, mode)     rtx op;     enum machine_mode mode;{  return (register_operand (op, mode)	  || (GET_CODE (op) == CONST_DOUBLE	      && (GET_MODE (op) == mode || GET_MODE (op) == VOIDmode)	      && (unsigned) (CONST_DOUBLE_LOW (op) + 0x400) < 0x800	      && ((CONST_DOUBLE_HIGH (op) == -1		   && (CONST_DOUBLE_LOW (op) & 0x400) == 0x400)		  || (CONST_DOUBLE_HIGH (op) == 0		      && (CONST_DOUBLE_LOW (op) & 0x400) == 0)))	  || (GET_CODE (op) == CONST_INT	      && (GET_MODE (op) == mode || GET_MODE (op) == VOIDmode)	      && (unsigned) (INTVAL (op) + 0x400) < 0x800));}/* Return true if OP is a register, or is a CONST_INT or CONST_DOUBLE that   can fit in an 10 bit immediate field.  This is an acceptable DImode   operand for the movrcc instructions.  *//* ??? Replace with arith10_operand?  */intarith10_double_operand (op, mode)     rtx op;     enum machine_mode mode;{  return (register_operand (op, mode)	  || (GET_CODE (op) == CONST_DOUBLE	      && (GET_MODE (op) == mode || GET_MODE (op) == VOIDmode)	      && (unsigned) (CONST_DOUBLE_LOW (op) + 0x200) < 0x400	      && ((CONST_DOUBLE_HIGH (op) == -1		   && (CONST_DOUBLE_LOW (op) & 0x200) == 0x200)		  || (CONST_DOUBLE_HIGH (op) == 0		      && (CONST_DOUBLE_LOW (op) & 0x200) == 0)))	  || (GET_CODE (op) == CONST_INT	      && (GET_MODE (op) == mode || GET_MODE (op) == VOIDmode)	      && (unsigned) (INTVAL (op) + 0x200) < 0x400));}/* Return truth value of whether OP is a integer which fits the   range constraining immediate operands in most three-address insns,   which have a 13 bit immediate field.  */intsmall_int (op, mode)     rtx op;     enum machine_mode mode;{  return (GET_CODE (op) == CONST_INT && SMALL_INT (op));}/* Recognize operand values for the umul instruction.  That instruction sign   extends immediate values just like all other sparc instructions, but   interprets the extended result as an unsigned number.  */intuns_small_int (op, mode)     rtx op;     enum machine_mode mode;{#if HOST_BITS_PER_WIDE_INT > 32  /* All allowed constants will fit a CONST_INT.  */  return (GET_CODE (op) == CONST_INT	  && ((INTVAL (op) >= 0 && INTVAL (op) < 0x1000)	      || (INTVAL (op) >= 0xFFFFF000 && INTVAL (op) < 0x100000000L)));#else  return ((GET_CODE (op) == CONST_INT && (unsigned) INTVAL (op) < 0x1000)	  || (GET_CODE (op) == CONST_DOUBLE	      && CONST_DOUBLE_HIGH (op) == 0	      && (unsigned) CONST_DOUBLE_LOW (op) - 0xFFFFF000 < 0x1000));#endif}intuns_arith_operand (op, mode)     rtx op;     enum machine_mode mode;{  return register_operand (op, mode) || uns_small_int (op, mode);}/* Return truth value of statement that OP is a call-clobbered register.  */intclobbered_register (op, mode)     rtx op;     enum machine_mode mode;{  return (GET_CODE (op) == REG && call_used_regs[REGNO (op)]);}/* X and Y are two things to compare using CODE.  Emit the compare insn and   return the rtx for the cc reg in the proper mode.  */rtxgen_compare_reg (code, x, y)     enum rtx_code code;     rtx x, y;{  enum machine_mode mode = SELECT_CC_MODE (code, x, y);  rtx cc_reg;  /* ??? We don't have movcc patterns so we cannot generate pseudo regs for the     fpcc regs (cse can't tell they're really call clobbered regs and will     remove a duplicate comparison even if there is an intervening function     call - it will then try to reload the cc reg via an int reg which is why     we need the movcc patterns).  It is possible to provide the movcc     patterns by using the ldxfsr/stxfsr v9 insns.  I tried it: you need two     registers (say %g1,%g5) and it takes about 6 insns.  A better fix would be     to tell cse that CCFPE mode registers (even pseudos) are call     clobbered.  */  /* ??? This is an experiment.  Rather than making changes to cse which may     or may not be easy/clean, we do our own cse.  This is possible because     we will generate hard registers.  Cse knows they're call clobbered (it     doesn't know the same thing about pseudos). If we guess wrong, no big     deal, but if we win, great!  */  if (TARGET_V9 && GET_MODE_CLASS (GET_MODE (x)) == MODE_FLOAT)#if 1 /* experiment */    {      int reg;      /* We cycle through the registers to ensure they're all exercised.  */      static int next_fpcc_reg = 0;      /* Previous x,y for each fpcc reg.  */      static rtx prev_args[4][2];      /* Scan prev_args for x,y.  */      for (reg = 0; reg < 4; reg++)	if (prev_args[reg][0] == x && prev_args[reg][1] == y)	  break;      if (reg == 4)	{	  reg = next_fpcc_reg;	  prev_args[reg][0] = x;	  prev_args[reg][1] = y;	  next_fpcc_reg = (next_fpcc_reg + 1) & 3;	}      cc_reg = gen_rtx (REG, mode, reg + 96);    }#else    cc_reg = gen_reg_rtx (mode);#endif /* ! experiment */  else    cc_reg = gen_rtx (REG, mode, 0);  emit_insn (gen_rtx (SET, VOIDmode, cc_reg,		      gen_rtx (COMPARE, mode, x, y)));  return cc_reg;}/* This function is used for v9 only.   CODE is the code for an Scc's comparison.   OPERANDS[0] is the target of the Scc insn.   OPERANDS[1] is the value we compare against const0_rtx (which hasn't   been generated yet).   This function is needed to turn	   (set (reg:SI 110)	       (gt (reg:CCX 0 %g0)	           (const_int 0)))   into	   (set (reg:SI 110)	       (gt:DI (reg:CCX 0 %g0)	           (const_int 0)))   IE: The instruction recognizer needs to see the mode of the comparison to   find the right instruction. We could use "gt:DI" right in the   define_expand, but leaving it out allows us to handle DI, SI, etc.   We refer to the global sparc compare operands sparc_compare_op0 and   sparc_compare_op1.     ??? Some of this is outdated as the scc insns set the mode of the   comparison now.   ??? We optimize for the case where op1 is 0 and the comparison allows us to   use the "movrCC" insns. This reduces the generated code from three to two   insns.  This way seems too brute force though.  Is there a more elegant way   to achieve the same effect?   Currently, this function always returns 1.  ??? Can it ever fail?  */intgen_v9_scc (compare_code, operands)     enum rtx_code compare_code;     register rtx *operands;{  rtx temp;  if (GET_MODE_CLASS (GET_MODE (sparc_compare_op0)) == MODE_INT      && sparc_compare_op1 == const0_rtx      && (compare_code == EQ || compare_code == NE	  || compare_code == LT || compare_code == LE	  || compare_code == GT || compare_code == GE))    {      /* Special case for op0 != 0.  This can be done with one instruction if	 op0 can be clobbered.  We store to a temp, and then clobber the temp,	 but the combiner will remove the first insn.  */      if (compare_code == NE	  && GET_MODE (operands[0]) == DImode	  && GET_MODE (sparc_compare_op0) == DImode)	{	  emit_insn (gen_rtx (SET, VOIDmode, operands[0], sparc_compare_op0));	  emit_insn (gen_rtx (SET, VOIDmode, operands[0],			      gen_rtx (IF_THEN_ELSE, VOIDmode,				       gen_rtx (compare_code, DImode,						sparc_compare_op0, const0_rtx),				       const1_rtx,				       operands[0])));	  return 1;	}      emit_insn (gen_rtx (SET, VOIDmode, operands[0], const0_rtx));      if (GET_MODE (sparc_compare_op0) != DImode)	{	  temp = gen_reg_rtx (DImode);	  convert_move (temp, sparc_compare_op0, 0);	}      else	{	  temp = sparc_compare_op0;	}      emit_insn (gen_rtx (SET, VOIDmode, operands[0],			  gen_rtx (IF_THEN_ELSE, VOIDmode,				   gen_rtx (compare_code, DImode,					    temp, const0_rtx),				   const1_rtx,				   operands[0])));      return 1;    }  else    {      operands[1] = gen_compare_reg (compare_code,				     sparc_compare_op0, sparc_compare_op1);      switch (GET_MODE (operands[1]))	{	  case CCmode :

⌨️ 快捷键说明

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