Re: [Qemu-devel] [PATCH v3 15/16] target-m68k: add more FPU instructions

2017-02-17 Thread Andreas Schwab
On Feb 17 2017, Richard Henderson  wrote:

> On 02/16/2017 09:18 PM, Andreas Schwab wrote:
>> There is no guarantee that the host long double has the same range and
>> precision as floatx80.
>
> Indeed not.  However, do you have another plan for implementing the
> trancendentals?  I'm quite happy using the host long double libm as an
> estimate.  Which is better than at least BasiliskII, which uses the host
> double.

In ARAnyM, I implemented a software emulation using mpfr (but it is
still incomplete in many ways).  I don't know if something like this
would be an option for qemu.

Andreas.

-- 
Andreas Schwab, sch...@linux-m68k.org
GPG Key fingerprint = 58CA 54C7 6D53 942B 1756  01D3 44D5 214B 8276 4ED5
"And now for something completely different."



Re: [Qemu-devel] [PATCH v3 15/16] target-m68k: add more FPU instructions

2017-02-16 Thread Richard Henderson

On 02/16/2017 09:18 PM, Andreas Schwab wrote:

There is no guarantee that the host long double has the same range and
precision as floatx80.


Indeed not.  However, do you have another plan for implementing the 
trancendentals?  I'm quite happy using the host long double libm as an 
estimate.  Which is better than at least BasiliskII, which uses the host double.



r~



Re: [Qemu-devel] [PATCH v3 15/16] target-m68k: add more FPU instructions

2017-02-15 Thread Richard Henderson

On 02/07/2017 11:59 AM, Laurent Vivier wrote:

+static long double floatx80_to_ldouble(floatx80 val)
+{
+if (floatx80_is_infinity(val)) {
+if (floatx80_is_neg(val)) {
+return -__builtin_infl();
+}
+return __builtin_infl();
+}
+if (floatx80_is_any_nan(val)) {
+char low[20];
+sprintf(low, "0x%016"PRIx64, val.low);
+
+return nanl(low);
+}
+
+return *(long double *)
+}


This doesn't work except for x86 host.

You ought to extract the mantissa, convert the 64-bit value to long-double, and 
use ldexpl to scale the result for the exponent.


Similarly converting the other way use frexpl and ldexpl.


r~



[Qemu-devel] [PATCH v3 15/16] target-m68k: add more FPU instructions

2017-02-06 Thread Laurent Vivier
Add fsinh, flognp1, ftanh, fatan, fasin, fatanh,
fsin, ftan, fetox, ftwotox, ftentox, flogn, flog10, facos,
fcos.

As softfloat library does not provide these functions,
we us the libm of the host.

Signed-off-by: Laurent Vivier 
---
 target/m68k/fpu_helper.c | 237 +++
 target/m68k/helper.h |  16 
 target/m68k/translate.c  |  48 ++
 3 files changed, 301 insertions(+)

diff --git a/target/m68k/fpu_helper.c b/target/m68k/fpu_helper.c
index c69efe1..95d5cc4 100644
--- a/target/m68k/fpu_helper.c
+++ b/target/m68k/fpu_helper.c
@@ -23,6 +23,7 @@
 #include "cpu.h"
 #include "exec/helper-proto.h"
 #include "exec/exec-all.h"
+#include 
 
 static const floatx80 fpu_rom[128] = {
 [0x00] = floatx80_pi,   /* Pi */
@@ -712,3 +713,239 @@ void HELPER(mod_FP0_FP1)(CPUM68KState *env)
 
 floatx80_to_FP0(env, res);
 }
+
+static long double floatx80_to_ldouble(floatx80 val)
+{
+if (floatx80_is_infinity(val)) {
+if (floatx80_is_neg(val)) {
+return -__builtin_infl();
+}
+return __builtin_infl();
+}
+if (floatx80_is_any_nan(val)) {
+char low[20];
+sprintf(low, "0x%016"PRIx64, val.low);
+
+return nanl(low);
+}
+
+return *(long double *)
+}
+
+static floatx80 ldouble_to_floatx80(long double val)
+{
+floatx80 res;
+
+if (isinf(val)) {
+res.high = floatx80_default_nan(NULL).high;
+res.low = 0;
+}
+if (isinf(val) < 0) {
+res.high |= 0x8000;
+}
+if (isnan(val)) {
+res.high = floatx80_default_nan(NULL).high;
+res.low = *(uint64_t *)((char *) + 4);
+}
+return *(floatx80 *)
+}
+
+void HELPER(sinh_FP0)(CPUM68KState *env)
+{
+floatx80 res;
+long double val;
+
+val = sinhl(floatx80_to_ldouble(FP0_to_floatx80(env)));
+res = ldouble_to_floatx80(val);
+
+floatx80_to_FP0(env, res);
+}
+
+void HELPER(lognp1_FP0)(CPUM68KState *env)
+{
+floatx80 val;
+long double res;
+
+val = FP0_to_floatx80(env);
+res = logl(floatx80_to_ldouble(val) + 1.0);
+
+floatx80_to_FP0(env, ldouble_to_floatx80(res));
+}
+
+void HELPER(ln_FP0)(CPUM68KState *env)
+{
+floatx80 val;
+long double res;
+
+val = FP0_to_floatx80(env);
+res = logl(floatx80_to_ldouble(val));
+
+floatx80_to_FP0(env, ldouble_to_floatx80(res));
+}
+
+void HELPER(log10_FP0)(CPUM68KState *env)
+{
+floatx80 val;
+long double res;
+
+val = FP0_to_floatx80(env);
+res = log10l(floatx80_to_ldouble(val));
+
+floatx80_to_FP0(env, ldouble_to_floatx80(res));
+}
+
+void HELPER(atan_FP0)(CPUM68KState *env)
+{
+floatx80 res;
+long double val;
+
+val = floatx80_to_ldouble(FP0_to_floatx80(env));
+
+val = atanl(val);
+res = ldouble_to_floatx80(val);
+floatx80_to_FP0(env, res);
+}
+
+void HELPER(asin_FP0)(CPUM68KState *env)
+{
+floatx80 res;
+long double val;
+
+val = floatx80_to_ldouble(FP0_to_floatx80(env));
+if (val < -1.0 || val > 1.0) {
+floatx80_to_FP0(env, floatx80_default_nan(NULL));
+return;
+}
+
+val = asinl(val);
+res = ldouble_to_floatx80(val);
+floatx80_to_FP0(env, res);
+}
+
+void HELPER(atanh_FP0)(CPUM68KState *env)
+{
+floatx80 res;
+long double val;
+
+val = floatx80_to_ldouble(FP0_to_floatx80(env));
+if (val < -1.0 || val > 1.0) {
+floatx80_to_FP0(env, floatx80_default_nan(NULL));
+return;
+}
+
+val = atanhl(val);
+res = ldouble_to_floatx80(val);
+floatx80_to_FP0(env, res);
+}
+
+void HELPER(sin_FP0)(CPUM68KState *env)
+{
+floatx80 res;
+long double val;
+
+val = floatx80_to_ldouble(FP0_to_floatx80(env));
+
+val = sinl(val);
+res = ldouble_to_floatx80(val);
+floatx80_to_FP0(env, res);
+}
+
+void HELPER(tanh_FP0)(CPUM68KState *env)
+{
+floatx80 res;
+long double val;
+
+val = floatx80_to_ldouble(FP0_to_floatx80(env));
+
+val = tanhl(val);
+res = ldouble_to_floatx80(val);
+floatx80_to_FP0(env, res);
+}
+
+void HELPER(tan_FP0)(CPUM68KState *env)
+{
+floatx80 res;
+long double val;
+
+val = floatx80_to_ldouble(FP0_to_floatx80(env));
+
+val = tanl(val);
+res = ldouble_to_floatx80(val);
+floatx80_to_FP0(env, res);
+}
+
+void HELPER(exp_FP0)(CPUM68KState *env)
+{
+floatx80 f;
+long double res;
+
+f = FP0_to_floatx80(env);
+
+res = expl(floatx80_to_ldouble(f));
+
+floatx80_to_FP0(env, ldouble_to_floatx80(res));
+}
+
+void HELPER(exp2_FP0)(CPUM68KState *env)
+{
+floatx80 f;
+long double res;
+
+f = FP0_to_floatx80(env);
+
+res = exp2l(floatx80_to_ldouble(f));
+
+floatx80_to_FP0(env, ldouble_to_floatx80(res));
+}
+
+void HELPER(exp10_FP0)(CPUM68KState *env)
+{
+floatx80 res;
+long double val;
+
+val = floatx80_to_ldouble(FP0_to_floatx80(env));
+
+val = exp10l(val);
+