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

📄 reg_ld_s.c

📁 汇编源码大全 有各种汇编源码 希望对你有所帮助
💻 C
📖 第 1 页 / 共 3 页
字号:
  short *d = (short *)FPU_data_address;  FPU_REG t;  int precision_loss;  if ( FPU_st0_tag == TW_Empty )    {      /* Empty register (stack underflow) */      EXCEPTION(EX_StackUnder);      goto invalid_operand;    }  else if ( (FPU_st0_tag == TW_Infinity) ||	   (FPU_st0_tag == TW_NaN) )    {      EXCEPTION(EX_Invalid);      goto invalid_operand;    }  reg_move(FPU_st0_ptr, &t);  precision_loss = round_to_int(&t);  if (t.sigh ||      ((t.sigl & 0xffff8000) &&       !((t.sigl == 0x8000) && (t.sign == SIGN_NEG))) )    {      EXCEPTION(EX_Invalid);      /* This is a special case: see sec 16.2.5.1 of the 80486 book */    invalid_operand:      if ( control_word & EX_Invalid )	{	  /* Produce something like QNaN "indefinite" */	  t.sigl = 0x8000;	}      else	return 0;    }  else    {      if ( precision_loss )	set_precision_flag(precision_loss);      if ( t.sign )	t.sigl = -t.sigl;    }  RE_ENTRANT_CHECK_OFF;  FPU_verify_area(VERIFY_WRITE,d,2);  put_fs_word((short)t.sigl,(short *) d);  RE_ENTRANT_CHECK_ON;  return 1;}/* Put a packed bcd array into user memory */int reg_store_bcd(void){  char *d = (char *)FPU_data_address;  FPU_REG t;  unsigned long long ll;  unsigned char b;  int i, precision_loss;  unsigned char sign = (FPU_st0_ptr->sign == SIGN_NEG) ? 0x80 : 0;  if ( FPU_st0_tag == TW_Empty )    {      /* Empty register (stack underflow) */      EXCEPTION(EX_StackUnder);      goto invalid_operand;    }  reg_move(FPU_st0_ptr, &t);  precision_loss = round_to_int(&t);  ll = significand(&t);  /* Check for overflow, by comparing with 999999999999999999 decimal. */  if ( (t.sigh > 0x0de0b6b3) ||      ((t.sigh == 0x0de0b6b3) && (t.sigl > 0xa763ffff)) )    {      EXCEPTION(EX_Invalid);      /* This is a special case: see sec 16.2.5.1 of the 80486 book */    invalid_operand:      if ( control_word & CW_Invalid )	{	  /* Produce the QNaN "indefinite" */	  RE_ENTRANT_CHECK_OFF;	  FPU_verify_area(VERIFY_WRITE,d,10);	  for ( i = 0; i < 7; i++)	    put_fs_byte(0, (unsigned char *) d+i); /* These bytes "undefined" */	  put_fs_byte(0xc0, (unsigned char *) d+7); /* This byte "undefined" */	  put_fs_byte(0xff, (unsigned char *) d+8);	  put_fs_byte(0xff, (unsigned char *) d+9);	  RE_ENTRANT_CHECK_ON;	  return 1;	}      else	return 0;    }  else if ( precision_loss )    {      /* Precision loss doesn't stop the data transfer */      set_precision_flag(precision_loss);    }  RE_ENTRANT_CHECK_OFF;  FPU_verify_area(VERIFY_WRITE,d,10);  RE_ENTRANT_CHECK_ON;  for ( i = 0; i < 9; i++)    {      b = div_small(&ll, 10);      b |= (div_small(&ll, 10)) << 4;      RE_ENTRANT_CHECK_OFF;      put_fs_byte(b,(unsigned char *) d+i);      RE_ENTRANT_CHECK_ON;    }  RE_ENTRANT_CHECK_OFF;  put_fs_byte(sign,(unsigned char *) d+9);  RE_ENTRANT_CHECK_ON;  return 1;}/*===========================================================================*//* r gets mangled such that sig is int, sign:    it is NOT normalized *//* The return value (in eax) is zero if the result is exact,   if bits are changed due to rounding, truncation, etc, then   a non-zero value is returned *//* Overflow is signalled by a non-zero return value (in eax).   In the case of overflow, the returned significand always has the   the largest possible value */int round_to_int(FPU_REG *r){  char     very_big;  unsigned eax;  if (r->tag == TW_Zero)    {      /* Make sure that zero is returned */      significand(r) = 0;      return 0;        /* o.k. */    }    if (r->exp > EXP_BIAS + 63)    {      r->sigl = r->sigh = ~0;      /* The largest representable number */      return 1;        /* overflow */    }  eax = shrxs(&r->sigl, EXP_BIAS + 63 - r->exp);  very_big = !(~(r->sigh) | ~(r->sigl));  /* test for 0xfff...fff */#define	half_or_more	(eax & 0x80000000)#define	frac_part	(eax)#define more_than_half  ((eax & 0x80000001) == 0x80000001)  switch (control_word & CW_RC)    {    case RC_RND:      if ( more_than_half               	/* nearest */	  || (half_or_more && (r->sigl & 1)) )	/* odd -> even */	{	  if ( very_big ) return 1;        /* overflow */	  significand(r) ++;	  return PRECISION_LOST_UP;	}      break;    case RC_DOWN:      if (frac_part && r->sign)	{	  if ( very_big ) return 1;        /* overflow */	  significand(r) ++;	  return PRECISION_LOST_UP;	}      break;    case RC_UP:      if (frac_part && !r->sign)	{	  if ( very_big ) return 1;        /* overflow */	  significand(r) ++;	  return PRECISION_LOST_UP;	}      break;    case RC_CHOP:      break;    }  return eax ? PRECISION_LOST_DOWN : 0;}/*===========================================================================*/char *fldenv(fpu_addr_modes addr_modes){  char *s = (char *)FPU_data_address;  unsigned short tag_word = 0;  unsigned char tag;  int i;  if ( addr_modes.vm86      || (addr_modes.override.operand_size == OP_SIZE_PREFIX) )    {      RE_ENTRANT_CHECK_OFF;      FPU_verify_area(VERIFY_READ, s, 0x0e);      control_word = get_fs_word((unsigned short *) s);      partial_status = get_fs_word((unsigned short *) (s+2));      tag_word = get_fs_word((unsigned short *) (s+4));      ip_offset = get_fs_word((unsigned short *) (s+6));      cs_selector = get_fs_word((unsigned short *) (s+8));      data_operand_offset = get_fs_word((unsigned short *) (s+0x0a));      operand_selector = get_fs_word((unsigned short *) (s+0x0c));      RE_ENTRANT_CHECK_ON;      s += 0x0e;      if ( addr_modes.vm86 )	{	  ip_offset += (cs_selector & 0xf000) << 4;	  data_operand_offset += (operand_selector & 0xf000) << 4;	}    }  else    {      RE_ENTRANT_CHECK_OFF;      FPU_verify_area(VERIFY_READ, s, 0x1c);      control_word = get_fs_word((unsigned short *) s);      partial_status = get_fs_word((unsigned short *) (s+4));      tag_word = get_fs_word((unsigned short *) (s+8));      ip_offset = get_fs_long((unsigned long *) (s+0x0c));      cs_selector = get_fs_long((unsigned long *) (s+0x10));      data_operand_offset = get_fs_long((unsigned long *) (s+0x14));      operand_selector = get_fs_long((unsigned long *) (s+0x18));      RE_ENTRANT_CHECK_ON;      s += 0x1c;    }#ifdef PECULIAR_486  control_word &= ~0xe080;#endif PECULIAR_486  top = (partial_status >> SW_Top_Shift) & 7;  if ( partial_status & ~control_word & CW_Exceptions )    partial_status |= (SW_Summary | SW_Backward);  else    partial_status &= ~(SW_Summary | SW_Backward);  for ( i = 0; i < 8; i++ )    {      tag = tag_word & 3;      tag_word >>= 2;      if ( tag == 3 )	/* New tag is empty.  Accept it */	regs[i].tag = TW_Empty;      else if ( regs[i].tag == TW_Empty )	{	  /* Old tag is empty and new tag is not empty.  New tag is determined	     by old reg contents */	  if ( regs[i].exp == EXP_BIAS - EXTENDED_Ebias )	    {	      if ( !(regs[i].sigl | regs[i].sigh) )		regs[i].tag = TW_Zero;	      else		regs[i].tag = TW_Valid;	    }	  else if ( regs[i].exp == 0x7fff + EXP_BIAS - EXTENDED_Ebias )	    {	      if ( !((regs[i].sigh & ~0x80000000) | regs[i].sigl) )		regs[i].tag = TW_Infinity;	      else		regs[i].tag = TW_NaN;	    }	  else	    regs[i].tag = TW_Valid;  	}      /* Else old tag is not empty and new tag is not empty.  Old tag	 remains correct */    }  /* Ensure that the values just loaded are not changed by     fix-up operations. */  NO_NET_DATA_EFFECT;  NO_NET_INSTR_EFFECT;  return s;}void frstor(fpu_addr_modes addr_modes){  int i, stnr;  unsigned char tag;  char *s = fldenv(addr_modes);  for ( i = 0; i < 8; i++ )    {      /* Load each register. */      FPU_data_address = (void *)(s+i*10);      reg_load_extended();      stnr = (i+top) & 7;      tag = regs[stnr].tag;   /* Derived from the loaded tag word. */      reg_move(&FPU_loaded_data, &regs[stnr]);      if ( tag == TW_Empty )  /* The loaded data over-rides all other cases. */	regs[stnr].tag = tag;    }  /* Reverse the effect which loading the registers had on the     data pointer */  NO_NET_DATA_EFFECT;}unsigned short tag_word(void){  unsigned short word = 0;  unsigned char tag;  int i;  for ( i = 7; i >= 0; i-- )    {      switch ( tag = regs[i].tag )	{	case TW_Valid:	  if ( regs[i].exp <= (EXP_BIAS - EXTENDED_Ebias) )	    tag = 2;	  break;	case TW_Infinity:	case TW_NaN:	  tag = 2;	  break;	case TW_Empty:	  tag = 3;	  break;	  /* TW_Zero already has the correct value */	}      word <<= 2;      word |= tag;    }  return word;}char *fstenv(fpu_addr_modes addr_modes){  char *d = (char *)FPU_data_address;  if ( addr_modes.vm86      || (addr_modes.override.operand_size == OP_SIZE_PREFIX) )    {      RE_ENTRANT_CHECK_OFF;      FPU_verify_area(VERIFY_WRITE,d,14);#ifdef PECULIAR_486      put_fs_long(control_word & ~0xe080, (unsigned short *) d);#else      put_fs_word(control_word, (unsigned short *) d);#endif PECULIAR_486      put_fs_word(status_word(), (unsigned short *) (d+2));      put_fs_word(tag_word(), (unsigned short *) (d+4));      put_fs_word(ip_offset, (unsigned short *) (d+6));      put_fs_word(data_operand_offset, (unsigned short *) (d+0x0a));      if ( addr_modes.vm86 )	{	  put_fs_word((ip_offset & 0xf0000) >> 4,		      (unsigned short *) (d+8));	  put_fs_word((data_operand_offset & 0xf0000) >> 4,		      (unsigned short *) (d+0x0c));	}      else	{	  put_fs_word(cs_selector, (unsigned short *) (d+8));	  put_fs_word(operand_selector, (unsigned short *) (d+0x0c));	}      RE_ENTRANT_CHECK_ON;      d += 0x0e;    }  else    {      RE_ENTRANT_CHECK_OFF;      FPU_verify_area(VERIFY_WRITE,d,28);#ifdef PECULIAR_486      /* An 80486 sets all the reserved bits to 1. */      put_fs_long(0xffff0040 | (control_word & ~0xe080), (unsigned long *) d);      put_fs_long(0xffff0000 | status_word(), (unsigned long *) (d+4));      put_fs_long(0xffff0000 | tag_word(), (unsigned long *) (d+8));#else      put_fs_word(control_word, (unsigned short *) d);      put_fs_word(status_word(), (unsigned short *) (d+4));      put_fs_word(tag_word(), (unsigned short *) (d+8));#endif PECULIAR_486      put_fs_long(ip_offset, (unsigned long *) (d+0x0c));      put_fs_long(cs_selector & ~0xf8000000, (unsigned long *) (d+0x10));      put_fs_long(data_operand_offset, (unsigned long *) (d+0x14));#ifdef PECULIAR_486      /* An 80486 sets all the reserved bits to 1. */      put_fs_long(0xffff0000 | operand_selector, (unsigned long *) (d+0x18));#else      put_fs_long(operand_selector, (unsigned long *) (d+0x18));#endif PECULIAR_486      RE_ENTRANT_CHECK_ON;      d += 0x1c;    }    control_word |= CW_Exceptions;  partial_status &= ~(SW_Summary | SW_Backward);  return d;}void fsave(fpu_addr_modes addr_modes){  char *d;  int i;  d = fstenv(addr_modes);  RE_ENTRANT_CHECK_OFF;  FPU_verify_area(VERIFY_WRITE,d,80);  RE_ENTRANT_CHECK_ON;  for ( i = 0; i < 8; i++ )    write_to_extended(&regs[(top + i) & 7], d + 10 * i);  finit();}/*===========================================================================*//*  A call to this function must be preceeded by a call to  FPU_verify_area() to verify access to the 10 bytes at d  */static void write_to_extended(FPU_REG *rp, char *d){  long e;  FPU_REG tmp;    e = rp->exp - EXP_BIAS + EXTENDED_Ebias;#ifdef PARANOID  switch ( rp->tag )    {    case TW_Zero:      if ( rp->sigh | rp->sigl | e )	EXCEPTION(EX_INTERNAL | 0x114);      break;    case TW_Infinity:    case TW_NaN:      if ( (e ^ 0x7fff) | !(rp->sigh & 0x80000000) )	EXCEPTION(EX_INTERNAL | 0x114);      break;    default:      if (e > 0x7fff || e < -63)	EXCEPTION(EX_INTERNAL | 0x114);    }#endif PARANOID  /*    All numbers except denormals are stored internally in a    format which is compatible with the extended real number    format.   */  if ( e > 0 )    {      /* just copy the reg */      RE_ENTRANT_CHECK_OFF;      put_fs_long(rp->sigl, (unsigned long *) d);      put_fs_long(rp->sigh, (unsigned long *) (d + 4));      RE_ENTRANT_CHECK_ON;    }  else    {      /*	The number is a de-normal stored as a normal using our	extra exponent range, or is Zero.	Convert it back to a de-normal, or leave it as Zero.       */      reg_move(rp, &tmp);      tmp.exp += -EXTENDED_Emin + 63;  /* largest exp to be 63 */      round_to_int(&tmp);      e = 0;      RE_ENTRANT_CHECK_OFF;      put_fs_long(tmp.sigl, (unsigned long *) d);      put_fs_long(tmp.sigh, (unsigned long *) (d + 4));      RE_ENTRANT_CHECK_ON;    }  e |= rp->sign == SIGN_POS ? 0 : 0x8000;  RE_ENTRANT_CHECK_OFF;  put_fs_word(e, (unsigned short *) (d + 8));  RE_ENTRANT_CHECK_ON;}

⌨️ 快捷键说明

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