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

📄 v850.c

📁 GCC编译器源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
              off_name = "zdaoff";              reg_name = "r0";            }          else if (SDA_NAME_P (name))            {              off_name = "sdaoff";              reg_name = "gp";            }          else if (TDA_NAME_P (name))            {              off_name = "tdaoff";              reg_name = "ep";            }          else            abort();          fprintf (file, "%s(", off_name);          output_addr_const (file, addr);          fprintf (file, ")[%s]", reg_name);        }      else        output_addr_const (file, addr);      break;    case CONST:      if (special_symbolref_operand (addr, VOIDmode))        {          char* name = XSTR (XEXP (XEXP (addr, 0), 0), 0);          char* off_name;          char* reg_name;          if (ZDA_NAME_P (name))            {              off_name = "zdaoff";              reg_name = "r0";            }          else if (SDA_NAME_P (name))            {              off_name = "sdaoff";              reg_name = "gp";            }          else if (TDA_NAME_P (name))            {              off_name = "tdaoff";              reg_name = "ep";            }          else            abort();          fprintf (file, "%s(", off_name);          output_addr_const (file, addr);          fprintf (file, ")[%s]", reg_name);        }      else        output_addr_const (file, addr);      break;    default:      output_addr_const (file, addr);      break;    }}/* Return appropriate code to load up a 1, 2, or 4 integer/floating   point value.  */char *output_move_single (operands)     rtx *operands;{  rtx dst = operands[0];  rtx src = operands[1];  if (REG_P (dst))    {      if (REG_P (src))	return "mov %1,%0";      else if (GET_CODE (src) == CONST_INT)	{	  HOST_WIDE_INT value = INTVAL (src);	  if (CONST_OK_FOR_J (value))		/* signed 5 bit immediate */	    return "mov %1,%0";	  else if (CONST_OK_FOR_K (value))	/* signed 16 bit immediate */	    return "movea lo(%1),%.,%0";	  else if (CONST_OK_FOR_L (value))	/* upper 16 bits were set */	    return "movhi hi(%1),%.,%0";	  else					/* random constant */	    return "movhi hi(%1),%.,%0\n\tmovea lo(%1),%0,%0";	}      else if (GET_CODE (src) == CONST_DOUBLE && GET_MODE (src) == SFmode)	{	  HOST_WIDE_INT high, low;	  const_double_split (src, &high, &low);	  if (CONST_OK_FOR_J (high))		/* signed 5 bit immediate */	    return "mov %F1,%0";	  else if (CONST_OK_FOR_K (high))	/* signed 16 bit immediate */	    return "movea lo(%F1),%.,%0";	  else if (CONST_OK_FOR_L (high))	/* upper 16 bits were set */	    return "movhi hi(%F1),%.,%0";	  else					/* random constant */	    return "movhi hi(%F1),%.,%0\n\tmovea lo(%F1),%0,%0";	}      else if (GET_CODE (src) == MEM)	return "%S1ld%W1 %1,%0";      else if (special_symbolref_operand (src, VOIDmode))	return "movea %O1(%P1),%Q1,%0";      else if (GET_CODE (src) == LABEL_REF	       || GET_CODE (src) == SYMBOL_REF	       || GET_CODE (src) == CONST)	{	  return "movhi hi(%1),%.,%0\n\tmovea lo(%1),%0,%0";	}      else if (GET_CODE (src) == HIGH)	return "movhi hi(%1),%.,%0";      else if (GET_CODE (src) == LO_SUM)	{	  operands[2] = XEXP (src, 0);	  operands[3] = XEXP (src, 1);	  return "movea lo(%3),%2,%0";	}    }  else if (GET_CODE (dst) == MEM)    {      if (REG_P (src))	return "%S0st%W0 %1,%0";      else if (GET_CODE (src) == CONST_INT && INTVAL (src) == 0)	return "%S0st%W0 %.,%0";      else if (GET_CODE (src) == CONST_DOUBLE	       && CONST0_RTX (GET_MODE (dst)) == src)	return "%S0st%W0 %.,%0";    }  fatal_insn ("output_move_single:", gen_rtx (SET, VOIDmode, dst, src));  return "";}/* Return appropriate code to load up an 8 byte integer or floating point value */char *output_move_double (operands)    rtx *operands;{  enum machine_mode mode = GET_MODE (operands[0]);  rtx dst = operands[0];  rtx src = operands[1];  if (register_operand (dst, mode)      && register_operand (src, mode))    {      if (REGNO (src) + 1 == REGNO (dst))	return "mov %R1,%R0\n\tmov %1,%0";      else	return "mov %1,%0\n\tmov %R1,%R0";    }  /* Storing 0 */  if (GET_CODE (dst) == MEM      && ((GET_CODE (src) == CONST_INT && INTVAL (src) == 0)	  || (GET_CODE (src) == CONST_DOUBLE && CONST_DOUBLE_OK_FOR_G (src))))    return "st.w %.,%0\n\tst.w %.,%R0";  if (GET_CODE (src) == CONST_INT || GET_CODE (src) == CONST_DOUBLE)    {      HOST_WIDE_INT high_low[2];      int i;      rtx xop[10];      if (GET_CODE (src) == CONST_DOUBLE)	const_double_split (src, &high_low[1], &high_low[0]);      else	{	  high_low[0] = INTVAL (src);	  high_low[1] = (INTVAL (src) >= 0) ? 0 : -1;	}      for (i = 0; i < 2; i++)	{	  xop[0] = gen_rtx (REG, SImode, REGNO (dst)+i);	  xop[1] = GEN_INT (high_low[i]);	  output_asm_insn (output_move_single (xop), xop);	}      return "";    }  if (GET_CODE (src) == MEM)    {      int ptrreg = -1;      int dreg = REGNO (dst);      rtx inside = XEXP (src, 0);      if (GET_CODE (inside) == REG) 	ptrreg = REGNO (inside);      else if (GET_CODE (inside) == SUBREG)	ptrreg = REGNO (SUBREG_REG (inside)) + SUBREG_WORD (inside);      else if (GET_CODE (inside) == PLUS)	ptrreg = REGNO (XEXP (inside, 0));      else if (GET_CODE (inside) == LO_SUM)	ptrreg = REGNO (XEXP (inside, 0));      if (dreg == ptrreg)	return "ld.w %R1,%R0\n\tld.w %1,%0";    }  if (GET_CODE (src) == MEM)    return "ld.w %1,%0\n\tld.w %R1,%R0";    if (GET_CODE (dst) == MEM)    return "st.w %1,%0\n\tst.w %R1,%R0";  return "mov %1,%0\n\tmov %R1,%R0";}/* Return maximum offset supported for a short EP memory reference of mode   MODE and signedness UNSIGNEDP.  */intep_memory_offset (mode, unsignedp)     enum machine_mode mode;     int unsignedp;{  int max_offset = 0;  switch (mode)    {    case QImode:      max_offset = (1 << 7);      break;    case HImode:      max_offset = (1 << 8);      break;    case SImode:    case SFmode:      max_offset = (1 << 8);      break;    }  return max_offset;}/* Return true if OP is a valid short EP memory reference */intep_memory_operand (op, mode, unsigned_load)     rtx op;     enum machine_mode mode;     int unsigned_load;{  rtx addr, op0, op1;  int max_offset;  int mask;  if (GET_CODE (op) != MEM)    return FALSE;  max_offset = ep_memory_offset (mode, unsigned_load);  mask = GET_MODE_SIZE (mode) - 1;  addr = XEXP (op, 0);  if (GET_CODE (addr) == CONST)    addr = XEXP (addr, 0);  switch (GET_CODE (addr))    {    default:      break;    case SYMBOL_REF:      return TDA_NAME_P (XSTR (addr, 0));    case REG:      return REGNO (addr) == EP_REGNUM;    case PLUS:      op0 = XEXP (addr, 0);      op1 = XEXP (addr, 1);      if (GET_CODE (op1) == CONST_INT	  && INTVAL (op1) < max_offset	  && (INTVAL (op1) & mask) == 0)	{	  if (GET_CODE (op0) == REG && REGNO (op0) == EP_REGNUM)	    return TRUE;	  if (GET_CODE (op0) == SYMBOL_REF && TDA_NAME_P (XSTR (op0, 0)))	    return TRUE;	}      break;    }  return FALSE;}/* Return true if OP is either a register or 0 */intreg_or_0_operand (op, mode)     rtx op;     enum machine_mode mode;{  if (GET_CODE (op) == CONST_INT)    return INTVAL (op) == 0;  else if (GET_CODE (op) == CONST_DOUBLE)    return CONST_DOUBLE_OK_FOR_G (op);  else    return register_operand (op, mode);}/* Return true if OP is either a register or a signed five bit integer */intreg_or_int5_operand (op, mode)     rtx op;     enum machine_mode mode;{  if (GET_CODE (op) == CONST_INT)    return CONST_OK_FOR_J (INTVAL (op));  else    return register_operand (op, mode);}/* Return true if OP is a valid call operand.  */intcall_address_operand (op, mode)     rtx op;     enum machine_mode mode;{  /* Only registers are valid call operands if TARGET_LONG_CALLS.  */  if (TARGET_LONG_CALLS)    return GET_CODE (op) == REG;  return (GET_CODE (op) == SYMBOL_REF || GET_CODE (op) == REG);}intspecial_symbolref_operand (op, mode)     rtx op;     enum machine_mode mode;{  if (GET_CODE (op) == SYMBOL_REF)    return ENCODED_NAME_P (XSTR (op, 0));  else if (GET_CODE (op) == CONST)    return (GET_CODE (XEXP (op, 0)) == PLUS	    && GET_CODE (XEXP (XEXP (op, 0), 0)) == SYMBOL_REF	    && ENCODED_NAME_P (XSTR (XEXP (XEXP (op, 0), 0), 0))	    && GET_CODE (XEXP (XEXP (op, 0), 1)) == CONST_INT	    && CONST_OK_FOR_K (INTVAL (XEXP (XEXP (op, 0), 1))));  return FALSE;}intmovsi_source_operand (op, mode)     rtx op;     enum machine_mode mode;{  /* Some constants, as well as symbolic operands     must be done with HIGH & LO_SUM patterns.  */  if (CONSTANT_P (op)      && GET_CODE (op) != HIGH      && !(GET_CODE (op) == CONST_INT           && (CONST_OK_FOR_J (INTVAL (op))               || CONST_OK_FOR_K (INTVAL (op))               || CONST_OK_FOR_L (INTVAL (op)))))    return special_symbolref_operand (op, mode);  else    return general_operand (op, mode);}intpower_of_two_operand (op, mode)     rtx op;     enum machine_mode mode;{  if (GET_CODE (op) != CONST_INT)    return 0;  if (exact_log2 (INTVAL (op)) == -1)    return 0;  return 1;}intnot_power_of_two_operand (op, mode)     rtx op;     enum machine_mode mode;{  unsigned int mask;  if (mode == QImode)    mask = 0xff;  else if (mode == HImode)    mask = 0xffff;  else if (mode == SImode)    mask = 0xffffffff;   else    return 0;  if (GET_CODE (op) != CONST_INT)    return 0;  if (exact_log2 (~INTVAL (op) & mask) == -1)    return 0;  return 1;}/* Substitute memory references involving a pointer, to use the ep pointer,   taking care to save and preserve the ep.  */static voidsubstitute_ep_register (first_insn, last_insn, uses, regno, p_r1, p_ep)     rtx first_insn;     rtx last_insn;     int uses;     int regno;     rtx *p_r1;     rtx *p_ep;{  rtx reg = gen_rtx (REG, Pmode, regno);  rtx insn;  int i;  if (!*p_r1)    {      regs_ever_live[1] = 1;      *p_r1 = gen_rtx (REG, Pmode, 1);      *p_ep = gen_rtx (REG, Pmode, 30);    }  if (TARGET_DEBUG)    fprintf (stderr, "Saved %d bytes (%d uses of register %s) in function %s, starting as insn %d, ending at %d\n",	     2 * (uses - 3), uses, reg_names[regno],	     IDENTIFIER_POINTER (DECL_NAME (current_function_decl)),	     INSN_UID (first_insn), INSN_UID (last_insn));  if (GET_CODE (first_insn) == NOTE)    first_insn = next_nonnote_insn (first_insn);  last_insn = next_nonnote_insn (last_insn);  for (insn = first_insn; insn && insn != last_insn; insn = NEXT_INSN (insn))    {      if (GET_CODE (insn) == INSN)	{	  rtx pattern = single_set (insn);	  /* Replace the memory references.  */	  if (pattern)	    {	      rtx *p_mem;	      /* Memory operands are signed by default.  */	      int unsignedp = FALSE;	      if (GET_CODE (SET_DEST (pattern)) == MEM		  && GET_CODE (SET_SRC (pattern)) == MEM)		p_mem = (rtx *)0;	      else if (GET_CODE (SET_DEST (pattern)) == MEM)		p_mem = &SET_DEST (pattern);	      else if (GET_CODE (SET_SRC (pattern)) == MEM)		p_mem = &SET_SRC (pattern);	      else		p_mem = (rtx *)0;	      if (p_mem)		{		  rtx addr = XEXP (*p_mem, 0);		  if (GET_CODE (addr) == REG && REGNO (addr) == regno)		    *p_mem = change_address (*p_mem, VOIDmode, *p_ep);		  else if (GET_CODE (addr) == PLUS			   && GET_CODE (XEXP (addr, 0)) == REG			   && REGNO (XEXP (addr, 0)) == regno			   && GET_CODE (XEXP (addr, 1)) == CONST_INT			   && (((unsigned)INTVAL (XEXP (addr, 1)))			       < ep_memory_offset (GET_MODE (*p_mem),						   unsignedp)))		    *p_mem = change_address (*p_mem, VOIDmode,					     gen_rtx (PLUS, Pmode,						      *p_ep, XEXP (addr, 1)));		}	    }	}    }  /* Optimize back to back cases of ep <- r1 & r1 <- ep.  */  insn = prev_nonnote_insn (first_insn);  if (insn && GET_CODE (insn) == INSN      && GET_CODE (PATTERN (insn)) == SET      && SET_DEST (PATTERN (insn)) == *p_ep      && SET_SRC (PATTERN (insn)) == *p_r1)    delete_insn (insn);  else    emit_insn_before (gen_rtx (SET, Pmode, *p_r1, *p_ep), first_insn);  emit_insn_before (gen_rtx (SET, Pmode, *p_ep, reg), first_insn);  emit_insn_before (gen_rtx (SET, Pmode, *p_ep, *p_r1), last_insn);}/* In rare cases, correct code generation requires extra machine   dependent processing between the second jump optimization pass and   delayed branch scheduling.  On those machines, define this macro   as a C statement to act on the code starting at INSN.   On the 850, we use it to implement the -mep mode to copy heavily used   pointers to ep to use the implicit addressing */void v850_reorg (start_insn)     rtx start_insn;{  struct {    int uses;    rtx first_insn;    rtx last_insn;  } regs[FIRST_PSEUDO_REGISTER];  int i;  int use_ep = FALSE;  rtx r1 = NULL_RTX;  rtx ep = NULL_RTX;  rtx insn;  rtx pattern;  /* If not ep mode, just return now */  if (!TARGET_EP)    return;  for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)    {      regs[i].uses = 0;      regs[i].first_insn = NULL_RTX;      regs[i].last_insn = NULL_RTX;    }  for (insn = start_insn; insn != NULL_RTX; insn = NEXT_INSN (insn))    {      switch (GET_CODE (insn))	{	  /* End of basic block */	default:	  if (!use_ep)	    {	      int max_uses = -1;

⌨️ 快捷键说明

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