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

📄 rs6000.c

📁 gcc库的原代码,对编程有很大帮助.
💻 C
📖 第 1 页 / 共 5 页
字号:
      /* If the high bit is set and the low bit is not, the value is zero.	 If the high bit is zero, the value is the first 1 bit we find from	 the left.  */      if (val < 0 && (val & 1) == 0)	{	  fprintf (file, "0");	  return;	}      else if (val >= 0)	{	  for (i = 1; i < 32; i++)	    if ((val <<= 1) < 0)	      break;	  fprintf (file, "%d", i);	  return;	}	        /* Otherwise, look for the first 0 bit from the right.  The result is its	 number plus 1. We know the low-order bit is one.  */      for (i = 0; i < 32; i++)	if (((val >>= 1) & 1) == 0)	  break;      /* If we ended in ...01, I would be 0.  The correct value is 31, so	 we want 31 - i.  */      fprintf (file, "%d", 31 - i);      return;    case 'M':      /* ME value for a mask operand.  */      if (! mask_operand (x, VOIDmode))	output_operand_lossage ("invalid %%m value");      val = INT_LOWPART (x);      /* If the low bit is set and the high bit is not, the value is 31.	 If the low bit is zero, the value is the first 1 bit we find from	 the right.  */      if ((val & 1) && val >= 0)	{	  fputs ("31", file);	  return;	}      else if ((val & 1) == 0)	{	  for (i = 0; i < 32; i++)	    if ((val >>= 1) & 1)	      break;	  /* If we had ....10, I would be 0.  The result should be	     30, so we need 30 - i.  */	  fprintf (file, "%d", 30 - i);	  return;	}	        /* Otherwise, look for the first 0 bit from the left.  The result is its	 number minus 1. We know the high-order bit is one.  */      for (i = 0; i < 32; i++)	if ((val <<= 1) >= 0)	  break;      fprintf (file, "%d", i);      return;    case 'N':      /* Write the number of elements in the vector times 4.  */      if (GET_CODE (x) != PARALLEL)	output_operand_lossage ("invalid %%N value");      fprintf (file, "%d", XVECLEN (x, 0) * 4);      return;    case 'O':      /* Similar, but subtract 1 first.  */      if (GET_CODE (x) != PARALLEL)	output_operand_lossage ("invalid %%N value");      fprintf (file, "%d", (XVECLEN (x, 0) - 1) * 4);      return;    case 'p':      /* X is a CONST_INT that is a power of two.  Output the logarithm.  */      if (! INT_P (x)	  || (i = exact_log2 (INT_LOWPART (x))) < 0)	output_operand_lossage ("invalid %%p value");      fprintf (file, "%d", i);      return;    case 'P':      /* The operand must be an indirect memory reference.  The result	 is the register number. */      if (GET_CODE (x) != MEM || GET_CODE (XEXP (x, 0)) != REG	  || REGNO (XEXP (x, 0)) >= 32)	output_operand_lossage ("invalid %%P value");      fprintf (file, "%d", REGNO (XEXP (x, 0)));      return;    case 'R':      /* X is a CR register.  Print the mask for `mtcrf'.  */      if (GET_CODE (x) != REG || ! CR_REGNO_P (REGNO (x)))	output_operand_lossage ("invalid %%R value");      else	fprintf (file, "%d", 128 >> (REGNO (x) - 68));      return;    case 's':      /* Low 5 bits of 32 - value */      if (! INT_P (x))	output_operand_lossage ("invalid %%s value");      fprintf (file, "%d", (32 - INT_LOWPART (x)) & 31);      return;    case 't':      /* Write 12 if this jump operation will branch if true, 4 otherwise. 	 All floating-point operations except NE branch true and integer	 EQ, LT, GT, LTU and GTU also branch true.  */      if (GET_RTX_CLASS (GET_CODE (x)) != '<')	output_operand_lossage ("invalid %%t value");      else if ((GET_MODE (XEXP (x, 0)) == CCFPmode		&& GET_CODE (x) != NE)	       || GET_CODE (x) == EQ	       || GET_CODE (x) == LT || GET_CODE (x) == GT	       || GET_CODE (x) == LTU || GET_CODE (x) == GTU)	fputs ("12", file);      else	putc ('4', file);      return;          case 'T':      /* Opposite of 't': write 4 if this jump operation will branch if true,	 12 otherwise.   */      if (GET_RTX_CLASS (GET_CODE (x)) != '<')	output_operand_lossage ("invalid %%t value");      else if ((GET_MODE (XEXP (x, 0)) == CCFPmode		&& GET_CODE (x) != NE)	       || GET_CODE (x) == EQ	       || GET_CODE (x) == LT || GET_CODE (x) == GT	       || GET_CODE (x) == LTU || GET_CODE (x) == GTU)	putc ('4', file);      else	fputs ("12", file);      return;          case 'u':      /* High-order 16 bits of constant.  */      if (! INT_P (x))	output_operand_lossage ("invalid %%u value");      fprintf (file, "0x%x", (INT_LOWPART (x) >> 16) & 0xffff);      return;    case 'U':      /* Print `u' if this has an auto-increment or auto-decrement.  */      if (GET_CODE (x) == MEM	  && (GET_CODE (XEXP (x, 0)) == PRE_INC	      || GET_CODE (XEXP (x, 0)) == PRE_DEC))	putc ('u', file);      return;    case 'w':      /* If constant, low-order 16 bits of constant, signed.  Otherwise, write	 normally.  */      if (INT_P (x))	fprintf (file, "%d",		 (INT_LOWPART (x) & 0xffff) - 2 * (INT_LOWPART (x) & 0x8000));      else	print_operand (file, x, 0);      return;    case 'W':      /* If constant, low-order 16 bits of constant, unsigned.	 Otherwise, write normally.  */      if (INT_P (x))	fprintf (file, "%d", INT_LOWPART (x) & 0xffff);      else	print_operand (file, x, 0);      return;    case 'X':      if (GET_CODE (x) == MEM	  && LEGITIMATE_INDEXED_ADDRESS_P (XEXP (x, 0)))	putc ('x', file);      return;    case 'Y':      /* Like 'L', for third word of TImode  */      if (GET_CODE (x) == REG)	fprintf (file, "%d", REGNO (x) + 2);      else if (GET_CODE (x) == MEM)	{	  if (GET_CODE (XEXP (x, 0)) == PRE_INC	      || GET_CODE (XEXP (x, 0)) == PRE_DEC)	    output_address (plus_constant (XEXP (XEXP (x, 0), 0), 8));	  else	    output_address (plus_constant (XEXP (x, 0), 8));	}      return;			        case 'z':      /* X is a SYMBOL_REF.  Write out the name preceded by a	 period and without any trailing data in brackets.  Used for function	 names.  If we are configured for System V (or the embedded ABI) on	 the PowerPC, do not emit the period, since those systems do not use	 TOCs and the like.  */      if (GET_CODE (x) != SYMBOL_REF)	abort ();#ifndef USING_SVR4_H      putc ('.', file);#endif      RS6000_OUTPUT_BASENAME (file, XSTR (x, 0));      return;    case 'Z':      /* Like 'L', for last word of TImode.  */      if (GET_CODE (x) == REG)	fprintf (file, "%d", REGNO (x) + 3);      else if (GET_CODE (x) == MEM)	{	  if (GET_CODE (XEXP (x, 0)) == PRE_INC	      || GET_CODE (XEXP (x, 0)) == PRE_DEC)	    output_address (plus_constant (XEXP (XEXP (x, 0), 0), 12));	  else	    output_address (plus_constant (XEXP (x, 0), 12));	}      return;			        case 0:      if (GET_CODE (x) == REG)	fprintf (file, "%s", reg_names[REGNO (x)]);      else if (GET_CODE (x) == MEM)	{	  /* We need to handle PRE_INC and PRE_DEC here, since we need to	     know the width from the mode.  */	  if (GET_CODE (XEXP (x, 0)) == PRE_INC)	    fprintf (file, "%d(%d)", GET_MODE_SIZE (GET_MODE (x)),		     REGNO (XEXP (XEXP (x, 0), 0)));	  else if (GET_CODE (XEXP (x, 0)) == PRE_DEC)	    fprintf (file, "%d(%d)", - GET_MODE_SIZE (GET_MODE (x)),		     REGNO (XEXP (XEXP (x, 0), 0)));	  else	    output_address (XEXP (x, 0));	}      else	output_addr_const (file, x);      return;    default:      output_operand_lossage ("invalid %%xn code");    }}/* Print the address of an operand.  */voidprint_operand_address (file, x)     FILE *file;     register rtx x;{  if (GET_CODE (x) == REG)    fprintf (file, "0(%s)", reg_names[ REGNO (x) ]);  else if (GET_CODE (x) == SYMBOL_REF || GET_CODE (x) == CONST)    {      output_addr_const (file, x);      /* When TARGET_MINIMAL_TOC, use the indirected toc table pointer instead	 of the toc pointer.  */#ifdef TARGET_NO_TOC      if (TARGET_NO_TOC)	;      else#endif	fprintf (file, "(%s)", reg_names[ TARGET_MINIMAL_TOC ? 30 : 2 ]);    }  else if (GET_CODE (x) == PLUS && GET_CODE (XEXP (x, 1)) == REG)    {      if (REGNO (XEXP (x, 0)) == 0)	fprintf (file, "%s,%s", reg_names[ REGNO (XEXP (x, 1)) ],		 reg_names[ REGNO (XEXP (x, 0)) ]);      else	fprintf (file, "%s,%s", reg_names[ REGNO (XEXP (x, 0)) ],		 reg_names[ REGNO (XEXP (x, 1)) ]);    }  else if (GET_CODE (x) == PLUS && GET_CODE (XEXP (x, 1)) == CONST_INT)    fprintf (file, "%d(%s)", INTVAL (XEXP (x, 1)), reg_names[ REGNO (XEXP (x, 0)) ]);  else if (TARGET_ELF && !TARGET_64BIT && GET_CODE (x) == LO_SUM	   && GET_CODE (XEXP (x, 0)) == REG && CONSTANT_P (XEXP (x, 1)))    {      output_addr_const (file, XEXP (x, 1));      fprintf (file, "@l(%s)", reg_names[ REGNO (XEXP (x, 0)) ]);    }  else    abort ();}/* This page contains routines that are used to determine what the function   prologue and epilogue code will do and write them out.  *//*  Return the first fixed-point register that is required to be saved. 32 if    none.  */intfirst_reg_to_save (){  int first_reg;  /* Find lowest numbered live register.  */  for (first_reg = 13; first_reg <= 31; first_reg++)    if (regs_ever_live[first_reg])      break;  /* If profiling, then we must save/restore every register that contains     a parameter before/after the .mcount call.  Use registers from 30 down     to 23 to do this.  Don't use the frame pointer in reg 31.     For now, save enough room for all of the parameter registers.  */#ifndef USING_SVR4_H  if (profile_flag)    if (first_reg > 23)      first_reg = 23;#endif  return first_reg;}/* Similar, for FP regs.  */intfirst_fp_reg_to_save (){  int first_reg;  /* Find lowest numbered live register.  */  for (first_reg = 14 + 32; first_reg <= 63; first_reg++)    if (regs_ever_live[first_reg])      break;  return first_reg;}/* Return non-zero if this function makes calls.  */intrs6000_makes_calls (){  rtx insn;  /* If we are profiling, we will be making a call to mcount.  */  if (profile_flag)    return 1;  for (insn = get_insns (); insn; insn = next_insn (insn))    if (GET_CODE (insn) == CALL_INSN)      return 1;  return 0;}/* Calculate the stack information for the current function.  This is   complicated by having two separate calling sequences, the AIX calling   sequence and the V.4 calling sequence.   AIX stack frames look like:	SP---->	+---------------------------------------+		| back chain to caller			| 0		+---------------------------------------+		| saved CR				| 4		+---------------------------------------+		| saved LR				| 8		+---------------------------------------+		| reserved for compilers		| 12		+---------------------------------------+		| reserved for binders			| 16		+---------------------------------------+		| saved TOC pointer			| 20		+---------------------------------------+		| Parameter save area (P)		| 24		+---------------------------------------+		| Alloca space (A)			| 24+P		+---------------------------------------+		| Local variable space (L)		| 24+P+A		+---------------------------------------+		| Save area for GP registers (G)	| 24+P+A+L		+---------------------------------------+		| Save area for FP registers (F)	| 24+P+A+L+G		+---------------------------------------+	old SP->| back chain to caller's caller		|		+---------------------------------------+   V.4 stack frames look like:	SP---->	+---------------------------------------+		| back chain to caller			| 0		+---------------------------------------+		| caller's saved LR			| 4		+---------------------------------------+		| Parameter save area (P)		| 8		+---------------------------------------+		| Alloca space (A)			| 8+P		+---------------------------------------+		| Varargs save area (V)			| 8+P+A		+---------------------------------------+		| Local variable space (L)		| 8+P+A+V		+---------------------------------------+		| saved CR (C)				| 8+P+A+V+L		+---------------------------------------+		| Save area for GP registers (G)	| 8+P+A+V+L+C		+---------------------------------------+		| Save area for FP registers (F)	| 8+P+A+V+L+C+G		+---------------------------------------+	old SP->| back chain to caller's caller		|		+---------------------------------------+*/rs6000_stack_t *rs6000_stack_info (){  static rs6000_stack_t info, zero_info;  rs6000_stack_t *info_ptr = &info;  int reg_size = TARGET_64BIT ? 8 : 4;  enum rs6000_abi abi;  /* Zero all fields portably */  info = zero_info;  /* Select which calling sequence */#ifdef TARGET_V4_CALLS  if (TARGET_V4_CALLS)    abi = ABI_V4;  else#endif    abi = ABI_AIX;  info_ptr->abi = abi;  /* Calculate which registers need to be saved & save area size */  info_ptr->first_gp_reg_save = first_reg_to_save ();  info_ptr->gp_size = reg_size * (32 - info_ptr->first_gp_reg_save);  info_ptr->first_fp_reg_save = first_fp_reg_to_save ();  info_ptr->fp_size = 8 * (64 - info_ptr->first_fp_reg_save);  /* Does this function call anything? */  info_ptr->calls_p = rs6000_makes_calls ();  /* Determine if we need to save the link register */  if (regs_ever_live[65] || profile_flag#ifdef TARGET_RELOCATABLE      || (TARGET_RELOCATABLE && (get_pool_size () != 0))#endif      || (info_ptr->first_fp_reg_save != 64	  && !FP_SAVE_INLINE (info_ptr->first_fp_reg_save))      || (abi == ABI_V4 && current_function_calls_alloca)      || info_ptr->calls_p)    {      info_ptr->lr_save_p = 1;      regs_ever_live[65] = 1;    }  /* Determine if we need to save the condition code registers */  if (regs_ever_live[70] || regs_ever_live[71] || regs_ever_live[72])    {      info_ptr->cr_save_p = 1;      if (abi == ABI_V4)	info_ptr->cr_size = reg_size;    }  /* Determine various sizes */  info_ptr->reg_size     = reg_size;  info_ptr->fixed_size   = RS6000_SAVE_AREA;  info_ptr->varargs_size = RS6000_VARARG

⌨️ 快捷键说明

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