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

📄 pa.c

📁 gcc库的原代码,对编程有很大帮助.
💻 C
📖 第 1 页 / 共 5 页
字号:
     enum machine_mode mode;{  return register_operand (op, mode) || lhs_lshift_cint_operand (op, mode);}/* True iff OP is a CONST_INT of the forms 0...0xxxx or 0...01...1xxxx.   Such values can be the left hand side x in (x << r), using the zvdepi   instruction.  */intlhs_lshift_cint_operand (op, mode)     rtx op;     enum machine_mode mode;{  unsigned HOST_WIDE_INT x;  if (GET_CODE (op) != CONST_INT)    return 0;  x = INTVAL (op) >> 4;  return (x & (x + 1)) == 0;}intarith32_operand (op, mode)     rtx op;     enum machine_mode mode;{  return register_operand (op, mode) || GET_CODE (op) == CONST_INT;}intpc_or_label_operand (op, mode)     rtx op;     enum machine_mode mode;{  return (GET_CODE (op) == PC || GET_CODE (op) == LABEL_REF);}/* Legitimize PIC addresses.  If the address is already   position-independent, we return ORIG.  Newly generated   position-independent addresses go to REG.  If we need more   than one register, we lose.  */rtxlegitimize_pic_address (orig, mode, reg)     rtx orig, reg;     enum machine_mode mode;{  rtx pic_ref = orig;  /* Labels need special handling.  */  if (pic_label_operand (orig))    {      emit_insn (gen_pic_load_label (reg, orig));      current_function_uses_pic_offset_table = 1;      return reg;    }  if (GET_CODE (orig) == SYMBOL_REF)    {      if (reg == 0)	abort ();      if (flag_pic == 2)	{	  emit_insn (gen_pic2_highpart (reg, pic_offset_table_rtx, orig));	  pic_ref = gen_rtx (MEM, Pmode,			     gen_rtx (LO_SUM, Pmode, reg,				      gen_rtx (UNSPEC, SImode, gen_rtvec (1, orig), 0)));	}      else	pic_ref = gen_rtx (MEM, Pmode,			   gen_rtx (PLUS, Pmode, pic_offset_table_rtx, orig));      current_function_uses_pic_offset_table = 1;      RTX_UNCHANGING_P (pic_ref) = 1;      emit_move_insn (reg, pic_ref);      return reg;    }  else if (GET_CODE (orig) == CONST)    {      rtx base;      if (GET_CODE (XEXP (orig, 0)) == PLUS	  && XEXP (XEXP (orig, 0), 0) == pic_offset_table_rtx)	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_for_output (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;     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);  /* 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 = GET_MODE_CLASS (mode) == MODE_FLOAT ? 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 = gen_rtx (CONST, VOIDmode,				    gen_rtx (PLUS, Pmode,					     XEXP (x, 0),					     GEN_INT (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);    }  /* Try to arrange things so that indexing modes can be used, but     only do so if indexing is safe.     Indexing is safe when the second operand for the outer PLUS     is a REG, SUBREG, SYMBOL_REF or the like.     For 2.5, indexing is also safe for (plus (symbol_ref) (const_int))     if the integer is > 0.  */  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 = force_reg (Pmode, force_operand (XEXP (x, 1), 0));      reg2 = force_reg (Pmode,			force_operand (XEXP (XEXP (x, 0), 0), 0));      return force_reg (Pmode,		        gen_rtx (PLUS, Pmode,				 gen_rtx (MULT, Pmode, reg2,					  GEN_INT (val)),				 reg1));    }  /* Uh-oh.  We might have an address for x[n-100000].  This needs     special handling.  */  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))))    {      /* 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.	 For 2.5, it might be profitable to set things up so that we	 compute the raw (unscaled) index first, then use scaled indexing	 to access memory, or better yet have the MI parts of the compiler	 handle this.  */      rtx regx1, 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)	{	  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 (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;}/* Emit insns to move operands[1] into operands[0].   Return 1 if we have written out everything that needs to be done to   do the move.  Otherwise, return 0 and the caller will emit the move   normally.  */intemit_move_sequence (operands, mode, scratch_reg)     rtx *operands;     enum machine_mode mode;     rtx scratch_reg;{  register rtx operand0 = operands[0];  register rtx operand1 = operands[1];  /* Handle secondary reloads for loads/stores of FP registers from     REG+D addresses where D does not fit in 5 bits, including      (subreg (mem (addr)) cases.  */  if (fp_reg_operand (operand0, mode)      && ((GET_CODE (operand1) == MEM	   && ! memory_address_p (DFmode, XEXP (operand1, 0)))	  || ((GET_CODE (operand1) == SUBREG	       && GET_CODE (XEXP (operand1, 0)) == MEM	       && !memory_address_p (DFmode, XEXP (XEXP (operand1, 0), 0)))))      && scratch_reg)    {      if (GET_CODE (operand1) == SUBREG)	operand1 = XEXP (operand1, 0);      scratch_reg = gen_rtx (REG, SImode, REGNO (scratch_reg));      /* D might not fit in 14 bits either; for such cases load D into	 scratch reg.  */      if (!memory_address_p (SImode, XEXP (operand1, 0)))	{	  emit_move_insn (scratch_reg, XEXP (XEXP (operand1, 0), 1));	  emit_move_insn (scratch_reg, gen_rtx (GET_CODE (XEXP (operand1, 0)),						SImode,						XEXP (XEXP (operand1, 0), 0),						scratch_reg));	}      else	emit_move_insn (scratch_reg, XEXP (operand1, 0));      emit_insn (gen_rtx (SET, VOIDmode, operand0, gen_rtx (MEM, mode,							    scratch_reg)));      return 1;    }  else if (fp_reg_operand (operand1, mode)	   && ((GET_CODE (operand0) == MEM		&& ! memory_address_p (DFmode, XEXP (operand0, 0)))	       || ((GET_CODE (operand0) == SUBREG)		   && GET_CODE (XEXP (operand0, 0)) == MEM		   && !memory_address_p (DFmode, XEXP (XEXP (operand0, 0), 0))))	   && scratch_reg)    {      if (GET_CODE (operand0) == SUBREG)	operand0 = XEXP (operand0, 0);      scratch_reg = gen_rtx (REG, SImode, REGNO (scratch_reg));      /* D might not fit in 14 bits either; for such cases load D into	 scratch reg.  */      if (!memory_address_p (SImode, XEXP (operand0, 0)))	{	  emit_move_insn (scratch_reg, XEXP (XEXP (operand0, 0), 1));	  emit_move_insn (scratch_reg, gen_rtx (GET_CODE (XEXP (operand0, 0)),						SImode,						XEXP (XEXP (operand0, 0), 0),						scratch_reg));	}      else	emit_move_insn (scratch_reg, XEXP (operand0, 0));      emit_insn (gen_rtx (SET, VOIDmode, gen_rtx (MEM, mode, scratch_reg),			  operand1));      return 1;    }  /* Handle secondary reloads for loads of FP registers from constant     expressions by forcing the constant into memory.     use scratch_reg to hold the address of the memory location.     ??? The proper fix is to change PREFERRED_RELOAD_CLASS to return     NO_REGS when presented with a const_int and an register class     containing only FP registers.  Doing so unfortunately creates     more problems than it solves.   Fix this for 2.5.  */  else if (fp_reg_operand (operand0, mode)	   && CONSTANT_P (operand1)	   && scratch_reg)    {      rtx xoperands[2];      /* Force the constant into memory and put the address of the	 memory location into scratch_reg.  */      xoperands[0] = scratch_reg;      xoperands[1] = XEXP (force_const_mem (mode, operand1), 0);      emit_move_sequence (xoperands, Pmode, 0);      /* Now load the destination register.  */      emit_insn (gen_rtx (SET, mode, operand0,			  gen_rtx (MEM, mode, scratch_reg)));      return 1;    }  /* Handle secondary reloads for SAR.  These occur when trying to load     the SAR from memory a FP register, or with a constant.  */  else if (GET_CODE (operand0) == REG	   && REGNO_REG_CLASS (REGNO (operand0)) == SHIFT_REGS	   && (GET_CODE (operand1) == MEM	       || GET_CODE (operand1) == CONST_INT	       || (GET_CODE (operand1) == REG		   && FP_REG_CLASS_P (REGNO_REG_CLASS (REGNO (operand1)))))	   && scratch_reg)    {      emit_move_insn (scratch_reg, operand1);      emit_move_insn (operand0, scratch_reg);      return 1;    }  /* Handle most common case: storing into a register.  */  else if (register_operand (operand0, mode))    {      if (register_operand (operand1, mode)	  || (GET_CODE (operand1) == CONST_INT && INT_14_BITS (operand1))	  || (operand1 == CONST0_RTX (mode))	  || (GET_CODE (operand1) == HIGH	      && !symbolic_operand (XEXP (operand1, 0), VOIDmode))	  /* Only `general_operands' can come here, so MEM is ok.  */	  || GET_CODE (operand1) == MEM)	{	  /* Run this case quickly.  */	  emit_insn (gen_rtx (SET, VOIDmode, operand0, operand1));	  return 1;	}    }  else if (GET_CODE (operand0) == MEM)    {      if (register_operand (operand1, mode) || operand1 == CONST0_RTX (mode))	{	  /* Run this case quickly.  */	  emit_insn (gen_rtx (SET, VOIDmode, operand0, operand1));	  return 1;	}      if (! (reload_in_progress || reload_completed))	{	  operands[0] = validize_mem (operand0);	  operands[1] = operand1 = force_reg (mode, operand1);	}    }  /* Simplify the source if we need to.  */  if ((GET_CODE (operand1) != HIGH && immediate_operand (operand1, mode))      || (GET_CODE (operand1) == HIGH	  && symbolic_operand (XEXP (operand1, 0), mode)))    {      int ishighonly = 0;      if (GET_CODE (operand1) == HIGH)	{	  ishighonly = 1;	  operand1 = XEXP (operand1, 0);	}      if (symbolic_operand (operand1, mode))	{

⌨️ 快捷键说明

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