diff options
| author | ptitSeb <sebastien.chev@gmail.com> | 2024-02-20 16:31:44 +0100 |
|---|---|---|
| committer | ptitSeb <sebastien.chev@gmail.com> | 2024-02-20 16:31:44 +0100 |
| commit | 02fadef9e700f7d0fc8fc91534e8e650f98af7b5 (patch) | |
| tree | b38c4129e17edd90b8e7e8a213b37409f35137db | |
| parent | 6e4d2470d220ac49475c7e13a1fbb11a9008a223 (diff) | |
| download | box64-02fadef9e700f7d0fc8fc91534e8e650f98af7b5.tar.gz box64-02fadef9e700f7d0fc8fc91534e8e650f98af7b5.zip | |
[INTERPRETER] Fix shl/sar/shr for large shft value on 8 and 16bits operations
| -rw-r--r-- | src/emu/x64emu_private.h | 4 | ||||
| -rw-r--r-- | src/emu/x64primop.c | 8 | ||||
| -rw-r--r-- | src/emu/x64run_private.c | 290 |
3 files changed, 96 insertions, 206 deletions
diff --git a/src/emu/x64emu_private.h b/src/emu/x64emu_private.h index 0c994e59..90c9b7b0 100644 --- a/src/emu/x64emu_private.h +++ b/src/emu/x64emu_private.h @@ -20,9 +20,13 @@ typedef struct forkpty_s { typedef union multiuint_s { uint8_t u8; + int8_t i8; uint16_t u16; + int16_t i16; uint32_t u32; + int32_t i32; uint64_t u64; + int64_t i64; } multiuint_t; typedef struct x64emu_s x64emu_t; diff --git a/src/emu/x64primop.c b/src/emu/x64primop.c index 9bb001ba..2c8277af 100644 --- a/src/emu/x64primop.c +++ b/src/emu/x64primop.c @@ -556,7 +556,7 @@ uint32_t rcl32(x64emu_t *emu, uint32_t d, uint8_t s) s = s&0x1f; res = d; - if ((cnt = s % 33) != 0) { + if ((cnt = s) != 0) { cf = (d >> (32 - cnt)) & 0x1; res = (d << cnt); mask = (1 << (cnt - 1)) - 1; @@ -578,7 +578,7 @@ uint64_t rcl64(x64emu_t *emu, uint64_t d, uint8_t s) s = s&0x3f; res = d; - if ((cnt = s % 65) != 0) { + if ((cnt = s) != 0) { cf = (d >> (64 - cnt)) & 0x1; res = (d << cnt); mask = (1LL << (cnt - 1)) - 1; @@ -713,7 +713,7 @@ uint32_t rcr32(x64emu_t *emu, uint32_t d, uint8_t s) /* rotate right through carry */ res = d; - if ((cnt = s % 33) != 0) { + if ((cnt = s) != 0) { if (cnt == 1) { cf = d & 0x1; ocf = ACCESS_FLAG(F_CF) != 0; @@ -742,7 +742,7 @@ uint64_t rcr64(x64emu_t *emu, uint64_t d, uint8_t s) /* rotate right through carry */ res = d; - if ((cnt = s % 65) != 0) { + if ((cnt = s) != 0) { if (cnt == 1) { cf = d & 0x1; ocf = ACCESS_FLAG(F_CF) != 0; diff --git a/src/emu/x64run_private.c b/src/emu/x64run_private.c index 8d7ff9b9..cd093609 100644 --- a/src/emu/x64run_private.c +++ b/src/emu/x64run_private.c @@ -496,88 +496,55 @@ void UpdateFlags(x64emu_t *emu) CONDITIONAL_SET_FLAG(bc & 0x8, F_AF); break; case d_shl8: - if (emu->op2.u8 < 8) { - cnt = emu->op2.u8 % 8; - if (cnt > 0) { - cc = emu->op1.u8 & (1 << (8 - cnt)); - CONDITIONAL_SET_FLAG(cc, F_CF); - CONDITIONAL_SET_FLAG((emu->res.u8 & 0xff) == 0, F_ZF); - CONDITIONAL_SET_FLAG(emu->res.u8 & 0x80, F_SF); - CONDITIONAL_SET_FLAG(PARITY(emu->res.u8 & 0xff), F_PF); - if (cnt == 1) { - CONDITIONAL_SET_FLAG((((emu->res.u8 & 0x80) == 0x80) ^(ACCESS_FLAG(F_CF) != 0)), F_OF); - } else { - CLEAR_FLAG(F_OF); - } - if(box64_dynarec_test) { - CLEAR_FLAG(F_AF); - } + cnt = emu->op2.u8 & 0x1f; + if (cnt > 0) { + cc = emu->op1.u8 & (1 << (8 - cnt)); + CONDITIONAL_SET_FLAG(cc, F_CF); + CONDITIONAL_SET_FLAG((emu->res.u8 & 0xff) == 0, F_ZF); + CONDITIONAL_SET_FLAG(emu->res.u8 & 0x80, F_SF); + CONDITIONAL_SET_FLAG(PARITY(emu->res.u8 & 0xff), F_PF); + if (cnt == 1) { + CONDITIONAL_SET_FLAG((((emu->res.u8 & 0x80) == 0x80) ^(ACCESS_FLAG(F_CF) != 0)), F_OF); + } else { + CLEAR_FLAG(F_OF); } - } else { - CONDITIONAL_SET_FLAG((emu->op1.u8 << (emu->op2.u8-1)) & 0x80, F_CF); - CLEAR_FLAG(F_OF); - CLEAR_FLAG(F_SF); - SET_FLAG(F_PF); - SET_FLAG(F_ZF); if(box64_dynarec_test) { CLEAR_FLAG(F_AF); } } break; case d_shl16: - if (emu->op2.u16 < 16) { - cnt = emu->op2.u16 % 16; - if (cnt > 0) { - cc = emu->op1.u16 & (1 << (16 - cnt)); - CONDITIONAL_SET_FLAG(cc, F_CF); - CONDITIONAL_SET_FLAG((emu->res.u16 & 0xffff) == 0, F_ZF); - CONDITIONAL_SET_FLAG(emu->res.u16 & 0x8000, F_SF); - CONDITIONAL_SET_FLAG(PARITY(emu->res.u16 & 0xff), F_PF); - if (cnt == 1) { - CONDITIONAL_SET_FLAG(((!!(emu->res.u16 & 0x8000)) ^(ACCESS_FLAG(F_CF) != 0)), F_OF); - } else { - CLEAR_FLAG(F_OF); - } - if(box64_dynarec_test) { - CLEAR_FLAG(F_AF); - } + cnt = emu->op2.u16 & 0x1f; + if (cnt > 0) { + cc = emu->op1.u16 & (1 << (16 - cnt)); + CONDITIONAL_SET_FLAG(cc, F_CF); + CONDITIONAL_SET_FLAG((emu->res.u16 & 0xffff) == 0, F_ZF); + CONDITIONAL_SET_FLAG(emu->res.u16 & 0x8000, F_SF); + CONDITIONAL_SET_FLAG(PARITY(emu->res.u16 & 0xff), F_PF); + if (cnt == 1) { + CONDITIONAL_SET_FLAG(((!!(emu->res.u16 & 0x8000)) ^(ACCESS_FLAG(F_CF) != 0)), F_OF); + } else { + CLEAR_FLAG(F_OF); } - } else { - CONDITIONAL_SET_FLAG((emu->op1.u16 << (emu->op2.u16-1)) & 0x8000, F_CF); - CLEAR_FLAG(F_OF); - CLEAR_FLAG(F_SF); - SET_FLAG(F_PF); - SET_FLAG(F_ZF); if(box64_dynarec_test) { CLEAR_FLAG(F_AF); } } break; case d_shl32: - if (emu->op2.u32 < 32) { - cnt = emu->op2.u32 % 32; - if (cnt > 0) { - cc = emu->op1.u32 & (1 << (32 - cnt)); - CONDITIONAL_SET_FLAG(cc, F_CF); - CONDITIONAL_SET_FLAG(!emu->res.u32, F_ZF); - CONDITIONAL_SET_FLAG(emu->res.u32 & 0x80000000, F_SF); - CONDITIONAL_SET_FLAG(PARITY(emu->res.u32 & 0xff), F_PF); - if (cnt == 1) { - CONDITIONAL_SET_FLAG(((!!(emu->res.u32 & 0x80000000)) ^ - (ACCESS_FLAG(F_CF) != 0)), F_OF); - } else { - CLEAR_FLAG(F_OF); - } - if(box64_dynarec_test) { - CLEAR_FLAG(F_AF); - } + cnt = emu->op2.u32 & 0x1f; + if (cnt > 0) { + cc = emu->op1.u32 & (1 << (32 - cnt)); + CONDITIONAL_SET_FLAG(cc, F_CF); + CONDITIONAL_SET_FLAG(!emu->res.u32, F_ZF); + CONDITIONAL_SET_FLAG(emu->res.u32 & 0x80000000, F_SF); + CONDITIONAL_SET_FLAG(PARITY(emu->res.u32 & 0xff), F_PF); + if (cnt == 1) { + CONDITIONAL_SET_FLAG(((!!(emu->res.u32 & 0x80000000)) ^ + (ACCESS_FLAG(F_CF) != 0)), F_OF); + } else { + CLEAR_FLAG(F_OF); } - } else { - CONDITIONAL_SET_FLAG((emu->op1.u32 << (emu->op2.u32-1)) & 0x80000000, F_CF); - CLEAR_FLAG(F_OF); - CLEAR_FLAG(F_SF); - SET_FLAG(F_PF); - SET_FLAG(F_ZF); if(box64_dynarec_test) { CLEAR_FLAG(F_AF); } @@ -602,93 +569,42 @@ void UpdateFlags(x64emu_t *emu) } break; case d_sar8: - if (emu->op2.u8 < 8) { - if(emu->op2.u8) { - cc = emu->op1.u8 & (1 << (emu->op2.u8 - 1)); - CONDITIONAL_SET_FLAG(cc, F_CF); - CONDITIONAL_SET_FLAG((emu->res.u8 & 0xff) == 0, F_ZF); - CONDITIONAL_SET_FLAG(PARITY(emu->res.u8 & 0xff), F_PF); - CONDITIONAL_SET_FLAG(emu->res.u8 & 0x80, F_SF); - if(emu->op2.u8==1) - CLEAR_FLAG(F_OF); - if(box64_dynarec_test) { - CLEAR_FLAG(F_AF); - } - } - } else { - if (emu->op1.u8&0x80) { - SET_FLAG(F_CF); - SET_FLAG(F_SF); - CLEAR_FLAG(F_ZF); - SET_FLAG(F_PF); - } else { - CLEAR_FLAG(F_CF); - CLEAR_FLAG(F_SF); - SET_FLAG(F_ZF); - SET_FLAG(F_PF); - } + if(emu->op2.u8) { + cc = (emu->op1.i8 >> (emu->op2.u8 - 1)) & 1; + CONDITIONAL_SET_FLAG(cc, F_CF); + CONDITIONAL_SET_FLAG((emu->res.u8 & 0xff) == 0, F_ZF); + CONDITIONAL_SET_FLAG(PARITY(emu->res.u8 & 0xff), F_PF); + CONDITIONAL_SET_FLAG(emu->res.u8 & 0x80, F_SF); + if(emu->op2.u8==1) + CLEAR_FLAG(F_OF); if(box64_dynarec_test) { CLEAR_FLAG(F_AF); } } break; case d_sar16: - if (emu->op2.u16 < 16) { - if(emu->op2.u16) { - cc = emu->op1.u16 & (1 << (emu->op2.u16 - 1)); - CONDITIONAL_SET_FLAG(cc, F_CF); - CONDITIONAL_SET_FLAG((emu->res.u16 & 0xffff) == 0, F_ZF); - CONDITIONAL_SET_FLAG(emu->res.u16 & 0x8000, F_SF); - CONDITIONAL_SET_FLAG(PARITY(emu->res.u16 & 0xff), F_PF); - if(emu->op2.u16==1) - CLEAR_FLAG(F_OF); - if(box64_dynarec_test) { - CLEAR_FLAG(F_AF); - } - } - } else { - if (emu->op1.u16&0x8000) { - SET_FLAG(F_CF); - CLEAR_FLAG(F_ZF); - SET_FLAG(F_SF); - SET_FLAG(F_PF); - } else { - CLEAR_FLAG(F_CF); - SET_FLAG(F_ZF); - CLEAR_FLAG(F_SF); - SET_FLAG(F_PF); - } + if(emu->op2.u16) { + cc = (emu->op1.i16 >> (emu->op2.u16 - 1)) & 1; + CONDITIONAL_SET_FLAG(cc, F_CF); + CONDITIONAL_SET_FLAG((emu->res.u16 & 0xffff) == 0, F_ZF); + CONDITIONAL_SET_FLAG(emu->res.u16 & 0x8000, F_SF); + CONDITIONAL_SET_FLAG(PARITY(emu->res.u16 & 0xff), F_PF); + if(emu->op2.u16==1) + CLEAR_FLAG(F_OF); if(box64_dynarec_test) { CLEAR_FLAG(F_AF); } } break; case d_sar32: - if (emu->op2.u32 < 32) { - if(emu->op2.u32) { - cc = emu->op1.u32 & (1 << (emu->op2.u32 - 1)); - CONDITIONAL_SET_FLAG(cc, F_CF); - CONDITIONAL_SET_FLAG((emu->res.u32 & 0xffffffff) == 0, F_ZF); - CONDITIONAL_SET_FLAG(emu->res.u32 & 0x80000000, F_SF); - CONDITIONAL_SET_FLAG(PARITY(emu->res.u32 & 0xff), F_PF); - if(emu->op2.u32==1) - CLEAR_FLAG(F_OF); - if(box64_dynarec_test) { - CLEAR_FLAG(F_AF); - } - } - } else { - if (emu->op1.u32&0x80000000) { - SET_FLAG(F_CF); - CLEAR_FLAG(F_ZF); - SET_FLAG(F_SF); - SET_FLAG(F_PF); - } else { - CLEAR_FLAG(F_CF); - SET_FLAG(F_ZF); - CLEAR_FLAG(F_SF); - SET_FLAG(F_PF); - } + if(emu->op2.u32) { + cc = emu->op1.u32 & (1 << (emu->op2.u32 - 1)); + CONDITIONAL_SET_FLAG(cc, F_CF); + CONDITIONAL_SET_FLAG((emu->res.u32 & 0xffffffff) == 0, F_ZF); + CONDITIONAL_SET_FLAG(emu->res.u32 & 0x80000000, F_SF); + CONDITIONAL_SET_FLAG(PARITY(emu->res.u32 & 0xff), F_PF); + if(emu->op2.u32==1) + CLEAR_FLAG(F_OF); if(box64_dynarec_test) { CLEAR_FLAG(F_AF); } @@ -709,82 +625,52 @@ void UpdateFlags(x64emu_t *emu) } break; case d_shr8: - if (emu->op2.u8 < 8) { - cnt = emu->op2.u8 % 8; - if (cnt > 0) { - cc = emu->op1.u8 & (1 << (cnt - 1)); - CONDITIONAL_SET_FLAG(cc, F_CF); - CONDITIONAL_SET_FLAG((emu->res.u8 & 0xff) == 0, F_ZF); - CONDITIONAL_SET_FLAG(emu->res.u8 & 0x80, F_SF); - CONDITIONAL_SET_FLAG(PARITY(emu->res.u8 & 0xff), F_PF); - if(box64_dynarec_test) { - CLEAR_FLAG(F_AF); - } - } - if (cnt == 1) { - CONDITIONAL_SET_FLAG(emu->op1.u8 & 0x80, F_OF); - } - } else { - CONDITIONAL_SET_FLAG((emu->op1.u8 >> (emu->op2.u8-1)) & 0x1, F_CF); - CLEAR_FLAG(F_SF); - SET_FLAG(F_PF); - SET_FLAG(F_ZF); + cnt = emu->op2.u8 & 0x1f; + if (cnt > 0) { + cc = emu->op1.u8 & (1 << (cnt - 1)); + CONDITIONAL_SET_FLAG(cc, F_CF); + CONDITIONAL_SET_FLAG((emu->res.u8 & 0xff) == 0, F_ZF); + CONDITIONAL_SET_FLAG(emu->res.u8 & 0x80, F_SF); + CONDITIONAL_SET_FLAG(PARITY(emu->res.u8 & 0xff), F_PF); if(box64_dynarec_test) { CLEAR_FLAG(F_AF); } } + if (cnt == 1) { + CONDITIONAL_SET_FLAG(emu->op1.u8 & 0x80, F_OF); + } break; case d_shr16: - if (emu->op2.u16 < 16) { - cnt = emu->op2.u16 % 16; - if (cnt > 0) { - cc = emu->op1.u16 & (1 << (cnt - 1)); - CONDITIONAL_SET_FLAG(cc, F_CF); - CONDITIONAL_SET_FLAG((emu->res.u16 & 0xffff) == 0, F_ZF); - CONDITIONAL_SET_FLAG(emu->res.u16 & 0x8000, F_SF); - CONDITIONAL_SET_FLAG(PARITY(emu->res.u16 & 0xff), F_PF); - if(box64_dynarec_test) { - CLEAR_FLAG(F_AF); - } - } - if (cnt == 1) { - CONDITIONAL_SET_FLAG(emu->op1.u16 & 0x8000, F_OF); - } - } else { - CLEAR_FLAG(F_CF); - SET_FLAG(F_ZF); - CLEAR_FLAG(F_SF); - SET_FLAG(F_PF); + cnt = emu->op2.u16 & 0x1f; + if (cnt > 0) { + cc = emu->op1.u16 & (1 << (cnt - 1)); + CONDITIONAL_SET_FLAG(cc, F_CF); + CONDITIONAL_SET_FLAG((emu->res.u16 & 0xffff) == 0, F_ZF); + CONDITIONAL_SET_FLAG(emu->res.u16 & 0x8000, F_SF); + CONDITIONAL_SET_FLAG(PARITY(emu->res.u16 & 0xff), F_PF); if(box64_dynarec_test) { CLEAR_FLAG(F_AF); } } + if (cnt == 1) { + CONDITIONAL_SET_FLAG(emu->op1.u16 & 0x8000, F_OF); + } break; case d_shr32: - if (emu->op2.u32 < 32) { - cnt = emu->op2.u32 % 32; - if (cnt > 0) { - cc = emu->op1.u32 & (1 << (cnt - 1)); - CONDITIONAL_SET_FLAG(cc, F_CF); - CONDITIONAL_SET_FLAG((emu->res.u32 & 0xffffffff) == 0, F_ZF); - CONDITIONAL_SET_FLAG(emu->res.u32 & 0x80000000, F_SF); - CONDITIONAL_SET_FLAG(PARITY(emu->res.u32 & 0xff), F_PF); - if(box64_dynarec_test) { - CLEAR_FLAG(F_AF); - } - } - if (cnt == 1) { - CONDITIONAL_SET_FLAG(emu->op1.u32 & 0x80000000, F_OF); - } - } else { - CLEAR_FLAG(F_CF); - SET_FLAG(F_ZF); - CLEAR_FLAG(F_SF); - SET_FLAG(F_PF); + cnt = emu->op2.u32 & 0x1f; + if (cnt > 0) { + cc = emu->op1.u32 & (1 << (cnt - 1)); + CONDITIONAL_SET_FLAG(cc, F_CF); + CONDITIONAL_SET_FLAG((emu->res.u32 & 0xffffffff) == 0, F_ZF); + CONDITIONAL_SET_FLAG(emu->res.u32 & 0x80000000, F_SF); + CONDITIONAL_SET_FLAG(PARITY(emu->res.u32 & 0xff), F_PF); if(box64_dynarec_test) { CLEAR_FLAG(F_AF); } } + if (cnt == 1) { + CONDITIONAL_SET_FLAG(emu->op1.u32 & 0x80000000, F_OF); + } break; case d_shr64: cnt = emu->op2.u64; |