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

📄 c4x.c

📁 gcc编译工具没有什么特别
💻 C
📖 第 1 页 / 共 5 页
字号:
    {      if (TARGET_LOAD_ADDRESS)	{	  /* Alias analysis seems to do a better job if we force	     constant addresses to memory after reload.  */	  emit_insn (gen_load_immed_address (op0, op1));	  return 1;	}      else	{	  /* Stick symbol or label address into the constant pool.  */	  op1 = force_const_mem (Pmode, op1);	}    }  else if (mode == HFmode && CONSTANT_P (op1) && ! LEGITIMATE_CONSTANT_P (op1))    {      /* We could be a lot smarter about loading some of these	 constants...  */      op1 = force_const_mem (mode, op1);    }  else if (mode == QImode && CONSTANT_P (op1) && ! LEGITIMATE_CONSTANT_P (op1))    {      /* We shouldn't need this test if only emit_move_insn was called.	 However, some routines call gen_move_insn which doesn't check that	 the constants are legitimate.  */      op1 = force_const_mem (mode, op1);    }  else if (mode == HImode && CONSTANT_P (op1) && ! LEGITIMATE_CONSTANT_P (op1))    {      /* We could load all sorts of constants in two goes by pulling all	 sorts of tricks... The tricky thing is that we cannot clobber CC	 so that stifles most of the obvious methods.  */      op1 = force_const_mem (mode, op1);    }  /* Convert (MEM (SYMREF)) to a (MEM (LO_SUM (REG) (SYMREF)))     and emit associated (HIGH (SYMREF)) if large memory model.       c4x_legitimize_address could be used to do this,     perhaps by calling validize_address.  */  if (TARGET_EXPOSE_LDP      && ! (reload_in_progress || reload_completed)      && GET_CODE (op1) == MEM      && symbolic_address_operand (XEXP (op1, 0), Pmode))    {      rtx dp_reg = gen_rtx_REG (Pmode, DP_REGNO);      if (! TARGET_SMALL)	emit_insn (gen_set_ldp (dp_reg, XEXP (op1, 0)));      op1 = change_address (op1, mode,			    gen_rtx_LO_SUM (Pmode, dp_reg, XEXP (op1, 0)));    }  if (TARGET_EXPOSE_LDP      && ! (reload_in_progress || reload_completed)      && GET_CODE (op0) == MEM       && symbolic_address_operand (XEXP (op0, 0), Pmode))    {      rtx dp_reg = gen_rtx_REG (Pmode, DP_REGNO);      if (! TARGET_SMALL)	emit_insn (gen_set_ldp (dp_reg, XEXP (op0, 0)));      op0 = change_address (op0, mode,			    gen_rtx_LO_SUM (Pmode, dp_reg, XEXP (op0, 0)));    }  if (GET_CODE (op0) == SUBREG      && mixed_subreg_operand (op0, mode))    {      /* We should only generate these mixed mode patterns	 during RTL generation.  If we need do it later on	 then we'll have to emit patterns that won't clobber CC.  */      if (reload_in_progress || reload_completed)	abort ();      if (GET_MODE (SUBREG_REG (op0)) == QImode)	op0 = SUBREG_REG (op0);      else if (GET_MODE (SUBREG_REG (op0)) == HImode)	{	  op0 = copy_rtx (op0);	  PUT_MODE (op0, QImode);	}      else	abort ();      if (mode == QFmode)	emit_insn (gen_storeqf_int_clobber (op0, op1));      else	abort ();      return 1;    }  if (GET_CODE (op1) == SUBREG      && mixed_subreg_operand (op1, mode))    {      /* We should only generate these mixed mode patterns	 during RTL generation.  If we need do it later on	 then we'll have to emit patterns that won't clobber CC.  */      if (reload_in_progress || reload_completed)	abort ();      if (GET_MODE (SUBREG_REG (op1)) == QImode)	op1 = SUBREG_REG (op1);      else if (GET_MODE (SUBREG_REG (op1)) == HImode)	{	  op1 = copy_rtx (op1);	  PUT_MODE (op1, QImode);	}      else	abort ();      if (mode == QFmode)	emit_insn (gen_loadqf_int_clobber (op0, op1));      else	abort ();      return 1;    }  /* Adjust operands in case we have modified them.  */  operands[0] = op0;  operands[1] = op1;  /* Emit normal pattern.  */  return 0;}voidc4x_emit_libcall (name, code, dmode, smode, noperands, operands)     char *name;     enum rtx_code code;     enum machine_mode dmode;     enum machine_mode smode;     int noperands;     rtx *operands;{  rtx ret;  rtx insns;  rtx libcall;  rtx equiv;  start_sequence ();  libcall = gen_rtx_SYMBOL_REF (Pmode, name);  switch (noperands)    {    case 2:      ret = emit_library_call_value (libcall, NULL_RTX, 1, dmode, 1,				     operands[1], smode);      equiv = gen_rtx (code, dmode, operands[1]);      break;    case 3:      ret = emit_library_call_value (libcall, NULL_RTX, 1, dmode, 2,				     operands[1], smode, operands[2], smode);      equiv = gen_rtx (code, dmode, operands[1], operands[2]);      break;    default:      fatal ("c4x_emit_libcall: Bad number of operands");    }  insns = get_insns ();  end_sequence ();  emit_libcall_block (insns, operands[0], ret, equiv);}voidc4x_emit_libcall3 (name, code, mode, operands)     const char *name;     enum rtx_code code;     enum machine_mode mode;     rtx *operands;{  return c4x_emit_libcall (name, code, mode, mode, 3, operands);}voidc4x_emit_libcall_mulhi (name, code, mode, operands)     char *name;     enum rtx_code code;     enum machine_mode mode;     rtx *operands;{  rtx ret;  rtx insns;  rtx libcall;  rtx equiv;  start_sequence ();  libcall = gen_rtx_SYMBOL_REF (Pmode, name);  ret = emit_library_call_value (libcall, NULL_RTX, 1, mode, 2,                                 operands[1], mode, operands[2], mode);  equiv = gen_rtx_TRUNCATE (mode,                   gen_rtx_LSHIFTRT (HImode,                            gen_rtx_MULT (HImode,                                     gen_rtx (code, HImode, operands[1]),                                     gen_rtx (code, HImode, operands[2])),                                     GEN_INT (32)));  insns = get_insns ();  end_sequence ();  emit_libcall_block (insns, operands[0], ret, equiv);}enum reg_classc4x_preferred_reload_class (x, class)     rtx x ATTRIBUTE_UNUSED;     enum reg_class class;{  return class;}enum reg_classc4x_limit_reload_class (mode, class)     enum machine_mode mode ATTRIBUTE_UNUSED;     enum reg_class class;{  return class;}enum reg_classc4x_secondary_memory_needed (class1, class2, mode)     enum reg_class class1 ATTRIBUTE_UNUSED;     enum reg_class class2 ATTRIBUTE_UNUSED;     enum machine_mode mode ATTRIBUTE_UNUSED;{  return 0;}/* Set the SYMBOL_REF_FLAG for a function decl.  However, wo do not   yet use this info.  */voidc4x_encode_section_info (decl)  tree decl;{#if 0  if (TREE_CODE (TREE_TYPE (decl)) == FUNCTION_TYPE)       SYMBOL_REF_FLAG (XEXP (DECL_RTL (decl), 0)) = 1;#else  if (TREE_CODE (decl) == FUNCTION_DECL)       SYMBOL_REF_FLAG (XEXP (DECL_RTL (decl), 0)) = 1;#endif}intc4x_check_legit_addr (mode, addr, strict)     enum machine_mode mode;     rtx addr;     int strict;{  rtx base = NULL_RTX;		/* Base register (AR0-AR7) */  rtx indx = NULL_RTX;		/* Index register (IR0,IR1) */  rtx disp = NULL_RTX;		/* Displacement */  enum rtx_code code;  code = GET_CODE (addr);  switch (code)    {      /* Register indirect with auto increment/decrement.  We don't	 allow SP here---push_operand should recognise an operand	 being pushed on the stack.  */    case PRE_DEC:    case PRE_INC:    case POST_DEC:      if (mode != QImode && mode != QFmode)	return 0;    case POST_INC:      base = XEXP (addr, 0);      if (! REG_P (base))	return 0;      break;    case PRE_MODIFY:    case POST_MODIFY:      {	rtx op0 = XEXP (addr, 0);	rtx op1 = XEXP (addr, 1);	if (mode != QImode && mode != QFmode)	  return 0;	if (! REG_P (op0) 	    || (GET_CODE (op1) != PLUS && GET_CODE (op1) != MINUS))	  return 0;	base = XEXP (op1, 0);	if (base != op0)	  return 0;	if (REG_P (XEXP (op1, 1)))	  indx = XEXP (op1, 1);	else	  disp = XEXP (op1, 1);      }      break;	      /* Register indirect.  */    case REG:      base = addr;      break;      /* Register indirect with displacement or index.  */    case PLUS:      {	rtx op0 = XEXP (addr, 0);	rtx op1 = XEXP (addr, 1);	enum rtx_code code0 = GET_CODE (op0);	switch (code0)	  {	  case REG:	    if (REG_P (op1))	      {		base = op0;	/* base + index */		indx = op1;		if (IS_INDEX_REGNO (base) || IS_ADDR_REGNO (indx))		  {		    base = op1;		    indx = op0;		  }	      }	    else	      {		base = op0;	/* base + displacement */		disp = op1;	      }	    break;	  default:	    return 0;	  }      }      break;      /* Direct addressing with DP register.  */    case LO_SUM:      {	rtx op0 = XEXP (addr, 0);	rtx op1 = XEXP (addr, 1);	/* HImode and HFmode direct memory references aren't truly	   offsettable (consider case at end of data page).  We	   probably get better code by loading a pointer and using an	   indirect memory reference.  */	if (mode == HImode || mode == HFmode)	  return 0;	if (!REG_P (op0) || REGNO (op0) != DP_REGNO)	  return 0;	if ((GET_CODE (op1) == SYMBOL_REF || GET_CODE (op1) == LABEL_REF))	  return 1;	if (GET_CODE (op1) == CONST)	  {	    addr = XEXP (op1, 0);	    	    if (GET_CODE (addr) == PLUS		&& (GET_CODE (XEXP (addr, 0)) == SYMBOL_REF		    || GET_CODE (XEXP (addr, 0)) == LABEL_REF)		&& GET_CODE (XEXP (addr, 1)) == CONST_INT)	      return 1;	  }	return 0;      }      break;      /* Direct addressing with some work for the assembler...  */    case CONST:      /* Direct addressing.  */    case LABEL_REF:    case SYMBOL_REF:      if (! TARGET_EXPOSE_LDP && ! strict && mode != HFmode && mode != HImode)	return 1;      /* These need to be converted to a LO_SUM (...). 	 LEGITIMIZE_RELOAD_ADDRESS will do this during reload.  */      return 0;      /* Do not allow direct memory access to absolute addresses.         This is more pain than it's worth, especially for the         small memory model where we can't guarantee that         this address is within the data page---we don't want         to modify the DP register in the small memory model,         even temporarily, since an interrupt can sneak in....  */    case CONST_INT:      return 0;      /* Indirect indirect addressing.  */    case MEM:      return 0;    case CONST_DOUBLE:      fatal_insn ("Using CONST_DOUBLE for address", addr);    default:      return 0;    }  /* Validate the base register.  */  if (base)    {      /* Check that the address is offsettable for HImode and HFmode.  */      if (indx && (mode == HImode || mode == HFmode))	return 0;      /* Handle DP based stuff.  */      if (REGNO (base) == DP_REGNO)	return 1;      if (strict && ! REGNO_OK_FOR_BASE_P (REGNO (base)))	return 0;      else if (! strict && ! IS_ADDR_OR_PSEUDO_REGNO (base))	return 0;    }  /* Now validate the index register.  */  if (indx)    {      if (GET_CODE (indx) != REG)	return 0;      if (strict && ! REGNO_OK_FOR_INDEX_P (REGNO (indx)))	return 0;      else if (! strict && ! IS_INDEX_OR_PSEUDO_REGNO (indx))	return 0;    }  /* Validate displacement.  */  if (disp)    {      if (GET_CODE (disp) != CONST_INT)	return 0;      if (mode == HImode || mode == HFmode)	{	  /* The offset displacement must be legitimate.  */	  if (! IS_DISP8_OFF_CONST (INTVAL (disp)))	    return 0;	}      else	{	  if (! IS_DISP8_CONST (INTVAL (disp)))	    return 0;	}      /* Can't add an index with a disp.  */      if (indx)	return 0;		    }  return 1;}rtxc4x_legitimize_address (orig, mode)     rtx orig ATTRIBUTE_UNUSED;     enum machine_mode mode ATTRIBUTE_UNUSED;{  if (GET_CODE (orig) == SYMBOL_REF      || GET_CODE (orig) == LABEL_REF)    {      if (mode == HImode || mode == HFmode)	{	  /* We need to force the address into	     a register so that it is offsettable.  */	  rtx addr_reg = gen_reg_rtx (Pmode);	  emit_move_insn (addr_reg, orig);	  return addr_reg;	}      else	{	  rtx dp_reg = gen_rtx_REG (Pmode, DP_REGNO);	  	  if (! TARGET_SMALL)	    emit_insn (gen_set_ldp (dp_reg, orig));	  	  return gen_rtx_LO_SUM (Pmode, dp_reg, orig);	}    }  return NULL_RTX;}rtxc4x_legitimize_reload_address (orig, mode, insn)     rtx orig ATTRIBUTE_UNUSED;     enum machine_mode mode;     rtx insn;{                                                                    	  if (mode != HImode       && mode != HFmode      && GET_MODE (orig) != HImode      && GET_MODE (orig) != HFmode      && (GET_CODE (orig) == CONST					          || GET_CODE (orig) == SYMBOL_REF				          || GET_CODE (orig) == LABEL_REF))    {                                                                         rtx dp_reg = gen_rtx_REG (Pmode, DP_REGNO);			      if (! TARGET_SMALL)						        emit_insn_before (gen_rtx_SET (VOIDmode, dp_reg, 						       gen_rtx_HIGH (Pmode, orig)),				  insn);      return gen_rtx_LO_SUM (Pmode, dp_reg, orig);    }  return NULL_RTX;}/* Provide the costs of an addressing mode that contains ADDR.   If ADDR is not a valid address, its cost is irrelevant.     This is used in cse and loop optimisation to determine   if it is worthwhile storing a common address into a register.    Unfortunately, the C4x address cost depends on other operands.  */int c4x_address_cost (addr)rtx addr;{  switch (GET_CODE (addr))    {    case REG:

⌨️ 快捷键说明

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