diff --git a/src/emu/modrm.h b/src/emu/modrm.h index cd2c3636a..bbad2e81b 100644 --- a/src/emu/modrm.h +++ b/src/emu/modrm.h @@ -10,6 +10,8 @@ #define F64 *(uint64_t*)(addr+=8, addr-8) #define F64S *(int64_t*)(addr+=8, addr-8) #define PK(a) *(uint8_t*)(addr+a) +#define PARITY(x) (((emu->x64emu_parity_tab[(x) / 32] >> ((x) % 32)) & 1) == 0) + #ifdef DYNAREC #define STEP CheckExec(emu, addr); if(step && !ACCESS_FLAG(F_TF)) return 0; #define STEP2 CheckExec(emu, addr); if(step && !ACCESS_FLAG(F_TF)) {R_RIP = addr; return 0;} diff --git a/src/emu/x64run0f.c b/src/emu/x64run0f.c index 61fa11f4e..bc182097c 100644 --- a/src/emu/x64run0f.c +++ b/src/emu/x64run0f.c @@ -1590,26 +1590,32 @@ uintptr_t Run0F(x64emu_t *emu, rex_t rex, uintptr_t addr, int *step) nextop = F8; GETED(0); GETGD; + tmp8u = 0; if(rex.w) { tmp64u = ED->q[0]; if(tmp64u) { CLEAR_FLAG(F_ZF); - tmp8u = 0; while(!(tmp64u&(1LL<q[0] = tmp8u; } else { SET_FLAG(F_ZF); } + GD->q[0] = tmp8u; } else { tmp32u = ED->dword[0]; if(tmp32u) { CLEAR_FLAG(F_ZF); - tmp8u = 0; while(!(tmp32u&(1<q[0] = tmp8u; } else { SET_FLAG(F_ZF); } + GD->q[0] = tmp8u; + } + if(!BOX64ENV(cputype)) { + CONDITIONAL_SET_FLAG(PARITY(tmp8u), F_PF); + CLEAR_FLAG(F_CF); + CLEAR_FLAG(F_AF); + CLEAR_FLAG(F_SF); + CLEAR_FLAG(F_OF); } break; case 0xBD: /* BSR Ed,Gd */ @@ -1617,16 +1623,17 @@ uintptr_t Run0F(x64emu_t *emu, rex_t rex, uintptr_t addr, int *step) nextop = F8; GETED(0); GETGD; + tmp8u = 0; if(rex.w) { tmp64u = ED->q[0]; if(tmp64u) { CLEAR_FLAG(F_ZF); tmp8u = 63; while(!(tmp64u&(1LL<q[0] = tmp8u; } else { SET_FLAG(F_ZF); } + GD->q[0] = tmp8u; } else { tmp32u = ED->dword[0]; if(tmp32u) { @@ -1636,8 +1643,16 @@ uintptr_t Run0F(x64emu_t *emu, rex_t rex, uintptr_t addr, int *step) GD->q[0] = tmp8u; } else { SET_FLAG(F_ZF); + GD->q[0] = tmp8u; } } + if(!BOX64ENV(cputype)) { + CONDITIONAL_SET_FLAG(PARITY(tmp8u), F_PF); + CLEAR_FLAG(F_CF); + CLEAR_FLAG(F_AF); + CLEAR_FLAG(F_SF); + CLEAR_FLAG(F_OF); + } break; case 0xBE: /* MOVSX Gd,Eb */ nextop = F8; diff --git a/src/emu/x64run660f.c b/src/emu/x64run660f.c index 001a9aa4a..8bb00f52e 100644 --- a/src/emu/x64run660f.c +++ b/src/emu/x64run660f.c @@ -2115,26 +2115,32 @@ uintptr_t Run660F(x64emu_t *emu, rex_t rex, uintptr_t addr) nextop = F8; GETEW(0); GETGW; + tmp8u = 0; if(rex.w) { tmp64u = EW->q[0]; if(tmp64u) { CLEAR_FLAG(F_ZF); - tmp8u = 0; while(!(tmp64u&(1LL<q[0] = tmp8u; } else { SET_FLAG(F_ZF); } + GW->q[0] = tmp8u; } else { tmp16u = EW->word[0]; if(tmp16u) { CLEAR_FLAG(F_ZF); - tmp8u = 0; while(!(tmp16u&(1<word[0] = tmp8u; } else { SET_FLAG(F_ZF); } + GW->word[0] = tmp8u; + } + if(!BOX64ENV(cputype)) { + CONDITIONAL_SET_FLAG(PARITY(tmp8u), F_PF); + CLEAR_FLAG(F_CF); + CLEAR_FLAG(F_AF); + CLEAR_FLAG(F_SF); + CLEAR_FLAG(F_OF); } break; case 0xBD: /* BSR Ew,Gw */ @@ -2142,26 +2148,34 @@ uintptr_t Run660F(x64emu_t *emu, rex_t rex, uintptr_t addr) nextop = F8; GETEW(0); GETGW; + tmp8u = 0; if(rex.w) { tmp64u = EW->q[0]; if(tmp64u) { CLEAR_FLAG(F_ZF); tmp8u = 63; while(!(tmp64u&(1LL<q[0] = tmp8u; } else { SET_FLAG(F_ZF); } + GW->q[0] = tmp8u; } else { tmp16u = EW->word[0]; if(tmp16u) { CLEAR_FLAG(F_ZF); tmp8u = 15; while(!(tmp16u&(1<word[0] = tmp8u; } else { SET_FLAG(F_ZF); } + GW->word[0] = tmp8u; + } + if(!BOX64ENV(cputype)) { + CONDITIONAL_SET_FLAG(PARITY(tmp8u), F_PF); + CLEAR_FLAG(F_CF); + CLEAR_FLAG(F_AF); + CLEAR_FLAG(F_SF); + CLEAR_FLAG(F_OF); } break; case 0xBE: /* MOVSX Gw,Eb */ diff --git a/src/emu/x64run66f30f.c b/src/emu/x64run66f30f.c index 9e56e94d9..00cd6ccaa 100644 --- a/src/emu/x64run66f30f.c +++ b/src/emu/x64run66f30f.c @@ -87,6 +87,11 @@ uintptr_t Run66F30F(x64emu_t *emu, rex_t rex, uintptr_t addr) GD->word[0] = 16; } } + CLEAR_FLAG(F_AF); + CLEAR_FLAG(F_SF); + CLEAR_FLAG(F_PF); + if(!BOX64ENV(cputype)) + CLEAR_FLAG(F_OF); break; case 0xBD: /* LZCNT Ed,Gd */ CHECK_FLAGS(emu); @@ -98,13 +103,19 @@ uintptr_t Run66F30F(x64emu_t *emu, rex_t rex, uintptr_t addr) tmp8u = (tmp64u)?__builtin_clzl(tmp64u):64; CONDITIONAL_SET_FLAG(tmp8u==0, F_ZF); CONDITIONAL_SET_FLAG(tmp8u==64, F_CF); + GD->q[0] = tmp8u; } else { tmp32u = EW->word[0]; tmp8u = (tmp32u)?__builtin_clz(tmp32u<<16):16; CONDITIONAL_SET_FLAG(tmp8u==0, F_ZF); CONDITIONAL_SET_FLAG(tmp8u==16, F_CF); + GD->word[0] = tmp8u; } - GD->q[0] = tmp8u; + CLEAR_FLAG(F_AF); + CLEAR_FLAG(F_SF); + CLEAR_FLAG(F_PF); + if(!BOX64ENV(cputype)) + CLEAR_FLAG(F_OF); break; case 0xB8: /* POPCNT Gd,Ed */ diff --git a/src/emu/x64runf30f.c b/src/emu/x64runf30f.c index 38ef2ad49..ea31cf011 100644 --- a/src/emu/x64runf30f.c +++ b/src/emu/x64runf30f.c @@ -388,7 +388,12 @@ uintptr_t RunF30F(x64emu_t *emu, rex_t rex, uintptr_t addr) GD->q[0] = 32; } } - break; + CLEAR_FLAG(F_AF); + CLEAR_FLAG(F_SF); + CLEAR_FLAG(F_PF); + if(!BOX64ENV(cputype)) + CLEAR_FLAG(F_OF); + break; case 0xBD: /* LZCNT Ed,Gd */ CHECK_FLAGS(emu); nextop = F8; @@ -406,6 +411,11 @@ uintptr_t RunF30F(x64emu_t *emu, rex_t rex, uintptr_t addr) CONDITIONAL_SET_FLAG(tmp8u==32, F_CF); } GD->q[0] = tmp8u; + CLEAR_FLAG(F_PF); + CLEAR_FLAG(F_AF); + CLEAR_FLAG(F_SF); + if(!BOX64ENV(cputype)) + CLEAR_FLAG(F_OF); break; case 0xC2: /* CMPSS Gx, Ex, Ib */