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

📄 pa.c

📁 gcc库的原代码,对编程有很大帮助.
💻 C
📖 第 1 页 / 共 5 页
字号:
    }  else if (FP_REG_P (operands[1]))    {      output_asm_insn ("fstds%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.   Restriction: If the length argument is non-constant, alignment   must be 4.   OPERANDS[0] is the destination pointer as a REG, clobbered.   OPERANDS[1] is the source pointer as a REG, clobbered.   if SIZE_IS_CONSTANT     OPERANDS[2] is a register for temporary storage.     OPERANDS[4] is the size as a CONST_INT   else     OPERANDS[2] is a REG which will contain the size, clobbered.   OPERANDS[3] is a register for temporary storage.   OPERANDS[5] is the alignment safe to use, as a CONST_INT.  */char *output_block_move (operands, size_is_constant)     rtx *operands;     int size_is_constant;{  int align = INTVAL (operands[5]);  unsigned long n_bytes;  /* 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;  if (size_is_constant)    {      unsigned long offset;      rtx temp;      n_bytes = INTVAL (operands[4]);      if (n_bytes == 0)	return "";      if (align >= 4)	{	  /* Don't unroll too large blocks.  */	  if (n_bytes > 32)	    goto copy_with_loop;	  /* Read and store using two registers, and hide latency	     by deferring the stores until three instructions after	     the corresponding load.  The last load insn will read	     the entire word were the last bytes are, possibly past	     the end of the source block, but since loads are aligned,	     this is harmless.  */	  output_asm_insn ("ldws,ma 4(0,%1),%2", operands);	  for (offset = 4; offset < n_bytes; offset += 4)	    {	      output_asm_insn ("ldws,ma 4(0,%1),%3", operands);	      output_asm_insn ("stws,ma %2,4(0,%0)", operands);	      temp = operands[2];	      operands[2] = operands[3];	      operands[3] = temp;	    }	  if (n_bytes % 4 == 0)	    /* Store the last word.  */	    output_asm_insn ("stw %2,0(0,%0)", operands);	  else	    {	      /* Store the last, partial word.  */	      operands[4] = GEN_INT (n_bytes % 4);	      output_asm_insn ("stbys,e %2,%4(0,%0)", operands);	    }	  return "";	}      if (align >= 2 && n_bytes >= 2)	{	  output_asm_insn ("ldhs,ma 2(0,%1),%2", operands);	  for (offset = 2; offset + 2 <= n_bytes; offset += 2)	    {	      output_asm_insn ("ldhs,ma 2(0,%1),%3", operands);	      output_asm_insn ("sths,ma %2,2(0,%0)", operands);	      temp = operands[2];	      operands[2] = operands[3];	      operands[3] = temp;	    }	  if (n_bytes % 2 != 0)	    output_asm_insn ("ldb 0(0,%1),%3", operands);	  output_asm_insn ("sths,ma %2,2(0,%0)", operands);	  if (n_bytes % 2 != 0)	    output_asm_insn ("stb %3,0(0,%0)", operands);	  return "";	}      output_asm_insn ("ldbs,ma 1(0,%1),%2", operands);      for (offset = 1; offset + 1 <= n_bytes; offset += 1)	{	  output_asm_insn ("ldbs,ma 1(0,%1),%3", operands);	  output_asm_insn ("stbs,ma %2,1(0,%0)", operands);	  temp = operands[2];	  operands[2] = operands[3];	  operands[3] = temp;	}      output_asm_insn ("stb %2,0(0,%0)", operands);      return "";    }  if (align != 4)    abort(); copy_with_loop:  if (size_is_constant)    {      /* Size is compile-time determined, and also not	 very small (such small cases are handled above).  */      operands[4] = GEN_INT (n_bytes - 4);      output_asm_insn ("ldo %4(0),%2", operands);    }  else    {      /* Decrement counter by 4, and if it becomes negative, jump past the	 word copying loop.  */      output_asm_insn ("addib,<,n -4,%2,.+16", operands);    }  /* Copying loop.  Note that the first load is in the annulled delay slot     of addib.  Is it OK on PA to have a load in a delay slot, i.e. is a     possible page fault stopped in time?  */  output_asm_insn ("ldws,ma 4(0,%1),%3", operands);  output_asm_insn ("addib,>= -4,%2,.-4", operands);  output_asm_insn ("stws,ma %3,4(0,%0)", operands);  /* The counter is negative, >= -4.  The remaining number of bytes are     determined by the two least significant bits.  */  if (size_is_constant)    {      if (n_bytes % 4 != 0)	{	  /* Read the entire word of the source block tail.  */	  output_asm_insn ("ldw 0(0,%1),%3", operands);	  operands[4] = GEN_INT (n_bytes % 4);	  output_asm_insn ("stbys,e %3,%4(0,%0)", operands);	}    }  else    {      /* Add 4 to counter.  If it becomes zero, we're done.  */      output_asm_insn ("addib,=,n 4,%2,.+16", operands);      /* Read the entire word of the source block tail.  (Also this	 load is in an annulled delay slot.)  */      output_asm_insn ("ldw 0(0,%1),%3", operands);      /* Make %0 point at the first byte after the destination block.  */      output_asm_insn ("addl %2,%0,%0", operands);      /* Store the leftmost bytes, up to, but not including, the address	 in %0.  */      output_asm_insn ("stbys,e %3,0(0,%0)", operands);    }  return "";}/* 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 size_is_constant;  int align = INTVAL (XEXP (XVECEXP (pat, 0, 6), 0));  unsigned long n_bytes;  int insn_count = 0;  if (GET_CODE (XEXP (XVECEXP (pat, 0, 5), 0)) == CONST_INT)    {      size_is_constant = 1;      n_bytes = INTVAL (XEXP (XVECEXP (pat, 0, 5), 0));    }  else    {      size_is_constant = 0;      n_bytes = 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;  if (size_is_constant)    {      unsigned long offset;      if (n_bytes == 0)	return 0;      if (align >= 4)	{	  /* Don't unroll too large blocks.  */	  if (n_bytes > 32)	    goto copy_with_loop;	  /* first load */	  insn_count = 1;	  /* Count the unrolled insns.  */	  for (offset = 4; offset < n_bytes; offset += 4)	    insn_count += 2;	  /* Count last store or partial store.  */	  insn_count += 1;	  return insn_count * 4;	}      if (align >= 2 && n_bytes >= 2)	{	  /* initial load.  */	  insn_count = 1;	  /* Unrolled loop.  */	  for (offset = 2; offset + 2 <= n_bytes; offset += 2)	    insn_count += 2;	  /* ??? odd load/store */	  if (n_bytes % 2 != 0)	    insn_count += 2;	  /* ??? final store from loop.  */	  insn_count += 1;	  return insn_count * 4;	}      /* First load.  */      insn_count = 1;      /* The unrolled loop.  */      for (offset = 1; offset + 1 <= n_bytes; offset += 1)	insn_count += 2;      /* Final store.  */      insn_count += 1;      return insn_count * 4;    }  if (align != 4)    abort(); copy_with_loop:  /* setup for constant and non-constant case.  */  insn_count = 1;  /* The copying loop.  */  insn_count += 3;  /* The counter is negative, >= -4.  The remaining number of bytes are     determined by the two least significant bits.  */  if (size_is_constant)    {      if (n_bytes % 4 != 0)	insn_count += 2;    }  else    insn_count += 4;  return insn_count * 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.  */  fprintf (file, "\t.STRING \"");  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)	{	  fprintf (file, "\"\n\t.STRING \"");	  chars_output = 0;	}      fwrite (partial_output, 1, co, file);      chars_output += co;      co = 0;    }

⌨️ 快捷键说明

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