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

📄 iq2000.c

📁 Mac OS X 10.4.9 for x86 Source Code gcc 实现源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
      return SYMBOL_REF_FLAG (addr) ? 1 : 2;    case PLUS:      {	rtx plus0 = XEXP (addr, 0);	rtx plus1 = XEXP (addr, 1);	if (GET_CODE (plus0) != REG && GET_CODE (plus1) == REG)	  plus0 = XEXP (addr, 1), plus1 = XEXP (addr, 0);	if (GET_CODE (plus0) != REG)	  break;	switch (GET_CODE (plus1))	  {	  case CONST_INT:	    return SMALL_INT (plus1) ? 1 : 2;	  case CONST:	  case SYMBOL_REF:	  case LABEL_REF:	  case HIGH:	  case LO_SUM:	    return iq2000_address_cost (plus1) + 1;	  default:	    break;	  }      }    default:      break;    }  return 4;}/* Make normal rtx_code into something we can index from an array.  */static enum internal_testmap_test_to_internal_test (enum rtx_code test_code){  enum internal_test test = ITEST_MAX;  switch (test_code)    {    case EQ:  test = ITEST_EQ;  break;    case NE:  test = ITEST_NE;  break;    case GT:  test = ITEST_GT;  break;    case GE:  test = ITEST_GE;  break;    case LT:  test = ITEST_LT;  break;    case LE:  test = ITEST_LE;  break;    case GTU: test = ITEST_GTU; break;    case GEU: test = ITEST_GEU; break;    case LTU: test = ITEST_LTU; break;    case LEU: test = ITEST_LEU; break;    default:			break;    }  return test;}/* Generate the code to do a TEST_CODE comparison on two integer values CMP0   and CMP1.  P_INVERT is NULL or ptr if branch needs to reverse its test.   The return value RESULT is:   (reg:SI xx)		The pseudo register the comparison is in   0		       	No register, generate a simple branch.  */rtxgen_int_relational (enum rtx_code test_code, rtx result, rtx cmp0, rtx cmp1,		    int *p_invert){  struct cmp_info  {    enum rtx_code test_code;	/* Code to use in instruction (LT vs. LTU).  */    int const_low;		/* Low bound of constant we can accept.  */    int const_high;		/* High bound of constant we can accept.  */    int const_add;		/* Constant to add (convert LE -> LT).  */    int reverse_regs;		/* Reverse registers in test.  */    int invert_const;		/* != 0 if invert value if cmp1 is constant.  */    int invert_reg;		/* != 0 if invert value if cmp1 is register.  */    int unsignedp;		/* != 0 for unsigned comparisons.  */  };  static struct cmp_info info[ (int)ITEST_MAX ] =  {    { XOR,	 0,  65535,  0,	 0,  0,	 0, 0 },	/* EQ  */    { XOR,	 0,  65535,  0,	 0,  1,	 1, 0 },	/* NE  */    { LT,   -32769,  32766,  1,	 1,  1,	 0, 0 },	/* GT  */    { LT,   -32768,  32767,  0,	 0,  1,	 1, 0 },	/* GE  */    { LT,   -32768,  32767,  0,	 0,  0,	 0, 0 },	/* LT  */    { LT,   -32769,  32766,  1,	 1,  0,	 1, 0 },	/* LE  */    { LTU,  -32769,  32766,  1,	 1,  1,	 0, 1 },	/* GTU */    { LTU,  -32768,  32767,  0,	 0,  1,	 1, 1 },	/* GEU */    { LTU,  -32768,  32767,  0,	 0,  0,	 0, 1 },	/* LTU */    { LTU,  -32769,  32766,  1,	 1,  0,	 1, 1 },	/* LEU */  };  enum internal_test test;  enum machine_mode mode;  struct cmp_info *p_info;  int branch_p;  int eqne_p;  int invert;  rtx reg;  rtx reg2;  test = map_test_to_internal_test (test_code);  if (test == ITEST_MAX)    abort ();  p_info = &info[(int) test];  eqne_p = (p_info->test_code == XOR);  mode = GET_MODE (cmp0);  if (mode == VOIDmode)    mode = GET_MODE (cmp1);  /* Eliminate simple branches.  */  branch_p = (result == 0);  if (branch_p)    {      if (GET_CODE (cmp0) == REG || GET_CODE (cmp0) == SUBREG)	{	  /* Comparisons against zero are simple branches.  */	  if (GET_CODE (cmp1) == CONST_INT && INTVAL (cmp1) == 0)	    return 0;	  /* Test for beq/bne.  */	  if (eqne_p)	    return 0;	}      /* Allocate a pseudo to calculate the value in.  */      result = gen_reg_rtx (mode);    }  /* Make sure we can handle any constants given to us.  */  if (GET_CODE (cmp0) == CONST_INT)    cmp0 = force_reg (mode, cmp0);  if (GET_CODE (cmp1) == CONST_INT)    {      HOST_WIDE_INT value = INTVAL (cmp1);      if (value < p_info->const_low	  || value > p_info->const_high)	cmp1 = force_reg (mode, cmp1);    }  /* See if we need to invert the result.  */  invert = (GET_CODE (cmp1) == CONST_INT	    ? p_info->invert_const : p_info->invert_reg);  if (p_invert != (int *)0)    {      *p_invert = invert;      invert = 0;    }  /* Comparison to constants, may involve adding 1 to change a LT into LE.     Comparison between two registers, may involve switching operands.  */  if (GET_CODE (cmp1) == CONST_INT)    {      if (p_info->const_add != 0)	{	  HOST_WIDE_INT new = INTVAL (cmp1) + p_info->const_add;	  /* If modification of cmp1 caused overflow,	     we would get the wrong answer if we follow the usual path;	     thus, x > 0xffffffffU would turn into x > 0U.  */	  if ((p_info->unsignedp	       ? (unsigned HOST_WIDE_INT) new >	       (unsigned HOST_WIDE_INT) INTVAL (cmp1)	       : new > INTVAL (cmp1))	      != (p_info->const_add > 0))	    {	      /* This test is always true, but if INVERT is true then		 the result of the test needs to be inverted so 0 should		 be returned instead.  */	      emit_move_insn (result, invert ? const0_rtx : const_true_rtx);	      return result;	    }	  else	    cmp1 = GEN_INT (new);	}    }  else if (p_info->reverse_regs)    {      rtx temp = cmp0;      cmp0 = cmp1;      cmp1 = temp;    }  if (test == ITEST_NE && GET_CODE (cmp1) == CONST_INT && INTVAL (cmp1) == 0)    reg = cmp0;  else    {      reg = (invert || eqne_p) ? gen_reg_rtx (mode) : result;      convert_move (reg, gen_rtx_fmt_ee (p_info->test_code, mode, cmp0, cmp1), 0);    }  if (test == ITEST_NE)    {      convert_move (result, gen_rtx_GTU (mode, reg, const0_rtx), 0);      if (p_invert != NULL)	*p_invert = 0;      invert = 0;    }  else if (test == ITEST_EQ)    {      reg2 = invert ? gen_reg_rtx (mode) : result;      convert_move (reg2, gen_rtx_LTU (mode, reg, const1_rtx), 0);      reg = reg2;    }  if (invert)    {      rtx one;      one = const1_rtx;      convert_move (result, gen_rtx_XOR (mode, reg, one), 0);    }  return result;}/* Emit the common code for doing conditional branches.   operand[0] is the label to jump to.   The comparison operands are saved away by cmp{si,di,sf,df}.  */voidgen_conditional_branch (rtx operands[], enum rtx_code test_code){  enum cmp_type type = branch_type;  rtx cmp0 = branch_cmp[0];  rtx cmp1 = branch_cmp[1];  enum machine_mode mode;  rtx reg;  int invert;  rtx label1, label2;  switch (type)    {    case CMP_SI:    case CMP_DI:      mode = type == CMP_SI ? SImode : DImode;      invert = 0;      reg = gen_int_relational (test_code, NULL_RTX, cmp0, cmp1, &invert);      if (reg)	{	  cmp0 = reg;	  cmp1 = const0_rtx;	  test_code = NE;	}      else if (GET_CODE (cmp1) == CONST_INT && INTVAL (cmp1) != 0)	/* We don't want to build a comparison against a nonzero	   constant.  */	cmp1 = force_reg (mode, cmp1);      break;    case CMP_SF:    case CMP_DF:      reg = gen_reg_rtx (CCmode);      /* For cmp0 != cmp1, build cmp0 == cmp1, and test for result == 0.  */      emit_insn (gen_rtx_SET (VOIDmode, reg,			      gen_rtx_fmt_ee (test_code == NE ? EQ : test_code,					      CCmode, cmp0, cmp1)));      test_code = test_code == NE ? EQ : NE;      mode = CCmode;      cmp0 = reg;      cmp1 = const0_rtx;      invert = 0;      break;    default:      abort_with_insn (gen_rtx_fmt_ee (test_code, VOIDmode, cmp0, cmp1),		       "bad test");    }  /* Generate the branch.  */  label1 = gen_rtx_LABEL_REF (VOIDmode, operands[0]);  label2 = pc_rtx;  if (invert)    {      label2 = label1;      label1 = pc_rtx;    }  emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx,			       gen_rtx_IF_THEN_ELSE (VOIDmode,						     gen_rtx_fmt_ee (test_code,								     mode,								     cmp0, cmp1),						     label1, label2)));}/* Initialize CUM for a function FNTYPE.  */voidinit_cumulative_args (CUMULATIVE_ARGS *cum, tree fntype,		      rtx libname ATTRIBUTE_UNUSED){  static CUMULATIVE_ARGS zero_cum;  tree param;  tree next_param;  if (TARGET_DEBUG_D_MODE)    {      fprintf (stderr,	       "\ninit_cumulative_args, fntype = 0x%.8lx", (long) fntype);      if (!fntype)	fputc ('\n', stderr);      else	{	  tree ret_type = TREE_TYPE (fntype);	  fprintf (stderr, ", fntype code = %s, ret code = %s\n",		   tree_code_name[(int)TREE_CODE (fntype)],		   tree_code_name[(int)TREE_CODE (ret_type)]);	}    }  *cum = zero_cum;  /* Determine if this function has variable arguments.  This is     indicated by the last argument being 'void_type_mode' if there     are no variable arguments.  The standard IQ2000 calling sequence     passes all arguments in the general purpose registers in this case.  */  for (param = fntype ? TYPE_ARG_TYPES (fntype) : 0;       param != 0; param = next_param)    {      next_param = TREE_CHAIN (param);      if (next_param == 0 && TREE_VALUE (param) != void_type_node)	cum->gp_reg_found = 1;    }}/* Advance the argument of type TYPE and mode MODE to the next argument   position in CUM.  */voidfunction_arg_advance (CUMULATIVE_ARGS *cum, enum machine_mode mode, tree type,		      int named){  if (TARGET_DEBUG_D_MODE)    {      fprintf (stderr,	       "function_adv({gp reg found = %d, arg # = %2d, words = %2d}, %4s, ",	       cum->gp_reg_found, cum->arg_number, cum->arg_words,	       GET_MODE_NAME (mode));      fprintf (stderr, HOST_PTR_PRINTF, (const PTR) type);      fprintf (stderr, ", %d )\n\n", named);    }  cum->arg_number++;  switch (mode)    {    case VOIDmode:      break;    default:      if (GET_MODE_CLASS (mode) != MODE_COMPLEX_INT	  && GET_MODE_CLASS (mode) != MODE_COMPLEX_FLOAT)	abort ();      cum->gp_reg_found = 1;      cum->arg_words += ((GET_MODE_SIZE (mode) + UNITS_PER_WORD - 1)			 / UNITS_PER_WORD);      break;    case BLKmode:      cum->gp_reg_found = 1;      cum->arg_words += ((int_size_in_bytes (type) + UNITS_PER_WORD - 1)			 / UNITS_PER_WORD);      break;    case SFmode:      cum->arg_words ++;      if (! cum->gp_reg_found && cum->arg_number <= 2)	cum->fp_code += 1 << ((cum->arg_number - 1) * 2);      break;    case DFmode:      cum->arg_words += 2;      if (! cum->gp_reg_found && cum->arg_number <= 2)	cum->fp_code += 2 << ((cum->arg_number - 1) * 2);      break;    case DImode:      cum->gp_reg_found = 1;      cum->arg_words += 2;      break;    case QImode:    case HImode:    case SImode:      cum->gp_reg_found = 1;      cum->arg_words ++;      break;    }}/* Return an RTL expression containing the register for the given mode MODE   and type TYPE in CUM, or 0 if the argument is to be passed on the stack.  */struct rtx_def *function_arg (CUMULATIVE_ARGS *cum, enum machine_mode mode, tree type,	      int named){  rtx ret;  int regbase = -1;  int bias = 0;  unsigned int *arg_words = &cum->arg_words;  int struct_p = (type != 0		  && (TREE_CODE (type) == RECORD_TYPE		      || TREE_CODE (type) == UNION_TYPE		      || TREE_CODE (type) == QUAL_UNION_TYPE));  if (TARGET_DEBUG_D_MODE)    {      fprintf (stderr,	       "function_arg( {gp reg found = %d, arg # = %2d, words = %2d}, %4s, ",	       cum->gp_reg_found, cum->arg_number, cum->arg_words,	       GET_MODE_NAME (mode));      fprintf (stderr, HOST_PTR_PRINTF, (const PTR) type);      fprintf (stderr, ", %d ) = ", named);    }  cum->last_arg_fp = 0;  switch (mode)    {    case SFmode:      regbase = GP_ARG_FIRST;      break;    case DFmode:      cum->arg_words += cum->arg_words & 1;      regbase = GP_ARG_FIRST;      break;    default:      if (GET_MODE_CLASS (mode) != MODE_COMPLEX_INT	  && GET_MODE_CLASS (mode) != MODE_COMPLEX_FLOAT)	abort ();      /* Drops through.  */    case BLKmode:      if (type != NULL_TREE && TYPE_ALIGN (type) > (unsigned) BITS_PER_WORD)	cum->arg_words += (cum->arg_words & 1);      regbase = GP_ARG_FIRST;      break;    case VOIDmode:    case QImode:    case HImode:    case SImode:      regbase = GP_ARG_FIRST;      break;    case DImode:      cum->arg_words += (cum->arg_words & 1);      regbase = GP_ARG_FIRST;    }  if (*arg_words >= (unsigned) MAX_ARGS_IN_REGISTERS)    {      if (TARGET_DEBUG_D_MODE)	fprintf (stderr, "<stack>%s\n", struct_p ? ", [struct]" : "");      ret = 0;    }  else    {      if (regbase == -1)	abort ();      if (! type || TREE_CODE (type) != RECORD_TYPE	  || ! named  || ! TYPE_SIZE_UNIT (type)

⌨️ 快捷键说明

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