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

📄 pa.c

📁 gcc-2.95.3 Linux下最常用的C编译器
💻 C
📖 第 1 页 / 共 5 页
字号:
  if (optype0 == REGOP)    latehalf[0] = gen_rtx_REG (SImode, REGNO (operands[0]) + 1);  else if (optype0 == OFFSOP)    latehalf[0] = adj_offsettable_operand (operands[0], 4);  else    latehalf[0] = operands[0];  if (optype1 == REGOP)    latehalf[1] = gen_rtx_REG (SImode, REGNO (operands[1]) + 1);  else if (optype1 == OFFSOP)    latehalf[1] = adj_offsettable_operand (operands[1], 4);  else if (optype1 == CNSTOP)    split_double (operands[1], &operands[1], &latehalf[1]);  else    latehalf[1] = operands[1];  /* If the first move would clobber the source of the second one,     do them in the other order.     This can happen in two cases:	mem -> register where the first half of the destination register 	is the same register used in the memory's address.  Reload	can create such insns.	mem in this case will be either register indirect or register	indirect plus a valid offset. 	register -> register move where REGNO(dst) == REGNO(src + 1)	someone (Tim/Tege?) claimed this can happen for parameter loads.      Handle mem -> register case first.  */  if (optype0 == REGOP      && (optype1 == MEMOP || optype1 == OFFSOP)      && refers_to_regno_p (REGNO (operands[0]), REGNO (operands[0]) + 1,			    operands[1], 0))    {      /* Do the late half first.  */      if (addreg1)	output_asm_insn ("ldo 4(%0),%0", &addreg1);      output_asm_insn (singlemove_string (latehalf), latehalf);      /* Then clobber.  */      if (addreg1)	output_asm_insn ("ldo -4(%0),%0", &addreg1);      return singlemove_string (operands);    }  /* Now handle register -> register case.  */  if (optype0 == REGOP && optype1 == REGOP      && REGNO (operands[0]) == REGNO (operands[1]) + 1)    {      output_asm_insn (singlemove_string (latehalf), latehalf);      return singlemove_string (operands);    }  /* Normal case: do the two words, low-numbered first.  */  output_asm_insn (singlemove_string (operands), operands);  /* Make any unoffsettable addresses point at high-numbered word.  */  if (addreg0)    output_asm_insn ("ldo 4(%0),%0", &addreg0);  if (addreg1)    output_asm_insn ("ldo 4(%0),%0", &addreg1);  /* Do that word.  */  output_asm_insn (singlemove_string (latehalf), latehalf);  /* Undo the adds we just did.  */  if (addreg0)    output_asm_insn ("ldo -4(%0),%0", &addreg0);  if (addreg1)    output_asm_insn ("ldo -4(%0),%0", &addreg1);  return "";}char *output_fp_move_double (operands)     rtx *operands;{  if (FP_REG_P (operands[0]))    {      if (FP_REG_P (operands[1])	  || operands[1] == CONST0_RTX (GET_MODE (operands[0])))	output_asm_insn ("fcpy,dbl %f1,%0", operands);      else	output_asm_insn ("fldd%F1 %1,%0", operands);    }  else if (FP_REG_P (operands[1]))    {      output_asm_insn ("fstd%F0 %1,%0", operands);    }  else if (operands[1] == CONST0_RTX (GET_MODE (operands[0])))    {      if (GET_CODE (operands[0]) == REG)	{	  rtx xoperands[2];	  xoperands[1] = gen_rtx_REG (SImode, REGNO (operands[0]) + 1);	  xoperands[0] = operands[0];	  output_asm_insn ("copy %%r0,%0\n\tcopy %%r0,%1", xoperands);	}      /* This is a pain.  You have to be prepared to deal with an	 arbitrary address here including pre/post increment/decrement.	 so avoid this in the MD.  */      else	abort ();    }  else abort ();  return "";}/* Return a REG that occurs in ADDR with coefficient 1.   ADDR can be effectively incremented by incrementing REG.  */static rtxfind_addr_reg (addr)     rtx addr;{  while (GET_CODE (addr) == PLUS)    {      if (GET_CODE (XEXP (addr, 0)) == REG)	addr = XEXP (addr, 0);      else if (GET_CODE (XEXP (addr, 1)) == REG)	addr = XEXP (addr, 1);      else if (CONSTANT_P (XEXP (addr, 0)))	addr = XEXP (addr, 1);      else if (CONSTANT_P (XEXP (addr, 1)))	addr = XEXP (addr, 0);      else	abort ();    }  if (GET_CODE (addr) == REG)    return addr;  abort ();}/* Emit code to perform a block move.   OPERANDS[0] is the destination pointer as a REG, clobbered.   OPERANDS[1] is the source pointer as a REG, clobbered.   OPERANDS[2] is a register for temporary storage.   OPERANDS[4] is the size as a CONST_INT   OPERANDS[3] is a register for temporary storage.   OPERANDS[5] is the alignment safe to use, as a CONST_INT.    OPERANDS[6] is another temporary register.   */char *output_block_move (operands, size_is_constant)     rtx *operands;     int size_is_constant ATTRIBUTE_UNUSED;{  int align = INTVAL (operands[5]);  unsigned long n_bytes = INTVAL (operands[4]);  /* We can't move more than four bytes at a time because the PA     has no longer integer move insns.  (Could use fp mem ops?)  */  if (align > 4)    align = 4;  /* Note that we know each loop below will execute at least twice     (else we would have open-coded the copy).  */  switch (align)    {      case 4:	/* Pre-adjust the loop counter.  */	operands[4] = GEN_INT (n_bytes - 8);	output_asm_insn ("ldi %4,%2", operands);	/* Copying loop.  */	output_asm_insn ("ldws,ma 4(%1),%3", operands);	output_asm_insn ("ldws,ma 4(%1),%6", operands);	output_asm_insn ("stws,ma %3,4(%0)", operands);	output_asm_insn ("addib,>= -8,%2,.-12", operands);	output_asm_insn ("stws,ma %6,4(%0)", operands);	/* Handle the residual.  There could be up to 7 bytes of	   residual to copy!  */	if (n_bytes % 8 != 0)	  {	    operands[4] = GEN_INT (n_bytes % 4);	    if (n_bytes % 8 >= 4)	      output_asm_insn ("ldws,ma 4(%1),%3", operands);	    if (n_bytes % 4 != 0)	      output_asm_insn ("ldw 0(%1),%6", operands);	    if (n_bytes % 8 >= 4)	      output_asm_insn ("stws,ma %3,4(%0)", operands);	    if (n_bytes % 4 != 0)	      output_asm_insn ("stbys,e %6,%4(%0)", operands);	  }	return "";      case 2:	/* Pre-adjust the loop counter.  */	operands[4] = GEN_INT (n_bytes - 4);	output_asm_insn ("ldi %4,%2", operands);	/* Copying loop.  */	output_asm_insn ("ldhs,ma 2(%1),%3", operands);	output_asm_insn ("ldhs,ma 2(%1),%6", operands);	output_asm_insn ("sths,ma %3,2(%0)", operands);	output_asm_insn ("addib,>= -4,%2,.-12", operands);	output_asm_insn ("sths,ma %6,2(%0)", operands);	/* Handle the residual.  */	if (n_bytes % 4 != 0)	  {	    if (n_bytes % 4 >= 2)	      output_asm_insn ("ldhs,ma 2(%1),%3", operands);	    if (n_bytes % 2 != 0)	      output_asm_insn ("ldb 0(%1),%6", operands);	    if (n_bytes % 4 >= 2)	      output_asm_insn ("sths,ma %3,2(%0)", operands);	    if (n_bytes % 2 != 0)	      output_asm_insn ("stb %6,0(%0)", operands);	  }	return "";      case 1:	/* Pre-adjust the loop counter.  */	operands[4] = GEN_INT (n_bytes - 2);	output_asm_insn ("ldi %4,%2", operands);	/* Copying loop.  */	output_asm_insn ("ldbs,ma 1(%1),%3", operands);	output_asm_insn ("ldbs,ma 1(%1),%6", operands);	output_asm_insn ("stbs,ma %3,1(%0)", operands);	output_asm_insn ("addib,>= -2,%2,.-12", operands);	output_asm_insn ("stbs,ma %6,1(%0)", operands);	/* Handle the residual.  */	if (n_bytes % 2 != 0)	  {	    output_asm_insn ("ldb 0(%1),%3", operands);	    output_asm_insn ("stb %3,0(%0)", operands);	  }	return "";      default:	abort ();    }}/* Count the number of insns necessary to handle this block move.   Basic structure is the same as emit_block_move, except that we   count insns rather than emit them.  */intcompute_movstrsi_length (insn)     rtx insn;{  rtx pat = PATTERN (insn);  int align = INTVAL (XEXP (XVECEXP (pat, 0, 6), 0));  unsigned long n_bytes = INTVAL (XEXP (XVECEXP (pat, 0, 5), 0));  unsigned int n_insns = 0;  /* We can't move more than four bytes at a time because the PA     has no longer integer move insns.  (Could use fp mem ops?)  */  if (align > 4)    align = 4;  /* The basic copying loop.  */  n_insns = 6;  /* Residuals.  */  if (n_bytes % (2 * align) != 0)    {      if ((n_bytes % (2 * align)) >= align)	n_insns += 2;      if ((n_bytes % align) != 0)	n_insns += 2;    }  /* Lengths are expressed in bytes now; each insn is 4 bytes.  */  return n_insns * 4;}char *output_and (operands)     rtx *operands;{  if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) != 0)    {      unsigned HOST_WIDE_INT mask = INTVAL (operands[2]);      int ls0, ls1, ms0, p, len;      for (ls0 = 0; ls0 < 32; ls0++)	if ((mask & (1 << ls0)) == 0)	  break;      for (ls1 = ls0; ls1 < 32; ls1++)	if ((mask & (1 << ls1)) != 0)	  break;      for (ms0 = ls1; ms0 < 32; ms0++)	if ((mask & (1 << ms0)) == 0)	  break;      if (ms0 != 32)	abort();      if (ls1 == 32)	{	  len = ls0;	  if (len == 0)	    abort ();	  operands[2] = GEN_INT (len);	  return "extru %1,31,%2,%0";	}      else	{	  /* We could use this `depi' for the case above as well, but `depi'	     requires one more register file access than an `extru'.  */	  p = 31 - ls0;	  len = ls1 - ls0;	  operands[2] = GEN_INT (p);	  operands[3] = GEN_INT (len);	  return "depi 0,%2,%3,%0";	}    }  else    return "and %1,%2,%0";}char *output_ior (operands)     rtx *operands;{  unsigned HOST_WIDE_INT mask = INTVAL (operands[2]);  int bs0, bs1, p, len;  if (INTVAL (operands[2]) == 0)    return "copy %1,%0";  for (bs0 = 0; bs0 < 32; bs0++)    if ((mask & (1 << bs0)) != 0)      break;  for (bs1 = bs0; bs1 < 32; bs1++)    if ((mask & (1 << bs1)) == 0)      break;  if (bs1 != 32 && ((unsigned HOST_WIDE_INT) 1 << bs1) <= mask)    abort();  p = 31 - bs0;  len = bs1 - bs0;  operands[2] = GEN_INT (p);  operands[3] = GEN_INT (len);  return "depi -1,%2,%3,%0";}/* Output an ascii string.  */voidoutput_ascii (file, p, size)     FILE *file;     unsigned char *p;     int size;{  int i;  int chars_output;  unsigned char partial_output[16];	/* Max space 4 chars can occupy.   */  /* The HP assembler can only take strings of 256 characters at one     time.  This is a limitation on input line length, *not* the     length of the string.  Sigh.  Even worse, it seems that the     restriction is in number of input characters (see \xnn &     \whatever).  So we have to do this very carefully.  */  fputs ("\t.STRING \"", file);  chars_output = 0;  for (i = 0; i < size; i += 4)    {      int co = 0;      int io = 0;      for (io = 0, co = 0; io < MIN (4, size - i); io++)	{	  register unsigned int c = p[i + io];	  if (c == '\"' || c == '\\')	    partial_output[co++] = '\\';	  if (c >= ' ' && c < 0177)	    partial_output[co++] = c;	  else	    {	      unsigned int hexd;	      partial_output[co++] = '\\';	      partial_output[co++] = 'x';	      hexd =  c  / 16 - 0 + '0';	      if (hexd > '9')		hexd -= '9' - 'a' + 1;	      partial_output[co++] = hexd;	      hexd =  c % 16 - 0 + '0';	      if (hexd > '9')		hexd -= '9' - 'a' + 1;	      partial_output[co++] = hexd;	    }	}      if (chars_output + co > 243)	{	  fputs ("\"\n\t.STRING \"", file);	  chars_output = 0;	}      fwrite (partial_output, 1, co, file);      chars_output += co;      co = 0;    }  fputs ("\"\n", file);}/* Try to rewrite floating point comparisons & branches to avoid   useless add,tr insns.   CHECK_NOTES is nonzero if we should examine REG_DEAD notes   to see if FPCC is dead.  CHECK_NOTES is nonzero for the   first attempt to remove useless add,tr insns.  It is zero   for the second pass as reorg sometimes leaves bogus REG_DEAD   notes lying around.   When CHECK_NOTES is zero we can only eliminate add,tr insns   when there's a 1:1 correspondence between fcmp and ftest/fbranch   instructions.  */voidremove_useless_addtr_insns (insns, check_notes)     rtx insns;     int check_notes;{  rtx insn;  static int pass = 0;  /* This is fairly cheap, so always run it when optimizing.  */  if (optimize > 0)    {      int fcmp_count = 0;      int fbranch_count = 0;      /* Walk all the insns in this function looking for fcmp & fbranch	 instructions.  Keep track of how many of each we find.  */      insns = get_insns ();      for (insn = insns; insn; insn = next_insn (insn))	{	  rtx tmp;	 

⌨️ 快捷键说明

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