diff options
| author | ptitSeb <sebastien.chev@gmail.com> | 2025-02-17 17:46:03 +0100 |
|---|---|---|
| committer | ptitSeb <sebastien.chev@gmail.com> | 2025-02-17 17:46:03 +0100 |
| commit | 049cbd3783cf079a27fa5c871d69272e945f60bd (patch) | |
| tree | 904b80736e1c13326aa1ae9a44668f24ba7648a1 | |
| parent | 8b5b5aa3a7690746688496d9cbbeae729290f2b2 (diff) | |
| download | box64-049cbd3783cf079a27fa5c871d69272e945f60bd.tar.gz box64-049cbd3783cf079a27fa5c871d69272e945f60bd.zip | |
[ARM64_DYNAREC] More work on UD flags
| -rw-r--r-- | src/dynarec/arm64/dynarec_arm64_00.c | 130 | ||||
| -rw-r--r-- | src/dynarec/arm64/dynarec_arm64_0f.c | 2 | ||||
| -rw-r--r-- | src/dynarec/arm64/dynarec_arm64_64.c | 74 | ||||
| -rw-r--r-- | src/dynarec/arm64/dynarec_arm64_66.c | 74 | ||||
| -rw-r--r-- | src/dynarec/arm64/dynarec_arm64_67.c | 74 | ||||
| -rw-r--r-- | src/emu/x64primop.c | 28 |
6 files changed, 224 insertions, 158 deletions
diff --git a/src/dynarec/arm64/dynarec_arm64_00.c b/src/dynarec/arm64/dynarec_arm64_00.c index 8bef8bc8..30fd5f6b 100644 --- a/src/dynarec/arm64/dynarec_arm64_00.c +++ b/src/dynarec/arm64/dynarec_arm64_00.c @@ -3521,7 +3521,11 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin break; case 4: INST_NAME("MUL AL, Eb"); - SETFLAGS(X_ALL, SF_SET); + if(BOX64ENV(dynarec_safeflags) && BOX64ENV(cputype)) { + SETFLAGS(X_OF|X_CF, SF_SET); + } else { + SETFLAGS(X_ALL, SF_SET); + } GETEB(x1, 0); UXTBw(x2, xRAX); MULw(x1, x2, x1); @@ -3537,16 +3541,17 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin BFIw(xFlags, x3, F_OF, 1); } } - IFX(X_AF | X_PF | X_ZF | X_SF) - if (BOX64ENV(dynarec_test)) { - // to avoid noise during test - MOV32w(x3, (1<<F_ZF)|(1<<F_AF)|(1<<F_PF)|(1<<F_SF)); - BICw(xFlags, xFlags, x3); - } + IFX2(X_AF, && !BOX64ENV(cputype)) {BFCw(xFlags, F_AF, 1);} + IFX2(X_ZF, && !BOX64ENV(cputype)) {BFCw(xFlags, F_ZF, 1);} + IFX2(X_SF, && !BOX64ENV(cputype)) { + LSRxw(x3, xRAX, 7); + BFIw(xFlags, x3, F_SF, 1); + } + IFX2(X_PF, && !BOX64ENV(cputype)) emit_pf(dyn, ninst, xRAX, x3); break; case 5: INST_NAME("IMUL AL, Eb"); - if(BOX64ENV(dynarec_safeflags)>1 && BOX64ENV(cputype)) { + if(BOX64ENV(dynarec_safeflags) && BOX64ENV(cputype)) { SETFLAGS(X_OF|X_CF, SF_SET); } else { SETFLAGS(X_ALL, SF_SET); @@ -3570,7 +3575,7 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin IFX2(X_AF, && !BOX64ENV(cputype)) {BFCw(xFlags, F_AF, 1);} IFX2(X_ZF, && !BOX64ENV(cputype)) {BFCw(xFlags, F_ZF, 1);} IFX2(X_SF, && !BOX64ENV(cputype)) { - LSRxw(x3, xRAX, 15); + LSRxw(x3, xRAX, 7); BFIw(xFlags, x3, F_SF, 1); } IFX2(X_PF, && !BOX64ENV(cputype)) emit_pf(dyn, ninst, xRAX, x3); @@ -3595,16 +3600,24 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin BFIx(xRAX, x3, 0, 8); BFIx(xRAX, x4, 8, 8); SET_DFNONE(); - IFX(X_AF | X_SF | X_CF | X_PF | X_ZF | X_OF) - if (BOX64ENV(dynarec_test)) { - MOV32w(x1, (1<<F_AF) | (1<<F_SF) | (1<<F_CF) | (1<<F_PF) | (1<<F_ZF) | (1<<F_OF)); - BICw(xFlags, xFlags, x1); - } + IFX(X_OF) {BFCw(xFlags, F_OF, 1);} + IFX(X_CF) {BFCw(xFlags, F_CF, 1);} + IFX2(X_AF, && !BOX64ENV(cputype)) {BFCw(xFlags, F_AF, 1);} + IFX2(X_AF, && BOX64ENV(cputype)) {ORRw_mask(xFlags, xFlags, 28, 0);} //mask=0x10 + IFX2(X_ZF, && !BOX64ENV(cputype)) {ORRw_mask(xFlags, xFlags, 26, 0);} //mask=0x40 + IFX2(X_ZF, && BOX64ENV(cputype)) {BFCw(xFlags, F_ZF, 1);} + IFX(X_SF) {BFCw(xFlags, F_SF, 1);} + IFX2(X_PF, && !BOX64ENV(cputype)) {ORRw_mask(xFlags, xFlags, 30, 0);} //mask=0x04 + IFX2(X_PF, && BOX64ENV(cputype)) {BFCw(xFlags, F_PF, 1);} break; case 7: INST_NAME("IDIV Eb"); SKIPTEST(x1); - SETFLAGS(X_ALL, SF_SET); + if(!BOX64ENV(dynarec_safeflags)) { + SETFLAGS(X_ALL, SF_SET); + } else if(BOX64ENV(cputype)) { + SETFLAGS(X_SF|X_PF|X_ZF|X_AF, SF_SET); + } GETSEB(x1, 0); if(BOX64ENV(dynarec_div0)) { CBNZw_MARK3(ed); @@ -3621,12 +3634,13 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin MSUBw(x4, x3, ed, x2); // x4 = x2 mod ed (i.e. x2 - x3*ed) BFIx(xRAX, x3, 0, 8); BFIx(xRAX, x4, 8, 8); - SET_DFNONE(); - IFX(X_AF | X_SF | X_CF | X_PF | X_ZF | X_OF) - if (BOX64ENV(dynarec_test)) { - MOV32w(x1, (1<<F_AF) | (1<<F_SF) | (1<<F_CF) | (1<<F_PF) | (1<<F_ZF) | (1<<F_OF)); - BICw(xFlags, xFlags, x1); - } + if(!BOX64ENV(dynarec_safeflags)) { + SET_DFNONE(); + } + IFX2(X_AF, && BOX64ENV(cputype)) {ORRw_mask(xFlags, xFlags, 28, 0);} //mask=0x10 + IFX2(X_ZF, && BOX64ENV(cputype)) {BFCw(xFlags, F_ZF, 1);} + IFX2(X_SF, && BOX64ENV(cputype)) {BFCw(xFlags, F_SF, 1);} + IFX2(X_PF, && BOX64ENV(cputype)) {BFCw(xFlags, F_PF, 1);} break; } break; @@ -3656,7 +3670,11 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin break; case 4: INST_NAME("MUL EAX, Ed"); - SETFLAGS(X_ALL, SF_SET); + if(BOX64ENV(dynarec_safeflags) && BOX64ENV(cputype)) { + SETFLAGS(X_OF|X_CF, SF_SET); + } else { + SETFLAGS(X_ALL, SF_SET); + } GETED(0); if(rex.w) { if(ed==xRDX) gd=x3; else gd=xRDX; @@ -3668,29 +3686,28 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin MOVw_REG(xRAX, xRDX); LSRx(xRDX, xRDX, 32); } - UFLAG_IF { - SET_DFNONE(); - IFX(X_CF|X_OF) { - CMPSxw_U12(xRDX, 0); - CSETw(x3, cNE); - IFX(X_CF) { - BFIw(xFlags, x3, F_CF, 1); - } - IFX(X_OF) { - BFIw(xFlags, x3, F_OF, 1); - } + SET_DFNONE(); + IFX(X_CF|X_OF) { + CMPSxw_U12(xRDX, 0); + CSETw(x3, cNE); + IFX(X_CF) { + BFIw(xFlags, x3, F_CF, 1); + } + IFX(X_OF) { + BFIw(xFlags, x3, F_OF, 1); } - IFX(X_AF | X_PF | X_ZF | X_SF) - if (BOX64ENV(dynarec_test)) { - // to avoid noise during test - MOV32w(x3, (1<<F_ZF)|(1<<F_AF)|(1<<F_PF)|(1<<F_SF)); - BICw(xFlags, xFlags, x3); - } } + IFX2(X_AF, && !BOX64ENV(cputype)) {BFCw(xFlags, F_AF, 1);} + IFX2(X_ZF, && !BOX64ENV(cputype)) {BFCw(xFlags, F_ZF, 1);} + IFX2(X_SF, && !BOX64ENV(cputype)) { + LSRxw(x3, xRAX, rex.w?63:31); + BFIw(xFlags, x3, F_SF, 1); + } + IFX2(X_PF, && !BOX64ENV(cputype)) emit_pf(dyn, ninst, xRAX, x3); break; case 5: INST_NAME("IMUL EAX, Ed"); - if(BOX64ENV(dynarec_safeflags)>1 && BOX64ENV(cputype)) { + if(BOX64ENV(dynarec_safeflags) && BOX64ENV(cputype)) { SETFLAGS(X_OF|X_CF, SF_SET); } else { SETFLAGS(X_ALL, SF_SET); @@ -3804,16 +3821,24 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin } } SET_DFNONE(); - IFX(X_AF | X_SF | X_CF | X_PF | X_ZF | X_OF) - if (BOX64ENV(dynarec_test)) { - MOV32w(x1, (1<<F_AF) | (1<<F_SF) | (1<<F_CF) | (1<<F_PF) | (1<<F_ZF) | (1<<F_OF)); - BICw(xFlags, xFlags, x1); - } + IFX(X_OF) {BFCw(xFlags, F_OF, 1);} + IFX(X_CF) {BFCw(xFlags, F_CF, 1);} + IFX2(X_AF, && !BOX64ENV(cputype)) {BFCw(xFlags, F_AF, 1);} + IFX2(X_AF, && BOX64ENV(cputype)) {ORRw_mask(xFlags, xFlags, 28, 0);} //mask=0x10 + IFX2(X_ZF, && !BOX64ENV(cputype)) {ORRw_mask(xFlags, xFlags, 26, 0);} //mask=0x40 + IFX2(X_ZF, && BOX64ENV(cputype)) {BFCw(xFlags, F_ZF, 1);} + IFX(X_SF) {BFCw(xFlags, F_SF, 1);} + IFX2(X_PF, && !BOX64ENV(cputype)) {ORRw_mask(xFlags, xFlags, 30, 0);} //mask=0x04 + IFX2(X_PF, && BOX64ENV(cputype)) {BFCw(xFlags, F_PF, 1);} break; case 7: INST_NAME("IDIV Ed"); SKIPTEST(x1); - SETFLAGS(X_ALL, SF_SET); + if(!BOX64ENV(dynarec_safeflags)) { + SETFLAGS(X_ALL, SF_SET); + } else if(BOX64ENV(cputype)) { + SETFLAGS(X_SF|X_PF|X_ZF|X_AF, SF_SET); + } if(!rex.w) { GETSEDw(0); if(BOX64ENV(dynarec_div0)) { @@ -3881,12 +3906,13 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin MOVx_REG(xRAX, x2); } } - SET_DFNONE(); - IFX(X_AF | X_SF | X_CF | X_PF | X_ZF | X_OF) - if (BOX64ENV(dynarec_test)) { - MOV32w(x1, (1<<F_AF) | (1<<F_SF) | (1<<F_CF) | (1<<F_PF) | (1<<F_ZF) | (1<<F_OF)); - BICw(xFlags, xFlags, x1); - } + if(!BOX64ENV(dynarec_safeflags)) { + SET_DFNONE(); + } + IFX2(X_AF, && BOX64ENV(cputype)) {ORRw_mask(xFlags, xFlags, 28, 0);} //mask=0x10 + IFX2(X_ZF, && BOX64ENV(cputype)) {BFCw(xFlags, F_ZF, 1);} + IFX2(X_SF, && BOX64ENV(cputype)) {BFCw(xFlags, F_SF, 1);} + IFX2(X_PF, && BOX64ENV(cputype)) {BFCw(xFlags, F_PF, 1);} break; } break; diff --git a/src/dynarec/arm64/dynarec_arm64_0f.c b/src/dynarec/arm64/dynarec_arm64_0f.c index 5a0c1882..cda0cfc8 100644 --- a/src/dynarec/arm64/dynarec_arm64_0f.c +++ b/src/dynarec/arm64/dynarec_arm64_0f.c @@ -1996,7 +1996,7 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin break; case 0xAF: INST_NAME("IMUL Gd, Ed"); - if(BOX64ENV(dynarec_safeflags)>1 && BOX64ENV(cputype)) { + if(BOX64ENV(dynarec_safeflags) && BOX64ENV(cputype)) { SETFLAGS(X_OF|X_CF, SF_SET); } else { SETFLAGS(X_ALL, SF_SET); diff --git a/src/dynarec/arm64/dynarec_arm64_64.c b/src/dynarec/arm64/dynarec_arm64_64.c index ee1d22f1..6c50e374 100644 --- a/src/dynarec/arm64/dynarec_arm64_64.c +++ b/src/dynarec/arm64/dynarec_arm64_64.c @@ -1334,7 +1334,11 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin break; case 4: INST_NAME("MUL EAX, Ed"); - SETFLAGS(X_ALL, SF_SET); + if(BOX64ENV(dynarec_safeflags) && BOX64ENV(cputype)) { + SETFLAGS(X_OF|X_CF, SF_SET); + } else { + SETFLAGS(X_ALL, SF_SET); + } GETEDO(x6, 0); if(rex.w) { if(ed==xRDX) gd=x3; else gd=xRDX; @@ -1346,29 +1350,28 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin MOVw_REG(xRAX, xRDX); LSRx(xRDX, xRDX, 32); } - UFLAG_IF { - SET_DFNONE(); - IFX(X_CF|X_OF) { - CMPSxw_U12(xRDX, 0); - CSETw(x3, cNE); - IFX(X_CF) { - BFIw(xFlags, x3, F_CF, 1); - } - IFX(X_OF) { - BFIw(xFlags, x3, F_OF, 1); - } + SET_DFNONE(); + IFX(X_CF|X_OF) { + CMPSxw_U12(xRDX, 0); + CSETw(x3, cNE); + IFX(X_CF) { + BFIw(xFlags, x3, F_CF, 1); + } + IFX(X_OF) { + BFIw(xFlags, x3, F_OF, 1); } - IFX(X_AF | X_PF | X_ZF | X_SF) - if (BOX64ENV(dynarec_test)) { - // to avoid noise during test - MOV32w(x3, (1<<F_ZF)|(1<<F_AF)|(1<<F_PF)|(1<<F_SF)); - BICw(xFlags, xFlags, x3); - } } + IFX2(X_AF, && !BOX64ENV(cputype)) {BFCw(xFlags, F_AF, 1);} + IFX2(X_ZF, && !BOX64ENV(cputype)) {BFCw(xFlags, F_ZF, 1);} + IFX2(X_SF, && !BOX64ENV(cputype)) { + LSRxw(x3, xRAX, rex.w?63:31); + BFIw(xFlags, x3, F_SF, 1); + } + IFX2(X_PF, && !BOX64ENV(cputype)) emit_pf(dyn, ninst, xRAX, x3); break; case 5: INST_NAME("IMUL EAX, Ed"); - if(BOX64ENV(dynarec_safeflags)>1 && BOX64ENV(cputype)) { + if(BOX64ENV(dynarec_safeflags) && BOX64ENV(cputype)) { SETFLAGS(X_OF|X_CF, SF_SET); } else { SETFLAGS(X_ALL, SF_SET); @@ -1471,16 +1474,24 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin } } SET_DFNONE(); - IFX(X_AF | X_SF | X_CF | X_PF | X_ZF | X_OF) - if (BOX64ENV(dynarec_test)) { - MOV32w(x1, (1<<F_AF) | (1<<F_SF) | (1<<F_CF) | (1<<F_PF) | (1<<F_ZF) | (1<<F_OF)); - BICw(xFlags, xFlags, x1); - } + IFX(X_OF) {BFCw(xFlags, F_OF, 1);} + IFX(X_CF) {BFCw(xFlags, F_CF, 1);} + IFX2(X_AF, && !BOX64ENV(cputype)) {BFCw(xFlags, F_AF, 1);} + IFX2(X_AF, && BOX64ENV(cputype)) {ORRw_mask(xFlags, xFlags, 28, 0);} //mask=0x10 + IFX2(X_ZF, && !BOX64ENV(cputype)) {ORRw_mask(xFlags, xFlags, 26, 0);} //mask=0x40 + IFX2(X_ZF, && BOX64ENV(cputype)) {BFCw(xFlags, F_ZF, 1);} + IFX(X_SF) {BFCw(xFlags, F_SF, 1);} + IFX2(X_PF, && !BOX64ENV(cputype)) {ORRw_mask(xFlags, xFlags, 30, 0);} //mask=0x04 + IFX2(X_PF, && BOX64ENV(cputype)) {BFCw(xFlags, F_PF, 1);} break; case 7: INST_NAME("IDIV Ed"); NOTEST(x1); - SETFLAGS(X_ALL, SF_SET); + if(!BOX64ENV(dynarec_safeflags)) { + SETFLAGS(X_ALL, SF_SET); + } else if(BOX64ENV(cputype)) { + SETFLAGS(X_SF|X_PF|X_ZF|X_AF, SF_SET); + } if(!rex.w) { GETSEDOw(x6, 0); MOVw_REG(x3, xRAX); @@ -1542,12 +1553,13 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin MOVx_REG(xRAX, x2); } } - SET_DFNONE(); - IFX(X_AF | X_SF | X_CF | X_PF | X_ZF | X_OF) - if (BOX64ENV(dynarec_test)) { - MOV32w(x1, (1<<F_AF) | (1<<F_SF) | (1<<F_CF) | (1<<F_PF) | (1<<F_ZF) | (1<<F_OF)); - BICw(xFlags, xFlags, x1); - } + if(!BOX64ENV(dynarec_safeflags)) { + SET_DFNONE(); + } + IFX2(X_AF, && BOX64ENV(cputype)) {ORRw_mask(xFlags, xFlags, 28, 0);} //mask=0x10 + IFX2(X_ZF, && BOX64ENV(cputype)) {BFCw(xFlags, F_ZF, 1);} + IFX2(X_SF, && BOX64ENV(cputype)) {BFCw(xFlags, F_SF, 1);} + IFX2(X_PF, && BOX64ENV(cputype)) {BFCw(xFlags, F_PF, 1);} break; } break; diff --git a/src/dynarec/arm64/dynarec_arm64_66.c b/src/dynarec/arm64/dynarec_arm64_66.c index b0dc2160..8fa366ef 100644 --- a/src/dynarec/arm64/dynarec_arm64_66.c +++ b/src/dynarec/arm64/dynarec_arm64_66.c @@ -1436,35 +1436,38 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin break; case 4: INST_NAME("MUL AX, Ew"); - SETFLAGS(X_ALL, SF_SET); + if(BOX64ENV(dynarec_safeflags) && BOX64ENV(cputype)) { + SETFLAGS(X_OF|X_CF, SF_SET); + } else { + SETFLAGS(X_ALL, SF_SET); + } GETEW(x1, 0); UXTHw(x2, xRAX); MULw(x1, x2, x1); BFIz(xRAX, x1, 0, 16); BFXILx(xRDX, x1, 16, 16); - UFLAG_IF { - SET_DFNONE(); - IFX(X_CF|X_OF) { - CMPSw_REG_LSR(xZR, x1, 16); - CSETw(x3, cNE); - IFX(X_CF) { - BFIw(xFlags, x3, F_CF, 1); - } - IFX(X_OF) { - BFIw(xFlags, x3, F_OF, 1); - } + SET_DFNONE(); + IFX(X_CF|X_OF) { + CMPSw_REG_LSR(xZR, x1, 16); + CSETw(x3, cNE); + IFX(X_CF) { + BFIw(xFlags, x3, F_CF, 1); + } + IFX(X_OF) { + BFIw(xFlags, x3, F_OF, 1); } - IFX(X_AF | X_PF | X_ZF | X_SF) - if (BOX64ENV(dynarec_test)) { - // to avoid noise during test - MOV32w(x3, (1<<F_ZF)|(1<<F_AF)|(1<<F_PF)|(1<<F_SF)); - BICw(xFlags, xFlags, x3); - } } + IFX2(X_AF, && !BOX64ENV(cputype)) {BFCw(xFlags, F_AF, 1);} + IFX2(X_ZF, && !BOX64ENV(cputype)) {BFCw(xFlags, F_ZF, 1);} + IFX2(X_SF, && !BOX64ENV(cputype)) { + LSRxw(x3, xRAX, 15); + BFIw(xFlags, x3, F_SF, 1); + } + IFX2(X_PF, && !BOX64ENV(cputype)) emit_pf(dyn, ninst, xRAX, x3); break; case 5: INST_NAME("IMUL AX, Ew"); - if(BOX64ENV(dynarec_safeflags)>1 && BOX64ENV(cputype)) { + if(BOX64ENV(dynarec_safeflags) && BOX64ENV(cputype)) { SETFLAGS(X_OF|X_CF, SF_SET); } else { SETFLAGS(X_ALL, SF_SET); @@ -1515,16 +1518,24 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin BFIz(xRAX, x3, 0, 16); BFIz(xRDX, x4, 0, 16); SET_DFNONE(); - IFX(X_AF | X_SF | X_CF | X_PF | X_ZF | X_OF) - if (BOX64ENV(dynarec_test)) { - MOV32w(x1, (1<<F_AF) | (1<<F_SF) | (1<<F_CF) | (1<<F_PF) | (1<<F_ZF) | (1<<F_OF)); - BICw(xFlags, xFlags, x1); - } + IFX(X_OF) {BFCw(xFlags, F_OF, 1);} + IFX(X_CF) {BFCw(xFlags, F_CF, 1);} + IFX2(X_AF, && !BOX64ENV(cputype)) {BFCw(xFlags, F_AF, 1);} + IFX2(X_AF, && BOX64ENV(cputype)) {ORRw_mask(xFlags, xFlags, 28, 0);} //mask=0x10 + IFX2(X_ZF, && !BOX64ENV(cputype)) {ORRw_mask(xFlags, xFlags, 26, 0);} //mask=0x40 + IFX2(X_ZF, && BOX64ENV(cputype)) {BFCw(xFlags, F_ZF, 1);} + IFX(X_SF) {BFCw(xFlags, F_SF, 1);} + IFX2(X_PF, && !BOX64ENV(cputype)) {ORRw_mask(xFlags, xFlags, 30, 0);} //mask=0x04 + IFX2(X_PF, && BOX64ENV(cputype)) {BFCw(xFlags, F_PF, 1);} break; case 7: INST_NAME("IDIV Ew"); SKIPTEST(x1); - SETFLAGS(X_ALL, SF_SET); + if(!BOX64ENV(dynarec_safeflags)) { + SETFLAGS(X_ALL, SF_SET); + } else if(BOX64ENV(cputype)) { + SETFLAGS(X_SF|X_PF|X_ZF|X_AF, SF_SET); + } GETSEW(x1, 0); if(BOX64ENV(dynarec_div0)) { CBNZw_MARK3(ed); @@ -1542,12 +1553,13 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin MSUBw(x4, x3, ed, x2); // x4 = x2 mod ed (i.e. x2 - x3*ed) BFIz(xRAX, x3, 0, 16); BFIz(xRDX, x4, 0, 16); - SET_DFNONE(); - IFX(X_AF | X_SF | X_CF | X_PF | X_ZF | X_OF) - if (BOX64ENV(dynarec_test)) { - MOV32w(x1, (1<<F_AF) | (1<<F_SF) | (1<<F_CF) | (1<<F_PF) | (1<<F_ZF) | (1<<F_OF)); - BICw(xFlags, xFlags, x1); - } + if(!BOX64ENV(dynarec_safeflags)) { + SET_DFNONE(); + } + IFX2(X_AF, && BOX64ENV(cputype)) {ORRw_mask(xFlags, xFlags, 28, 0);} //mask=0x10 + IFX2(X_ZF, && BOX64ENV(cputype)) {BFCw(xFlags, F_ZF, 1);} + IFX2(X_SF, && BOX64ENV(cputype)) {BFCw(xFlags, F_SF, 1);} + IFX2(X_PF, && BOX64ENV(cputype)) {BFCw(xFlags, F_PF, 1);} break; } break; diff --git a/src/dynarec/arm64/dynarec_arm64_67.c b/src/dynarec/arm64/dynarec_arm64_67.c index 810a3a33..36180f02 100644 --- a/src/dynarec/arm64/dynarec_arm64_67.c +++ b/src/dynarec/arm64/dynarec_arm64_67.c @@ -1466,7 +1466,11 @@ uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin break; case 4: INST_NAME("MUL EAX, Ed"); - SETFLAGS(X_ALL, SF_SET); + if(BOX64ENV(dynarec_safeflags) && BOX64ENV(cputype)) { + SETFLAGS(X_OF|X_CF, SF_SET); + } else { + SETFLAGS(X_ALL, SF_SET); + } GETED32(0); if(rex.w) { if(ed==xRDX) gd=x3; else gd=xRDX; @@ -1478,29 +1482,28 @@ uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin MOVw_REG(xRAX, xRDX); LSRx(xRDX, xRDX, 32); } - UFLAG_IF { - SET_DFNONE(); - IFX(X_CF|X_OF) { - CMPSxw_U12(xRDX, 0); - CSETw(x3, cNE); - IFX(X_CF) { - BFIw(xFlags, x3, F_CF, 1); - } - IFX(X_OF) { - BFIw(xFlags, x3, F_OF, 1); - } + SET_DFNONE(); + IFX(X_CF|X_OF) { + CMPSxw_U12(xRDX, 0); + CSETw(x3, cNE); + IFX(X_CF) { + BFIw(xFlags, x3, F_CF, 1); + } + IFX(X_OF) { + BFIw(xFlags, x3, F_OF, 1); } - IFX(X_AF | X_PF | X_ZF | X_SF) - if (BOX64ENV(dynarec_test)) { - // to avoid noise during test - MOV32w(x3, (1<<F_ZF)|(1<<F_AF)|(1<<F_PF)|(1<<F_SF)); - BICw(xFlags, xFlags, x3); - } } + IFX2(X_AF, && !BOX64ENV(cputype)) {BFCw(xFlags, F_AF, 1);} + IFX2(X_ZF, && !BOX64ENV(cputype)) {BFCw(xFlags, F_ZF, 1);} + IFX2(X_SF, && !BOX64ENV(cputype)) { + LSRxw(x3, xRAX, rex.w?63:31); + BFIw(xFlags, x3, F_SF, 1); + } + IFX2(X_PF, && !BOX64ENV(cputype)) emit_pf(dyn, ninst, xRAX, x3); break; case 5: INST_NAME("IMUL EAX, Ed"); - if(BOX64ENV(dynarec_safeflags)>1 && BOX64ENV(cputype)) { + if(BOX64ENV(dynarec_safeflags) && BOX64ENV(cputype)) { SETFLAGS(X_OF|X_CF, SF_SET); } else { SETFLAGS(X_ALL, SF_SET); @@ -1572,16 +1575,24 @@ uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin } } SET_DFNONE(); - IFX(X_AF | X_SF | X_CF | X_PF | X_ZF | X_OF) - if (BOX64ENV(dynarec_test)) { - MOV32w(x1, (1<<F_AF) | (1<<F_SF) | (1<<F_CF) | (1<<F_PF) | (1<<F_ZF) | (1<<F_OF)); - BICw(xFlags, xFlags, x1); - } + IFX(X_OF) {BFCw(xFlags, F_OF, 1);} + IFX(X_CF) {BFCw(xFlags, F_CF, 1);} + IFX2(X_AF, && !BOX64ENV(cputype)) {BFCw(xFlags, F_AF, 1);} + IFX2(X_AF, && BOX64ENV(cputype)) {ORRw_mask(xFlags, xFlags, 28, 0);} //mask=0x10 + IFX2(X_ZF, && !BOX64ENV(cputype)) {ORRw_mask(xFlags, xFlags, 26, 0);} //mask=0x40 + IFX2(X_ZF, && BOX64ENV(cputype)) {BFCw(xFlags, F_ZF, 1);} + IFX(X_SF) {BFCw(xFlags, F_SF, 1);} + IFX2(X_PF, && !BOX64ENV(cputype)) {ORRw_mask(xFlags, xFlags, 30, 0);} //mask=0x04 + IFX2(X_PF, && BOX64ENV(cputype)) {BFCw(xFlags, F_PF, 1);} break; case 7: INST_NAME("IDIV Ed"); NOTEST(x1); - SETFLAGS(X_ALL, SF_SET); + if(!BOX64ENV(dynarec_safeflags)) { + SETFLAGS(X_ALL, SF_SET); + } else if(BOX64ENV(cputype)) { + SETFLAGS(X_SF|X_PF|X_ZF|X_AF, SF_SET); + } if(!rex.w) { GETSED32w(0); MOVw_REG(x3, xRAX); @@ -1613,12 +1624,13 @@ uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin MOVx_REG(xRAX, x2); } } - SET_DFNONE(); - IFX(X_AF | X_SF | X_CF | X_PF | X_ZF | X_OF) - if (BOX64ENV(dynarec_test)) { - MOV32w(x1, (1<<F_AF) | (1<<F_SF) | (1<<F_CF) | (1<<F_PF) | (1<<F_ZF) | (1<<F_OF)); - BICw(xFlags, xFlags, x1); - } + if(!BOX64ENV(dynarec_safeflags)) { + SET_DFNONE(); + } + IFX2(X_AF, && BOX64ENV(cputype)) {ORRw_mask(xFlags, xFlags, 28, 0);} //mask=0x10 + IFX2(X_ZF, && BOX64ENV(cputype)) {BFCw(xFlags, F_ZF, 1);} + IFX2(X_SF, && BOX64ENV(cputype)) {BFCw(xFlags, F_SF, 1);} + IFX2(X_PF, && BOX64ENV(cputype)) {BFCw(xFlags, F_PF, 1);} break; } break; diff --git a/src/emu/x64primop.c b/src/emu/x64primop.c index 9c1f2865..8a17da5a 100644 --- a/src/emu/x64primop.c +++ b/src/emu/x64primop.c @@ -521,9 +521,12 @@ uint8_t rcl8(x64emu_t *emu, uint8_t d, uint8_t s) CONDITIONAL_SET_FLAG(cf, F_CF); /* OVERFLOW is set *IFF* cnt==1, then it is the xor of CF and the most significant bit. Blecck. */ - CONDITIONAL_SET_FLAG((cf ^ (res >> 7)) & 0x1, F_OF); - - } + if(BOX64ENV(cputype)) + CONDITIONAL_SET_FLAG((cf ^ (res >> 7)) & 0x1, F_OF); + else + CONDITIONAL_SET_FLAG((XOR2(d >> 6)), F_OF); + } else if(s && BOX64ENV(cputype)) + CONDITIONAL_SET_FLAG((ACCESS_FLAG(F_CF) ^ (res >> 7)) & 0x1, F_OF); return (uint8_t)res; } @@ -547,7 +550,8 @@ uint16_t rcl16(x64emu_t *emu, uint16_t d, uint8_t s) CONDITIONAL_SET_FLAG((cf ^ (res >> 15)) & 0x1, F_OF); else CONDITIONAL_SET_FLAG((XOR2(d >> 14)), F_OF); - } + } else if(s && BOX64ENV(cputype)) + CONDITIONAL_SET_FLAG((ACCESS_FLAG(F_CF) ^ (res >> 15)) & 0x1, F_OF); return (uint16_t)res; } @@ -679,9 +683,9 @@ uint8_t rcr8(x64emu_t *emu, uint8_t d, uint8_t s) /* set the new carry flag, based on the variable "cf" */ CONDITIONAL_SET_FLAG(cf, F_CF); - if(BOX64ENV(cputype)) - CONDITIONAL_SET_FLAG((XOR2(res >> 6)), F_OF); } + if(s && BOX64ENV(cputype)) + CONDITIONAL_SET_FLAG((XOR2(res >> 6)), F_OF); return (uint8_t)res; } @@ -709,9 +713,9 @@ uint16_t rcr16(x64emu_t *emu, uint16_t d, uint8_t s) res |= 1 << (16 - cnt); } CONDITIONAL_SET_FLAG(cf, F_CF); - if(BOX64ENV(cputype)) - CONDITIONAL_SET_FLAG((XOR2(res >> 14)), F_OF); } + if(s && BOX64ENV(cputype)) + CONDITIONAL_SET_FLAG((XOR2(res >> 14)), F_OF); return (uint16_t)res; } @@ -741,9 +745,9 @@ uint32_t rcr32(x64emu_t *emu, uint32_t d, uint8_t s) res |= 1 << (32 - cnt); } CONDITIONAL_SET_FLAG(cf, F_CF); - if(BOX64ENV(cputype)) - CONDITIONAL_SET_FLAG((XOR2(res >> 30)), F_OF); } + if(s && BOX64ENV(cputype)) + CONDITIONAL_SET_FLAG((XOR2(res >> 30)), F_OF); return res; } @@ -773,9 +777,9 @@ uint64_t rcr64(x64emu_t *emu, uint64_t d, uint8_t s) res |= 1LL << (64 - cnt); } CONDITIONAL_SET_FLAG(cf, F_CF); - if(BOX64ENV(cputype)) - CONDITIONAL_SET_FLAG((XOR2(res >> 62)), F_OF); } + if(s && BOX64ENV(cputype)) + CONDITIONAL_SET_FLAG((XOR2(res >> 62)), F_OF); return res; } /**************************************************************************** |