From d49fc437917cbbad9ea556fa373f8a08dafeda65 Mon Sep 17 00:00:00 2001 From: ptitSeb Date: Mon, 17 Feb 2025 14:18:49 +0100 Subject: [PATCH] [ARM64_DYNAREC] Continue work on UD flags --- src/dynarec/arm64/dynarec_arm64_00.c | 79 +++-- src/dynarec/arm64/dynarec_arm64_0f.c | 117 +++---- src/dynarec/arm64/dynarec_arm64_64.c | 80 +++-- src/dynarec/arm64/dynarec_arm64_66.c | 28 +- src/dynarec/arm64/dynarec_arm64_660f.c | 120 +++---- src/dynarec/arm64/dynarec_arm64_67.c | 28 +- src/dynarec/arm64/dynarec_arm64_emit_shift.c | 348 +++++++++++++------ src/dynarec/arm64/dynarec_arm64_f0.c | 96 ++--- src/emu/x64primop.c | 40 ++- 9 files changed, 539 insertions(+), 397 deletions(-) diff --git a/src/dynarec/arm64/dynarec_arm64_00.c b/src/dynarec/arm64/dynarec_arm64_00.c index b43ea42175..8bef8bc861 100644 --- a/src/dynarec/arm64/dynarec_arm64_00.c +++ b/src/dynarec/arm64/dynarec_arm64_00.c @@ -888,7 +888,11 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin break; case 0x69: INST_NAME("IMUL Gd, Ed, Id"); - SETFLAGS(X_ALL, SF_SET); + if(BOX64ENV(dynarec_safeflags)>1 && BOX64ENV(cputype)) { + SETFLAGS(X_OF|X_CF, SF_SET); + } else { + SETFLAGS(X_ALL, SF_SET); + } nextop = F8; GETGD; GETED(4); @@ -934,13 +938,13 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin MULxw(gd, ed, x4); } } - IFX(X_AF) {BFCw(xFlags, F_AF, 1);} - IFX(X_ZF) {BFCw(xFlags, F_ZF, 1);} - IFX(X_SF) { + 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, gd, rex.w?63:31); BFIw(xFlags, x3, F_SF, 1); } - IFX(X_PF) emit_pf(dyn, ninst, gd, x3); + IFX2(X_PF, && !BOX64ENV(cputype)) emit_pf(dyn, ninst, gd, x3); break; case 0x6A: INST_NAME("PUSH Ib"); @@ -951,7 +955,11 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin break; case 0x6B: INST_NAME("IMUL Gd, Ed, Ib"); - SETFLAGS(X_ALL, SF_SET); + if(BOX64ENV(dynarec_safeflags)>1 && BOX64ENV(cputype)) { + SETFLAGS(X_OF|X_CF, SF_SET); + } else { + SETFLAGS(X_ALL, SF_SET); + } nextop = F8; GETGD; GETED(1); @@ -997,13 +1005,13 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin MULxw(gd, ed, x4); } } - IFX(X_AF) {BFCw(xFlags, F_AF, 1);} - IFX(X_ZF) {BFCw(xFlags, F_ZF, 1);} - IFX(X_SF) { + 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, gd, rex.w?63:31); BFIw(xFlags, x3, F_SF, 1); } - IFX(X_PF) emit_pf(dyn, ninst, gd, x3); + IFX2(X_PF, && !BOX64ENV(cputype)) emit_pf(dyn, ninst, gd, x3); break; case 0x6C: case 0x6D: @@ -2981,17 +2989,20 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin UFLAG_DF(x2, d_none); } GETED(0); - UFLAG_IF { - if(!rex.w && !rex.is32bits && MODREG) {MOVw_REG(ed, ed);} - CBZw_NEXT(x3); + if(!rex.w && !rex.is32bits && MODREG) {MOVw_REG(ed, ed);} + CBZw_NEXT(x3); + IFX2(X_OF, && !BOX64ENV(cputype)) { + LSRxw(x4, ed, rex.w?62:30); + EORw_REG_LSR(x4, x4, x4, 1); + BFIw(xFlags, x4, F_OF, 1); } MOV64xw(x4, (rex.w?64:32)); SUBx_REG(x3, x4, x3); RORxw_REG(ed, ed, x3); WBACK; - IFX(X_OF) { - EORxw_REG_LSR(x3, ed, ed, rex.w?63:31); - BFIw(xFlags, x3, F_OF, 1); + IFX2(X_OF, && BOX64ENV(cputype)) { + EORxw_REG_LSR(x4, ed, ed, rex.w?63:31); + BFIw(xFlags, x4, F_OF, 1); } IFX(X_CF) { BFIw(xFlags, ed, F_CF, 1); @@ -3010,10 +3021,8 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin } SET_DFNONE(); GETED(0); - UFLAG_IF { - if(!rex.w && !rex.is32bits && MODREG) {MOVw_REG(ed, ed);} - CBZw_NEXT(x3); - } + if(!rex.w && !rex.is32bits && MODREG) {MOVw_REG(ed, ed);} + CBZw_NEXT(x3); IFX2(X_OF, && !BOX64ENV(cputype)) { EORxw_REG_LSR(x4, ed, ed, rex.w?63:31); BFIw(xFlags, x4, F_OF, 1); @@ -3537,7 +3546,11 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin break; case 5: INST_NAME("IMUL AL, Eb"); - SETFLAGS(X_ALL, SF_SET); + if(BOX64ENV(dynarec_safeflags)>1 && BOX64ENV(cputype)) { + SETFLAGS(X_OF|X_CF, SF_SET); + } else { + SETFLAGS(X_ALL, SF_SET); + } GETSEB(x1, 0); SXTBw(x2, xRAX); MULw(x1, x2, x1); @@ -3554,14 +3567,14 @@ 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) {BFCw(xFlags, F_AF, 1);} - IFX(X_ZF) {BFCw(xFlags, F_ZF, 1);} - IFX(X_SF) { + 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); } - IFX(X_PF) emit_pf(dyn, ninst, xRAX, x3); - break; + IFX2(X_PF, && !BOX64ENV(cputype)) emit_pf(dyn, ninst, xRAX, x3); + break; case 6: INST_NAME("DIV Eb"); SETFLAGS(X_ALL, SF_SET); @@ -3677,7 +3690,11 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin break; case 5: INST_NAME("IMUL EAX, Ed"); - SETFLAGS(X_ALL, SF_SET); + if(BOX64ENV(dynarec_safeflags)>1 && 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; @@ -3700,13 +3717,13 @@ 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) {BFCw(xFlags, F_AF, 1);} - IFX(X_ZF) {BFCw(xFlags, F_ZF, 1);} - IFX(X_SF) { + 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); } - IFX(X_PF) emit_pf(dyn, ninst, xRAX, x3); + IFX2(X_PF, && !BOX64ENV(cputype)) emit_pf(dyn, ninst, xRAX, x3); break; case 6: INST_NAME("DIV Ed"); diff --git a/src/dynarec/arm64/dynarec_arm64_0f.c b/src/dynarec/arm64/dynarec_arm64_0f.c index a032ce1546..b9a95f56bf 100644 --- a/src/dynarec/arm64/dynarec_arm64_0f.c +++ b/src/dynarec/arm64/dynarec_arm64_0f.c @@ -1722,8 +1722,11 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin break; case 0xA3: INST_NAME("BT Ed, Gd"); - SETFLAGS(X_ALL&~X_ZF, SF_SUBSET); - SET_DFNONE(); + if(!BOX64ENV(dynarec_safeflags)) { + SETFLAGS(X_ALL&~X_ZF, SF_SUBSET); + } else { + SETFLAGS(X_CF, SF_SUBSET); + } nextop = F8; GETGD; if(MODREG) { @@ -1746,12 +1749,6 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin LSRxw_REG(x4, ed, x2); BFIw(xFlags, x4, F_CF, 1); } - if (BOX64ENV(dynarec_test)) { - IFX(X_OF) {BFCw(xFlags, F_OF, 1);} - IFX(X_SF) {BFCw(xFlags, F_SF, 1);} - IFX(X_AF) {BFCw(xFlags, F_AF, 1);} - IFX(X_PF) {BFCw(xFlags, F_PF, 1);} - } break; case 0xA4: nextop = F8; @@ -1803,8 +1800,11 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin case 0xAB: INST_NAME("BTS Ed, Gd"); - SETFLAGS(X_ALL&~X_ZF, SF_SUBSET); - SET_DFNONE(); + if(!BOX64ENV(dynarec_safeflags)) { + SETFLAGS(X_ALL&~X_ZF, SF_SUBSET); + } else { + SETFLAGS(X_CF, SF_SUBSET); + } nextop = F8; GETGD; if(MODREG) { @@ -1836,12 +1836,6 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin STxw(ed, wback, fixedaddress); SMWRITE(); } - if (BOX64ENV(dynarec_test)) { - IFX(X_OF) {BFCw(xFlags, F_OF, 1);} - IFX(X_SF) {BFCw(xFlags, F_SF, 1);} - IFX(X_AF) {BFCw(xFlags, F_AF, 1);} - IFX(X_PF) {BFCw(xFlags, F_PF, 1);} - } break; case 0xAC: nextop = F8; @@ -2001,7 +1995,11 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin break; case 0xAF: INST_NAME("IMUL Gd, Ed"); - SETFLAGS(X_ALL, SF_SET); + if(BOX64ENV(dynarec_safeflags)>1 && BOX64ENV(cputype)) { + SETFLAGS(X_OF|X_CF, SF_SET); + } else { + SETFLAGS(X_ALL, SF_SET); + } nextop = F8; GETGD; GETED(0); @@ -2045,13 +2043,13 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin MULxw(gd, gd, ed); } } - IFX(X_AF) {BFCw(xFlags, F_AF, 1);} - IFX(X_ZF) {BFCw(xFlags, F_ZF, 1);} - IFX(X_SF) { + 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, gd, rex.w?63:31); BFIw(xFlags, x3, F_SF, 1); } - IFX(X_PF) emit_pf(dyn, ninst, gd, x3); + IFX2(X_PF, && !BOX64ENV(cputype)) emit_pf(dyn, ninst, gd, x3); break; case 0xB1: @@ -2083,7 +2081,11 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin case 0xB3: INST_NAME("BTR Ed, Gd"); - SETFLAGS(X_ALL&~X_ZF, SF_SUBSET); + if(!BOX64ENV(dynarec_safeflags)) { + SETFLAGS(X_ALL&~X_ZF, SF_SUBSET); + } else { + SETFLAGS(X_CF, SF_SUBSET); + } SET_DFNONE(); nextop = F8; GETGD; @@ -2116,12 +2118,6 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin STxw(ed, wback, fixedaddress); SMWRITE(); } - if (BOX64ENV(dynarec_test)) { - IFX(X_OF) {BFCw(xFlags, F_OF, 1);} - IFX(X_SF) {BFCw(xFlags, F_SF, 1);} - IFX(X_AF) {BFCw(xFlags, F_AF, 1);} - IFX(X_PF) {BFCw(xFlags, F_PF, 1);} - } break; case 0xB6: @@ -2163,8 +2159,11 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin switch((nextop>>3)&7) { case 4: INST_NAME("BT Ed, Ib"); - SETFLAGS(X_ALL&~X_ZF, SF_SUBSET); - SET_DFNONE(); + if(!BOX64ENV(dynarec_safeflags)) { + SETFLAGS(X_ALL&~X_ZF, SF_SUBSET); + } else { + SETFLAGS(X_CF, SF_SUBSET); + } gd = x2; if(MODREG) { ed = TO_NAT((nextop & 7) + (rex.b << 3)); @@ -2179,17 +2178,14 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin IFX(X_CF) { BFXILxw(xFlags, ed, u8, 1); // inject 1 bit from u8 to F_CF (i.e. pos 0) } - if (BOX64ENV(dynarec_test)) { - IFX(X_OF) {BFCw(xFlags, F_OF, 1);} - IFX(X_SF) {BFCw(xFlags, F_SF, 1);} - IFX(X_AF) {BFCw(xFlags, F_AF, 1);} - IFX(X_PF) {BFCw(xFlags, F_PF, 1);} - } break; case 5: INST_NAME("BTS Ed, Ib"); - SETFLAGS(X_ALL&~X_ZF, SF_SUBSET); - SET_DFNONE(); + if(!BOX64ENV(dynarec_safeflags)) { + SETFLAGS(X_ALL&~X_ZF, SF_SUBSET); + } else { + SETFLAGS(X_CF, SF_SUBSET); + } if(MODREG) { ed = TO_NAT((nextop & 7) + (rex.b << 3)); wback = 0; @@ -2210,17 +2206,14 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin STxw(ed, wback, fixedaddress); SMWRITE(); } - if (BOX64ENV(dynarec_test)) { - IFX(X_OF) {BFCw(xFlags, F_OF, 1);} - IFX(X_SF) {BFCw(xFlags, F_SF, 1);} - IFX(X_AF) {BFCw(xFlags, F_AF, 1);} - IFX(X_PF) {BFCw(xFlags, F_PF, 1);} - } break; case 6: INST_NAME("BTR Ed, Ib"); - SETFLAGS(X_ALL&~X_ZF, SF_SUBSET); - SET_DFNONE(); + if(!BOX64ENV(dynarec_safeflags)) { + SETFLAGS(X_ALL&~X_ZF, SF_SUBSET); + } else { + SETFLAGS(X_CF, SF_SUBSET); + } if(MODREG) { ed = TO_NAT((nextop & 7) + (rex.b << 3)); wback = 0; @@ -2240,17 +2233,14 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin STxw(ed, wback, fixedaddress); SMWRITE(); } - if (BOX64ENV(dynarec_test)) { - IFX(X_OF) {BFCw(xFlags, F_OF, 1);} - IFX(X_SF) {BFCw(xFlags, F_SF, 1);} - IFX(X_AF) {BFCw(xFlags, F_AF, 1);} - IFX(X_PF) {BFCw(xFlags, F_PF, 1);} - } break; case 7: INST_NAME("BTC Ed, Ib"); - SETFLAGS(X_ALL&~X_ZF, SF_SUBSET); - SET_DFNONE(); + if(!BOX64ENV(dynarec_safeflags)) { + SETFLAGS(X_ALL&~X_ZF, SF_SUBSET); + } else { + SETFLAGS(X_CF, SF_SUBSET); + } if(MODREG) { ed = TO_NAT((nextop & 7) + (rex.b << 3)); wback = 0; @@ -2271,12 +2261,6 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin STxw(ed, wback, fixedaddress); SMWRITE(); } - if (BOX64ENV(dynarec_test)) { - IFX(X_OF) {BFCw(xFlags, F_OF, 1);} - IFX(X_SF) {BFCw(xFlags, F_SF, 1);} - IFX(X_AF) {BFCw(xFlags, F_AF, 1);} - IFX(X_PF) {BFCw(xFlags, F_PF, 1);} - } break; default: DEFAULT; @@ -2284,8 +2268,11 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin break; case 0xBB: INST_NAME("BTC Ed, Gd"); - SETFLAGS(X_ALL&~X_ZF, SF_SUBSET); - SET_DFNONE(); + if(!BOX64ENV(dynarec_safeflags)) { + SETFLAGS(X_ALL&~X_ZF, SF_SUBSET); + } else { + SETFLAGS(X_CF, SF_SUBSET); + } nextop = F8; GETGD; if(MODREG) { @@ -2317,12 +2304,6 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin STxw(ed, wback, fixedaddress); SMWRITE(); } - if (BOX64ENV(dynarec_test)) { - IFX(X_OF) {BFCw(xFlags, F_OF, 1);} - IFX(X_SF) {BFCw(xFlags, F_SF, 1);} - IFX(X_AF) {BFCw(xFlags, F_AF, 1);} - IFX(X_PF) {BFCw(xFlags, F_PF, 1);} - } break; case 0xBC: INST_NAME("BSF Gd, Ed"); diff --git a/src/dynarec/arm64/dynarec_arm64_64.c b/src/dynarec/arm64/dynarec_arm64_64.c index d770d4c7f2..3aa3571ba4 100644 --- a/src/dynarec/arm64/dynarec_arm64_64.c +++ b/src/dynarec/arm64/dynarec_arm64_64.c @@ -271,7 +271,11 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin switch(rep) { case 0: INST_NAME("IMUL Gd, Ed"); - SETFLAGS(X_ALL, SF_SET); + if(BOX64ENV(dynarec_safeflags)>1 && BOX64ENV(cputype)) { + SETFLAGS(X_OF|X_CF, SF_SET); + } else { + SETFLAGS(X_ALL, SF_SET); + } nextop = F8; grab_segdata(dyn, addr, ninst, x4, seg, (MODREG)); GETGD; @@ -319,13 +323,13 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin MULxw(gd, gd, ed); } } - IFX(X_AF) {BFCw(xFlags, F_AF, 1);} - IFX(X_ZF) {BFCw(xFlags, F_ZF, 1);} - IFX(X_SF) { + 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, gd, rex.w?63:31); BFIw(xFlags, x3, F_SF, 1); } - IFX(X_PF) emit_pf(dyn, ninst, gd, x3); + IFX2(X_PF, && !BOX64ENV(cputype)) emit_pf(dyn, ninst, gd, x3); break; default: DEFAULT; @@ -537,7 +541,11 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin case 0x69: INST_NAME("IMUL Gd, Ed, Id"); - SETFLAGS(X_ALL, SF_SET); + if(BOX64ENV(dynarec_safeflags)>1 && BOX64ENV(cputype)) { + SETFLAGS(X_OF|X_CF, SF_SET); + } else { + SETFLAGS(X_ALL, SF_SET); + } nextop = F8; grab_segdata(dyn, addr, ninst, x4, seg, (MODREG)); GETGD; @@ -586,13 +594,13 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin MULxw(gd, ed, x4); } } - IFX(X_AF) {BFCw(xFlags, F_AF, 1);} - IFX(X_ZF) {BFCw(xFlags, F_ZF, 1);} - IFX(X_SF) { + 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, gd, rex.w?63:31); BFIw(xFlags, x3, F_SF, 1); } - IFX(X_PF) emit_pf(dyn, ninst, gd, x3); + IFX2(X_PF, && !BOX64ENV(cputype)) emit_pf(dyn, ninst, gd, x3); break; case 0x6C: @@ -1145,16 +1153,19 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin GETEDO(x6, 0); if(!rex.w && MODREG) {MOVw_REG(ed, ed);} CBZw_NEXT(x3); + IFX2(X_OF, && !BOX64ENV(cputype)) { + LSRxw(x4, ed, rex.w?62:30); + EORw_REG_LSR(x4, x4, x4, 1); + BFIw(xFlags, x4, F_OF, 1); + } RORxw_REG(ed, ed, x3); WBACKO(x6); - UFLAG_IF { // calculate flags directly - SUBw_U12(x4, x3, rex.w?63:31); - CBNZw_MARK(x4); - EORw_REG_LSR(x4, ed, ed, rex.w?63:31); - BFIw(xFlags, x4, F_OF, 1); - MARK; + IFX2(X_OF, && BOX64ENV(cputype)) { + EORxw_REG_LSR(x4, ed, ed, rex.w?63:31); + BFIw(xFlags, x4, F_OF, 1); + } + IFX(X_CF) { BFIw(xFlags, ed, F_CF, 1); - UFLAG_DF(x2, d_none); } break; case 1: @@ -1171,18 +1182,19 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin GETEDO(x6, 0); if(!rex.w && MODREG) {MOVw_REG(ed, ed);} CBZw_NEXT(x3); + IFX2(X_OF, && !BOX64ENV(cputype)) { + EORxw_REG_LSR(x4, ed, ed, rex.w?63:31); + BFIw(xFlags, x4, F_OF, 1); + } RORxw_REG(ed, ed, x3); WBACKO(x6); - UFLAG_IF { // calculate flags directly - SUBw_U12(x2, x3, 1); - CBNZw_MARK(x2); - LSRxw(x2, ed, rex.w?62:30); // x2 = d>>30 - EORw_REG_LSR(x2, x2, x2, 1); // x2 = ((d>>30) ^ ((d>>30)>>1)) - BFIw(xFlags, x2, F_OF, 1); - MARK; - LSRxw(x2, ed, rex.w?63:31); - BFIw(xFlags, x2, F_CF, 1); - UFLAG_DF(x2, d_none); + IFX2(X_OF, && BOX64ENV(cputype)) { + LSRxw(x2, ed, rex.w?62:30); // x2 = d>>30 + EORw_REG_LSR(x2, x2, x2, 1); // x2 = ((d>>30) ^ ((d>>30)>>1)) + BFIw(xFlags, x2, F_OF, 1); + } + IFX(X_CF) { + BFXILxw(xFlags, ed, rex.w?63:31, 1); } break; case 2: @@ -1350,7 +1362,11 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin break; case 5: INST_NAME("IMUL EAX, Ed"); - SETFLAGS(X_ALL, SF_SET); + if(BOX64ENV(dynarec_safeflags)>1 && 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; @@ -1374,13 +1390,13 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin BFIw(xFlags, x3, F_OF, 1); } } - IFX(X_AF) {BFCw(xFlags, F_AF, 1);} - IFX(X_ZF) {BFCw(xFlags, F_ZF, 1);} - IFX(X_SF) { + 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); } - IFX(X_PF) emit_pf(dyn, ninst, xRAX, x3); + IFX2(X_PF, && !BOX64ENV(cputype)) emit_pf(dyn, ninst, xRAX, x3); break; case 6: INST_NAME("DIV Ed"); diff --git a/src/dynarec/arm64/dynarec_arm64_66.c b/src/dynarec/arm64/dynarec_arm64_66.c index 89bc503e63..b0dc2160ac 100644 --- a/src/dynarec/arm64/dynarec_arm64_66.c +++ b/src/dynarec/arm64/dynarec_arm64_66.c @@ -436,7 +436,11 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin } else { INST_NAME("IMUL Gw,Ew,Ib"); } - SETFLAGS(X_ALL, SF_SET); + if(BOX64ENV(dynarec_safeflags)>1 && BOX64ENV(cputype)) { + SETFLAGS(X_OF|X_CF, SF_SET); + } else { + SETFLAGS(X_ALL, SF_SET); + } nextop = F8; GETSEW(x1, (opcode==0x69)?2:1); if(opcode==0x69) i32 = F16S; else i32 = F8S; @@ -456,13 +460,13 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin BFIw(xFlags, x3, F_OF, 1); } } - IFX(X_AF) {BFCw(xFlags, F_AF, 1);} - IFX(X_ZF) {BFCw(xFlags, F_ZF, 1);} - IFX(X_SF) { + 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)) { LSRw(x3, x2, 15); BFIw(xFlags, x3, F_SF, 1); } - IFX(X_PF) emit_pf(dyn, ninst, x2, x3); + IFX2(X_PF, && !BOX64ENV(cputype)) emit_pf(dyn, ninst, x2, x3); break; case 0x6A: INST_NAME("PUSH Ib"); @@ -1460,7 +1464,11 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin break; case 5: INST_NAME("IMUL AX, Ew"); - SETFLAGS(X_ALL, SF_SET); + if(BOX64ENV(dynarec_safeflags)>1 && BOX64ENV(cputype)) { + SETFLAGS(X_OF|X_CF, SF_SET); + } else { + SETFLAGS(X_ALL, SF_SET); + } GETSEW(x1, 0); SXTHw(x2, xRAX); MULw(x1, x2, x1); @@ -1478,13 +1486,13 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin BFIw(xFlags, x3, F_OF, 1); } } - IFX(X_AF) {BFCw(xFlags, F_AF, 1);} - IFX(X_ZF) {BFCw(xFlags, F_ZF, 1);} - IFX(X_SF) { + 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); } - IFX(X_PF) emit_pf(dyn, ninst, xRAX, x3); + IFX2(X_PF, && !BOX64ENV(cputype)) emit_pf(dyn, ninst, xRAX, x3); break; case 6: INST_NAME("DIV Ew"); diff --git a/src/dynarec/arm64/dynarec_arm64_660f.c b/src/dynarec/arm64/dynarec_arm64_660f.c index a1fa87ec6b..d43a2be824 100644 --- a/src/dynarec/arm64/dynarec_arm64_660f.c +++ b/src/dynarec/arm64/dynarec_arm64_660f.c @@ -2351,8 +2351,11 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n case 0xA3: INST_NAME("BT Ew, Gw"); - SETFLAGS(X_ALL&~X_ZF, SF_SUBSET); - SET_DFNONE(); + if(!BOX64ENV(dynarec_safeflags)) { + SETFLAGS(X_ALL&~X_ZF, SF_SUBSET); + } else { + SETFLAGS(X_CF, SF_SUBSET); + } nextop = F8; gd = TO_NAT(((nextop & 0x38) >> 3) + (rex.r << 3)); // GETGD if(MODREG) { @@ -2370,12 +2373,6 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n LSRw_REG(x1, ed, x2); BFIw(xFlags, x1, F_CF, 1); } - if (BOX64ENV(dynarec_test)) { - IFX(X_OF) {BFCw(xFlags, F_OF, 1);} - IFX(X_SF) {BFCw(xFlags, F_SF, 1);} - IFX(X_AF) {BFCw(xFlags, F_AF, 1);} - IFX(X_PF) {BFCw(xFlags, F_PF, 1);} - } break; case 0xA4: INST_NAME("SHLD Ew, Gw, Ib"); @@ -2413,8 +2410,11 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n case 0xAB: INST_NAME("BTS Ew, Gw"); - SETFLAGS(X_ALL&~X_ZF, SF_SUBSET); - SET_DFNONE(); + if(!BOX64ENV(dynarec_safeflags)) { + SETFLAGS(X_ALL&~X_ZF, SF_SUBSET); + } else { + SETFLAGS(X_CF, SF_SUBSET); + } nextop = F8; gd = TO_NAT(((nextop & 0x38) >> 3) + (rex.r << 3)); // GETGD if(MODREG) { @@ -2440,12 +2440,6 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n STH(ed, wback, fixedaddress); SMWRITE(); } - if (BOX64ENV(dynarec_test)) { - IFX(X_OF) {BFCw(xFlags, F_OF, 1);} - IFX(X_SF) {BFCw(xFlags, F_SF, 1);} - IFX(X_AF) {BFCw(xFlags, F_AF, 1);} - IFX(X_PF) {BFCw(xFlags, F_PF, 1);} - } break; case 0xAC: nextop = F8; @@ -2514,7 +2508,11 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n break; case 0xAF: INST_NAME("IMUL Gw,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); + } nextop = F8; GETSEW(x1, 0); GETSGW(x2); @@ -2522,7 +2520,7 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n GWBACK; SET_DFNONE(); IFX(X_CF|X_OF) { - ASRw(x1, x2, 16); + ASRw(x1, x2, 15); CMPSw_REG_ASR(x1, x2, 31); CSETw(x3, cNE); IFX(X_CF) { @@ -2532,19 +2530,22 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n BFIw(xFlags, x3, F_OF, 1); } } - IFX(X_AF) {BFCw(xFlags, F_AF, 1);} - IFX(X_ZF) {BFCw(xFlags, F_ZF, 1);} - IFX(X_SF) { + 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, gd, 15); BFIw(xFlags, x3, F_SF, 1); } - IFX(X_PF) emit_pf(dyn, ninst, gd, x3); + IFX2(X_PF, && !BOX64ENV(cputype)) emit_pf(dyn, ninst, gd, x3); break; case 0xB3: INST_NAME("BTR Ew, Gw"); - SETFLAGS(X_ALL&~X_ZF, SF_SUBSET); - SET_DFNONE(); + if(!BOX64ENV(dynarec_safeflags)) { + SETFLAGS(X_ALL&~X_ZF, SF_SUBSET); + } else { + SETFLAGS(X_CF, SF_SUBSET); + } nextop = F8; gd = TO_NAT(((nextop & 0x38) >> 3) + (rex.r << 3)); // GETGD if(MODREG) { @@ -2569,12 +2570,6 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n STH(ed, wback, fixedaddress); SMWRITE(); } - if (BOX64ENV(dynarec_test)) { - IFX(X_OF) {BFCw(xFlags, F_OF, 1);} - IFX(X_SF) {BFCw(xFlags, F_SF, 1);} - IFX(X_AF) {BFCw(xFlags, F_AF, 1);} - IFX(X_PF) {BFCw(xFlags, F_PF, 1);} - } break; case 0xB6: @@ -2619,8 +2614,11 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n switch((nextop>>3)&7) { case 4: INST_NAME("BT Ew, Ib"); - SETFLAGS(X_ALL&~X_ZF, SF_SUBSET); - SET_DFNONE(); + if(!BOX64ENV(dynarec_safeflags)) { + SETFLAGS(X_ALL&~X_ZF, SF_SUBSET); + } else { + SETFLAGS(X_CF, SF_SUBSET); + } gd = x2; GETEW(x1, 1); u8 = F8; @@ -2628,17 +2626,14 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n IFX(X_CF) { BFXILxw(xFlags, ed, u8, 1); // inject 1 bit from u8 to F_CF (i.e. pos 0) } - if (BOX64ENV(dynarec_test)) { - IFX(X_OF) {BFCw(xFlags, F_OF, 1);} - IFX(X_SF) {BFCw(xFlags, F_SF, 1);} - IFX(X_AF) {BFCw(xFlags, F_AF, 1);} - IFX(X_PF) {BFCw(xFlags, F_PF, 1);} - } break; case 5: INST_NAME("BTS Ew, Ib"); - SETFLAGS(X_ALL&~X_ZF, SF_SUBSET); - SET_DFNONE(); + if(!BOX64ENV(dynarec_safeflags)) { + SETFLAGS(X_ALL&~X_ZF, SF_SUBSET); + } else { + SETFLAGS(X_CF, SF_SUBSET); + } GETEW(x1, 1); u8 = F8; u8&=(rex.w?0x3f:0x0f); @@ -2648,17 +2643,14 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n mask = convert_bitmask_xw(1<>12)&1, mask&0x3F, (mask>>6)&0x3F); EWBACK; - if (BOX64ENV(dynarec_test)) { - IFX(X_OF) {BFCw(xFlags, F_OF, 1);} - IFX(X_SF) {BFCw(xFlags, F_SF, 1);} - IFX(X_AF) {BFCw(xFlags, F_AF, 1);} - IFX(X_PF) {BFCw(xFlags, F_PF, 1);} - } break; case 6: INST_NAME("BTR Ew, Ib"); - SETFLAGS(X_ALL&~X_ZF, SF_SUBSET); - SET_DFNONE(); + if(!BOX64ENV(dynarec_safeflags)) { + SETFLAGS(X_ALL&~X_ZF, SF_SUBSET); + } else { + SETFLAGS(X_CF, SF_SUBSET); + } GETEW(x1, 1); u8 = F8; u8&=(rex.w?0x3f:0x0f); @@ -2667,17 +2659,14 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n } BFCxw(ed, u8, 1); EWBACK; - if (BOX64ENV(dynarec_test)) { - IFX(X_OF) {BFCw(xFlags, F_OF, 1);} - IFX(X_SF) {BFCw(xFlags, F_SF, 1);} - IFX(X_AF) {BFCw(xFlags, F_AF, 1);} - IFX(X_PF) {BFCw(xFlags, F_PF, 1);} - } break; case 7: INST_NAME("BTC Ew, Ib"); - SETFLAGS(X_ALL&~X_ZF, SF_SUBSET); - SET_DFNONE(); + if(!BOX64ENV(dynarec_safeflags)) { + SETFLAGS(X_ALL&~X_ZF, SF_SUBSET); + } else { + SETFLAGS(X_CF, SF_SUBSET); + } GETEW(x1, 1); u8 = F8; u8&=(rex.w?0x3f:0x0f); @@ -2687,12 +2676,6 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n mask = convert_bitmask_xw(1<>12)&1, mask&0x3F, (mask>>6)&0x3F); EWBACK; - if (BOX64ENV(dynarec_test)) { - IFX(X_OF) {BFCw(xFlags, F_OF, 1);} - IFX(X_SF) {BFCw(xFlags, F_SF, 1);} - IFX(X_AF) {BFCw(xFlags, F_AF, 1);} - IFX(X_PF) {BFCw(xFlags, F_PF, 1);} - } break; default: DEFAULT; @@ -2700,8 +2683,11 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n break; case 0xBB: INST_NAME("BTC Ew, Gw"); - SETFLAGS(X_ALL&~X_ZF, SF_SUBSET); - SET_DFNONE(); + if(!BOX64ENV(dynarec_safeflags)) { + SETFLAGS(X_ALL&~X_ZF, SF_SUBSET); + } else { + SETFLAGS(X_CF, SF_SUBSET); + } nextop = F8; gd = TO_NAT(((nextop & 0x38) >> 3) + (rex.r << 3)); // GETGD if(MODREG) { @@ -2728,12 +2714,6 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n STH(ed, wback, fixedaddress); SMWRITE(); } - if (BOX64ENV(dynarec_test)) { - IFX(X_OF) {BFCw(xFlags, F_OF, 1);} - IFX(X_SF) {BFCw(xFlags, F_SF, 1);} - IFX(X_AF) {BFCw(xFlags, F_AF, 1);} - IFX(X_PF) {BFCw(xFlags, F_PF, 1);} - } break; case 0xBC: INST_NAME("BSF Gw,Ew"); diff --git a/src/dynarec/arm64/dynarec_arm64_67.c b/src/dynarec/arm64/dynarec_arm64_67.c index 4473c491a2..810a3a3345 100644 --- a/src/dynarec/arm64/dynarec_arm64_67.c +++ b/src/dynarec/arm64/dynarec_arm64_67.c @@ -917,7 +917,11 @@ uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin case 0x6B: INST_NAME("IMUL Gd, Ed, Ib"); - SETFLAGS(X_ALL, SF_SET); + if(BOX64ENV(dynarec_safeflags)>1 && BOX64ENV(cputype)) { + SETFLAGS(X_OF|X_CF, SF_SET); + } else { + SETFLAGS(X_ALL, SF_SET); + } nextop = F8; GETGD; GETED32(1); @@ -963,13 +967,13 @@ uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin MULxw(gd, ed, x4); } } - IFX(X_AF) {BFCw(xFlags, F_AF, 1);} - IFX(X_ZF) {BFCw(xFlags, F_ZF, 1);} - IFX(X_SF) { + 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, gd, rex.w?63:31); BFIw(xFlags, x3, F_SF, 1); } - IFX(X_PF) emit_pf(dyn, ninst, gd, x3); + IFX2(X_PF, && !BOX64ENV(cputype)) emit_pf(dyn, ninst, gd, x3); break; case 0x70: @@ -1496,7 +1500,11 @@ uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin break; case 5: INST_NAME("IMUL EAX, Ed"); - SETFLAGS(X_ALL, SF_SET); + if(BOX64ENV(dynarec_safeflags)>1 && 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; @@ -1519,13 +1527,13 @@ uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin BFIw(xFlags, x3, F_OF, 1); } } - IFX(X_AF) {BFCw(xFlags, F_AF, 1);} - IFX(X_ZF) {BFCw(xFlags, F_ZF, 1);} - IFX(X_SF) { + 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); } - IFX(X_PF) emit_pf(dyn, ninst, xRAX, x3); + IFX2(X_PF, && !BOX64ENV(cputype)) emit_pf(dyn, ninst, xRAX, x3); break; case 6: INST_NAME("DIV Ed"); diff --git a/src/dynarec/arm64/dynarec_arm64_emit_shift.c b/src/dynarec/arm64/dynarec_arm64_emit_shift.c index 7a290e5454..f0bafd1edb 100644 --- a/src/dynarec/arm64/dynarec_arm64_emit_shift.c +++ b/src/dynarec/arm64/dynarec_arm64_emit_shift.c @@ -79,10 +79,12 @@ void emit_shl32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3 BFIw(xFlags, s4, F_ZF, 1); } } - if (BOX64ENV(dynarec_test)) - IFX(X_AF) { + IFX(X_AF) { + if(BOX64ENV(cputype)) + ORRw_mask(xFlags, xFlags, 28, 0); // mask = 0x10 + else BFCw(xFlags, F_AF, 1); - } + } IFX(X_PF) { emit_pf(dyn, ninst, s1, s4); } @@ -145,7 +147,10 @@ void emit_shl32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, uint32_t c, i BFIw(xFlags, s4, F_OF, 1); } IFX(X_AF) { - BFCw(xFlags, F_AF, 1); + if(BOX64ENV(cputype)) + ORRw_mask(xFlags, xFlags, 28, 0); // mask = 0x10 + else + BFCw(xFlags, F_AF, 1); } IFX(X_PF) { if(c>7) { @@ -176,7 +181,7 @@ void emit_shr32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3 LSRxw_REG(s3, s1, s3); BFIw(xFlags, s3, 0, 1); } - IFX(X_OF) { + IFX2(X_OF, && !BOX64ENV(cputype)) { LSRxw(s4, s1, rex.w?63:31); BFIw(xFlags, s4, F_OF, 1); } @@ -184,6 +189,10 @@ void emit_shr32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3 IFX(X_PEND) { STRxw_U12(s1, xEmu, offsetof(x64emu_t, res)); } + IFX2(X_OF, && BOX64ENV(cputype)) { + LSRxw(s4, s1, rex.w?62:30); + BFIw(xFlags, s4, F_OF, 1); + } int need_tst = 0; IFX(X_ZF) need_tst = 1; IFXNATIVE(X_SF, NF_SF) need_tst = 1; @@ -201,7 +210,10 @@ void emit_shr32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3 } } IFX(X_AF) { - BFCw(xFlags, F_AF, 1); + if(BOX64ENV(cputype)) + ORRw_mask(xFlags, xFlags, 28, 0); // mask = 0x10 + else + BFCw(xFlags, F_AF, 1); } IFX(X_PF) { emit_pf(dyn, ninst, s1, s4); @@ -229,7 +241,7 @@ void emit_shr32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, uint32_t c, i BFIw(xFlags, s3, 0, 1); } } - IFX(X_OF) { + IFX2(X_OF, && !BOX64ENV(cputype)) { LSRxw(s4, s1, rex.w?63:31); BFIw(xFlags, s4, F_OF, 1); } @@ -237,6 +249,10 @@ void emit_shr32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, uint32_t c, i IFX(X_PEND) { STRxw_U12(s1, xEmu, offsetof(x64emu_t, res)); } + IFX2(X_OF, && BOX64ENV(cputype)) { + LSRxw(s4, s1, rex.w?62:30); + BFIw(xFlags, s4, F_OF, 1); + } int need_tst = 0; IFX(X_ZF) need_tst = 1; IFXNATIVE(X_SF, NF_SF) need_tst = 1; @@ -254,7 +270,10 @@ void emit_shr32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, uint32_t c, i } } IFX(X_AF) { - BFCw(xFlags, F_AF, 1); + if(BOX64ENV(cputype)) + ORRw_mask(xFlags, xFlags, 28, 0); // mask = 0x10 + else + BFCw(xFlags, F_AF, 1); } IFX(X_PF) { emit_pf(dyn, ninst, s1, s4); @@ -304,7 +323,10 @@ void emit_sar32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3 } } IFX(X_AF) { - BFCw(xFlags, F_AF, 1); + if(BOX64ENV(cputype)) + ORRw_mask(xFlags, xFlags, 28, 0); // mask = 0x10 + else + BFCw(xFlags, F_AF, 1); } IFX(X_PF) { emit_pf(dyn, ninst, s1, s4); @@ -352,7 +374,10 @@ void emit_sar32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, uint32_t c, i BFCw(xFlags, F_OF, 1); } IFX(X_AF) { - BFCw(xFlags, F_AF, 1); + if(BOX64ENV(cputype)) + ORRw_mask(xFlags, xFlags, 28, 0); // mask = 0x10 + else + BFCw(xFlags, F_AF, 1); } IFX(X_PF) { emit_pf(dyn, ninst, s1, s4); @@ -405,7 +430,10 @@ void emit_shl8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4) } COMP_ZFSF(s1, 8) IFX(X_AF) { - BFCw(xFlags, F_AF, 1); + if(BOX64ENV(cputype)) + ORRw_mask(xFlags, xFlags, 28, 0); // mask = 0x10 + else + BFCw(xFlags, F_AF, 1); } IFX(X_PF) { emit_pf(dyn, ninst, s1, s4); @@ -453,7 +481,10 @@ void emit_shl8c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int s BFIw(xFlags, s4, F_OF, 1); } IFX (X_AF) { - BFCw(xFlags, F_AF, 1); + if(BOX64ENV(cputype)) + ORRw_mask(xFlags, xFlags, 28, 0); // mask = 0x10 + else + BFCw(xFlags, F_AF, 1); } IFX(X_PF) { emit_pf(dyn, ninst, s1, s4); @@ -489,7 +520,10 @@ void emit_shr8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4) } COMP_ZFSF(s1, 8) IFX(X_AF) { - BFCw(xFlags, F_AF, 1); + if(BOX64ENV(cputype)) + ORRw_mask(xFlags, xFlags, 28, 0); // mask = 0x10 + else + BFCw(xFlags, F_AF, 1); } IFX(X_PF) { emit_pf(dyn, ninst, s1, s4); @@ -526,7 +560,10 @@ void emit_shr8c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int s } COMP_ZFSF(s1, 8) IFX(X_AF) { - BFCw(xFlags, F_AF, 1); + if(BOX64ENV(cputype)) + ORRw_mask(xFlags, xFlags, 28, 0); // mask = 0x10 + else + BFCw(xFlags, F_AF, 1); } IFX(X_PF) { emit_pf(dyn, ninst, s1, s4); @@ -556,10 +593,12 @@ void emit_sar8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4) IFX(X_OF) { BFCw(xFlags, F_OF, 1); } - if (BOX64ENV(dynarec_test)) - IFX(X_AF) { + IFX(X_AF) { + if(BOX64ENV(cputype)) + ORRw_mask(xFlags, xFlags, 28, 0); // mask = 0x10 + else BFCw(xFlags, F_AF, 1); - } + } IFX(X_PF) { emit_pf(dyn, ninst, s1, s4); } @@ -607,10 +646,12 @@ void emit_sar8c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int s } } } - if (BOX64ENV(dynarec_test)) - IFX(X_AF) { + IFX(X_AF) { + if(BOX64ENV(cputype)) + ORRw_mask(xFlags, xFlags, 28, 0); // mask = 0x10 + else BFCw(xFlags, F_AF, 1); - } + } } // emit SHL16 instruction, from s1 , shift s2, store result in s1 using s3 and s4 as scratch. s3 can be same as s2 @@ -655,7 +696,10 @@ void emit_shl16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4) } COMP_ZFSF(s1, 16) IFX(X_AF) { - BFCw(xFlags, F_AF, 1); + if(BOX64ENV(cputype)) + ORRw_mask(xFlags, xFlags, 28, 0); // mask = 0x10 + else + BFCw(xFlags, F_AF, 1); } IFX(X_PF) { emit_pf(dyn, ninst, s1, s4); @@ -676,7 +720,7 @@ void emit_shl16c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int } if(BOX64ENV(cputype)) { IFX(X_CF|X_OF) { - LSRw(s3, s1, 16-c); + LSRw(s3, s1, (c>16)?16:(16-c)); BFIw(xFlags, s3, F_CF, 1); } } else { @@ -702,7 +746,10 @@ void emit_shl16c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int BFIw(xFlags, s4, F_OF, 1); } IFX (X_AF) { - BFCw(xFlags, F_AF, 1); + if(BOX64ENV(cputype)) + ORRw_mask(xFlags, xFlags, 28, 0); // mask = 0x10 + else + BFCw(xFlags, F_AF, 1); } IFX(X_PF) { if(c>7) { @@ -728,7 +775,7 @@ void emit_shr16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4) LSRw_REG(s4, s1, s4); BFIw(xFlags, s4, 0, 1); } - IFX(X_OF) { + IFX2(X_OF, && !BOX64ENV(cputype)) { LSRw(s4, s1, 15); BFIw(xFlags, s4, F_OF, 1); } @@ -736,11 +783,17 @@ void emit_shr16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4) IFX(X_PEND) { STRH_U12(s1, xEmu, offsetof(x64emu_t, res)); } + IFX2(X_OF, && BOX64ENV(cputype)) { + LSRw(s4, s1, 14); + BFIw(xFlags, s4, F_OF, 1); + } COMP_ZFSF(s1, 16) - if (BOX64ENV(dynarec_test)) - IFX(X_AF) { + IFX(X_AF) { + if(BOX64ENV(cputype)) + ORRw_mask(xFlags, xFlags, 28, 0); // mask = 0x10 + else BFCw(xFlags, F_AF, 1); - } + } IFX(X_PF) { emit_pf(dyn, ninst, s1, s4); } @@ -767,7 +820,7 @@ void emit_shr16c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int BFIw(xFlags, s3, 0, 1); } } - IFX(X_OF) { + IFX2(X_OF, && !BOX64ENV(cputype)) { LSRw(s4, s1, 15); BFIw(xFlags, s4, F_OF, 1); } @@ -775,9 +828,16 @@ void emit_shr16c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int IFX(X_PEND) { STRH_U12(s1, xEmu, offsetof(x64emu_t, res)); } + IFX2(X_OF, && BOX64ENV(cputype)) { + LSRw(s4, s1, 14); + BFIw(xFlags, s4, F_OF, 1); + } COMP_ZFSF(s1, 16) IFX(X_AF) { - BFCw(xFlags, F_AF, 1); + if(BOX64ENV(cputype)) + ORRw_mask(xFlags, xFlags, 28, 0); // mask = 0x10 + else + BFCw(xFlags, F_AF, 1); } IFX(X_PF) { emit_pf(dyn, ninst, s1, s4); @@ -808,7 +868,10 @@ void emit_sar16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4) } COMP_ZFSF(s1, 16) IFX(X_AF) { - BFCw(xFlags, F_AF, 1); + if(BOX64ENV(cputype)) + ORRw_mask(xFlags, xFlags, 28, 0); // mask = 0x10 + else + BFCw(xFlags, F_AF, 1); } IFX(X_PF) { emit_pf(dyn, ninst, s1, s4); @@ -840,7 +903,10 @@ void emit_sar16c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int BFCw(xFlags, F_OF, 1); } IFX(X_AF) { - BFCw(xFlags, F_AF, 1); + if(BOX64ENV(cputype)) + ORRw_mask(xFlags, xFlags, 28, 0); // mask = 0x10 + else + BFCw(xFlags, F_AF, 1); } IFX(X_PF) { emit_pf(dyn, ninst, s1, s4); @@ -1059,12 +1125,20 @@ void emit_rcl16c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int { MAYUSE(s1); MAYUSE(s3); MAYUSE(s4); - if (!(c%17)) return; + if (!(c%17) && !BOX64ENV(cputype)) return; c%=17; - BFIw(s1, xFlags, 16, 1); // insert cf - IFX(X_OF|X_CF) { - BFXILw(xFlags, s1, 16-c, 1); + if(c) { + BFIw(s1, xFlags, 16, 1); // insert cf + if(BOX64ENV(cputype)) { + IFX(X_OF|X_CF) { + BFXILw(xFlags, s1, 16-c, 1); + } + } else { + IFX(X_CF) { + BFXILw(xFlags, s1, 16-c, 1); + } + } } if(!BOX64ENV(cputype)) IFX(X_OF) { @@ -1072,8 +1146,10 @@ void emit_rcl16c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int EORw_REG_LSR(s3, s3, s3, 1); BFIw(xFlags, s3, F_OF, 1); } - ORRx_REG_LSL(s1, s1, s1, 17); // insert s1 again - LSRx_IMM(s1, s1, 17-c); // do the rcl + if(c) { + ORRx_REG_LSL(s1, s1, s1, 17); // insert s1 again + LSRx_IMM(s1, s1, 17-c); // do the rcl + } if(BOX64ENV(cputype)) IFX(X_OF) { EORw_REG_LSR(s3, xFlags, s1, 15); @@ -1086,21 +1162,28 @@ void emit_rcr16c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int { MAYUSE(s1); MAYUSE(s3); MAYUSE(s4); - if (!(c%17)) return; + if (!(c%17) && !BOX64ENV(cputype)) return; c%=17; - BFIw(s1, xFlags, 16, 1); // insert cf - IFX(X_OF) { + IFX2(X_OF, && !BOX64ENV(cputype)) { EORw_REG_LSR(s3, xFlags, s1, 15); BFIw(xFlags, s3, F_OF, 1); } - IFX(X_CF) { - BFXILx(xFlags, s1, c-1, 1); + if(c) { + BFIw(s1, xFlags, 16, 1); // insert cf + IFX(X_CF) { + BFXILx(xFlags, s1, c-1, 1); + } + if(c>1) { + ORRx_REG_LSL(s1, s1, s1, 17); // insert s1 again + } + LSRx_IMM(s1, s1, c); // do the rcr } - if(c>1) { - ORRx_REG_LSL(s1, s1, s1, 17); // insert s1 again + IFX2(X_OF, && BOX64ENV(cputype)) { + LSRw(s4, s1, 14); + EORw_REG_LSR(s4, s4, s4, 1); + BFIw(xFlags, s4, F_OF, 1); } - LSRx_IMM(s1, s1, c); // do the rcr } // emit RCL32/RCL64 instruction, from s1 , constant c, store result in s1 using s3 and s4 as scratch @@ -1110,9 +1193,21 @@ void emit_rcl32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, uint32_t c, i if(!c) return; - IFX(X_OF|X_CF) { - LSRxw_IMM(s3, s1, (rex.w?64:32)-c); + if(BOX64ENV(cputype)) { + IFX(X_OF|X_CF) { + LSRxw_IMM(s3, s1, (rex.w?64:32)-c); + } + } else { + IFX(X_CF) { + LSRxw_IMM(s3, s1, (rex.w?64:32)-c); + } } + if(!BOX64ENV(cputype)) + IFX(X_OF) { + LSRxw(s4, s1, rex.w?62:30); + EORw_REG_LSR(s4, s4, s4, 1); + BFIw(xFlags, s4, F_OF, 1); + } if(c==1) { LSLxw(s1, s1, 1); BFIxw(s1, xFlags, 0, 1); @@ -1124,7 +1219,7 @@ void emit_rcl32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, uint32_t c, i IFX(X_CF) { BFIw(xFlags, s3, F_CF, 1); } - IFX(X_OF) { + IFX2(X_OF, && BOX64ENV(cputype)) { EORxw_REG_LSR(s3, s3, s1, rex.w?63:31); BFIw(xFlags, s3, F_OF, 1); } @@ -1136,7 +1231,7 @@ void emit_rcr32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, uint32_t c, i if(!c) return; - IFX(X_OF) { + IFX2(X_OF, && !BOX64ENV(cputype)) { EORxw_REG_LSR(s3, xFlags, s1, rex.w?63:31); BFIw(xFlags, s3, F_OF, 1); } @@ -1154,6 +1249,11 @@ void emit_rcr32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, uint32_t c, i IFX(X_CF) { BFIw(wFlags, s3, 0, 1); } + IFX2(X_OF, && BOX64ENV(cputype)) { + LSRxw(s4, s1, rex.w?62:30); + EORw_REG_LSR(s4, s4, s4, 1); + BFIw(xFlags, s4, F_OF, 1); + } } // emit SHRD32 instruction, from s1, fill s2 , constant c, store result in s1 using s3 and s4 as scratch @@ -1174,16 +1274,14 @@ void emit_shrd32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, uint EORx_REG_LSR(s3, s2, s1, rex.w?63:31); // OF is set if sign changed BFIw(xFlags, s3, F_OF, 1); } - IFX2(X_OF, && BOX64ENV(cputype)) { - LSRxw(s4, s1, rex.w?63:31); - } EXTRxw(s1, s2, s1, c); IFX(X_PEND) { STRxw_U12(s1, xEmu, offsetof(x64emu_t, res)); } IFX2(X_OF, && BOX64ENV(cputype)) { - EORx_REG_LSR(s3, s4, s1, rex.w?63:31); // OF is set if sign changed - BFIw(xFlags, s3, F_OF, 1); + LSRxw(s4, s1, rex.w?62:30); + EORx_REG_LSR(s4, s4, s4, 1); // OF is set if sign changed + BFIw(xFlags, s4, F_OF, 1); } int need_tst = 0; IFX(X_ZF) need_tst = 1; @@ -1201,7 +1299,12 @@ void emit_shrd32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, uint BFIx(xFlags, s4, F_SF, 1); } } - IFX(X_AF) {BFCw(xFlags, F_AF, 1);} + IFX(X_AF) { + if(BOX64ENV(cputype)) + ORRw_mask(xFlags, xFlags, 28, 0); // mask = 0x10 + else + BFCw(xFlags, F_AF, 1); + } IFX(X_PF) { emit_pf(dyn, ninst, s1, s4); } @@ -1217,11 +1320,14 @@ void emit_shld32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, uint } else { SET_DFNONE(); } - IFX(X_CF) { - BFXILx(xFlags, s1, (rex.w?64:32)-c, 1); - } - IFX2(X_OF, && BOX64ENV(cputype)) { - LSRxw(s4, s1, rex.w?63:31); + if(BOX64ENV(cputype)) { + IFX(X_CF|X_OF) { + BFXILx(xFlags, s1, (rex.w?64:32)-c, 1); + } + } else { + IFX(X_CF) { + BFXILx(xFlags, s1, (rex.w?64:32)-c, 1); + } } IFX2(X_OF, && !BOX64ENV(cputype)) { LSRxw(s3, s1, rex.w?62:30); @@ -1234,7 +1340,7 @@ void emit_shld32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, uint STRxw_U12(s1, xEmu, offsetof(x64emu_t, res)); } IFX2(X_OF, && BOX64ENV(cputype)) { - EORx_REG_LSR(s3, s4, s1, rex.w?63:31); // OF is set if sign changed + EORx_REG_LSR(s3, xFlags, s1, rex.w?63:31); // OF is set if sign changed BFIw(xFlags, s3, F_OF, 1); } int need_tst = 0; @@ -1253,7 +1359,12 @@ void emit_shld32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, uint BFIx(xFlags, s4, F_SF, 1); } } - IFX(X_AF) {BFCw(xFlags, F_AF, 1);} + IFX(X_AF) { + if(BOX64ENV(cputype)) + ORRw_mask(xFlags, xFlags, 28, 0); // mask = 0x10 + else + BFCw(xFlags, F_AF, 1); + } IFX(X_PF) { emit_pf(dyn, ninst, s1, s4); } @@ -1279,9 +1390,6 @@ void emit_shrd32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s EORx_REG_LSR(s3, s2, s1, rex.w?63:31); // OF is set if sign changed BFIw(xFlags, s3, F_OF, 1); } - IFX2(X_OF, && BOX64ENV(cputype)) { - LSRxw(s4, s1, rex.w?63:31); - } if(s1==s2) { RORxw_REG(s1, s1, s5); } else { @@ -1295,8 +1403,9 @@ void emit_shrd32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s STRxw_U12(s1, xEmu, offsetof(x64emu_t, res)); } IFX2(X_OF, && BOX64ENV(cputype)) { - EORxw_REG_LSR(s3, s4, s1, rex.w?63:31); // OF is set if sign changed - BFIw(xFlags, s3, F_OF, 1); + LSRxw(s4, s1, rex.w?62:30); + EORx_REG_LSR(s4, s4, s4, 1); // OF is set if sign changed + BFIw(xFlags, s4, F_OF, 1); } int need_tst = 0; IFX(X_ZF) need_tst = 1; @@ -1314,7 +1423,12 @@ void emit_shrd32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s BFIx(xFlags, s4, F_SF, 1); } } - IFX(X_AF) {BFCw(xFlags, F_AF, 1);} + IFX(X_AF) { + if(BOX64ENV(cputype)) + ORRw_mask(xFlags, xFlags, 28, 0); // mask = 0x10 + else + BFCw(xFlags, F_AF, 1); + } IFX(X_PF) { emit_pf(dyn, ninst, s1, s4); } @@ -1331,12 +1445,16 @@ void emit_shld32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s } MOV32w(s3, (rex.w?64:32)); SUBw_REG(s3, s3, s5); - IFX(X_CF) { - LSRxw_REG(s4, s1, s3); - BFIxw(xFlags, s4, F_CF, 1); - } - IFX2(X_OF, && BOX64ENV(cputype)) { - LSRxw(s4, s1, rex.w?63:31); + if(BOX64ENV(cputype)) { + IFX(X_CF|X_OF) { + LSRxw_REG(s4, s1, s3); + BFIxw(xFlags, s4, F_CF, 1); + } + } else { + IFX(X_CF) { + LSRxw_REG(s4, s1, s3); + BFIxw(xFlags, s4, F_CF, 1); + } } IFX2(X_OF, && !BOX64ENV(cputype)) { LSRxw(s4, s1, rex.w?62:30); @@ -1355,7 +1473,7 @@ void emit_shld32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s STRxw_U12(s1, xEmu, offsetof(x64emu_t, res)); } IFX2(X_OF, && BOX64ENV(cputype)) { - EORx_REG_LSR(s3, s4, s1, rex.w?63:31); // OF is set if sign changed + EORx_REG_LSR(s3, xFlags, s1, rex.w?63:31); // OF is set if sign changed BFIw(xFlags, s3, F_OF, 1); } int need_tst = 0; @@ -1374,7 +1492,12 @@ void emit_shld32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s BFIx(xFlags, s4, F_SF, 1); } } - IFX(X_AF) {BFCw(xFlags, F_AF, 1);} + IFX(X_AF) { + if(BOX64ENV(cputype)) + ORRw_mask(xFlags, xFlags, 28, 0); // mask = 0x10 + else + BFCw(xFlags, F_AF, 1); + } IFX(X_PF) { emit_pf(dyn, ninst, s1, s4); } @@ -1412,7 +1535,12 @@ void emit_shrd16c(dynarec_arm_t* dyn, int ninst, int s1, int s2, uint32_t c, int BFIw(xFlags, s3, F_OF, 1); } COMP_ZFSF(s1, 16) - IFX(X_AF) {BFCw(xFlags, F_AF, 1);} + IFX(X_AF) { + if(BOX64ENV(cputype)) + ORRw_mask(xFlags, xFlags, 28, 0); // mask = 0x10 + else + BFCw(xFlags, F_AF, 1); + } IFX(X_PF) { emit_pf(dyn, ninst, s1, s4); } @@ -1451,7 +1579,12 @@ void emit_shrd16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s5, int s3, BFIw(xFlags, s3, F_OF, 1); } COMP_ZFSF(s1, 16) - IFX(X_AF) {BFCw(xFlags, F_AF, 1);} + IFX(X_AF) { + if(BOX64ENV(cputype)) + ORRw_mask(xFlags, xFlags, 28, 0); // mask = 0x10 + else + BFCw(xFlags, F_AF, 1); + } IFX(X_PF) { emit_pf(dyn, ninst, s1, s4); } @@ -1469,33 +1602,45 @@ void emit_shld16c(dynarec_arm_t* dyn, int ninst, int s1, int s2, uint32_t c, int SET_DFNONE(); } BFIw(s1, s2, 16, 16); // create concat first - IFX(X_CF) { - if(c<=16) - LSRw(s3, s1, 16-c); - else - LSRw(s3, s2, 32-c); - BFIw(xFlags, s3, F_CF, 1); + if(BOX64ENV(cputype)) { + IFX(X_CF|X_OF) { + if(c<=16) + BFXILw(xFlags, s1, 16-c, 1); + else + BFCw(xFlags, F_CF, 1); + } + } else { + IFX(X_CF) { + if(c<=16) + BFXILw(xFlags, s1, 16-c, 1); + else + BFXILw(xFlags, s2, 32-c, 1); + } + IFX(X_OF) { + LSRw(s4, s1, 14); + EORw_REG_LSR(s4, s4, s4, 1); // OF is set if sign changed + BFIw(xFlags, s4, F_OF, 1); + } } + RORw(s1, s1, 32-c); IFX2(X_OF, && BOX64ENV(cputype)) { - LSRw(s4, s1, 15); - } - IFX2(X_OF, && !BOX64ENV(cputype)) { - LSRw(s4, s1, 14); - EORw_REG_LSR(s4, s4, s4, 1); // OF is set if sign changed - BFIw(xFlags, s4, F_OF, 1); + if(c>15) + BFIw(xFlags, xFlags, F_OF, 1); // copy CF + else { + EORw_REG_LSR(s4, xFlags, s1, 15); + BFIw(xFlags, s4, F_OF, 1); + } } - if(c) - RORw(s1, s1, 32-c); - + COMP_ZFSF(s1, 16) IFX(X_PEND) { STRH_U12(s1, xEmu, offsetof(x64emu_t, res)); } - COMP_ZFSF(s1, 16) - IFX2(X_OF, && BOX64ENV(cputype)) { - EORw_REG_LSR(s3, s4, s1, 15); // OF is set if sign changed - BFIw(xFlags, s3, F_OF, 1); + IFX(X_AF) { + if(BOX64ENV(cputype)) + ORRw_mask(xFlags, xFlags, 28, 0); // mask = 0x10 + else + BFCw(xFlags, F_AF, 1); } - IFX(X_AF) {BFCw(xFlags, F_AF, 1);} IFX(X_PF) { emit_pf(dyn, ninst, s1, s4); } @@ -1538,7 +1683,12 @@ void emit_shld16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s5, int s3, BFIw(xFlags, s3, F_OF, 1); } COMP_ZFSF(s1, 16) - IFX(X_AF) {BFCw(xFlags, F_AF, 1);} + IFX(X_AF) { + if(BOX64ENV(cputype)) + ORRw_mask(xFlags, xFlags, 28, 0); // mask = 0x10 + else + BFCw(xFlags, F_AF, 1); + } IFX(X_PF) { emit_pf(dyn, ninst, s1, s4); } diff --git a/src/dynarec/arm64/dynarec_arm64_f0.c b/src/dynarec/arm64/dynarec_arm64_f0.c index 6ec7fcbd0f..5841dbbdc1 100644 --- a/src/dynarec/arm64/dynarec_arm64_f0.c +++ b/src/dynarec/arm64/dynarec_arm64_f0.c @@ -212,8 +212,11 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin case 0xAB: INST_NAME("LOCK BTS Ed, Gd"); - SETFLAGS(X_ALL&~X_ZF, SF_SUBSET); - SET_DFNONE(); + if(!BOX64ENV(dynarec_safeflags)) { + SETFLAGS(X_ALL&~X_ZF, SF_SUBSET); + } else { + SETFLAGS(X_CF, SF_SUBSET); + } nextop = F8; GETGD; if(MODREG) { @@ -258,12 +261,6 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin CBNZw_MARKLOCK(x4); SMDMB(); } - if (BOX64ENV(dynarec_test)) { - IFX(X_OF) {BFCw(xFlags, F_OF, 1);} - IFX(X_SF) {BFCw(xFlags, F_SF, 1);} - IFX(X_AF) {BFCw(xFlags, F_AF, 1);} - IFX(X_PF) {BFCw(xFlags, F_PF, 1);} - } break; case 0xB0: switch(rep) { @@ -415,8 +412,11 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin case 0xB3: INST_NAME("LOCK BTR Ed, Gd"); - SETFLAGS(X_ALL&~X_ZF, SF_SUBSET); - SET_DFNONE(); + if(!BOX64ENV(dynarec_safeflags)) { + SETFLAGS(X_ALL&~X_ZF, SF_SUBSET); + } else { + SETFLAGS(X_CF, SF_SUBSET); + } nextop = F8; GETGD; if(MODREG) { @@ -456,12 +456,6 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin CBNZw_MARKLOCK(x4); SMDMB(); } - if (BOX64ENV(dynarec_test)) { - IFX(X_OF) {BFCw(xFlags, F_OF, 1);} - IFX(X_SF) {BFCw(xFlags, F_SF, 1);} - IFX(X_AF) {BFCw(xFlags, F_AF, 1);} - IFX(X_PF) {BFCw(xFlags, F_PF, 1);} - } break; case 0xBA: @@ -469,8 +463,11 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin switch((nextop>>3)&7) { case 4: INST_NAME("LOCK BT Ed, Ib"); - SETFLAGS(X_ALL&~X_ZF, SF_SUBSET); - SET_DFNONE(); + if(!BOX64ENV(dynarec_safeflags)) { + SETFLAGS(X_ALL&~X_ZF, SF_SUBSET); + } else { + SETFLAGS(X_CF, SF_SUBSET); + } gd = x2; if(MODREG) { ed = TO_NAT((nextop & 7) + (rex.b << 3)); @@ -495,17 +492,14 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin BFXILxw(xFlags, x1, u8&7, 1); // inject 1 bit from u8 to F_CF (i.e. pos 0) } } - if (BOX64ENV(dynarec_test)) { - IFX(X_OF) {BFCw(xFlags, F_OF, 1);} - IFX(X_SF) {BFCw(xFlags, F_SF, 1);} - IFX(X_AF) {BFCw(xFlags, F_AF, 1);} - IFX(X_PF) {BFCw(xFlags, F_PF, 1);} - } break; case 5: INST_NAME("LOCK BTS Ed, Ib"); - SETFLAGS(X_ALL&~X_ZF, SF_SUBSET); - SET_DFNONE(); + if(!BOX64ENV(dynarec_safeflags)) { + SETFLAGS(X_ALL&~X_ZF, SF_SUBSET); + } else { + SETFLAGS(X_CF, SF_SUBSET); + } if(MODREG) { ed = TO_NAT((nextop & 7) + (rex.b << 3)); wback = 0; @@ -514,12 +508,6 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin IFX(X_CF) { BFXILxw(xFlags, ed, u8, 1); // inject 1 bit from u8 to F_CF (i.e. pos 0) } - if (BOX64ENV(dynarec_test)) { - IFX(X_OF) {BFCw(xFlags, F_OF, 1);} - IFX(X_SF) {BFCw(xFlags, F_SF, 1);} - IFX(X_AF) {BFCw(xFlags, F_AF, 1);} - IFX(X_PF) {BFCw(xFlags, F_PF, 1);} - } mask = convert_bitmask_xw(1LL<>12)&1, mask&0x3F, (mask>>6)&0x3F); } else { @@ -536,12 +524,6 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin IFX(X_CF) { BFXILw(xFlags, ed, u8&7, 1); // inject 1 bit from u8 to F_CF (i.e. pos 0) } - if (BOX64ENV(dynarec_test)) { - IFX(X_OF) {BFCw(xFlags, F_OF, 1);} - IFX(X_SF) {BFCw(xFlags, F_SF, 1);} - IFX(X_AF) {BFCw(xFlags, F_AF, 1);} - IFX(X_PF) {BFCw(xFlags, F_PF, 1);} - } mask = convert_bitmask_xw(1LL<<(u8&7)); ORRxw_mask(ed, ed, (mask>>12)&1, mask&0x3F, (mask>>6)&0x3F); STLXRB(x4, ed, wback); @@ -551,8 +533,11 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin break; case 6: INST_NAME("LOCK BTR Ed, Ib"); - SETFLAGS(X_ALL&~X_ZF, SF_SUBSET); - SET_DFNONE(); + if(!BOX64ENV(dynarec_safeflags)) { + SETFLAGS(X_ALL&~X_ZF, SF_SUBSET); + } else { + SETFLAGS(X_CF, SF_SUBSET); + } if(MODREG) { ed = TO_NAT((nextop & 7) + (rex.b << 3)); wback = 0; @@ -561,12 +546,6 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin IFX(X_CF) { BFXILxw(xFlags, ed, u8, 1); // inject 1 bit from u8 to F_CF (i.e. pos 0) } - if (BOX64ENV(dynarec_test)) { - IFX(X_OF) {BFCw(xFlags, F_OF, 1);} - IFX(X_SF) {BFCw(xFlags, F_SF, 1);} - IFX(X_AF) {BFCw(xFlags, F_AF, 1);} - IFX(X_PF) {BFCw(xFlags, F_PF, 1);} - } BFCxw(ed, u8, 1); } else { addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, NULL, 0, 0, rex, LOCK_LOCK, 0, 1); @@ -579,12 +558,6 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin MARKLOCK; LDAXRB(ed, wback); BFXILw(xFlags, ed, u8&7, 1); // inject 1 bit from u8 to F_CF (i.e. pos 0) - if (BOX64ENV(dynarec_test)) { - IFX(X_OF) {BFCw(xFlags, F_OF, 1);} - IFX(X_SF) {BFCw(xFlags, F_SF, 1);} - IFX(X_AF) {BFCw(xFlags, F_AF, 1);} - IFX(X_PF) {BFCw(xFlags, F_PF, 1);} - } BFCw(ed, u8&7, 1); STLXRB(x4, ed, wback); CBNZw_MARKLOCK(x4); @@ -593,8 +566,11 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin break; case 7: INST_NAME("LOCK BTC Ed, Ib"); - SETFLAGS(X_ALL&~X_ZF, SF_SUBSET); - SET_DFNONE(); + if(!BOX64ENV(dynarec_safeflags)) { + SETFLAGS(X_ALL&~X_ZF, SF_SUBSET); + } else { + SETFLAGS(X_CF, SF_SUBSET); + } if(MODREG) { ed = TO_NAT((nextop & 7) + (rex.b << 3)); wback = 0; @@ -603,12 +579,6 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin IFX(X_CF) { BFXILxw(xFlags, ed, u8, 1); // inject 1 bit from u8 to F_CF (i.e. pos 0) } - if (BOX64ENV(dynarec_test)) { - IFX(X_OF) {BFCw(xFlags, F_OF, 1);} - IFX(X_SF) {BFCw(xFlags, F_SF, 1);} - IFX(X_AF) {BFCw(xFlags, F_AF, 1);} - IFX(X_PF) {BFCw(xFlags, F_PF, 1);} - } MOV32w(x4, 1); EORxw_REG_LSL(ed, ed, x4, u8); } else { @@ -624,12 +594,6 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin IFX(X_CF) { BFXILw(xFlags, ed, u8&7, 1); // inject 1 bit from u8 to F_CF (i.e. pos 0) } - if (BOX64ENV(dynarec_test)) { - IFX(X_OF) {BFCw(xFlags, F_OF, 1);} - IFX(X_SF) {BFCw(xFlags, F_SF, 1);} - IFX(X_AF) {BFCw(xFlags, F_AF, 1);} - IFX(X_PF) {BFCw(xFlags, F_PF, 1);} - } mask = convert_bitmask_xw(1LL<<(u8&7)); ORRxw_mask(ed, ed, (mask>>12)&1, mask&0x3F, (mask>>6)&0x3F); STLXRB(x4, ed, wback); diff --git a/src/emu/x64primop.c b/src/emu/x64primop.c index e196143445..9c1f2865bd 100644 --- a/src/emu/x64primop.c +++ b/src/emu/x64primop.c @@ -543,7 +543,10 @@ uint16_t rcl16(x64emu_t *emu, uint16_t d, uint8_t s) res |= 1 << (cnt - 1); } CONDITIONAL_SET_FLAG(cf, F_CF); - CONDITIONAL_SET_FLAG((cf ^ (res >> 15)) & 0x1, F_OF); + if(BOX64ENV(cputype)) + CONDITIONAL_SET_FLAG((cf ^ (res >> 15)) & 0x1, F_OF); + else + CONDITIONAL_SET_FLAG((XOR2(d >> 14)), F_OF); } return (uint16_t)res; } @@ -564,7 +567,10 @@ uint32_t rcl32(x64emu_t *emu, uint32_t d, uint8_t s) res |= 1 << (cnt - 1); } CONDITIONAL_SET_FLAG(cf, F_CF); - CONDITIONAL_SET_FLAG((cf ^ (res >> 31)) & 0x1, F_OF); + if(BOX64ENV(cputype)) + CONDITIONAL_SET_FLAG((cf ^ (res >> 31)) & 0x1, F_OF); + else + CONDITIONAL_SET_FLAG((XOR2(d >> 30)), F_OF); } return res; } @@ -585,7 +591,10 @@ uint64_t rcl64(x64emu_t *emu, uint64_t d, uint8_t s) res |= 1LL << (cnt - 1); } CONDITIONAL_SET_FLAG(cf, F_CF); - CONDITIONAL_SET_FLAG((cf ^ (res >> 63)) & 0x1, F_OF); + if(BOX64ENV(cputype)) + CONDITIONAL_SET_FLAG((cf ^ (res >> 63)) & 0x1, F_OF); + else + CONDITIONAL_SET_FLAG((XOR2(d >> 62)), F_OF); } return res; } @@ -630,8 +639,8 @@ uint8_t rcr8(x64emu_t *emu, uint8_t d, uint8_t s) /* OVERFLOW is set *IFF* cnt==1, then it is the xor of CF and the most significant bit. Blecck. */ /* parenthesized... */ - CONDITIONAL_SET_FLAG((ocf ^ (d >> 7)) & 0x1, - F_OF); + if(!BOX64ENV(cputype)) + CONDITIONAL_SET_FLAG((ocf ^ (d >> 7)) & 0x1, F_OF); if (cnt == 1) { cf = d & 0x1; /* note hackery here. Access_flag(..) evaluates to either @@ -669,6 +678,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); } return (uint8_t)res; } @@ -684,8 +696,8 @@ uint16_t rcr16(x64emu_t *emu, uint16_t d, uint8_t s) res = d; if ((cnt = s % 17) != 0) { ocf = ACCESS_FLAG(F_CF) != 0; - CONDITIONAL_SET_FLAG((ocf ^ (d >> 15)) & 0x1, - F_OF); + if(!BOX64ENV(cputype)) + CONDITIONAL_SET_FLAG((ocf ^ (d >> 15)) & 0x1, F_OF); if (cnt == 1) { cf = d & 0x1; } else @@ -697,6 +709,8 @@ 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); } return (uint16_t)res; } @@ -712,8 +726,8 @@ uint32_t rcr32(x64emu_t *emu, uint32_t d, uint8_t s) res = d; if ((cnt = s) != 0) { ocf = ACCESS_FLAG(F_CF) != 0; - CONDITIONAL_SET_FLAG((ocf ^ (d >> 31)) & 0x1, - F_OF); + if(!BOX64ENV(cputype)) + CONDITIONAL_SET_FLAG((ocf ^ (d >> 31)) & 0x1, F_OF); if (cnt == 1) { cf = d & 0x1; } else { @@ -727,6 +741,8 @@ 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); } return res; } @@ -742,8 +758,8 @@ uint64_t rcr64(x64emu_t *emu, uint64_t d, uint8_t s) res = d; if ((cnt = s) != 0) { ocf = ACCESS_FLAG(F_CF) != 0; - CONDITIONAL_SET_FLAG((ocf ^ (d >> 63)) & 0x1, - F_OF); + if(!BOX64ENV(cputype)) + CONDITIONAL_SET_FLAG((ocf ^ (d >> 63)) & 0x1, F_OF); if (cnt == 1) { cf = d & 0x1; } else { @@ -757,6 +773,8 @@ 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); } return res; }