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

📄 pa.c

📁 linux下的gcc编译器
💻 C
📖 第 1 页 / 共 5 页
字号:
	return orig;      if (reg == 0)	abort ();      if (GET_CODE (XEXP (orig, 0)) == PLUS)	{	  base = legitimize_pic_address (XEXP (XEXP (orig, 0), 0), Pmode, reg);	  orig = legitimize_pic_address (XEXP (XEXP (orig, 0), 1), Pmode,					 base == reg ? 0 : reg);	}      else abort ();      if (GET_CODE (orig) == CONST_INT)	{	  if (INT_14_BITS (orig))	    return plus_constant (base, INTVAL (orig));	  orig = force_reg (Pmode, orig);	}      pic_ref = gen_rtx_PLUS (Pmode, base, orig);      /* Likewise, should we set special REG_NOTEs here?  */    }  return pic_ref;}/* Try machine-dependent ways of modifying an illegitimate address   to be legitimate.  If we find one, return the new, valid address.   This macro is used in only one place: `memory_address' in explow.c.   OLDX is the address as it was before break_out_memory_refs was called.   In some cases it is useful to look at this to decide what needs to be done.   MODE and WIN are passed so that this macro can use   GO_IF_LEGITIMATE_ADDRESS.   It is always safe for this macro to do nothing.  It exists to recognize   opportunities to optimize the output.   For the PA, transform:	memory(X + <large int>)   into:	if (<large int> & mask) >= 16	  Y = (<large int> & ~mask) + mask + 1	Round up.	else	  Y = (<large int> & ~mask)		Round down.	Z = X + Y	memory (Z + (<large int> - Y));   This is for CSE to find several similar references, and only use one Z.   X can either be a SYMBOL_REF or REG, but because combine can not   perform a 4->2 combination we do nothing for SYMBOL_REF + D where   D will not fit in 14 bits.   MODE_FLOAT references allow displacements which fit in 5 bits, so use   0x1f as the mask.   MODE_INT references allow displacements which fit in 14 bits, so use   0x3fff as the mask.   This relies on the fact that most mode MODE_FLOAT references will use FP   registers and most mode MODE_INT references will use integer registers.   (In the rare case of an FP register used in an integer MODE, we depend   on secondary reloads to clean things up.)   It is also beneficial to handle (plus (mult (X) (Y)) (Z)) in a special   manner if Y is 2, 4, or 8.  (allows more shadd insns and shifted indexed   addressing modes to be used).   Put X and Z into registers.  Then put the entire expression into   a register.  */rtxhppa_legitimize_address (x, oldx, mode)     rtx x, oldx ATTRIBUTE_UNUSED;     enum machine_mode mode;{  rtx orig = x;  if (flag_pic)    return legitimize_pic_address (x, mode, gen_reg_rtx (Pmode));  /* Strip off CONST.  */  if (GET_CODE (x) == CONST)    x = XEXP (x, 0);  /* Special case.  Get the SYMBOL_REF into a register and use indexing.     That should always be safe.  */  if (GET_CODE (x) == PLUS      && GET_CODE (XEXP (x, 0)) == REG      && GET_CODE (XEXP (x, 1)) == SYMBOL_REF)    {      rtx reg = force_reg (Pmode, XEXP (x, 1));      return force_reg (Pmode, gen_rtx_PLUS (Pmode, reg, XEXP (x, 0)));    }  /* Note we must reject symbols which represent function addresses     since the assembler/linker can't handle arithmetic on plabels.  */  if (GET_CODE (x) == PLUS      && GET_CODE (XEXP (x, 1)) == CONST_INT      && ((GET_CODE (XEXP (x, 0)) == SYMBOL_REF	   && !FUNCTION_NAME_P (XSTR (XEXP (x, 0), 0)))	  || GET_CODE (XEXP (x, 0)) == REG))    {      rtx int_part, ptr_reg;      int newoffset;      int offset = INTVAL (XEXP (x, 1));      int mask;      mask = (GET_MODE_CLASS (mode) == MODE_FLOAT	      ? (TARGET_PA_20 ? 0x3fff : 0x1f) : 0x3fff);      /* Choose which way to round the offset.  Round up if we	 are >= halfway to the next boundary.  */      if ((offset & mask) >= ((mask + 1) / 2))	newoffset = (offset & ~ mask) + mask + 1;      else	newoffset = (offset & ~ mask);      /* If the newoffset will not fit in 14 bits (ldo), then	 handling this would take 4 or 5 instructions (2 to load	 the SYMBOL_REF + 1 or 2 to load the newoffset + 1 to	 add the new offset and the SYMBOL_REF.)  Combine can	 not handle 4->2 or 5->2 combinations, so do not create	 them.  */      if (! VAL_14_BITS_P (newoffset)	  && GET_CODE (XEXP (x, 0)) == SYMBOL_REF)	{	  rtx const_part = plus_constant (XEXP (x, 0), newoffset);	  rtx tmp_reg	    = force_reg (Pmode,			 gen_rtx_HIGH (Pmode, const_part));	  ptr_reg	    = force_reg (Pmode,			 gen_rtx_LO_SUM (Pmode,					 tmp_reg, const_part));	}      else	{	  if (! VAL_14_BITS_P (newoffset))	    int_part = force_reg (Pmode, GEN_INT (newoffset));	  else	    int_part = GEN_INT (newoffset);	  ptr_reg = force_reg (Pmode,			       gen_rtx_PLUS (Pmode,					     force_reg (Pmode, XEXP (x, 0)),					     int_part));	}      return plus_constant (ptr_reg, offset - newoffset);    }  /* Handle (plus (mult (a) (shadd_constant)) (b)).  */  if (GET_CODE (x) == PLUS && GET_CODE (XEXP (x, 0)) == MULT      && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT      && shadd_constant_p (INTVAL (XEXP (XEXP (x, 0), 1)))      && (GET_RTX_CLASS (GET_CODE (XEXP (x, 1))) == 'o'	  || GET_CODE (XEXP (x, 1)) == SUBREG)      && GET_CODE (XEXP (x, 1)) != CONST)    {      int val = INTVAL (XEXP (XEXP (x, 0), 1));      rtx reg1, reg2;      reg1 = XEXP (x, 1);      if (GET_CODE (reg1) != REG)	reg1 = force_reg (Pmode, force_operand (reg1, 0));      reg2 = XEXP (XEXP (x, 0), 0);      if (GET_CODE (reg2) != REG)        reg2 = force_reg (Pmode, force_operand (reg2, 0));      return force_reg (Pmode, gen_rtx_PLUS (Pmode,					     gen_rtx_MULT (Pmode,							   reg2,							   GEN_INT (val)),					     reg1));    }  /* Similarly for (plus (plus (mult (a) (shadd_constant)) (b)) (c)).     Only do so for floating point modes since this is more speculative     and we lose if it's an integer store.  */  if (GET_CODE (x) == PLUS      && GET_CODE (XEXP (x, 0)) == PLUS      && GET_CODE (XEXP (XEXP (x, 0), 0)) == MULT      && GET_CODE (XEXP (XEXP (XEXP (x, 0), 0), 1)) == CONST_INT      && shadd_constant_p (INTVAL (XEXP (XEXP (XEXP (x, 0), 0), 1)))      && (mode == SFmode || mode == DFmode))    {      /* First, try and figure out what to use as a base register.  */      rtx reg1, reg2, base, idx, orig_base;      reg1 = XEXP (XEXP (x, 0), 1);      reg2 = XEXP (x, 1);      base = NULL_RTX;      idx = NULL_RTX;      /* Make sure they're both regs.  If one was a SYMBOL_REF [+ const],	 then emit_move_sequence will turn on REG_POINTER so we'll know	 it's a base register below.  */      if (GET_CODE (reg1) != REG)	reg1 = force_reg (Pmode, force_operand (reg1, 0));      if (GET_CODE (reg2) != REG)	reg2 = force_reg (Pmode, force_operand (reg2, 0));      /* Figure out what the base and index are.  */      if (GET_CODE (reg1) == REG	  && REG_POINTER (reg1))	{	  base = reg1;	  orig_base = XEXP (XEXP (x, 0), 1);	  idx = gen_rtx_PLUS (Pmode,			      gen_rtx_MULT (Pmode,					    XEXP (XEXP (XEXP (x, 0), 0), 0),					    XEXP (XEXP (XEXP (x, 0), 0), 1)),			      XEXP (x, 1));	}      else if (GET_CODE (reg2) == REG	       && REG_POINTER (reg2))	{	  base = reg2;	  orig_base = XEXP (x, 1);	  idx = XEXP (x, 0);	}      if (base == 0)	return orig;      /* If the index adds a large constant, try to scale the	 constant so that it can be loaded with only one insn.  */      if (GET_CODE (XEXP (idx, 1)) == CONST_INT	  && VAL_14_BITS_P (INTVAL (XEXP (idx, 1))			    / INTVAL (XEXP (XEXP (idx, 0), 1)))	  && INTVAL (XEXP (idx, 1)) % INTVAL (XEXP (XEXP (idx, 0), 1)) == 0)	{	  /* Divide the CONST_INT by the scale factor, then add it to A.  */	  int val = INTVAL (XEXP (idx, 1));	  val /= INTVAL (XEXP (XEXP (idx, 0), 1));	  reg1 = XEXP (XEXP (idx, 0), 0);	  if (GET_CODE (reg1) != REG)	    reg1 = force_reg (Pmode, force_operand (reg1, 0));	  reg1 = force_reg (Pmode, gen_rtx_PLUS (Pmode, reg1, GEN_INT (val)));	  /* We can now generate a simple scaled indexed address.  */	  return	    force_reg	      (Pmode, gen_rtx_PLUS (Pmode,				    gen_rtx_MULT (Pmode, reg1,						  XEXP (XEXP (idx, 0), 1)),				    base));	}      /* If B + C is still a valid base register, then add them.  */      if (GET_CODE (XEXP (idx, 1)) == CONST_INT	  && INTVAL (XEXP (idx, 1)) <= 4096	  && INTVAL (XEXP (idx, 1)) >= -4096)	{	  int val = INTVAL (XEXP (XEXP (idx, 0), 1));	  rtx reg1, reg2;	  reg1 = force_reg (Pmode, gen_rtx_PLUS (Pmode, base, XEXP (idx, 1)));	  reg2 = XEXP (XEXP (idx, 0), 0);	  if (GET_CODE (reg2) != CONST_INT)	    reg2 = force_reg (Pmode, force_operand (reg2, 0));	  return force_reg (Pmode, gen_rtx_PLUS (Pmode,						 gen_rtx_MULT (Pmode,							       reg2,							       GEN_INT (val)),						 reg1));	}      /* Get the index into a register, then add the base + index and	 return a register holding the result.  */      /* First get A into a register.  */      reg1 = XEXP (XEXP (idx, 0), 0);      if (GET_CODE (reg1) != REG)	reg1 = force_reg (Pmode, force_operand (reg1, 0));      /* And get B into a register.  */      reg2 = XEXP (idx, 1);      if (GET_CODE (reg2) != REG)	reg2 = force_reg (Pmode, force_operand (reg2, 0));      reg1 = force_reg (Pmode,			gen_rtx_PLUS (Pmode,				      gen_rtx_MULT (Pmode, reg1,						    XEXP (XEXP (idx, 0), 1)),				      reg2));      /* Add the result to our base register and return.  */      return force_reg (Pmode, gen_rtx_PLUS (Pmode, base, reg1));    }  /* Uh-oh.  We might have an address for x[n-100000].  This needs     special handling to avoid creating an indexed memory address     with x-100000 as the base.     If the constant part is small enough, then it's still safe because     there is a guard page at the beginning and end of the data segment.     Scaled references are common enough that we want to try and rearrange the     terms so that we can use indexing for these addresses too.  Only     do the optimization for floatint point modes.  */  if (GET_CODE (x) == PLUS      && symbolic_expression_p (XEXP (x, 1)))    {      /* Ugly.  We modify things here so that the address offset specified	 by the index expression is computed first, then added to x to form	 the entire address.  */      rtx regx1, regx2, regy1, regy2, y;      /* Strip off any CONST.  */      y = XEXP (x, 1);      if (GET_CODE (y) == CONST)	y = XEXP (y, 0);      if (GET_CODE (y) == PLUS || GET_CODE (y) == MINUS)	{	  /* See if this looks like		(plus (mult (reg) (shadd_const))		      (const (plus (symbol_ref) (const_int))))	     Where const_int is small.  In that case the const	     expression is a valid pointer for indexing.	     If const_int is big, but can be divided evenly by shadd_const	     and added to (reg).  This allows more scaled indexed addresses.  */	  if (GET_CODE (XEXP (y, 0)) == SYMBOL_REF	      && GET_CODE (XEXP (x, 0)) == MULT	      && GET_CODE (XEXP (y, 1)) == CONST_INT	      && INTVAL (XEXP (y, 1)) >= -4096	      && INTVAL (XEXP (y, 1)) <= 4095	      && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT	      && shadd_constant_p (INTVAL (XEXP (XEXP (x, 0), 1))))	    {	      int val = INTVAL (XEXP (XEXP (x, 0), 1));	      rtx reg1, reg2;	      reg1 = XEXP (x, 1);	      if (GET_CODE (reg1) != REG)		reg1 = force_reg (Pmode, force_operand (reg1, 0));	      reg2 = XEXP (XEXP (x, 0), 0);	      if (GET_CODE (reg2) != REG)	        reg2 = force_reg (Pmode, force_operand (reg2, 0));	      return force_reg (Pmode,				gen_rtx_PLUS (Pmode,					      gen_rtx_MULT (Pmode,							    reg2,							    GEN_INT (val)),					      reg1));	    }	  else if ((mode == DFmode || mode == SFmode)		   && GET_CODE (XEXP (y, 0)) == SYMBOL_REF		   && GET_CODE (XEXP (x, 0)) == MULT		   && GET_CODE (XEXP (y, 1)) == CONST_INT		   && INTVAL (XEXP (y, 1)) % INTVAL (XEXP (XEXP (x, 0), 1)) == 0		   && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT		   && shadd_constant_p (INTVAL (XEXP (XEXP (x, 0), 1))))	    {	      regx1		= force_reg (Pmode, GEN_INT (INTVAL (XEXP (y, 1))					     / INTVAL (XEXP (XEXP (x, 0), 1))));	      regx2 = XEXP (XEXP (x, 0), 0);	      if (GET_CODE (regx2) != REG)		regx2 = force_reg (Pmode, force_operand (regx2, 0));	      regx2 = force_reg (Pmode, gen_rtx_fmt_ee (GET_CODE (y), Pmode,							regx2, regx1));	      return		force_reg (Pmode,			   gen_rtx_PLUS (Pmode,					 gen_rtx_MULT (Pmode, regx2,						       XEXP (XEXP (x, 0), 1)),					 force_reg (Pmode, XEXP (y, 0))));	    }	  else if (GET_CODE (XEXP (y, 1)) == CONST_INT		   && INTVAL (XEXP (y, 1)) >= -4096		   && INTVAL (XEXP (y, 1)) <= 4095)	    {	      /* This is safe because of the guard page at the		 beginning and end of the data space.  Just		 return the original address.  */	      return orig;	    }	  else	    {	      /* Doesn't look like one we can optimize.  */	      regx1 = force_reg (Pmode, force_operand (XEXP (x, 0), 0));	      regy1 = force_reg (Pmode, force_operand (XEXP (y, 0), 0));	      regy2 = force_reg (Pmode, force_operand (XEXP (y, 1), 0));	      regx1 = force_reg (Pmode,				 gen_rtx_fmt_ee (GET_CODE (y), Pmode,						 regx1, regy2));	      return force_reg (Pmode, gen_rtx_PLUS (Pmode, regx1, regy1));	    }	}    }  return orig;}/* For the HPPA, REG and REG+CONST is cost 0   and addresses involving symbolic constants are cost 2.   PIC addresses are very expensive.   It is no coincidence that this has the same structure   as GO_IF_LEGITIMATE_ADDRESS.  */inthppa_address_cost (X)     rtx X;{  if (GET_CODE (X) == PLUS)      return 1;  else if (GET_CODE (X) == LO_SUM)    return 1;  else if (GET_CODE (X) == HIGH)    return 2;  return 4;}/* Ensure mode of ORIG, a REG rtx, is MODE.  Returns either ORIG or a   new rtx with the correct mode.  */static inline rtxforce_mode (mode, orig)     enum machine_mode mode;     rtx orig;

⌨️ 快捷键说明

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