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

📄 i386.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 4 页
字号:
/* Split one or more DImode RTL references into pairs of SImode   references.  The RTL can be REG, offsettable MEM, integer constant, or   CONST_DOUBLE.  "operands" is a pointer to an array of DImode RTL to   split and "num" is its length.  lo_half and hi_half are output arrays   that parallel "operands". */voidsplit_di (operands, num, lo_half, hi_half)     rtx operands[];     int num;     rtx lo_half[], hi_half[];{  while (num--)    {      if (GET_CODE (operands[num]) == REG)	{	  lo_half[num] = gen_rtx (REG, SImode, REGNO (operands[num]));	  hi_half[num] = gen_rtx (REG, SImode, REGNO (operands[num]) + 1);	}      else if (CONSTANT_P (operands[num]))	{	  split_double (operands[num], &lo_half[num], &hi_half[num]);	}      else if (offsettable_memref_p (operands[num]))	{	  lo_half[num] = operands[num];	  hi_half[num] = adj_offsettable_operand (operands[num], 4);	}      else	abort();    }}/* Return 1 if this is a valid binary operation on a 387.   OP is the expression matched, and MODE is its mode. */intbinary_387_op (op, mode)    register rtx op;    enum machine_mode mode;{  if (mode != VOIDmode && mode != GET_MODE (op))    return 0;  switch (GET_CODE (op))    {    case PLUS:    case MINUS:    case MULT:    case DIV:      return GET_MODE_CLASS (GET_MODE (op)) == MODE_FLOAT;    default:      return 0;    }}/* Return 1 if this is a valid conversion operation on a 387.   OP is the expression matched, and MODE is its mode. */intconvert_387_op (op, mode)    register rtx op;    enum machine_mode mode;{  if (mode != VOIDmode && mode != GET_MODE (op))    return 0;  switch (GET_CODE (op))    {    case FLOAT:      return GET_MODE (XEXP (op, 0)) == SImode;    case FLOAT_EXTEND:      return mode == DFmode && GET_MODE (XEXP (op, 0)) == SFmode;    default:      return 0;    }}/* Return 1 if this is a valid shift or rotate operation on a 386.   OP is the expression matched, and MODE is its mode. */intshift_op (op, mode)    register rtx op;    enum machine_mode mode;{  rtx operand = XEXP (op, 0);  if (mode != VOIDmode && mode != GET_MODE (op))    return 0;  if (GET_MODE (operand) != GET_MODE (op)      || GET_MODE_CLASS (GET_MODE (op)) != MODE_INT)    return 0;  return (GET_CODE (op) == ASHIFT	  || GET_CODE (op) == ASHIFTRT	  || GET_CODE (op) == LSHIFTRT	  || GET_CODE (op) == ROTATE	  || GET_CODE (op) == ROTATERT);}/* Output code to perform a 387 binary operation in INSN, one of PLUS,   MINUS, MULT or DIV.  OPERANDS are the insn operands, where operands[3]   is the expression of the binary operation.  The output may either be   emitted here, or returned to the caller, like all output_* functions.   There is no guarantee that the operands are the same mode, as they   might be within FLOAT or FLOAT_EXTEND expressions. */char *output_387_binary_op (insn, operands)     rtx insn;     rtx *operands;{  rtx temp;  char *base_op;  static char buf[100];  switch (GET_CODE (operands[3]))    {    case PLUS:      if (GET_MODE_CLASS (GET_MODE (operands[1])) == MODE_INT	  || GET_MODE_CLASS (GET_MODE (operands[2])) == MODE_INT)	base_op = "fiadd";      else	base_op = "fadd";      break;    case MINUS:      if (GET_MODE_CLASS (GET_MODE (operands[1])) == MODE_INT	  || GET_MODE_CLASS (GET_MODE (operands[2])) == MODE_INT)	base_op = "fisub";      else	base_op = "fsub";      break;    case MULT:      if (GET_MODE_CLASS (GET_MODE (operands[1])) == MODE_INT	  || GET_MODE_CLASS (GET_MODE (operands[2])) == MODE_INT)	base_op = "fimul";      else	base_op = "fmul";      break;    case DIV:      if (GET_MODE_CLASS (GET_MODE (operands[1])) == MODE_INT	  || GET_MODE_CLASS (GET_MODE (operands[2])) == MODE_INT)	base_op = "fidiv";      else	base_op = "fdiv";      break;    default:      abort ();    }  strcpy (buf, base_op);  switch (GET_CODE (operands[3]))    {    case MULT:    case PLUS:      if (REG_P (operands[2]) && REGNO (operands[0]) == REGNO (operands[2]))	{	  temp = operands[2];	  operands[2] = operands[1];	  operands[1] = temp;	}      if (GET_CODE (operands[2]) == MEM)	return strcat (buf, AS1 (%z2,%2));      if (NON_STACK_REG_P (operands[1]))	{	  output_op_from_reg (operands[1], strcat (buf, AS1 (%z0,%1)));	  RET;	}      else if (NON_STACK_REG_P (operands[2]))	{	  output_op_from_reg (operands[2], strcat (buf, AS1 (%z0,%1)));	  RET;	}      if (find_regno_note (insn, REG_DEAD, REGNO (operands[2])))	return strcat (buf, AS2 (p,%2,%0));      if (STACK_TOP_P (operands[0]))	return strcat (buf, AS2 (,%y2,%0));      else	return strcat (buf, AS2 (,%2,%0));    case MINUS:    case DIV:      if (GET_CODE (operands[1]) == MEM)	return strcat (buf, AS1 (r%z1,%1));      if (GET_CODE (operands[2]) == MEM)	return strcat (buf, AS1 (%z2,%2));      if (NON_STACK_REG_P (operands[1]))	{	  output_op_from_reg (operands[1], strcat (buf, AS1 (r%z0,%1)));	  RET;	}      else if (NON_STACK_REG_P (operands[2]))	{	  output_op_from_reg (operands[2], strcat (buf, AS1 (%z0,%1)));	  RET;	}      if (! STACK_REG_P (operands[1]) || ! STACK_REG_P (operands[2]))	abort ();      if (find_regno_note (insn, REG_DEAD, REGNO (operands[2])))	return strcat (buf, AS2 (rp,%2,%0));      if (find_regno_note (insn, REG_DEAD, REGNO (operands[1])))	return strcat (buf, AS2 (p,%1,%0));      if (STACK_TOP_P (operands[0]))	{	  if (STACK_TOP_P (operands[1]))	    return strcat (buf, AS2 (,%y2,%0));	  else	    return strcat (buf, AS2 (r,%y1,%0));	}      else if (STACK_TOP_P (operands[1]))	return strcat (buf, AS2 (,%1,%0));      else	return strcat (buf, AS2 (r,%2,%0));    default:      abort ();    }}/* Output code for INSN to convert a float to a signed int.  OPERANDS   are the insn operands.  The output may be SFmode or DFmode and the   input operand may be SImode or DImode.  As a special case, make sure   that the 387 stack top dies if the output mode is DImode, because the   hardware requires this.  */char *output_fix_trunc (insn, operands)     rtx insn;     rtx *operands;{  int stack_top_dies = find_regno_note (insn, REG_DEAD, FIRST_STACK_REG) != 0;  rtx xops[6];  if (! STACK_TOP_P (operands[1]) ||      (GET_MODE (operands[0]) == DImode && ! stack_top_dies))    abort ();  xops[0] = stack_pointer_rtx;  xops[1] = AT_SP (SImode);  xops[2] = adj_offsettable_operand (xops[1], 2);  xops[3] = GEN_INT (4);  xops[4] = GEN_INT (0xc00);  xops[5] = operands[2];  output_asm_insn (AS2 (sub%L0,%3,%0), xops);  output_asm_insn (AS1 (fnstc%W5,%1), xops);  output_asm_insn (AS2 (mov%W5,%1,%5), xops);  output_asm_insn (AS2 (or%W5,%4,%5), xops);  output_asm_insn (AS2 (mov%W5,%5,%2), xops);  output_asm_insn (AS1 (fldc%W5,%2), xops);  if (NON_STACK_REG_P (operands[0]))    output_to_reg (operands[0], stack_top_dies);  else if (GET_CODE (operands[0]) == MEM)    {      /* If frame pointer elimination is being done, the MEM reference	 might be an index off of the stack pointer.  In that case,	 since we have already adjusted %esp above, adjust the operand	 address so it points where it should. */      if (! frame_pointer_needed	  && reg_mentioned_p (stack_pointer_rtx, operands[0]))	operands[0] = adj_offsettable_operand (operands[0], 4);      if (stack_top_dies)	output_asm_insn (AS1 (fistp%z0,%0), operands);      else	output_asm_insn (AS1 (fist%z0,%0), operands);    }  else    abort ();  output_asm_insn (AS1 (fldc%W5,%1), xops);  output_asm_insn (AS2 (add%L0,%3,%0), xops);  RET;}/* Output code for INSN to compare OPERANDS.  The two operands might   not have the same mode: one might be within a FLOAT or FLOAT_EXTEND   expression.  If the compare is in mode CCFPEQmode, use an opcode that   will not fault if a qNaN is present. */char *output_float_compare (insn, operands)     rtx insn;     rtx *operands;{  int stack_top_dies;  rtx body = XVECEXP (PATTERN (insn), 0, 0);  int unordered_compare = GET_MODE (SET_SRC (body)) == CCFPEQmode;  if (! STACK_TOP_P (operands[0]))    abort ();  stack_top_dies = find_regno_note (insn, REG_DEAD, FIRST_STACK_REG) != 0;  if (STACK_REG_P (operands[1])      && stack_top_dies      && find_regno_note (insn, REG_DEAD, REGNO (operands[1]))      && REGNO (operands[1]) != FIRST_STACK_REG)    {      /* If both the top of the 387 stack dies, and the other operand	 is also a stack register that dies, then this must be a	 `fcompp' float compare */      if (unordered_compare)	output_asm_insn ("fucompp", operands);      else	output_asm_insn ("fcompp", operands);    }  else    {      static char buf[100];      /* Decide if this is the integer or float compare opcode, or the	 unordered float compare. */      if (unordered_compare)	strcpy (buf, "fucom");      else if (GET_MODE_CLASS (GET_MODE (operands[1])) == MODE_FLOAT)	strcpy (buf, "fcom");      else	strcpy (buf, "ficom");      /* Modify the opcode if the 387 stack is to be popped. */      if (stack_top_dies)	strcat (buf, "p");      if (NON_STACK_REG_P (operands[1]))	output_op_from_reg (operands[1], strcat (buf, AS1 (%z0,%1)));      else        output_asm_insn (strcat (buf, AS1 (%z1,%y1)), operands);    }  /* Now retrieve the condition code. */  return output_fp_cc0_set (insn);}/* Output opcodes to transfer the results of FP compare or test INSN   from the FPU to the CPU flags.  If TARGET_IEEE_FP, ensure that if the   result of the compare or test is unordered, no comparison operator   succeeds except NE.  Return an output template, if any.  */char *output_fp_cc0_set (insn)     rtx insn;{  rtx xops[3];  rtx unordered_label;  rtx next;  enum rtx_code code;  xops[0] = gen_rtx (REG, HImode, 0);  output_asm_insn (AS1 (fnsts%W0,%0), xops);  if (! TARGET_IEEE_FP)    return "sahf";  next = next_cc0_user (insn);  if (GET_CODE (next) == JUMP_INSN      && GET_CODE (PATTERN (next)) == SET      && SET_DEST (PATTERN (next)) == pc_rtx      && GET_CODE (SET_SRC (PATTERN (next))) == IF_THEN_ELSE)    {      code = GET_CODE (XEXP (SET_SRC (PATTERN (next)), 0));    }  else if (GET_CODE (PATTERN (next)) == SET)    {      code = GET_CODE (SET_SRC (PATTERN (next)));    }  else    abort ();  xops[0] = gen_rtx (REG, QImode, 0);  switch (code)    {    case GT:      xops[1] = GEN_INT (0x45);      output_asm_insn (AS2 (and%B0,%1,%h0), xops);      /* je label */      break;    case LT:      xops[1] = GEN_INT (0x45);      xops[2] = GEN_INT (0x01);      output_asm_insn (AS2 (and%B0,%1,%h0), xops);      output_asm_insn (AS2 (cmp%B0,%2,%h0), xops);      /* je label */      break;    case GE:      xops[1] = GEN_INT (0x05);      output_asm_insn (AS2 (and%B0,%1,%h0), xops);      /* je label */      break;    case LE:      xops[1] = GEN_INT (0x45);      xops[2] = GEN_INT (0x40);      output_asm_insn (AS2 (and%B0,%1,%h0), xops);      output_asm_insn (AS1 (dec%B0,%h0), xops);      output_asm_insn (AS2 (cmp%B0,%2,%h0), xops);      /* jb label */      break;    case EQ:      xops[1] = GEN_INT (0x45);      xops[2] = GEN_INT (0x40);      output_asm_insn (AS2 (and%B0,%1,%h0), xops);      output_asm_insn (AS2 (cmp%B0,%2,%h0), xops);      /* je label */      break;    case NE:      xops[1] = GEN_INT (0x44);      xops[2] = GEN_INT (0x40);      output_asm_insn (AS2 (and%B0,%1,%h0), xops);      output_asm_insn (AS2 (xor%B0,%2,%h0), xops);      /* jne label */      break;    case GTU:    case LTU:    case GEU:    case LEU:    default:      abort ();    }  RET;}

⌨️ 快捷键说明

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