qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [PATCH for-9.2 0/4] target/m68k: Implement fmove.p
@ 2024-08-11  6:03 Richard Henderson
  2024-08-11  6:03 ` [PATCH 1/4] target/m68k: Introduce M68K_FEATURE_FPU_PACKED_DECIMAL Richard Henderson
                   ` (3 more replies)
  0 siblings, 4 replies; 5+ messages in thread
From: Richard Henderson @ 2024-08-11  6:03 UTC (permalink / raw)
  To: qemu-devel; +Cc: laurent

Implement packed decimal real conversions.

This is perhaps too trivial, as it does not produce correctly rounded
results compared to the compiler.  I'm not sure how else to implement
this without using gmp, which seems a bit heavy-weight.

Perhaps we could do better with a compile-time table of powers of 10,
rather that the pile of runtime roundings that I use in this patch set.
If the host libc supports float128, we could probably leverage scanf
to produce properly rounded results, but that ignores other hosts.


r~


Richard Henderson (4):
  target/m68k: Introduce M68K_FEATURE_FPU_PACKED_DECIMAL
  target/m68k: Implement packed decimal real loads
  target/m68k: Implement packed decimal real stores
  tests/tcg/m68k: Add packed decimal tests

 target/m68k/cpu.h                |   2 +
 target/m68k/helper.h             |   3 +
 target/m68k/cpu.c                |   2 +
 target/m68k/fpu_helper.c         | 237 +++++++++++++++++++++++++++++++
 target/m68k/translate.c          |  49 +++++--
 tests/tcg/m68k/packeddecimal-1.c |  45 ++++++
 tests/tcg/m68k/packeddecimal-2.c |  42 ++++++
 tests/tcg/m68k/Makefile.target   |   2 +-
 8 files changed, 368 insertions(+), 14 deletions(-)
 create mode 100644 tests/tcg/m68k/packeddecimal-1.c
 create mode 100644 tests/tcg/m68k/packeddecimal-2.c

-- 
2.43.0



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

* [PATCH 1/4] target/m68k: Introduce M68K_FEATURE_FPU_PACKED_DECIMAL
  2024-08-11  6:03 [PATCH for-9.2 0/4] target/m68k: Implement fmove.p Richard Henderson
@ 2024-08-11  6:03 ` Richard Henderson
  2024-08-11  6:03 ` [PATCH 2/4] target/m68k: Implement packed decimal real loads Richard Henderson
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 5+ messages in thread
From: Richard Henderson @ 2024-08-11  6:03 UTC (permalink / raw)
  To: qemu-devel; +Cc: laurent

Set for 68020 and 68030, but does nothing so far.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 target/m68k/cpu.h | 2 ++
 target/m68k/cpu.c | 2 ++
 2 files changed, 4 insertions(+)

diff --git a/target/m68k/cpu.h b/target/m68k/cpu.h
index b5bbeedb7a..7114324e4d 100644
--- a/target/m68k/cpu.h
+++ b/target/m68k/cpu.h
@@ -553,6 +553,8 @@ enum m68k_features {
     M68K_FEATURE_MOVEFROMSR_PRIV,
     /* Exception frame with format+vector (from 68010) */
     M68K_FEATURE_EXCEPTION_FORMAT_VEC,
+    /* FPU supports packed decimal real format */
+    M68K_FEATURE_FPU_PACKED_DECIMAL,
 };
 
 static inline bool m68k_feature(CPUM68KState *env, int feature)
diff --git a/target/m68k/cpu.c b/target/m68k/cpu.c
index 1d49f4cb23..65058dd052 100644
--- a/target/m68k/cpu.c
+++ b/target/m68k/cpu.c
@@ -182,6 +182,7 @@ static void m68020_cpu_initfn(Object *obj)
     m68k_set_feature(env, M68K_FEATURE_MSP);
     m68k_set_feature(env, M68K_FEATURE_UNALIGNED_DATA);
     m68k_set_feature(env, M68K_FEATURE_TRAPCC);
+    m68k_set_feature(env, M68K_FEATURE_FPU_PACKED_DECIMAL);
 }
 
 /*
@@ -224,6 +225,7 @@ static void m68040_cpu_initfn(Object *obj)
 
     m68030_cpu_initfn(obj);
     m68k_unset_feature(env, M68K_FEATURE_M68030);
+    m68k_unset_feature(env, M68K_FEATURE_FPU_PACKED_DECIMAL);
     m68k_set_feature(env, M68K_FEATURE_M68040);
 }
 
-- 
2.43.0



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

* [PATCH 2/4] target/m68k: Implement packed decimal real loads
  2024-08-11  6:03 [PATCH for-9.2 0/4] target/m68k: Implement fmove.p Richard Henderson
  2024-08-11  6:03 ` [PATCH 1/4] target/m68k: Introduce M68K_FEATURE_FPU_PACKED_DECIMAL Richard Henderson
@ 2024-08-11  6:03 ` Richard Henderson
  2024-08-11  6:03 ` [PATCH 3/4] target/m68k: Implement packed decimal real stores Richard Henderson
  2024-08-11  6:03 ` [PATCH 4/4] tests/tcg/m68k: Add packed decimal tests Richard Henderson
  3 siblings, 0 replies; 5+ messages in thread
From: Richard Henderson @ 2024-08-11  6:03 UTC (permalink / raw)
  To: qemu-devel; +Cc: laurent

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 target/m68k/helper.h     |   2 +
 target/m68k/fpu_helper.c | 137 +++++++++++++++++++++++++++++++++++++++
 target/m68k/translate.c  |  22 ++++---
 3 files changed, 151 insertions(+), 10 deletions(-)

diff --git a/target/m68k/helper.h b/target/m68k/helper.h
index 95aa5e53bb..2c71361451 100644
--- a/target/m68k/helper.h
+++ b/target/m68k/helper.h
@@ -126,6 +126,8 @@ DEF_HELPER_FLAGS_4(bfffo_mem, TCG_CALL_NO_WG, i64, env, i32, s32, i32)
 DEF_HELPER_3(chk, void, env, s32, s32)
 DEF_HELPER_4(chk2, void, env, s32, s32, s32)
 
+DEF_HELPER_FLAGS_3(load_pdr_to_fx80, TCG_CALL_NO_RWG, void, env, fp, tl)
+
 #if !defined(CONFIG_USER_ONLY)
 DEF_HELPER_3(ptest, void, env, i32, i32)
 DEF_HELPER_3(pflush, void, env, i32, i32)
diff --git a/target/m68k/fpu_helper.c b/target/m68k/fpu_helper.c
index 8314791f50..dd80943153 100644
--- a/target/m68k/fpu_helper.c
+++ b/target/m68k/fpu_helper.c
@@ -749,3 +749,140 @@ void HELPER(fcosh)(CPUM68KState *env, FPReg *res, FPReg *val)
 {
     res->d = floatx80_cosh(val->d, &env->fp_status);
 }
+
+/* From m68k float.h, LDBL_MAX_10_EXP. */
+#define FX80_MAX_10_EXP  4932
+
+/* 10**0 through 10**18 */
+static const int64_t i64_pow10[] = {
+    1ll,
+    10ll,
+    100ll,
+    1000ll,
+    10000ll,
+    100000ll,
+    1000000ll,
+    10000000ll,
+    100000000ll,
+    1000000000ll,
+    10000000000ll,
+    100000000000ll,
+    1000000000000ll,
+    10000000000000ll,
+    100000000000000ll,
+    1000000000000000ll,
+    10000000000000000ll,
+    100000000000000000ll,
+    1000000000000000000ll,
+};
+
+/* Form 10**exp */
+static floatx80 floatx80_exp10i(int exp, float_status *status)
+{
+    static floatx80 cache[FX80_MAX_10_EXP + 1];
+
+    floatx80 ret;
+
+    assert(exp >= 0 && exp <= FX80_MAX_10_EXP);
+
+    ret = cache[exp];
+    if (ret.high) {
+        if (exp >= ARRAY_SIZE(i64_pow10)) {
+            float_raise(float_flag_inexact, status);
+        }
+    } else {
+        FloatRoundMode old_round = get_float_rounding_mode(status);
+        set_float_rounding_mode(float_round_nearest_even, status);
+
+        if (exp < ARRAY_SIZE(i64_pow10)) {
+            ret = int64_to_floatx80(i64_pow10[exp], status);
+        } else {
+            int e0 = exp / 2;
+            int e1 = exp - e0;
+            ret = floatx80_mul(floatx80_exp10i(e0, status),
+                               floatx80_exp10i(e1, status), status);
+        }
+
+        set_float_rounding_mode(old_round, status);
+        cache[exp] = ret;
+    }
+    return ret;
+}
+
+void HELPER(load_pdr_to_fx80)(CPUM68KState *env, FPReg *res, target_ulong addr)
+{
+    uint64_t lo;
+    uint32_t hi;
+    int64_t mant;
+    int exp;
+    floatx80 fexp;
+
+    hi = cpu_ldl_be_data_ra(env, addr, GETPC());
+    lo = cpu_ldq_be_data_ra(env, addr + 4, GETPC());
+
+    if (unlikely((hi & 0x7fff0000) == 0x7fff0000)) {
+        /* NaN or Inf */
+        res->l.lower = lo;
+        res->l.upper = hi >> 16;
+        return;
+    }
+
+    /* Initialize mant with the integer digit. */
+    mant = hi & 0xf;
+    if (!mant && !lo) {
+        /* +/- 0, regardless of exponent. */
+        res->l.lower = 0;
+        res->l.upper = (hi >> 16) & 0x8000;
+        return;
+    }
+
+    /*
+     * Accumulate the 16 decimal fraction digits into mant.
+     * With 17 decimal digits, the maximum value is 10**17 - 1,
+     * which is less than 2**57.
+     */
+    for (int i = 60; i >= 0; i -= 4) {
+        /*
+         * From 1.6.6 Data Format and Type Summary:
+         * The fpu does not detect non-decimal digits in any of the exponent,
+         * integer, or fraction digits.  These non-decimal digits are converted
+         * in the same manner as decimal digits; the result is probably useless
+         * although it is repeatable.
+         */
+        mant = mant * 10 + ((lo >> i) & 0xf);
+    }
+
+    /* Apply the mantissa sign. */
+    if (hi & 0x80000000) {
+        mant = -mant;
+    }
+
+    /* Convert the 3 digit decimal exponent to binary. */
+    exp = ((hi >> 24) & 0xf)
+        + ((hi >> 20) & 0xf) * 10
+        + ((hi >> 16) & 0xf) * 100;
+
+    /* Apply the exponent sign. */
+    if (hi & 0x40000000) {
+        exp = -exp;
+    }
+
+    /*
+     * Our representation of mant is integral, whereas the decimal point
+     * belongs between the integer and fractional components.
+     * Adjust the exponent to compensate.
+     */
+    exp -= 16;
+
+    /* Convert mantissa. */
+    res->d = int64_to_floatx80(mant, &env->fp_status);
+
+    /* Apply exponent. */
+    if (exp > 0) {
+        fexp = floatx80_exp10i(exp, &env->fp_status);
+        res->d = floatx80_mul(res->d, fexp, &env->fp_status);
+    } else if (exp < 0) {
+        fexp = floatx80_exp10i(-exp, &env->fp_status);
+        res->d = floatx80_div(res->d, fexp, &env->fp_status);
+    }
+}
diff --git a/target/m68k/translate.c b/target/m68k/translate.c
index 445966fb6a..59e7d27393 100644
--- a/target/m68k/translate.c
+++ b/target/m68k/translate.c
@@ -963,11 +963,11 @@ static void gen_load_fp(DisasContext *s, int opsize, TCGv addr, TCGv_ptr fp,
         tcg_gen_st_i64(t64, fp, offsetof(FPReg, l.lower));
         break;
     case OS_PACKED:
-        /*
-         * unimplemented data type on 68040/ColdFire
-         * FIXME if needed for another FPU
-         */
-        gen_exception(s, s->base.pc_next, EXCP_FP_UNIMP);
+        if (!m68k_feature(s->env, M68K_FEATURE_FPU_PACKED_DECIMAL)) {
+            gen_exception(s, s->base.pc_next, EXCP_FP_UNIMP);
+            break;
+        }
+        gen_helper_load_pdr_to_fx80(tcg_env, fp, addr);
         break;
     default:
         g_assert_not_reached();
@@ -1142,11 +1142,13 @@ static int gen_ea_mode_fp(CPUM68KState *env, DisasContext *s, int mode,
                 tcg_gen_st_i64(t64, fp, offsetof(FPReg, l.lower));
                 break;
             case OS_PACKED:
-                /*
-                 * unimplemented data type on 68040/ColdFire
-                 * FIXME if needed for another FPU
-                 */
-                gen_exception(s, s->base.pc_next, EXCP_FP_UNIMP);
+                if (!m68k_feature(s->env, M68K_FEATURE_FPU_PACKED_DECIMAL)) {
+                    gen_exception(s, s->base.pc_next, EXCP_FP_UNIMP);
+                    break;
+                }
+                tmp = tcg_constant_tl(s->pc);
+                s->pc += 12;
+                gen_helper_load_pdr_to_fx80(tcg_env, fp, tmp);
                 break;
             default:
                 g_assert_not_reached();
-- 
2.43.0



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

* [PATCH 3/4] target/m68k: Implement packed decimal real stores
  2024-08-11  6:03 [PATCH for-9.2 0/4] target/m68k: Implement fmove.p Richard Henderson
  2024-08-11  6:03 ` [PATCH 1/4] target/m68k: Introduce M68K_FEATURE_FPU_PACKED_DECIMAL Richard Henderson
  2024-08-11  6:03 ` [PATCH 2/4] target/m68k: Implement packed decimal real loads Richard Henderson
@ 2024-08-11  6:03 ` Richard Henderson
  2024-08-11  6:03 ` [PATCH 4/4] tests/tcg/m68k: Add packed decimal tests Richard Henderson
  3 siblings, 0 replies; 5+ messages in thread
From: Richard Henderson @ 2024-08-11  6:03 UTC (permalink / raw)
  To: qemu-devel; +Cc: laurent

Resolves: https://gitlab.com/qemu-project/qemu/-/issues/2488
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 target/m68k/helper.h     |   1 +
 target/m68k/fpu_helper.c | 100 +++++++++++++++++++++++++++++++++++++++
 target/m68k/translate.c  |  27 +++++++++--
 3 files changed, 125 insertions(+), 3 deletions(-)

diff --git a/target/m68k/helper.h b/target/m68k/helper.h
index 2c71361451..21af6adb39 100644
--- a/target/m68k/helper.h
+++ b/target/m68k/helper.h
@@ -127,6 +127,7 @@ DEF_HELPER_3(chk, void, env, s32, s32)
 DEF_HELPER_4(chk2, void, env, s32, s32, s32)
 
 DEF_HELPER_FLAGS_3(load_pdr_to_fx80, TCG_CALL_NO_RWG, void, env, fp, tl)
+DEF_HELPER_FLAGS_4(store_fx80_to_pdr, TCG_CALL_NO_RWG, void, env, tl, fp, int)
 
 #if !defined(CONFIG_USER_ONLY)
 DEF_HELPER_3(ptest, void, env, i32, i32)
diff --git a/target/m68k/fpu_helper.c b/target/m68k/fpu_helper.c
index dd80943153..6f37a165e2 100644
--- a/target/m68k/fpu_helper.c
+++ b/target/m68k/fpu_helper.c
@@ -886,3 +886,103 @@ void HELPER(load_pdr_to_fx80)(CPUM68KState *env, FPReg *res, target_ulong addr)
         res->d = floatx80_div(res->d, fexp, &env->fp_status);
     }
 }
+
+static floatx80 floatx80_scale10i(floatx80 x, int e, float_status *status)
+{
+    floatx80 t;
+    if (e >= 0) {
+        t = floatx80_exp10i(e, status);
+        t = floatx80_mul(x, t, status);
+    } else {
+        t = floatx80_exp10i(-e, status);
+        t = floatx80_div(x, t, status);
+    }
+    return t;
+}
+
+void HELPER(store_fx80_to_pdr)(CPUM68KState *env, target_ulong addr,
+                               FPReg *srcp, int kfactor)
+{
+    floatx80 t, x = srcp->d;
+    int len, exp2, exp10;
+    uint64_t res_lo;
+    uint32_t res_hi;
+    int64_t y;
+
+    res_lo = x.low;
+    exp2 = x.high & 0x7fff;
+    if (unlikely(exp2 == 0x7fff)) {
+        /* NaN and Inf */
+        res_hi = (uint32_t)x.high << 16;
+        goto done;
+    }
+
+    /* Copy the sign bit to the output, and then x = abs(x). */
+    res_hi = (x.high & 0x8000u) << 16;
+    x.high &= 0x7fff;
+
+    if (exp2 == 0) {
+        if (res_lo == 0) {
+            /* +/- 0 */
+            goto done;
+        }
+        /* denormal */
+        exp2 = -0x3fff - clz64(res_lo);
+    } else {
+        exp2 -= 0x3fff;
+    }
+
+    /*
+     * Begin with an approximation of log2(x) via the base 2 exponent.
+     * Adjust, so that we compute the value scaled by 10**17, which will
+     * allows an integer to be extracted to match the output digits.
+     */
+    exp10 = (exp2 * 30102) / 100000;
+    while (1) {
+        /* kfactor controls the number of output digits */
+        if (kfactor <= 0) {
+            /* kfactor is number of digits right of the decimal point. */
+            len = exp10 - kfactor;
+        } else {
+            /* kfactor is number of significant digits */
+            len = kfactor;
+        }
+        len = MIN(MAX(len, 1), 17);
+
+        /*
+         * Scale, so that we have the requested number of digits
+         * left of the decimal point.  Convert to integer, which
+         * handles the rounding (and may force adjustment of exp10).
+         */
+        t = floatx80_scale10i(x, len - 1 - exp10, &env->fp_status);
+        y = floatx80_to_int64(t, &env->fp_status);
+        if (y < i64_pow10[len - 1]) {
+            exp10--;
+        } else if (y < i64_pow10[len]) {
+            break;
+        } else {
+            exp10++;
+        }
+    }
+
+    /* Output the mantissa. */
+    res_hi |= y / i64_pow10[len - 1];
+    res_lo = 0;
+    for (int i = 1; i < len; ++i) {
+        int64_t d = (y / i64_pow10[len - 1 - i]) % 10;
+        res_lo |= d << (64 - i * 4);
+    }
+
+    /* Output the exponent. */
+    if (exp10 < 0) {
+        res_hi |= 0x40000000;
+        exp10 = -exp10;
+    }
+    for (int i = 24; exp10; i -= 4, exp10 /= 10) {
+        res_hi |= (exp10 % 10) << i;
+    }
+
+ done:
+    cpu_stl_be_data_ra(env, addr, res_hi, GETPC());
+    cpu_stq_be_data_ra(env, addr + 4, res_lo, GETPC());
+}
diff --git a/target/m68k/translate.c b/target/m68k/translate.c
index 59e7d27393..fb5ecce0c3 100644
--- a/target/m68k/translate.c
+++ b/target/m68k/translate.c
@@ -119,6 +119,8 @@ typedef struct DisasContext {
     int done_mac;
     int writeback_mask;
     TCGv writeback[8];
+    uint16_t insn;
+    uint16_t ext;
     bool ss_active;
 } DisasContext;
 
@@ -671,6 +673,7 @@ static inline int ext_opsize(int ext, int pos)
     case 4: return OS_WORD;
     case 5: return OS_DOUBLE;
     case 6: return OS_BYTE;
+    case 7: return OS_PACKED; /* store, dynamic k-factor */
     default:
         g_assert_not_reached();
     }
@@ -1010,11 +1013,25 @@ static void gen_store_fp(DisasContext *s, int opsize, TCGv addr, TCGv_ptr fp,
         tcg_gen_qemu_st_i64(t64, tmp, index, MO_TEUQ);
         break;
     case OS_PACKED:
+        if (!m68k_feature(s->env, M68K_FEATURE_FPU_PACKED_DECIMAL)) {
+            gen_exception(s, s->base.pc_next, EXCP_FP_UNIMP);
+            break;
+        }
         /*
-         * unimplemented data type on 68040/ColdFire
-         * FIXME if needed for another FPU
+         * For stores we must recover k-factor, either from an
+         * immediate or the low 7 bits of a D register.
          */
-        gen_exception(s, s->base.pc_next, EXCP_FP_UNIMP);
+        switch ((s->ext >> 10) & 7) {
+        case 3:
+            tcg_gen_movi_i32(tmp, sextract32(s->ext, 0, 7));
+            break;
+        case 7:
+            tcg_gen_sextract_i32(tmp, DREG(s->ext, 4), 0, 7);
+            break;
+        default:
+            g_assert_not_reached();
+        }
+        gen_helper_store_fx80_to_pdr(tcg_env, addr, fp, tmp);
         break;
     default:
         g_assert_not_reached();
@@ -4940,6 +4957,8 @@ DISAS_INSN(fpu)
     TCGv_ptr cpu_src, cpu_dest;
 
     ext = read_im16(env, s);
+    s->ext = ext;
+
     opmode = ext & 0x7f;
     switch ((ext >> 13) & 7) {
     case 0:
@@ -6042,6 +6061,8 @@ static void m68k_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
     CPUM68KState *env = cpu_env(cpu);
     uint16_t insn = read_im16(env, dc);
 
+    dc->insn = insn;
+    dc->ext = 0;
     opcode_table[insn](env, dc, insn);
     do_writebacks(dc);
 
-- 
2.43.0



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

* [PATCH 4/4] tests/tcg/m68k: Add packed decimal tests
  2024-08-11  6:03 [PATCH for-9.2 0/4] target/m68k: Implement fmove.p Richard Henderson
                   ` (2 preceding siblings ...)
  2024-08-11  6:03 ` [PATCH 3/4] target/m68k: Implement packed decimal real stores Richard Henderson
@ 2024-08-11  6:03 ` Richard Henderson
  3 siblings, 0 replies; 5+ messages in thread
From: Richard Henderson @ 2024-08-11  6:03 UTC (permalink / raw)
  To: qemu-devel; +Cc: laurent

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 tests/tcg/m68k/packeddecimal-1.c | 45 ++++++++++++++++++++++++++++++++
 tests/tcg/m68k/packeddecimal-2.c | 42 +++++++++++++++++++++++++++++
 tests/tcg/m68k/Makefile.target   |  2 +-
 3 files changed, 88 insertions(+), 1 deletion(-)
 create mode 100644 tests/tcg/m68k/packeddecimal-1.c
 create mode 100644 tests/tcg/m68k/packeddecimal-2.c

diff --git a/tests/tcg/m68k/packeddecimal-1.c b/tests/tcg/m68k/packeddecimal-1.c
new file mode 100644
index 0000000000..812307402a
--- /dev/null
+++ b/tests/tcg/m68k/packeddecimal-1.c
@@ -0,0 +1,45 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/* Test packed decimal real conversion to long double. */
+
+#include <stdio.h>
+
+struct T {
+    unsigned int d[3];
+    double f;
+};
+
+static const struct T tests[] = {
+    { { 0x00000001, 0x00000000, 0x00000000 }, 1.0e0l },
+    { { 0x01000001, 0x00000000, 0x00000000 }, 1.0e1l },
+    { { 0x00100001, 0x00000000, 0x00000000 }, 1.0e10l },
+    { { 0x00000000, 0x10000000, 0x00000000 }, 0.1e0l },
+    { { 0x41000001, 0x00000000, 0x00000000 }, 1.0e-1l },
+    { { 0x85000005, 0x55550000, 0x00000000 }, -5.5555e5l },
+    { { 0x09990009, 0x99999999, 0x99999999 }, 9.9999999999999999e999l },
+    { { 0x03210001, 0x23456789, 0x12345678 }, 1.2345678912345678e123l },
+    { { 0x00000000, 0x00000000, 0x00000000 }, 0.0l },
+    { { 0x80000000, 0x00000000, 0x00000000 }, -0.0l },
+    { { 0x09990000, 0x00000000, 0x00000000 }, 0.0e999l },
+};
+
+int main()
+{
+    int ret = 0;
+
+    for (int i = 0; i < sizeof(tests) / sizeof(tests[0]); i++) {
+        const struct T *t = &tests[i];
+        long double lf;
+        volatile double f;
+
+        asm("fmove.p (%1),%0" : "=f"(lf) : "a"(t->d));
+
+        /* Round to double; as yet we cannot promise perfect rounding. */
+        f = lf;
+
+        if (f != t->f) {
+            fprintf(stderr, "Mismatch at %d: %.17e != %.17e\n", i, f, t->f);
+            ret = 1;
+        }
+    }
+    return ret;
+}
diff --git a/tests/tcg/m68k/packeddecimal-2.c b/tests/tcg/m68k/packeddecimal-2.c
new file mode 100644
index 0000000000..3547dc7b84
--- /dev/null
+++ b/tests/tcg/m68k/packeddecimal-2.c
@@ -0,0 +1,42 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/* Test packed decimal real conversion from long double, dynamic k-factor */
+
+#include <stdio.h>
+
+struct T {
+    unsigned int d[3];
+    long double lf;
+    int kfactor;
+};
+
+static const struct T tests[] = {
+    { { 0x00000001, 0x00000000, 0x00000000 }, 1.0e0l, 0 },
+    { { 0x00100001, 0x00000000, 0x00000000 }, 1.0e10l, 0 },
+    { { 0x41000001, 0x00000000, 0x00000000 }, 1.0e-1l, 0 },
+    { { 0x85000005, 0x55550000, 0x00000000 }, -5.5555e5l, 5 },
+    { { 0x45000005, 0x55550000, 0x00000000 }, 5.5555e-5l, 5 },
+    { { 0x05000002, 0x22220000, 0x00000000 }, 2.2222e5, 99 },
+    { { 0x05000002, 0x22220000, 0x00000000 }, 2.2222e5, 5 },
+    { { 0x05000002, 0x20000000, 0x00000000 }, 2.2222e5, 2 },
+};
+
+int main()
+{
+    int ret = 0;
+
+    for (int i = 0; i < sizeof(tests) / sizeof(tests[0]); i++) {
+        const struct T *t = &tests[i];
+        unsigned int out[3];
+
+        asm("fmove.p %1,(%0),%2"
+            : : "a"(out), "f"(t->lf), "d"(t->kfactor) : "memory");
+
+        if (out[0] != t->d[0] || out[1] != t->d[1] || out[2] != t->d[2]) {
+            fprintf(stderr, "Mismatch at %d: %08x%08x%08x != %08x%08x%08x\n",
+                    i, out[0], out[1], out[2],
+                    t->d[0], t->d[1], t->d[2]);
+            ret = 1;
+        }
+    }
+    return ret;
+}
diff --git a/tests/tcg/m68k/Makefile.target b/tests/tcg/m68k/Makefile.target
index 33f7b1b127..7587b8f249 100644
--- a/tests/tcg/m68k/Makefile.target
+++ b/tests/tcg/m68k/Makefile.target
@@ -4,4 +4,4 @@
 #
 
 VPATH += $(SRC_PATH)/tests/tcg/m68k
-TESTS += trap denormal
+TESTS += trap denormal packeddecimal-1 packeddecimal-2
-- 
2.43.0



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

end of thread, other threads:[~2024-08-11  6:04 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-08-11  6:03 [PATCH for-9.2 0/4] target/m68k: Implement fmove.p Richard Henderson
2024-08-11  6:03 ` [PATCH 1/4] target/m68k: Introduce M68K_FEATURE_FPU_PACKED_DECIMAL Richard Henderson
2024-08-11  6:03 ` [PATCH 2/4] target/m68k: Implement packed decimal real loads Richard Henderson
2024-08-11  6:03 ` [PATCH 3/4] target/m68k: Implement packed decimal real stores Richard Henderson
2024-08-11  6:03 ` [PATCH 4/4] tests/tcg/m68k: Add packed decimal tests Richard Henderson

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).