diff --git a/emu/decode.h b/emu/decode.h index 7242766fe8..7016e13111 100644 --- a/emu/decode.h +++ b/emu/decode.h @@ -725,6 +725,7 @@ __no_instrument DECODER_RET glue(DECODER_NAME, OP_SIZE)(DECODER_ARGS) { case 0xd960: TRACE("f2xm1"); F2XM1(); break; case 0xd961: TRACE("fyl2x"); FYL2X(); break; case 0xd963: TRACE("fpatan"); FPATAN(); break; + case 0xd964: TRACE("fxtract"); FXTRACT(); break; case 0xd967: TRACE("fincstp"); FINCSTP(); break; case 0xd970: TRACE("fprem"); FPREM(); break; case 0xd972: TRACE("fsqrt"); FSQRT(); break; diff --git a/emu/float80.c b/emu/float80.c index d159b63285..44675a06a2 100644 --- a/emu/float80.c +++ b/emu/float80.c @@ -515,3 +515,9 @@ float80 f80_scale(float80 x, int scale) { return F80_NAN; return u128_normalize_round((uint128_t) x.signif << 64, unbias(x.exp) + scale, x.sign); } + +void f80_xtract(float80 f, int *exp, float80 *signif) { + *exp = unbias(f.exp); + *signif = f; + signif->exp = bias(0); +} diff --git a/emu/float80.h b/emu/float80.h index 2f0018a82b..f825bbc8f5 100644 --- a/emu/float80.h +++ b/emu/float80.h @@ -45,6 +45,9 @@ float80 f80_sqrt(float80 x); float80 f80_scale(float80 x, int scale); +// Used to implement fxtract +void f80_xtract(float80 f, int *exp, float80 *signif); + enum f80_rounding_mode { round_to_nearest = 0, round_down = 1, diff --git a/emu/fpu.c b/emu/fpu.c index 18f5f6a526..00a18a6115 100644 --- a/emu/fpu.c +++ b/emu/fpu.c @@ -274,6 +274,14 @@ void fpu_cos(struct cpu_state *cpu) { ST(0) = f80_from_double(cos(f80_to_double(ST(0)))); } +void fpu_xtract(struct cpu_state *cpu) { + int exp; + float80 signif; + f80_xtract(ST(0), &exp, &signif); + ST(0) = f80_from_int(exp); + fpush(signif); +} + void fpu_xam(struct cpu_state *cpu) { float80 f = ST(0); int outflags = 0; diff --git a/emu/fpu.h b/emu/fpu.h index 4abdbc123b..ddaedc4660 100644 --- a/emu/fpu.h +++ b/emu/fpu.h @@ -102,6 +102,7 @@ void fpu_patan(struct cpu_state *cpu); void fpu_sin(struct cpu_state *cpu); void fpu_cos(struct cpu_state *cpu); void fpu_xam(struct cpu_state *cpu); +void fpu_xtract(struct cpu_state *cpu); void fpu_stcw16(struct cpu_state *cpu, uint16_t *i); void fpu_ldcw16(struct cpu_state *cpu, uint16_t *i); diff --git a/jit/gen.c b/jit/gen.c index 8d10af1ca7..3d17765ccd 100644 --- a/jit/gen.c +++ b/jit/gen.c @@ -423,6 +423,7 @@ void helper_rdtsc(struct cpu_state *cpu); #define FPATAN() h(fpu_patan) #define FSIN() h(fpu_sin) #define FCOS() h(fpu_cos) +#define FXTRACT() h(fpu_xtract) // vector