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

📄 final.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 5 页
字号:
	value = 2;	break;      case LTU:	/* Jump becomes no-op.  */	return -1;      }  if (cc_status.flags & (CC_Z_IN_NOT_N | CC_Z_IN_N))    switch (GET_CODE (cond))      {      case LE:      case LEU:      case GE:      case GEU:      case LT:      case LTU:      case GT:      case GTU:	abort ();      case NE:	PUT_CODE (cond, cc_status.flags & CC_Z_IN_N ? GE : LT);	value = 2;	break;      case EQ:	PUT_CODE (cond, cc_status.flags & CC_Z_IN_N ? LT : GE);	value = 2;	break;      }  if (cc_status.flags & CC_NOT_SIGNED)    /* The flags are valid if signed condition operators are converted       to unsigned.  */    switch (GET_CODE (cond))      {      case LE:	PUT_CODE (cond, LEU);	value = 2;	break;      case LT:	PUT_CODE (cond, LTU);	value = 2;	break;      case GT:	PUT_CODE (cond, GTU);	value = 2;	break;      case GE:	PUT_CODE (cond, GEU);	value = 2;	break;      }  return value;}#endif/* Report inconsistency between the assembler template and the operands.   In an `asm', it's the user's fault; otherwise, the compiler's fault.  */voidoutput_operand_lossage (str)     char *str;{  if (this_is_asm_operands)    error_for_asm (this_is_asm_operands, "invalid `asm': %s", str);  else    abort ();}/* Output of assembler code from a template, and its subroutines.  *//* Output text from TEMPLATE to the assembler output file,   obeying %-directions to substitute operands taken from   the vector OPERANDS.   %N (for N a digit) means print operand N in usual manner.   %lN means require operand N to be a CODE_LABEL or LABEL_REF      and print the label name with no punctuation.   %cN means require operand N to be a constant      and print the constant expression with no punctuation.   %aN means expect operand N to be a memory address      (not a memory reference!) and print a reference      to that address.   %nN means expect operand N to be a constant      and print a constant expression for minus the value      of the operand, with no other punctuation.  */voidoutput_asm_insn (template, operands)     char *template;     rtx *operands;{  register char *p;  register int c;  /* An insn may return a null string template     in a case where no assembler code is needed.  */  if (*template == 0)    return;  p = template;  putc ('\t', asm_out_file);#ifdef ASM_OUTPUT_OPCODE  ASM_OUTPUT_OPCODE (asm_out_file, p);#endif  while (c = *p++)    {#ifdef ASM_OUTPUT_OPCODE      if (c == '\n')	{	  putc (c, asm_out_file);	  while ((c = *p) == '\t')	    {	      putc (c, asm_out_file);	      p++;	    }	  ASM_OUTPUT_OPCODE (asm_out_file, p);	}      else#endif      if (c != '%')	putc (c, asm_out_file);      else	{	  /* %% outputs a single %.  */	  if (*p == '%')	    {	      p++;	      putc (c, asm_out_file);	    }	  /* %= outputs a number which is unique to each insn in the entire	     compilation.  This is useful for making local labels that are	     referred to more than once in a given insn.  */	  else if (*p == '=')	    {	      p++;	      fprintf (asm_out_file, "%d", insn_counter);	    }	  /* % followed by a letter and some digits	     outputs an operand in a special way depending on the letter.	     Letters `acln' are implemented directly.	     Other letters are passed to `output_operand' so that	     the PRINT_OPERAND macro can define them.  */	  else if ((*p >= 'a' && *p <= 'z')		   || (*p >= 'A' && *p <= 'Z'))	    {	      int letter = *p++;	      c = atoi (p);	      if (! (*p >= '0' && *p <= '9'))		output_operand_lossage ("operand number missing after %-letter");	      else if (this_is_asm_operands && c >= (unsigned) insn_noperands)		output_operand_lossage ("operand number out of range");	      else if (letter == 'l')		output_asm_label (operands[c]);	      else if (letter == 'a')		output_address (operands[c]);	      else if (letter == 'c')		{		  if (CONSTANT_ADDRESS_P (operands[c]))		    output_addr_const (asm_out_file, operands[c]);		  else		    output_operand (operands[c], 'c');		}	      else if (letter == 'n')		{		  if (GET_CODE (operands[c]) == CONST_INT)		    fprintf (asm_out_file,#if HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_INT			     "%d",#else			     "%ld",#endif			     - INTVAL (operands[c]));		  else		    {		      putc ('-', asm_out_file);		      output_addr_const (asm_out_file, operands[c]);		    }		}	      else		output_operand (operands[c], letter);	      while ((c = *p) >= '0' && c <= '9') p++;	    }	  /* % followed by a digit outputs an operand the default way.  */	  else if (*p >= '0' && *p <= '9')	    {	      c = atoi (p);	      if (this_is_asm_operands && c >= (unsigned) insn_noperands)		output_operand_lossage ("operand number out of range");	      else		output_operand (operands[c], 0);	      while ((c = *p) >= '0' && c <= '9') p++;	    }	  /* % followed by punctuation: output something for that	     punctuation character alone, with no operand.	     The PRINT_OPERAND macro decides what is actually done.  */#ifdef PRINT_OPERAND_PUNCT_VALID_P	  else if (PRINT_OPERAND_PUNCT_VALID_P (*p))	    output_operand (NULL_RTX, *p++);#endif	  else	    output_operand_lossage ("invalid %%-code");	}    }  if (flag_print_asm_name)    {      /* Annotate the assembly with a comment describing the pattern and	 alternative used.  */      if (debug_insn)	{	  register int num = INSN_CODE (debug_insn);	  fprintf (asm_out_file, " %s %d %s", 		   ASM_COMMENT_START, INSN_UID (debug_insn), insn_name[num]);	  if (insn_n_alternatives[num] > 1)	    fprintf (asm_out_file, "/%d", which_alternative + 1);	  /* Clear this so only the first assembler insn	     of any rtl insn will get the special comment for -dp.  */	  debug_insn = 0;	}    }  putc ('\n', asm_out_file);}/* Output a LABEL_REF, or a bare CODE_LABEL, as an assembler symbol.  */voidoutput_asm_label (x)     rtx x;{  char buf[256];  if (GET_CODE (x) == LABEL_REF)    ASM_GENERATE_INTERNAL_LABEL (buf, "L", CODE_LABEL_NUMBER (XEXP (x, 0)));  else if (GET_CODE (x) == CODE_LABEL)    ASM_GENERATE_INTERNAL_LABEL (buf, "L", CODE_LABEL_NUMBER (x));  else    output_operand_lossage ("`%l' operand isn't a label");  assemble_name (asm_out_file, buf);}/* Print operand X using machine-dependent assembler syntax.   The macro PRINT_OPERAND is defined just to control this function.   CODE is a non-digit that preceded the operand-number in the % spec,   such as 'z' if the spec was `%z3'.  CODE is 0 if there was no char   between the % and the digits.   When CODE is a non-letter, X is 0.   The meanings of the letters are machine-dependent and controlled   by PRINT_OPERAND.  */static voidoutput_operand (x, code)     rtx x;     int code;{  if (x && GET_CODE (x) == SUBREG)    x = alter_subreg (x);  /* If X is a pseudo-register, abort now rather than writing trash to the     assembler file.  */  if (x && GET_CODE (x) == REG && REGNO (x) >= FIRST_PSEUDO_REGISTER)    abort ();  PRINT_OPERAND (asm_out_file, x, code);}/* Print a memory reference operand for address X   using machine-dependent assembler syntax.   The macro PRINT_OPERAND_ADDRESS exists just to control this function.  */voidoutput_address (x)     rtx x;{  walk_alter_subreg (x);  PRINT_OPERAND_ADDRESS (asm_out_file, x);}/* Print an integer constant expression in assembler syntax.   Addition and subtraction are the only arithmetic   that may appear in these expressions.  */voidoutput_addr_const (file, x)     FILE *file;     rtx x;{  char buf[256]; restart:  switch (GET_CODE (x))    {    case PC:      if (flag_pic)	putc ('.', file);      else	abort ();      break;    case SYMBOL_REF:      assemble_name (file, XSTR (x, 0));      break;    case LABEL_REF:      ASM_GENERATE_INTERNAL_LABEL (buf, "L", CODE_LABEL_NUMBER (XEXP (x, 0)));      assemble_name (file, buf);      break;    case CODE_LABEL:      ASM_GENERATE_INTERNAL_LABEL (buf, "L", CODE_LABEL_NUMBER (x));      assemble_name (file, buf);      break;    case CONST_INT:      fprintf (file,#if HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_INT	       "%d",#else	       "%ld",#endif	       INTVAL (x));      break;    case CONST:      /* This used to output parentheses around the expression,	 but that does not work on the 386 (either ATT or BSD assembler).  */      output_addr_const (file, XEXP (x, 0));      break;    case CONST_DOUBLE:      if (GET_MODE (x) == VOIDmode)	{	  /* We can use %d if the number is one word and positive.  */	  if (CONST_DOUBLE_HIGH (x) || CONST_DOUBLE_LOW (x) < 0)	    fprintf (file,#if HOST_BITS_PER_WIDE_INT == 64#if HOST_BITS_PER_WIDE_INT != HOST_BITS_PER_INT		 " 0x%lx%016lx",#else		 " 0x%x%016x",#endif#else#if HOST_BITS_PER_WIDE_INT != HOST_BITS_PER_INT		 " 0x%lx%08lx",#else		 " 0x%x%08x",#endif#endif		     CONST_DOUBLE_HIGH (x), CONST_DOUBLE_LOW (x));	  else	    fprintf (file,#if HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_INT		     "%d",#else		     "%ld",#endif		     CONST_DOUBLE_LOW (x));	}      else	/* We can't handle floating point constants;	   PRINT_OPERAND must handle them.  */	output_operand_lossage ("floating constant misused");      break;    case PLUS:      /* Some assemblers need integer constants to appear last (eg masm).  */      if (GET_CODE (XEXP (x, 0)) == CONST_INT)	{	  output_addr_const (file, XEXP (x, 1));	  if (INTVAL (XEXP (x, 0)) >= 0)	    fprintf (file, "+");	  output_addr_const (file, XEXP (x, 0));	}      else	{	  output_addr_const (file, XEXP (x, 0));	  if (INTVAL (XEXP (x, 1)) >= 0)	    fprintf (file, "+");	  output_addr_const (file, XEXP (x, 1));	}      break;    case MINUS:      /* Avoid outputting things like x-x or x+5-x,	 since some assemblers can't handle that.  */      x = simplify_subtraction (x);      if (GET_CODE (x) != MINUS)	goto restart;      output_addr_const (file, XEXP (x, 0));      fprintf (file, "-");      if (GET_CODE (XEXP (x, 1)) == CONST_INT	  && INTVAL (XEXP (x, 1)) < 0)	{	  fprintf (file, ASM_OPEN_PAREN);	  output_addr_const (file, XEXP (x, 1));	  fprintf (file, ASM_CLOSE_PAREN);	}      else	output_addr_const (file, XEXP (x, 1));      break;    case ZERO_EXTEND:    case SIGN_EXTEND:      output_addr_const (file, XEXP (x, 0));      break;    default:      output_operand_lossage ("invalid expression as operand");    }}/* A poor man's fprintf, with the added features of %I, %R, %L, and %U.   %R prints the value of REGISTER_PREFIX.   %L prints the value of LOCAL_LABEL_PREFIX.   %U prints the value of USER_LABEL_PREFIX.   %I prints the value of IMMEDIATE_PREFIX.   %O runs ASM_OUTPUT_OPCODE to transform what follows in the string.   Also supported are %d, %x, %s, %e, %f, %g and %%.  */voidasm_fprintf (va_alist)     va_dcl{  va_list argptr;  FILE *file;  char buf[10];  char *p, *q, c;  va_start (argptr);  file = va_arg (argptr, FILE *);  p = va_arg (argptr, char *);  buf[0] = '%';  while (c = *p++)    switch (c)      {      case '%':	c = *p++;	q = &buf[1];	while ((c >= '0' && c <= '9') || c == '.')	  {	    *q++ = c;	    c = *p++;	  }	switch (c)	  {	  case '%':	    fprintf (file, "%%");	    break;	  case 'd':  case 'i':  case 'u':	  case 'x':  case 'p':  case 'X':	  case 'o':	    *q++ = c;	    *q = 0;	    fprintf (file, buf, va_arg (argptr, int));	    break;	  case 'e':	  case 'f':	  case 'g':	    *q++ = c;	    *q = 0;	    fprintf (file, buf, va_arg (argptr, double));	    break;	  case 's':	    *q++ = c

⌨️ 快捷键说明

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