diff --git a/target/ppc/fpu_helper.c b/target/ppc/fpu_helper.c index cb82e6e842..aedf5d1e3b 100644 --- a/target/ppc/fpu_helper.c +++ b/target/ppc/fpu_helper.c @@ -52,10 +52,15 @@ static inline bool fp_exceptions_enabled(CPUPPCState *env) * This is the non-arithmatic conversion that happens e.g. on loads. * In the Power ISA pseudocode, this is called DOUBLE. */ -uint64_t helper_todouble(uint32_t arg) +uint64_t helper_todouble(CPUPPCState *env, uint32_t arg) { uint32_t abs_arg = arg & 0x7fffffff; uint64_t ret; + CPU_FloatU f; + CPU_DoubleU d; + + f.l = arg; + d.d = float32_to_float64(f.f, &env->fp_status); if (likely(abs_arg >= 0x00800000)) { /* Normalized operand, or Inf, or NaN. */ @@ -73,6 +78,13 @@ uint64_t helper_todouble(uint32_t arg) ret |= abs_arg << (shift + 29); } } + + if (d.ll != ret) { + printf("helper_todouble diff for arg: %x d.ll: %lx ret: %lx\n", arg, d.ll, ret); + // Uncommenting this allows MacOS to run + //ret = d.ll; + } + return ret; } @@ -80,10 +92,15 @@ uint64_t helper_todouble(uint32_t arg) * This is the non-arithmatic conversion that happens e.g. on stores. * In the Power ISA pseudocode, this is called SINGLE. */ -uint32_t helper_tosingle(uint64_t arg) +uint32_t helper_tosingle(CPUPPCState *env, uint64_t arg) { int exp = extract64(arg, 52, 11); uint32_t ret; + CPU_FloatU f; + CPU_DoubleU d; + + d.ll = arg; + f.f = float64_to_float32(d.d, &env->fp_status); if (likely(exp > 896)) { /* No denormalization required (includes Inf, NaN). */ @@ -101,6 +118,11 @@ uint32_t helper_tosingle(uint64_t arg) ret |= ((1ULL << 52) | extract64(arg, 0, 52)) >> (896 + 30 - exp); } } + + if (f.l != ret) { + printf("helper_tosingle diff for arg: %lx f.l: %x ret: %x\n", arg, f.l, ret); + } + return ret; } diff --git a/target/ppc/helper.h b/target/ppc/helper.h index ef64248bc4..94b5f4fd8c 100644 --- a/target/ppc/helper.h +++ b/target/ppc/helper.h @@ -61,8 +61,8 @@ DEF_HELPER_2(compute_fprf_float64, void, env, i64) DEF_HELPER_3(store_fpscr, void, env, i64, i32) DEF_HELPER_2(fpscr_clrbit, void, env, i32) DEF_HELPER_2(fpscr_setbit, void, env, i32) -DEF_HELPER_FLAGS_1(todouble, TCG_CALL_NO_RWG_SE, i64, i32) -DEF_HELPER_FLAGS_1(tosingle, TCG_CALL_NO_RWG_SE, i32, i64) +DEF_HELPER_FLAGS_2(todouble, TCG_CALL_NO_RWG_SE, i64, env, i32) +DEF_HELPER_FLAGS_2(tosingle, TCG_CALL_NO_RWG_SE, i32, env, i64) DEF_HELPER_4(fcmpo, void, env, i64, i64, i32) DEF_HELPER_4(fcmpu, void, env, i64, i64, i32) diff --git a/target/ppc/translate/fp-impl.inc.c b/target/ppc/translate/fp-impl.inc.c index a6f522b85c..16ecca3048 100644 --- a/target/ppc/translate/fp-impl.inc.c +++ b/target/ppc/translate/fp-impl.inc.c @@ -664,7 +664,7 @@ static void gen_qemu_ld32fs(DisasContext *ctx, TCGv_i64 dest, TCGv addr) { TCGv_i32 tmp = tcg_temp_new_i32(); tcg_gen_qemu_ld_i32(tmp, addr, ctx->mem_idx, DEF_MEMOP(MO_UL)); - gen_helper_todouble(dest, tmp); + gen_helper_todouble(dest, cpu_env, tmp); tcg_temp_free_i32(tmp); } @@ -836,7 +836,7 @@ GEN_STXF(name, stop, 0x17, op | 0x00, type) static void gen_qemu_st32fs(DisasContext *ctx, TCGv_i64 src, TCGv addr) { TCGv_i32 tmp = tcg_temp_new_i32(); - gen_helper_tosingle(tmp, src); + gen_helper_tosingle(tmp, cpu_env, src); tcg_gen_qemu_st_i32(tmp, addr, ctx->mem_idx, DEF_MEMOP(MO_UL)); tcg_temp_free_i32(tmp); }