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

📄 pa.c

📁 gcc3.2.1源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
    {      if (GET_CODE (operand1) == SUBREG)	operand1 = XEXP (operand1, 0);      /* SCRATCH_REG will hold an address and maybe the actual data.  We want	 it in WORD_MODE regardless of what mode it was originally given	 to us.  */      scratch_reg = force_mode (word_mode, scratch_reg);      /* D might not fit in 14 bits either; for such cases load D into	 scratch reg.  */      if (!memory_address_p (Pmode, XEXP (operand1, 0)))	{	  emit_move_insn (scratch_reg, XEXP (XEXP (operand1, 0), 1));	  emit_move_insn (scratch_reg, gen_rtx_fmt_ee (GET_CODE (XEXP (operand1, 0)),						       Pmode,						       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 will hold an address and maybe the actual data.  We want	 it in WORD_MODE regardless of what mode it was originally given	 to us.  */      scratch_reg = force_mode (word_mode, scratch_reg);      /* D might not fit in 14 bits either; for such cases load D into	 scratch reg.  */      if (!memory_address_p (Pmode, XEXP (operand0, 0)))	{	  emit_move_insn (scratch_reg, XEXP (XEXP (operand0, 0), 1));	  emit_move_insn (scratch_reg, gen_rtx_fmt_ee (GET_CODE (XEXP (operand0,								        0)),						       Pmode,						       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];      /* SCRATCH_REG will hold an address and maybe the actual data.  We want	 it in WORD_MODE regardless of what mode it was originally given	 to us.  */      scratch_reg = force_mode (word_mode, scratch_reg);      /* 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, FP register, or with a constant.  */  else if (GET_CODE (operand0) == REG	   && REGNO (operand0) < FIRST_PSEUDO_REGISTER	   && 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)    {      /* D might not fit in 14 bits either; for such cases load D into	 scratch reg.  */      if (GET_CODE (operand1) == MEM	  && !memory_address_p (Pmode, XEXP (operand1, 0)))	{	  /* We are reloading the address into the scratch register, so we	     want to make sure the scratch register is a full register.  */	  scratch_reg = force_mode (word_mode, scratch_reg);	  emit_move_insn (scratch_reg, XEXP (XEXP (operand1, 0), 1));	  emit_move_insn (scratch_reg, gen_rtx_fmt_ee (GET_CODE (XEXP (operand1,								        0)),						       Pmode,						       XEXP (XEXP (operand1, 0),						       0),						       scratch_reg));	  /* Now we are going to load the scratch register from memory,	     we want to load it in the same width as the original MEM,	     which must be the same as the width of the ultimate destination,	     OPERAND0.  */	  scratch_reg = force_mode (GET_MODE (operand0), scratch_reg);	  emit_move_insn (scratch_reg, gen_rtx_MEM (GET_MODE (operand0),						    scratch_reg));	}      else	{	  /* We want to load the scratch register using the same mode as	     the ultimate destination.  */	  scratch_reg = force_mode (GET_MODE (operand0), scratch_reg);	  emit_move_insn (scratch_reg, operand1);	}      /* And emit the insn to set the ultimate destination.  We know that	 the scratch register has the same mode as the destination at this	 point.  */      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	      && cint_ok_for_move (INTVAL (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 (mode == DFmode && operand1 == CONST0_RTX (mode)	  && !(reload_in_progress || reload_completed))	{	  rtx temp = gen_reg_rtx (DFmode);	  emit_insn (gen_rtx_SET (VOIDmode, temp, operand1));	  emit_insn (gen_rtx_SET (VOIDmode, operand0, temp));	  return 1;	}      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.     Note we do have to handle function labels here, even though we do     not consider them legitimate constants.  Loop optimizations can     call the emit_move_xxx with one as a source.  */  if ((GET_CODE (operand1) != HIGH && immediate_operand (operand1, mode))      || function_label_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))	{	  /* Argh.  The assembler and linker can't handle arithmetic	     involving plabels.	     So we force the plabel into memory, load operand0 from	     the memory location, then add in the constant part.  */	  if ((GET_CODE (operand1) == CONST	       && GET_CODE (XEXP (operand1, 0)) == PLUS	       && function_label_operand (XEXP (XEXP (operand1, 0), 0), Pmode))	      || function_label_operand (operand1, mode))	    {	      rtx temp, const_part;	      /* Figure out what (if any) scratch register to use.  */	      if (reload_in_progress || reload_completed)		{		  scratch_reg = scratch_reg ? scratch_reg : operand0;		  /* SCRATCH_REG will hold an address and maybe the actual		     data.  We want it in WORD_MODE regardless of what mode it		     was originally given to us.  */		  scratch_reg = force_mode (word_mode, scratch_reg);		}	      else if (flag_pic)		scratch_reg = gen_reg_rtx (Pmode);	      if (GET_CODE (operand1) == CONST)		{		  /* Save away the constant part of the expression.  */		  const_part = XEXP (XEXP (operand1, 0), 1);		  if (GET_CODE (const_part) != CONST_INT)		    abort ();		  /* Force the function label into memory.  */		  temp = force_const_mem (mode, XEXP (XEXP (operand1, 0), 0));		}	      else		{		  /* No constant part.  */		  const_part = NULL_RTX;		  /* Force the function label into memory.  */		  temp = force_const_mem (mode, operand1);		}	      /* Get the address of the memory location.  PIC-ify it if		 necessary.  */	      temp = XEXP (temp, 0);	      if (flag_pic)		temp = legitimize_pic_address (temp, mode, scratch_reg);	      /* Put the address of the memory location into our destination		 register.  */	      operands[1] = temp;	      emit_move_sequence (operands, mode, scratch_reg);	      /* Now load from the memory location into our destination		 register.  */	      operands[1] = gen_rtx_MEM (Pmode, operands[0]);	      emit_move_sequence (operands, mode, scratch_reg);	      /* And add back in the constant part.  */	      if (const_part != NULL_RTX)		expand_inc (operand0, const_part);	      return 1;	    }	  if (flag_pic)	    {	      rtx temp;	      if (reload_in_progress || reload_completed)		{		  temp = scratch_reg ? scratch_reg : operand0;		  /* TEMP will hold an address and maybe the actual		     data.  We want it in WORD_MODE regardless of what mode it		     was originally given to us.  */		  temp = force_mode (word_mode, temp);		}	      else		temp = gen_reg_rtx (Pmode);	      /* (const (plus (symbol) (const_int))) must be forced to		 memory during/after reload if the const_int will not fit		 in 14 bits.  */	      if (GET_CODE (operand1) == CONST		       && GET_CODE (XEXP (operand1, 0)) == PLUS		       && GET_CODE (XEXP (XEXP (operand1, 0), 1)) == CONST_INT		       && !INT_14_BITS (XEXP (XEXP (operand1, 0), 1))		       && (reload_completed || reload_in_progress)		       && flag_pic)		{		  operands[1] = force_const_mem (mode, operand1);		  operands[1] = legitimize_pic_address (XEXP (operands[1], 0),							mode, temp);		  emit_move_sequence (operands, mode, temp);		}	      else		{		  operands[1] = legitimize_pic_address (operand1, mode, temp);		  emit_insn (gen_rtx_SET (VOIDmode, operand0, operands[1]));		}	    }	  /* On the HPPA, references to data space are supposed to use dp,	     register 27, but showing it in the RTL inhibits various cse	     and loop optimizations.  */	  else	    {	      rtx temp, set;	      if (reload_in_progress || reload_completed)		{		  temp = scratch_reg ? scratch_reg : operand0;		  /* TEMP will hold an address and maybe the actual		     data.  We want it in WORD_MODE regardless of what mode it		     was originally given to us.  */		  temp = force_mode (word_mode, temp);		}	      else		temp = gen_reg_rtx (mode);	      /* Loading a SYMBOL_REF into a register makes that register		 safe to be used as the base in an indexed address.		 Don't mark hard registers though.  That loses.  */	      if (GET_CODE (operand0) == REG		  && REGNO (operand0) >= FIRST_PSEUDO_REGISTER)		REG_POINTER (operand0) = 1;	      if (REGNO (temp) >= FIRST_PSEUDO_REGISTER)		REG_POINTER (temp) = 1;	      if (ishighonly)		set = gen_rtx_SET (mode, operand0, temp);	      else		set = gen_rtx_SET (VOIDmode,				   operand0,				   gen_rtx_LO_SUM (mode, temp, operand1));	      emit_insn (gen_rtx_SET (VOIDmode,				      temp,				      gen_rtx_HIGH (mode, operand1)));	      emit_insn (set);	    }	  return 1;	}      else if (GET_CODE (operand1) != CONST_INT	       || ! cint_ok_for_move (INTVAL (operand1)))	{	  rtx extend = NULL_RTX;	  rtx temp;	  if (TARGET_64BIT && GET_CODE (operand1) == CONST_INT	      && HOST_BITS_PER_WIDE_INT > 32	      && GET_MODE_BITSIZE (GET_MODE (operand0)) > 32)	    {	      HOST_WIDE_INT val = INTVAL (operand1);	      HOST_WIDE_INT nval;	      /* Extract the low order 32 bits of the value and sign extend.		 If the new value is the same as the original value, we can		 can use the original value as-is.  If the new value is		 different, we use it and insert the most-significant 32-bits		 of the original value into the final result.  */	      nval = ((val & (((HOST_WIDE_INT) 2 << 31) - 1))		      ^ ((HOST_WIDE_INT) 1 << 31)) - ((HOST_WIDE_INT) 1 << 31);	      if (val != nval)		{#if HOST_BITS_PER_WIDE_INT > 32		  extend = GEN_INT (val >> 32);#endif		  operand1 = GEN_INT (nval);		}	    }	  if (reload_in_progress || reload_completed)	    temp = operand0;	  else	    temp = gen_reg_rtx (mode);	  /* We don't directly split DImode constants on 32-bit targets	     because PLUS uses an 11-bit immediate and the insn sequence	     generated is not as efficient as the one using HIGH/LO_SUM.  */	  if (GET_CODE (operand1) == CONST_INT	      && GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT)	    {	      /* Directly break constant into high and low parts.  This		 provides better optimization opportunities because various		 passes recognize constants split with PLUS but not LO_SUM.		 We use a 14-bit signed low part except when the addition		 of 0x4000 to the high part might change the sign of the		 high part.  */	      HOST_WIDE_INT value = INTVAL (operand1);	      HOST_WIDE_INT low = value & 0x3fff;	      HOST_WIDE_INT high = value & ~ 0x3fff;	      if (low >= 0x2000)		{		  if (high == 0x7fffc000 || (mode == HImode && high == 0x4000))		    high += 0x2000;		  else		    high += 0x4000;		}	      low = value - high;	      emit_insn (gen_rtx_SET (VOIDmode, temp, GEN_INT (high)));	      operands[1] = gen_rtx_PLUS (mode, temp, GEN_INT (low));	    }	  else	    {	      emit_insn (gen_rtx_SET (VOIDmode, temp,				      gen_rtx_HIGH (mode, operand1)));	      operands[1] = gen_rtx_LO_SUM (mode, temp, operand1);	    }	  emit_move_insn (operands[0], operands[1]);	  if (extend != NULL_RTX)	    emit_insn (gen_insv (operands[0], GEN_INT (32), const0_rtx,				 extend));	  return 1;	}    }  /* Now have insn-emit do whatever it normally does.  */  return 0;}/* Examine EXP and return nonzero if it contains an ADDR_EXPR (meaning   it will need a link/runtime reloc).  */intreloc_needed (exp)     tree exp;{  int reloc = 0;  switch (TREE_CODE (exp))    {    case ADDR_EXPR:      return 1;

⌨️ 快捷键说明

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