diff options
| author | Yang Liu <liuyang22@iscas.ac.cn> | 2023-04-05 14:26:57 +0800 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2023-04-05 08:26:57 +0200 |
| commit | 77cc2a6b8e98a2782bd9b0ea7e2b08f43e59a258 (patch) | |
| tree | 46da02e31b4d531ccc153c933587958f72bd5d45 | |
| parent | e58ff89044215e24ab74f7dbdfef57ce7e2c8ee9 (diff) | |
| download | box64-77cc2a6b8e98a2782bd9b0ea7e2b08f43e59a258.tar.gz box64-77cc2a6b8e98a2782bd9b0ea7e2b08f43e59a258.zip | |
[INTERP] Added 66 0F 2B MOVNTPD opcode & fixed some edge cases (#668)
* [INTERP] Fixed shift amount issues * [INTERP] Added 66 0F 2B MOVNTPD opcode * [INTERP] Fixed float to int convert issues
| -rw-r--r-- | src/emu/x64run660f.c | 53 | ||||
| -rw-r--r-- | src/emu/x64runf20f.c | 30 | ||||
| -rw-r--r-- | src/emu/x64runf30f.c | 13 |
3 files changed, 61 insertions, 35 deletions
diff --git a/src/emu/x64run660f.c b/src/emu/x64run660f.c index 3e164c04..f67b7738 100644 --- a/src/emu/x64run660f.c +++ b/src/emu/x64run660f.c @@ -193,7 +193,13 @@ uintptr_t Run660F(x64emu_t *emu, rex_t rex, uintptr_t addr) GX->d[0] = EM->sd[0]; GX->d[1] = EM->sd[1]; break; - + case 0x2B: /* MOVNTPD Ex, Gx */ + nextop = F8; + GETEX(0); + GETGX; + EX->q[0] = GX->q[0]; + EX->q[1] = GX->q[1]; + break; case 0x2C: /* CVTTPD2PI Gm, Ex */ nextop = F8; GETEX(0); @@ -1063,24 +1069,27 @@ uintptr_t Run660F(x64emu_t *emu, rex_t rex, uintptr_t addr) nextop = F8; GETEX(0); GETGX; - for(int i=0; i<4; ++i) - if(isnanf(EX->f[i]) || isinff(EX->f[i]) || EX->f[i]>(int32_t)0x7fffffff || EX->f[i]<(int32_t)0x80000000) - GX->sd[i] = 0x80000000; - else - switch(emu->mxcsr.f.MXCSR_RC) { - case ROUND_Nearest: - GX->sd[i] = nearbyintf(EX->f[i]); - break; - case ROUND_Down: - GX->sd[i] = floorf(EX->f[i]); - break; - case ROUND_Up: - GX->sd[i] = ceilf(EX->f[i]); - break; - case ROUND_Chop: - GX->sd[i] = EX->f[i]; - break; - } + for(int i=0; i<4; ++i) { + switch(emu->mxcsr.f.MXCSR_RC) { + case ROUND_Nearest: + tmp64s = nearbyintf(EX->f[i]); + break; + case ROUND_Down: + tmp64s = floorf(EX->f[i]); + break; + case ROUND_Up: + tmp64s = ceilf(EX->f[i]); + break; + case ROUND_Chop: + tmp64s = EX->f[i]; + break; + } + if (tmp64s==(int32_t)tmp64s) { + GX->sd[i] = (int32_t)tmp64s; + } else { + GX->sd[i] = INT32_MIN; + } + } break; case 0x5C: /* SUBPD Gx, Ex */ nextop = F8; @@ -1374,7 +1383,7 @@ uintptr_t Run660F(x64emu_t *emu, rex_t rex, uintptr_t addr) tmp8u = F8; if(tmp8u>15) {EX->q[0] = EX->q[1] = 0;} - else { + else if (tmp8u!=0) { tmp8u*=8; if (tmp8u < 64) { EX->q[0] = (EX->q[0] >> tmp8u) | (EX->q[1] << (64 - tmp8u)); @@ -1396,7 +1405,7 @@ uintptr_t Run660F(x64emu_t *emu, rex_t rex, uintptr_t addr) tmp8u = F8; if(tmp8u>15) {EX->q[0] = EX->q[1] = 0;} - else { + else if (tmp8u!=0) { tmp8u*=8; if (tmp8u < 64) { EX->q[1] = (EX->q[1] << tmp8u) | (EX->q[0] >> (64 - tmp8u)); @@ -2317,4 +2326,4 @@ uintptr_t Run660F(x64emu_t *emu, rex_t rex, uintptr_t addr) return 0; } return addr; -} \ No newline at end of file +} diff --git a/src/emu/x64runf20f.c b/src/emu/x64runf20f.c index d7ce1eee..eb94958d 100644 --- a/src/emu/x64runf20f.c +++ b/src/emu/x64runf20f.c @@ -33,6 +33,7 @@ uintptr_t RunF20F(x64emu_t *emu, rex_t rex, uintptr_t addr, int *step) int8_t tmp8s; uint8_t tmp8u; int32_t tmp32s; + int64_t tmp64s0, tmp64s1; reg64_t *oped, *opgd; sse_regs_t *opex, *opgx, eax1; mmx87_regs_t *opgm; @@ -321,22 +322,33 @@ uintptr_t RunF20F(x64emu_t *emu, rex_t rex, uintptr_t addr, int *step) GETGX; switch(emu->mxcsr.f.MXCSR_RC) { case ROUND_Nearest: - GX->sd[0] = nearbyint(EX->d[0]); - GX->sd[1] = nearbyint(EX->d[1]); + tmp64s0 = nearbyint(EX->d[0]); + tmp64s1 = nearbyint(EX->d[1]); break; case ROUND_Down: - GX->sd[0] = floor(EX->d[0]); - GX->sd[1] = floor(EX->d[1]); + tmp64s0 = floor(EX->d[0]); + tmp64s1 = floor(EX->d[1]); break; case ROUND_Up: - GX->sd[0] = ceil(EX->d[0]); - GX->sd[1] = ceil(EX->d[1]); + tmp64s0 = ceil(EX->d[0]); + tmp64s1 = ceil(EX->d[1]); break; case ROUND_Chop: - GX->sd[0] = EX->d[0]; - GX->sd[1] = EX->d[1]; + tmp64s0 = EX->d[0]; + tmp64s1 = EX->d[1]; break; } + if (tmp64s0==(int32_t)tmp64s0) { + GX->sd[0] = (int32_t)tmp64s0; + } else { + GX->sd[0] = INT32_MIN; + } + if (tmp64s1==(int32_t)tmp64s1) { + GX->sd[1] = (int32_t)tmp64s1; + } else { + GX->sd[1] = INT32_MIN; + } + GX->q[1] = 0; break; @@ -351,4 +363,4 @@ uintptr_t RunF20F(x64emu_t *emu, rex_t rex, uintptr_t addr, int *step) return 0; } return addr; -} \ No newline at end of file +} diff --git a/src/emu/x64runf30f.c b/src/emu/x64runf30f.c index 4149c94e..e2830c4a 100644 --- a/src/emu/x64runf30f.c +++ b/src/emu/x64runf30f.c @@ -33,6 +33,7 @@ uintptr_t RunF30F(x64emu_t *emu, rex_t rex, uintptr_t addr) int8_t tmp8s; uint8_t tmp8u; uint32_t tmp32u; + int64_t tmp64s; uint64_t tmp64u; reg64_t *oped, *opgd; sse_regs_t *opex, *opgx, eax1; @@ -194,10 +195,14 @@ uintptr_t RunF30F(x64emu_t *emu, rex_t rex, uintptr_t addr) nextop = F8; GETEX(0); GETGX; - GX->sd[0] = EX->f[0]; - GX->sd[1] = EX->f[1]; - GX->sd[2] = EX->f[2]; - GX->sd[3] = EX->f[3]; + for(int i=0; i<4; ++i) { + tmp64s = EX->f[i]; + if (tmp64s==(int32_t)tmp64s) { + GX->sd[i] = (int32_t)tmp64s; + } else { + GX->sd[i] = INT32_MIN; + } + } break; case 0x5C: /* SUBSS Gx, Ex */ nextop = F8; |