diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/emu/x64run0f.c | 28 | ||||
| -rw-r--r-- | src/emu/x64run660f.c | 19 | ||||
| -rw-r--r-- | src/emu/x64runf20f.c | 28 |
3 files changed, 75 insertions, 0 deletions
diff --git a/src/emu/x64run0f.c b/src/emu/x64run0f.c index e48c0eb6..ec055fb2 100644 --- a/src/emu/x64run0f.c +++ b/src/emu/x64run0f.c @@ -34,6 +34,7 @@ int Run0F(x64emu_t *emu, rex_t rex) uint8_t tmp8u; int32_t tmp32s, tmp32s2; uint32_t tmp32u; + uint64_t tmp64u; reg64_t *oped, *opgd; sse_regs_t *opex, *opgx; mmx87_regs_t *opem, *opgm; @@ -595,6 +596,33 @@ int Run0F(x64emu_t *emu, rex_t rex) } break; + case 0xBD: /* BSR Ed,Gd */ + CHECK_FLAGS(emu); + nextop = F8; + GETED(0); + GETGD; + if(rex.w) { + tmp64u = ED->q[0]; + if(tmp64u) { + CLEAR_FLAG(F_ZF); + tmp8u = 63; + while(!(tmp64u&(1L<<tmp8u))) --tmp8u; + GD->q[0] = tmp8u; + } else { + SET_FLAG(F_ZF); + } + } else { + tmp32u = ED->dword[0]; + if(tmp32u) { + CLEAR_FLAG(F_ZF); + tmp8u = 31; + while(!(tmp32u&(1<<tmp8u))) --tmp8u; + GD->q[0] = tmp8u; + } else { + SET_FLAG(F_ZF); + } + } + break; case 0xBE: /* MOVSX Gd,Eb */ nextop = F8; GETEB(0); diff --git a/src/emu/x64run660f.c b/src/emu/x64run660f.c index 3d1939ca..660ac028 100644 --- a/src/emu/x64run660f.c +++ b/src/emu/x64run660f.c @@ -123,6 +123,15 @@ int Run660F(x64emu_t *emu, rex_t rex) CLEAR_FLAG(F_OF); CLEAR_FLAG(F_AF); CLEAR_FLAG(F_SF); break; + GOCOND(0x40 + , nextop = F8; + CHECK_FLAGS(emu); + GETEW(0); + GETGW; + , if(rex.w) GW->q[0] = EW->q[0]; else GW->word[0] = EW->word[0]; + , + ) /* 0x40 -> 0x4F CMOVxx Gw,Ew */ // conditional move, no sign + case 0x54: /* ANDPD Gx, Ex */ nextop = F8; GETEX(0); @@ -377,6 +386,16 @@ int Run660F(x64emu_t *emu, rex_t rex) EX->q[1] = GX->q[1]; break; + case 0xBE: /* MOVSX Gw,Eb */ + nextop = F8; + GETEB(0); + GETGW; + if(rex.w) + GW->sq[0] = EB->sbyte[0]; + else + GW->sword[0] = EB->sbyte[0]; + break; + case 0xD6: /* MOVQ Ex,Gx */ nextop = F8; GETEX(0); diff --git a/src/emu/x64runf20f.c b/src/emu/x64runf20f.c index a45a23d9..cd50f6f6 100644 --- a/src/emu/x64runf20f.c +++ b/src/emu/x64runf20f.c @@ -30,6 +30,9 @@ int RunF20F(x64emu_t *emu, rex_t rex) { uint8_t opcode; uint8_t nextop; + int8_t tmp8s; + uint8_t tmp8u; + int32_t tmp32s; reg64_t *oped, *opgd; sse_regs_t *opex, *opgx; @@ -120,6 +123,31 @@ int RunF20F(x64emu_t *emu, rex_t rex) GX->d[0] = EX->d[0]; break; + GOCOND(0x80 + , tmp32s = F32S; CHECK_FLAGS(emu); + , R_RIP += tmp32s; + , + ) /* 0x80 -> 0x8F Jxx */ + + case 0xC2: /* CMPSD Gx, Ex, Ib */ + nextop = F8; + GETEX(0); + GETGX; + tmp8u = F8; + tmp8s = 0; + switch(tmp8u&7) { + case 0: tmp8s=(GX->d[0] == EX->d[0]); break; + case 1: tmp8s=isless(GX->d[0], EX->d[0]); break; + case 2: tmp8s=islessequal(GX->d[0], EX->d[0]); break; + case 3: tmp8s=isnan(GX->d[0]) || isnan(EX->d[0]); break; + case 4: tmp8s=(GX->d[0] != EX->d[0]); break; + case 5: tmp8s=isnan(GX->d[0]) || isnan(EX->d[0]) || isgreaterequal(GX->d[0], EX->d[0]); break; + case 6: tmp8s=isnan(GX->d[0]) || isnan(EX->d[0]) || isgreater(GX->d[0], EX->d[0]); break; + case 7: tmp8s=!isnan(GX->d[0]) && !isnan(EX->d[0]); break; + } + GX->q[0]=(tmp8s)?0xffffffffffffffffLL:0LL; + break; + default: return 1; } |