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

📄 bfin.c

📁 Mac OS X 10.4.9 for x86 Source Code gcc 实现源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
	}      if ((val & 0xFFFF0000) == 0xFFFF0000)	{	  emit_insn (gen_movsi (operands[0], constm1_rtx));	  emit_insn (gen_movsi_low (operands[0], operands[0], operands[1]));	  return 1;	}    }  /* Need DREGs for the remaining case.  */  if (regno > REG_R7)    return 0;  if (optimize_size      && num_compl_zero && CONST_7BIT_IMM_P (shifted_compl))    {      /* If optimizing for size, generate a sequence that has more instructions	 but is shorter.  */      emit_insn (gen_movsi (operands[0], GEN_INT (shifted_compl)));      emit_insn (gen_ashlsi3 (operands[0], operands[0],			      GEN_INT (num_compl_zero)));      emit_insn (gen_one_cmplsi2 (operands[0], operands[0]));      return 1;    }  return 0;}/* Return true if the legitimate memory address for a memory operand of mode   MODE.  Return false if not.  */static boolbfin_valid_add (enum machine_mode mode, HOST_WIDE_INT value){  unsigned HOST_WIDE_INT v = value > 0 ? value : -value;  int sz = GET_MODE_SIZE (mode);  int shift = sz == 1 ? 0 : sz == 2 ? 1 : 2;  /* The usual offsettable_memref machinery doesn't work so well for this     port, so we deal with the problem here.  */  unsigned HOST_WIDE_INT mask = sz == 8 ? 0x7ffe : 0x7fff;  return (v & ~(mask << shift)) == 0;}static boolbfin_valid_reg_p (unsigned int regno, int strict){  return ((strict && REGNO_OK_FOR_BASE_STRICT_P (regno))	  || (!strict && REGNO_OK_FOR_BASE_NONSTRICT_P (regno)));}boolbfin_legitimate_address_p (enum machine_mode mode, rtx x, int strict){  switch (GET_CODE (x)) {  case REG:    if (bfin_valid_reg_p (REGNO (x), strict))      return true;    break;  case PLUS:    if (REG_P (XEXP (x, 0))	&& bfin_valid_reg_p (REGNO (XEXP (x, 0)), strict)	&& (GET_CODE (XEXP (x, 1)) == UNSPEC	    || (GET_CODE (XEXP (x, 1)) == CONST_INT		&& bfin_valid_add (mode, INTVAL (XEXP (x, 1))))))      return true;    break;  case POST_INC:  case POST_DEC:    if (LEGITIMATE_MODE_FOR_AUTOINC_P (mode)	&& REG_P (XEXP (x, 0))	&& bfin_valid_reg_p (REGNO (XEXP (x, 0)), strict))      return true;  case PRE_DEC:    if (LEGITIMATE_MODE_FOR_AUTOINC_P (mode)	&& XEXP (x, 0) == stack_pointer_rtx	&& REG_P (XEXP (x, 0))	&& bfin_valid_reg_p (REGNO (XEXP (x, 0)), strict))      return true;    break;  default:    break;  }  return false;}static boolbfin_rtx_costs (rtx x, int code, int outer_code, int *total){  int cost2 = COSTS_N_INSNS (1);  switch (code)    {    case CONST_INT:      if (outer_code == SET || outer_code == PLUS)        *total = CONST_7BIT_IMM_P (INTVAL (x)) ? 0 : cost2;      else if (outer_code == AND)        *total = log2constp (~INTVAL (x)) ? 0 : cost2;      else if (outer_code == LE || outer_code == LT || outer_code == EQ)        *total = (INTVAL (x) >= -4 && INTVAL (x) <= 3) ? 0 : cost2;      else if (outer_code == LEU || outer_code == LTU)        *total = (INTVAL (x) >= 0 && INTVAL (x) <= 7) ? 0 : cost2;      else if (outer_code == MULT)        *total = (INTVAL (x) == 2 || INTVAL (x) == 4) ? 0 : cost2;      else if (outer_code == ASHIFT && (INTVAL (x) == 1 || INTVAL (x) == 2))        *total = 0;      else if (outer_code == ASHIFT || outer_code == ASHIFTRT	       || outer_code == LSHIFTRT)        *total = (INTVAL (x) >= 0 && INTVAL (x) <= 31) ? 0 : cost2;      else if (outer_code == IOR || outer_code == XOR)        *total = (INTVAL (x) & (INTVAL (x) - 1)) == 0 ? 0 : cost2;      else	*total = cost2;      return true;    case CONST:    case LABEL_REF:    case SYMBOL_REF:    case CONST_DOUBLE:      *total = COSTS_N_INSNS (2);      return true;    case PLUS:      if (GET_MODE (x) == Pmode)	{	  if (GET_CODE (XEXP (x, 0)) == MULT	      && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT)	    {	      HOST_WIDE_INT val = INTVAL (XEXP (XEXP (x, 0), 1));	      if (val == 2 || val == 4)		{		  *total = cost2;		  *total += rtx_cost (XEXP (XEXP (x, 0), 0), outer_code);		  *total += rtx_cost (XEXP (x, 1), outer_code);		  return true;		}	    }	}      /* fall through */    case MINUS:    case ASHIFT:     case ASHIFTRT:    case LSHIFTRT:      if (GET_MODE (x) == DImode)	*total = 6 * cost2;      return false;	      case AND:    case IOR:    case XOR:      if (GET_MODE (x) == DImode)	*total = 2 * cost2;      return false;    case MULT:      if (GET_MODE_SIZE (GET_MODE (x)) <= UNITS_PER_WORD)	*total = COSTS_N_INSNS (3);      return false;    default:      return false;    }}static voidbfin_internal_label (FILE *stream, const char *prefix, unsigned long num){  fprintf (stream, "%s%s$%ld:\n", LOCAL_LABEL_PREFIX, prefix, num);}/* Used for communication between {push,pop}_multiple_operation (which   we use not only as a predicate) and the corresponding output functions.  */static int first_preg_to_save, first_dreg_to_save;intpush_multiple_operation (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED){  int lastdreg = 8, lastpreg = 6;  int i, group;  first_preg_to_save = lastpreg;  first_dreg_to_save = lastdreg;  for (i = 1, group = 0; i < XVECLEN (op, 0) - 1; i++)    {      rtx t = XVECEXP (op, 0, i);      rtx src, dest;      int regno;      if (GET_CODE (t) != SET)	return 0;      src = SET_SRC (t);      dest = SET_DEST (t);      if (GET_CODE (dest) != MEM || ! REG_P (src))	return 0;      dest = XEXP (dest, 0);      if (GET_CODE (dest) != PLUS	  || ! REG_P (XEXP (dest, 0))	  || REGNO (XEXP (dest, 0)) != REG_SP	  || GET_CODE (XEXP (dest, 1)) != CONST_INT	  || INTVAL (XEXP (dest, 1)) != -i * 4)	return 0;      regno = REGNO (src);      if (group == 0)	{	  if (D_REGNO_P (regno))	    {	      group = 1;	      first_dreg_to_save = lastdreg = regno - REG_R0;	    }	  else if (regno >= REG_P0 && regno <= REG_P7)	    {	      group = 2;	      first_preg_to_save = lastpreg = regno - REG_P0;	    }	  else	    return 0;	  continue;	}      if (group == 1)	{	  if (regno >= REG_P0 && regno <= REG_P7)	    {	      group = 2;	      first_preg_to_save = lastpreg = regno - REG_P0;	    }	  else if (regno != REG_R0 + lastdreg + 1)	    return 0;	  else	    lastdreg++;	}      else if (group == 2)	{	  if (regno != REG_P0 + lastpreg + 1)	    return 0;	  lastpreg++;	}    }  return 1;}intpop_multiple_operation (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED){  int lastdreg = 8, lastpreg = 6;  int i, group;  for (i = 1, group = 0; i < XVECLEN (op, 0); i++)    {      rtx t = XVECEXP (op, 0, i);      rtx src, dest;      int regno;      if (GET_CODE (t) != SET)	return 0;      src = SET_SRC (t);      dest = SET_DEST (t);      if (GET_CODE (src) != MEM || ! REG_P (dest))	return 0;      src = XEXP (src, 0);      if (i == 1)	{	  if (! REG_P (src) || REGNO (src) != REG_SP)	    return 0;	}      else if (GET_CODE (src) != PLUS	       || ! REG_P (XEXP (src, 0))	       || REGNO (XEXP (src, 0)) != REG_SP	       || GET_CODE (XEXP (src, 1)) != CONST_INT	       || INTVAL (XEXP (src, 1)) != (i - 1) * 4)	return 0;      regno = REGNO (dest);      if (group == 0)	{	  if (regno == REG_R7)	    {	      group = 1;	      lastdreg = 7;	    }	  else if (regno != REG_P0 + lastpreg - 1)	    return 0;	  else	    lastpreg--;	}      else if (group == 1)	{	  if (regno != REG_R0 + lastdreg - 1)	    return 0;	  else	    lastdreg--;	}    }  first_dreg_to_save = lastdreg;  first_preg_to_save = lastpreg;  return 1;}/* Emit assembly code for one multi-register push described by INSN, with   operands in OPERANDS.  */voidoutput_push_multiple (rtx insn, rtx *operands){  char buf[80];  /* Validate the insn again, and compute first_[dp]reg_to_save. */  if (! push_multiple_operation (PATTERN (insn), VOIDmode))    abort ();  if (first_dreg_to_save == 8)    sprintf (buf, "[--sp] = ( p5:%d );\n", first_preg_to_save);  else if (first_preg_to_save == 6)    sprintf (buf, "[--sp] = ( r7:%d );\n", first_dreg_to_save);  else    sprintf (buf, "[--sp] = ( r7:%d, p5:%d );\n", first_dreg_to_save, first_preg_to_save);  output_asm_insn (buf, operands);}/* Emit assembly code for one multi-register pop described by INSN, with   operands in OPERANDS.  */voidoutput_pop_multiple (rtx insn, rtx *operands){  char buf[80];  /* Validate the insn again, and compute first_[dp]reg_to_save. */  if (! pop_multiple_operation (PATTERN (insn), VOIDmode))    abort ();  if (first_dreg_to_save == 8)    sprintf (buf, "( p5:%d ) = [sp++];\n", first_preg_to_save);  else if (first_preg_to_save == 6)    sprintf (buf, "( r7:%d ) = [sp++];\n", first_dreg_to_save);  else    sprintf (buf, "( r7:%d, p5:%d ) = [sp++];\n", first_dreg_to_save, first_preg_to_save);  output_asm_insn (buf, operands);}/* Adjust DST and SRC by OFFSET bytes, and generate one move in mode MODE.  */static voidsingle_move_for_strmov (rtx dst, rtx src, enum machine_mode mode, HOST_WIDE_INT offset){  rtx scratch = gen_reg_rtx (mode);  rtx srcmem, dstmem;  srcmem = adjust_address_nv (src, mode, offset);  dstmem = adjust_address_nv (dst, mode, offset);  emit_move_insn (scratch, srcmem);  emit_move_insn (dstmem, scratch);}/* Expand a string move operation of COUNT_EXP bytes from SRC to DST, with   alignment ALIGN_EXP.  Return true if successful, false if we should fall   back on a different method.  */boolbfin_expand_strmov (rtx dst, rtx src, rtx count_exp, rtx align_exp){  rtx srcreg, destreg, countreg;  HOST_WIDE_INT align = 0;  unsigned HOST_WIDE_INT count = 0;  if (GET_CODE (align_exp) == CONST_INT)    align = INTVAL (align_exp);  if (GET_CODE (count_exp) == CONST_INT)    {      count = INTVAL (count_exp);#if 0      if (!TARGET_INLINE_ALL_STRINGOPS && count > 64)	return false;#endif    }  /* If optimizing for size, only do single copies inline.  */  if (optimize_size)    {      if (count == 2 && align < 2)	return false;      if (count == 4 && align < 4)	return false;      if (count != 1 && count != 2 && count != 4)	return false;    }  if (align < 2 && count != 1)    return false;  destreg = copy_to_mode_reg (Pmode, XEXP (dst, 0));  if (destreg != XEXP (dst, 0))    dst = replace_equiv_address_nv (dst, destreg);  srcreg = copy_to_mode_reg (Pmode, XEXP (src, 0));  if (srcreg != XEXP (src, 0))    src = replace_equiv_address_nv (src, srcreg);  if (count != 0 && align >= 2)    {      unsigned HOST_WIDE_INT offset = 0;      if (align >= 4)	{	  if ((count & ~3) == 4)	    {	      single_move_for_strmov (dst, src, SImode, offset);	      offset = 4;	    }	  else if (count & ~3)	    {	      HOST_WIDE_INT new_count = ((count >> 2) & 0x3fffffff) - 1;	      countreg = copy_to_mode_reg (Pmode, GEN_INT (new_count));	      emit_insn (gen_rep_movsi (destreg, srcreg, countreg, destreg, srcreg));	    }	}      else	{	  if ((count & ~1) == 2)	    {	      single_move_for_strmov (dst, src, HImode, offset);	      offset = 2;	    }	  else if (count & ~1)	    {	      HOST_WIDE_INT new_count = ((count >> 1) & 0x7fffffff) - 1;	      countreg = copy_to_mode_reg (Pmode, GEN_INT (new_count));	      emit_insn (gen_rep_movhi (destreg, srcreg, countreg, destreg, srcreg));	    }	}      if (count & 2)	{	  single_move_for_strmov (dst, src, HImode, offset);	  offset += 2;	}      if (count & 1)	{	  single_move_for_strmov (dst, src, QImode, offset);	}      return true;    }  return false;}static intbfin_adjust_cost (rtx insn, rtx link, rtx dep_insn, int cost){  enum attr_type insn_type, dep_insn_type;  int dep_insn_code_number;  /* Anti and output dependencies have zero cost.  */  if (REG_NOTE_KIND (link) != 0)    return 0;  dep_insn_code_number = recog_memoized (dep_insn);  /* If we can't recognize the insns, we can't really do anything.  */  if (dep_insn_code_number < 0 || recog_memoized (insn) < 0)    return cost;  insn_type = get_attr_type (insn);  dep_insn_type = get_attr_type (dep_insn);  if (dep_insn_type == TYPE_MOVE || dep_insn_type == TYPE_MCLD)    {      rtx pat = PATTERN (dep_insn);      rtx dest = SET_DEST (pat);      rtx src = SET_SRC (pat);      if (! ADDRESS_REGNO_P (REGNO (dest)) || ! D_REGNO_P (REGNO (src)))	return cost;      return cost + (dep_insn_type == TYPE_MOVE ? 4 : 3);    }  return cost;}/* We use the machine specific reorg pass for emitting CSYNC instructions   after conditional branches as needed.   The Blackfin is unusual in that a code sequence like     if cc jump label     r0 = (p0)   may speculatively perform the load even if the condition isn't true.  This   happ

⌨️ 快捷键说明

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