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

📄 pa.c

📁 linux下的gcc编译器
💻 C
📖 第 1 页 / 共 5 页
字号:
	  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;    case PLUS_EXPR:    case MINUS_EXPR:      reloc = reloc_needed (TREE_OPERAND (exp, 0));      reloc |= reloc_needed (TREE_OPERAND (exp, 1));      break;    case NOP_EXPR:    case CONVERT_EXPR:    case NON_LVALUE_EXPR:      reloc = reloc_needed (TREE_OPERAND (exp, 0));      break;    case CONSTRUCTOR:      {	register tree link;	for (link = CONSTRUCTOR_ELTS (exp); link; link = TREE_CHAIN (link))	  if (TREE_VALUE (link) != 0)	    reloc |= reloc_needed (TREE_VALUE (link));      }      break;    case ERROR_MARK:      break;    default:      break;    }  return reloc;}/* Does operand (which is a symbolic_operand) live in text space?   If so, SYMBOL_REF_FLAG, which is set by pa_encode_section_info,   will be true.  */intread_only_operand (operand, mode)     rtx operand;     enum machine_mode mode ATTRIBUTE_UNUSED;{  if (GET_CODE (operand) == CONST)    operand = XEXP (XEXP (operand, 0), 0);  if (flag_pic)    {      if (GET_CODE (operand) == SYMBOL_REF)	return SYMBOL_REF_FLAG (operand) && !CONSTANT_POOL_ADDRESS_P (operand);    }  else    {      if (GET_CODE (operand) == SYMBOL_REF)	return SYMBOL_REF_FLAG (operand) || CONSTANT_POOL_ADDRESS_P (operand);    }  return 1;}/* Return the best assembler insn template   for moving operands[1] into operands[0] as a fullword.   */const char *singlemove_string (operands)     rtx *operands;{  HOST_WIDE_INT intval;  if (GET_CODE (operands[0]) == MEM)    return "stw %r1,%0";  if (GET_CODE (operands[1]) == MEM)    return "ldw %1,%0";  if (GET_CODE (operands[1]) == CONST_DOUBLE)    {      long i;      REAL_VALUE_TYPE d;      if (GET_MODE (operands[1]) != SFmode)	abort ();      /* Translate the CONST_DOUBLE to a CONST_INT with the same target	 bit pattern.  */      REAL_VALUE_FROM_CONST_DOUBLE (d, operands[1]);      REAL_VALUE_TO_TARGET_SINGLE (d, i);      operands[1] = GEN_INT (i);      /* Fall through to CONST_INT case.  */    }  if (GET_CODE (operands[1]) == CONST_INT)    {      intval = INTVAL (operands[1]);      if (VAL_14_BITS_P (intval))	return "ldi %1,%0";      else if ((intval & 0x7ff) == 0)	return "ldil L'%1,%0";      else if (zdepi_cint_p (intval))	return "{zdepi %Z1,%0|depwi,z %Z1,%0}";      else	return "ldil L'%1,%0\n\tldo R'%1(%0),%0";    }  return "copy %1,%0";}/* Compute position (in OP[1]) and width (in OP[2])   useful for copying IMM to a register using the zdepi   instructions.  Store the immediate value to insert in OP[0].  */static voidcompute_zdepwi_operands (imm, op)     unsigned HOST_WIDE_INT imm;     unsigned *op;{  int lsb, len;  /* Find the least significant set bit in IMM.  */  for (lsb = 0; lsb < 32; lsb++)    {      if ((imm & 1) != 0)        break;      imm >>= 1;    }  /* Choose variants based on *sign* of the 5-bit field.  */  if ((imm & 0x10) == 0)    len = (lsb <= 28) ? 4 : 32 - lsb;  else    {      /* Find the width of the bitstring in IMM.  */      for (len = 5; len < 32; len++)	{	  if ((imm & (1 << len)) == 0)	    break;	}      /* Sign extend IMM as a 5-bit value.  */      imm = (imm & 0xf) - 0x10;    }  op[0] = imm;  op[1] = 31 - lsb;  op[2] = len;}/* Compute position (in OP[1]) and width (in OP[2])   useful for copying IMM to a register using the depdi,z   instructions.  Store the immediate value to insert in OP[0].  */voidcompute_zdepdi_operands (imm, op)     unsigned HOST_WIDE_INT imm;     unsigned *op;{  HOST_WIDE_INT lsb, len;  /* Find the least significant set bit in IMM.  */  for (lsb = 0; lsb < HOST_BITS_PER_WIDE_INT; lsb++)    {      if ((imm & 1) != 0)        break;      imm >>= 1;    }  /* Choose variants based on *sign* of the 5-bit field.  */  if ((imm & 0x10) == 0)    len = ((lsb <= HOST_BITS_PER_WIDE_INT - 4)	   ? 4 : HOST_BITS_PER_WIDE_INT - lsb);  else    {      /* Find the width of the bitstring in IMM.  */      for (len = 5; len < HOST_BITS_PER_WIDE_INT; len++)	{	  if ((imm & ((unsigned HOST_WIDE_INT) 1 << len)) == 0)	    break;	}      /* Sign extend IMM as a 5-bit value.  */      imm = (imm & 0xf) - 0x10;    }  op[0] = imm;  op[1] = 63 - lsb;  op[2] = len;}/* Output assembler code to perform a doubleword move insn   with operands OPERANDS.  */const char *output_move_double (operands)     rtx *operands;{  enum { REGOP, OFFSOP, MEMOP, CNSTOP, RNDOP } optype0, optype1;  rtx latehalf[2];  rtx addreg0 = 0, addreg1 = 0;  /* First classify both operands.  */  if (REG_P (operands[0]))    optype0 = REGOP;  else if (offsettable_memref_p (operands[0]))    optype0 = OFFSOP;  else if (GET_CODE (operands[0]) == MEM)    optype0 = MEMOP;  else    optype0 = RNDOP;  if (REG_P (operands[1]))    optype1 = REGOP;  else if (CONSTANT_P (operands[1]))    optype1 = CNSTOP;  else if (offsettable_memref_p (operands[1]))    optype1 = OFFSOP;  else if (GET_CODE (operands[1]) == MEM)    optype1 = MEMOP;  else    optype1 = RNDOP;  /* Check for the cases that the operand constraints are not     supposed to allow to happen.  Abort if we get one,     because generating code for these cases is painful.  */  if (optype0 != REGOP && optype1 != REGOP)    abort ();   /* Handle auto decrementing and incrementing loads and stores     specifically, since the structure of the function doesn't work     for them without major modification.  Do it better when we learn     this port about the general inc/dec addressing of PA.     (This was written by tege.  Chide him if it doesn't work.)  */  if (optype0 == MEMOP)    {      /* We have to output the address syntax ourselves, since print_operand	 doesn't deal with the addresses we want to use.  Fix this later.  */      rtx addr = XEXP (operands[0], 0);      if (GET_CODE (addr) == POST_INC || GET_CODE (addr) == POST_DEC)	{	  rtx high_reg = gen_rtx_SUBREG (SImode, operands[1], 0);	  operands[0] = XEXP (addr, 0);	  if (GET_CODE (operands[1]) != REG || GET_CODE (operands[0]) != REG)	    abort ();	  if (!reg_overlap_mentioned_p (high_reg, addr))	    {	      /* No overlap between high target register and address		 register.  (We do this in a non-obvious way to		 save a register file writeback)  */	      if (GET_CODE (addr) == POST_INC)		return "{stws|stw},ma %1,8(%0)\n\tstw %R1,-4(%0)";	      return "{stws|stw},ma %1,-8(%0)\n\tstw %R1,12(%0)";	    }	  else	    abort ();	}      else if (GET_CODE (addr) == PRE_INC || GET_CODE (addr) == PRE_DEC)	{	  rtx high_reg = gen_rtx_SUBREG (SImode, operands[1], 0);	  operands[0] = XEXP (addr, 0);	  if (GET_CODE (operands[1]) != REG || GET_CODE (operands[0]) != REG)	    abort ();	  if (!reg_overlap_mentioned_p (high_reg, addr))	    {	      /* No overlap between high target register and address		 register.  (We do this in a non-obvious way to		 save a register file writeback)  */	      if (GET_CODE (addr) == PRE_INC)		return "{stws|stw},mb %1,8(%0)\n\tstw %R1,4(%0)";	      return "{stws|stw},mb %1,-8(%0)\n\tstw %R1,4(%0)";	    }	  else	    abort ();	}    }  if (optype1 == MEMOP)    {      /* We have to output the address syntax ourselves, since print_operand	 doesn't deal with the addresses we want to use.  Fix this later.  */      rtx addr = XEXP (operands[1], 0);      if (GET_CODE (addr) == POST_INC || GET_CODE (addr) == POST_DEC)	{	  rtx high_reg = gen_rtx_SUBREG (SImode, operands[0], 0);	  operands[1] = XEXP (addr, 0);	  if (GET_CODE (operands[0]) != REG || GET_CODE (operands[1]) != REG)	    abort ();	  if (!reg_overlap_mentioned_p (high_reg, addr))	    {	      /* No overlap between high target register and address		 register.  (We do this in a non-obvious way to		 save a register file writeback)  */	      if (GET_CODE (addr) == POST_INC)		return "{ldws|ldw},ma 8(%1),%0\n\tldw -4(%1),%R0";	      return "{ldws|ldw},ma -8(%1),%0\n\tldw 12(%1),%R0";	    }	  else	    {	      /* This is an undefined situation.  We should load into the		 address register *and* update that register.  Probably		 we don't need to handle this at all.  */	      if (GET_CODE (addr) == POST_INC)		return "ldw 4(%1),%R0\n\t{ldws|ldw},ma 8(%1),%0";	      return "ldw 4(%1),%R0\n\t{ldws|ldw},ma -8(%1),%0";	    }	}      else if (GET_CODE (addr) == PRE_INC || GET_CODE (addr) == PRE_DEC)	{	  rtx high_reg = gen_rtx_SUBREG (SImode, operands[0], 0);	  operands[1] = XEXP (addr, 0);	  if (GET_CODE (operands[0]) != REG || GET_CODE (operands[1]) != REG)	    abort ();	  if (!reg_overlap_mentioned_p (high_reg, addr))	    {	      /* No overlap between high target register and address		 register.  (We do this in a non-obvious way to		 save a register file writeback)  */	      if (GET_CODE (addr) == PRE_INC)		return "{ldws|ldw},mb 8(%1),%0\n\tldw 4(%1),%R0";	      return "{ldws|ldw},mb -8(%1),%0\n\tldw 4(%1),%R0";	    }	  else	    {	      /* This is an undefined situation.  We should load into the		 address register *and* update that register.  Probably		 we don't need to handle this at all.  */	      if (GET_CODE (addr) == PRE_INC)		return "ldw 12(%1),%R0\n\t{ldws|ldw},mb 8(%1),%0";	      return "ldw -4(%1),%R0\n\t{ldws|ldw},mb -8(%1),%0";	    }	}      else if (GET_CODE (addr) == PLUS	       && GET_CODE (XEXP (addr, 0)) == MULT)	{	  rtx high_reg = gen_rtx_SUBREG (SImode, operands[0], 0);	  if (!reg_overlap_mentioned_p (high_reg, addr))	    {	      rtx xoperands[3];	      xoperands[0] = high_reg;	      xoperands[1] = XEXP (addr, 1);	      xoperands[2] = XEXP (XEXP (addr, 0), 0);	      xoperands[3] = XEXP (XEXP (addr, 0), 1);	      output_asm_insn ("{sh%O3addl %2,%1,%0|shladd,l %2,%O3,%1,%0}",			       xoperands);	      r

⌨️ 快捷键说明

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