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

📄 arm.c

📁 GCC编译器源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
		   ? 0 : 4));      return 8;    case MULT:      /* There is no point basing this on the tuning, since it is always the	 fast variant if it exists at all */      if (arm_fast_multiply && mode == DImode	  && (GET_CODE (XEXP (x, 0)) == GET_CODE (XEXP (x, 1)))	  && (GET_CODE (XEXP (x, 0)) == ZERO_EXTEND	      || GET_CODE (XEXP (x, 0)) == SIGN_EXTEND))	return 8;      if (GET_MODE_CLASS (mode) == MODE_FLOAT	  || mode == DImode)	return 30;      if (GET_CODE (XEXP (x, 1)) == CONST_INT)	{	  unsigned HOST_WIDE_INT i = (INTVAL (XEXP (x, 1))				      & (unsigned HOST_WIDE_INT) 0xffffffff);	  int add_cost = const_ok_for_arm (i) ? 4 : 8;	  int j;	  /* Tune as appropriate */ 	  int booth_unit_size = ((tune_flags & FL_FAST_MULT) ? 8 : 2);	  for (j = 0; i && j < 32; j += booth_unit_size)	    {	      i >>= booth_unit_size;	      add_cost += 2;	    }	  return add_cost;	}      return (((tune_flags & FL_FAST_MULT) ? 8 : 30)	      + (REG_OR_SUBREG_REG (XEXP (x, 0)) ? 0 : 4)	      + (REG_OR_SUBREG_REG (XEXP (x, 1)) ? 0 : 4));    case TRUNCATE:      if (arm_fast_multiply && mode == SImode	  && GET_CODE (XEXP (x, 0)) == LSHIFTRT	  && GET_CODE (XEXP (XEXP (x, 0), 0)) == MULT	  && (GET_CODE (XEXP (XEXP (XEXP (x, 0), 0), 0))	      == GET_CODE (XEXP (XEXP (XEXP (x, 0), 0), 1)))	  && (GET_CODE (XEXP (XEXP (XEXP (x, 0), 0), 0)) == ZERO_EXTEND	      || GET_CODE (XEXP (XEXP (XEXP (x, 0), 0), 0)) == SIGN_EXTEND))	return 8;      return 99;    case NEG:      if (GET_MODE_CLASS (mode) == MODE_FLOAT)	return 4 + (REG_OR_SUBREG_REG (XEXP (x, 0)) ? 0 : 6);      /* Fall through */    case NOT:      if (mode == DImode)	return 4 + (REG_OR_SUBREG_REG (XEXP (x, 0)) ? 0 : 4);      return 1 + (REG_OR_SUBREG_REG (XEXP (x, 0)) ? 0 : 4);    case IF_THEN_ELSE:      if (GET_CODE (XEXP (x, 1)) == PC || GET_CODE (XEXP (x, 2)) == PC)	return 14;      return 2;    case COMPARE:      return 1;    case ABS:      return 4 + (mode == DImode ? 4 : 0);    case SIGN_EXTEND:      if (GET_MODE (XEXP (x, 0)) == QImode)	return (4 + (mode == DImode ? 4 : 0)		+ (GET_CODE (XEXP (x, 0)) == MEM ? 10 : 0));      /* Fall through */    case ZERO_EXTEND:      switch (GET_MODE (XEXP (x, 0)))	{	case QImode:	  return (1 + (mode == DImode ? 4 : 0)		  + (GET_CODE (XEXP (x, 0)) == MEM ? 10 : 0));	case HImode:	  return (4 + (mode == DImode ? 4 : 0)		  + (GET_CODE (XEXP (x, 0)) == MEM ? 10 : 0));	case SImode:	  return (1 + (GET_CODE (XEXP (x, 0)) == MEM ? 10 : 0));	}      abort ();    default:      return 99;    }}intarm_adjust_cost (insn, link, dep, cost)     rtx insn;     rtx link;     rtx dep;     int cost;{  rtx i_pat, d_pat;  if ((i_pat = single_set (insn)) != NULL      && GET_CODE (SET_SRC (i_pat)) == MEM      && (d_pat = single_set (dep)) != NULL      && GET_CODE (SET_DEST (d_pat)) == MEM)    {      /* This is a load after a store, there is no conflict if the load reads	 from a cached area.  Assume that loads from the stack, and from the	 constant pool are cached, and that others will miss.  This is a 	 hack. */      /*       debug_rtx (insn);      debug_rtx (dep);      debug_rtx (link);      fprintf (stderr, "costs %d\n", cost); */      if (CONSTANT_POOL_ADDRESS_P (XEXP (SET_SRC (i_pat), 0))	  || reg_mentioned_p (stack_pointer_rtx, XEXP (SET_SRC (i_pat), 0))	  || reg_mentioned_p (frame_pointer_rtx, XEXP (SET_SRC (i_pat), 0))	  || reg_mentioned_p (hard_frame_pointer_rtx, 			      XEXP (SET_SRC (i_pat), 0)))	{/* 	  fprintf (stderr, "***** Now 1\n"); */	  return 1;	}    }  return cost;}/* This code has been fixed for cross compilation. */static int fpa_consts_inited = 0;char *strings_fpa[8] = {  "0",   "1",   "2",   "3",  "4",   "5",   "0.5", "10"};static REAL_VALUE_TYPE values_fpa[8];static voidinit_fpa_table (){  int i;  REAL_VALUE_TYPE r;  for (i = 0; i < 8; i++)    {      r = REAL_VALUE_ATOF (strings_fpa[i], DFmode);      values_fpa[i] = r;    }  fpa_consts_inited = 1;}/* Return TRUE if rtx X is a valid immediate FPU constant. */intconst_double_rtx_ok_for_fpu (x)     rtx x;{  REAL_VALUE_TYPE r;  int i;    if (!fpa_consts_inited)    init_fpa_table ();    REAL_VALUE_FROM_CONST_DOUBLE (r, x);  if (REAL_VALUE_MINUS_ZERO (r))    return 0;  for (i = 0; i < 8; i++)    if (REAL_VALUES_EQUAL (r, values_fpa[i]))      return 1;  return 0;}/* Return TRUE if rtx X is a valid immediate FPU constant. */intneg_const_double_rtx_ok_for_fpu (x)     rtx x;{  REAL_VALUE_TYPE r;  int i;    if (!fpa_consts_inited)    init_fpa_table ();    REAL_VALUE_FROM_CONST_DOUBLE (r, x);  r = REAL_VALUE_NEGATE (r);  if (REAL_VALUE_MINUS_ZERO (r))    return 0;  for (i = 0; i < 8; i++)    if (REAL_VALUES_EQUAL (r, values_fpa[i]))      return 1;  return 0;}/* Predicates for `match_operand' and `match_operator'.  *//* s_register_operand is the same as register_operand, but it doesn't accept   (SUBREG (MEM)...).   This function exists because at the time it was put in it led to better   code.  SUBREG(MEM) always needs a reload in the places where   s_register_operand is used, and this seemed to lead to excessive   reloading.  */ints_register_operand (op, mode)     register rtx op;     enum machine_mode mode;{  if (GET_MODE (op) != mode && mode != VOIDmode)    return 0;  if (GET_CODE (op) == SUBREG)    op = SUBREG_REG (op);  /* We don't consider registers whose class is NO_REGS     to be a register operand.  */  return (GET_CODE (op) == REG	  && (REGNO (op) >= FIRST_PSEUDO_REGISTER	      || REGNO_REG_CLASS (REGNO (op)) != NO_REGS));}/* Only accept reg, subreg(reg), const_int.  */intreg_or_int_operand (op, mode)     register rtx op;     enum machine_mode mode;{  if (GET_CODE (op) == CONST_INT)    return 1;  if (GET_MODE (op) != mode && mode != VOIDmode)    return 0;  if (GET_CODE (op) == SUBREG)    op = SUBREG_REG (op);  /* We don't consider registers whose class is NO_REGS     to be a register operand.  */  return (GET_CODE (op) == REG	  && (REGNO (op) >= FIRST_PSEUDO_REGISTER	      || REGNO_REG_CLASS (REGNO (op)) != NO_REGS));}/* Return 1 if OP is an item in memory, given that we are in reload.  */intreload_memory_operand (op, mode)     rtx op;     enum machine_mode mode;{  int regno = true_regnum (op);  return (! CONSTANT_P (op)	  && (regno == -1	      || (GET_CODE (op) == REG		  && REGNO (op) >= FIRST_PSEUDO_REGISTER)));}/* Return TRUE for valid operands for the rhs of an ARM instruction.  */intarm_rhs_operand (op, mode)     rtx op;     enum machine_mode mode;{  return (s_register_operand (op, mode)	  || (GET_CODE (op) == CONST_INT && const_ok_for_arm (INTVAL (op))));}/* Return TRUE for valid operands for the rhs of an ARM instruction, or a load. */intarm_rhsm_operand (op, mode)     rtx op;     enum machine_mode mode;{  return (s_register_operand (op, mode)	  || (GET_CODE (op) == CONST_INT && const_ok_for_arm (INTVAL (op)))	  || memory_operand (op, mode));}/* Return TRUE for valid operands for the rhs of an ARM instruction, or if a   constant that is valid when negated.  */intarm_add_operand (op, mode)     rtx op;     enum machine_mode mode;{  return (s_register_operand (op, mode)	  || (GET_CODE (op) == CONST_INT	      && (const_ok_for_arm (INTVAL (op))		  || const_ok_for_arm (-INTVAL (op)))));}intarm_not_operand (op, mode)     rtx op;     enum machine_mode mode;{  return (s_register_operand (op, mode)	  || (GET_CODE (op) == CONST_INT	      && (const_ok_for_arm (INTVAL (op))		  || const_ok_for_arm (~INTVAL (op)))));}/* Return TRUE if the operand is a memory reference which contains an   offsettable address.  */intoffsettable_memory_operand (op, mode)     register rtx op;     enum machine_mode mode;{  if (mode == VOIDmode)    mode = GET_MODE (op);  return (mode == GET_MODE (op)	  && GET_CODE (op) == MEM	  && offsettable_address_p (reload_completed | reload_in_progress,				    mode, XEXP (op, 0)));}/* Return TRUE if the operand is a memory reference which is, or can be   made word aligned by adjusting the offset.  */intalignable_memory_operand (op, mode)     register rtx op;     enum machine_mode mode;{  rtx reg;  if (mode == VOIDmode)    mode = GET_MODE (op);  if (mode != GET_MODE (op) || GET_CODE (op) != MEM)    return 0;  op = XEXP (op, 0);  return ((GET_CODE (reg = op) == REG	   || (GET_CODE (op) == SUBREG	       && GET_CODE (reg = SUBREG_REG (op)) == REG)	   || (GET_CODE (op) == PLUS	       && GET_CODE (XEXP (op, 1)) == CONST_INT	       && (GET_CODE (reg = XEXP (op, 0)) == REG		   || (GET_CODE (XEXP (op, 0)) == SUBREG		       && GET_CODE (reg = SUBREG_REG (XEXP (op, 0))) == REG))))	  && REGNO_POINTER_ALIGN (REGNO (reg)) >= 4);}/* Similar to s_register_operand, but does not allow hard integer    registers.  */intf_register_operand (op, mode)     register rtx op;     enum machine_mode mode;{  if (GET_MODE (op) != mode && mode != VOIDmode)    return 0;  if (GET_CODE (op) == SUBREG)    op = SUBREG_REG (op);  /* We don't consider registers whose class is NO_REGS     to be a register operand.  */  return (GET_CODE (op) == REG	  && (REGNO (op) >= FIRST_PSEUDO_REGISTER	      || REGNO_REG_CLASS (REGNO (op)) == FPU_REGS));}/* Return TRUE for valid operands for the rhs of an FPU instruction.  */intfpu_rhs_operand (op, mode)     rtx op;     enum machine_mode mode;{  if (s_register_operand (op, mode))    return TRUE;  else if (GET_CODE (op) == CONST_DOUBLE)    return (const_double_rtx_ok_for_fpu (op));  return FALSE;}intfpu_add_operand (op, mode)     rtx op;     enum machine_mode mode;{  if (s_register_operand (op, mode))    return TRUE;  else if (GET_CODE (op) == CONST_DOUBLE)    return (const_double_rtx_ok_for_fpu (op) 	    || neg_const_double_rtx_ok_for_fpu (op));  return FALSE;}/* Return nonzero if OP is a constant power of two.  */intpower_of_two_operand (op, mode)     rtx op;     enum machine_mode mode;{  if (GET_CODE (op) == CONST_INT)    {      HOST_WIDE_INT value = INTVAL(op);      return value != 0  &&  (value & (value - 1)) == 0;    }  return FALSE;}/* Return TRUE for a valid operand of a DImode operation.   Either: REG, CONST_DOUBLE or MEM(DImode_address).   Note that this disallows MEM(REG+REG), but allows   MEM(PRE/POST_INC/DEC(REG)).  */intdi_operand (op, mode)     rtx op;     enum machine_mode mode;{  if (s_register_operand (op, mode))    return TRUE;  switch (GET_CODE (op))    {    case CONST_DOUBLE:    case CONST_INT:      return TRUE;    case MEM:      return memory_address_p (DImode, XEXP (op, 0));    default:      return FALSE;    }}/* Return TRUE for a valid operand of a DFmode operation when -msoft-float.   Either: REG, CONST_DOUBLE or MEM(DImode_address).   Note that this disallows MEM(REG+REG), but allows   MEM(PRE/POST_INC/DEC(REG)).  */intsoft_df_operand (op, mode)     rtx op;     enum machine_mode mode;{  if (s_register_operand (op, mode))    return TRUE;  switch (GET_CODE (op))    {    case CONST_DOUBLE:      return TRUE;    case MEM:      return memory_address_p (DFmode, XEXP (op, 0));    default:      return FALSE;    }}/* Return TRUE for valid index operands. */intindex_operand (op, mode)     rtx op;     enum machine_mode mode;{

⌨️ 快捷键说明

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