Пример #1
0
static void single_arg_error(FPU_REG *st0_ptr, u_char st0_tag)
{
	if (st0_tag == TAG_Empty)
		FPU_stack_underflow();	/* Puts a QNaN in st(0) */
	else if (st0_tag == TW_NaN)
		real_1op_NaN(st0_ptr);	/* return with a NaN in st(0) */
#ifdef PARANOID
	else
		EXCEPTION(EX_INTERNAL | 0x0112);
#endif /* PARANOID */
}
Пример #2
0
static void single_arg_error(FPU_REG *st0_ptr, u_char st0_tag)
{
	if (st0_tag == TAG_Empty)
		FPU_stack_underflow();	
	else if (st0_tag == TW_NaN)
		real_1op_NaN(st0_ptr);	
#ifdef PARANOID
	else
		EXCEPTION(EX_INTERNAL | 0x0112);
#endif 
}
Пример #3
0
static void fxtract(FPU_REG *st0_ptr, u_char st0_tag)
{
	FPU_REG *st_new_ptr;
	u_char sign;
	register FPU_REG *st1_ptr = st0_ptr;	

	if (STACK_OVERFLOW) {
		FPU_stack_overflow();
		return;
	}

	clear_C1();

	if (st0_tag == TAG_Valid) {
		long e;

		push();
		sign = getsign(st1_ptr);
		reg_copy(st1_ptr, st_new_ptr);
		setexponent16(st_new_ptr, exponent(st_new_ptr));

	      denormal_arg:

		e = exponent16(st_new_ptr);
		convert_l2reg(&e, 1);
		setexponentpos(st_new_ptr, 0);
		setsign(st_new_ptr, sign);
		FPU_settag0(TAG_Valid);	
		return;
	} else if (st0_tag == TAG_Zero) {
		sign = getsign(st0_ptr);

		if (FPU_divide_by_zero(0, SIGN_NEG) < 0)
			return;

		push();
		FPU_copy_to_reg0(&CONST_Z, TAG_Zero);
		setsign(st_new_ptr, sign);
		return;
	}

	if (st0_tag == TAG_Special)
		st0_tag = FPU_Special(st0_ptr);

	if (st0_tag == TW_Denormal) {
		if (denormal_operand() < 0)
			return;

		push();
		sign = getsign(st1_ptr);
		FPU_to_exp16(st1_ptr, st_new_ptr);
		goto denormal_arg;
	} else if (st0_tag == TW_Infinity) {
		sign = getsign(st0_ptr);
		setpositive(st0_ptr);
		push();
		FPU_copy_to_reg0(&CONST_INF, TAG_Special);
		setsign(st_new_ptr, sign);
		return;
	} else if (st0_tag == TW_NaN) {
		if (real_1op_NaN(st0_ptr) < 0)
			return;

		push();
		FPU_copy_to_reg0(st0_ptr, TAG_Special);
		return;
	} else if (st0_tag == TAG_Empty) {
		
		if (control_word & EX_Invalid) {
			FPU_stack_underflow();
			push();
			FPU_stack_underflow();
		} else
			EXCEPTION(EX_StackUnder);
	}
#ifdef PARANOID
	else
		EXCEPTION(EX_INTERNAL | 0x119);
#endif 
}
Пример #4
0
int FPU_load_store(u_char type, fpu_addr_modes addr_modes,
		     void __user *data_address)
{
  FPU_REG loaded_data;
  FPU_REG *st0_ptr;
  u_char st0_tag = TAG_Empty;  /* This is just to stop a gcc warning. */
  u_char loaded_tag;

  st0_ptr = NULL;    /* Initialized just to stop compiler warnings. */

  if ( addr_modes.default_mode & PROTECTED )
    {
      if ( addr_modes.default_mode == SEG32 )
	{
	  if ( access_limit < data_sizes_32[type] )
	    math_abort(FPU_info,SIGSEGV);
	}
      else if ( addr_modes.default_mode == PM16 )
	{
	  if ( access_limit < data_sizes_16[type] )
	    math_abort(FPU_info,SIGSEGV);
	}
#ifdef PARANOID
      else
	EXCEPTION(EX_INTERNAL|0x140);
#endif /* PARANOID */
    }

  switch ( type_table[type] )
    {
    case _NONE_:
      break;
    case _REG0_:
      st0_ptr = &st(0);       /* Some of these instructions pop after
				 storing */
      st0_tag = FPU_gettag0();
      break;
    case _PUSH_:
      {
	if ( FPU_gettagi(-1) != TAG_Empty )
	  { FPU_stack_overflow(); return 0; }
	top--;
	st0_ptr = &st(0);
      }
      break;
    case _null_:
      FPU_illegal();
      return 0;
#ifdef PARANOID
    default:
      EXCEPTION(EX_INTERNAL|0x141);
      return 0;
#endif /* PARANOID */
    }

  switch ( type )
    {
    case 000:       /* fld m32real */
      clear_C1();
      loaded_tag = FPU_load_single((float __user *)data_address, &loaded_data);
      if ( (loaded_tag == TAG_Special)
	   && isNaN(&loaded_data)
	   && (real_1op_NaN(&loaded_data) < 0) )
	{
	  top++;
	  break;
	}
      FPU_copy_to_reg0(&loaded_data, loaded_tag);
      break;
    case 001:      /* fild m32int */
      clear_C1();
      loaded_tag = FPU_load_int32((long __user *)data_address, &loaded_data);
      FPU_copy_to_reg0(&loaded_data, loaded_tag);
      break;
    case 002:      /* fld m64real */
      clear_C1();
      loaded_tag = FPU_load_double((double __user *)data_address, &loaded_data);
      if ( (loaded_tag == TAG_Special)
	   && isNaN(&loaded_data)
	   && (real_1op_NaN(&loaded_data) < 0) )
	{
	  top++;
	  break;
	}
      FPU_copy_to_reg0(&loaded_data, loaded_tag);
      break;
    case 003:      /* fild m16int */
      clear_C1();
      loaded_tag = FPU_load_int16((short __user *)data_address, &loaded_data);
      FPU_copy_to_reg0(&loaded_data, loaded_tag);
      break;
    case 010:      /* fst m32real */
      clear_C1();
      FPU_store_single(st0_ptr, st0_tag, (float __user *)data_address);
      break;
    case 011:      /* fist m32int */
      clear_C1();
      FPU_store_int32(st0_ptr, st0_tag, (long __user *)data_address);
      break;
    case 012:     /* fst m64real */
      clear_C1();
      FPU_store_double(st0_ptr, st0_tag, (double __user *)data_address);
      break;
    case 013:     /* fist m16int */
      clear_C1();
      FPU_store_int16(st0_ptr, st0_tag, (short __user *)data_address);
      break;
    case 014:     /* fstp m32real */
      clear_C1();
      if ( FPU_store_single(st0_ptr, st0_tag, (float __user *)data_address) )
	pop_0();  /* pop only if the number was actually stored
		     (see the 80486 manual p16-28) */
      break;
    case 015:     /* fistp m32int */
      clear_C1();
      if ( FPU_store_int32(st0_ptr, st0_tag, (long __user *)data_address) )
	pop_0();  /* pop only if the number was actually stored
		     (see the 80486 manual p16-28) */
      break;
    case 016:     /* fstp m64real */
      clear_C1();
      if ( FPU_store_double(st0_ptr, st0_tag, (double __user *)data_address) )
	pop_0();  /* pop only if the number was actually stored
		     (see the 80486 manual p16-28) */
      break;
    case 017:     /* fistp m16int */
      clear_C1();
      if ( FPU_store_int16(st0_ptr, st0_tag, (short __user *)data_address) )
	pop_0();  /* pop only if the number was actually stored
		     (see the 80486 manual p16-28) */
      break;
    case 020:     /* fldenv  m14/28byte */
      fldenv(addr_modes, (u_char __user *)data_address);
      /* Ensure that the values just loaded are not changed by
	 fix-up operations. */
      return 1;
    case 022:     /* frstor m94/108byte */
      frstor(addr_modes, (u_char __user *)data_address);
      /* Ensure that the values just loaded are not changed by
	 fix-up operations. */
      return 1;
    case 023:     /* fbld m80dec */
      clear_C1();
      loaded_tag = FPU_load_bcd((u_char __user *)data_address);
      FPU_settag0(loaded_tag);
      break;
    case 024:     /* fldcw */
      RE_ENTRANT_CHECK_OFF;
      FPU_verify_area(VERIFY_READ, data_address, 2);
      FPU_get_user(control_word, (unsigned short __user *) data_address);
      RE_ENTRANT_CHECK_ON;
      if ( partial_status & ~control_word & CW_Exceptions )
	partial_status |= (SW_Summary | SW_Backward);
      else
	partial_status &= ~(SW_Summary | SW_Backward);
#ifdef PECULIAR_486
      control_word |= 0x40;  /* An 80486 appears to always set this bit */
#endif /* PECULIAR_486 */
      return 1;
    case 025:      /* fld m80real */
      clear_C1();
      loaded_tag = FPU_load_extended((long double __user *)data_address, 0);
      FPU_settag0(loaded_tag);
      break;
    case 027:      /* fild m64int */
      clear_C1();
      loaded_tag = FPU_load_int64((long long __user *)data_address);
      FPU_settag0(loaded_tag);
      break;
    case 030:     /* fstenv  m14/28byte */
      fstenv(addr_modes, (u_char __user *)data_address);
      return 1;
    case 032:      /* fsave */
      fsave(addr_modes, (u_char __user *)data_address);
      return 1;
    case 033:      /* fbstp m80dec */
      clear_C1();
      if ( FPU_store_bcd(st0_ptr, st0_tag, (u_char __user *)data_address) )
	pop_0();  /* pop only if the number was actually stored
		     (see the 80486 manual p16-28) */
      break;
    case 034:      /* fstcw m16int */
      RE_ENTRANT_CHECK_OFF;
      FPU_verify_area(VERIFY_WRITE,data_address,2);
      FPU_put_user(control_word, (unsigned short __user *) data_address);
      RE_ENTRANT_CHECK_ON;
      return 1;
    case 035:      /* fstp m80real */
      clear_C1();
      if ( FPU_store_extended(st0_ptr, st0_tag, (long double __user *)data_address) )
	pop_0();  /* pop only if the number was actually stored
		     (see the 80486 manual p16-28) */
      break;
    case 036:      /* fstsw m2byte */
      RE_ENTRANT_CHECK_OFF;
      FPU_verify_area(VERIFY_WRITE,data_address,2);
      FPU_put_user(status_word(),(unsigned short __user *) data_address);
      RE_ENTRANT_CHECK_ON;
      return 1;
    case 037:      /* fistp m64int */
      clear_C1();
      if ( FPU_store_int64(st0_ptr, st0_tag, (long long __user *)data_address) )
	pop_0();  /* pop only if the number was actually stored
		     (see the 80486 manual p16-28) */
      break;
    }
  return 0;
}