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

📄 bfin.c

📁 linux下编程用 编译软件
💻 C
📖 第 1 页 / 共 5 页
字号:
  /* If we have a BImode input, then we already have a compare result, and     do not need to emit another comparison.  */  if (GET_MODE (op0) == BImode)    {      gcc_assert ((code == NE || code == EQ) && op1 == const0_rtx);      tem = op0, code2 = code;    }  else    {      switch (code) {	/* bfin has these conditions */      case EQ:      case LT:      case LE:      case LEU:      case LTU:	code1 = code;	code2 = NE;	break;      default:	code1 = reverse_condition (code);	code2 = EQ;	break;      }      emit_insn (gen_rtx_SET (BImode, tem,			      gen_rtx_fmt_ee (code1, BImode, op0, op1)));    }  return gen_rtx_fmt_ee (code2, BImode, tem, CONST0_RTX (BImode));}/* Return nonzero iff C has exactly one bit set if it is interpreted   as a 32 bit constant.  */intlog2constp (unsigned HOST_WIDE_INT c){  c &= 0xFFFFFFFF;  return c != 0 && (c & (c-1)) == 0;}/* Returns the number of consecutive least significant zeros in the binary   representation of *V.   We modify *V to contain the original value arithmetically shifted right by   the number of zeroes.  */static intshiftr_zero (HOST_WIDE_INT *v){  unsigned HOST_WIDE_INT tmp = *v;  unsigned HOST_WIDE_INT sgn;  int n = 0;  if (tmp == 0)    return 0;  sgn = tmp & ((unsigned HOST_WIDE_INT) 1 << (HOST_BITS_PER_WIDE_INT - 1));  while ((tmp & 0x1) == 0 && n <= 32)    {      tmp = (tmp >> 1) | sgn;      n++;    }  *v = tmp;  return n;}/* After reload, split the load of an immediate constant.  OPERANDS are the   operands of the movsi_insn pattern which we are splitting.  We return   nonzero if we emitted a sequence to load the constant, zero if we emitted   nothing because we want to use the splitter's default sequence.  */intsplit_load_immediate (rtx operands[]){  HOST_WIDE_INT val = INTVAL (operands[1]);  HOST_WIDE_INT tmp;  HOST_WIDE_INT shifted = val;  HOST_WIDE_INT shifted_compl = ~val;  int num_zero = shiftr_zero (&shifted);  int num_compl_zero = shiftr_zero (&shifted_compl);  unsigned int regno = REGNO (operands[0]);  enum reg_class class1 = REGNO_REG_CLASS (regno);  /* This case takes care of single-bit set/clear constants, which we could     also implement with BITSET/BITCLR.  */  if (num_zero      && shifted >= -32768 && shifted < 65536      && (D_REGNO_P (regno)	  || (regno >= REG_P0 && regno <= REG_P7 && num_zero <= 2)))    {      emit_insn (gen_movsi (operands[0], GEN_INT (shifted)));      emit_insn (gen_ashlsi3 (operands[0], operands[0], GEN_INT (num_zero)));      return 1;    }  tmp = val & 0xFFFF;  tmp |= -(tmp & 0x8000);  /* If high word has one bit set or clear, try to use a bit operation.  */  if (D_REGNO_P (regno))    {      if (log2constp (val & 0xFFFF0000))	{	  emit_insn (gen_movsi (operands[0], GEN_INT (val & 0xFFFF)));	  emit_insn (gen_iorsi3 (operands[0], operands[0], GEN_INT (val & 0xFFFF0000)));	  return 1;	}      else if (log2constp (val | 0xFFFF) && (val & 0x8000) != 0)	{	  emit_insn (gen_movsi (operands[0], GEN_INT (tmp)));	  emit_insn (gen_andsi3 (operands[0], operands[0], GEN_INT (val | 0xFFFF)));	}    }  if (D_REGNO_P (regno))    {      if (CONST_7BIT_IMM_P (tmp))	{	  emit_insn (gen_movsi (operands[0], GEN_INT (tmp)));	  emit_insn (gen_movstricthi_high (operands[0], GEN_INT (val & -65536)));	  return 1;	}      if ((val & 0xFFFF0000) == 0)	{	  emit_insn (gen_movsi (operands[0], const0_rtx));	  emit_insn (gen_movsi_low (operands[0], operands[0], operands[1]));	  return 1;	}      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];  int ok;    /* Validate the insn again, and compute first_[dp]reg_to_save. */  ok = push_multiple_operation (PATTERN (insn), VOIDmode);  gcc_assert (ok);    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];  int ok;    /* Validate the insn again, and compute first_[dp]reg_to_save. */  ok = pop_multiple_operation (PATTERN (insn), VOIDmode);  gcc_assert (ok);  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 SR

⌨️ 快捷键说明

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