コード例 #1
0
ファイル: fsincos.cpp プロジェクト: ralvaradoc/libsf
static floatx80 sincos_approximation(int neg, float128 r, Bit64u quotient, float_status_t &status)
{
    if (quotient & 0x1) {
        r = poly_cos(r, status);
        neg = 0;
    } else  {
        r = poly_sin(r, status);
    }

    floatx80 result = float128_to_floatx80(r, status);
    if (quotient & 0x2) 
        neg = ! neg;

    if (neg) 
        floatx80_chs(result);

    return result;
}
コード例 #2
0
ファイル: fsincos.c プロジェクト: AreaScout/mame-libretro
static floatx80 sincos_approximation(int neg, float128 r, UINT64 quotient)
{
	if (quotient & 0x1) {
		r = poly_cos(r);
		neg = 0;
	} else  {
		r = poly_sin(r);
	}

	floatx80 result = float128_to_floatx80(r);
	if (quotient & 0x2)
		neg = ! neg;

	if (neg)
		result = floatx80_chs(result);

	return result;
}
コード例 #3
0
ファイル: fpu_load_store.cpp プロジェクト: hack477/bochs4wii
/* DF /4 */
void BX_CPP_AttrRegparmN(1) BX_CPU_C::FBLD_PACKED_BCD(bxInstruction_c *i)
{
#if BX_SUPPORT_FPU
  BX_CPU_THIS_PTR prepareFPU(i);

  // read packed bcd from memory
  Bit16u hi2 = read_virtual_word (i->seg(), RMAddr(i) + 8);
  Bit64u lo8 = read_virtual_qword(i->seg(), RMAddr(i));

  clear_C1();

  if (! IS_TAG_EMPTY(-1))
  {
    BX_CPU_THIS_PTR FPU_stack_overflow();
    return;
  }

  // convert packed BCD to 64-bit integer
  Bit64s scale = 1;
  Bit64s val64 = 0;

  for (int n = 0; n < 16; n++)
  {
    val64 += (lo8 & 0x0f) * scale;
    lo8 >>= 4;
    scale *= 10;
  }

  val64 += (hi2 & 0x0f) * scale;
  val64 += ((hi2>>4) & 0x0f) * scale * 10;

  floatx80 result = int64_to_floatx80(val64);
  if (hi2 & 0x8000)	// set negative
      floatx80_chs(result);

  BX_CPU_THIS_PTR the_i387.FPU_push();
  BX_WRITE_FPU_REG(result, 0);
#else
  BX_INFO(("FBLD_PACKED_BCD: required FPU, configure --enable-fpu"));
#endif
}
コード例 #4
0
ファイル: fpu_load_store.cpp プロジェクト: iver6/BA
/* DF /4 */
BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::FBLD_PACKED_BCD(bxInstruction_c *i)
{
  BX_CPU_THIS_PTR prepareFPU(i);

  RMAddr(i) = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
  Bit16u hi2 = read_virtual_word(i->seg(), (RMAddr(i) + 8) & i->asize_mask());
  Bit64u lo8 = read_virtual_qword(i->seg(), RMAddr(i));

  FPU_update_last_instruction(i);

  clear_C1();

  if (! IS_TAG_EMPTY(-1))
  {
    FPU_stack_overflow();
    BX_NEXT_INSTR(i);
  }

  // convert packed BCD to 64-bit integer
  Bit64s scale = 1;
  Bit64s val64 = 0;

  for (int n = 0; n < 16; n++)
  {
    val64 += (lo8 & 0x0f) * scale;
    lo8 >>= 4;
    scale *= 10;
  }

  val64 += (hi2 & 0x0f) * scale;
  val64 += ((hi2>>4) & 0x0f) * scale * 10;

  floatx80 result = int64_to_floatx80(val64);
  if (hi2 & 0x8000)        // set negative
      floatx80_chs(result);

  BX_CPU_THIS_PTR the_i387.FPU_push();
  BX_WRITE_FPU_REG(result, 0);

  BX_NEXT_INSTR(i);
}
コード例 #5
0
ファイル: fsincos.cpp プロジェクト: ralvaradoc/libsf
int ftan(floatx80 &a, float_status_t &status)
{
    Bit64u aSig0, aSig1 = 0;
    Bit32s aExp, zExp, expDiff;
    int aSign, zSign; 
    int q = 0;

    // handle unsupported extended double-precision floating encodings
    if (floatx80_is_unsupported(a)) 
    {
        goto invalid;
    }

    aSig0 = extractFloatx80Frac(a);
    aExp = extractFloatx80Exp(a);
    aSign = extractFloatx80Sign(a);
     
    /* invalid argument */
    if (aExp == 0x7FFF) {
        if ((Bit64u) (aSig0<<1))
        {
            a = propagateFloatx80NaN(a, status);
            return 0;
        }

    invalid:
        float_raise(status, float_flag_invalid);
        a = floatx80_default_nan;
        return 0;
    }

    if (aExp == 0) {
        if (aSig0 == 0) return 0;
        float_raise(status, float_flag_denormal);
        /* handle pseudo denormals */
        if (! (aSig0 & BX_CONST64(0x8000000000000000)))
        {
            float_raise(status, float_flag_inexact | float_flag_underflow);
            return 0;
        }
        normalizeFloatx80Subnormal(aSig0, &aExp, &aSig0);
    }
    
    zSign = aSign;
    zExp = EXP_BIAS;
    expDiff = aExp - zExp;

    /* argument is out-of-range */
    if (expDiff >= 63) 
        return -1;

    float_raise(status, float_flag_inexact);

    if (expDiff < -1) {    // doesn't require reduction
        if (expDiff <= -68) {
            a = packFloatx80(aSign, aExp, aSig0);
            return 0;
        }
        zExp = aExp;
    }
    else {
        q = reduce_trig_arg(expDiff, zSign, aSig0, aSig1);
    }

    /* **************************** */
    /* argument reduction completed */
    /* **************************** */

    /* using float128 for approximation */
    float128 r = normalizeRoundAndPackFloat128(0, zExp-0x10, aSig0, aSig1, status);

    float128 sin_r = poly_sin(r, status);
    float128 cos_r = poly_cos(r, status);

    if (q & 0x1) {
        r = float128_div(cos_r, sin_r, status);
        zSign = ! zSign;
    } else {
        r = float128_div(sin_r, cos_r, status);
    }

    a = float128_to_floatx80(r, status);
    if (zSign)
        floatx80_chs(a);

    return 0;
}
コード例 #6
0
ファイル: fsincos.c プロジェクト: AreaScout/mame-libretro
int floatx80_ftan(floatx80 &a)
{
	UINT64 aSig0, aSig1 = 0;
	INT32 aExp, zExp, expDiff;
	int aSign, zSign;
	int q = 0;

	aSig0 = extractFloatx80Frac(a);
	aExp = extractFloatx80Exp(a);
	aSign = extractFloatx80Sign(a);

	/* invalid argument */
	if (aExp == 0x7FFF) {
		if ((UINT64) (aSig0<<1))
		{
			a = propagateFloatx80NaNOneArg(a);
			return 0;
		}

		float_raise(float_flag_invalid);
		a = floatx80_default_nan;
		return 0;
	}

	if (aExp == 0) {
		if (aSig0 == 0) return 0;
//        float_raise(float_flag_denormal);
		/* handle pseudo denormals */
		if (! (aSig0 & U64(0x8000000000000000)))
		{
			float_raise(float_flag_inexact | float_flag_underflow);
			return 0;
		}
		normalizeFloatx80Subnormal(aSig0, &aExp, &aSig0);
	}

	zSign = aSign;
	zExp = EXP_BIAS;
	expDiff = aExp - zExp;

	/* argument is out-of-range */
	if (expDiff >= 63)
		return -1;

	float_raise(float_flag_inexact);

	if (expDiff < -1) {    // doesn't require reduction
		if (expDiff <= -68) {
			a = packFloatx80(aSign, aExp, aSig0);
			return 0;
		}
		zExp = aExp;
	}
	else {
		q = reduce_trig_arg(expDiff, zSign, aSig0, aSig1);
	}

	/* **************************** */
	/* argument reduction completed */
	/* **************************** */

	/* using float128 for approximation */
	float128 r = normalizeRoundAndPackFloat128(0, zExp-0x10, aSig0, aSig1);

	float128 sin_r = poly_sin(r);
	float128 cos_r = poly_cos(r);

	if (q & 0x1) {
		r = float128_div(cos_r, sin_r);
		zSign = ! zSign;
	} else {
		r = float128_div(sin_r, cos_r);
	}

	a = float128_to_floatx80(r);
	if (zSign)
		a = floatx80_chs(a);

	return 0;
}
コード例 #7
0
ファイル: fpatan.cpp プロジェクト: iver6/BA
floatx80 fpatan(floatx80 a, floatx80 b, float_status_t &status)
{
    // handle unsupported extended double-precision floating encodings
    if (floatx80_is_unsupported(a) || floatx80_is_unsupported(b)) {
        float_raise(status, float_flag_invalid);
        return floatx80_default_nan;
    }

    Bit64u aSig = extractFloatx80Frac(a);
    Bit32s aExp = extractFloatx80Exp(a);
    int aSign = extractFloatx80Sign(a);
    Bit64u bSig = extractFloatx80Frac(b);
    Bit32s bExp = extractFloatx80Exp(b);
    int bSign = extractFloatx80Sign(b);

    int zSign = aSign ^ bSign;

    if (bExp == 0x7FFF)
    {
        if ((Bit64u) (bSig<<1))
            return propagateFloatx80NaN(a, b, status);

        if (aExp == 0x7FFF) {
            if ((Bit64u) (aSig<<1))
                return propagateFloatx80NaN(a, b, status);

            if (aSign) {   /* return 3PI/4 */
                return roundAndPackFloatx80(80, bSign,
                        FLOATX80_3PI4_EXP, FLOAT_3PI4_HI, FLOAT_3PI4_LO, status);
            }
            else {         /* return  PI/4 */
                return roundAndPackFloatx80(80, bSign,
                        FLOATX80_PI4_EXP, FLOAT_PI_HI, FLOAT_PI_LO, status);
            }
        }

        if (aSig && (aExp == 0))
            float_raise(status, float_flag_denormal);

        /* return PI/2 */
        return roundAndPackFloatx80(80, bSign, FLOATX80_PI2_EXP, FLOAT_PI_HI, FLOAT_PI_LO, status);
    }
    if (aExp == 0x7FFF)
    {
        if ((Bit64u) (aSig<<1))
            return propagateFloatx80NaN(a, b, status);

        if (bSig && (bExp == 0))
            float_raise(status, float_flag_denormal);

return_PI_or_ZERO:

        if (aSign) {   /* return PI */
            return roundAndPackFloatx80(80, bSign, FLOATX80_PI_EXP, FLOAT_PI_HI, FLOAT_PI_LO, status);
        } else {       /* return  0 */
            return packFloatx80(bSign, 0, 0);
        }
    }
    if (bExp == 0)
    {
        if (bSig == 0) {
             if (aSig && (aExp == 0)) float_raise(status, float_flag_denormal);
             goto return_PI_or_ZERO;
        }

        float_raise(status, float_flag_denormal);
        normalizeFloatx80Subnormal(bSig, &bExp, &bSig);
    }
    if (aExp == 0)
    {
        if (aSig == 0)   /* return PI/2 */
            return roundAndPackFloatx80(80, bSign, FLOATX80_PI2_EXP, FLOAT_PI_HI, FLOAT_PI_LO, status);

        float_raise(status, float_flag_denormal);
        normalizeFloatx80Subnormal(aSig, &aExp, &aSig);
    }

    float_raise(status, float_flag_inexact);

    /* |a| = |b| ==> return PI/4 */
    if (aSig == bSig && aExp == bExp)
        return roundAndPackFloatx80(80, bSign, FLOATX80_PI4_EXP, FLOAT_PI_HI, FLOAT_PI_LO, status);

    /* ******************************** */
    /* using float128 for approximation */
    /* ******************************** */

    float128 a128 = normalizeRoundAndPackFloat128(0, aExp-0x10, aSig, 0, status);
    float128 b128 = normalizeRoundAndPackFloat128(0, bExp-0x10, bSig, 0, status);
    float128 x;
    int swap = 0, add_pi6 = 0, add_pi4 = 0;

    if (aExp > bExp || (aExp == bExp && aSig > bSig))
    {
        x = float128_div(b128, a128, status);
    }
    else {
        x = float128_div(a128, b128, status);
        swap = 1;
    }

    Bit32s xExp = extractFloat128Exp(x);

    if (xExp <= EXP_BIAS-40)
        goto approximation_completed;

    if (x.hi >= BX_CONST64(0x3ffe800000000000))        // 3/4 < x < 1
    {
        /*
        arctan(x) = arctan((x-1)/(x+1)) + pi/4
        */
        float128 t1 = float128_sub(x, float128_one, status);
        float128 t2 = float128_add(x, float128_one, status);
        x = float128_div(t1, t2, status);
        add_pi4 = 1;
    }
    else
    {
        /* argument correction */
        if (xExp >= 0x3FFD)                     // 1/4 < x < 3/4
        {
            /*
            arctan(x) = arctan((x*sqrt(3)-1)/(x+sqrt(3))) + pi/6
            */
            float128 t1 = float128_mul(x, float128_sqrt3, status);
            float128 t2 = float128_add(x, float128_sqrt3, status);
            x = float128_sub(t1, float128_one, status);
            x = float128_div(x, t2, status);
            add_pi6 = 1;
        }
    }

    x = poly_atan(x, status);
    if (add_pi6) x = float128_add(x, float128_pi6, status);
    if (add_pi4) x = float128_add(x, float128_pi4, status);

approximation_completed:
    if (swap) x = float128_sub(float128_pi2, x, status);
    floatx80 result = float128_to_floatx80(x, status);
    if (zSign) floatx80_chs(result);
    int rSign = extractFloatx80Sign(result);
    if (!bSign && rSign)
        return floatx80_add(result, floatx80_pi, status);
    if (bSign && !rSign)
        return floatx80_sub(result, floatx80_pi, status);
    return result;
}