All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] [PULL v2 0/8] M68k for 2.12 patches
@ 2018-03-09 14:57 Laurent Vivier
  2018-03-09 14:57 ` [Qemu-devel] [PULL v2 1/8] target/m68k: define floatx80_move() Laurent Vivier
                   ` (8 more replies)
  0 siblings, 9 replies; 10+ messages in thread
From: Laurent Vivier @ 2018-03-09 14:57 UTC (permalink / raw)
  To: qemu-devel; +Cc: Laurent Vivier

The following changes since commit e1ee9ee139ed7091c2c592d5b784fbb7227bfc0d:

  Merge remote-tracking branch 'remotes/dgibson/tags/ppc-for-2.12-20180306' into staging (2018-03-06 10:21:35 +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 6c25be6e30bda0e470f8f0b6b93d53a6efe469e8:

  target/m68k: implement ftentox (2018-03-09 15:50:38 +0100)

----------------------------------------------------------------
v2 fixes permissions of file target/m68k/softfloat_fpsp_tables.h
----------------------------------------------------------------

Laurent Vivier (8):
  target/m68k: define floatx80_move()
  target/m68k: implement flognp1
  target/m68k: implement flogn
  target/m68k: implement flog10
  target/m68k: implement flog2
  target/m68k: implement fetox
  target/m68k: implement ftwotox
  target/m68k: implement ftentox

 target/m68k/fpu_helper.c            |   35 ++
 target/m68k/helper.h                |    7 +
 target/m68k/softfloat.c             | 1019 +++++++++++++++++++++++++++++++++++
 target/m68k/softfloat.h             |    8 +
 target/m68k/softfloat_fpsp_tables.h |  374 +++++++++++++
 target/m68k/translate.c             |   21 +
 6 files changed, 1464 insertions(+)
 create mode 100644 target/m68k/softfloat_fpsp_tables.h

-- 
2.14.3

^ permalink raw reply	[flat|nested] 10+ messages in thread

* [Qemu-devel] [PULL v2 1/8] target/m68k: define floatx80_move()
  2018-03-09 14:57 [Qemu-devel] [PULL v2 0/8] M68k for 2.12 patches Laurent Vivier
@ 2018-03-09 14:57 ` Laurent Vivier
  2018-03-09 14:57 ` [Qemu-devel] [PULL v2 2/8] target/m68k: implement flognp1 Laurent Vivier
                   ` (7 subsequent siblings)
  8 siblings, 0 replies; 10+ messages in thread
From: Laurent Vivier @ 2018-03-09 14:57 UTC (permalink / raw)
  To: qemu-devel; +Cc: Laurent Vivier

This functions is needed by upcoming m68k softfloat functions.

Source code copied for WinUAE (tag 3500)
(The WinUAE file has been copied from QEMU and has
the QEMU licensing notice)

Signed-off-by: Laurent Vivier <laurent@vivier.eu>
Message-Id: <20180305203910.10391-2-laurent@vivier.eu>
---
 target/m68k/softfloat.c | 27 +++++++++++++++++++++++++++
 target/m68k/softfloat.h |  1 +
 2 files changed, 28 insertions(+)

diff --git a/target/m68k/softfloat.c b/target/m68k/softfloat.c
index 9cb141900c..55eb7a260a 100644
--- a/target/m68k/softfloat.c
+++ b/target/m68k/softfloat.c
@@ -247,3 +247,30 @@ floatx80 floatx80_scale(floatx80 a, floatx80 b, float_status *status)
     return roundAndPackFloatx80(status->floatx80_rounding_precision,
                                 aSign, aExp, aSig, 0, status);
 }
+
+floatx80 floatx80_move(floatx80 a, float_status *status)
+{
+    flag aSign;
+    int32_t aExp;
+    uint64_t aSig;
+
+    aSig = extractFloatx80Frac(a);
+    aExp = extractFloatx80Exp(a);
+    aSign = extractFloatx80Sign(a);
+
+    if (aExp == 0x7FFF) {
+        if ((uint64_t)(aSig << 1)) {
+            return propagateFloatx80NaNOneArg(a, status);
+        }
+        return a;
+    }
+    if (aExp == 0) {
+        if (aSig == 0) {
+            return a;
+        }
+        normalizeRoundAndPackFloatx80(status->floatx80_rounding_precision,
+                                      aSign, aExp, aSig, 0, status);
+    }
+    return roundAndPackFloatx80(status->floatx80_rounding_precision, aSign,
+                                aExp, aSig, 0, status);
+}
diff --git a/target/m68k/softfloat.h b/target/m68k/softfloat.h
index 78fbc0cd0c..18561b870d 100644
--- a/target/m68k/softfloat.h
+++ b/target/m68k/softfloat.h
@@ -26,4 +26,5 @@ floatx80 floatx80_mod(floatx80 a, floatx80 b, float_status *status);
 floatx80 floatx80_getman(floatx80 a, float_status *status);
 floatx80 floatx80_getexp(floatx80 a, float_status *status);
 floatx80 floatx80_scale(floatx80 a, floatx80 b, float_status *status);
+floatx80 floatx80_move(floatx80 a, float_status *status);
 #endif
-- 
2.14.3

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [Qemu-devel] [PULL v2 2/8] target/m68k: implement flognp1
  2018-03-09 14:57 [Qemu-devel] [PULL v2 0/8] M68k for 2.12 patches Laurent Vivier
  2018-03-09 14:57 ` [Qemu-devel] [PULL v2 1/8] target/m68k: define floatx80_move() Laurent Vivier
@ 2018-03-09 14:57 ` Laurent Vivier
  2018-03-09 14:57 ` [Qemu-devel] [PULL v2 3/8] target/m68k: implement flogn Laurent Vivier
                   ` (6 subsequent siblings)
  8 siblings, 0 replies; 10+ messages in thread
From: Laurent Vivier @ 2018-03-09 14:57 UTC (permalink / raw)
  To: qemu-devel; +Cc: Laurent Vivier

Using a local m68k floatx80_lognp1()
[copied from previous:
Written by Andreas Grabher for Previous, NeXT Computer Emulator.]

Signed-off-by: Laurent Vivier <laurent@vivier.eu>
Message-Id: <20180305203910.10391-3-laurent@vivier.eu>
---
 target/m68k/fpu_helper.c            |   5 +
 target/m68k/helper.h                |   1 +
 target/m68k/softfloat.c             | 216 ++++++++++++++++++++++++++++++++++++
 target/m68k/softfloat.h             |   1 +
 target/m68k/softfloat_fpsp_tables.h | 154 +++++++++++++++++++++++++
 target/m68k/translate.c             |   3 +
 6 files changed, 380 insertions(+)
 create mode 100644 target/m68k/softfloat_fpsp_tables.h

diff --git a/target/m68k/fpu_helper.c b/target/m68k/fpu_helper.c
index cdb9b50462..614064612e 100644
--- a/target/m68k/fpu_helper.c
+++ b/target/m68k/fpu_helper.c
@@ -557,3 +557,8 @@ void HELPER(fscale)(CPUM68KState *env, FPReg *res, FPReg *val0, FPReg *val1)
 {
     res->d = floatx80_scale(val1->d, val0->d, &env->fp_status);
 }
+
+void HELPER(flognp1)(CPUM68KState *env, FPReg *res, FPReg *val)
+{
+    res->d = floatx80_lognp1(val->d, &env->fp_status);
+}
diff --git a/target/m68k/helper.h b/target/m68k/helper.h
index c348dced3a..f7e6fc8c40 100644
--- a/target/m68k/helper.h
+++ b/target/m68k/helper.h
@@ -68,6 +68,7 @@ DEF_HELPER_4(frem, void, env, fp, fp, fp)
 DEF_HELPER_3(fgetexp, void, env, fp, fp)
 DEF_HELPER_3(fgetman, void, env, fp, fp)
 DEF_HELPER_4(fscale, void, env, fp, fp, fp)
+DEF_HELPER_3(flognp1, 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 55eb7a260a..834db12964 100644
--- a/target/m68k/softfloat.c
+++ b/target/m68k/softfloat.c
@@ -21,6 +21,7 @@
 #include "qemu/osdep.h"
 #include "softfloat.h"
 #include "fpu/softfloat-macros.h"
+#include "softfloat_fpsp_tables.h"
 
 static floatx80 propagateFloatx80NaNOneArg(floatx80 a, float_status *status)
 {
@@ -274,3 +275,218 @@ floatx80 floatx80_move(floatx80 a, float_status *status)
     return roundAndPackFloatx80(status->floatx80_rounding_precision, aSign,
                                 aExp, aSig, 0, status);
 }
+
+/*----------------------------------------------------------------------------
+| Algorithms for transcendental functions supported by MC68881 and MC68882
+| mathematical coprocessors. The functions are derived from FPSP library.
+*----------------------------------------------------------------------------*/
+
+#define one_exp     0x3FFF
+#define one_sig     LIT64(0x8000000000000000)
+
+/*----------------------------------------------------------------------------
+ | Function for compactifying extended double-precision floating point values.
+ *----------------------------------------------------------------------------*/
+
+static int32_t floatx80_make_compact(int32_t aExp, uint64_t aSig)
+{
+    return (aExp << 16) | (aSig >> 48);
+}
+
+/*----------------------------------------------------------------------------
+ | Log base e of x plus 1
+ *----------------------------------------------------------------------------*/
+
+floatx80 floatx80_lognp1(floatx80 a, float_status *status)
+{
+    flag aSign;
+    int32_t aExp;
+    uint64_t aSig, fSig;
+
+    int8_t user_rnd_mode, user_rnd_prec;
+
+    int32_t compact, j, k;
+    floatx80 fp0, fp1, fp2, fp3, f, logof2, klog2, saveu;
+
+    aSig = extractFloatx80Frac(a);
+    aExp = extractFloatx80Exp(a);
+    aSign = extractFloatx80Sign(a);
+
+    if (aExp == 0x7FFF) {
+        if ((uint64_t) (aSig << 1)) {
+            propagateFloatx80NaNOneArg(a, status);
+        }
+        if (aSign) {
+            float_raise(float_flag_invalid, status);
+            return floatx80_default_nan(status);
+        }
+        return packFloatx80(0, floatx80_infinity.high, floatx80_infinity.low);
+    }
+
+    if (aExp == 0 && aSig == 0) {
+        return packFloatx80(aSign, 0, 0);
+    }
+
+    if (aSign && aExp >= one_exp) {
+        if (aExp == one_exp && aSig == one_sig) {
+            float_raise(float_flag_divbyzero, status);
+            packFloatx80(aSign, floatx80_infinity.high, floatx80_infinity.low);
+        }
+        float_raise(float_flag_invalid, status);
+        return floatx80_default_nan(status);
+    }
+
+    if (aExp < 0x3f99 || (aExp == 0x3f99 && aSig == one_sig)) {
+        /* <= min threshold */
+        float_raise(float_flag_inexact, status);
+        return floatx80_move(a, status);
+    }
+
+    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; /* Z */
+    fp1 = a;
+
+    fp0 = floatx80_add(fp0, float32_to_floatx80(make_float32(0x3F800000),
+                       status), status); /* X = (1+Z) */
+
+    aExp = extractFloatx80Exp(fp0);
+    aSig = extractFloatx80Frac(fp0);
+
+    compact = floatx80_make_compact(aExp, aSig);
+
+    if (compact < 0x3FFE8000 || compact > 0x3FFFC000) {
+        /* |X| < 1/2 or |X| > 3/2 */
+        k = aExp - 0x3FFF;
+        fp1 = int32_to_floatx80(k, status);
+
+        fSig = (aSig & LIT64(0xFE00000000000000)) | LIT64(0x0100000000000000);
+        j = (fSig >> 56) & 0x7E; /* DISPLACEMENT FOR 1/F */
+
+        f = packFloatx80(0, 0x3FFF, fSig); /* F */
+        fp0 = packFloatx80(0, 0x3FFF, aSig); /* Y */
+
+        fp0 = floatx80_sub(fp0, f, status); /* Y-F */
+
+    lp1cont1:
+        /* LP1CONT1 */
+        fp0 = floatx80_mul(fp0, log_tbl[j], status); /* FP0 IS U = (Y-F)/F */
+        logof2 = packFloatx80(0, 0x3FFE, LIT64(0xB17217F7D1CF79AC));
+        klog2 = floatx80_mul(fp1, logof2, status); /* FP1 IS K*LOG2 */
+        fp2 = floatx80_mul(fp0, fp0, status); /* FP2 IS V=U*U */
+
+        fp3 = fp2;
+        fp1 = fp2;
+
+        fp1 = floatx80_mul(fp1, float64_to_floatx80(
+                           make_float64(0x3FC2499AB5E4040B), status),
+                           status); /* V*A6 */
+        fp2 = floatx80_mul(fp2, float64_to_floatx80(
+                           make_float64(0xBFC555B5848CB7DB), status),
+                           status); /* V*A5 */
+        fp1 = floatx80_add(fp1, float64_to_floatx80(
+                           make_float64(0x3FC99999987D8730), status),
+                           status); /* A4+V*A6 */
+        fp2 = floatx80_add(fp2, float64_to_floatx80(
+                           make_float64(0xBFCFFFFFFF6F7E97), status),
+                           status); /* A3+V*A5 */
+        fp1 = floatx80_mul(fp1, fp3, status); /* V*(A4+V*A6) */
+        fp2 = floatx80_mul(fp2, fp3, status); /* V*(A3+V*A5) */
+        fp1 = floatx80_add(fp1, float64_to_floatx80(
+                           make_float64(0x3FD55555555555A4), status),
+                           status); /* A2+V*(A4+V*A6) */
+        fp2 = floatx80_add(fp2, float64_to_floatx80(
+                           make_float64(0xBFE0000000000008), status),
+                           status); /* A1+V*(A3+V*A5) */
+        fp1 = floatx80_mul(fp1, fp3, status); /* V*(A2+V*(A4+V*A6)) */
+        fp2 = floatx80_mul(fp2, fp3, status); /* V*(A1+V*(A3+V*A5)) */
+        fp1 = floatx80_mul(fp1, fp0, status); /* U*V*(A2+V*(A4+V*A6)) */
+        fp0 = floatx80_add(fp0, fp2, status); /* U+V*(A1+V*(A3+V*A5)) */
+
+        fp1 = floatx80_add(fp1, log_tbl[j + 1],
+                           status); /* LOG(F)+U*V*(A2+V*(A4+V*A6)) */
+        fp0 = floatx80_add(fp0, fp1, status); /* FP0 IS LOG(F) + LOG(1+U) */
+
+        status->float_rounding_mode = user_rnd_mode;
+        status->floatx80_rounding_precision = user_rnd_prec;
+
+        a = floatx80_add(fp0, klog2, status);
+
+        float_raise(float_flag_inexact, status);
+
+        return a;
+    } else if (compact < 0x3FFEF07D || compact > 0x3FFF8841) {
+        /* |X| < 1/16 or |X| > -1/16 */
+        /* LP1CARE */
+        fSig = (aSig & LIT64(0xFE00000000000000)) | LIT64(0x0100000000000000);
+        f = packFloatx80(0, 0x3FFF, fSig); /* F */
+        j = (fSig >> 56) & 0x7E; /* DISPLACEMENT FOR 1/F */
+
+        if (compact >= 0x3FFF8000) { /* 1+Z >= 1 */
+            /* KISZERO */
+            fp0 = floatx80_sub(float32_to_floatx80(make_float32(0x3F800000),
+                               status), f, status); /* 1-F */
+            fp0 = floatx80_add(fp0, fp1, status); /* FP0 IS Y-F = (1-F)+Z */
+            fp1 = packFloatx80(0, 0, 0); /* K = 0 */
+        } else {
+            /* KISNEG */
+            fp0 = floatx80_sub(float32_to_floatx80(make_float32(0x40000000),
+                               status), f, status); /* 2-F */
+            fp1 = floatx80_add(fp1, fp1, status); /* 2Z */
+            fp0 = floatx80_add(fp0, fp1, status); /* FP0 IS Y-F = (2-F)+2Z */
+            fp1 = packFloatx80(1, one_exp, one_sig); /* K = -1 */
+        }
+        goto lp1cont1;
+    } else {
+        /* LP1ONE16 */
+        fp1 = floatx80_add(fp1, fp1, status); /* FP1 IS 2Z */
+        fp0 = floatx80_add(fp0, float32_to_floatx80(make_float32(0x3F800000),
+                           status), status); /* FP0 IS 1+X */
+
+        /* LP1CONT2 */
+        fp1 = floatx80_div(fp1, fp0, status); /* U */
+        saveu = fp1;
+        fp0 = floatx80_mul(fp1, fp1, status); /* FP0 IS V = U*U */
+        fp1 = floatx80_mul(fp0, fp0, status); /* FP1 IS W = V*V */
+
+        fp3 = float64_to_floatx80(make_float64(0x3F175496ADD7DAD6),
+                                  status); /* B5 */
+        fp2 = float64_to_floatx80(make_float64(0x3F3C71C2FE80C7E0),
+                                  status); /* B4 */
+        fp3 = floatx80_mul(fp3, fp1, status); /* W*B5 */
+        fp2 = floatx80_mul(fp2, fp1, status); /* W*B4 */
+        fp3 = floatx80_add(fp3, float64_to_floatx80(
+                           make_float64(0x3F624924928BCCFF), status),
+                           status); /* B3+W*B5 */
+        fp2 = floatx80_add(fp2, float64_to_floatx80(
+                           make_float64(0x3F899999999995EC), status),
+                           status); /* B2+W*B4 */
+        fp1 = floatx80_mul(fp1, fp3, status); /* W*(B3+W*B5) */
+        fp2 = floatx80_mul(fp2, fp0, status); /* V*(B2+W*B4) */
+        fp1 = floatx80_add(fp1, float64_to_floatx80(
+                           make_float64(0x3FB5555555555555), status),
+                           status); /* B1+W*(B3+W*B5) */
+
+        fp0 = floatx80_mul(fp0, saveu, status); /* FP0 IS U*V */
+        fp1 = floatx80_add(fp1, fp2,
+                           status); /* B1+W*(B3+W*B5) + V*(B2+W*B4) */
+        fp0 = floatx80_mul(fp0, fp1,
+                           status); /* U*V*([B1+W*(B3+W*B5)] + [V*(B2+W*B4)]) */
+
+        status->float_rounding_mode = user_rnd_mode;
+        status->floatx80_rounding_precision = user_rnd_prec;
+
+        a = floatx80_add(fp0, saveu, status);
+
+        /*if (!floatx80_is_zero(a)) { */
+            float_raise(float_flag_inexact, status);
+        /*} */
+
+        return a;
+    }
+}
diff --git a/target/m68k/softfloat.h b/target/m68k/softfloat.h
index 18561b870d..4d74eaf862 100644
--- a/target/m68k/softfloat.h
+++ b/target/m68k/softfloat.h
@@ -27,4 +27,5 @@ floatx80 floatx80_getman(floatx80 a, float_status *status);
 floatx80 floatx80_getexp(floatx80 a, float_status *status);
 floatx80 floatx80_scale(floatx80 a, floatx80 b, float_status *status);
 floatx80 floatx80_move(floatx80 a, float_status *status);
+floatx80 floatx80_lognp1(floatx80 a, float_status *status);
 #endif
diff --git a/target/m68k/softfloat_fpsp_tables.h b/target/m68k/softfloat_fpsp_tables.h
new file mode 100644
index 0000000000..a87179e11e
--- /dev/null
+++ b/target/m68k/softfloat_fpsp_tables.h
@@ -0,0 +1,154 @@
+/*
+ * Ported from a work by Andreas Grabher for Previous, NeXT Computer Emulator,
+ * derived from NetBSD M68040 FPSP functions,
+ * derived from release 2a of the SoftFloat IEC/IEEE Floating-point Arithmetic
+ * Package. Those parts of the code (and some later contributions) are
+ * provided under that license, as detailed below.
+ * It has subsequently been modified by contributors to the QEMU Project,
+ * so some portions are provided under:
+ *  the SoftFloat-2a license
+ *  the BSD license
+ *  GPL-v2-or-later
+ *
+ * Any future contributions to this file will be taken to be licensed under
+ * the Softfloat-2a license unless specifically indicated otherwise.
+ */
+
+/* Portions of this work are licensed under the terms of the GNU GPL,
+ * version 2 or later. See the COPYING file in the top-level directory.
+ */
+
+#ifndef TARGET_M68K_SOFTFLOAT_FPSP_TABLES_H
+#define TARGET_M68K_SOFTFLOAT_FPSP_TABLES_H
+
+static const floatx80 log_tbl[128] = {
+    make_floatx80_init(0x3FFE, 0xFE03F80FE03F80FE),
+    make_floatx80_init(0x3FF7, 0xFF015358833C47E2),
+    make_floatx80_init(0x3FFE, 0xFA232CF252138AC0),
+    make_floatx80_init(0x3FF9, 0xBDC8D83EAD88D549),
+    make_floatx80_init(0x3FFE, 0xF6603D980F6603DA),
+    make_floatx80_init(0x3FFA, 0x9CF43DCFF5EAFD48),
+    make_floatx80_init(0x3FFE, 0xF2B9D6480F2B9D65),
+    make_floatx80_init(0x3FFA, 0xDA16EB88CB8DF614),
+    make_floatx80_init(0x3FFE, 0xEF2EB71FC4345238),
+    make_floatx80_init(0x3FFB, 0x8B29B7751BD70743),
+    make_floatx80_init(0x3FFE, 0xEBBDB2A5C1619C8C),
+    make_floatx80_init(0x3FFB, 0xA8D839F830C1FB49),
+    make_floatx80_init(0x3FFE, 0xE865AC7B7603A197),
+    make_floatx80_init(0x3FFB, 0xC61A2EB18CD907AD),
+    make_floatx80_init(0x3FFE, 0xE525982AF70C880E),
+    make_floatx80_init(0x3FFB, 0xE2F2A47ADE3A18AF),
+    make_floatx80_init(0x3FFE, 0xE1FC780E1FC780E2),
+    make_floatx80_init(0x3FFB, 0xFF64898EDF55D551),
+    make_floatx80_init(0x3FFE, 0xDEE95C4CA037BA57),
+    make_floatx80_init(0x3FFC, 0x8DB956A97B3D0148),
+    make_floatx80_init(0x3FFE, 0xDBEB61EED19C5958),
+    make_floatx80_init(0x3FFC, 0x9B8FE100F47BA1DE),
+    make_floatx80_init(0x3FFE, 0xD901B2036406C80E),
+    make_floatx80_init(0x3FFC, 0xA9372F1D0DA1BD17),
+    make_floatx80_init(0x3FFE, 0xD62B80D62B80D62C),
+    make_floatx80_init(0x3FFC, 0xB6B07F38CE90E46B),
+    make_floatx80_init(0x3FFE, 0xD3680D3680D3680D),
+    make_floatx80_init(0x3FFC, 0xC3FD032906488481),
+    make_floatx80_init(0x3FFE, 0xD0B69FCBD2580D0B),
+    make_floatx80_init(0x3FFC, 0xD11DE0FF15AB18CA),
+    make_floatx80_init(0x3FFE, 0xCE168A7725080CE1),
+    make_floatx80_init(0x3FFC, 0xDE1433A16C66B150),
+    make_floatx80_init(0x3FFE, 0xCB8727C065C393E0),
+    make_floatx80_init(0x3FFC, 0xEAE10B5A7DDC8ADD),
+    make_floatx80_init(0x3FFE, 0xC907DA4E871146AD),
+    make_floatx80_init(0x3FFC, 0xF7856E5EE2C9B291),
+    make_floatx80_init(0x3FFE, 0xC6980C6980C6980C),
+    make_floatx80_init(0x3FFD, 0x82012CA5A68206D7),
+    make_floatx80_init(0x3FFE, 0xC4372F855D824CA6),
+    make_floatx80_init(0x3FFD, 0x882C5FCD7256A8C5),
+    make_floatx80_init(0x3FFE, 0xC1E4BBD595F6E947),
+    make_floatx80_init(0x3FFD, 0x8E44C60B4CCFD7DE),
+    make_floatx80_init(0x3FFE, 0xBFA02FE80BFA02FF),
+    make_floatx80_init(0x3FFD, 0x944AD09EF4351AF6),
+    make_floatx80_init(0x3FFE, 0xBD69104707661AA3),
+    make_floatx80_init(0x3FFD, 0x9A3EECD4C3EAA6B2),
+    make_floatx80_init(0x3FFE, 0xBB3EE721A54D880C),
+    make_floatx80_init(0x3FFD, 0xA0218434353F1DE8),
+    make_floatx80_init(0x3FFE, 0xB92143FA36F5E02E),
+    make_floatx80_init(0x3FFD, 0xA5F2FCABBBC506DA),
+    make_floatx80_init(0x3FFE, 0xB70FBB5A19BE3659),
+    make_floatx80_init(0x3FFD, 0xABB3B8BA2AD362A5),
+    make_floatx80_init(0x3FFE, 0xB509E68A9B94821F),
+    make_floatx80_init(0x3FFD, 0xB1641795CE3CA97B),
+    make_floatx80_init(0x3FFE, 0xB30F63528917C80B),
+    make_floatx80_init(0x3FFD, 0xB70475515D0F1C61),
+    make_floatx80_init(0x3FFE, 0xB11FD3B80B11FD3C),
+    make_floatx80_init(0x3FFD, 0xBC952AFEEA3D13E1),
+    make_floatx80_init(0x3FFE, 0xAF3ADDC680AF3ADE),
+    make_floatx80_init(0x3FFD, 0xC2168ED0F458BA4A),
+    make_floatx80_init(0x3FFE, 0xAD602B580AD602B6),
+    make_floatx80_init(0x3FFD, 0xC788F439B3163BF1),
+    make_floatx80_init(0x3FFE, 0xAB8F69E28359CD11),
+    make_floatx80_init(0x3FFD, 0xCCECAC08BF04565D),
+    make_floatx80_init(0x3FFE, 0xA9C84A47A07F5638),
+    make_floatx80_init(0x3FFD, 0xD24204872DD85160),
+    make_floatx80_init(0x3FFE, 0xA80A80A80A80A80B),
+    make_floatx80_init(0x3FFD, 0xD78949923BC3588A),
+    make_floatx80_init(0x3FFE, 0xA655C4392D7B73A8),
+    make_floatx80_init(0x3FFD, 0xDCC2C4B49887DACC),
+    make_floatx80_init(0x3FFE, 0xA4A9CF1D96833751),
+    make_floatx80_init(0x3FFD, 0xE1EEBD3E6D6A6B9E),
+    make_floatx80_init(0x3FFE, 0xA3065E3FAE7CD0E0),
+    make_floatx80_init(0x3FFD, 0xE70D785C2F9F5BDC),
+    make_floatx80_init(0x3FFE, 0xA16B312EA8FC377D),
+    make_floatx80_init(0x3FFD, 0xEC1F392C5179F283),
+    make_floatx80_init(0x3FFE, 0x9FD809FD809FD80A),
+    make_floatx80_init(0x3FFD, 0xF12440D3E36130E6),
+    make_floatx80_init(0x3FFE, 0x9E4CAD23DD5F3A20),
+    make_floatx80_init(0x3FFD, 0xF61CCE92346600BB),
+    make_floatx80_init(0x3FFE, 0x9CC8E160C3FB19B9),
+    make_floatx80_init(0x3FFD, 0xFB091FD38145630A),
+    make_floatx80_init(0x3FFE, 0x9B4C6F9EF03A3CAA),
+    make_floatx80_init(0x3FFD, 0xFFE97042BFA4C2AD),
+    make_floatx80_init(0x3FFE, 0x99D722DABDE58F06),
+    make_floatx80_init(0x3FFE, 0x825EFCED49369330),
+    make_floatx80_init(0x3FFE, 0x9868C809868C8098),
+    make_floatx80_init(0x3FFE, 0x84C37A7AB9A905C9),
+    make_floatx80_init(0x3FFE, 0x97012E025C04B809),
+    make_floatx80_init(0x3FFE, 0x87224C2E8E645FB7),
+    make_floatx80_init(0x3FFE, 0x95A02568095A0257),
+    make_floatx80_init(0x3FFE, 0x897B8CAC9F7DE298),
+    make_floatx80_init(0x3FFE, 0x9445809445809446),
+    make_floatx80_init(0x3FFE, 0x8BCF55DEC4CD05FE),
+    make_floatx80_init(0x3FFE, 0x92F113840497889C),
+    make_floatx80_init(0x3FFE, 0x8E1DC0FB89E125E5),
+    make_floatx80_init(0x3FFE, 0x91A2B3C4D5E6F809),
+    make_floatx80_init(0x3FFE, 0x9066E68C955B6C9B),
+    make_floatx80_init(0x3FFE, 0x905A38633E06C43B),
+    make_floatx80_init(0x3FFE, 0x92AADE74C7BE59E0),
+    make_floatx80_init(0x3FFE, 0x8F1779D9FDC3A219),
+    make_floatx80_init(0x3FFE, 0x94E9BFF615845643),
+    make_floatx80_init(0x3FFE, 0x8DDA520237694809),
+    make_floatx80_init(0x3FFE, 0x9723A1B720134203),
+    make_floatx80_init(0x3FFE, 0x8CA29C046514E023),
+    make_floatx80_init(0x3FFE, 0x995899C890EB8990),
+    make_floatx80_init(0x3FFE, 0x8B70344A139BC75A),
+    make_floatx80_init(0x3FFE, 0x9B88BDAA3A3DAE2F),
+    make_floatx80_init(0x3FFE, 0x8A42F8705669DB46),
+    make_floatx80_init(0x3FFE, 0x9DB4224FFFE1157C),
+    make_floatx80_init(0x3FFE, 0x891AC73AE9819B50),
+    make_floatx80_init(0x3FFE, 0x9FDADC268B7A12DA),
+    make_floatx80_init(0x3FFE, 0x87F78087F78087F8),
+    make_floatx80_init(0x3FFE, 0xA1FCFF17CE733BD4),
+    make_floatx80_init(0x3FFE, 0x86D905447A34ACC6),
+    make_floatx80_init(0x3FFE, 0xA41A9E8F5446FB9F),
+    make_floatx80_init(0x3FFE, 0x85BF37612CEE3C9B),
+    make_floatx80_init(0x3FFE, 0xA633CD7E6771CD8B),
+    make_floatx80_init(0x3FFE, 0x84A9F9C8084A9F9D),
+    make_floatx80_init(0x3FFE, 0xA8489E600B435A5E),
+    make_floatx80_init(0x3FFE, 0x839930523FBE3368),
+    make_floatx80_init(0x3FFE, 0xAA59233CCCA4BD49),
+    make_floatx80_init(0x3FFE, 0x828CBFBEB9A020A3),
+    make_floatx80_init(0x3FFE, 0xAC656DAE6BCC4985),
+    make_floatx80_init(0x3FFE, 0x81848DA8FAF0D277),
+    make_floatx80_init(0x3FFE, 0xAE6D8EE360BB2468),
+    make_floatx80_init(0x3FFE, 0x8080808080808081),
+    make_floatx80_init(0x3FFE, 0xB07197A23C46C654)
+};
+#endif
diff --git a/target/m68k/translate.c b/target/m68k/translate.c
index dbb24f8d84..2c3d20154a 100644
--- a/target/m68k/translate.c
+++ b/target/m68k/translate.c
@@ -5054,6 +5054,9 @@ DISAS_INSN(fpu)
     case 0x45: /* fdsqrt */
         gen_helper_fdsqrt(cpu_env, cpu_dest, cpu_src);
         break;
+    case 0x06: /* flognp1 */
+        gen_helper_flognp1(cpu_env, cpu_dest, cpu_src);
+        break;
     case 0x18: /* fabs */
         gen_helper_fabs(cpu_env, cpu_dest, cpu_src);
         break;
-- 
2.14.3

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [Qemu-devel] [PULL v2 3/8] target/m68k: implement flogn
  2018-03-09 14:57 [Qemu-devel] [PULL v2 0/8] M68k for 2.12 patches Laurent Vivier
  2018-03-09 14:57 ` [Qemu-devel] [PULL v2 1/8] target/m68k: define floatx80_move() Laurent Vivier
  2018-03-09 14:57 ` [Qemu-devel] [PULL v2 2/8] target/m68k: implement flognp1 Laurent Vivier
@ 2018-03-09 14:57 ` Laurent Vivier
  2018-03-09 14:57 ` [Qemu-devel] [PULL v2 4/8] target/m68k: implement flog10 Laurent Vivier
                   ` (5 subsequent siblings)
  8 siblings, 0 replies; 10+ messages in thread
From: Laurent Vivier @ 2018-03-09 14:57 UTC (permalink / raw)
  To: qemu-devel; +Cc: Laurent Vivier

Using a local m68k floatx80_logn()
[copied from previous:
Written by Andreas Grabher for Previous, NeXT Computer Emulator.]

Signed-off-by: Laurent Vivier <laurent@vivier.eu>
Message-Id: <20180305203910.10391-4-laurent@vivier.eu>
---
 target/m68k/fpu_helper.c |   5 ++
 target/m68k/helper.h     |   1 +
 target/m68k/softfloat.c  | 168 +++++++++++++++++++++++++++++++++++++++++++++++
 target/m68k/softfloat.h  |   1 +
 target/m68k/translate.c  |   3 +
 5 files changed, 178 insertions(+)

diff --git a/target/m68k/fpu_helper.c b/target/m68k/fpu_helper.c
index 614064612e..cc6d3dfa52 100644
--- a/target/m68k/fpu_helper.c
+++ b/target/m68k/fpu_helper.c
@@ -562,3 +562,8 @@ void HELPER(flognp1)(CPUM68KState *env, FPReg *res, FPReg *val)
 {
     res->d = floatx80_lognp1(val->d, &env->fp_status);
 }
+
+void HELPER(flogn)(CPUM68KState *env, FPReg *res, FPReg *val)
+{
+    res->d = floatx80_logn(val->d, &env->fp_status);
+}
diff --git a/target/m68k/helper.h b/target/m68k/helper.h
index f7e6fc8c40..68e5f4c0a7 100644
--- a/target/m68k/helper.h
+++ b/target/m68k/helper.h
@@ -69,6 +69,7 @@ DEF_HELPER_3(fgetexp, void, env, fp, fp)
 DEF_HELPER_3(fgetman, void, env, fp, fp)
 DEF_HELPER_4(fscale, void, env, fp, fp, fp)
 DEF_HELPER_3(flognp1, void, env, fp, fp)
+DEF_HELPER_3(flogn, 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 834db12964..180a17c39b 100644
--- a/target/m68k/softfloat.c
+++ b/target/m68k/softfloat.c
@@ -490,3 +490,171 @@ floatx80 floatx80_lognp1(floatx80 a, float_status *status)
         return a;
     }
 }
+
+/*----------------------------------------------------------------------------
+ | Log base e
+ *----------------------------------------------------------------------------*/
+
+floatx80 floatx80_logn(floatx80 a, float_status *status)
+{
+    flag aSign;
+    int32_t aExp;
+    uint64_t aSig, fSig;
+
+    int8_t user_rnd_mode, user_rnd_prec;
+
+    int32_t compact, j, k, adjk;
+    floatx80 fp0, fp1, fp2, fp3, f, logof2, klog2, saveu;
+
+    aSig = extractFloatx80Frac(a);
+    aExp = extractFloatx80Exp(a);
+    aSign = extractFloatx80Sign(a);
+
+    if (aExp == 0x7FFF) {
+        if ((uint64_t) (aSig << 1)) {
+            propagateFloatx80NaNOneArg(a, status);
+        }
+        if (aSign == 0) {
+            return packFloatx80(0, floatx80_infinity.high,
+                                floatx80_infinity.low);
+        }
+    }
+
+    adjk = 0;
+
+    if (aExp == 0) {
+        if (aSig == 0) { /* zero */
+            float_raise(float_flag_divbyzero, status);
+            return packFloatx80(1, floatx80_infinity.high,
+                                floatx80_infinity.low);
+        }
+        if ((aSig & one_sig) == 0) { /* denormal */
+            normalizeFloatx80Subnormal(aSig, &aExp, &aSig);
+            adjk = -100;
+            aExp += 100;
+            a = packFloatx80(aSign, aExp, aSig);
+        }
+    }
+
+    if (aSign) {
+        float_raise(float_flag_invalid, status);
+        return floatx80_default_nan(status);
+    }
+
+    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 < 0x3FFEF07D || compact > 0x3FFF8841) {
+        /* |X| < 15/16 or |X| > 17/16 */
+        k = aExp - 0x3FFF;
+        k += adjk;
+        fp1 = int32_to_floatx80(k, status);
+
+        fSig = (aSig & LIT64(0xFE00000000000000)) | LIT64(0x0100000000000000);
+        j = (fSig >> 56) & 0x7E; /* DISPLACEMENT FOR 1/F */
+
+        f = packFloatx80(0, 0x3FFF, fSig); /* F */
+        fp0 = packFloatx80(0, 0x3FFF, aSig); /* Y */
+
+        fp0 = floatx80_sub(fp0, f, status); /* Y-F */
+
+        /* LP1CONT1 */
+        fp0 = floatx80_mul(fp0, log_tbl[j], status); /* FP0 IS U = (Y-F)/F */
+        logof2 = packFloatx80(0, 0x3FFE, LIT64(0xB17217F7D1CF79AC));
+        klog2 = floatx80_mul(fp1, logof2, status); /* FP1 IS K*LOG2 */
+        fp2 = floatx80_mul(fp0, fp0, status); /* FP2 IS V=U*U */
+
+        fp3 = fp2;
+        fp1 = fp2;
+
+        fp1 = floatx80_mul(fp1, float64_to_floatx80(
+                           make_float64(0x3FC2499AB5E4040B), status),
+                           status); /* V*A6 */
+        fp2 = floatx80_mul(fp2, float64_to_floatx80(
+                           make_float64(0xBFC555B5848CB7DB), status),
+                           status); /* V*A5 */
+        fp1 = floatx80_add(fp1, float64_to_floatx80(
+                           make_float64(0x3FC99999987D8730), status),
+                           status); /* A4+V*A6 */
+        fp2 = floatx80_add(fp2, float64_to_floatx80(
+                           make_float64(0xBFCFFFFFFF6F7E97), status),
+                           status); /* A3+V*A5 */
+        fp1 = floatx80_mul(fp1, fp3, status); /* V*(A4+V*A6) */
+        fp2 = floatx80_mul(fp2, fp3, status); /* V*(A3+V*A5) */
+        fp1 = floatx80_add(fp1, float64_to_floatx80(
+                           make_float64(0x3FD55555555555A4), status),
+                           status); /* A2+V*(A4+V*A6) */
+        fp2 = floatx80_add(fp2, float64_to_floatx80(
+                           make_float64(0xBFE0000000000008), status),
+                           status); /* A1+V*(A3+V*A5) */
+        fp1 = floatx80_mul(fp1, fp3, status); /* V*(A2+V*(A4+V*A6)) */
+        fp2 = floatx80_mul(fp2, fp3, status); /* V*(A1+V*(A3+V*A5)) */
+        fp1 = floatx80_mul(fp1, fp0, status); /* U*V*(A2+V*(A4+V*A6)) */
+        fp0 = floatx80_add(fp0, fp2, status); /* U+V*(A1+V*(A3+V*A5)) */
+
+        fp1 = floatx80_add(fp1, log_tbl[j + 1],
+                           status); /* LOG(F)+U*V*(A2+V*(A4+V*A6)) */
+        fp0 = floatx80_add(fp0, fp1, status); /* FP0 IS LOG(F) + LOG(1+U) */
+
+        status->float_rounding_mode = user_rnd_mode;
+        status->floatx80_rounding_precision = user_rnd_prec;
+
+        a = floatx80_add(fp0, klog2, status);
+
+        float_raise(float_flag_inexact, status);
+
+        return a;
+    } else { /* |X-1| >= 1/16 */
+        fp0 = a;
+        fp1 = a;
+        fp1 = floatx80_sub(fp1, float32_to_floatx80(make_float32(0x3F800000),
+                           status), status); /* FP1 IS X-1 */
+        fp0 = floatx80_add(fp0, float32_to_floatx80(make_float32(0x3F800000),
+                           status), status); /* FP0 IS X+1 */
+        fp1 = floatx80_add(fp1, fp1, status); /* FP1 IS 2(X-1) */
+
+        /* LP1CONT2 */
+        fp1 = floatx80_div(fp1, fp0, status); /* U */
+        saveu = fp1;
+        fp0 = floatx80_mul(fp1, fp1, status); /* FP0 IS V = U*U */
+        fp1 = floatx80_mul(fp0, fp0, status); /* FP1 IS W = V*V */
+
+        fp3 = float64_to_floatx80(make_float64(0x3F175496ADD7DAD6),
+                                  status); /* B5 */
+        fp2 = float64_to_floatx80(make_float64(0x3F3C71C2FE80C7E0),
+                                  status); /* B4 */
+        fp3 = floatx80_mul(fp3, fp1, status); /* W*B5 */
+        fp2 = floatx80_mul(fp2, fp1, status); /* W*B4 */
+        fp3 = floatx80_add(fp3, float64_to_floatx80(
+                           make_float64(0x3F624924928BCCFF), status),
+                           status); /* B3+W*B5 */
+        fp2 = floatx80_add(fp2, float64_to_floatx80(
+                           make_float64(0x3F899999999995EC), status),
+                           status); /* B2+W*B4 */
+        fp1 = floatx80_mul(fp1, fp3, status); /* W*(B3+W*B5) */
+        fp2 = floatx80_mul(fp2, fp0, status); /* V*(B2+W*B4) */
+        fp1 = floatx80_add(fp1, float64_to_floatx80(
+                           make_float64(0x3FB5555555555555), status),
+                           status); /* B1+W*(B3+W*B5) */
+
+        fp0 = floatx80_mul(fp0, saveu, status); /* FP0 IS U*V */
+        fp1 = floatx80_add(fp1, fp2, status); /* B1+W*(B3+W*B5) + V*(B2+W*B4) */
+        fp0 = floatx80_mul(fp0, fp1,
+                           status); /* U*V*([B1+W*(B3+W*B5)] + [V*(B2+W*B4)]) */
+
+        status->float_rounding_mode = user_rnd_mode;
+        status->floatx80_rounding_precision = user_rnd_prec;
+
+        a = floatx80_add(fp0, saveu, status);
+
+        /*if (!floatx80_is_zero(a)) { */
+            float_raise(float_flag_inexact, status);
+        /*} */
+
+        return a;
+    }
+}
diff --git a/target/m68k/softfloat.h b/target/m68k/softfloat.h
index 4d74eaf862..161bd6dff7 100644
--- a/target/m68k/softfloat.h
+++ b/target/m68k/softfloat.h
@@ -28,4 +28,5 @@ floatx80 floatx80_getexp(floatx80 a, float_status *status);
 floatx80 floatx80_scale(floatx80 a, floatx80 b, float_status *status);
 floatx80 floatx80_move(floatx80 a, float_status *status);
 floatx80 floatx80_lognp1(floatx80 a, float_status *status);
+floatx80 floatx80_logn(floatx80 a, float_status *status);
 #endif
diff --git a/target/m68k/translate.c b/target/m68k/translate.c
index 2c3d20154a..705b9b0d5b 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 0x14: /* flogn */
+        gen_helper_flogn(cpu_env, cpu_dest, cpu_src);
+        break;
     case 0x18: /* fabs */
         gen_helper_fabs(cpu_env, cpu_dest, cpu_src);
         break;
-- 
2.14.3

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [Qemu-devel] [PULL v2 4/8] target/m68k: implement flog10
  2018-03-09 14:57 [Qemu-devel] [PULL v2 0/8] M68k for 2.12 patches Laurent Vivier
                   ` (2 preceding siblings ...)
  2018-03-09 14:57 ` [Qemu-devel] [PULL v2 3/8] target/m68k: implement flogn Laurent Vivier
@ 2018-03-09 14:57 ` Laurent Vivier
  2018-03-09 14:57 ` [Qemu-devel] [PULL v2 5/8] target/m68k: implement flog2 Laurent Vivier
                   ` (4 subsequent siblings)
  8 siblings, 0 replies; 10+ messages in thread
From: Laurent Vivier @ 2018-03-09 14:57 UTC (permalink / raw)
  To: qemu-devel; +Cc: Laurent Vivier

Using a local m68k floatx80_log10()
[copied from previous:
Written by Andreas Grabher for Previous, NeXT Computer Emulator.]

Signed-off-by: Laurent Vivier <laurent@vivier.eu>
Message-Id: <20180305203910.10391-5-laurent@vivier.eu>
---
 target/m68k/fpu_helper.c |  5 +++++
 target/m68k/helper.h     |  1 +
 target/m68k/softfloat.c  | 57 ++++++++++++++++++++++++++++++++++++++++++++++++
 target/m68k/softfloat.h  |  1 +
 target/m68k/translate.c  |  3 +++
 5 files changed, 67 insertions(+)

diff --git a/target/m68k/fpu_helper.c b/target/m68k/fpu_helper.c
index cc6d3dfa52..2628534136 100644
--- a/target/m68k/fpu_helper.c
+++ b/target/m68k/fpu_helper.c
@@ -567,3 +567,8 @@ void HELPER(flogn)(CPUM68KState *env, FPReg *res, FPReg *val)
 {
     res->d = floatx80_logn(val->d, &env->fp_status);
 }
+
+void HELPER(flog10)(CPUM68KState *env, FPReg *res, FPReg *val)
+{
+    res->d = floatx80_log10(val->d, &env->fp_status);
+}
diff --git a/target/m68k/helper.h b/target/m68k/helper.h
index 68e5f4c0a7..d1f38f260f 100644
--- a/target/m68k/helper.h
+++ b/target/m68k/helper.h
@@ -70,6 +70,7 @@ DEF_HELPER_3(fgetman, void, env, fp, fp)
 DEF_HELPER_4(fscale, void, env, fp, fp, fp)
 DEF_HELPER_3(flognp1, void, env, fp, fp)
 DEF_HELPER_3(flogn, void, env, fp, fp)
+DEF_HELPER_3(flog10, 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 180a17c39b..22fd7f6341 100644
--- a/target/m68k/softfloat.c
+++ b/target/m68k/softfloat.c
@@ -658,3 +658,60 @@ floatx80 floatx80_logn(floatx80 a, float_status *status)
         return a;
     }
 }
+
+/*----------------------------------------------------------------------------
+ | Log base 10
+ *----------------------------------------------------------------------------*/
+
+floatx80 floatx80_log10(floatx80 a, float_status *status)
+{
+    flag aSign;
+    int32_t aExp;
+    uint64_t aSig;
+
+    int8_t user_rnd_mode, user_rnd_prec;
+
+    floatx80 fp0, fp1;
+
+    aSig = extractFloatx80Frac(a);
+    aExp = extractFloatx80Exp(a);
+    aSign = extractFloatx80Sign(a);
+
+    if (aExp == 0x7FFF) {
+        if ((uint64_t) (aSig << 1)) {
+            propagateFloatx80NaNOneArg(a, status);
+        }
+        if (aSign == 0) {
+            return packFloatx80(0, floatx80_infinity.high,
+                                floatx80_infinity.low);
+        }
+    }
+
+    if (aExp == 0 && aSig == 0) {
+        float_raise(float_flag_divbyzero, status);
+        return packFloatx80(1, floatx80_infinity.high,
+                            floatx80_infinity.low);
+    }
+
+    if (aSign) {
+        float_raise(float_flag_invalid, status);
+        return floatx80_default_nan(status);
+    }
+
+    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;
+
+    fp0 = floatx80_logn(a, status);
+    fp1 = packFloatx80(0, 0x3FFD, LIT64(0xDE5BD8A937287195)); /* INV_L10 */
+
+    status->float_rounding_mode = user_rnd_mode;
+    status->floatx80_rounding_precision = user_rnd_prec;
+
+    a = floatx80_mul(fp0, fp1, status); /* LOGN(X)*INV_L10 */
+
+    float_raise(float_flag_inexact, status);
+
+    return a;
+}
diff --git a/target/m68k/softfloat.h b/target/m68k/softfloat.h
index 161bd6dff7..ac29e76189 100644
--- a/target/m68k/softfloat.h
+++ b/target/m68k/softfloat.h
@@ -29,4 +29,5 @@ floatx80 floatx80_scale(floatx80 a, floatx80 b, float_status *status);
 floatx80 floatx80_move(floatx80 a, float_status *status);
 floatx80 floatx80_lognp1(floatx80 a, float_status *status);
 floatx80 floatx80_logn(floatx80 a, float_status *status);
+floatx80 floatx80_log10(floatx80 a, float_status *status);
 #endif
diff --git a/target/m68k/translate.c b/target/m68k/translate.c
index 705b9b0d5b..f1130df314 100644
--- a/target/m68k/translate.c
+++ b/target/m68k/translate.c
@@ -5060,6 +5060,9 @@ DISAS_INSN(fpu)
     case 0x14: /* flogn */
         gen_helper_flogn(cpu_env, cpu_dest, cpu_src);
         break;
+    case 0x15: /* flog10 */
+        gen_helper_flog10(cpu_env, cpu_dest, cpu_src);
+        break;
     case 0x18: /* fabs */
         gen_helper_fabs(cpu_env, cpu_dest, cpu_src);
         break;
-- 
2.14.3

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [Qemu-devel] [PULL v2 5/8] target/m68k: implement flog2
  2018-03-09 14:57 [Qemu-devel] [PULL v2 0/8] M68k for 2.12 patches Laurent Vivier
                   ` (3 preceding siblings ...)
  2018-03-09 14:57 ` [Qemu-devel] [PULL v2 4/8] target/m68k: implement flog10 Laurent Vivier
@ 2018-03-09 14:57 ` Laurent Vivier
  2018-03-09 14:57 ` [Qemu-devel] [PULL v2 6/8] target/m68k: implement fetox Laurent Vivier
                   ` (3 subsequent siblings)
  8 siblings, 0 replies; 10+ messages in thread
From: Laurent Vivier @ 2018-03-09 14:57 UTC (permalink / raw)
  To: qemu-devel; +Cc: Laurent Vivier

Using a local m68k floatx80_log2()
[copied from previous:
Written by Andreas Grabher for Previous, NeXT Computer Emulator.]

Signed-off-by: Laurent Vivier <laurent@vivier.eu>
Message-Id: <20180305203910.10391-6-laurent@vivier.eu>
---
 target/m68k/fpu_helper.c |  5 ++++
 target/m68k/helper.h     |  1 +
 target/m68k/softfloat.c  | 67 ++++++++++++++++++++++++++++++++++++++++++++++++
 target/m68k/softfloat.h  |  1 +
 target/m68k/translate.c  |  3 +++
 5 files changed, 77 insertions(+)

diff --git a/target/m68k/fpu_helper.c b/target/m68k/fpu_helper.c
index 2628534136..97a4501126 100644
--- a/target/m68k/fpu_helper.c
+++ b/target/m68k/fpu_helper.c
@@ -572,3 +572,8 @@ void HELPER(flog10)(CPUM68KState *env, FPReg *res, FPReg *val)
 {
     res->d = floatx80_log10(val->d, &env->fp_status);
 }
+
+void HELPER(flog2)(CPUM68KState *env, FPReg *res, FPReg *val)
+{
+    res->d = floatx80_log2(val->d, &env->fp_status);
+}
diff --git a/target/m68k/helper.h b/target/m68k/helper.h
index d1f38f260f..15f63b353f 100644
--- a/target/m68k/helper.h
+++ b/target/m68k/helper.h
@@ -71,6 +71,7 @@ DEF_HELPER_4(fscale, void, env, fp, fp, fp)
 DEF_HELPER_3(flognp1, void, env, fp, fp)
 DEF_HELPER_3(flogn, void, env, fp, fp)
 DEF_HELPER_3(flog10, void, env, fp, fp)
+DEF_HELPER_3(flog2, 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 22fd7f6341..9fa6d6fd05 100644
--- a/target/m68k/softfloat.c
+++ b/target/m68k/softfloat.c
@@ -715,3 +715,70 @@ floatx80 floatx80_log10(floatx80 a, float_status *status)
 
     return a;
 }
+
+/*----------------------------------------------------------------------------
+ | Log base 2
+ *----------------------------------------------------------------------------*/
+
+floatx80 floatx80_log2(floatx80 a, float_status *status)
+{
+    flag aSign;
+    int32_t aExp;
+    uint64_t aSig;
+
+    int8_t user_rnd_mode, user_rnd_prec;
+
+    floatx80 fp0, fp1;
+
+    aSig = extractFloatx80Frac(a);
+    aExp = extractFloatx80Exp(a);
+    aSign = extractFloatx80Sign(a);
+
+    if (aExp == 0x7FFF) {
+        if ((uint64_t) (aSig << 1)) {
+            propagateFloatx80NaNOneArg(a, status);
+        }
+        if (aSign == 0) {
+            return packFloatx80(0, floatx80_infinity.high,
+                                floatx80_infinity.low);
+        }
+    }
+
+    if (aExp == 0) {
+        if (aSig == 0) {
+            float_raise(float_flag_divbyzero, status);
+            return packFloatx80(1, floatx80_infinity.high,
+                                floatx80_infinity.low);
+        }
+        normalizeFloatx80Subnormal(aSig, &aExp, &aSig);
+    }
+
+    if (aSign) {
+        float_raise(float_flag_invalid, status);
+        return floatx80_default_nan(status);
+    }
+
+    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 (aSig == one_sig) { /* X is 2^k */
+        status->float_rounding_mode = user_rnd_mode;
+        status->floatx80_rounding_precision = user_rnd_prec;
+
+        a = int32_to_floatx80(aExp - 0x3FFF, status);
+    } else {
+        fp0 = floatx80_logn(a, status);
+        fp1 = packFloatx80(0, 0x3FFF, LIT64(0xB8AA3B295C17F0BC)); /* INV_L2 */
+
+        status->float_rounding_mode = user_rnd_mode;
+        status->floatx80_rounding_precision = user_rnd_prec;
+
+        a = floatx80_mul(fp0, fp1, status); /* LOGN(X)*INV_L2 */
+    }
+
+    float_raise(float_flag_inexact, status);
+
+    return a;
+}
diff --git a/target/m68k/softfloat.h b/target/m68k/softfloat.h
index ac29e76189..c0b77cf01b 100644
--- a/target/m68k/softfloat.h
+++ b/target/m68k/softfloat.h
@@ -30,4 +30,5 @@ floatx80 floatx80_move(floatx80 a, float_status *status);
 floatx80 floatx80_lognp1(floatx80 a, float_status *status);
 floatx80 floatx80_logn(floatx80 a, float_status *status);
 floatx80 floatx80_log10(floatx80 a, float_status *status);
+floatx80 floatx80_log2(floatx80 a, float_status *status);
 #endif
diff --git a/target/m68k/translate.c b/target/m68k/translate.c
index f1130df314..189b23d38d 100644
--- a/target/m68k/translate.c
+++ b/target/m68k/translate.c
@@ -5063,6 +5063,9 @@ DISAS_INSN(fpu)
     case 0x15: /* flog10 */
         gen_helper_flog10(cpu_env, cpu_dest, cpu_src);
         break;
+    case 0x16: /* flog2 */
+        gen_helper_flog2(cpu_env, cpu_dest, cpu_src);
+        break;
     case 0x18: /* fabs */
         gen_helper_fabs(cpu_env, cpu_dest, cpu_src);
         break;
-- 
2.14.3

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [Qemu-devel] [PULL v2 6/8] target/m68k: implement fetox
  2018-03-09 14:57 [Qemu-devel] [PULL v2 0/8] M68k for 2.12 patches Laurent Vivier
                   ` (4 preceding siblings ...)
  2018-03-09 14:57 ` [Qemu-devel] [PULL v2 5/8] target/m68k: implement flog2 Laurent Vivier
@ 2018-03-09 14:57 ` Laurent Vivier
  2018-03-09 14:57 ` [Qemu-devel] [PULL v2 7/8] target/m68k: implement ftwotox Laurent Vivier
                   ` (2 subsequent siblings)
  8 siblings, 0 replies; 10+ messages in thread
From: Laurent Vivier @ 2018-03-09 14:57 UTC (permalink / raw)
  To: qemu-devel; +Cc: Laurent Vivier

Using a local m68k floatx80_etox()
[copied from previous:
Written by Andreas Grabher for Previous, NeXT Computer Emulator.]

Signed-off-by: Laurent Vivier <laurent@vivier.eu>
Message-Id: <20180305203910.10391-7-laurent@vivier.eu>
---
 target/m68k/fpu_helper.c            |   5 +
 target/m68k/helper.h                |   1 +
 target/m68k/softfloat.c             | 183 ++++++++++++++++++++++++++++++++++++
 target/m68k/softfloat.h             |   1 +
 target/m68k/softfloat_fpsp_tables.h | 134 ++++++++++++++++++++++++++
 target/m68k/translate.c             |   3 +
 6 files changed, 327 insertions(+)

diff --git a/target/m68k/fpu_helper.c b/target/m68k/fpu_helper.c
index 97a4501126..154666cbb5 100644
--- a/target/m68k/fpu_helper.c
+++ b/target/m68k/fpu_helper.c
@@ -577,3 +577,8 @@ void HELPER(flog2)(CPUM68KState *env, FPReg *res, FPReg *val)
 {
     res->d = floatx80_log2(val->d, &env->fp_status);
 }
+
+void HELPER(fetox)(CPUM68KState *env, FPReg *res, FPReg *val)
+{
+    res->d = floatx80_etox(val->d, &env->fp_status);
+}
diff --git a/target/m68k/helper.h b/target/m68k/helper.h
index 15f63b353f..70aeb2da7c 100644
--- a/target/m68k/helper.h
+++ b/target/m68k/helper.h
@@ -72,6 +72,7 @@ DEF_HELPER_3(flognp1, void, env, fp, fp)
 DEF_HELPER_3(flogn, void, env, fp, fp)
 DEF_HELPER_3(flog10, void, env, fp, fp)
 DEF_HELPER_3(flog2, void, env, fp, fp)
+DEF_HELPER_3(fetox, 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 9fa6d6fd05..e58eb91738 100644
--- a/target/m68k/softfloat.c
+++ b/target/m68k/softfloat.c
@@ -782,3 +782,186 @@ floatx80 floatx80_log2(floatx80 a, float_status *status)
 
     return a;
 }
+
+/*----------------------------------------------------------------------------
+ | e to x
+ *----------------------------------------------------------------------------*/
+
+floatx80 floatx80_etox(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, k, m, m1;
+    floatx80 fp0, fp1, fp2, fp3, l2, scale, adjscale;
+    flag adjflag;
+
+    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(0, 0, 0);
+        }
+        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;
+
+    adjflag = 0;
+
+    if (aExp >= 0x3FBE) { /* |X| >= 2^(-65) */
+        compact = floatx80_make_compact(aExp, aSig);
+
+        if (compact < 0x400CB167) { /* |X| < 16380 log2 */
+            fp0 = a;
+            fp1 = a;
+            fp0 = floatx80_mul(fp0, float32_to_floatx80(
+                               make_float32(0x42B8AA3B), status),
+                               status); /* 64/log2 * X */
+            adjflag = 0;
+            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--;
+            }
+            m += 0x3FFF; /* biased exponent of 2^(M) */
+
+        expcont1:
+            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(0x3AB60B70),
+                                      status); /* A5 */
+            fp2 = floatx80_mul(fp2, fp1, status); /* fp2 is S*A5 */
+            fp3 = floatx80_mul(float32_to_floatx80(make_float32(0x3C088895),
+                               status), fp1,
+                               status); /* fp3 is S*A4 */
+            fp2 = floatx80_add(fp2, float64_to_floatx80(make_float64(
+                               0x3FA5555555554431), status),
+                               status); /* fp2 is A3+S*A5 */
+            fp3 = floatx80_add(fp3, float64_to_floatx80(make_float64(
+                               0x3FC5555555554018), status),
+                               status); /* fp3 is A2+S*A4 */
+            fp2 = floatx80_mul(fp2, fp1, status); /* fp2 is S*(A3+S*A5) */
+            fp3 = floatx80_mul(fp3, fp1, status); /* fp3 is S*(A2+S*A4) */
+            fp2 = floatx80_add(fp2, float32_to_floatx80(
+                               make_float32(0x3F000000), status),
+                               status); /* fp2 is A1+S*(A3+S*A5) */
+            fp3 = floatx80_mul(fp3, fp0, status); /* fp3 IS R*S*(A2+S*A4) */
+            fp2 = floatx80_mul(fp2, fp1,
+                               status); /* fp2 IS S*(A1+S*(A3+S*A5)) */
+            fp0 = floatx80_add(fp0, fp3, status); /* fp0 IS R+R*S*(A2+S*A4) */
+            fp0 = floatx80_add(fp0, fp2, status); /* fp0 IS EXP(R) - 1 */
+
+            fp1 = exp_tbl[j];
+            fp0 = floatx80_mul(fp0, fp1, status); /* 2^(J/64)*(Exp(R)-1) */
+            fp0 = floatx80_add(fp0, float32_to_floatx80(exp_tbl2[j], status),
+                               status); /* accurate 2^(J/64) */
+            fp0 = floatx80_add(fp0, fp1,
+                               status); /* 2^(J/64) + 2^(J/64)*(Exp(R)-1) */
+
+            scale = packFloatx80(0, m, one_sig);
+            if (adjflag) {
+                adjscale = packFloatx80(0, m1, one_sig);
+                fp0 = floatx80_mul(fp0, adjscale, status);
+            }
+
+            status->float_rounding_mode = user_rnd_mode;
+            status->floatx80_rounding_precision = user_rnd_prec;
+
+            a = floatx80_mul(fp0, scale, status);
+
+            float_raise(float_flag_inexact, status);
+
+            return a;
+        } else { /* |X| >= 16380 log2 */
+            if (compact > 0x400CB27C) { /* |X| >= 16480 log2 */
+                status->float_rounding_mode = user_rnd_mode;
+                status->floatx80_rounding_precision = user_rnd_prec;
+                if (aSign) {
+                    a = roundAndPackFloatx80(
+                                           status->floatx80_rounding_precision,
+                                           0, -0x1000, aSig, 0, status);
+                } else {
+                    a = roundAndPackFloatx80(
+                                           status->floatx80_rounding_precision,
+                                           0, 0x8000, aSig, 0, status);
+                }
+                float_raise(float_flag_inexact, status);
+
+                return a;
+            } else {
+                fp0 = a;
+                fp1 = a;
+                fp0 = floatx80_mul(fp0, float32_to_floatx80(
+                                   make_float32(0x42B8AA3B), status),
+                                   status); /* 64/log2 * X */
+                adjflag = 1;
+                n = floatx80_to_int32(fp0, status); /* int(64/log2*X) */
+                fp0 = int32_to_floatx80(n, status);
+
+                j = n & 0x3F; /* J = N mod 64 */
+                /* NOTE: this is really arithmetic right shift by 6 */
+                k = n / 64;
+                if (n < 0 && j) {
+                    /* arithmetic right shift is division and
+                     * round towards minus infinity
+                     */
+                    k--;
+                }
+                /* NOTE: this is really arithmetic right shift by 1 */
+                m1 = k / 2;
+                if (k < 0 && (k & 1)) {
+                    /* arithmetic right shift is division and
+                     * round towards minus infinity
+                     */
+                    m1--;
+                }
+                m = k - m1;
+                m1 += 0x3FFF; /* biased exponent of 2^(M1) */
+                m += 0x3FFF; /* biased exponent of 2^(M) */
+
+                goto expcont1;
+            }
+        }
+    } else { /* |X| < 2^(-65) */
+        status->float_rounding_mode = user_rnd_mode;
+        status->floatx80_rounding_precision = user_rnd_prec;
+
+        a = floatx80_add(a, float32_to_floatx80(make_float32(0x3F800000),
+                         status), status); /* 1 + X */
+
+        float_raise(float_flag_inexact, status);
+
+        return a;
+    }
+}
diff --git a/target/m68k/softfloat.h b/target/m68k/softfloat.h
index c0b77cf01b..250f0d926f 100644
--- a/target/m68k/softfloat.h
+++ b/target/m68k/softfloat.h
@@ -31,4 +31,5 @@ floatx80 floatx80_lognp1(floatx80 a, float_status *status);
 floatx80 floatx80_logn(floatx80 a, float_status *status);
 floatx80 floatx80_log10(floatx80 a, float_status *status);
 floatx80 floatx80_log2(floatx80 a, float_status *status);
+floatx80 floatx80_etox(floatx80 a, float_status *status);
 #endif
diff --git a/target/m68k/softfloat_fpsp_tables.h b/target/m68k/softfloat_fpsp_tables.h
index a87179e11e..b2b63e5ced 100644
--- a/target/m68k/softfloat_fpsp_tables.h
+++ b/target/m68k/softfloat_fpsp_tables.h
@@ -151,4 +151,138 @@ static const floatx80 log_tbl[128] = {
     make_floatx80_init(0x3FFE, 0x8080808080808081),
     make_floatx80_init(0x3FFE, 0xB07197A23C46C654)
 };
+
+static const floatx80 exp_tbl[64] = {
+    make_floatx80_init(0x3FFF, 0x8000000000000000),
+    make_floatx80_init(0x3FFF, 0x8164D1F3BC030774),
+    make_floatx80_init(0x3FFF, 0x82CD8698AC2BA1D8),
+    make_floatx80_init(0x3FFF, 0x843A28C3ACDE4048),
+    make_floatx80_init(0x3FFF, 0x85AAC367CC487B14),
+    make_floatx80_init(0x3FFF, 0x871F61969E8D1010),
+    make_floatx80_init(0x3FFF, 0x88980E8092DA8528),
+    make_floatx80_init(0x3FFF, 0x8A14D575496EFD9C),
+    make_floatx80_init(0x3FFF, 0x8B95C1E3EA8BD6E8),
+    make_floatx80_init(0x3FFF, 0x8D1ADF5B7E5BA9E4),
+    make_floatx80_init(0x3FFF, 0x8EA4398B45CD53C0),
+    make_floatx80_init(0x3FFF, 0x9031DC431466B1DC),
+    make_floatx80_init(0x3FFF, 0x91C3D373AB11C338),
+    make_floatx80_init(0x3FFF, 0x935A2B2F13E6E92C),
+    make_floatx80_init(0x3FFF, 0x94F4EFA8FEF70960),
+    make_floatx80_init(0x3FFF, 0x96942D3720185A00),
+    make_floatx80_init(0x3FFF, 0x9837F0518DB8A970),
+    make_floatx80_init(0x3FFF, 0x99E0459320B7FA64),
+    make_floatx80_init(0x3FFF, 0x9B8D39B9D54E5538),
+    make_floatx80_init(0x3FFF, 0x9D3ED9A72CFFB750),
+    make_floatx80_init(0x3FFF, 0x9EF5326091A111AC),
+    make_floatx80_init(0x3FFF, 0xA0B0510FB9714FC4),
+    make_floatx80_init(0x3FFF, 0xA27043030C496818),
+    make_floatx80_init(0x3FFF, 0xA43515AE09E680A0),
+    make_floatx80_init(0x3FFF, 0xA5FED6A9B15138EC),
+    make_floatx80_init(0x3FFF, 0xA7CD93B4E9653568),
+    make_floatx80_init(0x3FFF, 0xA9A15AB4EA7C0EF8),
+    make_floatx80_init(0x3FFF, 0xAB7A39B5A93ED338),
+    make_floatx80_init(0x3FFF, 0xAD583EEA42A14AC8),
+    make_floatx80_init(0x3FFF, 0xAF3B78AD690A4374),
+    make_floatx80_init(0x3FFF, 0xB123F581D2AC2590),
+    make_floatx80_init(0x3FFF, 0xB311C412A9112488),
+    make_floatx80_init(0x3FFF, 0xB504F333F9DE6484),
+    make_floatx80_init(0x3FFF, 0xB6FD91E328D17790),
+    make_floatx80_init(0x3FFF, 0xB8FBAF4762FB9EE8),
+    make_floatx80_init(0x3FFF, 0xBAFF5AB2133E45FC),
+    make_floatx80_init(0x3FFF, 0xBD08A39F580C36C0),
+    make_floatx80_init(0x3FFF, 0xBF1799B67A731084),
+    make_floatx80_init(0x3FFF, 0xC12C4CCA66709458),
+    make_floatx80_init(0x3FFF, 0xC346CCDA24976408),
+    make_floatx80_init(0x3FFF, 0xC5672A115506DADC),
+    make_floatx80_init(0x3FFF, 0xC78D74C8ABB9B15C),
+    make_floatx80_init(0x3FFF, 0xC9B9BD866E2F27A4),
+    make_floatx80_init(0x3FFF, 0xCBEC14FEF2727C5C),
+    make_floatx80_init(0x3FFF, 0xCE248C151F8480E4),
+    make_floatx80_init(0x3FFF, 0xD06333DAEF2B2594),
+    make_floatx80_init(0x3FFF, 0xD2A81D91F12AE45C),
+    make_floatx80_init(0x3FFF, 0xD4F35AABCFEDFA20),
+    make_floatx80_init(0x3FFF, 0xD744FCCAD69D6AF4),
+    make_floatx80_init(0x3FFF, 0xD99D15C278AFD7B4),
+    make_floatx80_init(0x3FFF, 0xDBFBB797DAF23754),
+    make_floatx80_init(0x3FFF, 0xDE60F4825E0E9124),
+    make_floatx80_init(0x3FFF, 0xE0CCDEEC2A94E110),
+    make_floatx80_init(0x3FFF, 0xE33F8972BE8A5A50),
+    make_floatx80_init(0x3FFF, 0xE5B906E77C8348A8),
+    make_floatx80_init(0x3FFF, 0xE8396A503C4BDC68),
+    make_floatx80_init(0x3FFF, 0xEAC0C6E7DD243930),
+    make_floatx80_init(0x3FFF, 0xED4F301ED9942B84),
+    make_floatx80_init(0x3FFF, 0xEFE4B99BDCDAF5CC),
+    make_floatx80_init(0x3FFF, 0xF281773C59FFB138),
+    make_floatx80_init(0x3FFF, 0xF5257D152486CC2C),
+    make_floatx80_init(0x3FFF, 0xF7D0DF730AD13BB8),
+    make_floatx80_init(0x3FFF, 0xFA83B2DB722A033C),
+    make_floatx80_init(0x3FFF, 0xFD3E0C0CF486C174)
+};
+
+static const float32 exp_tbl2[64] = {
+    const_float32(0x00000000),
+    const_float32(0x9F841A9B),
+    const_float32(0x9FC1D5B9),
+    const_float32(0xA0728369),
+    const_float32(0x1FC5C95C),
+    const_float32(0x1EE85C9F),
+    const_float32(0x9FA20729),
+    const_float32(0xA07BF9AF),
+    const_float32(0xA0020DCF),
+    const_float32(0x205A63DA),
+    const_float32(0x1EB70051),
+    const_float32(0x1F6EB029),
+    const_float32(0xA0781494),
+    const_float32(0x9EB319B0),
+    const_float32(0x2017457D),
+    const_float32(0x1F11D537),
+    const_float32(0x9FB952DD),
+    const_float32(0x1FE43087),
+    const_float32(0x1FA2A818),
+    const_float32(0x1FDE494D),
+    const_float32(0x20504890),
+    const_float32(0xA073691C),
+    const_float32(0x1F9B7A05),
+    const_float32(0xA0797126),
+    const_float32(0xA071A140),
+    const_float32(0x204F62DA),
+    const_float32(0x1F283C4A),
+    const_float32(0x9F9A7FDC),
+    const_float32(0xA05B3FAC),
+    const_float32(0x1FDF2610),
+    const_float32(0x9F705F90),
+    const_float32(0x201F678A),
+    const_float32(0x1F32FB13),
+    const_float32(0x20038B30),
+    const_float32(0x200DC3CC),
+    const_float32(0x9F8B2AE6),
+    const_float32(0xA02BBF70),
+    const_float32(0xA00BF518),
+    const_float32(0xA041DD41),
+    const_float32(0x9FDF137B),
+    const_float32(0x201F1568),
+    const_float32(0x1FC13A2E),
+    const_float32(0xA03F8F03),
+    const_float32(0x1FF4907D),
+    const_float32(0x9E6E53E4),
+    const_float32(0x1FD6D45C),
+    const_float32(0xA076EDB9),
+    const_float32(0x9FA6DE21),
+    const_float32(0x1EE69A2F),
+    const_float32(0x207F439F),
+    const_float32(0x201EC207),
+    const_float32(0x9E8BE175),
+    const_float32(0x20032C4B),
+    const_float32(0x2004DFF5),
+    const_float32(0x1E72F47A),
+    const_float32(0x1F722F22),
+    const_float32(0xA017E945),
+    const_float32(0x1F401A5B),
+    const_float32(0x9FB9A9E3),
+    const_float32(0x20744C05),
+    const_float32(0x1F773A19),
+    const_float32(0x1FFE90D5),
+    const_float32(0xA041ED22),
+    const_float32(0x1F853F3A),
+};
 #endif
diff --git a/target/m68k/translate.c b/target/m68k/translate.c
index 189b23d38d..4774310ded 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 0x10: /* fetox */
+        gen_helper_fetox(cpu_env, cpu_dest, cpu_src);
+        break;
     case 0x14: /* flogn */
         gen_helper_flogn(cpu_env, cpu_dest, cpu_src);
         break;
-- 
2.14.3

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [Qemu-devel] [PULL v2 7/8] target/m68k: implement ftwotox
  2018-03-09 14:57 [Qemu-devel] [PULL v2 0/8] M68k for 2.12 patches Laurent Vivier
                   ` (5 preceding siblings ...)
  2018-03-09 14:57 ` [Qemu-devel] [PULL v2 6/8] target/m68k: implement fetox Laurent Vivier
@ 2018-03-09 14:57 ` Laurent Vivier
  2018-03-09 14:57 ` [Qemu-devel] [PULL v2 8/8] target/m68k: implement ftentox Laurent Vivier
  2018-03-12 10:07 ` [Qemu-devel] [PULL v2 0/8] M68k for 2.12 patches Peter Maydell
  8 siblings, 0 replies; 10+ messages in thread
From: Laurent Vivier @ 2018-03-09 14:57 UTC (permalink / raw)
  To: qemu-devel; +Cc: Laurent Vivier

Using a local m68k floatx80_twotox()
[copied from previous:
Written by Andreas Grabher for Previous, NeXT Computer Emulator.]

Signed-off-by: Laurent Vivier <laurent@vivier.eu>
Message-Id: <20180305203910.10391-8-laurent@vivier.eu>
---
 target/m68k/fpu_helper.c            |   5 ++
 target/m68k/helper.h                |   1 +
 target/m68k/softfloat.c             | 148 ++++++++++++++++++++++++++++++++++++
 target/m68k/softfloat.h             |   1 +
 target/m68k/softfloat_fpsp_tables.h |  86 +++++++++++++++++++++
 target/m68k/translate.c             |   3 +
 6 files changed, 244 insertions(+)

diff --git a/target/m68k/fpu_helper.c b/target/m68k/fpu_helper.c
index 154666cbb5..f488a92ab2 100644
--- a/target/m68k/fpu_helper.c
+++ b/target/m68k/fpu_helper.c
@@ -582,3 +582,8 @@ void HELPER(fetox)(CPUM68KState *env, FPReg *res, FPReg *val)
 {
     res->d = floatx80_etox(val->d, &env->fp_status);
 }
+
+void HELPER(ftwotox)(CPUM68KState *env, FPReg *res, FPReg *val)
+{
+    res->d = floatx80_twotox(val->d, &env->fp_status);
+}
diff --git a/target/m68k/helper.h b/target/m68k/helper.h
index 70aeb2da7c..8caa82296d 100644
--- a/target/m68k/helper.h
+++ b/target/m68k/helper.h
@@ -73,6 +73,7 @@ DEF_HELPER_3(flogn, void, env, fp, fp)
 DEF_HELPER_3(flog10, void, env, fp, fp)
 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(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 e58eb91738..cfff30d359 100644
--- a/target/m68k/softfloat.c
+++ b/target/m68k/softfloat.c
@@ -965,3 +965,151 @@ floatx80 floatx80_etox(floatx80 a, float_status *status)
         return a;
     }
 }
+
+/*----------------------------------------------------------------------------
+ | 2 to x
+ *----------------------------------------------------------------------------*/
+
+floatx80 floatx80_twotox(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, l, m, m1;
+    floatx80 fp0, fp1, fp2, fp3, adjfact, fact1, fact2;
+
+    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(0, 0, 0);
+        }
+        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;
+
+    fp0 = a;
+
+    compact = floatx80_make_compact(aExp, aSig);
+
+    if (compact < 0x3FB98000 || compact > 0x400D80C0) {
+        /* |X| > 16480 or |X| < 2^(-70) */
+        if (compact > 0x3FFF8000) { /* |X| > 16480 */
+            status->float_rounding_mode = user_rnd_mode;
+            status->floatx80_rounding_precision = user_rnd_prec;
+
+            if (aSign) {
+                return roundAndPackFloatx80(status->floatx80_rounding_precision,
+                                            0, -0x1000, aSig, 0, status);
+            } else {
+                return roundAndPackFloatx80(status->floatx80_rounding_precision,
+                                            0, 0x8000, aSig, 0, status);
+            }
+        } else { /* |X| < 2^(-70) */
+            status->float_rounding_mode = user_rnd_mode;
+            status->floatx80_rounding_precision = user_rnd_prec;
+
+            a = floatx80_add(fp0, float32_to_floatx80(
+                             make_float32(0x3F800000), status),
+                             status); /* 1 + X */
+
+            float_raise(float_flag_inexact, status);
+
+            return a;
+        }
+    } else { /* 2^(-70) <= |X| <= 16480 */
+        fp1 = fp0; /* X */
+        fp1 = floatx80_mul(fp1, float32_to_floatx80(
+                           make_float32(0x42800000), status),
+                           status); /* X * 64 */
+        n = floatx80_to_int32(fp1, status);
+        fp1 = int32_to_floatx80(n, status);
+        j = n & 0x3F;
+        l = 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
+             */
+            l--;
+        }
+        m = l / 2; /* NOTE: this is really arithmetic right shift by 1 */
+        if (l < 0 && (l & 1)) {
+            /* arithmetic right shift is division and
+             * round towards minus infinity
+             */
+            m--;
+        }
+        m1 = l - m;
+        m1 += 0x3FFF; /* ADJFACT IS 2^(M') */
+
+        adjfact = packFloatx80(0, m1, one_sig);
+        fact1 = exp2_tbl[j];
+        fact1.high += m;
+        fact2.high = exp2_tbl2[j] >> 16;
+        fact2.high += m;
+        fact2.low = (uint64_t)(exp2_tbl2[j] & 0xFFFF);
+        fact2.low <<= 48;
+
+        fp1 = floatx80_mul(fp1, float32_to_floatx80(
+                           make_float32(0x3C800000), status),
+                           status); /* (1/64)*N */
+        fp0 = floatx80_sub(fp0, fp1, status); /* X - (1/64)*INT(64 X) */
+        fp2 = packFloatx80(0, 0x3FFE, LIT64(0xB17217F7D1CF79AC)); /* LOG2 */
+        fp0 = floatx80_mul(fp0, fp2, status); /* R */
+
+        /* EXPR */
+        fp1 = floatx80_mul(fp0, fp0, status); /* S = R*R */
+        fp2 = float64_to_floatx80(make_float64(0x3F56C16D6F7BD0B2),
+                                  status); /* A5 */
+        fp3 = float64_to_floatx80(make_float64(0x3F811112302C712C),
+                                  status); /* A4 */
+        fp2 = floatx80_mul(fp2, fp1, status); /* S*A5 */
+        fp3 = floatx80_mul(fp3, fp1, status); /* S*A4 */
+        fp2 = floatx80_add(fp2, float64_to_floatx80(
+                           make_float64(0x3FA5555555554CC1), status),
+                           status); /* A3+S*A5 */
+        fp3 = floatx80_add(fp3, float64_to_floatx80(
+                           make_float64(0x3FC5555555554A54), status),
+                           status); /* A2+S*A4 */
+        fp2 = floatx80_mul(fp2, fp1, status); /* S*(A3+S*A5) */
+        fp3 = floatx80_mul(fp3, fp1, status); /* S*(A2+S*A4) */
+        fp2 = floatx80_add(fp2, float64_to_floatx80(
+                           make_float64(0x3FE0000000000000), status),
+                           status); /* A1+S*(A3+S*A5) */
+        fp3 = floatx80_mul(fp3, fp0, status); /* R*S*(A2+S*A4) */
+
+        fp2 = floatx80_mul(fp2, fp1, status); /* S*(A1+S*(A3+S*A5)) */
+        fp0 = floatx80_add(fp0, fp3, status); /* R+R*S*(A2+S*A4) */
+        fp0 = floatx80_add(fp0, fp2, status); /* EXP(R) - 1 */
+
+        fp0 = floatx80_mul(fp0, fact1, status);
+        fp0 = floatx80_add(fp0, fact2, status);
+        fp0 = floatx80_add(fp0, fact1, status);
+
+        status->float_rounding_mode = user_rnd_mode;
+        status->floatx80_rounding_precision = user_rnd_prec;
+
+        a = floatx80_mul(fp0, adjfact, status);
+
+        float_raise(float_flag_inexact, status);
+
+        return a;
+    }
+}
diff --git a/target/m68k/softfloat.h b/target/m68k/softfloat.h
index 250f0d926f..964275d2a5 100644
--- a/target/m68k/softfloat.h
+++ b/target/m68k/softfloat.h
@@ -32,4 +32,5 @@ floatx80 floatx80_logn(floatx80 a, float_status *status);
 floatx80 floatx80_log10(floatx80 a, float_status *status);
 floatx80 floatx80_log2(floatx80 a, float_status *status);
 floatx80 floatx80_etox(floatx80 a, float_status *status);
+floatx80 floatx80_twotox(floatx80 a, float_status *status);
 #endif
diff --git a/target/m68k/softfloat_fpsp_tables.h b/target/m68k/softfloat_fpsp_tables.h
index b2b63e5ced..dd76dc0373 100644
--- a/target/m68k/softfloat_fpsp_tables.h
+++ b/target/m68k/softfloat_fpsp_tables.h
@@ -285,4 +285,90 @@ static const float32 exp_tbl2[64] = {
     const_float32(0xA041ED22),
     const_float32(0x1F853F3A),
 };
+
+static const floatx80 exp2_tbl[64] = {
+    make_floatx80_init(0x3FFF, 0x8000000000000000),
+    make_floatx80_init(0x3FFF, 0x8164D1F3BC030773),
+    make_floatx80_init(0x3FFF, 0x82CD8698AC2BA1D7),
+    make_floatx80_init(0x3FFF, 0x843A28C3ACDE4046),
+    make_floatx80_init(0x3FFF, 0x85AAC367CC487B15),
+    make_floatx80_init(0x3FFF, 0x871F61969E8D1010),
+    make_floatx80_init(0x3FFF, 0x88980E8092DA8527),
+    make_floatx80_init(0x3FFF, 0x8A14D575496EFD9A),
+    make_floatx80_init(0x3FFF, 0x8B95C1E3EA8BD6E7),
+    make_floatx80_init(0x3FFF, 0x8D1ADF5B7E5BA9E6),
+    make_floatx80_init(0x3FFF, 0x8EA4398B45CD53C0),
+    make_floatx80_init(0x3FFF, 0x9031DC431466B1DC),
+    make_floatx80_init(0x3FFF, 0x91C3D373AB11C336),
+    make_floatx80_init(0x3FFF, 0x935A2B2F13E6E92C),
+    make_floatx80_init(0x3FFF, 0x94F4EFA8FEF70961),
+    make_floatx80_init(0x3FFF, 0x96942D3720185A00),
+    make_floatx80_init(0x3FFF, 0x9837F0518DB8A96F),
+    make_floatx80_init(0x3FFF, 0x99E0459320B7FA65),
+    make_floatx80_init(0x3FFF, 0x9B8D39B9D54E5539),
+    make_floatx80_init(0x3FFF, 0x9D3ED9A72CFFB751),
+    make_floatx80_init(0x3FFF, 0x9EF5326091A111AE),
+    make_floatx80_init(0x3FFF, 0xA0B0510FB9714FC2),
+    make_floatx80_init(0x3FFF, 0xA27043030C496819),
+    make_floatx80_init(0x3FFF, 0xA43515AE09E6809E),
+    make_floatx80_init(0x3FFF, 0xA5FED6A9B15138EA),
+    make_floatx80_init(0x3FFF, 0xA7CD93B4E965356A),
+    make_floatx80_init(0x3FFF, 0xA9A15AB4EA7C0EF8),
+    make_floatx80_init(0x3FFF, 0xAB7A39B5A93ED337),
+    make_floatx80_init(0x3FFF, 0xAD583EEA42A14AC6),
+    make_floatx80_init(0x3FFF, 0xAF3B78AD690A4375),
+    make_floatx80_init(0x3FFF, 0xB123F581D2AC2590),
+    make_floatx80_init(0x3FFF, 0xB311C412A9112489),
+    make_floatx80_init(0x3FFF, 0xB504F333F9DE6484),
+    make_floatx80_init(0x3FFF, 0xB6FD91E328D17791),
+    make_floatx80_init(0x3FFF, 0xB8FBAF4762FB9EE9),
+    make_floatx80_init(0x3FFF, 0xBAFF5AB2133E45FB),
+    make_floatx80_init(0x3FFF, 0xBD08A39F580C36BF),
+    make_floatx80_init(0x3FFF, 0xBF1799B67A731083),
+    make_floatx80_init(0x3FFF, 0xC12C4CCA66709456),
+    make_floatx80_init(0x3FFF, 0xC346CCDA24976407),
+    make_floatx80_init(0x3FFF, 0xC5672A115506DADD),
+    make_floatx80_init(0x3FFF, 0xC78D74C8ABB9B15D),
+    make_floatx80_init(0x3FFF, 0xC9B9BD866E2F27A3),
+    make_floatx80_init(0x3FFF, 0xCBEC14FEF2727C5D),
+    make_floatx80_init(0x3FFF, 0xCE248C151F8480E4),
+    make_floatx80_init(0x3FFF, 0xD06333DAEF2B2595),
+    make_floatx80_init(0x3FFF, 0xD2A81D91F12AE45A),
+    make_floatx80_init(0x3FFF, 0xD4F35AABCFEDFA1F),
+    make_floatx80_init(0x3FFF, 0xD744FCCAD69D6AF4),
+    make_floatx80_init(0x3FFF, 0xD99D15C278AFD7B6),
+    make_floatx80_init(0x3FFF, 0xDBFBB797DAF23755),
+    make_floatx80_init(0x3FFF, 0xDE60F4825E0E9124),
+    make_floatx80_init(0x3FFF, 0xE0CCDEEC2A94E111),
+    make_floatx80_init(0x3FFF, 0xE33F8972BE8A5A51),
+    make_floatx80_init(0x3FFF, 0xE5B906E77C8348A8),
+    make_floatx80_init(0x3FFF, 0xE8396A503C4BDC68),
+    make_floatx80_init(0x3FFF, 0xEAC0C6E7DD24392F),
+    make_floatx80_init(0x3FFF, 0xED4F301ED9942B84),
+    make_floatx80_init(0x3FFF, 0xEFE4B99BDCDAF5CB),
+    make_floatx80_init(0x3FFF, 0xF281773C59FFB13A),
+    make_floatx80_init(0x3FFF, 0xF5257D152486CC2C),
+    make_floatx80_init(0x3FFF, 0xF7D0DF730AD13BB9),
+    make_floatx80_init(0x3FFF, 0xFA83B2DB722A033A),
+    make_floatx80_init(0x3FFF, 0xFD3E0C0CF486C175)
+};
+
+static const uint32_t exp2_tbl2[64] = {
+    0x3F738000, 0x3FBEF7CA, 0x3FBDF8A9, 0x3FBCD7C9,
+    0xBFBDE8DA, 0x3FBDE85C, 0x3FBEBBF1, 0x3FBB80CA,
+    0xBFBA8373, 0xBFBE9670, 0x3FBDB700, 0x3FBEEEB0,
+    0x3FBBFD6D, 0xBFBDB319, 0x3FBDBA2B, 0x3FBE91D5,
+    0x3FBE8D5A, 0xBFBCDE7B, 0xBFBEBAAF, 0xBFBD86DA,
+    0xBFBEBEDD, 0x3FBCC96E, 0xBFBEC90B, 0x3FBBD1DB,
+    0x3FBCE5EB, 0xBFBEC274, 0x3FBEA83C, 0x3FBECB00,
+    0x3FBE9301, 0xBFBD8367, 0xBFBEF05F, 0x3FBDFB3C,
+    0x3FBEB2FB, 0x3FBAE2CB, 0x3FBCDC3C, 0x3FBEE9AA,
+    0xBFBEAEFD, 0xBFBCBF51, 0x3FBEF88A, 0x3FBD83B2,
+    0x3FBDF8AB, 0xBFBDFB17, 0xBFBEFE3C, 0xBFBBB6F8,
+    0xBFBCEE53, 0xBFBDA4AE, 0x3FBC9124, 0x3FBEB243,
+    0x3FBDE69A, 0xBFB8BC61, 0x3FBDF610, 0xBFBD8BE1,
+    0x3FBACB12, 0x3FBB9BFE, 0x3FBCF2F4, 0x3FBEF22F,
+    0xBFBDBF4A, 0x3FBEC01A, 0x3FBE8CAC, 0xBFBCBB3F,
+    0x3FBEF73A, 0xBFB8B795, 0x3FBEF84B, 0xBFBEF581
+};
 #endif
diff --git a/target/m68k/translate.c b/target/m68k/translate.c
index 4774310ded..c65c82e258 100644
--- a/target/m68k/translate.c
+++ b/target/m68k/translate.c
@@ -5060,6 +5060,9 @@ DISAS_INSN(fpu)
     case 0x10: /* fetox */
         gen_helper_fetox(cpu_env, cpu_dest, cpu_src);
         break;
+    case 0x11: /* ftwotox */
+        gen_helper_ftwotox(cpu_env, cpu_dest, cpu_src);
+        break;
     case 0x14: /* flogn */
         gen_helper_flogn(cpu_env, cpu_dest, cpu_src);
         break;
-- 
2.14.3

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [Qemu-devel] [PULL v2 8/8] target/m68k: implement ftentox
  2018-03-09 14:57 [Qemu-devel] [PULL v2 0/8] M68k for 2.12 patches Laurent Vivier
                   ` (6 preceding siblings ...)
  2018-03-09 14:57 ` [Qemu-devel] [PULL v2 7/8] target/m68k: implement ftwotox Laurent Vivier
@ 2018-03-09 14:57 ` Laurent Vivier
  2018-03-12 10:07 ` [Qemu-devel] [PULL v2 0/8] M68k for 2.12 patches Peter Maydell
  8 siblings, 0 replies; 10+ messages in thread
From: Laurent Vivier @ 2018-03-09 14:57 UTC (permalink / raw)
  To: qemu-devel; +Cc: Laurent Vivier

Using a local m68k floatx80_tentox()
[copied from previous:
Written by Andreas Grabher for Previous, NeXT Computer Emulator.]

Signed-off-by: Laurent Vivier <laurent@vivier.eu>
Message-Id: <20180305203910.10391-9-laurent@vivier.eu>
---
 target/m68k/fpu_helper.c |   5 ++
 target/m68k/helper.h     |   1 +
 target/m68k/softfloat.c  | 153 +++++++++++++++++++++++++++++++++++++++++++++++
 target/m68k/softfloat.h  |   1 +
 target/m68k/translate.c  |   3 +
 5 files changed, 163 insertions(+)

diff --git a/target/m68k/fpu_helper.c b/target/m68k/fpu_helper.c
index f488a92ab2..62cbb0dff1 100644
--- a/target/m68k/fpu_helper.c
+++ b/target/m68k/fpu_helper.c
@@ -587,3 +587,8 @@ void HELPER(ftwotox)(CPUM68KState *env, FPReg *res, FPReg *val)
 {
     res->d = floatx80_twotox(val->d, &env->fp_status);
 }
+
+void HELPER(ftentox)(CPUM68KState *env, FPReg *res, FPReg *val)
+{
+    res->d = floatx80_tentox(val->d, &env->fp_status);
+}
diff --git a/target/m68k/helper.h b/target/m68k/helper.h
index 8caa82296d..9a9734c196 100644
--- a/target/m68k/helper.h
+++ b/target/m68k/helper.h
@@ -74,6 +74,7 @@ DEF_HELPER_3(flog10, void, env, fp, fp)
 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(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 cfff30d359..4bd5b9e6b7 100644
--- a/target/m68k/softfloat.c
+++ b/target/m68k/softfloat.c
@@ -1113,3 +1113,156 @@ floatx80 floatx80_twotox(floatx80 a, float_status *status)
         return a;
     }
 }
+
+/*----------------------------------------------------------------------------
+ | 10 to x
+ *----------------------------------------------------------------------------*/
+
+floatx80 floatx80_tentox(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, l, m, m1;
+    floatx80 fp0, fp1, fp2, fp3, adjfact, fact1, fact2;
+
+    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(0, 0, 0);
+        }
+        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;
+
+    fp0 = a;
+
+    compact = floatx80_make_compact(aExp, aSig);
+
+    if (compact < 0x3FB98000 || compact > 0x400B9B07) {
+        /* |X| > 16480 LOG2/LOG10 or |X| < 2^(-70) */
+        if (compact > 0x3FFF8000) { /* |X| > 16480 */
+            status->float_rounding_mode = user_rnd_mode;
+            status->floatx80_rounding_precision = user_rnd_prec;
+
+            if (aSign) {
+                return roundAndPackFloatx80(status->floatx80_rounding_precision,
+                                            0, -0x1000, aSig, 0, status);
+            } else {
+                return roundAndPackFloatx80(status->floatx80_rounding_precision,
+                                            0, 0x8000, aSig, 0, status);
+            }
+        } else { /* |X| < 2^(-70) */
+            status->float_rounding_mode = user_rnd_mode;
+            status->floatx80_rounding_precision = user_rnd_prec;
+
+            a = floatx80_add(fp0, float32_to_floatx80(
+                             make_float32(0x3F800000), status),
+                             status); /* 1 + X */
+
+            float_raise(float_flag_inexact, status);
+
+            return a;
+        }
+    } else { /* 2^(-70) <= |X| <= 16480 LOG 2 / LOG 10 */
+        fp1 = fp0; /* X */
+        fp1 = floatx80_mul(fp1, float64_to_floatx80(
+                           make_float64(0x406A934F0979A371),
+                           status), status); /* X*64*LOG10/LOG2 */
+        n = floatx80_to_int32(fp1, status); /* N=INT(X*64*LOG10/LOG2) */
+        fp1 = int32_to_floatx80(n, status);
+
+        j = n & 0x3F;
+        l = 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
+             */
+            l--;
+        }
+        m = l / 2; /* NOTE: this is really arithmetic right shift by 1 */
+        if (l < 0 && (l & 1)) {
+            /* arithmetic right shift is division and
+             * round towards minus infinity
+             */
+            m--;
+        }
+        m1 = l - m;
+        m1 += 0x3FFF; /* ADJFACT IS 2^(M') */
+
+        adjfact = packFloatx80(0, m1, one_sig);
+        fact1 = exp2_tbl[j];
+        fact1.high += m;
+        fact2.high = exp2_tbl2[j] >> 16;
+        fact2.high += m;
+        fact2.low = (uint64_t)(exp2_tbl2[j] & 0xFFFF);
+        fact2.low <<= 48;
+
+        fp2 = fp1; /* N */
+        fp1 = floatx80_mul(fp1, float64_to_floatx80(
+                           make_float64(0x3F734413509F8000), status),
+                           status); /* N*(LOG2/64LOG10)_LEAD */
+        fp3 = packFloatx80(1, 0x3FCD, LIT64(0xC0219DC1DA994FD2));
+        fp2 = floatx80_mul(fp2, fp3, status); /* N*(LOG2/64LOG10)_TRAIL */
+        fp0 = floatx80_sub(fp0, fp1, status); /* X - N L_LEAD */
+        fp0 = floatx80_sub(fp0, fp2, status); /* X - N L_TRAIL */
+        fp2 = packFloatx80(0, 0x4000, LIT64(0x935D8DDDAAA8AC17)); /* LOG10 */
+        fp0 = floatx80_mul(fp0, fp2, status); /* R */
+
+        /* EXPR */
+        fp1 = floatx80_mul(fp0, fp0, status); /* S = R*R */
+        fp2 = float64_to_floatx80(make_float64(0x3F56C16D6F7BD0B2),
+                                  status); /* A5 */
+        fp3 = float64_to_floatx80(make_float64(0x3F811112302C712C),
+                                  status); /* A4 */
+        fp2 = floatx80_mul(fp2, fp1, status); /* S*A5 */
+        fp3 = floatx80_mul(fp3, fp1, status); /* S*A4 */
+        fp2 = floatx80_add(fp2, float64_to_floatx80(
+                           make_float64(0x3FA5555555554CC1), status),
+                           status); /* A3+S*A5 */
+        fp3 = floatx80_add(fp3, float64_to_floatx80(
+                           make_float64(0x3FC5555555554A54), status),
+                           status); /* A2+S*A4 */
+        fp2 = floatx80_mul(fp2, fp1, status); /* S*(A3+S*A5) */
+        fp3 = floatx80_mul(fp3, fp1, status); /* S*(A2+S*A4) */
+        fp2 = floatx80_add(fp2, float64_to_floatx80(
+                           make_float64(0x3FE0000000000000), status),
+                           status); /* A1+S*(A3+S*A5) */
+        fp3 = floatx80_mul(fp3, fp0, status); /* R*S*(A2+S*A4) */
+
+        fp2 = floatx80_mul(fp2, fp1, status); /* S*(A1+S*(A3+S*A5)) */
+        fp0 = floatx80_add(fp0, fp3, status); /* R+R*S*(A2+S*A4) */
+        fp0 = floatx80_add(fp0, fp2, status); /* EXP(R) - 1 */
+
+        fp0 = floatx80_mul(fp0, fact1, status);
+        fp0 = floatx80_add(fp0, fact2, status);
+        fp0 = floatx80_add(fp0, fact1, status);
+
+        status->float_rounding_mode = user_rnd_mode;
+        status->floatx80_rounding_precision = user_rnd_prec;
+
+        a = floatx80_mul(fp0, adjfact, status);
+
+        float_raise(float_flag_inexact, status);
+
+        return a;
+    }
+}
diff --git a/target/m68k/softfloat.h b/target/m68k/softfloat.h
index 964275d2a5..d28e49fe9f 100644
--- a/target/m68k/softfloat.h
+++ b/target/m68k/softfloat.h
@@ -33,4 +33,5 @@ floatx80 floatx80_log10(floatx80 a, float_status *status);
 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);
 #endif
diff --git a/target/m68k/translate.c b/target/m68k/translate.c
index c65c82e258..6d5bde0777 100644
--- a/target/m68k/translate.c
+++ b/target/m68k/translate.c
@@ -5063,6 +5063,9 @@ DISAS_INSN(fpu)
     case 0x11: /* ftwotox */
         gen_helper_ftwotox(cpu_env, cpu_dest, cpu_src);
         break;
+    case 0x12: /* ftentox */
+        gen_helper_ftentox(cpu_env, cpu_dest, cpu_src);
+        break;
     case 0x14: /* flogn */
         gen_helper_flogn(cpu_env, cpu_dest, cpu_src);
         break;
-- 
2.14.3

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* Re: [Qemu-devel] [PULL v2 0/8] M68k for 2.12 patches
  2018-03-09 14:57 [Qemu-devel] [PULL v2 0/8] M68k for 2.12 patches Laurent Vivier
                   ` (7 preceding siblings ...)
  2018-03-09 14:57 ` [Qemu-devel] [PULL v2 8/8] target/m68k: implement ftentox Laurent Vivier
@ 2018-03-12 10:07 ` Peter Maydell
  8 siblings, 0 replies; 10+ messages in thread
From: Peter Maydell @ 2018-03-12 10:07 UTC (permalink / raw)
  To: Laurent Vivier; +Cc: QEMU Developers

On 9 March 2018 at 14:57, Laurent Vivier <laurent@vivier.eu> wrote:
> The following changes since commit e1ee9ee139ed7091c2c592d5b784fbb7227bfc0d:
>
>   Merge remote-tracking branch 'remotes/dgibson/tags/ppc-for-2.12-20180306' into staging (2018-03-06 10:21:35 +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 6c25be6e30bda0e470f8f0b6b93d53a6efe469e8:
>
>   target/m68k: implement ftentox (2018-03-09 15:50:38 +0100)
>
> ----------------------------------------------------------------
> v2 fixes permissions of file target/m68k/softfloat_fpsp_tables.h
> ----------------------------------------------------------------

Applied, thanks.

-- PMM

^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2018-03-12 10:08 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-03-09 14:57 [Qemu-devel] [PULL v2 0/8] M68k for 2.12 patches Laurent Vivier
2018-03-09 14:57 ` [Qemu-devel] [PULL v2 1/8] target/m68k: define floatx80_move() Laurent Vivier
2018-03-09 14:57 ` [Qemu-devel] [PULL v2 2/8] target/m68k: implement flognp1 Laurent Vivier
2018-03-09 14:57 ` [Qemu-devel] [PULL v2 3/8] target/m68k: implement flogn Laurent Vivier
2018-03-09 14:57 ` [Qemu-devel] [PULL v2 4/8] target/m68k: implement flog10 Laurent Vivier
2018-03-09 14:57 ` [Qemu-devel] [PULL v2 5/8] target/m68k: implement flog2 Laurent Vivier
2018-03-09 14:57 ` [Qemu-devel] [PULL v2 6/8] target/m68k: implement fetox Laurent Vivier
2018-03-09 14:57 ` [Qemu-devel] [PULL v2 7/8] target/m68k: implement ftwotox Laurent Vivier
2018-03-09 14:57 ` [Qemu-devel] [PULL v2 8/8] target/m68k: implement ftentox Laurent Vivier
2018-03-12 10:07 ` [Qemu-devel] [PULL v2 0/8] M68k for 2.12 patches Peter Maydell

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.