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

📄 mcore.c

📁 gcc-you can use this code to learn something about gcc, and inquire further into linux,
💻 C
📖 第 1 页 / 共 5 页
字号:
  else if ((load_value & (load_value - 1)) == 0)    output_asm_insn ("bgeni\t%0,%P1", out_operands);  else if ((load_value & (load_value + 1)) == 0)    output_asm_insn ("bmaski\t%0,%N1", out_operands);     /* Output the constant adjustment.  */  if (load_value > adjust_value)    {      if (cmp_t)	output_asm_insn ("decf\t%0", out_operands);      else	output_asm_insn ("dect\t%0", out_operands);    }  else    {      if (cmp_t)	output_asm_insn ("incf\t%0", out_operands);      else	output_asm_insn ("inct\t%0", out_operands);    }  return "";}/* Outputs the peephole for moving a constant that gets not'ed followed    by an and (i.e. combine the not and the and into andn). BRC  */const char *mcore_output_andn (insn, operands)     rtx insn ATTRIBUTE_UNUSED;     rtx operands[];{  int x, y;  rtx out_operands[3];  const char * load_op;  char buf[256];  if (try_constant_tricks (INTVAL (operands[1]), &x, &y) != 2)    abort ();  out_operands[0] = operands[0];  out_operands[1] = GEN_INT(x);  out_operands[2] = operands[2];  if (x >= 0 && x <= 127)    load_op = "movi\t%0,%1";    /* Try exact power of two.  */  else if ((x & (x - 1)) == 0)    load_op = "bgeni\t%0,%P1";    /* Try exact power of two - 1.  */  else if ((x & (x + 1)) == 0)    load_op = "bmaski\t%0,%N1";    else     load_op = "BADMOVI\t%0,%1";  sprintf (buf, "%s\n\tandn\t%%2,%%0", load_op);  output_asm_insn (buf, out_operands);  return "";}/* Output an inline constant.  */static const char *output_inline_const (mode, operands)     enum machine_mode mode;     rtx operands[];{  int x = 0, y = 0;  int trick_no;  rtx out_operands[3];  char buf[256];  char load_op[256];  const char *dst_fmt;  int value;  value = INTVAL (operands[1]);     if ((trick_no = try_constant_tricks (value, &x, &y)) == 0)    {      /* lrw's are handled separately:  Large inlinable constants	 never get turned into lrw's.  Our caller uses try_constant_tricks         to back off to an lrw rather than calling this routine.  */      abort ();    }  if (trick_no == 1)    x = value;  /* operands: 0 = dst, 1 = load immed., 2 = immed. adjustment.  */  out_operands[0] = operands[0];  out_operands[1] = GEN_INT (x);    if (trick_no > 2)    out_operands[2] = GEN_INT (y);  /* Select dst format based on mode.  */  if (mode == DImode && (! TARGET_LITTLE_END))    dst_fmt = "%R0";  else    dst_fmt = "%0";  if (x >= 0 && x <= 127)    sprintf (load_op, "movi\t%s,%%1", dst_fmt);    /* Try exact power of two.  */  else if ((x & (x - 1)) == 0)    sprintf (load_op, "bgeni\t%s,%%P1", dst_fmt);    /* Try exact power of two - 1.  */  else if ((x & (x + 1)) == 0)    sprintf (load_op, "bmaski\t%s,%%N1", dst_fmt);    else     sprintf (load_op, "BADMOVI\t%s,%%1", dst_fmt);  switch (trick_no)    {    case 1:      strcpy (buf, load_op);      break;    case 2:   /* not */      sprintf (buf, "%s\n\tnot\t%s\t// %d 0x%x", load_op, dst_fmt, value, value);      break;    case 3:   /* add */      sprintf (buf, "%s\n\taddi\t%s,%%2\t// %d 0x%x", load_op, dst_fmt, value, value);      break;    case 4:   /* sub */      sprintf (buf, "%s\n\tsubi\t%s,%%2\t// %d 0x%x", load_op, dst_fmt, value, value);      break;    case 5:   /* rsub */      /* Never happens unless -mrsubi, see try_constant_tricks().  */      sprintf (buf, "%s\n\trsubi\t%s,%%2\t// %d 0x%x", load_op, dst_fmt, value, value);      break;    case 6:   /* bset */      sprintf (buf, "%s\n\tbseti\t%s,%%P2\t// %d 0x%x", load_op, dst_fmt, value, value);      break;    case 7:   /* bclr */      sprintf (buf, "%s\n\tbclri\t%s,%%Q2\t// %d 0x%x", load_op, dst_fmt, value, value);      break;    case 8:   /* rotl */      sprintf (buf, "%s\n\trotli\t%s,%%2\t// %d 0x%x", load_op, dst_fmt, value, value);      break;    case 9:   /* lsl */      sprintf (buf, "%s\n\tlsli\t%s,%%2\t// %d 0x%x", load_op, dst_fmt, value, value);      break;    case 10:  /* ixh */      sprintf (buf, "%s\n\tixh\t%s,%s\t// %d 0x%x", load_op, dst_fmt, dst_fmt, value, value);      break;    case 11:  /* ixw */      sprintf (buf, "%s\n\tixw\t%s,%s\t// %d 0x%x", load_op, dst_fmt, dst_fmt, value, value);      break;    default:      return "";    }    output_asm_insn (buf, out_operands);  return "";}/* Output a move of a word or less value.  */const char *mcore_output_move (insn, operands, mode)     rtx insn ATTRIBUTE_UNUSED;     rtx operands[];     enum machine_mode mode ATTRIBUTE_UNUSED;{  rtx dst = operands[0];  rtx src = operands[1];  if (GET_CODE (dst) == REG)    {      if (GET_CODE (src) == REG)	{               	  if (REGNO (src) == CC_REG)            /* r-c */            return "mvc\t%0"; 	  else             return "mov\t%0,%1";                /* r-r*/	}      else if (GET_CODE (src) == MEM)	{	  if (GET_CODE (XEXP (src, 0)) == LABEL_REF)             return "lrw\t%0,[%1]";              /* a-R */	  else            return "ldw\t%0,%1";                 /* r-m */	}      else if (GET_CODE (src) == CONST_INT)	{	  int x, y;	  	  if (CONST_OK_FOR_I (INTVAL (src)))       /* r-I */            return "movi\t%0,%1";	  else if (CONST_OK_FOR_M (INTVAL (src)))  /* r-M */            return "bgeni\t%0,%P1\t// %1 %x1";	  else if (CONST_OK_FOR_N (INTVAL (src)))  /* r-N */            return "bmaski\t%0,%N1\t// %1 %x1";	  else if (try_constant_tricks (INTVAL (src), &x, &y))     /* R-P */            return output_inline_const (SImode, operands);  /* 1-2 insns */	  else             return "lrw\t%0,%x1\t// %1";	/* Get it from literal pool.  */	}      else	return "lrw\t%0, %1";                /* Into the literal pool.  */    }  else if (GET_CODE (dst) == MEM)               /* m-r */    return "stw\t%1,%0";  abort ();}/* Outputs a constant inline -- regardless of the cost.   Useful for things where we've gotten into trouble and think we'd   be doing an lrw into r15 (forbidden). This lets us get out of   that pickle even after register allocation.  */const char *mcore_output_inline_const_forced (insn, operands, mode)     rtx insn ATTRIBUTE_UNUSED;     rtx operands[];     enum machine_mode mode ATTRIBUTE_UNUSED;{  unsigned long value = INTVAL (operands[1]);  unsigned long ovalue = value;  struct piece  {    int low;    int shift;  }  part[6];  int i;  if (mcore_const_ok_for_inline (value))    return output_inline_const (SImode, operands);  for (i = 0; (unsigned) i < ARRAY_SIZE (part); i++)    {      part[i].shift = 0;      part[i].low = (value & 0x1F);      value -= part[i].low;            if (mcore_const_ok_for_inline (value))	break;      else	{	  value >>= 5;	  part[i].shift = 5;	  	  while ((value & 1) == 0)	    {	      part[i].shift++;	      value >>= 1;	    }	  	  if (mcore_const_ok_for_inline (value))	    break;	}    }    /* 5 bits per iteration, a maximum of 5 times == 25 bits and leaves     7 bits left in the constant -- which we know we can cover with     a movi.  The final value can't be zero otherwise we'd have stopped     in the previous iteration.   */  if (value == 0 || ! mcore_const_ok_for_inline (value))    abort ();  /* Now, work our way backwards emitting the constant.  */  /* Emit the value that remains -- it will be nonzero.  */  operands[1] = GEN_INT (value);  output_asm_insn (output_inline_const (SImode, operands), operands);   while (i >= 0)    {      /* Shift anything we've already loaded.  */      if (part[i].shift)        {	  operands[2] = GEN_INT (part[i].shift);	  output_asm_insn ("lsli       %0,%2", operands);	  value <<= part[i].shift;        }            /* Add anything we need into the low 5 bits.  */      if (part[i].low != 0)        {	  operands[2] = GEN_INT (part[i].low);	  output_asm_insn ("addi      %0,%2", operands);	  value += part[i].low;        }            i--;    }    if (value != ovalue)          /* sanity */    abort ();   /* We've output all the instructions.  */  return "";}/* Return a sequence of instructions to perform DI or DF move.   Since the MCORE cannot move a DI or DF in one instruction, we have   to take care when we see overlapping source and dest registers.  */const char *mcore_output_movedouble (operands, mode)     rtx operands[];     enum machine_mode mode ATTRIBUTE_UNUSED;{  rtx dst = operands[0];  rtx src = operands[1];  if (GET_CODE (dst) == REG)    {      if (GET_CODE (src) == REG)	{	  int dstreg = REGNO (dst);	  int srcreg = REGNO (src);	  	  /* Ensure the second source not overwritten.  */	  if (srcreg + 1 == dstreg)	    return "mov	%R0,%R1\n\tmov	%0,%1";	  else	    return "mov	%0,%1\n\tmov	%R0,%R1";	}      else if (GET_CODE (src) == MEM)	{	  rtx memexp = memexp = XEXP (src, 0);	  int dstreg = REGNO (dst);	  int basereg = -1;	  	  if (GET_CODE (memexp) == LABEL_REF)	    return "lrw\t%0,[%1]\n\tlrw\t%R0,[%R1]";	  else if (GET_CODE (memexp) == REG) 	    basereg = REGNO (memexp);	  else if (GET_CODE (memexp) == PLUS)	    {	      if (GET_CODE (XEXP (memexp, 0)) == REG)		basereg = REGNO (XEXP (memexp, 0));	      else if (GET_CODE (XEXP (memexp, 1)) == REG)		basereg = REGNO (XEXP (memexp, 1));	      else		abort ();	    }	  else	    abort ();          /* ??? length attribute is wrong here.  */	  if (dstreg == basereg)	    {	      /* Just load them in reverse order.  */	      return "ldw\t%R0,%R1\n\tldw\t%0,%1";	      	      /* XXX: alternative: move basereg to basereg+1	         and then fall through.  */	    }	  else	    return "ldw\t%0,%1\n\tldw\t%R0,%R1";	}      else if (GET_CODE (src) == CONST_INT)	{	  if (TARGET_LITTLE_END)	    {	      if (CONST_OK_FOR_I (INTVAL (src)))		output_asm_insn ("movi	%0,%1", operands);	      else if (CONST_OK_FOR_M (INTVAL (src)))		output_asm_insn ("bgeni	%0,%P1", operands);	      else if (INTVAL (src) == -1)		output_asm_insn ("bmaski	%0,32", operands);	      else if (CONST_OK_FOR_N (INTVAL (src)))		output_asm_insn ("bmaski	%0,%N1", operands);	      else		abort ();	      if (INTVAL (src) < 0)		return "bmaski	%R0,32";	      else		return "movi	%R0,0";	    }	  else	    {	      if (CONST_OK_FOR_I (INTVAL (src)))		output_asm_insn ("movi	%R0,%1", operands);	      else if (CONST_OK_FOR_M (INTVAL (src)))		output_asm_insn ("bgeni	%R0,%P1", operands);	      else if (INTVAL (src) == -1)		output_asm_insn ("bmaski	%R0,32", operands);	      else if (CONST_OK_FOR_N (INTVAL (src)))		output_asm_insn ("bmaski	%R0,%N1", operands);	      else		abort ();	      	      if (INTVAL (src) < 0)		return "bmaski	%0,32";	      else		return "movi	%0,0";	    }	}      else	abort ();    }  else if (GET_CODE (dst) == MEM && GET_CODE (src) == REG)    return "stw\t%1,%0\n\tstw\t%R1,%R0";  else    abort ();}/* Predicates used by the templates.  *//* Nonzero if OP can be source of a simple move operation.  */intmcore_general_movsrc_operand (op, mode)     rtx op;     enum machine_mode mode;{  /* Any (MEM LABEL_REF) is OK.  That is a pc-relative load.  */  if (GET_CODE (op) == MEM && GET_CODE (XEXP (op, 0)) == LABEL_REF)    return 1;  return general_operand (op, mode);}/* Nonzero if OP can be destination of a simple move operation. */intmcore_general_movdst_operand (op, mode)     rtx op;     enum machine_mode mode;{  if (GET_CODE (op) == REG && REGNO (op) == CC_REG)    return 0;    return general_operand (op, mode);}/* Nonzero if OP is a normal arithmetic register.  */intmcore_arith_reg_operand (op, mode)     rtx op;     enum machine_mode mode;{  if (! register_operand (op, mode))    return 0;  if (GET_CODE (op) == SUBREG)    op = SUBREG_REG (op);  if (GET_CODE (op) == REG)    return REGNO (op) != CC_REG;  return 1;}/* Nonzero if OP should be recognized during reload for an ixh/ixw   operand.  See the ixh/ixw patterns.  */intmcore_reload_operand (op, mode)     rtx op;     enum machine_mode mode;{  if (mcore_arith_reg_operand (op, mode))    return 1;  if (! reload_in_progress)    return 0;  return GET_CODE (op) == MEM;}/* Nonzero if OP is a valid source operand for an arithmetic insn.  */intmcore_arith_J_operand (op, mode)     rtx op;     enum machine_mode mode;{  if (register_operand (op, mode))    return 1;  if (GET_CODE (op) == CONST_INT && CONST_OK_FOR_J (INTVAL (op)))    return 1;    return 0;}/* Nonzero if OP is a valid source operand for an arithmetic insn.  */intmcore_arith_K_operand (op, mode)     rtx op;     enum machine_mode mode;{  if (register_operand (op, mode))    return 1;  if (GET_CODE (op) == CONST_INT && CONST_OK_FOR_K (INTVAL (op)))    return 1;  return 0;}/* Nonzero if OP is a valid source operand for a shift or rotate insn.  */intmcore_arith_K_operand_not_0 (op, mode)     rtx op;

⌨️ 快捷键说明

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