* [Qemu-devel] [PULL 00/11] M68k for 2.12 patches
@ 2018-03-13 15:59 Laurent Vivier
2018-03-13 15:59 ` [Qemu-devel] [PULL 01/11] target/m68k: implement ftan Laurent Vivier
` (11 more replies)
0 siblings, 12 replies; 15+ messages in thread
From: Laurent Vivier @ 2018-03-13 15:59 UTC (permalink / raw)
To: qemu-devel; +Cc: Laurent Vivier
The following changes since commit 59667bb167f773965ce6547352f312eff0d4d523:
Merge remote-tracking branch 'remotes/ehabkost/tags/x86-next-pull-request' into staging (2018-03-13 14:02:47 +0000)
are available in the Git repository at:
git://github.com/vivier/qemu-m68k.git tags/m68k-for-2.12-pull-request
for you to fetch changes up to 02f9124ebe26c36f0f7ed58085bd963e4372b2cd:
target/m68k: implement fcosh (2018-03-13 16:35:05 +0100)
----------------------------------------------------------------
----------------------------------------------------------------
Laurent Vivier (11):
target/m68k: implement ftan
target/m68k: implement fsin
target/m68k: implement fcos
target/m68k: implement fsincos
target/m68k: implement fatan
target/m68k: implement fasin
target/m68k: implement facos
target/m68k: implement fatanh
target/m68k: implement ftanh
target/m68k: implement fsinh
target/m68k: implement fcosh
target/m68k/fpu_helper.c | 61 ++
target/m68k/helper.h | 11 +
target/m68k/softfloat.c | 1637 +++++++++++++++++++++++++++++++++++
target/m68k/softfloat.h | 11 +
target/m68k/softfloat_fpsp_tables.h | 267 ++++++
target/m68k/translate.c | 38 +
6 files changed, 2025 insertions(+)
--
2.14.3
^ permalink raw reply [flat|nested] 15+ messages in thread
* [Qemu-devel] [PULL 01/11] target/m68k: implement ftan
2018-03-13 15:59 [Qemu-devel] [PULL 00/11] M68k for 2.12 patches Laurent Vivier
@ 2018-03-13 15:59 ` Laurent Vivier
2018-03-13 15:59 ` [Qemu-devel] [PULL 02/11] target/m68k: implement fsin Laurent Vivier
` (10 subsequent siblings)
11 siblings, 0 replies; 15+ messages in thread
From: Laurent Vivier @ 2018-03-13 15:59 UTC (permalink / raw)
To: qemu-devel; +Cc: Laurent Vivier
Using a local m68k floatx80_tan()
[copied from previous:
Written by Andreas Grabher for Previous, NeXT Computer Emulator.]
Signed-off-by: Laurent Vivier <laurent@vivier.eu>
Message-Id: <20180312202728.23790-2-laurent@vivier.eu>
---
target/m68k/fpu_helper.c | 5 +
target/m68k/helper.h | 1 +
target/m68k/softfloat.c | 210 ++++++++++++++++++++++++++++++++++++
target/m68k/softfloat.h | 1 +
target/m68k/softfloat_fpsp_tables.h | 136 +++++++++++++++++++++++
target/m68k/translate.c | 3 +
6 files changed, 356 insertions(+)
diff --git a/target/m68k/fpu_helper.c b/target/m68k/fpu_helper.c
index 62cbb0dff1..c41115ea05 100644
--- a/target/m68k/fpu_helper.c
+++ b/target/m68k/fpu_helper.c
@@ -592,3 +592,8 @@ void HELPER(ftentox)(CPUM68KState *env, FPReg *res, FPReg *val)
{
res->d = floatx80_tentox(val->d, &env->fp_status);
}
+
+void HELPER(ftan)(CPUM68KState *env, FPReg *res, FPReg *val)
+{
+ res->d = floatx80_tan(val->d, &env->fp_status);
+}
diff --git a/target/m68k/helper.h b/target/m68k/helper.h
index 9a9734c196..af9480fe49 100644
--- a/target/m68k/helper.h
+++ b/target/m68k/helper.h
@@ -75,6 +75,7 @@ DEF_HELPER_3(flog2, void, env, fp, fp)
DEF_HELPER_3(fetox, void, env, fp, fp)
DEF_HELPER_3(ftwotox, void, env, fp, fp)
DEF_HELPER_3(ftentox, void, env, fp, fp)
+DEF_HELPER_3(ftan, void, env, fp, fp)
DEF_HELPER_3(mac_move, void, env, i32, i32)
DEF_HELPER_3(macmulf, i64, env, i32, i32)
diff --git a/target/m68k/softfloat.c b/target/m68k/softfloat.c
index 4bd5b9e6b7..488dbc522b 100644
--- a/target/m68k/softfloat.c
+++ b/target/m68k/softfloat.c
@@ -1266,3 +1266,213 @@ floatx80 floatx80_tentox(floatx80 a, float_status *status)
return a;
}
}
+
+/*----------------------------------------------------------------------------
+ | Tangent
+ *----------------------------------------------------------------------------*/
+
+floatx80 floatx80_tan(floatx80 a, float_status *status)
+{
+ flag aSign, xSign;
+ int32_t aExp, xExp;
+ uint64_t aSig, xSig;
+
+ int8_t user_rnd_mode, user_rnd_prec;
+
+ int32_t compact, l, n, j;
+ floatx80 fp0, fp1, fp2, fp3, fp4, fp5, invtwopi, twopi1, twopi2;
+ float32 twoto63;
+ flag endflag;
+
+ aSig = extractFloatx80Frac(a);
+ aExp = extractFloatx80Exp(a);
+ aSign = extractFloatx80Sign(a);
+
+ if (aExp == 0x7FFF) {
+ if ((uint64_t) (aSig << 1)) {
+ return propagateFloatx80NaNOneArg(a, status);
+ }
+ float_raise(float_flag_invalid, status);
+ return floatx80_default_nan(status);
+ }
+
+ if (aExp == 0 && aSig == 0) {
+ return packFloatx80(aSign, 0, 0);
+ }
+
+ user_rnd_mode = status->float_rounding_mode;
+ user_rnd_prec = status->floatx80_rounding_precision;
+ status->float_rounding_mode = float_round_nearest_even;
+ status->floatx80_rounding_precision = 80;
+
+ compact = floatx80_make_compact(aExp, aSig);
+
+ fp0 = a;
+
+ if (compact < 0x3FD78000 || compact > 0x4004BC7E) {
+ /* 2^(-40) > |X| > 15 PI */
+ if (compact > 0x3FFF8000) { /* |X| >= 15 PI */
+ /* REDUCEX */
+ fp1 = packFloatx80(0, 0, 0);
+ if (compact == 0x7FFEFFFF) {
+ twopi1 = packFloatx80(aSign ^ 1, 0x7FFE,
+ LIT64(0xC90FDAA200000000));
+ twopi2 = packFloatx80(aSign ^ 1, 0x7FDC,
+ LIT64(0x85A308D300000000));
+ fp0 = floatx80_add(fp0, twopi1, status);
+ fp1 = fp0;
+ fp0 = floatx80_add(fp0, twopi2, status);
+ fp1 = floatx80_sub(fp1, fp0, status);
+ fp1 = floatx80_add(fp1, twopi2, status);
+ }
+ loop:
+ xSign = extractFloatx80Sign(fp0);
+ xExp = extractFloatx80Exp(fp0);
+ xExp -= 0x3FFF;
+ if (xExp <= 28) {
+ l = 0;
+ endflag = 1;
+ } else {
+ l = xExp - 27;
+ endflag = 0;
+ }
+ invtwopi = packFloatx80(0, 0x3FFE - l,
+ LIT64(0xA2F9836E4E44152A)); /* INVTWOPI */
+ twopi1 = packFloatx80(0, 0x3FFF + l, LIT64(0xC90FDAA200000000));
+ twopi2 = packFloatx80(0, 0x3FDD + l, LIT64(0x85A308D300000000));
+
+ /* SIGN(INARG)*2^63 IN SGL */
+ twoto63 = packFloat32(xSign, 0xBE, 0);
+
+ fp2 = floatx80_mul(fp0, invtwopi, status);
+ fp2 = floatx80_add(fp2, float32_to_floatx80(twoto63, status),
+ status); /* THE FRACT PART OF FP2 IS ROUNDED */
+ fp2 = floatx80_sub(fp2, float32_to_floatx80(twoto63, status),
+ status); /* FP2 is N */
+ fp4 = floatx80_mul(twopi1, fp2, status); /* W = N*P1 */
+ fp5 = floatx80_mul(twopi2, fp2, status); /* w = N*P2 */
+ fp3 = floatx80_add(fp4, fp5, status); /* FP3 is P */
+ fp4 = floatx80_sub(fp4, fp3, status); /* W-P */
+ fp0 = floatx80_sub(fp0, fp3, status); /* FP0 is A := R - P */
+ fp4 = floatx80_add(fp4, fp5, status); /* FP4 is p = (W-P)+w */
+ fp3 = fp0; /* FP3 is A */
+ fp1 = floatx80_sub(fp1, fp4, status); /* FP1 is a := r - p */
+ fp0 = floatx80_add(fp0, fp1, status); /* FP0 is R := A+a */
+
+ if (endflag > 0) {
+ n = floatx80_to_int32(fp2, status);
+ goto tancont;
+ }
+ fp3 = floatx80_sub(fp3, fp0, status); /* A-R */
+ fp1 = floatx80_add(fp1, fp3, status); /* FP1 is r := (A-R)+a */
+ goto loop;
+ } else {
+ status->float_rounding_mode = user_rnd_mode;
+ status->floatx80_rounding_precision = user_rnd_prec;
+
+ a = floatx80_move(a, status);
+
+ float_raise(float_flag_inexact, status);
+
+ return a;
+ }
+ } else {
+ fp1 = floatx80_mul(fp0, float64_to_floatx80(
+ make_float64(0x3FE45F306DC9C883), status),
+ status); /* X*2/PI */
+
+ n = floatx80_to_int32(fp1, status);
+ j = 32 + n;
+
+ fp0 = floatx80_sub(fp0, pi_tbl[j], status); /* X-Y1 */
+ fp0 = floatx80_sub(fp0, float32_to_floatx80(pi_tbl2[j], status),
+ status); /* FP0 IS R = (X-Y1)-Y2 */
+
+ tancont:
+ if (n & 1) {
+ /* NODD */
+ fp1 = fp0; /* R */
+ fp0 = floatx80_mul(fp0, fp0, status); /* S = R*R */
+ fp3 = float64_to_floatx80(make_float64(0x3EA0B759F50F8688),
+ status); /* Q4 */
+ fp2 = float64_to_floatx80(make_float64(0xBEF2BAA5A8924F04),
+ status); /* P3 */
+ fp3 = floatx80_mul(fp3, fp0, status); /* SQ4 */
+ fp2 = floatx80_mul(fp2, fp0, status); /* SP3 */
+ fp3 = floatx80_add(fp3, float64_to_floatx80(
+ make_float64(0xBF346F59B39BA65F), status),
+ status); /* Q3+SQ4 */
+ fp4 = packFloatx80(0, 0x3FF6, LIT64(0xE073D3FC199C4A00));
+ fp2 = floatx80_add(fp2, fp4, status); /* P2+SP3 */
+ fp3 = floatx80_mul(fp3, fp0, status); /* S(Q3+SQ4) */
+ fp2 = floatx80_mul(fp2, fp0, status); /* S(P2+SP3) */
+ fp4 = packFloatx80(0, 0x3FF9, LIT64(0xD23CD68415D95FA1));
+ fp3 = floatx80_add(fp3, fp4, status); /* Q2+S(Q3+SQ4) */
+ fp4 = packFloatx80(1, 0x3FFC, LIT64(0x8895A6C5FB423BCA));
+ fp2 = floatx80_add(fp2, fp4, status); /* P1+S(P2+SP3) */
+ fp3 = floatx80_mul(fp3, fp0, status); /* S(Q2+S(Q3+SQ4)) */
+ fp2 = floatx80_mul(fp2, fp0, status); /* S(P1+S(P2+SP3)) */
+ fp4 = packFloatx80(1, 0x3FFD, LIT64(0xEEF57E0DA84BC8CE));
+ fp3 = floatx80_add(fp3, fp4, status); /* Q1+S(Q2+S(Q3+SQ4)) */
+ fp2 = floatx80_mul(fp2, fp1, status); /* RS(P1+S(P2+SP3)) */
+ fp0 = floatx80_mul(fp0, fp3, status); /* S(Q1+S(Q2+S(Q3+SQ4))) */
+ fp1 = floatx80_add(fp1, fp2, status); /* R+RS(P1+S(P2+SP3)) */
+ fp0 = floatx80_add(fp0, float32_to_floatx80(
+ make_float32(0x3F800000), status),
+ status); /* 1+S(Q1+S(Q2+S(Q3+SQ4))) */
+
+ xSign = extractFloatx80Sign(fp1);
+ xExp = extractFloatx80Exp(fp1);
+ xSig = extractFloatx80Frac(fp1);
+ xSign ^= 1;
+ fp1 = packFloatx80(xSign, xExp, xSig);
+
+ status->float_rounding_mode = user_rnd_mode;
+ status->floatx80_rounding_precision = user_rnd_prec;
+
+ a = floatx80_div(fp0, fp1, status);
+
+ float_raise(float_flag_inexact, status);
+
+ return a;
+ } else {
+ fp1 = floatx80_mul(fp0, fp0, status); /* S = R*R */
+ fp3 = float64_to_floatx80(make_float64(0x3EA0B759F50F8688),
+ status); /* Q4 */
+ fp2 = float64_to_floatx80(make_float64(0xBEF2BAA5A8924F04),
+ status); /* P3 */
+ fp3 = floatx80_mul(fp3, fp1, status); /* SQ4 */
+ fp2 = floatx80_mul(fp2, fp1, status); /* SP3 */
+ fp3 = floatx80_add(fp3, float64_to_floatx80(
+ make_float64(0xBF346F59B39BA65F), status),
+ status); /* Q3+SQ4 */
+ fp4 = packFloatx80(0, 0x3FF6, LIT64(0xE073D3FC199C4A00));
+ fp2 = floatx80_add(fp2, fp4, status); /* P2+SP3 */
+ fp3 = floatx80_mul(fp3, fp1, status); /* S(Q3+SQ4) */
+ fp2 = floatx80_mul(fp2, fp1, status); /* S(P2+SP3) */
+ fp4 = packFloatx80(0, 0x3FF9, LIT64(0xD23CD68415D95FA1));
+ fp3 = floatx80_add(fp3, fp4, status); /* Q2+S(Q3+SQ4) */
+ fp4 = packFloatx80(1, 0x3FFC, LIT64(0x8895A6C5FB423BCA));
+ fp2 = floatx80_add(fp2, fp4, status); /* P1+S(P2+SP3) */
+ fp3 = floatx80_mul(fp3, fp1, status); /* S(Q2+S(Q3+SQ4)) */
+ fp2 = floatx80_mul(fp2, fp1, status); /* S(P1+S(P2+SP3)) */
+ fp4 = packFloatx80(1, 0x3FFD, LIT64(0xEEF57E0DA84BC8CE));
+ fp3 = floatx80_add(fp3, fp4, status); /* Q1+S(Q2+S(Q3+SQ4)) */
+ fp2 = floatx80_mul(fp2, fp0, status); /* RS(P1+S(P2+SP3)) */
+ fp1 = floatx80_mul(fp1, fp3, status); /* S(Q1+S(Q2+S(Q3+SQ4))) */
+ fp0 = floatx80_add(fp0, fp2, status); /* R+RS(P1+S(P2+SP3)) */
+ fp1 = floatx80_add(fp1, float32_to_floatx80(
+ make_float32(0x3F800000), status),
+ status); /* 1+S(Q1+S(Q2+S(Q3+SQ4))) */
+
+ status->float_rounding_mode = user_rnd_mode;
+ status->floatx80_rounding_precision = user_rnd_prec;
+
+ a = floatx80_div(fp0, fp1, status);
+
+ float_raise(float_flag_inexact, status);
+
+ return a;
+ }
+ }
+}
diff --git a/target/m68k/softfloat.h b/target/m68k/softfloat.h
index d28e49fe9f..c5ac54d87b 100644
--- a/target/m68k/softfloat.h
+++ b/target/m68k/softfloat.h
@@ -34,4 +34,5 @@ floatx80 floatx80_log2(floatx80 a, float_status *status);
floatx80 floatx80_etox(floatx80 a, float_status *status);
floatx80 floatx80_twotox(floatx80 a, float_status *status);
floatx80 floatx80_tentox(floatx80 a, float_status *status);
+floatx80 floatx80_tan(floatx80 a, float_status *status);
#endif
diff --git a/target/m68k/softfloat_fpsp_tables.h b/target/m68k/softfloat_fpsp_tables.h
index dd76dc0373..a9c86a5af2 100644
--- a/target/m68k/softfloat_fpsp_tables.h
+++ b/target/m68k/softfloat_fpsp_tables.h
@@ -371,4 +371,140 @@ static const uint32_t exp2_tbl2[64] = {
0xBFBDBF4A, 0x3FBEC01A, 0x3FBE8CAC, 0xBFBCBB3F,
0x3FBEF73A, 0xBFB8B795, 0x3FBEF84B, 0xBFBEF581
};
+
+static const floatx80 pi_tbl[65] = {
+ make_floatx80_init(0xC004, 0xC90FDAA22168C235),
+ make_floatx80_init(0xC004, 0xC2C75BCD105D7C23),
+ make_floatx80_init(0xC004, 0xBC7EDCF7FF523611),
+ make_floatx80_init(0xC004, 0xB6365E22EE46F000),
+ make_floatx80_init(0xC004, 0xAFEDDF4DDD3BA9EE),
+ make_floatx80_init(0xC004, 0xA9A56078CC3063DD),
+ make_floatx80_init(0xC004, 0xA35CE1A3BB251DCB),
+ make_floatx80_init(0xC004, 0x9D1462CEAA19D7B9),
+ make_floatx80_init(0xC004, 0x96CBE3F9990E91A8),
+ make_floatx80_init(0xC004, 0x9083652488034B96),
+ make_floatx80_init(0xC004, 0x8A3AE64F76F80584),
+ make_floatx80_init(0xC004, 0x83F2677A65ECBF73),
+ make_floatx80_init(0xC003, 0xFB53D14AA9C2F2C2),
+ make_floatx80_init(0xC003, 0xEEC2D3A087AC669F),
+ make_floatx80_init(0xC003, 0xE231D5F66595DA7B),
+ make_floatx80_init(0xC003, 0xD5A0D84C437F4E58),
+ make_floatx80_init(0xC003, 0xC90FDAA22168C235),
+ make_floatx80_init(0xC003, 0xBC7EDCF7FF523611),
+ make_floatx80_init(0xC003, 0xAFEDDF4DDD3BA9EE),
+ make_floatx80_init(0xC003, 0xA35CE1A3BB251DCB),
+ make_floatx80_init(0xC003, 0x96CBE3F9990E91A8),
+ make_floatx80_init(0xC003, 0x8A3AE64F76F80584),
+ make_floatx80_init(0xC002, 0xFB53D14AA9C2F2C2),
+ make_floatx80_init(0xC002, 0xE231D5F66595DA7B),
+ make_floatx80_init(0xC002, 0xC90FDAA22168C235),
+ make_floatx80_init(0xC002, 0xAFEDDF4DDD3BA9EE),
+ make_floatx80_init(0xC002, 0x96CBE3F9990E91A8),
+ make_floatx80_init(0xC001, 0xFB53D14AA9C2F2C2),
+ make_floatx80_init(0xC001, 0xC90FDAA22168C235),
+ make_floatx80_init(0xC001, 0x96CBE3F9990E91A8),
+ make_floatx80_init(0xC000, 0xC90FDAA22168C235),
+ make_floatx80_init(0xBFFF, 0xC90FDAA22168C235),
+ make_floatx80_init(0x0000, 0x0000000000000000),
+ make_floatx80_init(0x3FFF, 0xC90FDAA22168C235),
+ make_floatx80_init(0x4000, 0xC90FDAA22168C235),
+ make_floatx80_init(0x4001, 0x96CBE3F9990E91A8),
+ make_floatx80_init(0x4001, 0xC90FDAA22168C235),
+ make_floatx80_init(0x4001, 0xFB53D14AA9C2F2C2),
+ make_floatx80_init(0x4002, 0x96CBE3F9990E91A8),
+ make_floatx80_init(0x4002, 0xAFEDDF4DDD3BA9EE),
+ make_floatx80_init(0x4002, 0xC90FDAA22168C235),
+ make_floatx80_init(0x4002, 0xE231D5F66595DA7B),
+ make_floatx80_init(0x4002, 0xFB53D14AA9C2F2C2),
+ make_floatx80_init(0x4003, 0x8A3AE64F76F80584),
+ make_floatx80_init(0x4003, 0x96CBE3F9990E91A8),
+ make_floatx80_init(0x4003, 0xA35CE1A3BB251DCB),
+ make_floatx80_init(0x4003, 0xAFEDDF4DDD3BA9EE),
+ make_floatx80_init(0x4003, 0xBC7EDCF7FF523611),
+ make_floatx80_init(0x4003, 0xC90FDAA22168C235),
+ make_floatx80_init(0x4003, 0xD5A0D84C437F4E58),
+ make_floatx80_init(0x4003, 0xE231D5F66595DA7B),
+ make_floatx80_init(0x4003, 0xEEC2D3A087AC669F),
+ make_floatx80_init(0x4003, 0xFB53D14AA9C2F2C2),
+ make_floatx80_init(0x4004, 0x83F2677A65ECBF73),
+ make_floatx80_init(0x4004, 0x8A3AE64F76F80584),
+ make_floatx80_init(0x4004, 0x9083652488034B96),
+ make_floatx80_init(0x4004, 0x96CBE3F9990E91A8),
+ make_floatx80_init(0x4004, 0x9D1462CEAA19D7B9),
+ make_floatx80_init(0x4004, 0xA35CE1A3BB251DCB),
+ make_floatx80_init(0x4004, 0xA9A56078CC3063DD),
+ make_floatx80_init(0x4004, 0xAFEDDF4DDD3BA9EE),
+ make_floatx80_init(0x4004, 0xB6365E22EE46F000),
+ make_floatx80_init(0x4004, 0xBC7EDCF7FF523611),
+ make_floatx80_init(0x4004, 0xC2C75BCD105D7C23),
+ make_floatx80_init(0x4004, 0xC90FDAA22168C235)
+};
+
+static const float32 pi_tbl2[65] = {
+ const_float32(0x21800000),
+ const_float32(0xA0D00000),
+ const_float32(0xA1E80000),
+ const_float32(0x21480000),
+ const_float32(0xA1200000),
+ const_float32(0x21FC0000),
+ const_float32(0x21100000),
+ const_float32(0xA1580000),
+ const_float32(0x21E00000),
+ const_float32(0x20B00000),
+ const_float32(0xA1880000),
+ const_float32(0x21C40000),
+ const_float32(0x20000000),
+ const_float32(0x21380000),
+ const_float32(0xA1300000),
+ const_float32(0x9FC00000),
+ const_float32(0x21000000),
+ const_float32(0xA1680000),
+ const_float32(0xA0A00000),
+ const_float32(0x20900000),
+ const_float32(0x21600000),
+ const_float32(0xA1080000),
+ const_float32(0x1F800000),
+ const_float32(0xA0B00000),
+ const_float32(0x20800000),
+ const_float32(0xA0200000),
+ const_float32(0x20E00000),
+ const_float32(0x1F000000),
+ const_float32(0x20000000),
+ const_float32(0x20600000),
+ const_float32(0x1F800000),
+ const_float32(0x1F000000),
+ const_float32(0x00000000),
+ const_float32(0x9F000000),
+ const_float32(0x9F800000),
+ const_float32(0xA0600000),
+ const_float32(0xA0000000),
+ const_float32(0x9F000000),
+ const_float32(0xA0E00000),
+ const_float32(0x20200000),
+ const_float32(0xA0800000),
+ const_float32(0x20B00000),
+ const_float32(0x9F800000),
+ const_float32(0x21080000),
+ const_float32(0xA1600000),
+ const_float32(0xA0900000),
+ const_float32(0x20A00000),
+ const_float32(0x21680000),
+ const_float32(0xA1000000),
+ const_float32(0x1FC00000),
+ const_float32(0x21300000),
+ const_float32(0xA1380000),
+ const_float32(0xA0000000),
+ const_float32(0xA1C40000),
+ const_float32(0x21880000),
+ const_float32(0xA0B00000),
+ const_float32(0xA1E00000),
+ const_float32(0x21580000),
+ const_float32(0xA1100000),
+ const_float32(0xA1FC0000),
+ const_float32(0x21200000),
+ const_float32(0xA1480000),
+ const_float32(0x21E80000),
+ const_float32(0x20D00000),
+ const_float32(0xA1800000),
+};
#endif
diff --git a/target/m68k/translate.c b/target/m68k/translate.c
index 6d5bde0777..af8cdc2580 100644
--- a/target/m68k/translate.c
+++ b/target/m68k/translate.c
@@ -5057,6 +5057,9 @@ DISAS_INSN(fpu)
case 0x06: /* flognp1 */
gen_helper_flognp1(cpu_env, cpu_dest, cpu_src);
break;
+ case 0x0f: /* ftan */
+ gen_helper_ftan(cpu_env, cpu_dest, cpu_src);
+ break;
case 0x10: /* fetox */
gen_helper_fetox(cpu_env, cpu_dest, cpu_src);
break;
--
2.14.3
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [Qemu-devel] [PULL 02/11] target/m68k: implement fsin
2018-03-13 15:59 [Qemu-devel] [PULL 00/11] M68k for 2.12 patches Laurent Vivier
2018-03-13 15:59 ` [Qemu-devel] [PULL 01/11] target/m68k: implement ftan Laurent Vivier
@ 2018-03-13 15:59 ` Laurent Vivier
2018-04-27 13:47 ` Peter Maydell
2018-03-13 15:59 ` [Qemu-devel] [PULL 03/11] target/m68k: implement fcos Laurent Vivier
` (9 subsequent siblings)
11 siblings, 1 reply; 15+ messages in thread
From: Laurent Vivier @ 2018-03-13 15:59 UTC (permalink / raw)
To: qemu-devel; +Cc: Laurent Vivier
Using a local m68k floatx80_sin()
[copied from previous:
Written by Andreas Grabher for Previous, NeXT Computer Emulator.]
Signed-off-by: Laurent Vivier <laurent@vivier.eu>
Message-Id: <20180312202728.23790-3-laurent@vivier.eu>
---
target/m68k/fpu_helper.c | 5 +
target/m68k/helper.h | 1 +
target/m68k/softfloat.c | 247 +++++++++++++++++++++++++++++++++++++++++++++++
target/m68k/softfloat.h | 1 +
target/m68k/translate.c | 3 +
5 files changed, 257 insertions(+)
diff --git a/target/m68k/fpu_helper.c b/target/m68k/fpu_helper.c
index c41115ea05..a6cfb4db1a 100644
--- a/target/m68k/fpu_helper.c
+++ b/target/m68k/fpu_helper.c
@@ -597,3 +597,8 @@ void HELPER(ftan)(CPUM68KState *env, FPReg *res, FPReg *val)
{
res->d = floatx80_tan(val->d, &env->fp_status);
}
+
+void HELPER(fsin)(CPUM68KState *env, FPReg *res, FPReg *val)
+{
+ res->d = floatx80_sin(val->d, &env->fp_status);
+}
diff --git a/target/m68k/helper.h b/target/m68k/helper.h
index af9480fe49..6d8bfaab64 100644
--- a/target/m68k/helper.h
+++ b/target/m68k/helper.h
@@ -76,6 +76,7 @@ DEF_HELPER_3(fetox, void, env, fp, fp)
DEF_HELPER_3(ftwotox, void, env, fp, fp)
DEF_HELPER_3(ftentox, void, env, fp, fp)
DEF_HELPER_3(ftan, void, env, fp, fp)
+DEF_HELPER_3(fsin, void, env, fp, fp)
DEF_HELPER_3(mac_move, void, env, i32, i32)
DEF_HELPER_3(macmulf, i64, env, i32, i32)
diff --git a/target/m68k/softfloat.c b/target/m68k/softfloat.c
index 488dbc522b..6fb9665336 100644
--- a/target/m68k/softfloat.c
+++ b/target/m68k/softfloat.c
@@ -1476,3 +1476,250 @@ floatx80 floatx80_tan(floatx80 a, float_status *status)
}
}
}
+
+/*----------------------------------------------------------------------------
+ | Sine
+ *----------------------------------------------------------------------------*/
+
+floatx80 floatx80_sin(floatx80 a, float_status *status)
+{
+ flag aSign, xSign;
+ int32_t aExp, xExp;
+ uint64_t aSig, xSig;
+
+ int8_t user_rnd_mode, user_rnd_prec;
+
+ int32_t compact, l, n, j;
+ floatx80 fp0, fp1, fp2, fp3, fp4, fp5, x, invtwopi, twopi1, twopi2;
+ float32 posneg1, twoto63;
+ flag adjn, endflag;
+
+ aSig = extractFloatx80Frac(a);
+ aExp = extractFloatx80Exp(a);
+ aSign = extractFloatx80Sign(a);
+
+ if (aExp == 0x7FFF) {
+ if ((uint64_t) (aSig << 1)) {
+ return propagateFloatx80NaNOneArg(a, status);
+ }
+ float_raise(float_flag_invalid, status);
+ return floatx80_default_nan(status);
+ }
+
+ if (aExp == 0 && aSig == 0) {
+ return packFloatx80(aSign, 0, 0);
+ }
+
+ adjn = 0;
+
+ user_rnd_mode = status->float_rounding_mode;
+ user_rnd_prec = status->floatx80_rounding_precision;
+ status->float_rounding_mode = float_round_nearest_even;
+ status->floatx80_rounding_precision = 80;
+
+ compact = floatx80_make_compact(aExp, aSig);
+
+ fp0 = a;
+
+ if (compact < 0x3FD78000 || compact > 0x4004BC7E) {
+ /* 2^(-40) > |X| > 15 PI */
+ if (compact > 0x3FFF8000) { /* |X| >= 15 PI */
+ /* REDUCEX */
+ fp1 = packFloatx80(0, 0, 0);
+ if (compact == 0x7FFEFFFF) {
+ twopi1 = packFloatx80(aSign ^ 1, 0x7FFE,
+ LIT64(0xC90FDAA200000000));
+ twopi2 = packFloatx80(aSign ^ 1, 0x7FDC,
+ LIT64(0x85A308D300000000));
+ fp0 = floatx80_add(fp0, twopi1, status);
+ fp1 = fp0;
+ fp0 = floatx80_add(fp0, twopi2, status);
+ fp1 = floatx80_sub(fp1, fp0, status);
+ fp1 = floatx80_add(fp1, twopi2, status);
+ }
+ loop:
+ xSign = extractFloatx80Sign(fp0);
+ xExp = extractFloatx80Exp(fp0);
+ xExp -= 0x3FFF;
+ if (xExp <= 28) {
+ l = 0;
+ endflag = 1;
+ } else {
+ l = xExp - 27;
+ endflag = 0;
+ }
+ invtwopi = packFloatx80(0, 0x3FFE - l,
+ LIT64(0xA2F9836E4E44152A)); /* INVTWOPI */
+ twopi1 = packFloatx80(0, 0x3FFF + l, LIT64(0xC90FDAA200000000));
+ twopi2 = packFloatx80(0, 0x3FDD + l, LIT64(0x85A308D300000000));
+
+ /* SIGN(INARG)*2^63 IN SGL */
+ twoto63 = packFloat32(xSign, 0xBE, 0);
+
+ fp2 = floatx80_mul(fp0, invtwopi, status);
+ fp2 = floatx80_add(fp2, float32_to_floatx80(twoto63, status),
+ status); /* THE FRACT PART OF FP2 IS ROUNDED */
+ fp2 = floatx80_sub(fp2, float32_to_floatx80(twoto63, status),
+ status); /* FP2 is N */
+ fp4 = floatx80_mul(twopi1, fp2, status); /* W = N*P1 */
+ fp5 = floatx80_mul(twopi2, fp2, status); /* w = N*P2 */
+ fp3 = floatx80_add(fp4, fp5, status); /* FP3 is P */
+ fp4 = floatx80_sub(fp4, fp3, status); /* W-P */
+ fp0 = floatx80_sub(fp0, fp3, status); /* FP0 is A := R - P */
+ fp4 = floatx80_add(fp4, fp5, status); /* FP4 is p = (W-P)+w */
+ fp3 = fp0; /* FP3 is A */
+ fp1 = floatx80_sub(fp1, fp4, status); /* FP1 is a := r - p */
+ fp0 = floatx80_add(fp0, fp1, status); /* FP0 is R := A+a */
+
+ if (endflag > 0) {
+ n = floatx80_to_int32(fp2, status);
+ goto sincont;
+ }
+ fp3 = floatx80_sub(fp3, fp0, status); /* A-R */
+ fp1 = floatx80_add(fp1, fp3, status); /* FP1 is r := (A-R)+a */
+ goto loop;
+ } else {
+ /* SINSM */
+ fp0 = float32_to_floatx80(make_float32(0x3F800000),
+ status); /* 1 */
+
+ status->float_rounding_mode = user_rnd_mode;
+ status->floatx80_rounding_precision = user_rnd_prec;
+
+ if (adjn) {
+ /* COSTINY */
+ a = floatx80_sub(fp0, float32_to_floatx80(
+ make_float32(0x00800000), status), status);
+ } else {
+ /* SINTINY */
+ a = floatx80_move(a, status);
+ }
+ float_raise(float_flag_inexact, status);
+
+ return a;
+ }
+ } else {
+ fp1 = floatx80_mul(fp0, float64_to_floatx80(
+ make_float64(0x3FE45F306DC9C883), status),
+ status); /* X*2/PI */
+
+ n = floatx80_to_int32(fp1, status);
+ j = 32 + n;
+
+ fp0 = floatx80_sub(fp0, pi_tbl[j], status); /* X-Y1 */
+ fp0 = floatx80_sub(fp0, float32_to_floatx80(pi_tbl2[j], status),
+ status); /* FP0 IS R = (X-Y1)-Y2 */
+
+ sincont:
+ if ((n + adjn) & 1) {
+ /* COSPOLY */
+ fp0 = floatx80_mul(fp0, fp0, status); /* FP0 IS S */
+ fp1 = floatx80_mul(fp0, fp0, status); /* FP1 IS T */
+ fp2 = float64_to_floatx80(make_float64(0x3D2AC4D0D6011EE3),
+ status); /* B8 */
+ fp3 = float64_to_floatx80(make_float64(0xBDA9396F9F45AC19),
+ status); /* B7 */
+
+ xSign = extractFloatx80Sign(fp0); /* X IS S */
+ xExp = extractFloatx80Exp(fp0);
+ xSig = extractFloatx80Frac(fp0);
+
+ if (((n + adjn) >> 1) & 1) {
+ xSign ^= 1;
+ posneg1 = make_float32(0xBF800000); /* -1 */
+ } else {
+ xSign ^= 0;
+ posneg1 = make_float32(0x3F800000); /* 1 */
+ } /* X IS NOW R'= SGN*R */
+
+ fp2 = floatx80_mul(fp2, fp1, status); /* TB8 */
+ fp3 = floatx80_mul(fp3, fp1, status); /* TB7 */
+ fp2 = floatx80_add(fp2, float64_to_floatx80(
+ make_float64(0x3E21EED90612C972), status),
+ status); /* B6+TB8 */
+ fp3 = floatx80_add(fp3, float64_to_floatx80(
+ make_float64(0xBE927E4FB79D9FCF), status),
+ status); /* B5+TB7 */
+ fp2 = floatx80_mul(fp2, fp1, status); /* T(B6+TB8) */
+ fp3 = floatx80_mul(fp3, fp1, status); /* T(B5+TB7) */
+ fp2 = floatx80_add(fp2, float64_to_floatx80(
+ make_float64(0x3EFA01A01A01D423), status),
+ status); /* B4+T(B6+TB8) */
+ fp4 = packFloatx80(1, 0x3FF5, LIT64(0xB60B60B60B61D438));
+ fp3 = floatx80_add(fp3, fp4, status); /* B3+T(B5+TB7) */
+ fp2 = floatx80_mul(fp2, fp1, status); /* T(B4+T(B6+TB8)) */
+ fp1 = floatx80_mul(fp1, fp3, status); /* T(B3+T(B5+TB7)) */
+ fp4 = packFloatx80(0, 0x3FFA, LIT64(0xAAAAAAAAAAAAAB5E));
+ fp2 = floatx80_add(fp2, fp4, status); /* B2+T(B4+T(B6+TB8)) */
+ fp1 = floatx80_add(fp1, float32_to_floatx80(
+ make_float32(0xBF000000), status),
+ status); /* B1+T(B3+T(B5+TB7)) */
+ fp0 = floatx80_mul(fp0, fp2, status); /* S(B2+T(B4+T(B6+TB8))) */
+ fp0 = floatx80_add(fp0, fp1, status); /* [B1+T(B3+T(B5+TB7))]+
+ * [S(B2+T(B4+T(B6+TB8)))]
+ */
+
+ x = packFloatx80(xSign, xExp, xSig);
+ fp0 = floatx80_mul(fp0, x, status);
+
+ status->float_rounding_mode = user_rnd_mode;
+ status->floatx80_rounding_precision = user_rnd_prec;
+
+ a = floatx80_add(fp0, float32_to_floatx80(posneg1, status), status);
+
+ float_raise(float_flag_inexact, status);
+
+ return a;
+ } else {
+ /* SINPOLY */
+ xSign = extractFloatx80Sign(fp0); /* X IS R */
+ xExp = extractFloatx80Exp(fp0);
+ xSig = extractFloatx80Frac(fp0);
+
+ xSign ^= ((n + adjn) >> 1) & 1; /* X IS NOW R'= SGN*R */
+
+ fp0 = floatx80_mul(fp0, fp0, status); /* FP0 IS S */
+ fp1 = floatx80_mul(fp0, fp0, status); /* FP1 IS T */
+ fp3 = float64_to_floatx80(make_float64(0xBD6AAA77CCC994F5),
+ status); /* A7 */
+ fp2 = float64_to_floatx80(make_float64(0x3DE612097AAE8DA1),
+ status); /* A6 */
+ fp3 = floatx80_mul(fp3, fp1, status); /* T*A7 */
+ fp2 = floatx80_mul(fp2, fp1, status); /* T*A6 */
+ fp3 = floatx80_add(fp3, float64_to_floatx80(
+ make_float64(0xBE5AE6452A118AE4), status),
+ status); /* A5+T*A7 */
+ fp2 = floatx80_add(fp2, float64_to_floatx80(
+ make_float64(0x3EC71DE3A5341531), status),
+ status); /* A4+T*A6 */
+ fp3 = floatx80_mul(fp3, fp1, status); /* T(A5+TA7) */
+ fp2 = floatx80_mul(fp2, fp1, status); /* T(A4+TA6) */
+ fp3 = floatx80_add(fp3, float64_to_floatx80(
+ make_float64(0xBF2A01A01A018B59), status),
+ status); /* A3+T(A5+TA7) */
+ fp4 = packFloatx80(0, 0x3FF8, LIT64(0x88888888888859AF));
+ fp2 = floatx80_add(fp2, fp4, status); /* A2+T(A4+TA6) */
+ fp1 = floatx80_mul(fp1, fp3, status); /* T(A3+T(A5+TA7)) */
+ fp2 = floatx80_mul(fp2, fp0, status); /* S(A2+T(A4+TA6)) */
+ fp4 = packFloatx80(1, 0x3FFC, LIT64(0xAAAAAAAAAAAAAA99));
+ fp1 = floatx80_add(fp1, fp4, status); /* A1+T(A3+T(A5+TA7)) */
+ fp1 = floatx80_add(fp1, fp2,
+ status); /* [A1+T(A3+T(A5+TA7))]+
+ * [S(A2+T(A4+TA6))]
+ */
+
+ x = packFloatx80(xSign, xExp, xSig);
+ fp0 = floatx80_mul(fp0, x, status); /* R'*S */
+ fp0 = floatx80_mul(fp0, fp1, status); /* SIN(R')-R' */
+
+ status->float_rounding_mode = user_rnd_mode;
+ status->floatx80_rounding_precision = user_rnd_prec;
+
+ a = floatx80_add(fp0, x, status);
+
+ float_raise(float_flag_inexact, status);
+
+ return a;
+ }
+ }
+}
diff --git a/target/m68k/softfloat.h b/target/m68k/softfloat.h
index c5ac54d87b..e8ccf69ba8 100644
--- a/target/m68k/softfloat.h
+++ b/target/m68k/softfloat.h
@@ -35,4 +35,5 @@ floatx80 floatx80_etox(floatx80 a, float_status *status);
floatx80 floatx80_twotox(floatx80 a, float_status *status);
floatx80 floatx80_tentox(floatx80 a, float_status *status);
floatx80 floatx80_tan(floatx80 a, float_status *status);
+floatx80 floatx80_sin(floatx80 a, float_status *status);
#endif
diff --git a/target/m68k/translate.c b/target/m68k/translate.c
index af8cdc2580..05ab75e43f 100644
--- a/target/m68k/translate.c
+++ b/target/m68k/translate.c
@@ -5057,6 +5057,9 @@ DISAS_INSN(fpu)
case 0x06: /* flognp1 */
gen_helper_flognp1(cpu_env, cpu_dest, cpu_src);
break;
+ case 0x0e: /* fsin */
+ gen_helper_fsin(cpu_env, cpu_dest, cpu_src);
+ break;
case 0x0f: /* ftan */
gen_helper_ftan(cpu_env, cpu_dest, cpu_src);
break;
--
2.14.3
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [Qemu-devel] [PULL 03/11] target/m68k: implement fcos
2018-03-13 15:59 [Qemu-devel] [PULL 00/11] M68k for 2.12 patches Laurent Vivier
2018-03-13 15:59 ` [Qemu-devel] [PULL 01/11] target/m68k: implement ftan Laurent Vivier
2018-03-13 15:59 ` [Qemu-devel] [PULL 02/11] target/m68k: implement fsin Laurent Vivier
@ 2018-03-13 15:59 ` Laurent Vivier
2018-03-13 15:59 ` [Qemu-devel] [PULL 04/11] target/m68k: implement fsincos Laurent Vivier
` (8 subsequent siblings)
11 siblings, 0 replies; 15+ messages in thread
From: Laurent Vivier @ 2018-03-13 15:59 UTC (permalink / raw)
To: qemu-devel; +Cc: Laurent Vivier
Using a local m68k floatx80_cos()
[copied from previous:
Written by Andreas Grabher for Previous, NeXT Computer Emulator.]
Signed-off-by: Laurent Vivier <laurent@vivier.eu>
Message-Id: <20180312202728.23790-4-laurent@vivier.eu>
---
target/m68k/fpu_helper.c | 5 +
target/m68k/helper.h | 1 +
target/m68k/softfloat.c | 244 +++++++++++++++++++++++++++++++++++++++++++++++
target/m68k/softfloat.h | 1 +
target/m68k/translate.c | 3 +
5 files changed, 254 insertions(+)
diff --git a/target/m68k/fpu_helper.c b/target/m68k/fpu_helper.c
index a6cfb4db1a..71df19c685 100644
--- a/target/m68k/fpu_helper.c
+++ b/target/m68k/fpu_helper.c
@@ -602,3 +602,8 @@ void HELPER(fsin)(CPUM68KState *env, FPReg *res, FPReg *val)
{
res->d = floatx80_sin(val->d, &env->fp_status);
}
+
+void HELPER(fcos)(CPUM68KState *env, FPReg *res, FPReg *val)
+{
+ res->d = floatx80_cos(val->d, &env->fp_status);
+}
diff --git a/target/m68k/helper.h b/target/m68k/helper.h
index 6d8bfaab64..767baf75a3 100644
--- a/target/m68k/helper.h
+++ b/target/m68k/helper.h
@@ -77,6 +77,7 @@ DEF_HELPER_3(ftwotox, void, env, fp, fp)
DEF_HELPER_3(ftentox, void, env, fp, fp)
DEF_HELPER_3(ftan, void, env, fp, fp)
DEF_HELPER_3(fsin, void, env, fp, fp)
+DEF_HELPER_3(fcos, void, env, fp, fp)
DEF_HELPER_3(mac_move, void, env, i32, i32)
DEF_HELPER_3(macmulf, i64, env, i32, i32)
diff --git a/target/m68k/softfloat.c b/target/m68k/softfloat.c
index 6fb9665336..a3a12a0bcb 100644
--- a/target/m68k/softfloat.c
+++ b/target/m68k/softfloat.c
@@ -1723,3 +1723,247 @@ floatx80 floatx80_sin(floatx80 a, float_status *status)
}
}
}
+
+/*----------------------------------------------------------------------------
+ | Cosine
+ *----------------------------------------------------------------------------*/
+
+floatx80 floatx80_cos(floatx80 a, float_status *status)
+{
+ flag aSign, xSign;
+ int32_t aExp, xExp;
+ uint64_t aSig, xSig;
+
+ int8_t user_rnd_mode, user_rnd_prec;
+
+ int32_t compact, l, n, j;
+ floatx80 fp0, fp1, fp2, fp3, fp4, fp5, x, invtwopi, twopi1, twopi2;
+ float32 posneg1, twoto63;
+ flag adjn, endflag;
+
+ aSig = extractFloatx80Frac(a);
+ aExp = extractFloatx80Exp(a);
+ aSign = extractFloatx80Sign(a);
+
+ if (aExp == 0x7FFF) {
+ if ((uint64_t) (aSig << 1)) {
+ return propagateFloatx80NaNOneArg(a, status);
+ }
+ float_raise(float_flag_invalid, status);
+ return floatx80_default_nan(status);
+ }
+
+ if (aExp == 0 && aSig == 0) {
+ return packFloatx80(0, one_exp, one_sig);
+ }
+
+ adjn = 1;
+
+ user_rnd_mode = status->float_rounding_mode;
+ user_rnd_prec = status->floatx80_rounding_precision;
+ status->float_rounding_mode = float_round_nearest_even;
+ status->floatx80_rounding_precision = 80;
+
+ compact = floatx80_make_compact(aExp, aSig);
+
+ fp0 = a;
+
+ if (compact < 0x3FD78000 || compact > 0x4004BC7E) {
+ /* 2^(-40) > |X| > 15 PI */
+ if (compact > 0x3FFF8000) { /* |X| >= 15 PI */
+ /* REDUCEX */
+ fp1 = packFloatx80(0, 0, 0);
+ if (compact == 0x7FFEFFFF) {
+ twopi1 = packFloatx80(aSign ^ 1, 0x7FFE,
+ LIT64(0xC90FDAA200000000));
+ twopi2 = packFloatx80(aSign ^ 1, 0x7FDC,
+ LIT64(0x85A308D300000000));
+ fp0 = floatx80_add(fp0, twopi1, status);
+ fp1 = fp0;
+ fp0 = floatx80_add(fp0, twopi2, status);
+ fp1 = floatx80_sub(fp1, fp0, status);
+ fp1 = floatx80_add(fp1, twopi2, status);
+ }
+ loop:
+ xSign = extractFloatx80Sign(fp0);
+ xExp = extractFloatx80Exp(fp0);
+ xExp -= 0x3FFF;
+ if (xExp <= 28) {
+ l = 0;
+ endflag = 1;
+ } else {
+ l = xExp - 27;
+ endflag = 0;
+ }
+ invtwopi = packFloatx80(0, 0x3FFE - l,
+ LIT64(0xA2F9836E4E44152A)); /* INVTWOPI */
+ twopi1 = packFloatx80(0, 0x3FFF + l, LIT64(0xC90FDAA200000000));
+ twopi2 = packFloatx80(0, 0x3FDD + l, LIT64(0x85A308D300000000));
+
+ /* SIGN(INARG)*2^63 IN SGL */
+ twoto63 = packFloat32(xSign, 0xBE, 0);
+
+ fp2 = floatx80_mul(fp0, invtwopi, status);
+ fp2 = floatx80_add(fp2, float32_to_floatx80(twoto63, status),
+ status); /* THE FRACT PART OF FP2 IS ROUNDED */
+ fp2 = floatx80_sub(fp2, float32_to_floatx80(twoto63, status),
+ status); /* FP2 is N */
+ fp4 = floatx80_mul(twopi1, fp2, status); /* W = N*P1 */
+ fp5 = floatx80_mul(twopi2, fp2, status); /* w = N*P2 */
+ fp3 = floatx80_add(fp4, fp5, status); /* FP3 is P */
+ fp4 = floatx80_sub(fp4, fp3, status); /* W-P */
+ fp0 = floatx80_sub(fp0, fp3, status); /* FP0 is A := R - P */
+ fp4 = floatx80_add(fp4, fp5, status); /* FP4 is p = (W-P)+w */
+ fp3 = fp0; /* FP3 is A */
+ fp1 = floatx80_sub(fp1, fp4, status); /* FP1 is a := r - p */
+ fp0 = floatx80_add(fp0, fp1, status); /* FP0 is R := A+a */
+
+ if (endflag > 0) {
+ n = floatx80_to_int32(fp2, status);
+ goto sincont;
+ }
+ fp3 = floatx80_sub(fp3, fp0, status); /* A-R */
+ fp1 = floatx80_add(fp1, fp3, status); /* FP1 is r := (A-R)+a */
+ goto loop;
+ } else {
+ /* SINSM */
+ fp0 = float32_to_floatx80(make_float32(0x3F800000), status); /* 1 */
+
+ status->float_rounding_mode = user_rnd_mode;
+ status->floatx80_rounding_precision = user_rnd_prec;
+
+ if (adjn) {
+ /* COSTINY */
+ a = floatx80_sub(fp0, float32_to_floatx80(
+ make_float32(0x00800000), status),
+ status);
+ } else {
+ /* SINTINY */
+ a = floatx80_move(a, status);
+ }
+ float_raise(float_flag_inexact, status);
+
+ return a;
+ }
+ } else {
+ fp1 = floatx80_mul(fp0, float64_to_floatx80(
+ make_float64(0x3FE45F306DC9C883), status),
+ status); /* X*2/PI */
+
+ n = floatx80_to_int32(fp1, status);
+ j = 32 + n;
+
+ fp0 = floatx80_sub(fp0, pi_tbl[j], status); /* X-Y1 */
+ fp0 = floatx80_sub(fp0, float32_to_floatx80(pi_tbl2[j], status),
+ status); /* FP0 IS R = (X-Y1)-Y2 */
+
+ sincont:
+ if ((n + adjn) & 1) {
+ /* COSPOLY */
+ fp0 = floatx80_mul(fp0, fp0, status); /* FP0 IS S */
+ fp1 = floatx80_mul(fp0, fp0, status); /* FP1 IS T */
+ fp2 = float64_to_floatx80(make_float64(0x3D2AC4D0D6011EE3),
+ status); /* B8 */
+ fp3 = float64_to_floatx80(make_float64(0xBDA9396F9F45AC19),
+ status); /* B7 */
+
+ xSign = extractFloatx80Sign(fp0); /* X IS S */
+ xExp = extractFloatx80Exp(fp0);
+ xSig = extractFloatx80Frac(fp0);
+
+ if (((n + adjn) >> 1) & 1) {
+ xSign ^= 1;
+ posneg1 = make_float32(0xBF800000); /* -1 */
+ } else {
+ xSign ^= 0;
+ posneg1 = make_float32(0x3F800000); /* 1 */
+ } /* X IS NOW R'= SGN*R */
+
+ fp2 = floatx80_mul(fp2, fp1, status); /* TB8 */
+ fp3 = floatx80_mul(fp3, fp1, status); /* TB7 */
+ fp2 = floatx80_add(fp2, float64_to_floatx80(
+ make_float64(0x3E21EED90612C972), status),
+ status); /* B6+TB8 */
+ fp3 = floatx80_add(fp3, float64_to_floatx80(
+ make_float64(0xBE927E4FB79D9FCF), status),
+ status); /* B5+TB7 */
+ fp2 = floatx80_mul(fp2, fp1, status); /* T(B6+TB8) */
+ fp3 = floatx80_mul(fp3, fp1, status); /* T(B5+TB7) */
+ fp2 = floatx80_add(fp2, float64_to_floatx80(
+ make_float64(0x3EFA01A01A01D423), status),
+ status); /* B4+T(B6+TB8) */
+ fp4 = packFloatx80(1, 0x3FF5, LIT64(0xB60B60B60B61D438));
+ fp3 = floatx80_add(fp3, fp4, status); /* B3+T(B5+TB7) */
+ fp2 = floatx80_mul(fp2, fp1, status); /* T(B4+T(B6+TB8)) */
+ fp1 = floatx80_mul(fp1, fp3, status); /* T(B3+T(B5+TB7)) */
+ fp4 = packFloatx80(0, 0x3FFA, LIT64(0xAAAAAAAAAAAAAB5E));
+ fp2 = floatx80_add(fp2, fp4, status); /* B2+T(B4+T(B6+TB8)) */
+ fp1 = floatx80_add(fp1, float32_to_floatx80(
+ make_float32(0xBF000000), status),
+ status); /* B1+T(B3+T(B5+TB7)) */
+ fp0 = floatx80_mul(fp0, fp2, status); /* S(B2+T(B4+T(B6+TB8))) */
+ fp0 = floatx80_add(fp0, fp1, status);
+ /* [B1+T(B3+T(B5+TB7))]+[S(B2+T(B4+T(B6+TB8)))] */
+
+ x = packFloatx80(xSign, xExp, xSig);
+ fp0 = floatx80_mul(fp0, x, status);
+
+ status->float_rounding_mode = user_rnd_mode;
+ status->floatx80_rounding_precision = user_rnd_prec;
+
+ a = floatx80_add(fp0, float32_to_floatx80(posneg1, status), status);
+
+ float_raise(float_flag_inexact, status);
+
+ return a;
+ } else {
+ /* SINPOLY */
+ xSign = extractFloatx80Sign(fp0); /* X IS R */
+ xExp = extractFloatx80Exp(fp0);
+ xSig = extractFloatx80Frac(fp0);
+
+ xSign ^= ((n + adjn) >> 1) & 1; /* X IS NOW R'= SGN*R */
+
+ fp0 = floatx80_mul(fp0, fp0, status); /* FP0 IS S */
+ fp1 = floatx80_mul(fp0, fp0, status); /* FP1 IS T */
+ fp3 = float64_to_floatx80(make_float64(0xBD6AAA77CCC994F5),
+ status); /* A7 */
+ fp2 = float64_to_floatx80(make_float64(0x3DE612097AAE8DA1),
+ status); /* A6 */
+ fp3 = floatx80_mul(fp3, fp1, status); /* T*A7 */
+ fp2 = floatx80_mul(fp2, fp1, status); /* T*A6 */
+ fp3 = floatx80_add(fp3, float64_to_floatx80(
+ make_float64(0xBE5AE6452A118AE4), status),
+ status); /* A5+T*A7 */
+ fp2 = floatx80_add(fp2, float64_to_floatx80(
+ make_float64(0x3EC71DE3A5341531), status),
+ status); /* A4+T*A6 */
+ fp3 = floatx80_mul(fp3, fp1, status); /* T(A5+TA7) */
+ fp2 = floatx80_mul(fp2, fp1, status); /* T(A4+TA6) */
+ fp3 = floatx80_add(fp3, float64_to_floatx80(
+ make_float64(0xBF2A01A01A018B59), status),
+ status); /* A3+T(A5+TA7) */
+ fp4 = packFloatx80(0, 0x3FF8, LIT64(0x88888888888859AF));
+ fp2 = floatx80_add(fp2, fp4, status); /* A2+T(A4+TA6) */
+ fp1 = floatx80_mul(fp1, fp3, status); /* T(A3+T(A5+TA7)) */
+ fp2 = floatx80_mul(fp2, fp0, status); /* S(A2+T(A4+TA6)) */
+ fp4 = packFloatx80(1, 0x3FFC, LIT64(0xAAAAAAAAAAAAAA99));
+ fp1 = floatx80_add(fp1, fp4, status); /* A1+T(A3+T(A5+TA7)) */
+ fp1 = floatx80_add(fp1, fp2, status);
+ /* [A1+T(A3+T(A5+TA7))]+[S(A2+T(A4+TA6))] */
+
+ x = packFloatx80(xSign, xExp, xSig);
+ fp0 = floatx80_mul(fp0, x, status); /* R'*S */
+ fp0 = floatx80_mul(fp0, fp1, status); /* SIN(R')-R' */
+
+ status->float_rounding_mode = user_rnd_mode;
+ status->floatx80_rounding_precision = user_rnd_prec;
+
+ a = floatx80_add(fp0, x, status);
+
+ float_raise(float_flag_inexact, status);
+
+ return a;
+ }
+ }
+}
diff --git a/target/m68k/softfloat.h b/target/m68k/softfloat.h
index e8ccf69ba8..4fd5b2c609 100644
--- a/target/m68k/softfloat.h
+++ b/target/m68k/softfloat.h
@@ -36,4 +36,5 @@ floatx80 floatx80_twotox(floatx80 a, float_status *status);
floatx80 floatx80_tentox(floatx80 a, float_status *status);
floatx80 floatx80_tan(floatx80 a, float_status *status);
floatx80 floatx80_sin(floatx80 a, float_status *status);
+floatx80 floatx80_cos(floatx80 a, float_status *status);
#endif
diff --git a/target/m68k/translate.c b/target/m68k/translate.c
index 05ab75e43f..f47388da4b 100644
--- a/target/m68k/translate.c
+++ b/target/m68k/translate.c
@@ -5099,6 +5099,9 @@ DISAS_INSN(fpu)
case 0x5e: /* fdneg */
gen_helper_fdneg(cpu_env, cpu_dest, cpu_src);
break;
+ case 0x1d: /* fcos */
+ gen_helper_fcos(cpu_env, cpu_dest, cpu_src);
+ break;
case 0x1e: /* fgetexp */
gen_helper_fgetexp(cpu_env, cpu_dest, cpu_src);
break;
--
2.14.3
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [Qemu-devel] [PULL 04/11] target/m68k: implement fsincos
2018-03-13 15:59 [Qemu-devel] [PULL 00/11] M68k for 2.12 patches Laurent Vivier
` (2 preceding siblings ...)
2018-03-13 15:59 ` [Qemu-devel] [PULL 03/11] target/m68k: implement fcos Laurent Vivier
@ 2018-03-13 15:59 ` Laurent Vivier
2018-03-13 15:59 ` [Qemu-devel] [PULL 05/11] target/m68k: implement fatan Laurent Vivier
` (7 subsequent siblings)
11 siblings, 0 replies; 15+ messages in thread
From: Laurent Vivier @ 2018-03-13 15:59 UTC (permalink / raw)
To: qemu-devel; +Cc: Laurent Vivier
using floatx80_sin() and floatx80_cos()
Signed-off-by: Laurent Vivier <laurent@vivier.eu>
Message-Id: <20180312202728.23790-5-laurent@vivier.eu>
---
target/m68k/fpu_helper.c | 11 +++++++++++
target/m68k/helper.h | 1 +
target/m68k/translate.c | 8 ++++++++
3 files changed, 20 insertions(+)
diff --git a/target/m68k/fpu_helper.c b/target/m68k/fpu_helper.c
index 71df19c685..36e34d42a8 100644
--- a/target/m68k/fpu_helper.c
+++ b/target/m68k/fpu_helper.c
@@ -607,3 +607,14 @@ void HELPER(fcos)(CPUM68KState *env, FPReg *res, FPReg *val)
{
res->d = floatx80_cos(val->d, &env->fp_status);
}
+
+void HELPER(fsincos)(CPUM68KState *env, FPReg *res0, FPReg *res1, FPReg *val)
+{
+ floatx80 a = val->d;
+ /* If res0 and res1 specify the same floating-point data register,
+ * the sine result is stored in the register, and the cosine
+ * result is discarded.
+ */
+ res1->d = floatx80_cos(a, &env->fp_status);
+ res0->d = floatx80_sin(a, &env->fp_status);
+}
diff --git a/target/m68k/helper.h b/target/m68k/helper.h
index 767baf75a3..a168ffbaea 100644
--- a/target/m68k/helper.h
+++ b/target/m68k/helper.h
@@ -78,6 +78,7 @@ DEF_HELPER_3(ftentox, void, env, fp, fp)
DEF_HELPER_3(ftan, void, env, fp, fp)
DEF_HELPER_3(fsin, void, env, fp, fp)
DEF_HELPER_3(fcos, void, env, fp, fp)
+DEF_HELPER_4(fsincos, void, env, fp, fp, fp)
DEF_HELPER_3(mac_move, void, env, i32, i32)
DEF_HELPER_3(macmulf, i64, env, i32, i32)
diff --git a/target/m68k/translate.c b/target/m68k/translate.c
index f47388da4b..a78edd8825 100644
--- a/target/m68k/translate.c
+++ b/target/m68k/translate.c
@@ -5159,6 +5159,14 @@ DISAS_INSN(fpu)
case 0x6c: /* fdsub */
gen_helper_fdsub(cpu_env, cpu_dest, cpu_src, cpu_dest);
break;
+ case 0x30: case 0x31: case 0x32:
+ case 0x33: case 0x34: case 0x35:
+ case 0x36: case 0x37: {
+ TCGv_ptr cpu_dest2 = gen_fp_ptr(REG(ext, 0));
+ gen_helper_fsincos(cpu_env, cpu_dest, cpu_dest2, cpu_src);
+ tcg_temp_free_ptr(cpu_dest2);
+ }
+ break;
case 0x38: /* fcmp */
gen_helper_fcmp(cpu_env, cpu_src, cpu_dest);
return;
--
2.14.3
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [Qemu-devel] [PULL 05/11] target/m68k: implement fatan
2018-03-13 15:59 [Qemu-devel] [PULL 00/11] M68k for 2.12 patches Laurent Vivier
` (3 preceding siblings ...)
2018-03-13 15:59 ` [Qemu-devel] [PULL 04/11] target/m68k: implement fsincos Laurent Vivier
@ 2018-03-13 15:59 ` Laurent Vivier
2018-03-13 15:59 ` [Qemu-devel] [PULL 06/11] target/m68k: implement fasin Laurent Vivier
` (6 subsequent siblings)
11 siblings, 0 replies; 15+ messages in thread
From: Laurent Vivier @ 2018-03-13 15:59 UTC (permalink / raw)
To: qemu-devel; +Cc: Laurent Vivier
Using a local m68k floatx80_atan()
[copied from previous:
Written by Andreas Grabher for Previous, NeXT Computer Emulator.]
Signed-off-by: Laurent Vivier <laurent@vivier.eu>
Message-Id: <20180312202728.23790-6-laurent@vivier.eu>
---
target/m68k/fpu_helper.c | 5 +
target/m68k/helper.h | 1 +
target/m68k/softfloat.c | 200 ++++++++++++++++++++++++++++++++++++
target/m68k/softfloat.h | 1 +
target/m68k/softfloat_fpsp_tables.h | 131 +++++++++++++++++++++++
target/m68k/translate.c | 3 +
6 files changed, 341 insertions(+)
diff --git a/target/m68k/fpu_helper.c b/target/m68k/fpu_helper.c
index 36e34d42a8..47328490ee 100644
--- a/target/m68k/fpu_helper.c
+++ b/target/m68k/fpu_helper.c
@@ -618,3 +618,8 @@ void HELPER(fsincos)(CPUM68KState *env, FPReg *res0, FPReg *res1, FPReg *val)
res1->d = floatx80_cos(a, &env->fp_status);
res0->d = floatx80_sin(a, &env->fp_status);
}
+
+void HELPER(fatan)(CPUM68KState *env, FPReg *res, FPReg *val)
+{
+ res->d = floatx80_atan(val->d, &env->fp_status);
+}
diff --git a/target/m68k/helper.h b/target/m68k/helper.h
index a168ffbaea..304569e997 100644
--- a/target/m68k/helper.h
+++ b/target/m68k/helper.h
@@ -79,6 +79,7 @@ DEF_HELPER_3(ftan, void, env, fp, fp)
DEF_HELPER_3(fsin, void, env, fp, fp)
DEF_HELPER_3(fcos, void, env, fp, fp)
DEF_HELPER_4(fsincos, void, env, fp, fp, fp)
+DEF_HELPER_3(fatan, void, env, fp, fp)
DEF_HELPER_3(mac_move, void, env, i32, i32)
DEF_HELPER_3(macmulf, i64, env, i32, i32)
diff --git a/target/m68k/softfloat.c b/target/m68k/softfloat.c
index a3a12a0bcb..00ac9a1e0a 100644
--- a/target/m68k/softfloat.c
+++ b/target/m68k/softfloat.c
@@ -23,6 +23,9 @@
#include "fpu/softfloat-macros.h"
#include "softfloat_fpsp_tables.h"
+#define piby2_exp 0x3FFF
+#define pi_sig LIT64(0xc90fdaa22168c235)
+
static floatx80 propagateFloatx80NaNOneArg(floatx80 a, float_status *status)
{
if (floatx80_is_signaling_nan(a, status)) {
@@ -1967,3 +1970,200 @@ floatx80 floatx80_cos(floatx80 a, float_status *status)
}
}
}
+
+/*----------------------------------------------------------------------------
+ | Arc tangent
+ *----------------------------------------------------------------------------*/
+
+floatx80 floatx80_atan(floatx80 a, float_status *status)
+{
+ flag aSign;
+ int32_t aExp;
+ uint64_t aSig;
+
+ int8_t user_rnd_mode, user_rnd_prec;
+
+ int32_t compact, tbl_index;
+ floatx80 fp0, fp1, fp2, fp3, xsave;
+
+ aSig = extractFloatx80Frac(a);
+ aExp = extractFloatx80Exp(a);
+ aSign = extractFloatx80Sign(a);
+
+ if (aExp == 0x7FFF) {
+ if ((uint64_t) (aSig << 1)) {
+ return propagateFloatx80NaNOneArg(a, status);
+ }
+ a = packFloatx80(aSign, piby2_exp, pi_sig);
+ float_raise(float_flag_inexact, status);
+ return floatx80_move(a, status);
+ }
+
+ if (aExp == 0 && aSig == 0) {
+ return packFloatx80(aSign, 0, 0);
+ }
+
+ compact = floatx80_make_compact(aExp, aSig);
+
+ user_rnd_mode = status->float_rounding_mode;
+ user_rnd_prec = status->floatx80_rounding_precision;
+ status->float_rounding_mode = float_round_nearest_even;
+ status->floatx80_rounding_precision = 80;
+
+ if (compact < 0x3FFB8000 || compact > 0x4002FFFF) {
+ /* |X| >= 16 or |X| < 1/16 */
+ if (compact > 0x3FFF8000) { /* |X| >= 16 */
+ if (compact > 0x40638000) { /* |X| > 2^(100) */
+ fp0 = packFloatx80(aSign, piby2_exp, pi_sig);
+ fp1 = packFloatx80(aSign, 0x0001, one_sig);
+
+ status->float_rounding_mode = user_rnd_mode;
+ status->floatx80_rounding_precision = user_rnd_prec;
+
+ a = floatx80_sub(fp0, fp1, status);
+
+ float_raise(float_flag_inexact, status);
+
+ return a;
+ } else {
+ fp0 = a;
+ fp1 = packFloatx80(1, one_exp, one_sig); /* -1 */
+ fp1 = floatx80_div(fp1, fp0, status); /* X' = -1/X */
+ xsave = fp1;
+ fp0 = floatx80_mul(fp1, fp1, status); /* Y = X'*X' */
+ fp1 = floatx80_mul(fp0, fp0, status); /* Z = Y*Y */
+ fp3 = float64_to_floatx80(make_float64(0xBFB70BF398539E6A),
+ status); /* C5 */
+ fp2 = float64_to_floatx80(make_float64(0x3FBC7187962D1D7D),
+ status); /* C4 */
+ fp3 = floatx80_mul(fp3, fp1, status); /* Z*C5 */
+ fp2 = floatx80_mul(fp2, fp1, status); /* Z*C4 */
+ fp3 = floatx80_add(fp3, float64_to_floatx80(
+ make_float64(0xBFC24924827107B8), status),
+ status); /* C3+Z*C5 */
+ fp2 = floatx80_add(fp2, float64_to_floatx80(
+ make_float64(0x3FC999999996263E), status),
+ status); /* C2+Z*C4 */
+ fp1 = floatx80_mul(fp1, fp3, status); /* Z*(C3+Z*C5) */
+ fp2 = floatx80_mul(fp2, fp0, status); /* Y*(C2+Z*C4) */
+ fp1 = floatx80_add(fp1, float64_to_floatx80(
+ make_float64(0xBFD5555555555536), status),
+ status); /* C1+Z*(C3+Z*C5) */
+ fp0 = floatx80_mul(fp0, xsave, status); /* X'*Y */
+ /* [Y*(C2+Z*C4)]+[C1+Z*(C3+Z*C5)] */
+ fp1 = floatx80_add(fp1, fp2, status);
+ /* X'*Y*([B1+Z*(B3+Z*B5)]+[Y*(B2+Z*(B4+Z*B6))]) ?? */
+ fp0 = floatx80_mul(fp0, fp1, status);
+ fp0 = floatx80_add(fp0, xsave, status);
+ fp1 = packFloatx80(aSign, piby2_exp, pi_sig);
+
+ status->float_rounding_mode = user_rnd_mode;
+ status->floatx80_rounding_precision = user_rnd_prec;
+
+ a = floatx80_add(fp0, fp1, status);
+
+ float_raise(float_flag_inexact, status);
+
+ return a;
+ }
+ } else { /* |X| < 1/16 */
+ if (compact < 0x3FD78000) { /* |X| < 2^(-40) */
+ status->float_rounding_mode = user_rnd_mode;
+ status->floatx80_rounding_precision = user_rnd_prec;
+
+ a = floatx80_move(a, status);
+
+ float_raise(float_flag_inexact, status);
+
+ return a;
+ } else {
+ fp0 = a;
+ xsave = a;
+ fp0 = floatx80_mul(fp0, fp0, status); /* Y = X*X */
+ fp1 = floatx80_mul(fp0, fp0, status); /* Z = Y*Y */
+ fp2 = float64_to_floatx80(make_float64(0x3FB344447F876989),
+ status); /* B6 */
+ fp3 = float64_to_floatx80(make_float64(0xBFB744EE7FAF45DB),
+ status); /* B5 */
+ fp2 = floatx80_mul(fp2, fp1, status); /* Z*B6 */
+ fp3 = floatx80_mul(fp3, fp1, status); /* Z*B5 */
+ fp2 = floatx80_add(fp2, float64_to_floatx80(
+ make_float64(0x3FBC71C646940220), status),
+ status); /* B4+Z*B6 */
+ fp3 = floatx80_add(fp3, float64_to_floatx80(
+ make_float64(0xBFC24924921872F9),
+ status), status); /* B3+Z*B5 */
+ fp2 = floatx80_mul(fp2, fp1, status); /* Z*(B4+Z*B6) */
+ fp1 = floatx80_mul(fp1, fp3, status); /* Z*(B3+Z*B5) */
+ fp2 = floatx80_add(fp2, float64_to_floatx80(
+ make_float64(0x3FC9999999998FA9), status),
+ status); /* B2+Z*(B4+Z*B6) */
+ fp1 = floatx80_add(fp1, float64_to_floatx80(
+ make_float64(0xBFD5555555555555), status),
+ status); /* B1+Z*(B3+Z*B5) */
+ fp2 = floatx80_mul(fp2, fp0, status); /* Y*(B2+Z*(B4+Z*B6)) */
+ fp0 = floatx80_mul(fp0, xsave, status); /* X*Y */
+ /* [B1+Z*(B3+Z*B5)]+[Y*(B2+Z*(B4+Z*B6))] */
+ fp1 = floatx80_add(fp1, fp2, status);
+ /* X*Y*([B1+Z*(B3+Z*B5)]+[Y*(B2+Z*(B4+Z*B6))]) */
+ fp0 = floatx80_mul(fp0, fp1, status);
+
+ status->float_rounding_mode = user_rnd_mode;
+ status->floatx80_rounding_precision = user_rnd_prec;
+
+ a = floatx80_add(fp0, xsave, status);
+
+ float_raise(float_flag_inexact, status);
+
+ return a;
+ }
+ }
+ } else {
+ aSig &= LIT64(0xF800000000000000);
+ aSig |= LIT64(0x0400000000000000);
+ xsave = packFloatx80(aSign, aExp, aSig); /* F */
+ fp0 = a;
+ fp1 = a; /* X */
+ fp2 = packFloatx80(0, one_exp, one_sig); /* 1 */
+ fp1 = floatx80_mul(fp1, xsave, status); /* X*F */
+ fp0 = floatx80_sub(fp0, xsave, status); /* X-F */
+ fp1 = floatx80_add(fp1, fp2, status); /* 1 + X*F */
+ fp0 = floatx80_div(fp0, fp1, status); /* U = (X-F)/(1+X*F) */
+
+ tbl_index = compact;
+
+ tbl_index &= 0x7FFF0000;
+ tbl_index -= 0x3FFB0000;
+ tbl_index >>= 1;
+ tbl_index += compact & 0x00007800;
+ tbl_index >>= 11;
+
+ fp3 = atan_tbl[tbl_index];
+
+ fp3.high |= aSign ? 0x8000 : 0; /* ATAN(F) */
+
+ fp1 = floatx80_mul(fp0, fp0, status); /* V = U*U */
+ fp2 = float64_to_floatx80(make_float64(0xBFF6687E314987D8),
+ status); /* A3 */
+ fp2 = floatx80_add(fp2, fp1, status); /* A3+V */
+ fp2 = floatx80_mul(fp2, fp1, status); /* V*(A3+V) */
+ fp1 = floatx80_mul(fp1, fp0, status); /* U*V */
+ fp2 = floatx80_add(fp2, float64_to_floatx80(
+ make_float64(0x4002AC6934A26DB3), status),
+ status); /* A2+V*(A3+V) */
+ fp1 = floatx80_mul(fp1, float64_to_floatx80(
+ make_float64(0xBFC2476F4E1DA28E), status),
+ status); /* A1+U*V */
+ fp1 = floatx80_mul(fp1, fp2, status); /* A1*U*V*(A2+V*(A3+V)) */
+ fp0 = floatx80_add(fp0, fp1, status); /* ATAN(U) */
+
+ status->float_rounding_mode = user_rnd_mode;
+ status->floatx80_rounding_precision = user_rnd_prec;
+
+ a = floatx80_add(fp0, fp3, status); /* ATAN(X) */
+
+ float_raise(float_flag_inexact, status);
+
+ return a;
+ }
+}
diff --git a/target/m68k/softfloat.h b/target/m68k/softfloat.h
index 4fd5b2c609..eec45f3ffe 100644
--- a/target/m68k/softfloat.h
+++ b/target/m68k/softfloat.h
@@ -37,4 +37,5 @@ floatx80 floatx80_tentox(floatx80 a, float_status *status);
floatx80 floatx80_tan(floatx80 a, float_status *status);
floatx80 floatx80_sin(floatx80 a, float_status *status);
floatx80 floatx80_cos(floatx80 a, float_status *status);
+floatx80 floatx80_atan(floatx80 a, float_status *status);
#endif
diff --git a/target/m68k/softfloat_fpsp_tables.h b/target/m68k/softfloat_fpsp_tables.h
index a9c86a5af2..3f1419ee6e 100644
--- a/target/m68k/softfloat_fpsp_tables.h
+++ b/target/m68k/softfloat_fpsp_tables.h
@@ -507,4 +507,135 @@ static const float32 pi_tbl2[65] = {
const_float32(0x20D00000),
const_float32(0xA1800000),
};
+
+static const floatx80 atan_tbl[128] = {
+ make_floatx80_init(0x3FFB, 0x83D152C5060B7A51),
+ make_floatx80_init(0x3FFB, 0x8BC8544565498B8B),
+ make_floatx80_init(0x3FFB, 0x93BE406017626B0D),
+ make_floatx80_init(0x3FFB, 0x9BB3078D35AEC202),
+ make_floatx80_init(0x3FFB, 0xA3A69A525DDCE7DE),
+ make_floatx80_init(0x3FFB, 0xAB98E94362765619),
+ make_floatx80_init(0x3FFB, 0xB389E502F9C59862),
+ make_floatx80_init(0x3FFB, 0xBB797E436B09E6FB),
+ make_floatx80_init(0x3FFB, 0xC367A5C739E5F446),
+ make_floatx80_init(0x3FFB, 0xCB544C61CFF7D5C6),
+ make_floatx80_init(0x3FFB, 0xD33F62F82488533E),
+ make_floatx80_init(0x3FFB, 0xDB28DA8162404C77),
+ make_floatx80_init(0x3FFB, 0xE310A4078AD34F18),
+ make_floatx80_init(0x3FFB, 0xEAF6B0A8188EE1EB),
+ make_floatx80_init(0x3FFB, 0xF2DAF1949DBE79D5),
+ make_floatx80_init(0x3FFB, 0xFABD581361D47E3E),
+ make_floatx80_init(0x3FFC, 0x8346AC210959ECC4),
+ make_floatx80_init(0x3FFC, 0x8B232A08304282D8),
+ make_floatx80_init(0x3FFC, 0x92FB70B8D29AE2F9),
+ make_floatx80_init(0x3FFC, 0x9ACF476F5CCD1CB4),
+ make_floatx80_init(0x3FFC, 0xA29E76304954F23F),
+ make_floatx80_init(0x3FFC, 0xAA68C5D08AB85230),
+ make_floatx80_init(0x3FFC, 0xB22DFFFD9D539F83),
+ make_floatx80_init(0x3FFC, 0xB9EDEF453E900EA5),
+ make_floatx80_init(0x3FFC, 0xC1A85F1CC75E3EA5),
+ make_floatx80_init(0x3FFC, 0xC95D1BE828138DE6),
+ make_floatx80_init(0x3FFC, 0xD10BF300840D2DE4),
+ make_floatx80_init(0x3FFC, 0xD8B4B2BA6BC05E7A),
+ make_floatx80_init(0x3FFC, 0xE0572A6BB42335F6),
+ make_floatx80_init(0x3FFC, 0xE7F32A70EA9CAA8F),
+ make_floatx80_init(0x3FFC, 0xEF88843264ECEFAA),
+ make_floatx80_init(0x3FFC, 0xF7170A28ECC06666),
+ make_floatx80_init(0x3FFD, 0x812FD288332DAD32),
+ make_floatx80_init(0x3FFD, 0x88A8D1B1218E4D64),
+ make_floatx80_init(0x3FFD, 0x9012AB3F23E4AEE8),
+ make_floatx80_init(0x3FFD, 0x976CC3D411E7F1B9),
+ make_floatx80_init(0x3FFD, 0x9EB689493889A227),
+ make_floatx80_init(0x3FFD, 0xA5EF72C34487361B),
+ make_floatx80_init(0x3FFD, 0xAD1700BAF07A7227),
+ make_floatx80_init(0x3FFD, 0xB42CBCFAFD37EFB7),
+ make_floatx80_init(0x3FFD, 0xBB303A940BA80F89),
+ make_floatx80_init(0x3FFD, 0xC22115C6FCAEBBAF),
+ make_floatx80_init(0x3FFD, 0xC8FEF3E686331221),
+ make_floatx80_init(0x3FFD, 0xCFC98330B4000C70),
+ make_floatx80_init(0x3FFD, 0xD6807AA1102C5BF9),
+ make_floatx80_init(0x3FFD, 0xDD2399BC31252AA3),
+ make_floatx80_init(0x3FFD, 0xE3B2A8556B8FC517),
+ make_floatx80_init(0x3FFD, 0xEA2D764F64315989),
+ make_floatx80_init(0x3FFD, 0xF3BF5BF8BAD1A21D),
+ make_floatx80_init(0x3FFE, 0x801CE39E0D205C9A),
+ make_floatx80_init(0x3FFE, 0x8630A2DADA1ED066),
+ make_floatx80_init(0x3FFE, 0x8C1AD445F3E09B8C),
+ make_floatx80_init(0x3FFE, 0x91DB8F1664F350E2),
+ make_floatx80_init(0x3FFE, 0x97731420365E538C),
+ make_floatx80_init(0x3FFE, 0x9CE1C8E6A0B8CDBA),
+ make_floatx80_init(0x3FFE, 0xA22832DBCADAAE09),
+ make_floatx80_init(0x3FFE, 0xA746F2DDB7602294),
+ make_floatx80_init(0x3FFE, 0xAC3EC0FB997DD6A2),
+ make_floatx80_init(0x3FFE, 0xB110688AEBDC6F6A),
+ make_floatx80_init(0x3FFE, 0xB5BCC49059ECC4B0),
+ make_floatx80_init(0x3FFE, 0xBA44BC7DD470782F),
+ make_floatx80_init(0x3FFE, 0xBEA94144FD049AAC),
+ make_floatx80_init(0x3FFE, 0xC2EB4ABB661628B6),
+ make_floatx80_init(0x3FFE, 0xC70BD54CE602EE14),
+ make_floatx80_init(0x3FFE, 0xCD000549ADEC7159),
+ make_floatx80_init(0x3FFE, 0xD48457D2D8EA4EA3),
+ make_floatx80_init(0x3FFE, 0xDB948DA712DECE3B),
+ make_floatx80_init(0x3FFE, 0xE23855F969E8096A),
+ make_floatx80_init(0x3FFE, 0xE8771129C4353259),
+ make_floatx80_init(0x3FFE, 0xEE57C16E0D379C0D),
+ make_floatx80_init(0x3FFE, 0xF3E10211A87C3779),
+ make_floatx80_init(0x3FFE, 0xF919039D758B8D41),
+ make_floatx80_init(0x3FFE, 0xFE058B8F64935FB3),
+ make_floatx80_init(0x3FFF, 0x8155FB497B685D04),
+ make_floatx80_init(0x3FFF, 0x83889E3549D108E1),
+ make_floatx80_init(0x3FFF, 0x859CFA76511D724B),
+ make_floatx80_init(0x3FFF, 0x87952ECFFF8131E7),
+ make_floatx80_init(0x3FFF, 0x89732FD19557641B),
+ make_floatx80_init(0x3FFF, 0x8B38CAD101932A35),
+ make_floatx80_init(0x3FFF, 0x8CE7A8D8301EE6B5),
+ make_floatx80_init(0x3FFF, 0x8F46A39E2EAE5281),
+ make_floatx80_init(0x3FFF, 0x922DA7D791888487),
+ make_floatx80_init(0x3FFF, 0x94D19FCBDEDF5241),
+ make_floatx80_init(0x3FFF, 0x973AB94419D2A08B),
+ make_floatx80_init(0x3FFF, 0x996FF00E08E10B96),
+ make_floatx80_init(0x3FFF, 0x9B773F9512321DA7),
+ make_floatx80_init(0x3FFF, 0x9D55CC320F935624),
+ make_floatx80_init(0x3FFF, 0x9F100575006CC571),
+ make_floatx80_init(0x3FFF, 0xA0A9C290D97CC06C),
+ make_floatx80_init(0x3FFF, 0xA22659EBEBC0630A),
+ make_floatx80_init(0x3FFF, 0xA388B4AFF6EF0EC9),
+ make_floatx80_init(0x3FFF, 0xA4D35F1061D292C4),
+ make_floatx80_init(0x3FFF, 0xA60895DCFBE3187E),
+ make_floatx80_init(0x3FFF, 0xA72A51DC7367BEAC),
+ make_floatx80_init(0x3FFF, 0xA83A51530956168F),
+ make_floatx80_init(0x3FFF, 0xA93A20077539546E),
+ make_floatx80_init(0x3FFF, 0xAA9E7245023B2605),
+ make_floatx80_init(0x3FFF, 0xAC4C84BA6FE4D58F),
+ make_floatx80_init(0x3FFF, 0xADCE4A4A606B9712),
+ make_floatx80_init(0x3FFF, 0xAF2A2DCD8D263C9C),
+ make_floatx80_init(0x3FFF, 0xB0656F81F22265C7),
+ make_floatx80_init(0x3FFF, 0xB18465150F71496A),
+ make_floatx80_init(0x3FFF, 0xB28AAA156F9ADA35),
+ make_floatx80_init(0x3FFF, 0xB37B44FF3766B895),
+ make_floatx80_init(0x3FFF, 0xB458C3DCE9630433),
+ make_floatx80_init(0x3FFF, 0xB525529D562246BD),
+ make_floatx80_init(0x3FFF, 0xB5E2CCA95F9D88CC),
+ make_floatx80_init(0x3FFF, 0xB692CADA7ACA1ADA),
+ make_floatx80_init(0x3FFF, 0xB736AEA7A6925838),
+ make_floatx80_init(0x3FFF, 0xB7CFAB287E9F7B36),
+ make_floatx80_init(0x3FFF, 0xB85ECC66CB219835),
+ make_floatx80_init(0x3FFF, 0xB8E4FD5A20A593DA),
+ make_floatx80_init(0x3FFF, 0xB99F41F64AFF9BB5),
+ make_floatx80_init(0x3FFF, 0xBA7F1E17842BBE7B),
+ make_floatx80_init(0x3FFF, 0xBB4712857637E17D),
+ make_floatx80_init(0x3FFF, 0xBBFABE8A4788DF6F),
+ make_floatx80_init(0x3FFF, 0xBC9D0FAD2B689D79),
+ make_floatx80_init(0x3FFF, 0xBD306A39471ECD86),
+ make_floatx80_init(0x3FFF, 0xBDB6C731856AF18A),
+ make_floatx80_init(0x3FFF, 0xBE31CAC502E80D70),
+ make_floatx80_init(0x3FFF, 0xBEA2D55CE33194E2),
+ make_floatx80_init(0x3FFF, 0xBF0B10B7C03128F0),
+ make_floatx80_init(0x3FFF, 0xBF6B7A18DACB778D),
+ make_floatx80_init(0x3FFF, 0xBFC4EA4663FA18F6),
+ make_floatx80_init(0x3FFF, 0xC0181BDE8B89A454),
+ make_floatx80_init(0x3FFF, 0xC065B066CFBF6439),
+ make_floatx80_init(0x3FFF, 0xC0AE345F56340AE6),
+ make_floatx80_init(0x3FFF, 0xC0F222919CB9E6A7)
+};
#endif
diff --git a/target/m68k/translate.c b/target/m68k/translate.c
index a78edd8825..88015e7ed8 100644
--- a/target/m68k/translate.c
+++ b/target/m68k/translate.c
@@ -5057,6 +5057,9 @@ DISAS_INSN(fpu)
case 0x06: /* flognp1 */
gen_helper_flognp1(cpu_env, cpu_dest, cpu_src);
break;
+ case 0x0a: /* fatan */
+ gen_helper_fatan(cpu_env, cpu_dest, cpu_src);
+ break;
case 0x0e: /* fsin */
gen_helper_fsin(cpu_env, cpu_dest, cpu_src);
break;
--
2.14.3
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [Qemu-devel] [PULL 06/11] target/m68k: implement fasin
2018-03-13 15:59 [Qemu-devel] [PULL 00/11] M68k for 2.12 patches Laurent Vivier
` (4 preceding siblings ...)
2018-03-13 15:59 ` [Qemu-devel] [PULL 05/11] target/m68k: implement fatan Laurent Vivier
@ 2018-03-13 15:59 ` Laurent Vivier
2018-03-13 15:59 ` [Qemu-devel] [PULL 07/11] target/m68k: implement facos Laurent Vivier
` (5 subsequent siblings)
11 siblings, 0 replies; 15+ messages in thread
From: Laurent Vivier @ 2018-03-13 15:59 UTC (permalink / raw)
To: qemu-devel; +Cc: Laurent Vivier
Using a local m68k floatx80_asin()
[copied from previous:
Written by Andreas Grabher for Previous, NeXT Computer Emulator.]
Signed-off-by: Laurent Vivier <laurent@vivier.eu>
Message-Id: <20180312202728.23790-7-laurent@vivier.eu>
---
target/m68k/fpu_helper.c | 5 ++++
target/m68k/helper.h | 1 +
target/m68k/softfloat.c | 65 ++++++++++++++++++++++++++++++++++++++++++++++++
target/m68k/softfloat.h | 1 +
target/m68k/translate.c | 3 +++
5 files changed, 75 insertions(+)
diff --git a/target/m68k/fpu_helper.c b/target/m68k/fpu_helper.c
index 47328490ee..972cc97d96 100644
--- a/target/m68k/fpu_helper.c
+++ b/target/m68k/fpu_helper.c
@@ -623,3 +623,8 @@ void HELPER(fatan)(CPUM68KState *env, FPReg *res, FPReg *val)
{
res->d = floatx80_atan(val->d, &env->fp_status);
}
+
+void HELPER(fasin)(CPUM68KState *env, FPReg *res, FPReg *val)
+{
+ res->d = floatx80_asin(val->d, &env->fp_status);
+}
diff --git a/target/m68k/helper.h b/target/m68k/helper.h
index 304569e997..e1aca375e0 100644
--- a/target/m68k/helper.h
+++ b/target/m68k/helper.h
@@ -80,6 +80,7 @@ DEF_HELPER_3(fsin, void, env, fp, fp)
DEF_HELPER_3(fcos, void, env, fp, fp)
DEF_HELPER_4(fsincos, void, env, fp, fp, fp)
DEF_HELPER_3(fatan, void, env, fp, fp)
+DEF_HELPER_3(fasin, void, env, fp, fp)
DEF_HELPER_3(mac_move, void, env, i32, i32)
DEF_HELPER_3(macmulf, i64, env, i32, i32)
diff --git a/target/m68k/softfloat.c b/target/m68k/softfloat.c
index 00ac9a1e0a..91f0435ac3 100644
--- a/target/m68k/softfloat.c
+++ b/target/m68k/softfloat.c
@@ -2167,3 +2167,68 @@ floatx80 floatx80_atan(floatx80 a, float_status *status)
return a;
}
}
+
+/*----------------------------------------------------------------------------
+ | Arc sine
+ *----------------------------------------------------------------------------*/
+
+floatx80 floatx80_asin(floatx80 a, float_status *status)
+{
+ flag aSign;
+ int32_t aExp;
+ uint64_t aSig;
+
+ int8_t user_rnd_mode, user_rnd_prec;
+
+ int32_t compact;
+ floatx80 fp0, fp1, fp2, one;
+
+ aSig = extractFloatx80Frac(a);
+ aExp = extractFloatx80Exp(a);
+ aSign = extractFloatx80Sign(a);
+
+ if (aExp == 0x7FFF && (uint64_t) (aSig << 1)) {
+ return propagateFloatx80NaNOneArg(a, status);
+ }
+
+ if (aExp == 0 && aSig == 0) {
+ return packFloatx80(aSign, 0, 0);
+ }
+
+ compact = floatx80_make_compact(aExp, aSig);
+
+ if (compact >= 0x3FFF8000) { /* |X| >= 1 */
+ if (aExp == one_exp && aSig == one_sig) { /* |X| == 1 */
+ float_raise(float_flag_inexact, status);
+ a = packFloatx80(aSign, piby2_exp, pi_sig);
+ return floatx80_move(a, status);
+ } else { /* |X| > 1 */
+ float_raise(float_flag_invalid, status);
+ return floatx80_default_nan(status);
+ }
+
+ } /* |X| < 1 */
+
+ user_rnd_mode = status->float_rounding_mode;
+ user_rnd_prec = status->floatx80_rounding_precision;
+ status->float_rounding_mode = float_round_nearest_even;
+ status->floatx80_rounding_precision = 80;
+
+ one = packFloatx80(0, one_exp, one_sig);
+ fp0 = a;
+
+ fp1 = floatx80_sub(one, fp0, status); /* 1 - X */
+ fp2 = floatx80_add(one, fp0, status); /* 1 + X */
+ fp1 = floatx80_mul(fp2, fp1, status); /* (1+X)*(1-X) */
+ fp1 = floatx80_sqrt(fp1, status); /* SQRT((1+X)*(1-X)) */
+ fp0 = floatx80_div(fp0, fp1, status); /* X/SQRT((1+X)*(1-X)) */
+
+ status->float_rounding_mode = user_rnd_mode;
+ status->floatx80_rounding_precision = user_rnd_prec;
+
+ a = floatx80_atan(fp0, status); /* ATAN(X/SQRT((1+X)*(1-X))) */
+
+ float_raise(float_flag_inexact, status);
+
+ return a;
+}
diff --git a/target/m68k/softfloat.h b/target/m68k/softfloat.h
index eec45f3ffe..ca0eb674aa 100644
--- a/target/m68k/softfloat.h
+++ b/target/m68k/softfloat.h
@@ -38,4 +38,5 @@ floatx80 floatx80_tan(floatx80 a, float_status *status);
floatx80 floatx80_sin(floatx80 a, float_status *status);
floatx80 floatx80_cos(floatx80 a, float_status *status);
floatx80 floatx80_atan(floatx80 a, float_status *status);
+floatx80 floatx80_asin(floatx80 a, float_status *status);
#endif
diff --git a/target/m68k/translate.c b/target/m68k/translate.c
index 88015e7ed8..d4169c4533 100644
--- a/target/m68k/translate.c
+++ b/target/m68k/translate.c
@@ -5060,6 +5060,9 @@ DISAS_INSN(fpu)
case 0x0a: /* fatan */
gen_helper_fatan(cpu_env, cpu_dest, cpu_src);
break;
+ case 0x0c: /* fasin */
+ gen_helper_fasin(cpu_env, cpu_dest, cpu_src);
+ break;
case 0x0e: /* fsin */
gen_helper_fsin(cpu_env, cpu_dest, cpu_src);
break;
--
2.14.3
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [Qemu-devel] [PULL 07/11] target/m68k: implement facos
2018-03-13 15:59 [Qemu-devel] [PULL 00/11] M68k for 2.12 patches Laurent Vivier
` (5 preceding siblings ...)
2018-03-13 15:59 ` [Qemu-devel] [PULL 06/11] target/m68k: implement fasin Laurent Vivier
@ 2018-03-13 15:59 ` Laurent Vivier
2018-03-13 15:59 ` [Qemu-devel] [PULL 08/11] target/m68k: implement fatanh Laurent Vivier
` (4 subsequent siblings)
11 siblings, 0 replies; 15+ messages in thread
From: Laurent Vivier @ 2018-03-13 15:59 UTC (permalink / raw)
To: qemu-devel; +Cc: Laurent Vivier
Using a local m68k floatx80_acos()
[copied from previous:
Written by Andreas Grabher for Previous, NeXT Computer Emulator.]
Signed-off-by: Laurent Vivier <laurent@vivier.eu>
Message-Id: <20180312202728.23790-8-laurent@vivier.eu>
---
target/m68k/fpu_helper.c | 5 ++++
target/m68k/helper.h | 1 +
target/m68k/softfloat.c | 70 ++++++++++++++++++++++++++++++++++++++++++++++++
target/m68k/softfloat.h | 1 +
target/m68k/translate.c | 3 +++
5 files changed, 80 insertions(+)
diff --git a/target/m68k/fpu_helper.c b/target/m68k/fpu_helper.c
index 972cc97d96..18ad6999cb 100644
--- a/target/m68k/fpu_helper.c
+++ b/target/m68k/fpu_helper.c
@@ -628,3 +628,8 @@ void HELPER(fasin)(CPUM68KState *env, FPReg *res, FPReg *val)
{
res->d = floatx80_asin(val->d, &env->fp_status);
}
+
+void HELPER(facos)(CPUM68KState *env, FPReg *res, FPReg *val)
+{
+ res->d = floatx80_acos(val->d, &env->fp_status);
+}
diff --git a/target/m68k/helper.h b/target/m68k/helper.h
index e1aca375e0..83247a8143 100644
--- a/target/m68k/helper.h
+++ b/target/m68k/helper.h
@@ -81,6 +81,7 @@ DEF_HELPER_3(fcos, void, env, fp, fp)
DEF_HELPER_4(fsincos, void, env, fp, fp, fp)
DEF_HELPER_3(fatan, void, env, fp, fp)
DEF_HELPER_3(fasin, void, env, fp, fp)
+DEF_HELPER_3(facos, void, env, fp, fp)
DEF_HELPER_3(mac_move, void, env, i32, i32)
DEF_HELPER_3(macmulf, i64, env, i32, i32)
diff --git a/target/m68k/softfloat.c b/target/m68k/softfloat.c
index 91f0435ac3..3d66f6946f 100644
--- a/target/m68k/softfloat.c
+++ b/target/m68k/softfloat.c
@@ -23,6 +23,7 @@
#include "fpu/softfloat-macros.h"
#include "softfloat_fpsp_tables.h"
+#define pi_exp 0x4000
#define piby2_exp 0x3FFF
#define pi_sig LIT64(0xc90fdaa22168c235)
@@ -2232,3 +2233,72 @@ floatx80 floatx80_asin(floatx80 a, float_status *status)
return a;
}
+
+/*----------------------------------------------------------------------------
+ | Arc cosine
+ *----------------------------------------------------------------------------*/
+
+floatx80 floatx80_acos(floatx80 a, float_status *status)
+{
+ flag aSign;
+ int32_t aExp;
+ uint64_t aSig;
+
+ int8_t user_rnd_mode, user_rnd_prec;
+
+ int32_t compact;
+ floatx80 fp0, fp1, one;
+
+ aSig = extractFloatx80Frac(a);
+ aExp = extractFloatx80Exp(a);
+ aSign = extractFloatx80Sign(a);
+
+ if (aExp == 0x7FFF && (uint64_t) (aSig << 1)) {
+ return propagateFloatx80NaNOneArg(a, status);
+ }
+ if (aExp == 0 && aSig == 0) {
+ float_raise(float_flag_inexact, status);
+ return roundAndPackFloatx80(status->floatx80_rounding_precision, 0,
+ piby2_exp, pi_sig, 0, status);
+ }
+
+ compact = floatx80_make_compact(aExp, aSig);
+
+ if (compact >= 0x3FFF8000) { /* |X| >= 1 */
+ if (aExp == one_exp && aSig == one_sig) { /* |X| == 1 */
+ if (aSign) { /* X == -1 */
+ a = packFloatx80(0, pi_exp, pi_sig);
+ float_raise(float_flag_inexact, status);
+ return floatx80_move(a, status);
+ } else { /* X == +1 */
+ return packFloatx80(0, 0, 0);
+ }
+ } else { /* |X| > 1 */
+ float_raise(float_flag_invalid, status);
+ return floatx80_default_nan(status);
+ }
+ } /* |X| < 1 */
+
+ user_rnd_mode = status->float_rounding_mode;
+ user_rnd_prec = status->floatx80_rounding_precision;
+ status->float_rounding_mode = float_round_nearest_even;
+ status->floatx80_rounding_precision = 80;
+
+ one = packFloatx80(0, one_exp, one_sig);
+ fp0 = a;
+
+ fp1 = floatx80_add(one, fp0, status); /* 1 + X */
+ fp0 = floatx80_sub(one, fp0, status); /* 1 - X */
+ fp0 = floatx80_div(fp0, fp1, status); /* (1-X)/(1+X) */
+ fp0 = floatx80_sqrt(fp0, status); /* SQRT((1-X)/(1+X)) */
+ fp0 = floatx80_atan(fp0, status); /* ATAN(SQRT((1-X)/(1+X))) */
+
+ status->float_rounding_mode = user_rnd_mode;
+ status->floatx80_rounding_precision = user_rnd_prec;
+
+ a = floatx80_add(fp0, fp0, status); /* 2 * ATAN(SQRT((1-X)/(1+X))) */
+
+ float_raise(float_flag_inexact, status);
+
+ return a;
+}
diff --git a/target/m68k/softfloat.h b/target/m68k/softfloat.h
index ca0eb674aa..1140491c81 100644
--- a/target/m68k/softfloat.h
+++ b/target/m68k/softfloat.h
@@ -39,4 +39,5 @@ floatx80 floatx80_sin(floatx80 a, float_status *status);
floatx80 floatx80_cos(floatx80 a, float_status *status);
floatx80 floatx80_atan(floatx80 a, float_status *status);
floatx80 floatx80_asin(floatx80 a, float_status *status);
+floatx80 floatx80_acos(floatx80 a, float_status *status);
#endif
diff --git a/target/m68k/translate.c b/target/m68k/translate.c
index d4169c4533..5fad76c785 100644
--- a/target/m68k/translate.c
+++ b/target/m68k/translate.c
@@ -5105,6 +5105,9 @@ DISAS_INSN(fpu)
case 0x5e: /* fdneg */
gen_helper_fdneg(cpu_env, cpu_dest, cpu_src);
break;
+ case 0x1c: /* facos */
+ gen_helper_facos(cpu_env, cpu_dest, cpu_src);
+ break;
case 0x1d: /* fcos */
gen_helper_fcos(cpu_env, cpu_dest, cpu_src);
break;
--
2.14.3
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [Qemu-devel] [PULL 08/11] target/m68k: implement fatanh
2018-03-13 15:59 [Qemu-devel] [PULL 00/11] M68k for 2.12 patches Laurent Vivier
` (6 preceding siblings ...)
2018-03-13 15:59 ` [Qemu-devel] [PULL 07/11] target/m68k: implement facos Laurent Vivier
@ 2018-03-13 15:59 ` Laurent Vivier
2018-03-13 15:59 ` [Qemu-devel] [PULL 09/11] target/m68k: implement ftanh Laurent Vivier
` (3 subsequent siblings)
11 siblings, 0 replies; 15+ messages in thread
From: Laurent Vivier @ 2018-03-13 15:59 UTC (permalink / raw)
To: qemu-devel; +Cc: Laurent Vivier
Using a local m68k floatx80_atanh()
[copied from previous:
Written by Andreas Grabher for Previous, NeXT Computer Emulator.]
Signed-off-by: Laurent Vivier <laurent@vivier.eu>
Message-Id: <20180312202728.23790-9-laurent@vivier.eu>
---
target/m68k/fpu_helper.c | 5 ++++
target/m68k/helper.h | 1 +
target/m68k/softfloat.c | 65 ++++++++++++++++++++++++++++++++++++++++++++++++
target/m68k/softfloat.h | 1 +
target/m68k/translate.c | 3 +++
5 files changed, 75 insertions(+)
diff --git a/target/m68k/fpu_helper.c b/target/m68k/fpu_helper.c
index 18ad6999cb..38b663e1d2 100644
--- a/target/m68k/fpu_helper.c
+++ b/target/m68k/fpu_helper.c
@@ -633,3 +633,8 @@ void HELPER(facos)(CPUM68KState *env, FPReg *res, FPReg *val)
{
res->d = floatx80_acos(val->d, &env->fp_status);
}
+
+void HELPER(fatanh)(CPUM68KState *env, FPReg *res, FPReg *val)
+{
+ res->d = floatx80_atanh(val->d, &env->fp_status);
+}
diff --git a/target/m68k/helper.h b/target/m68k/helper.h
index 83247a8143..092baec3d5 100644
--- a/target/m68k/helper.h
+++ b/target/m68k/helper.h
@@ -82,6 +82,7 @@ DEF_HELPER_4(fsincos, void, env, fp, fp, fp)
DEF_HELPER_3(fatan, void, env, fp, fp)
DEF_HELPER_3(fasin, void, env, fp, fp)
DEF_HELPER_3(facos, void, env, fp, fp)
+DEF_HELPER_3(fatanh, void, env, fp, fp)
DEF_HELPER_3(mac_move, void, env, i32, i32)
DEF_HELPER_3(macmulf, i64, env, i32, i32)
diff --git a/target/m68k/softfloat.c b/target/m68k/softfloat.c
index 3d66f6946f..5ce8413e96 100644
--- a/target/m68k/softfloat.c
+++ b/target/m68k/softfloat.c
@@ -2302,3 +2302,68 @@ floatx80 floatx80_acos(floatx80 a, float_status *status)
return a;
}
+
+/*----------------------------------------------------------------------------
+ | Hyperbolic arc tangent
+ *----------------------------------------------------------------------------*/
+
+floatx80 floatx80_atanh(floatx80 a, float_status *status)
+{
+ flag aSign;
+ int32_t aExp;
+ uint64_t aSig;
+
+ int8_t user_rnd_mode, user_rnd_prec;
+
+ int32_t compact;
+ floatx80 fp0, fp1, fp2, one;
+
+ aSig = extractFloatx80Frac(a);
+ aExp = extractFloatx80Exp(a);
+ aSign = extractFloatx80Sign(a);
+
+ if (aExp == 0x7FFF && (uint64_t) (aSig << 1)) {
+ return propagateFloatx80NaNOneArg(a, status);
+ }
+
+ if (aExp == 0 && aSig == 0) {
+ return packFloatx80(aSign, 0, 0);
+ }
+
+ compact = floatx80_make_compact(aExp, aSig);
+
+ if (compact >= 0x3FFF8000) { /* |X| >= 1 */
+ if (aExp == one_exp && aSig == one_sig) { /* |X| == 1 */
+ float_raise(float_flag_divbyzero, status);
+ return packFloatx80(aSign, floatx80_infinity.high,
+ floatx80_infinity.low);
+ } else { /* |X| > 1 */
+ float_raise(float_flag_invalid, status);
+ return floatx80_default_nan(status);
+ }
+ } /* |X| < 1 */
+
+ user_rnd_mode = status->float_rounding_mode;
+ user_rnd_prec = status->floatx80_rounding_precision;
+ status->float_rounding_mode = float_round_nearest_even;
+ status->floatx80_rounding_precision = 80;
+
+ one = packFloatx80(0, one_exp, one_sig);
+ fp2 = packFloatx80(aSign, 0x3FFE, one_sig); /* SIGN(X) * (1/2) */
+ fp0 = packFloatx80(0, aExp, aSig); /* Y = |X| */
+ fp1 = packFloatx80(1, aExp, aSig); /* -Y */
+ fp0 = floatx80_add(fp0, fp0, status); /* 2Y */
+ fp1 = floatx80_add(fp1, one, status); /* 1-Y */
+ fp0 = floatx80_div(fp0, fp1, status); /* Z = 2Y/(1-Y) */
+ fp0 = floatx80_lognp1(fp0, status); /* LOG1P(Z) */
+
+ status->float_rounding_mode = user_rnd_mode;
+ status->floatx80_rounding_precision = user_rnd_prec;
+
+ a = floatx80_mul(fp0, fp2,
+ status); /* ATANH(X) = SIGN(X) * (1/2) * LOG1P(Z) */
+
+ float_raise(float_flag_inexact, status);
+
+ return a;
+}
diff --git a/target/m68k/softfloat.h b/target/m68k/softfloat.h
index 1140491c81..e9943aed20 100644
--- a/target/m68k/softfloat.h
+++ b/target/m68k/softfloat.h
@@ -40,4 +40,5 @@ floatx80 floatx80_cos(floatx80 a, float_status *status);
floatx80 floatx80_atan(floatx80 a, float_status *status);
floatx80 floatx80_asin(floatx80 a, float_status *status);
floatx80 floatx80_acos(floatx80 a, float_status *status);
+floatx80 floatx80_atanh(floatx80 a, float_status *status);
#endif
diff --git a/target/m68k/translate.c b/target/m68k/translate.c
index 5fad76c785..2f7caa0ca0 100644
--- a/target/m68k/translate.c
+++ b/target/m68k/translate.c
@@ -5063,6 +5063,9 @@ DISAS_INSN(fpu)
case 0x0c: /* fasin */
gen_helper_fasin(cpu_env, cpu_dest, cpu_src);
break;
+ case 0x0d: /* fatanh */
+ gen_helper_fatanh(cpu_env, cpu_dest, cpu_src);
+ break;
case 0x0e: /* fsin */
gen_helper_fsin(cpu_env, cpu_dest, cpu_src);
break;
--
2.14.3
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [Qemu-devel] [PULL 09/11] target/m68k: implement ftanh
2018-03-13 15:59 [Qemu-devel] [PULL 00/11] M68k for 2.12 patches Laurent Vivier
` (7 preceding siblings ...)
2018-03-13 15:59 ` [Qemu-devel] [PULL 08/11] target/m68k: implement fatanh Laurent Vivier
@ 2018-03-13 15:59 ` Laurent Vivier
2018-03-13 15:59 ` [Qemu-devel] [PULL 10/11] target/m68k: implement fsinh Laurent Vivier
` (2 subsequent siblings)
11 siblings, 0 replies; 15+ messages in thread
From: Laurent Vivier @ 2018-03-13 15:59 UTC (permalink / raw)
To: qemu-devel; +Cc: Laurent Vivier
Using local m68k floatx80_tanh() and floatx80_etoxm1()
[copied from previous:
Written by Andreas Grabher for Previous, NeXT Computer Emulator.]
Signed-off-by: Laurent Vivier <laurent@vivier.eu>
Message-Id: <20180312202728.23790-10-laurent@vivier.eu>
---
target/m68k/fpu_helper.c | 5 +
target/m68k/helper.h | 1 +
target/m68k/softfloat.c | 366 +++++++++++++++++++++++++++++++++++++++++++++++
target/m68k/softfloat.h | 2 +
target/m68k/translate.c | 3 +
5 files changed, 377 insertions(+)
diff --git a/target/m68k/fpu_helper.c b/target/m68k/fpu_helper.c
index 38b663e1d2..7d68879f34 100644
--- a/target/m68k/fpu_helper.c
+++ b/target/m68k/fpu_helper.c
@@ -638,3 +638,8 @@ void HELPER(fatanh)(CPUM68KState *env, FPReg *res, FPReg *val)
{
res->d = floatx80_atanh(val->d, &env->fp_status);
}
+
+void HELPER(ftanh)(CPUM68KState *env, FPReg *res, FPReg *val)
+{
+ res->d = floatx80_tanh(val->d, &env->fp_status);
+}
diff --git a/target/m68k/helper.h b/target/m68k/helper.h
index 092baec3d5..f100141367 100644
--- a/target/m68k/helper.h
+++ b/target/m68k/helper.h
@@ -83,6 +83,7 @@ DEF_HELPER_3(fatan, void, env, fp, fp)
DEF_HELPER_3(fasin, void, env, fp, fp)
DEF_HELPER_3(facos, void, env, fp, fp)
DEF_HELPER_3(fatanh, void, env, fp, fp)
+DEF_HELPER_3(ftanh, void, env, fp, fp)
DEF_HELPER_3(mac_move, void, env, i32, i32)
DEF_HELPER_3(macmulf, i64, env, i32, i32)
diff --git a/target/m68k/softfloat.c b/target/m68k/softfloat.c
index 5ce8413e96..4ce5783f03 100644
--- a/target/m68k/softfloat.c
+++ b/target/m68k/softfloat.c
@@ -2367,3 +2367,369 @@ floatx80 floatx80_atanh(floatx80 a, float_status *status)
return a;
}
+
+/*----------------------------------------------------------------------------
+ | e to x minus 1
+ *----------------------------------------------------------------------------*/
+
+floatx80 floatx80_etoxm1(floatx80 a, float_status *status)
+{
+ flag aSign;
+ int32_t aExp;
+ uint64_t aSig;
+
+ int8_t user_rnd_mode, user_rnd_prec;
+
+ int32_t compact, n, j, m, m1;
+ floatx80 fp0, fp1, fp2, fp3, l2, sc, onebysc;
+
+ aSig = extractFloatx80Frac(a);
+ aExp = extractFloatx80Exp(a);
+ aSign = extractFloatx80Sign(a);
+
+ if (aExp == 0x7FFF) {
+ if ((uint64_t) (aSig << 1)) {
+ return propagateFloatx80NaNOneArg(a, status);
+ }
+ if (aSign) {
+ return packFloatx80(aSign, one_exp, one_sig);
+ }
+ return packFloatx80(0, floatx80_infinity.high,
+ floatx80_infinity.low);
+ }
+
+ if (aExp == 0 && aSig == 0) {
+ return packFloatx80(aSign, 0, 0);
+ }
+
+ user_rnd_mode = status->float_rounding_mode;
+ user_rnd_prec = status->floatx80_rounding_precision;
+ status->float_rounding_mode = float_round_nearest_even;
+ status->floatx80_rounding_precision = 80;
+
+ if (aExp >= 0x3FFD) { /* |X| >= 1/4 */
+ compact = floatx80_make_compact(aExp, aSig);
+
+ if (compact <= 0x4004C215) { /* |X| <= 70 log2 */
+ fp0 = a;
+ fp1 = a;
+ fp0 = floatx80_mul(fp0, float32_to_floatx80(
+ make_float32(0x42B8AA3B), status),
+ status); /* 64/log2 * X */
+ n = floatx80_to_int32(fp0, status); /* int(64/log2*X) */
+ fp0 = int32_to_floatx80(n, status);
+
+ j = n & 0x3F; /* J = N mod 64 */
+ m = n / 64; /* NOTE: this is really arithmetic right shift by 6 */
+ if (n < 0 && j) {
+ /* arithmetic right shift is division and
+ * round towards minus infinity
+ */
+ m--;
+ }
+ m1 = -m;
+ /*m += 0x3FFF; // biased exponent of 2^(M) */
+ /*m1 += 0x3FFF; // biased exponent of -2^(-M) */
+
+ fp2 = fp0; /* N */
+ fp0 = floatx80_mul(fp0, float32_to_floatx80(
+ make_float32(0xBC317218), status),
+ status); /* N * L1, L1 = lead(-log2/64) */
+ l2 = packFloatx80(0, 0x3FDC, LIT64(0x82E308654361C4C6));
+ fp2 = floatx80_mul(fp2, l2, status); /* N * L2, L1+L2 = -log2/64 */
+ fp0 = floatx80_add(fp0, fp1, status); /* X + N*L1 */
+ fp0 = floatx80_add(fp0, fp2, status); /* R */
+
+ fp1 = floatx80_mul(fp0, fp0, status); /* S = R*R */
+ fp2 = float32_to_floatx80(make_float32(0x3950097B),
+ status); /* A6 */
+ fp2 = floatx80_mul(fp2, fp1, status); /* fp2 is S*A6 */
+ fp3 = floatx80_mul(float32_to_floatx80(make_float32(0x3AB60B6A),
+ status), fp1, status); /* fp3 is S*A5 */
+ fp2 = floatx80_add(fp2, float64_to_floatx80(
+ make_float64(0x3F81111111174385), status),
+ status); /* fp2 IS A4+S*A6 */
+ fp3 = floatx80_add(fp3, float64_to_floatx80(
+ make_float64(0x3FA5555555554F5A), status),
+ status); /* fp3 is A3+S*A5 */
+ fp2 = floatx80_mul(fp2, fp1, status); /* fp2 IS S*(A4+S*A6) */
+ fp3 = floatx80_mul(fp3, fp1, status); /* fp3 IS S*(A3+S*A5) */
+ fp2 = floatx80_add(fp2, float64_to_floatx80(
+ make_float64(0x3FC5555555555555), status),
+ status); /* fp2 IS A2+S*(A4+S*A6) */
+ fp3 = floatx80_add(fp3, float32_to_floatx80(
+ make_float32(0x3F000000), status),
+ status); /* fp3 IS A1+S*(A3+S*A5) */
+ fp2 = floatx80_mul(fp2, fp1,
+ status); /* fp2 IS S*(A2+S*(A4+S*A6)) */
+ fp1 = floatx80_mul(fp1, fp3,
+ status); /* fp1 IS S*(A1+S*(A3+S*A5)) */
+ fp2 = floatx80_mul(fp2, fp0,
+ status); /* fp2 IS R*S*(A2+S*(A4+S*A6)) */
+ fp0 = floatx80_add(fp0, fp1,
+ status); /* fp0 IS R+S*(A1+S*(A3+S*A5)) */
+ fp0 = floatx80_add(fp0, fp2, status); /* fp0 IS EXP(R) - 1 */
+
+ fp0 = floatx80_mul(fp0, exp_tbl[j],
+ status); /* 2^(J/64)*(Exp(R)-1) */
+
+ if (m >= 64) {
+ fp1 = float32_to_floatx80(exp_tbl2[j], status);
+ onebysc = packFloatx80(1, m1 + 0x3FFF, one_sig); /* -2^(-M) */
+ fp1 = floatx80_add(fp1, onebysc, status);
+ fp0 = floatx80_add(fp0, fp1, status);
+ fp0 = floatx80_add(fp0, exp_tbl[j], status);
+ } else if (m < -3) {
+ fp0 = floatx80_add(fp0, float32_to_floatx80(exp_tbl2[j],
+ status), status);
+ fp0 = floatx80_add(fp0, exp_tbl[j], status);
+ onebysc = packFloatx80(1, m1 + 0x3FFF, one_sig); /* -2^(-M) */
+ fp0 = floatx80_add(fp0, onebysc, status);
+ } else { /* -3 <= m <= 63 */
+ fp1 = exp_tbl[j];
+ fp0 = floatx80_add(fp0, float32_to_floatx80(exp_tbl2[j],
+ status), status);
+ onebysc = packFloatx80(1, m1 + 0x3FFF, one_sig); /* -2^(-M) */
+ fp1 = floatx80_add(fp1, onebysc, status);
+ fp0 = floatx80_add(fp0, fp1, status);
+ }
+
+ sc = packFloatx80(0, m + 0x3FFF, one_sig);
+
+ status->float_rounding_mode = user_rnd_mode;
+ status->floatx80_rounding_precision = user_rnd_prec;
+
+ a = floatx80_mul(fp0, sc, status);
+
+ float_raise(float_flag_inexact, status);
+
+ return a;
+ } else { /* |X| > 70 log2 */
+ if (aSign) {
+ fp0 = float32_to_floatx80(make_float32(0xBF800000),
+ status); /* -1 */
+
+ status->float_rounding_mode = user_rnd_mode;
+ status->floatx80_rounding_precision = user_rnd_prec;
+
+ a = floatx80_add(fp0, float32_to_floatx80(
+ make_float32(0x00800000), status),
+ status); /* -1 + 2^(-126) */
+
+ float_raise(float_flag_inexact, status);
+
+ return a;
+ } else {
+ status->float_rounding_mode = user_rnd_mode;
+ status->floatx80_rounding_precision = user_rnd_prec;
+
+ return floatx80_etox(a, status);
+ }
+ }
+ } else { /* |X| < 1/4 */
+ if (aExp >= 0x3FBE) {
+ fp0 = a;
+ fp0 = floatx80_mul(fp0, fp0, status); /* S = X*X */
+ fp1 = float32_to_floatx80(make_float32(0x2F30CAA8),
+ status); /* B12 */
+ fp1 = floatx80_mul(fp1, fp0, status); /* S * B12 */
+ fp2 = float32_to_floatx80(make_float32(0x310F8290),
+ status); /* B11 */
+ fp1 = floatx80_add(fp1, float32_to_floatx80(
+ make_float32(0x32D73220), status),
+ status); /* B10 */
+ fp2 = floatx80_mul(fp2, fp0, status);
+ fp1 = floatx80_mul(fp1, fp0, status);
+ fp2 = floatx80_add(fp2, float32_to_floatx80(
+ make_float32(0x3493F281), status),
+ status); /* B9 */
+ fp1 = floatx80_add(fp1, float64_to_floatx80(
+ make_float64(0x3EC71DE3A5774682), status),
+ status); /* B8 */
+ fp2 = floatx80_mul(fp2, fp0, status);
+ fp1 = floatx80_mul(fp1, fp0, status);
+ fp2 = floatx80_add(fp2, float64_to_floatx80(
+ make_float64(0x3EFA01A019D7CB68), status),
+ status); /* B7 */
+ fp1 = floatx80_add(fp1, float64_to_floatx80(
+ make_float64(0x3F2A01A01A019DF3), status),
+ status); /* B6 */
+ fp2 = floatx80_mul(fp2, fp0, status);
+ fp1 = floatx80_mul(fp1, fp0, status);
+ fp2 = floatx80_add(fp2, float64_to_floatx80(
+ make_float64(0x3F56C16C16C170E2), status),
+ status); /* B5 */
+ fp1 = floatx80_add(fp1, float64_to_floatx80(
+ make_float64(0x3F81111111111111), status),
+ status); /* B4 */
+ fp2 = floatx80_mul(fp2, fp0, status);
+ fp1 = floatx80_mul(fp1, fp0, status);
+ fp2 = floatx80_add(fp2, float64_to_floatx80(
+ make_float64(0x3FA5555555555555), status),
+ status); /* B3 */
+ fp3 = packFloatx80(0, 0x3FFC, LIT64(0xAAAAAAAAAAAAAAAB));
+ fp1 = floatx80_add(fp1, fp3, status); /* B2 */
+ fp2 = floatx80_mul(fp2, fp0, status);
+ fp1 = floatx80_mul(fp1, fp0, status);
+
+ fp2 = floatx80_mul(fp2, fp0, status);
+ fp1 = floatx80_mul(fp1, a, status);
+
+ fp0 = floatx80_mul(fp0, float32_to_floatx80(
+ make_float32(0x3F000000), status),
+ status); /* S*B1 */
+ fp1 = floatx80_add(fp1, fp2, status); /* Q */
+ fp0 = floatx80_add(fp0, fp1, status); /* S*B1+Q */
+
+ status->float_rounding_mode = user_rnd_mode;
+ status->floatx80_rounding_precision = user_rnd_prec;
+
+ a = floatx80_add(fp0, a, status);
+
+ float_raise(float_flag_inexact, status);
+
+ return a;
+ } else { /* |X| < 2^(-65) */
+ sc = packFloatx80(1, 1, one_sig);
+ fp0 = a;
+
+ if (aExp < 0x0033) { /* |X| < 2^(-16382) */
+ fp0 = floatx80_mul(fp0, float64_to_floatx80(
+ make_float64(0x48B0000000000000), status),
+ status);
+ fp0 = floatx80_add(fp0, sc, status);
+
+ status->float_rounding_mode = user_rnd_mode;
+ status->floatx80_rounding_precision = user_rnd_prec;
+
+ a = floatx80_mul(fp0, float64_to_floatx80(
+ make_float64(0x3730000000000000), status),
+ status);
+ } else {
+ status->float_rounding_mode = user_rnd_mode;
+ status->floatx80_rounding_precision = user_rnd_prec;
+
+ a = floatx80_add(fp0, sc, status);
+ }
+
+ float_raise(float_flag_inexact, status);
+
+ return a;
+ }
+ }
+}
+
+/*----------------------------------------------------------------------------
+ | Hyperbolic tangent
+ *----------------------------------------------------------------------------*/
+
+floatx80 floatx80_tanh(floatx80 a, float_status *status)
+{
+ flag aSign, vSign;
+ int32_t aExp, vExp;
+ uint64_t aSig, vSig;
+
+ int8_t user_rnd_mode, user_rnd_prec;
+
+ int32_t compact;
+ floatx80 fp0, fp1;
+ uint32_t sign;
+
+ aSig = extractFloatx80Frac(a);
+ aExp = extractFloatx80Exp(a);
+ aSign = extractFloatx80Sign(a);
+
+ if (aExp == 0x7FFF) {
+ if ((uint64_t) (aSig << 1)) {
+ return propagateFloatx80NaNOneArg(a, status);
+ }
+ return packFloatx80(aSign, one_exp, one_sig);
+ }
+
+ if (aExp == 0 && aSig == 0) {
+ return packFloatx80(aSign, 0, 0);
+ }
+
+ user_rnd_mode = status->float_rounding_mode;
+ user_rnd_prec = status->floatx80_rounding_precision;
+ status->float_rounding_mode = float_round_nearest_even;
+ status->floatx80_rounding_precision = 80;
+
+ compact = floatx80_make_compact(aExp, aSig);
+
+ if (compact < 0x3FD78000 || compact > 0x3FFFDDCE) {
+ /* TANHBORS */
+ if (compact < 0x3FFF8000) {
+ /* TANHSM */
+ status->float_rounding_mode = user_rnd_mode;
+ status->floatx80_rounding_precision = user_rnd_prec;
+
+ a = floatx80_move(a, status);
+
+ float_raise(float_flag_inexact, status);
+
+ return a;
+ } else {
+ if (compact > 0x40048AA1) {
+ /* TANHHUGE */
+ sign = 0x3F800000;
+ sign |= aSign ? 0x80000000 : 0x00000000;
+ fp0 = float32_to_floatx80(make_float32(sign), status);
+ sign &= 0x80000000;
+ sign ^= 0x80800000; /* -SIGN(X)*EPS */
+
+ status->float_rounding_mode = user_rnd_mode;
+ status->floatx80_rounding_precision = user_rnd_prec;
+
+ a = floatx80_add(fp0, float32_to_floatx80(make_float32(sign),
+ status), status);
+
+ float_raise(float_flag_inexact, status);
+
+ return a;
+ } else {
+ fp0 = packFloatx80(0, aExp + 1, aSig); /* Y = 2|X| */
+ fp0 = floatx80_etox(fp0, status); /* FP0 IS EXP(Y) */
+ fp0 = floatx80_add(fp0, float32_to_floatx80(
+ make_float32(0x3F800000),
+ status), status); /* EXP(Y)+1 */
+ sign = aSign ? 0x80000000 : 0x00000000;
+ fp1 = floatx80_div(float32_to_floatx80(make_float32(
+ sign ^ 0xC0000000), status), fp0,
+ status); /* -SIGN(X)*2 / [EXP(Y)+1] */
+ fp0 = float32_to_floatx80(make_float32(sign | 0x3F800000),
+ status); /* SIGN */
+
+ status->float_rounding_mode = user_rnd_mode;
+ status->floatx80_rounding_precision = user_rnd_prec;
+
+ a = floatx80_add(fp1, fp0, status);
+
+ float_raise(float_flag_inexact, status);
+
+ return a;
+ }
+ }
+ } else { /* 2**(-40) < |X| < (5/2)LOG2 */
+ fp0 = packFloatx80(0, aExp + 1, aSig); /* Y = 2|X| */
+ fp0 = floatx80_etoxm1(fp0, status); /* FP0 IS Z = EXPM1(Y) */
+ fp1 = floatx80_add(fp0, float32_to_floatx80(make_float32(0x40000000),
+ status),
+ status); /* Z+2 */
+
+ vSign = extractFloatx80Sign(fp1);
+ vExp = extractFloatx80Exp(fp1);
+ vSig = extractFloatx80Frac(fp1);
+
+ fp1 = packFloatx80(vSign ^ aSign, vExp, vSig);
+
+ status->float_rounding_mode = user_rnd_mode;
+ status->floatx80_rounding_precision = user_rnd_prec;
+
+ a = floatx80_div(fp0, fp1, status);
+
+ float_raise(float_flag_inexact, status);
+
+ return a;
+ }
+}
diff --git a/target/m68k/softfloat.h b/target/m68k/softfloat.h
index e9943aed20..4cdb5a49ca 100644
--- a/target/m68k/softfloat.h
+++ b/target/m68k/softfloat.h
@@ -41,4 +41,6 @@ floatx80 floatx80_atan(floatx80 a, float_status *status);
floatx80 floatx80_asin(floatx80 a, float_status *status);
floatx80 floatx80_acos(floatx80 a, float_status *status);
floatx80 floatx80_atanh(floatx80 a, float_status *status);
+floatx80 floatx80_etoxm1(floatx80 a, float_status *status);
+floatx80 floatx80_tanh(floatx80 a, float_status *status);
#endif
diff --git a/target/m68k/translate.c b/target/m68k/translate.c
index 2f7caa0ca0..0caae904b5 100644
--- a/target/m68k/translate.c
+++ b/target/m68k/translate.c
@@ -5057,6 +5057,9 @@ DISAS_INSN(fpu)
case 0x06: /* flognp1 */
gen_helper_flognp1(cpu_env, cpu_dest, cpu_src);
break;
+ case 0x09: /* ftanh */
+ gen_helper_ftanh(cpu_env, cpu_dest, cpu_src);
+ break;
case 0x0a: /* fatan */
gen_helper_fatan(cpu_env, cpu_dest, cpu_src);
break;
--
2.14.3
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [Qemu-devel] [PULL 10/11] target/m68k: implement fsinh
2018-03-13 15:59 [Qemu-devel] [PULL 00/11] M68k for 2.12 patches Laurent Vivier
` (8 preceding siblings ...)
2018-03-13 15:59 ` [Qemu-devel] [PULL 09/11] target/m68k: implement ftanh Laurent Vivier
@ 2018-03-13 15:59 ` Laurent Vivier
2018-03-13 15:59 ` [Qemu-devel] [PULL 11/11] target/m68k: implement fcosh Laurent Vivier
2018-03-15 13:01 ` [Qemu-devel] [PULL 00/11] M68k for 2.12 patches Peter Maydell
11 siblings, 0 replies; 15+ messages in thread
From: Laurent Vivier @ 2018-03-13 15:59 UTC (permalink / raw)
To: qemu-devel; +Cc: Laurent Vivier
Using a local m68k floatx80_sinh()
[copied from previous:
Written by Andreas Grabher for Previous, NeXT Computer Emulator.]
Signed-off-by: Laurent Vivier <laurent@vivier.eu>
Message-Id: <20180312202728.23790-11-laurent@vivier.eu>
---
target/m68k/fpu_helper.c | 5 +++
target/m68k/helper.h | 1 +
target/m68k/softfloat.c | 89 ++++++++++++++++++++++++++++++++++++++++++++++++
target/m68k/softfloat.h | 1 +
target/m68k/translate.c | 3 ++
5 files changed, 99 insertions(+)
diff --git a/target/m68k/fpu_helper.c b/target/m68k/fpu_helper.c
index 7d68879f34..4c969dfe00 100644
--- a/target/m68k/fpu_helper.c
+++ b/target/m68k/fpu_helper.c
@@ -643,3 +643,8 @@ void HELPER(ftanh)(CPUM68KState *env, FPReg *res, FPReg *val)
{
res->d = floatx80_tanh(val->d, &env->fp_status);
}
+
+void HELPER(fsinh)(CPUM68KState *env, FPReg *res, FPReg *val)
+{
+ res->d = floatx80_sinh(val->d, &env->fp_status);
+}
diff --git a/target/m68k/helper.h b/target/m68k/helper.h
index f100141367..acdca1af03 100644
--- a/target/m68k/helper.h
+++ b/target/m68k/helper.h
@@ -84,6 +84,7 @@ DEF_HELPER_3(fasin, void, env, fp, fp)
DEF_HELPER_3(facos, void, env, fp, fp)
DEF_HELPER_3(fatanh, void, env, fp, fp)
DEF_HELPER_3(ftanh, void, env, fp, fp)
+DEF_HELPER_3(fsinh, void, env, fp, fp)
DEF_HELPER_3(mac_move, void, env, i32, i32)
DEF_HELPER_3(macmulf, i64, env, i32, i32)
diff --git a/target/m68k/softfloat.c b/target/m68k/softfloat.c
index 4ce5783f03..1528bfd147 100644
--- a/target/m68k/softfloat.c
+++ b/target/m68k/softfloat.c
@@ -2733,3 +2733,92 @@ floatx80 floatx80_tanh(floatx80 a, float_status *status)
return a;
}
}
+
+/*----------------------------------------------------------------------------
+ | Hyperbolic sine
+ *----------------------------------------------------------------------------*/
+
+floatx80 floatx80_sinh(floatx80 a, float_status *status)
+{
+ flag aSign;
+ int32_t aExp;
+ uint64_t aSig;
+
+ int8_t user_rnd_mode, user_rnd_prec;
+
+ int32_t compact;
+ floatx80 fp0, fp1, fp2;
+ float32 fact;
+
+ aSig = extractFloatx80Frac(a);
+ aExp = extractFloatx80Exp(a);
+ aSign = extractFloatx80Sign(a);
+
+ if (aExp == 0x7FFF) {
+ if ((uint64_t) (aSig << 1)) {
+ return propagateFloatx80NaNOneArg(a, status);
+ }
+ return packFloatx80(aSign, floatx80_infinity.high,
+ floatx80_infinity.low);
+ }
+
+ if (aExp == 0 && aSig == 0) {
+ return packFloatx80(aSign, 0, 0);
+ }
+
+ user_rnd_mode = status->float_rounding_mode;
+ user_rnd_prec = status->floatx80_rounding_precision;
+ status->float_rounding_mode = float_round_nearest_even;
+ status->floatx80_rounding_precision = 80;
+
+ compact = floatx80_make_compact(aExp, aSig);
+
+ if (compact > 0x400CB167) {
+ /* SINHBIG */
+ if (compact > 0x400CB2B3) {
+ status->float_rounding_mode = user_rnd_mode;
+ status->floatx80_rounding_precision = user_rnd_prec;
+
+ return roundAndPackFloatx80(status->floatx80_rounding_precision,
+ aSign, 0x8000, aSig, 0, status);
+ } else {
+ fp0 = floatx80_abs(a); /* Y = |X| */
+ fp0 = floatx80_sub(fp0, float64_to_floatx80(
+ make_float64(0x40C62D38D3D64634), status),
+ status); /* (|X|-16381LOG2_LEAD) */
+ fp0 = floatx80_sub(fp0, float64_to_floatx80(
+ make_float64(0x3D6F90AEB1E75CC7), status),
+ status); /* |X| - 16381 LOG2, ACCURATE */
+ fp0 = floatx80_etox(fp0, status);
+ fp2 = packFloatx80(aSign, 0x7FFB, one_sig);
+
+ status->float_rounding_mode = user_rnd_mode;
+ status->floatx80_rounding_precision = user_rnd_prec;
+
+ a = floatx80_mul(fp0, fp2, status);
+
+ float_raise(float_flag_inexact, status);
+
+ return a;
+ }
+ } else { /* |X| < 16380 LOG2 */
+ fp0 = floatx80_abs(a); /* Y = |X| */
+ fp0 = floatx80_etoxm1(fp0, status); /* FP0 IS Z = EXPM1(Y) */
+ fp1 = floatx80_add(fp0, float32_to_floatx80(make_float32(0x3F800000),
+ status), status); /* 1+Z */
+ fp2 = fp0;
+ fp0 = floatx80_div(fp0, fp1, status); /* Z/(1+Z) */
+ fp0 = floatx80_add(fp0, fp2, status);
+
+ fact = packFloat32(aSign, 0x7E, 0);
+
+ status->float_rounding_mode = user_rnd_mode;
+ status->floatx80_rounding_precision = user_rnd_prec;
+
+ a = floatx80_mul(fp0, float32_to_floatx80(fact, status), status);
+
+ float_raise(float_flag_inexact, status);
+
+ return a;
+ }
+}
diff --git a/target/m68k/softfloat.h b/target/m68k/softfloat.h
index 4cdb5a49ca..f033abf9ea 100644
--- a/target/m68k/softfloat.h
+++ b/target/m68k/softfloat.h
@@ -43,4 +43,5 @@ floatx80 floatx80_acos(floatx80 a, float_status *status);
floatx80 floatx80_atanh(floatx80 a, float_status *status);
floatx80 floatx80_etoxm1(floatx80 a, float_status *status);
floatx80 floatx80_tanh(floatx80 a, float_status *status);
+floatx80 floatx80_sinh(floatx80 a, float_status *status);
#endif
diff --git a/target/m68k/translate.c b/target/m68k/translate.c
index 0caae904b5..7d83aaf91d 100644
--- a/target/m68k/translate.c
+++ b/target/m68k/translate.c
@@ -5042,6 +5042,9 @@ DISAS_INSN(fpu)
case 1: /* fint */
gen_helper_firound(cpu_env, cpu_dest, cpu_src);
break;
+ case 2: /* fsinh */
+ gen_helper_fsinh(cpu_env, cpu_dest, cpu_src);
+ break;
case 3: /* fintrz */
gen_helper_fitrunc(cpu_env, cpu_dest, cpu_src);
break;
--
2.14.3
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [Qemu-devel] [PULL 11/11] target/m68k: implement fcosh
2018-03-13 15:59 [Qemu-devel] [PULL 00/11] M68k for 2.12 patches Laurent Vivier
` (9 preceding siblings ...)
2018-03-13 15:59 ` [Qemu-devel] [PULL 10/11] target/m68k: implement fsinh Laurent Vivier
@ 2018-03-13 15:59 ` Laurent Vivier
2018-03-15 13:01 ` [Qemu-devel] [PULL 00/11] M68k for 2.12 patches Peter Maydell
11 siblings, 0 replies; 15+ messages in thread
From: Laurent Vivier @ 2018-03-13 15:59 UTC (permalink / raw)
To: qemu-devel; +Cc: Laurent Vivier
Using a local m68k floatx80_cosh()
[copied from previous:
Written by Andreas Grabher for Previous, NeXT Computer Emulator.]
Signed-off-by: Laurent Vivier <laurent@vivier.eu>
Message-Id: <20180312202728.23790-12-laurent@vivier.eu>
---
target/m68k/fpu_helper.c | 5 +++
target/m68k/helper.h | 1 +
target/m68k/softfloat.c | 81 ++++++++++++++++++++++++++++++++++++++++++++++++
target/m68k/softfloat.h | 1 +
target/m68k/translate.c | 3 ++
5 files changed, 91 insertions(+)
diff --git a/target/m68k/fpu_helper.c b/target/m68k/fpu_helper.c
index 4c969dfe00..6eeffdf9bb 100644
--- a/target/m68k/fpu_helper.c
+++ b/target/m68k/fpu_helper.c
@@ -648,3 +648,8 @@ void HELPER(fsinh)(CPUM68KState *env, FPReg *res, FPReg *val)
{
res->d = floatx80_sinh(val->d, &env->fp_status);
}
+
+void HELPER(fcosh)(CPUM68KState *env, FPReg *res, FPReg *val)
+{
+ res->d = floatx80_cosh(val->d, &env->fp_status);
+}
diff --git a/target/m68k/helper.h b/target/m68k/helper.h
index acdca1af03..feee7be626 100644
--- a/target/m68k/helper.h
+++ b/target/m68k/helper.h
@@ -85,6 +85,7 @@ DEF_HELPER_3(facos, void, env, fp, fp)
DEF_HELPER_3(fatanh, void, env, fp, fp)
DEF_HELPER_3(ftanh, void, env, fp, fp)
DEF_HELPER_3(fsinh, void, env, fp, fp)
+DEF_HELPER_3(fcosh, void, env, fp, fp)
DEF_HELPER_3(mac_move, void, env, i32, i32)
DEF_HELPER_3(macmulf, i64, env, i32, i32)
diff --git a/target/m68k/softfloat.c b/target/m68k/softfloat.c
index 1528bfd147..dffb371c71 100644
--- a/target/m68k/softfloat.c
+++ b/target/m68k/softfloat.c
@@ -2822,3 +2822,84 @@ floatx80 floatx80_sinh(floatx80 a, float_status *status)
return a;
}
}
+
+/*----------------------------------------------------------------------------
+ | Hyperbolic cosine
+ *----------------------------------------------------------------------------*/
+
+floatx80 floatx80_cosh(floatx80 a, float_status *status)
+{
+ int32_t aExp;
+ uint64_t aSig;
+
+ int8_t user_rnd_mode, user_rnd_prec;
+
+ int32_t compact;
+ floatx80 fp0, fp1;
+
+ aSig = extractFloatx80Frac(a);
+ aExp = extractFloatx80Exp(a);
+
+ if (aExp == 0x7FFF) {
+ if ((uint64_t) (aSig << 1)) {
+ return propagateFloatx80NaNOneArg(a, status);
+ }
+ return packFloatx80(0, floatx80_infinity.high,
+ floatx80_infinity.low);
+ }
+
+ if (aExp == 0 && aSig == 0) {
+ return packFloatx80(0, one_exp, one_sig);
+ }
+
+ user_rnd_mode = status->float_rounding_mode;
+ user_rnd_prec = status->floatx80_rounding_precision;
+ status->float_rounding_mode = float_round_nearest_even;
+ status->floatx80_rounding_precision = 80;
+
+ compact = floatx80_make_compact(aExp, aSig);
+
+ if (compact > 0x400CB167) {
+ if (compact > 0x400CB2B3) {
+ status->float_rounding_mode = user_rnd_mode;
+ status->floatx80_rounding_precision = user_rnd_prec;
+ return roundAndPackFloatx80(status->floatx80_rounding_precision, 0,
+ 0x8000, one_sig, 0, status);
+ } else {
+ fp0 = packFloatx80(0, aExp, aSig);
+ fp0 = floatx80_sub(fp0, float64_to_floatx80(
+ make_float64(0x40C62D38D3D64634), status),
+ status);
+ fp0 = floatx80_sub(fp0, float64_to_floatx80(
+ make_float64(0x3D6F90AEB1E75CC7), status),
+ status);
+ fp0 = floatx80_etox(fp0, status);
+ fp1 = packFloatx80(0, 0x7FFB, one_sig);
+
+ status->float_rounding_mode = user_rnd_mode;
+ status->floatx80_rounding_precision = user_rnd_prec;
+
+ a = floatx80_mul(fp0, fp1, status);
+
+ float_raise(float_flag_inexact, status);
+
+ return a;
+ }
+ }
+
+ fp0 = packFloatx80(0, aExp, aSig); /* |X| */
+ fp0 = floatx80_etox(fp0, status); /* EXP(|X|) */
+ fp0 = floatx80_mul(fp0, float32_to_floatx80(make_float32(0x3F000000),
+ status), status); /* (1/2)*EXP(|X|) */
+ fp1 = float32_to_floatx80(make_float32(0x3E800000), status); /* 1/4 */
+ fp1 = floatx80_div(fp1, fp0, status); /* 1/(2*EXP(|X|)) */
+
+ status->float_rounding_mode = user_rnd_mode;
+ status->floatx80_rounding_precision = user_rnd_prec;
+
+ a = floatx80_add(fp0, fp1, status);
+
+ float_raise(float_flag_inexact, status);
+
+ return a;
+}
diff --git a/target/m68k/softfloat.h b/target/m68k/softfloat.h
index f033abf9ea..602661d5a8 100644
--- a/target/m68k/softfloat.h
+++ b/target/m68k/softfloat.h
@@ -44,4 +44,5 @@ floatx80 floatx80_atanh(floatx80 a, float_status *status);
floatx80 floatx80_etoxm1(floatx80 a, float_status *status);
floatx80 floatx80_tanh(floatx80 a, float_status *status);
floatx80 floatx80_sinh(floatx80 a, float_status *status);
+floatx80 floatx80_cosh(floatx80 a, float_status *status);
#endif
diff --git a/target/m68k/translate.c b/target/m68k/translate.c
index 7d83aaf91d..cef6f663ad 100644
--- a/target/m68k/translate.c
+++ b/target/m68k/translate.c
@@ -5105,6 +5105,9 @@ DISAS_INSN(fpu)
case 0x5c: /* fdabs */
gen_helper_fdabs(cpu_env, cpu_dest, cpu_src);
break;
+ case 0x19: /* fcosh */
+ gen_helper_fcosh(cpu_env, cpu_dest, cpu_src);
+ break;
case 0x1a: /* fneg */
gen_helper_fneg(cpu_env, cpu_dest, cpu_src);
break;
--
2.14.3
^ permalink raw reply related [flat|nested] 15+ messages in thread
* Re: [Qemu-devel] [PULL 00/11] M68k for 2.12 patches
2018-03-13 15:59 [Qemu-devel] [PULL 00/11] M68k for 2.12 patches Laurent Vivier
` (10 preceding siblings ...)
2018-03-13 15:59 ` [Qemu-devel] [PULL 11/11] target/m68k: implement fcosh Laurent Vivier
@ 2018-03-15 13:01 ` Peter Maydell
11 siblings, 0 replies; 15+ messages in thread
From: Peter Maydell @ 2018-03-15 13:01 UTC (permalink / raw)
To: Laurent Vivier; +Cc: QEMU Developers
On 13 March 2018 at 15:59, Laurent Vivier <laurent@vivier.eu> wrote:
> The following changes since commit 59667bb167f773965ce6547352f312eff0d4d523:
>
> Merge remote-tracking branch 'remotes/ehabkost/tags/x86-next-pull-request' into staging (2018-03-13 14:02:47 +0000)
>
> are available in the Git repository at:
>
> git://github.com/vivier/qemu-m68k.git tags/m68k-for-2.12-pull-request
>
> for you to fetch changes up to 02f9124ebe26c36f0f7ed58085bd963e4372b2cd:
>
> target/m68k: implement fcosh (2018-03-13 16:35:05 +0100)
>
> ----------------------------------------------------------------
>
> ----------------------------------------------------------------
>
> Laurent Vivier (11):
> target/m68k: implement ftan
> target/m68k: implement fsin
> target/m68k: implement fcos
> target/m68k: implement fsincos
> target/m68k: implement fatan
> target/m68k: implement fasin
> target/m68k: implement facos
> target/m68k: implement fatanh
> target/m68k: implement ftanh
> target/m68k: implement fsinh
> target/m68k: implement fcosh
>
> target/m68k/fpu_helper.c | 61 ++
> target/m68k/helper.h | 11 +
> target/m68k/softfloat.c | 1637 +++++++++++++++++++++++++++++++++++
> target/m68k/softfloat.h | 11 +
> target/m68k/softfloat_fpsp_tables.h | 267 ++++++
> target/m68k/translate.c | 38 +
> 6 files changed, 2025 insertions(+)
Applied, thanks.
-- PMM
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [Qemu-devel] [PULL 02/11] target/m68k: implement fsin
2018-03-13 15:59 ` [Qemu-devel] [PULL 02/11] target/m68k: implement fsin Laurent Vivier
@ 2018-04-27 13:47 ` Peter Maydell
2018-04-27 14:11 ` Laurent Vivier
0 siblings, 1 reply; 15+ messages in thread
From: Peter Maydell @ 2018-04-27 13:47 UTC (permalink / raw)
To: Laurent Vivier; +Cc: QEMU Developers
On 13 March 2018 at 15:59, Laurent Vivier <laurent@vivier.eu> wrote:
> Using a local m68k floatx80_sin()
> [copied from previous:
> Written by Andreas Grabher for Previous, NeXT Computer Emulator.]
>
> Signed-off-by: Laurent Vivier <laurent@vivier.eu>
> Message-Id: <20180312202728.23790-3-laurent@vivier.eu>
> ---
> target/m68k/fpu_helper.c | 5 +
> target/m68k/helper.h | 1 +
> target/m68k/softfloat.c | 247 +++++++++++++++++++++++++++++++++++++++++++++++
> target/m68k/softfloat.h | 1 +
> target/m68k/translate.c | 3 +
> 5 files changed, 257 insertions(+)
>
> diff --git a/target/m68k/fpu_helper.c b/target/m68k/fpu_helper.c
> index c41115ea05..a6cfb4db1a 100644
> --- a/target/m68k/fpu_helper.c
> +++ b/target/m68k/fpu_helper.c
> @@ -597,3 +597,8 @@ void HELPER(ftan)(CPUM68KState *env, FPReg *res, FPReg *val)
> {
> res->d = floatx80_tan(val->d, &env->fp_status);
> }
> +
> +void HELPER(fsin)(CPUM68KState *env, FPReg *res, FPReg *val)
> +{
> + res->d = floatx80_sin(val->d, &env->fp_status);
> +}
> diff --git a/target/m68k/helper.h b/target/m68k/helper.h
> index af9480fe49..6d8bfaab64 100644
> --- a/target/m68k/helper.h
> +++ b/target/m68k/helper.h
> @@ -76,6 +76,7 @@ DEF_HELPER_3(fetox, void, env, fp, fp)
> DEF_HELPER_3(ftwotox, void, env, fp, fp)
> DEF_HELPER_3(ftentox, void, env, fp, fp)
> DEF_HELPER_3(ftan, void, env, fp, fp)
> +DEF_HELPER_3(fsin, void, env, fp, fp)
>
> DEF_HELPER_3(mac_move, void, env, i32, i32)
> DEF_HELPER_3(macmulf, i64, env, i32, i32)
> diff --git a/target/m68k/softfloat.c b/target/m68k/softfloat.c
> index 488dbc522b..6fb9665336 100644
> --- a/target/m68k/softfloat.c
> +++ b/target/m68k/softfloat.c
> @@ -1476,3 +1476,250 @@ floatx80 floatx80_tan(floatx80 a, float_status *status)
> }
> }
> }
> +
> +/*----------------------------------------------------------------------------
> + | Sine
> + *----------------------------------------------------------------------------*/
> +
> +floatx80 floatx80_sin(floatx80 a, float_status *status)
> +{
Hi; Coverity (CID1390617) points out that there is dead code in this function:
> + flag aSign, xSign;
> + int32_t aExp, xExp;
> + uint64_t aSig, xSig;
> +
> + int8_t user_rnd_mode, user_rnd_prec;
> +
> + int32_t compact, l, n, j;
> + floatx80 fp0, fp1, fp2, fp3, fp4, fp5, x, invtwopi, twopi1, twopi2;
> + float32 posneg1, twoto63;
> + flag adjn, endflag;
> +
> + aSig = extractFloatx80Frac(a);
> + aExp = extractFloatx80Exp(a);
> + aSign = extractFloatx80Sign(a);
> +
> + if (aExp == 0x7FFF) {
> + if ((uint64_t) (aSig << 1)) {
> + return propagateFloatx80NaNOneArg(a, status);
> + }
> + float_raise(float_flag_invalid, status);
> + return floatx80_default_nan(status);
> + }
> +
> + if (aExp == 0 && aSig == 0) {
> + return packFloatx80(aSign, 0, 0);
> + }
> +
> + adjn = 0;
Here we set adjn == 0...
> +
> + user_rnd_mode = status->float_rounding_mode;
> + user_rnd_prec = status->floatx80_rounding_precision;
> + status->float_rounding_mode = float_round_nearest_even;
> + status->floatx80_rounding_precision = 80;
> +
> + compact = floatx80_make_compact(aExp, aSig);
> +
> + fp0 = a;
> +
> + if (compact < 0x3FD78000 || compact > 0x4004BC7E) {
> + /* 2^(-40) > |X| > 15 PI */
> + if (compact > 0x3FFF8000) { /* |X| >= 15 PI */
> + /* REDUCEX */
> + fp1 = packFloatx80(0, 0, 0);
> + if (compact == 0x7FFEFFFF) {
> + twopi1 = packFloatx80(aSign ^ 1, 0x7FFE,
> + LIT64(0xC90FDAA200000000));
> + twopi2 = packFloatx80(aSign ^ 1, 0x7FDC,
> + LIT64(0x85A308D300000000));
> + fp0 = floatx80_add(fp0, twopi1, status);
> + fp1 = fp0;
> + fp0 = floatx80_add(fp0, twopi2, status);
> + fp1 = floatx80_sub(fp1, fp0, status);
> + fp1 = floatx80_add(fp1, twopi2, status);
> + }
> + loop:
> + xSign = extractFloatx80Sign(fp0);
> + xExp = extractFloatx80Exp(fp0);
> + xExp -= 0x3FFF;
> + if (xExp <= 28) {
> + l = 0;
> + endflag = 1;
> + } else {
> + l = xExp - 27;
> + endflag = 0;
> + }
> + invtwopi = packFloatx80(0, 0x3FFE - l,
> + LIT64(0xA2F9836E4E44152A)); /* INVTWOPI */
> + twopi1 = packFloatx80(0, 0x3FFF + l, LIT64(0xC90FDAA200000000));
> + twopi2 = packFloatx80(0, 0x3FDD + l, LIT64(0x85A308D300000000));
> +
> + /* SIGN(INARG)*2^63 IN SGL */
> + twoto63 = packFloat32(xSign, 0xBE, 0);
> +
> + fp2 = floatx80_mul(fp0, invtwopi, status);
> + fp2 = floatx80_add(fp2, float32_to_floatx80(twoto63, status),
> + status); /* THE FRACT PART OF FP2 IS ROUNDED */
> + fp2 = floatx80_sub(fp2, float32_to_floatx80(twoto63, status),
> + status); /* FP2 is N */
> + fp4 = floatx80_mul(twopi1, fp2, status); /* W = N*P1 */
> + fp5 = floatx80_mul(twopi2, fp2, status); /* w = N*P2 */
> + fp3 = floatx80_add(fp4, fp5, status); /* FP3 is P */
> + fp4 = floatx80_sub(fp4, fp3, status); /* W-P */
> + fp0 = floatx80_sub(fp0, fp3, status); /* FP0 is A := R - P */
> + fp4 = floatx80_add(fp4, fp5, status); /* FP4 is p = (W-P)+w */
> + fp3 = fp0; /* FP3 is A */
> + fp1 = floatx80_sub(fp1, fp4, status); /* FP1 is a := r - p */
> + fp0 = floatx80_add(fp0, fp1, status); /* FP0 is R := A+a */
> +
> + if (endflag > 0) {
> + n = floatx80_to_int32(fp2, status);
> + goto sincont;
> + }
> + fp3 = floatx80_sub(fp3, fp0, status); /* A-R */
> + fp1 = floatx80_add(fp1, fp3, status); /* FP1 is r := (A-R)+a */
> + goto loop;
> + } else {
> + /* SINSM */
> + fp0 = float32_to_floatx80(make_float32(0x3F800000),
> + status); /* 1 */
> +
> + status->float_rounding_mode = user_rnd_mode;
> + status->floatx80_rounding_precision = user_rnd_prec;
> +
> + if (adjn) {
...and we never change it before here, so this branch of this 'if'
is dead code.
> + /* COSTINY */
> + a = floatx80_sub(fp0, float32_to_floatx80(
> + make_float32(0x00800000), status), status);
> + } else {
> + /* SINTINY */
> + a = floatx80_move(a, status);
> + }
> + float_raise(float_flag_inexact, status);
> +
> + return a;
> + }
Similarly in floatx80_cos(), we set adjn = 1 at the top of
the function, and then later test it.
Should these two functions be sharing code? They do look
rather similar...
thanks
-- PMM
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [Qemu-devel] [PULL 02/11] target/m68k: implement fsin
2018-04-27 13:47 ` Peter Maydell
@ 2018-04-27 14:11 ` Laurent Vivier
0 siblings, 0 replies; 15+ messages in thread
From: Laurent Vivier @ 2018-04-27 14:11 UTC (permalink / raw)
To: Peter Maydell; +Cc: QEMU Developers
Le 27/04/2018 à 15:47, Peter Maydell a écrit :
> On 13 March 2018 at 15:59, Laurent Vivier <laurent@vivier.eu> wrote:
>> Using a local m68k floatx80_sin()
>> [copied from previous:
>> Written by Andreas Grabher for Previous, NeXT Computer Emulator.]
>>
>> Signed-off-by: Laurent Vivier <laurent@vivier.eu>
>> Message-Id: <20180312202728.23790-3-laurent@vivier.eu>
>> ---
>> target/m68k/fpu_helper.c | 5 +
>> target/m68k/helper.h | 1 +
>> target/m68k/softfloat.c | 247 +++++++++++++++++++++++++++++++++++++++++++++++
>> target/m68k/softfloat.h | 1 +
>> target/m68k/translate.c | 3 +
>> 5 files changed, 257 insertions(+)
>>
>> diff --git a/target/m68k/fpu_helper.c b/target/m68k/fpu_helper.c
>> index c41115ea05..a6cfb4db1a 100644
>> --- a/target/m68k/fpu_helper.c
>> +++ b/target/m68k/fpu_helper.c
>> @@ -597,3 +597,8 @@ void HELPER(ftan)(CPUM68KState *env, FPReg *res, FPReg *val)
>> {
>> res->d = floatx80_tan(val->d, &env->fp_status);
>> }
>> +
>> +void HELPER(fsin)(CPUM68KState *env, FPReg *res, FPReg *val)
>> +{
>> + res->d = floatx80_sin(val->d, &env->fp_status);
>> +}
>> diff --git a/target/m68k/helper.h b/target/m68k/helper.h
>> index af9480fe49..6d8bfaab64 100644
>> --- a/target/m68k/helper.h
>> +++ b/target/m68k/helper.h
>> @@ -76,6 +76,7 @@ DEF_HELPER_3(fetox, void, env, fp, fp)
>> DEF_HELPER_3(ftwotox, void, env, fp, fp)
>> DEF_HELPER_3(ftentox, void, env, fp, fp)
>> DEF_HELPER_3(ftan, void, env, fp, fp)
>> +DEF_HELPER_3(fsin, void, env, fp, fp)
>>
>> DEF_HELPER_3(mac_move, void, env, i32, i32)
>> DEF_HELPER_3(macmulf, i64, env, i32, i32)
>> diff --git a/target/m68k/softfloat.c b/target/m68k/softfloat.c
>> index 488dbc522b..6fb9665336 100644
>> --- a/target/m68k/softfloat.c
>> +++ b/target/m68k/softfloat.c
>> @@ -1476,3 +1476,250 @@ floatx80 floatx80_tan(floatx80 a, float_status *status)
>> }
>> }
>> }
>> +
>> +/*----------------------------------------------------------------------------
>> + | Sine
>> + *----------------------------------------------------------------------------*/
>> +
>> +floatx80 floatx80_sin(floatx80 a, float_status *status)
>> +{
>
> Hi; Coverity (CID1390617) points out that there is dead code in this function:
>
>> + flag aSign, xSign;
>> + int32_t aExp, xExp;
>> + uint64_t aSig, xSig;
>> +
>> + int8_t user_rnd_mode, user_rnd_prec;
>> +
>> + int32_t compact, l, n, j;
>> + floatx80 fp0, fp1, fp2, fp3, fp4, fp5, x, invtwopi, twopi1, twopi2;
>> + float32 posneg1, twoto63;
>> + flag adjn, endflag;
>> +
>> + aSig = extractFloatx80Frac(a);
>> + aExp = extractFloatx80Exp(a);
>> + aSign = extractFloatx80Sign(a);
>> +
>> + if (aExp == 0x7FFF) {
>> + if ((uint64_t) (aSig << 1)) {
>> + return propagateFloatx80NaNOneArg(a, status);
>> + }
>> + float_raise(float_flag_invalid, status);
>> + return floatx80_default_nan(status);
>> + }
>> +
>> + if (aExp == 0 && aSig == 0) {
>> + return packFloatx80(aSign, 0, 0);
>> + }
>> +
>> + adjn = 0;
>
> Here we set adjn == 0...
>> +
>> + user_rnd_mode = status->float_rounding_mode;
>> + user_rnd_prec = status->floatx80_rounding_precision;
>> + status->float_rounding_mode = float_round_nearest_even;
>> + status->floatx80_rounding_precision = 80;
>> +
>> + compact = floatx80_make_compact(aExp, aSig);
>> +
>> + fp0 = a;
>> +
>> + if (compact < 0x3FD78000 || compact > 0x4004BC7E) {
>> + /* 2^(-40) > |X| > 15 PI */
>> + if (compact > 0x3FFF8000) { /* |X| >= 15 PI */
>> + /* REDUCEX */
>> + fp1 = packFloatx80(0, 0, 0);
>> + if (compact == 0x7FFEFFFF) {
>> + twopi1 = packFloatx80(aSign ^ 1, 0x7FFE,
>> + LIT64(0xC90FDAA200000000));
>> + twopi2 = packFloatx80(aSign ^ 1, 0x7FDC,
>> + LIT64(0x85A308D300000000));
>> + fp0 = floatx80_add(fp0, twopi1, status);
>> + fp1 = fp0;
>> + fp0 = floatx80_add(fp0, twopi2, status);
>> + fp1 = floatx80_sub(fp1, fp0, status);
>> + fp1 = floatx80_add(fp1, twopi2, status);
>> + }
>> + loop:
>> + xSign = extractFloatx80Sign(fp0);
>> + xExp = extractFloatx80Exp(fp0);
>> + xExp -= 0x3FFF;
>> + if (xExp <= 28) {
>> + l = 0;
>> + endflag = 1;
>> + } else {
>> + l = xExp - 27;
>> + endflag = 0;
>> + }
>> + invtwopi = packFloatx80(0, 0x3FFE - l,
>> + LIT64(0xA2F9836E4E44152A)); /* INVTWOPI */
>> + twopi1 = packFloatx80(0, 0x3FFF + l, LIT64(0xC90FDAA200000000));
>> + twopi2 = packFloatx80(0, 0x3FDD + l, LIT64(0x85A308D300000000));
>> +
>> + /* SIGN(INARG)*2^63 IN SGL */
>> + twoto63 = packFloat32(xSign, 0xBE, 0);
>> +
>> + fp2 = floatx80_mul(fp0, invtwopi, status);
>> + fp2 = floatx80_add(fp2, float32_to_floatx80(twoto63, status),
>> + status); /* THE FRACT PART OF FP2 IS ROUNDED */
>> + fp2 = floatx80_sub(fp2, float32_to_floatx80(twoto63, status),
>> + status); /* FP2 is N */
>> + fp4 = floatx80_mul(twopi1, fp2, status); /* W = N*P1 */
>> + fp5 = floatx80_mul(twopi2, fp2, status); /* w = N*P2 */
>> + fp3 = floatx80_add(fp4, fp5, status); /* FP3 is P */
>> + fp4 = floatx80_sub(fp4, fp3, status); /* W-P */
>> + fp0 = floatx80_sub(fp0, fp3, status); /* FP0 is A := R - P */
>> + fp4 = floatx80_add(fp4, fp5, status); /* FP4 is p = (W-P)+w */
>> + fp3 = fp0; /* FP3 is A */
>> + fp1 = floatx80_sub(fp1, fp4, status); /* FP1 is a := r - p */
>> + fp0 = floatx80_add(fp0, fp1, status); /* FP0 is R := A+a */
>> +
>> + if (endflag > 0) {
>> + n = floatx80_to_int32(fp2, status);
>> + goto sincont;
>> + }
>> + fp3 = floatx80_sub(fp3, fp0, status); /* A-R */
>> + fp1 = floatx80_add(fp1, fp3, status); /* FP1 is r := (A-R)+a */
>> + goto loop;
>> + } else {
>> + /* SINSM */
>> + fp0 = float32_to_floatx80(make_float32(0x3F800000),
>> + status); /* 1 */
>> +
>> + status->float_rounding_mode = user_rnd_mode;
>> + status->floatx80_rounding_precision = user_rnd_prec;
>> +
>> + if (adjn) {
>
> ...and we never change it before here, so this branch of this 'if'
> is dead code.
>
>> + /* COSTINY */
>> + a = floatx80_sub(fp0, float32_to_floatx80(
>> + make_float32(0x00800000), status), status);
>> + } else {
>> + /* SINTINY */
>> + a = floatx80_move(a, status);
>> + }
>> + float_raise(float_flag_inexact, status);
>> +
>> + return a;
>> + }
>
> Similarly in floatx80_cos(), we set adjn = 1 at the top of
> the function, and then later test it.
>
> Should these two functions be sharing code? They do look
> rather similar...
yes, I'm aware of these problems, but I let the code as-is to only port
functions from "Previous" to QEMU. In fact, the original assembly code
uses a sincos() function to compute both of them and then sin() and
cos() calls it.
All these function need some cleanup now...
Thanks,
Laurent
^ permalink raw reply [flat|nested] 15+ messages in thread
end of thread, other threads:[~2018-04-27 14:11 UTC | newest]
Thread overview: 15+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2018-03-13 15:59 [Qemu-devel] [PULL 00/11] M68k for 2.12 patches Laurent Vivier
2018-03-13 15:59 ` [Qemu-devel] [PULL 01/11] target/m68k: implement ftan Laurent Vivier
2018-03-13 15:59 ` [Qemu-devel] [PULL 02/11] target/m68k: implement fsin Laurent Vivier
2018-04-27 13:47 ` Peter Maydell
2018-04-27 14:11 ` Laurent Vivier
2018-03-13 15:59 ` [Qemu-devel] [PULL 03/11] target/m68k: implement fcos Laurent Vivier
2018-03-13 15:59 ` [Qemu-devel] [PULL 04/11] target/m68k: implement fsincos Laurent Vivier
2018-03-13 15:59 ` [Qemu-devel] [PULL 05/11] target/m68k: implement fatan Laurent Vivier
2018-03-13 15:59 ` [Qemu-devel] [PULL 06/11] target/m68k: implement fasin Laurent Vivier
2018-03-13 15:59 ` [Qemu-devel] [PULL 07/11] target/m68k: implement facos Laurent Vivier
2018-03-13 15:59 ` [Qemu-devel] [PULL 08/11] target/m68k: implement fatanh Laurent Vivier
2018-03-13 15:59 ` [Qemu-devel] [PULL 09/11] target/m68k: implement ftanh Laurent Vivier
2018-03-13 15:59 ` [Qemu-devel] [PULL 10/11] target/m68k: implement fsinh Laurent Vivier
2018-03-13 15:59 ` [Qemu-devel] [PULL 11/11] target/m68k: implement fcosh Laurent Vivier
2018-03-15 13:01 ` [Qemu-devel] [PULL 00/11] M68k for 2.12 patches Peter Maydell
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).