diff options
| author | ptitSeb <sebastien.chev@gmail.com> | 2025-04-16 12:03:05 +0200 |
|---|---|---|
| committer | ptitSeb <sebastien.chev@gmail.com> | 2025-04-16 12:03:13 +0200 |
| commit | 1ba0ea157fdde73df5c9f242c6ad4db7abddeaca (patch) | |
| tree | 2e5c62cd25b0aa6f906f66d371f134198e1fcc3a /src | |
| parent | 1e64476f313bf286caac8de08104891b5956f9ac (diff) | |
| download | box64-1ba0ea157fdde73df5c9f242c6ad4db7abddeaca.tar.gz box64-1ba0ea157fdde73df5c9f242c6ad4db7abddeaca.zip | |
[INTERP] Added x87 Precision Control set to 24bits handling
Diffstat (limited to 'src')
| -rw-r--r-- | src/emu/x64rund8.c | 12 | ||||
| -rw-r--r-- | src/emu/x64rund9.c | 1 | ||||
| -rw-r--r-- | src/emu/x64runda.c | 6 | ||||
| -rw-r--r-- | src/emu/x64rundc.c | 12 | ||||
| -rw-r--r-- | src/emu/x64runde.c | 12 | ||||
| -rw-r--r-- | src/include/regs.h | 6 |
6 files changed, 49 insertions, 0 deletions
diff --git a/src/emu/x64rund8.c b/src/emu/x64rund8.c index 44413c10..fc1101f4 100644 --- a/src/emu/x64rund8.c +++ b/src/emu/x64rund8.c @@ -50,6 +50,7 @@ uintptr_t RunD8(x64emu_t *emu, rex_t rex, uintptr_t addr, uintptr_t offs) case 0xC6: case 0xC7: /* FADD */ ST0.d += ST(nextop&7).d; + if(!emu->cw.f.C87_PC) ST0.d = (float)ST0.d; break; case 0xC8: case 0xC9: @@ -60,6 +61,7 @@ uintptr_t RunD8(x64emu_t *emu, rex_t rex, uintptr_t addr, uintptr_t offs) case 0xCE: case 0xCF: /* FMUL */ ST0.d *= ST(nextop&7).d; + if(!emu->cw.f.C87_PC) ST0.d = (float)ST0.d; break; case 0xD0: case 0xD1: @@ -91,6 +93,7 @@ uintptr_t RunD8(x64emu_t *emu, rex_t rex, uintptr_t addr, uintptr_t offs) case 0xE6: case 0xE7: /* FSUB */ ST0.d -= ST(nextop&7).d; + if(!emu->cw.f.C87_PC) ST0.d = (float)ST0.d; break; case 0xE8: case 0xE9: @@ -101,6 +104,7 @@ uintptr_t RunD8(x64emu_t *emu, rex_t rex, uintptr_t addr, uintptr_t offs) case 0xEE: case 0xEF: /* FSUBR */ ST0.d = ST(nextop&7).d - ST0.d; + if(!emu->cw.f.C87_PC) ST0.d = (float)ST0.d; break; case 0xF0: case 0xF1: @@ -111,6 +115,7 @@ uintptr_t RunD8(x64emu_t *emu, rex_t rex, uintptr_t addr, uintptr_t offs) case 0xF6: case 0xF7: /* FDIV */ ST0.d /= ST(nextop&7).d; + if(!emu->cw.f.C87_PC) ST0.d = (float)ST0.d; break; case 0xF8: case 0xF9: @@ -121,6 +126,7 @@ uintptr_t RunD8(x64emu_t *emu, rex_t rex, uintptr_t addr, uintptr_t offs) case 0xFE: case 0xFF: /* FDIVR */ ST0.d = ST(nextop&7).d / ST0.d; + if(!emu->cw.f.C87_PC) ST0.d = (float)ST0.d; break; default: fesetround(oldround); @@ -134,6 +140,7 @@ uintptr_t RunD8(x64emu_t *emu, rex_t rex, uintptr_t addr, uintptr_t offs) GETE4(0); } ST0.d += *(float*)ED; + if(!emu->cw.f.C87_PC) ST0.d = (float)ST0.d; break; case 1: /* FMUL ST0, float */ if(offs) { @@ -142,6 +149,7 @@ uintptr_t RunD8(x64emu_t *emu, rex_t rex, uintptr_t addr, uintptr_t offs) GETE4(0); } ST0.d *= *(float*)ED; + if(!emu->cw.f.C87_PC) ST0.d = (float)ST0.d; break; case 2: /* FCOM ST0, float */ if(offs) { @@ -167,6 +175,7 @@ uintptr_t RunD8(x64emu_t *emu, rex_t rex, uintptr_t addr, uintptr_t offs) GETE4(0); } ST0.d -= *(float*)ED; + if(!emu->cw.f.C87_PC) ST0.d = (float)ST0.d; break; case 5: /* FSUBR ST0, float */ if(offs) { @@ -175,6 +184,7 @@ uintptr_t RunD8(x64emu_t *emu, rex_t rex, uintptr_t addr, uintptr_t offs) GETE4(0); } ST0.d = *(float*)ED - ST0.d; + if(!emu->cw.f.C87_PC) ST0.d = (float)ST0.d; break; case 6: /* FDIV ST0, float */ if(offs) { @@ -183,6 +193,7 @@ uintptr_t RunD8(x64emu_t *emu, rex_t rex, uintptr_t addr, uintptr_t offs) GETE4(0); } ST0.d /= *(float*)ED; + if(!emu->cw.f.C87_PC) ST0.d = (float)ST0.d; break; case 7: /* FDIVR ST0, float */ if(offs) { @@ -191,6 +202,7 @@ uintptr_t RunD8(x64emu_t *emu, rex_t rex, uintptr_t addr, uintptr_t offs) GETE4(0); } ST0.d = *(float*)ED / ST0.d; + if(!emu->cw.f.C87_PC) ST0.d = (float)ST0.d; break; default: fesetround(oldround); diff --git a/src/emu/x64rund9.c b/src/emu/x64rund9.c index a4f6cc2b..1f4366f5 100644 --- a/src/emu/x64rund9.c +++ b/src/emu/x64rund9.c @@ -230,6 +230,7 @@ uintptr_t RunD9(x64emu_t *emu, rex_t rex, uintptr_t addr, uintptr_t offs) case 0xFA: /* FSQRT */ oldround = fpu_setround(emu); ST0.d = sqrt(ST0.d); + if(!emu->cw.f.C87_PC) ST0.d = (float)ST0.d; fesetround(oldround); break; case 0xFB: /* FSINCOS */ diff --git a/src/emu/x64runda.c b/src/emu/x64runda.c index f8a1b70e..59278b15 100644 --- a/src/emu/x64runda.c +++ b/src/emu/x64runda.c @@ -101,10 +101,12 @@ uintptr_t RunDA(x64emu_t *emu, rex_t rex, uintptr_t addr) case 0: /* FIADD ST0, Ed int */ GETE4(0); ST0.d += ED->sdword[0]; + if(!emu->cw.f.C87_PC) ST0.d = (float)ST0.d; break; case 1: /* FIMUL ST0, Ed int */ GETE4(0); ST0.d *= ED->sdword[0]; + if(!emu->cw.f.C87_PC) ST0.d = (float)ST0.d; break; case 2: /* FICOM ST0, Ed int */ GETE4(0); @@ -118,18 +120,22 @@ uintptr_t RunDA(x64emu_t *emu, rex_t rex, uintptr_t addr) case 4: /* FISUB ST0, Ed int */ GETE4(0); ST0.d -= ED->sdword[0]; + if(!emu->cw.f.C87_PC) ST0.d = (float)ST0.d; break; case 5: /* FISUBR ST0, Ed int */ GETE4(0); ST0.d = (double)ED->sdword[0] - ST0.d; + if(!emu->cw.f.C87_PC) ST0.d = (float)ST0.d; break; case 6: /* FIDIV ST0, Ed int */ GETE4(0); ST0.d /= ED->sdword[0]; + if(!emu->cw.f.C87_PC) ST0.d = (float)ST0.d; break; case 7: /* FIDIVR ST0, Ed int */ GETE4(0); ST0.d = (double)ED->sdword[0] / ST0.d; + if(!emu->cw.f.C87_PC) ST0.d = (float)ST0.d; break; } fesetround(oldround); diff --git a/src/emu/x64rundc.c b/src/emu/x64rundc.c index 00775698..99b12c76 100644 --- a/src/emu/x64rundc.c +++ b/src/emu/x64rundc.c @@ -47,6 +47,7 @@ uintptr_t RunDC(x64emu_t *emu, rex_t rex, uintptr_t addr) case 0xC6: case 0xC7: /* FADD */ ST(nextop&7).d += ST0.d; + if(!emu->cw.f.C87_PC) ST(nextop&7).d = (float)ST(nextop&7).d; break; case 0xC8: case 0xC9: @@ -57,6 +58,7 @@ uintptr_t RunDC(x64emu_t *emu, rex_t rex, uintptr_t addr) case 0xCE: case 0xCF: /* FMUL */ ST(nextop&7).d *= ST0.d; + if(!emu->cw.f.C87_PC) ST(nextop&7).d = (float)ST(nextop&7).d; break; case 0xD0: case 0xD1: @@ -88,6 +90,7 @@ uintptr_t RunDC(x64emu_t *emu, rex_t rex, uintptr_t addr) case 0xE6: case 0xE7: /* FSUBR */ ST(nextop&7).d = ST0.d -ST(nextop&7).d; + if(!emu->cw.f.C87_PC) ST(nextop&7).d = (float)ST(nextop&7).d; break; case 0xE8: case 0xE9: @@ -98,6 +101,7 @@ uintptr_t RunDC(x64emu_t *emu, rex_t rex, uintptr_t addr) case 0xEE: case 0xEF: /* FSUB */ ST(nextop&7).d -= ST0.d; + if(!emu->cw.f.C87_PC) ST(nextop&7).d = (float)ST(nextop&7).d; break; case 0xF0: case 0xF1: @@ -108,6 +112,7 @@ uintptr_t RunDC(x64emu_t *emu, rex_t rex, uintptr_t addr) case 0xF6: case 0xF7: /* FDIVR */ ST(nextop&7).d = ST0.d / ST(nextop&7).d; + if(!emu->cw.f.C87_PC) ST(nextop&7).d = (float)ST(nextop&7).d; break; case 0xF8: case 0xF9: @@ -118,6 +123,7 @@ uintptr_t RunDC(x64emu_t *emu, rex_t rex, uintptr_t addr) case 0xFE: case 0xFF: /* FDIV */ ST(nextop&7).d /= ST0.d; + if(!emu->cw.f.C87_PC) ST(nextop&7).d = (float)ST(nextop&7).d; break; default: fesetround(oldround); @@ -127,9 +133,11 @@ uintptr_t RunDC(x64emu_t *emu, rex_t rex, uintptr_t addr) switch((nextop>>3)&7) { case 0: /* FADD ST0, double */ ST0.d += *(double*)ED; + if(!emu->cw.f.C87_PC) ST0.d = (float)ST0.d; break; case 1: /* FMUL ST0, double */ ST0.d *= *(double*)ED; + if(!emu->cw.f.C87_PC) ST0.d = (float)ST0.d; break; case 2: /* FCOM ST0, double */ fpu_fcom(emu, *(double*)ED); @@ -140,15 +148,19 @@ uintptr_t RunDC(x64emu_t *emu, rex_t rex, uintptr_t addr) break; case 4: /* FSUB ST0, double */ ST0.d -= *(double*)ED; + if(!emu->cw.f.C87_PC) ST0.d = (float)ST0.d; break; case 5: /* FSUBR ST0, double */ ST0.d = *(double*)ED - ST0.d; + if(!emu->cw.f.C87_PC) ST0.d = (float)ST0.d; break; case 6: /* FDIV ST0, double */ ST0.d /= *(double*)ED; + if(!emu->cw.f.C87_PC) ST0.d = (float)ST0.d; break; case 7: /* FDIVR ST0, double */ ST0.d = *(double*)ED / ST0.d; + if(!emu->cw.f.C87_PC) ST0.d = (float)ST0.d; break; default: fesetround(oldround); diff --git a/src/emu/x64runde.c b/src/emu/x64runde.c index 782edcc7..8c5a444b 100644 --- a/src/emu/x64runde.c +++ b/src/emu/x64runde.c @@ -48,6 +48,7 @@ uintptr_t RunDE(x64emu_t *emu, rex_t rex, uintptr_t addr) case 0xC6: case 0xC7: ST(nextop&7).d += ST0.d; + if(!emu->cw.f.C87_PC) ST(nextop&7).d = (float)ST(nextop&7).d; fpu_do_pop(emu); break; case 0xC8: /* FMULP STx, ST0 */ @@ -59,6 +60,7 @@ uintptr_t RunDE(x64emu_t *emu, rex_t rex, uintptr_t addr) case 0xCE: case 0xCF: ST(nextop&7).d *= ST0.d; + if(!emu->cw.f.C87_PC) ST(nextop&7).d = (float)ST(nextop&7).d; fpu_do_pop(emu); break; case 0xD0: @@ -91,6 +93,7 @@ uintptr_t RunDE(x64emu_t *emu, rex_t rex, uintptr_t addr) case 0xE6: case 0xE7: ST(nextop&7).d = ST0.d - ST(nextop&7).d; + if(!emu->cw.f.C87_PC) ST(nextop&7).d = (float)ST(nextop&7).d; fpu_do_pop(emu); break; case 0xE8: /* FSUBP STx, ST0 */ @@ -102,6 +105,7 @@ uintptr_t RunDE(x64emu_t *emu, rex_t rex, uintptr_t addr) case 0xEE: case 0xEF: ST(nextop&7).d -= ST0.d; + if(!emu->cw.f.C87_PC) ST(nextop&7).d = (float)ST(nextop&7).d; fpu_do_pop(emu); break; case 0xF0: /* FDIVRP STx, ST0 */ @@ -113,6 +117,7 @@ uintptr_t RunDE(x64emu_t *emu, rex_t rex, uintptr_t addr) case 0xF6: case 0xF7: ST(nextop&7).d = ST0.d / ST(nextop&7).d; + if(!emu->cw.f.C87_PC) ST(nextop&7).d = (float)ST(nextop&7).d; fpu_do_pop(emu); break; case 0xF8: /* FDIVP STx, ST0 */ @@ -124,6 +129,7 @@ uintptr_t RunDE(x64emu_t *emu, rex_t rex, uintptr_t addr) case 0xFE: case 0xFF: ST(nextop&7).d /= ST0.d; + if(!emu->cw.f.C87_PC) ST(nextop&7).d = (float)ST(nextop&7).d; fpu_do_pop(emu); break; @@ -135,26 +141,32 @@ uintptr_t RunDE(x64emu_t *emu, rex_t rex, uintptr_t addr) case 0: /* FIADD ST0, Ew int */ GETEW(0); ST0.d += EW->sword[0]; + if(!emu->cw.f.C87_PC) ST0.d = (float)ST0.d; break; case 1: /* FIMUL ST0, Ew int */ GETEW(0); ST0.d *= EW->sword[0]; + if(!emu->cw.f.C87_PC) ST0.d = (float)ST0.d; break; case 4: /* FISUB ST0, Ew int */ GETEW(0); ST0.d -= EW->sword[0]; + if(!emu->cw.f.C87_PC) ST0.d = (float)ST0.d; break; case 5: /* FISUBR ST0, Ew int */ GETEW(0); ST0.d = (double)EW->sword[0] - ST0.d; + if(!emu->cw.f.C87_PC) ST0.d = (float)ST0.d; break; case 6: /* FIDIV ST0, Ew int */ GETEW(0); ST0.d /= EW->sword[0]; + if(!emu->cw.f.C87_PC) ST0.d = (float)ST0.d; break; case 7: /* FIDIVR ST0, Ew int */ GETEW(0); ST0.d = (double)EW->sword[0] / ST0.d; + if(!emu->cw.f.C87_PC) ST0.d = (float)ST0.d; break; default: fesetround(oldround); diff --git a/src/include/regs.h b/src/include/regs.h index 58070c8a..d83fbcbd 100644 --- a/src/include/regs.h +++ b/src/include/regs.h @@ -245,6 +245,12 @@ typedef union { } f; uint16_t x16; } x87control_t; +/* +Precision Controls: 00b = 24bits, 01b=reserved, 10b=53bits and 11b=64bits +The precision-control bits only affect the results of the following floating-point instructions: FADD, FADDP, FIADD, +FSUB, FSUBP, FISUB, FSUBR, FSUBRP, FISUBR, FMUL, FMULP, FIMUL, FDIV, FDIVP, FIDIV, FDIVR, FDIVRP, FIDIVR, +and FSQRT. +*/ typedef union { struct __attribute__ ((__packed__)) { |