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

📄 i386.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 4 页
字号:
	/* 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.*/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 '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 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;	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 (XEXP (x, 0)))	{	  if (flag_pic)	    output_pic_addr_const (file, XEXP (x, 0), code);	  else	    output_addr_const (file, XEXP (x, 0));	}      else	output_address (XEXP (x, 0));    }  else if (GET_CODE (x) == CONST_DOUBLE && GET_MODE (x) == SFmode)    {      union { double d; int i[2]; } u;      union { float f; int i; } u1;      u.i[0] = CONST_DOUBLE_LOW (x);      u.i[1] = CONST_DOUBLE_HIGH (x);      u1.f = u.d;      PRINT_IMMED_PREFIX (file);      fprintf (file, "0x%x", u1.i);    }  else if (GET_CODE (x) == CONST_DOUBLE && GET_MODE (x) == DFmode)    {      union { double d; int i[2]; } u;      u.i[0] = CONST_DOUBLE_LOW (x);      u.i[1] = CONST_DOUBLE_HIGH (x);      fprintf (file, "%.22e", u.d);    }  else     {      if (code != 'P')	{	  if (GET_CODE (x) == CONST_INT || GET_CODE (x) == CONST_DOUBLE)	    PRINT_IMMED_PREFIX (file);	  else if (GET_CODE (x) == CONST || GET_CODE (x) == SYMBOL_REF		   || GET_CODE (x) == LABEL_REF)	    PRINT_OFFSET_PREFIX (file);	}      if (flag_pic)	output_pic_addr_const (file, x, code);      else	output_addr_const (file, x);    }}/* Print a memory operand whose address is ADDR.  */voidprint_operand_address (file, addr)     FILE *file;     register rtx addr;{  register rtx reg1, reg2, breg, ireg;  rtx offset;  switch (GET_CODE (addr))    {    case REG:      ADDR_BEG (file);      fprintf (file, "%se", RP);      fputs (hi_reg_name[REGNO (addr)], file);      ADDR_END (file);      break;    case PLUS:      reg1 = 0;      reg2 = 0;      ireg = 0;      breg = 0;      offset = 0;      if (CONSTANT_ADDRESS_P (XEXP (addr, 0)))	{	  offset = XEXP (addr, 0);	  addr = XEXP (addr, 1);	}      else if (CONSTANT_ADDRESS_P (XEXP (addr, 1)))	{	  offset = XEXP (addr, 1);	  addr = XEXP (addr, 0);	}      if (GET_CODE (addr) != PLUS) ;      else if (GET_CODE (XEXP (addr, 0)) == MULT)	{	  reg1 = XEXP (addr, 0);	  addr = XEXP (addr, 1);	}      else if (GET_CODE (XEXP (addr, 1)) == MULT)	{	  reg1 = XEXP (addr, 1);	  addr = XEXP (addr, 0);	}      else if (GET_CODE (XEXP (addr, 0)) == REG)	{	  reg1 = XEXP (addr, 0);	  addr = XEXP (addr, 1);	}      else if (GET_CODE (XEXP (addr, 1)) == REG)	{	  reg1 = XEXP (addr, 1);	  addr = XEXP (addr, 0);	}      if (GET_CODE (addr) == REG || GET_CODE (addr) == MULT)	{	  if (reg1 == 0) reg1 = addr;	  else reg2 = addr;	  addr = 0;	}      if (offset != 0)	{	  if (addr != 0) abort ();	  addr = offset;	}      if ((reg1 && GET_CODE (reg1) == MULT)	  || (reg2 != 0 && REGNO_OK_FOR_BASE_P (REGNO (reg2))))	{	  breg = reg2;	  ireg = reg1;	}      else if (reg1 != 0 && REGNO_OK_FOR_BASE_P (REGNO (reg1)))	{	  breg = reg1;	  ireg = reg2;	}      if (ireg != 0 || breg != 0)	{	  int scale = 1;	  if (addr != 0)	    {	      if (GET_CODE (addr) == LABEL_REF)		output_asm_label (addr);	      else		{		  if (flag_pic)		    output_pic_addr_const (file, addr, 0);		  else		    output_addr_const (file, addr);		}	    }  	  if (ireg != 0 && GET_CODE (ireg) == MULT)	    {	      scale = INTVAL (XEXP (ireg, 1));	      ireg = XEXP (ireg, 0);	    }	  /* The stack pointer can only appear as a base register,	     never an index register, so exchange the regs if it is wrong. */	  if (scale == 1 && ireg && REGNO (ireg) == STACK_POINTER_REGNUM)	    {	      rtx tmp;	      tmp = breg;	      breg = ireg;	      ireg = tmp;	    }	  /* output breg+ireg*scale */	  PRINT_B_I_S (breg, ireg, scale, file);	  break;	}    case MULT:      {	int scale;	if (GET_CODE (XEXP (addr, 0)) == CONST_INT)	  {	    scale = INTVAL (XEXP (addr, 0));	    ireg = XEXP (addr, 1);	  }	else	  {	    scale = INTVAL (XEXP (addr, 1));	    ireg = XEXP (addr, 0);	  }	output_addr_const (file, const0_rtx);	PRINT_B_I_S ((rtx) 0, ireg, scale, file);      }      break;    default:      if (GET_CODE (addr) == CONST_INT	  && INTVAL (addr) < 0x8000	  && INTVAL (addr) >= -0x8000)	fprintf (file, "%d", INTVAL (addr));      else	{	  if (flag_pic)	    output_pic_addr_const (file, addr, 0);	  else	    output_addr_const (file, addr);	}    }}/* Set the cc_status for the results of an insn whose pattern is EXP.   On the 80386, we assume that only test and compare insns, as well   as SI, HI, & DI mode ADD, SUB, NEG, AND, IOR, XOR, ASHIFT, LSHIFT,   ASHIFTRT, and LSHIFTRT instructions set the condition codes usefully.   Also, we assume that jumps, moves and sCOND don't affect the condition   codes.  All else clobbers the condition codes, by assumption.   We assume that ALL integer add, minus, etc. instructions effect the   condition codes.  This MUST be consistent with i386.md.   We don't record any float test or compare - the redundant test &   compare check in final.c does not handle stack-like regs correctly. */voidnotice_update_cc (exp)     rtx exp;{  if (GET_CODE (exp) == SET)    {      /* Jumps do not alter the cc's.  */      if (SET_DEST (exp) == pc_rtx)	return;      /* Moving register or memory into a register:	 it doesn't alter the cc's, but it might invalidate	 the RTX's which we remember the cc's came from.	 (Note that moving a constant 0 or 1 MAY set the cc's).  */      if (REG_P (SET_DEST (exp))	  && (REG_P (SET_SRC (exp)) || GET_CODE (SET_SRC (exp)) == MEM	      || GET_RTX_CLASS (GET_CODE (SET_SRC (exp))) == '<'))	{	  if (cc_status.value1	      && reg_overlap_mentioned_p (SET_DEST (exp), cc_status.value1))	    cc_status.value1 = 0;	  if (cc_status.value2	      && reg_overlap_mentioned_p (SET_DEST (exp), cc_status.value2))	    cc_status.value2 = 0;	  return;	}      /* Moving register into memory doesn't alter the cc's.	 It may invalidate the RTX's which we remember the cc's came from.  */      if (GET_CODE (SET_DEST (exp)) == MEM	  && (REG_P (SET_SRC (exp))	      || GET_RTX_CLASS (GET_CODE (SET_SRC (exp))) == '<'))	{	  if (cc_status.value1 && GET_CODE (cc_status.value1) == MEM)	    cc_status.value1 = 0;	  if (cc_status.value2 && GET_CODE (cc_status.value2) == MEM)	    cc_status.value2 = 0;	  return;	}      /* Function calls clobber the cc's.  */      else if (GET_CODE (SET_SRC (exp)) == CALL)	{	  CC_STATUS_INIT;	  return;	}      /* Tests and compares set the cc's in predictable ways.  */      else if (SET_DEST (exp) == cc0_rtx)	{	  CC_STATUS_INIT;	  cc_status.value1 = SET_SRC (exp);	  return;	}      /* Certain instructions effect the condition codes. */      else if (GET_MODE (SET_SRC (exp)) == SImode	       || GET_MODE (SET_SRC (exp)) == HImode	       || GET_MODE (SET_SRC (exp)) == QImode)	switch (GET_CODE (SET_SRC (exp)))	  {	  case ASHIFTRT: case LSHIFTRT:	  case ASHIFT: case LSHIFT:	    /* Shifts on the 386 don't set the condition codes if the	       shift count is zero. */	    if (GET_CODE (XEXP (SET_SRC (exp), 1)) != CONST_INT)	      {		CC_STATUS_INIT;		break;	      }	    /* We assume that the CONST_INT is non-zero (this rtx would	       have been deleted if it were zero. */	  case PLUS: case MINUS: case NEG:	  case AND: case IOR: case XOR:	    cc_status.flags = CC_NO_OVERFLOW;	    cc_status.value1 = SET_SRC (exp);	    cc_status.value2 = SET_DEST (exp);	    break;	  default:	    CC_STATUS_INIT;	  }      else	{	  CC_STATUS_INIT;	}    }  else if (GET_CODE (exp) == PARALLEL	   && GET_CODE (XVECEXP (exp, 0, 0)) == SET)    {      if (SET_DEST (XVECEXP (exp, 0, 0)) == pc_rtx)	return;      if (SET_DEST (XVECEXP (exp, 0, 0)) == cc0_rtx)	{	  CC_STATUS_INIT;	  if (stack_regs_mentioned_p (SET_SRC (XVECEXP (exp, 0, 0))))	    cc_status.flags |= CC_IN_80387;	  else	    cc_status.value1 = SET_SRC (XVECEXP (exp, 0, 0));	  return;	}      CC_STATUS_INIT;    }  else    {      CC_STATUS_INIT;    }}

⌨️ 快捷键说明

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