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

📄 i386.c

📁 gcc库的原代码,对编程有很大帮助.
💻 C
📖 第 1 页 / 共 5 页
字号:
	}      current_function_uses_pic_offset_table = 1;      return reg;    }  else if (GET_CODE (addr) == CONST || GET_CODE (addr) == PLUS)    {      rtx base;      if (GET_CODE (addr) == CONST)	{	  addr = XEXP (addr, 0);	  if (GET_CODE (addr) != PLUS)	    abort ();	}      if (XEXP (addr, 0) == pic_offset_table_rtx)	return orig;      if (reg == 0)	reg = gen_reg_rtx (Pmode);      base = legitimize_pic_address (XEXP (addr, 0), reg);      addr = legitimize_pic_address (XEXP (addr, 1),				     base == reg ? NULL_RTX : reg);      if (GET_CODE (addr) == CONST_INT)	return plus_constant (base, INTVAL (addr));      if (GET_CODE (addr) == PLUS && CONSTANT_P (XEXP (addr, 1)))	{	  base = gen_rtx (PLUS, Pmode, base, XEXP (addr, 0));	  addr = XEXP (addr, 1);	}	return gen_rtx (PLUS, Pmode, base, addr);    }  return new;}/* Emit insns to move operands[1] into operands[0].  */voidemit_pic_move (operands, mode)     rtx *operands;     enum machine_mode mode;{  rtx temp = reload_in_progress ? operands[0] : gen_reg_rtx (Pmode);  if (GET_CODE (operands[0]) == MEM && SYMBOLIC_CONST (operands[1]))    operands[1] = (rtx) force_reg (SImode, operands[1]);  else    operands[1] = legitimize_pic_address (operands[1], temp);}/* Try machine-dependent ways of modifying an illegitimate address   to be legitimate.  If we find one, return the new, valid address.   This macro is used in only one place: `memory_address' in explow.c.   OLDX is the address as it was before break_out_memory_refs was called.   In some cases it is useful to look at this to decide what needs to be done.   MODE and WIN are passed so that this macro can use   GO_IF_LEGITIMATE_ADDRESS.   It is always safe for this macro to do nothing.  It exists to recognize   opportunities to optimize the output.   For the 80386, we handle X+REG by loading X into a register R and   using R+REG.  R will go in a general reg and indexing will be used.   However, if REG is a broken-out memory address or multiplication,   nothing needs to be done because REG can certainly go in a general reg.   When -fpic is used, special handling is needed for symbolic references.   See comments by legitimize_pic_address in i386.c for details.  */rtxlegitimize_address (x, oldx, mode)     register rtx x;     register rtx oldx;     enum machine_mode mode;{  int changed = 0;  unsigned log;  if (TARGET_DEBUG_ADDR)    {      fprintf (stderr, "\n==========\nLEGITIMIZE_ADDRESS, mode = %s\n", GET_MODE_NAME (mode));      debug_rtx (x);    }  if (flag_pic && SYMBOLIC_CONST (x))    return legitimize_pic_address (x, 0);  /* Canonicalize shifts by 0, 1, 2, 3 into multiply */  if (GET_CODE (x) == ASHIFT      && GET_CODE (XEXP (x, 1)) == CONST_INT      && (log = (unsigned)exact_log2 (INTVAL (XEXP (x, 1)))) < 4)    {      changed = 1;      x = gen_rtx (MULT, Pmode,		   force_reg (Pmode, XEXP (x, 0)),		   GEN_INT (1 << log));    }  if (GET_CODE (x) == PLUS)    {      /* Canonicalize shifts by 0, 1, 2, 3 into multiply */      if (GET_CODE (XEXP (x, 0)) == ASHIFT	  && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT	  && (log = (unsigned)exact_log2 (INTVAL (XEXP (XEXP (x, 0), 1)))) < 4)	{	  changed = 1;	  XEXP (x, 0) = gen_rtx (MULT, Pmode,				 force_reg (Pmode, XEXP (XEXP (x, 0), 0)),				 GEN_INT (1 << log));	}      if (GET_CODE (XEXP (x, 1)) == ASHIFT	  && GET_CODE (XEXP (XEXP (x, 1), 1)) == CONST_INT	  && (log = (unsigned)exact_log2 (INTVAL (XEXP (XEXP (x, 1), 1)))) < 4)	{	  changed = 1;	  XEXP (x, 1) = gen_rtx (MULT, Pmode,				 force_reg (Pmode, XEXP (XEXP (x, 1), 0)),				 GEN_INT (1 << log));	}      /* Put multiply first if it isn't already */      if (GET_CODE (XEXP (x, 1)) == MULT)	{	  rtx tmp = XEXP (x, 0);	  XEXP (x, 0) = XEXP (x, 1);	  XEXP (x, 1) = tmp;	  changed = 1;	}      /* Canonicalize (plus (mult (reg) (const)) (plus (reg) (const)))	 into (plus (plus (mult (reg) (const)) (reg)) (const)).  This can be	 created by virtual register instantiation, register elimination, and	 similar optimizations.  */      if (GET_CODE (XEXP (x, 0)) == MULT && GET_CODE (XEXP (x, 1)) == PLUS)	{	  changed = 1;	  x = gen_rtx (PLUS, Pmode,		       gen_rtx (PLUS, Pmode, XEXP (x, 0), XEXP (XEXP (x, 1), 0)),		       XEXP (XEXP (x, 1), 1));	}      /* Canonicalize (plus (plus (mult (reg) (const)) (plus (reg) (const))) const)	 into (plus (plus (mult (reg) (const)) (reg)) (const)).  */      else if (GET_CODE (x) == PLUS && GET_CODE (XEXP (x, 0)) == PLUS	       && GET_CODE (XEXP (XEXP (x, 0), 0)) == MULT	       && GET_CODE (XEXP (XEXP (x, 0), 1)) == PLUS	       && CONSTANT_P (XEXP (x, 1)))	{	  rtx constant, other;	  if (GET_CODE (XEXP (x, 1)) == CONST_INT)	    {	      constant = XEXP (x, 1);	      other = XEXP (XEXP (XEXP (x, 0), 1), 1);	    }	  else if (GET_CODE (XEXP (XEXP (XEXP (x, 0), 1), 1)) == CONST_INT)	    {	      constant = XEXP (XEXP (XEXP (x, 0), 1), 1);	      other = XEXP (x, 1);	    }	  else	    constant = 0;	  if (constant)	    {	      changed = 1;	      x = gen_rtx (PLUS, Pmode,			   gen_rtx (PLUS, Pmode, XEXP (XEXP (x, 0), 0),				    XEXP (XEXP (XEXP (x, 0), 1), 0)),			   plus_constant (other, INTVAL (constant)));	    }	}      if (changed && legitimate_address_p (mode, x, FALSE))	return x;      if (GET_CODE (XEXP (x, 0)) == MULT)	{	  changed = 1;	  XEXP (x, 0) = force_operand (XEXP (x, 0), 0);	}      if (GET_CODE (XEXP (x, 1)) == MULT)	{	  changed = 1;	  XEXP (x, 1) = force_operand (XEXP (x, 1), 0);	}      if (changed	  && GET_CODE (XEXP (x, 1)) == REG	  && GET_CODE (XEXP (x, 0)) == REG)	return x;      if (flag_pic && SYMBOLIC_CONST (XEXP (x, 1)))	{	  changed = 1;	  x = legitimize_pic_address (x, 0);	}      if (changed && legitimate_address_p (mode, x, FALSE))	return x;      if (GET_CODE (XEXP (x, 0)) == REG)	{	  register rtx temp = gen_reg_rtx (Pmode);	  register rtx val  = force_operand (XEXP (x, 1), temp);	  if (val != temp)	    emit_move_insn (temp, val);	  XEXP (x, 1) = temp;	  return x;	}      else if (GET_CODE (XEXP (x, 1)) == REG)	{	  register rtx temp = gen_reg_rtx (Pmode);	  register rtx val  = force_operand (XEXP (x, 0), temp);	  if (val != temp)	    emit_move_insn (temp, val);	  XEXP (x, 0) = temp;	  return x;	}    }  return x;}/* Print an integer constant expression in assembler syntax.  Addition   and subtraction are the only arithmetic that may appear in these   expressions.  FILE is the stdio stream to write to, X is the rtx, and   CODE is the operand print code from the output string.  */static voidoutput_pic_addr_const (file, x, code)     FILE *file;     rtx x;     int code;{  char buf[256];  switch (GET_CODE (x))    {    case PC:      if (flag_pic)	putc ('.', file);      else	abort ();      break;    case SYMBOL_REF:    case LABEL_REF:      if (GET_CODE (x) == SYMBOL_REF)	assemble_name (file, XSTR (x, 0));      else	{	  ASM_GENERATE_INTERNAL_LABEL (buf, "L",				       CODE_LABEL_NUMBER (XEXP (x, 0)));	  assemble_name (asm_out_file, buf);	}      if (GET_CODE (x) == SYMBOL_REF && CONSTANT_POOL_ADDRESS_P (x))	fprintf (file, "@GOTOFF(%%ebx)");      else if (code == 'P')	fprintf (file, "@PLT");      else if (GET_CODE (x) == LABEL_REF)	fprintf (file, "@GOTOFF");      else if (! SYMBOL_REF_FLAG (x))	fprintf (file, "@GOT");      else	fprintf (file, "@GOTOFF");      break;    case CODE_LABEL:      ASM_GENERATE_INTERNAL_LABEL (buf, "L", CODE_LABEL_NUMBER (x));      assemble_name (asm_out_file, buf);      break;    case CONST_INT:      fprintf (file, "%d", 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_pic_addr_const (file, XEXP (x, 0), code);      break;    case CONST_DOUBLE:      if (GET_MODE (x) == VOIDmode)	{	  /* We can use %d if the number is <32 bits and positive.  */	  if (CONST_DOUBLE_HIGH (x) || CONST_DOUBLE_LOW (x) < 0)	    fprintf (file, "0x%x%08x",		     CONST_DOUBLE_HIGH (x), CONST_DOUBLE_LOW (x));	  else	    fprintf (file, "%d", 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_pic_addr_const (file, XEXP (x, 1), code);	  if (INTVAL (XEXP (x, 0)) >= 0)	    fprintf (file, "+");	  output_pic_addr_const (file, XEXP (x, 0), code);	}      else	{	  output_pic_addr_const (file, XEXP (x, 0), code);	  if (INTVAL (XEXP (x, 1)) >= 0)	    fprintf (file, "+");	  output_pic_addr_const (file, XEXP (x, 1), code);	}      break;    case MINUS:      output_pic_addr_const (file, XEXP (x, 0), code);      fprintf (file, "-");      output_pic_addr_const (file, XEXP (x, 1), code);      break;    default:      output_operand_lossage ("invalid expression as operand");    }}/* Meaning of CODE:   f -- float insn (print a CONST_DOUBLE as a float rather than in hex).   D,L,W,B,Q,S -- print the opcode suffix for specified size of operand.   R -- print the prefix for register names.   z -- print the opcode suffix for the size of the current operand.   * -- print a star (in certain assembler syntax)   w -- print the operand as if it's a "word" (HImode) even if it isn't.   c -- don't print special prefixes before constant operands.   J -- print the appropriate jump operand.*/voidprint_operand (file, x, code)     FILE *file;     rtx x;     int code;{  if (code)    {      switch (code)	{	case '*':	  if (USE_STAR)	    putc ('*', file);	  return;	case 'L':	  PUT_OP_SIZE (code, 'l', file);	  return;	case 'W':	  PUT_OP_SIZE (code, 'w', file);	  return;	case 'B':	  PUT_OP_SIZE (code, 'b', file);	  return;	case 'Q':	  PUT_OP_SIZE (code, 'l', file);	  return;	case 'S':	  PUT_OP_SIZE (code, 's', file);	  return;	case 'T':	  PUT_OP_SIZE (code, 't', file);	  return;	case 'z':	  /* 387 opcodes don't get size suffixes if the operands are	     registers. */	  if (STACK_REG_P (x))	    return;	  /* this is the size of op from size of operand */	  switch (GET_MODE_SIZE (GET_MODE (x)))	    {	    case 1:	      PUT_OP_SIZE ('B', 'b', file);	      return;	    case 2:	      PUT_OP_SIZE ('W', 'w', file);	      return;	    case 4:	      if (GET_MODE (x) == SFmode)		{		  PUT_OP_SIZE ('S', 's', file);		  return;		}	      else		PUT_OP_SIZE ('L', 'l', file);	      return;	    case 12:		  PUT_OP_SIZE ('T', 't', file);		  return;	    case 8:	      if (GET_MODE_CLASS (GET_MODE (x)) == MODE_INT)		{#ifdef GAS_MNEMONICS		  PUT_OP_SIZE ('Q', 'q', file);		  return;#else		  PUT_OP_SIZE ('Q', 'l', file);	/* Fall through */#endif		}	      PUT_OP_SIZE ('Q', 'l', file);	      return;	    }	case 'b':	case 'w':	case 'k':	case 'h':	case 'y':	case 'P':	  break;	case 'J':	  switch (GET_CODE (x))	    {	      /* These conditions are appropriate for testing the result		 of an arithmetic operation, not for a compare operation.	         Cases GE, LT assume CC_NO_OVERFLOW true. All cases assume		 CC_Z_IN_NOT_C false and not floating point.  */	    case NE:  fputs ("jne", file); return;	    case EQ:  fputs ("je",  file); return;	    case GE:  fputs ("jns", file); return;	    case LT:  fputs ("js",  file); return;	    case GEU: fputs ("jmp", file); return;	    case GTU: fputs ("jne",  file); return;	    case LEU: fputs ("je", file); return;	    case LTU: fputs ("#branch never",  file); return;	    /* no matching branches for GT nor LE */	    }	  abort ();	default:	  {	    char str[50];	    sprintf (str, "invalid operand code `%c'", code);	    output_operand_lossage (str);	  }	}    }  if (GET_CODE (x) == REG)    {      PRINT_REG (x, code, file);    }  else if (GET_CODE (x) == MEM)    {      PRINT_PTR (x, file);      if (CONSTANT_ADDRESS_P

⌨️ 快捷键说明

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