diff options
| author | ptitSeb <sebastien.chev@gmail.com> | 2024-12-26 19:10:27 +0100 |
|---|---|---|
| committer | ptitSeb <sebastien.chev@gmail.com> | 2024-12-26 19:10:27 +0100 |
| commit | e86c6359d654d2d1d91da873b7e8c2168619141e (patch) | |
| tree | 69cbeff5ef003a12ebd8a2d0a5debc10a5913393 | |
| parent | acce64b268a55a0fcec896d160c87b3e71a6e597 (diff) | |
| download | box64-e86c6359d654d2d1d91da873b7e8c2168619141e.tar.gz box64-e86c6359d654d2d1d91da873b7e8c2168619141e.zip | |
[INTERPRETER] Improved some shift operands nd [AR64_DYNAREC] Improved shift operands and [COSIM] reduce noise on shift operands
| -rw-r--r-- | src/dynarec/arm64/dynarec_arm64_emit_shift.c | 254 | ||||
| -rw-r--r-- | src/emu/x64primop.c | 42 | ||||
| -rw-r--r-- | src/emu/x64run_private.c | 28 |
3 files changed, 227 insertions, 97 deletions
diff --git a/src/dynarec/arm64/dynarec_arm64_emit_shift.c b/src/dynarec/arm64/dynarec_arm64_emit_shift.c index 5e648a25..85c3f7aa 100644 --- a/src/dynarec/arm64/dynarec_arm64_emit_shift.c +++ b/src/dynarec/arm64/dynarec_arm64_emit_shift.c @@ -159,8 +159,8 @@ void emit_shr32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3 } IFX(X_OF) { CMPSxw_U12(s2, 1); // if s2==1 - Bcond(cNE, 4+2*4); LSRxw(s4, s1, rex.w?63:31); + CSELw(s4, s4, xZR, cEQ); // clear bit if c!=1 BFIw(xFlags, s4, F_OF, 1); } LSRxw_REG(s1, s1, s2); @@ -243,6 +243,9 @@ 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); } + IFX(X_OF) if(c>1) { + BFCw(xFlags, F_OF, 1); + } IFX(X_PF) { emit_pf(dyn, ninst, s1, s4); } @@ -482,8 +485,8 @@ void emit_shr8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4) } IFX(X_OF) { CMPSw_U12(s2, 1); // if s2==1 - Bcond(cNE, 4+2*4); LSRw(s4, s1, 7); + CSELw(s4, s4, xZR, cEQ); BFIw(xFlags, s4, F_OF, 1); } LSRw_REG(s1, s1, s2); @@ -524,6 +527,8 @@ void emit_shr8c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int s if(c==1) { LSRw(s4, s1, 7); BFIw(xFlags, s4, F_OF, 1); + } else if(box64_dynarec_test) { + BFCw(xFlags, F_OF, 1); } } LSRw(s1, s1, c); @@ -561,8 +566,8 @@ void emit_sar8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4) } COMP_ZFSF(s1, 8) IFX(X_OF) { - SUBw_U12(s4, s2, 1); - CBNZw(s4, 4+4); + //SUBw_U12(s4, s2, 1); + //CBNZw(s4, 4+4); BFCw(xFlags, F_OF, 1); } if(box64_dynarec_test) @@ -596,7 +601,7 @@ void emit_sar8c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int s if(c<8) { COMP_ZFSF(s1, 8) IFX(X_OF) - if(c==1) { + if((c==1) || box64_dynarec_test) { BFCw(xFlags, F_OF, 1); } IFX(X_PF) { @@ -687,7 +692,7 @@ void emit_shl16c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int IFX2(X_SF, && !arm64_flagm) {} else {LSRw(s3, s1, 15);} // use COMP_ZFSF operation EORw_REG(s4, s3, xFlags); // CF is set if OF is asked BFIw(xFlags, s4, F_OF, 1); - } else { + } else if(box64_dynarec_test) { BFCw(xFlags, F_OF, 1); } } @@ -750,9 +755,9 @@ void emit_shr16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4) BFIw(xFlags, s4, 0, 1); } IFX(X_OF) { - SUBw_U12(s4, s2, 1); // if s2==1 - CBNZw(s4, 4+2*4); + CMPSw_U12(s2, 1); // if s2==1 LSRw(s4, s1, 15); + CSELw(s4, s4, xZR, 0); BFIw(xFlags, s4, F_OF, 1); } LSRw_REG(s1, s1, s2); @@ -794,6 +799,8 @@ void emit_shr16c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int if(c==1) { LSRw(s4, s1, 15); BFIw(xFlags, s4, F_OF, 1); + } else if(box64_dynarec_test) { + BFCw(xFlags, F_OF, 1); } } LSRw(s1, s1, c); @@ -830,8 +837,8 @@ void emit_sar16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4) STRH_U12(s1, xEmu, offsetof(x64emu_t, res)); } IFX(X_OF) { - SUBw_U12(s4, s2, 1); - CBNZw(s4, 4+4); + //SUBw_U12(s4, s2, 1); + //CBNZw(s4, 4+4); BFCw(xFlags, F_OF, 1); } COMP_ZFSF(s1, 16) @@ -866,7 +873,7 @@ void emit_sar16c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int } COMP_ZFSF(s1, 16) IFX(X_OF) - if(c==1) { + if((c==1) || box64_dynarec_test) { BFCw(xFlags, F_OF, 1); } if(box64_dynarec_test) @@ -894,6 +901,8 @@ void emit_rol32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, uint32_t c, i if(c==1) { EORxw_REG_LSR(s3, s1, s1, rex.w?63:31); BFIw(xFlags, s3, F_OF, 1); + } else if(box64_dynarec_test) { + BFCw(xFlags, F_OF, 1); } } } @@ -916,6 +925,8 @@ void emit_ror32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, uint32_t c, i LSRxw(s3, s1, rex.w?62:30); EORxw_REG_LSR(s3, s3, s3, 1); BFIw(xFlags, s3, F_OF, 1); + } else if(box64_dynarec_test) { + BFCw(xFlags, F_OF, 1); } } } @@ -941,6 +952,8 @@ void emit_rol8c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int s if(c==1) { EORw_REG_LSR(s3, s1, s1, 7); BFIw(xFlags, s3, F_OF, 1); + } else if(box64_dynarec_test) { + BFCw(xFlags, F_OF, 1); } } } @@ -966,6 +979,8 @@ void emit_ror8c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int s LSRw(s3, s1, 6); EORw_REG_LSR(s3, s3, s3, 1); BFIw(xFlags, s3, F_OF, 1); + } else if(box64_dynarec_test) { + BFCw(xFlags, F_OF, 1); } } } @@ -991,6 +1006,8 @@ void emit_rol16c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int if(c==1) { EORw_REG_LSR(s3, s1, s1, 15); BFIw(xFlags, s3, F_OF, 1); + } else if(box64_dynarec_test) { + BFCw(xFlags, F_OF, 1); } } } @@ -1016,6 +1033,8 @@ void emit_ror16c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int LSRw(s3, s1, 14); EORw_REG_LSR(s3, s3, s3, 1); BFIw(xFlags, s3, F_OF, 1); + } else if(box64_dynarec_test) { + BFCw(xFlags, F_OF, 1); } } } @@ -1048,6 +1067,8 @@ void emit_rcl8c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int s if(c==1) { EORw_REG_LSR(s3, s3, s1, 7); BFIw(xFlags, s3, F_OF, 1); + } else if(box64_dynarec_test) { + BFCw(xFlags, F_OF, 1); } } } @@ -1078,6 +1099,8 @@ void emit_rcr8c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int s if(c==1) { EORw_REG_LSR(s3, s3, s1, 7); BFIw(xFlags, s3, F_OF, 1); + } else if(box64_dynarec_test) { + BFCw(xFlags, F_OF, 1); } } } @@ -1109,6 +1132,8 @@ void emit_rcl16c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int if(c==1) { EORw_REG_LSR(s3, s3, s1, 15); BFIw(xFlags, s3, F_OF, 1); + } else if(box64_dynarec_test) { + BFCw(xFlags, F_OF, 1); } } } @@ -1138,6 +1163,8 @@ void emit_rcr16c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int if(c==1) { EORw_REG_LSR(s3, s3, s1, 15); BFIw(xFlags, s3, F_OF, 1); + } else if(box64_dynarec_test) { + BFCw(xFlags, F_OF, 1); } } } @@ -1169,6 +1196,8 @@ void emit_rcl32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, uint32_t c, i if(c==1) { EORxw_REG_LSR(s3, s3, s1, rex.w?63:31); BFIw(xFlags, s3, F_OF, 1); + } else if(box64_dynarec_test) { + BFCw(xFlags, F_OF, 1); } } } @@ -1185,6 +1214,8 @@ void emit_rcr32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, uint32_t c, i if(c==1) { EORxw_REG_LSR(s3, xFlags, s1, rex.w?63:31); BFIw(xFlags, s3, F_OF, 1); + } else if(box64_dynarec_test) { + BFCw(xFlags, F_OF, 1); } } IFX(X_CF) { @@ -1225,15 +1256,20 @@ void emit_shrd32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, uint BFXILxw(xFlags, s1, c-1, 1); // set CF } IFX(X_OF) { - if((c==1) || box64_dynarec_test) { + if(c==1) { LSRxw(s4, s1, rex.w?63:31); - BFIw(xFlags, s4, F_OF, 1); // store sign for later use } } EXTRxw(s1, s2, s1, c); IFX(X_PEND) { STRxw_U12(s1, xEmu, offsetof(x64emu_t, res)); } + IFX(X_OF) { + if(c==1) { + EORx_REG_LSR(s3, s4, s1, rex.w?63:31); // OF is set if sign changed + BFIw(xFlags, s3, F_OF, 1); + } + } int need_tst = 0; IFX(X_ZF) need_tst = 1; IFXNATIVE(X_SF, NF_SF) need_tst = 1; @@ -1250,11 +1286,9 @@ 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_OF) { - if(c==1) { - UBFXx(s3, s1, rex.w?63:31, 1); - EORw_REG_LSL(xFlags, xFlags, s3, F_OF); // OF is set if sign changed - } + if(box64_dynarec_test) { + IFX(X_AF) {BFCw(xFlags, F_AF, 1);} + IFX(X_OF) if(c>1) {BFCw(xFlags, F_OF, 1);} } IFX(X_PF) { emit_pf(dyn, ninst, s1, s4); @@ -1272,44 +1306,45 @@ void emit_shld32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, uint } else IFX(X_ALL) { SET_DFNONE(s4); } - if(c==0) { - IFX(X_OF) { - BFCw(xFlags, F_OF, 1); - } - IFX(X_PEND) { - STRxw_U12(s1, xEmu, offsetof(x64emu_t, res)); - } - return; - } IFX(X_CF) { BFXILx(xFlags, s1, (rex.w?64:32)-c, 1); } - IFX(X_OF) { - LSRxw(s3, s1, rex.w?63:31); - BFIw(xFlags, s3, F_OF, 1); // store current sign for later use + if(c==1) { + IFX(X_OF) { + LSRxw(s4, s1, rex.w?63:31); + } } EXTRxw(s1, s1, s2, (rex.w?64:32)-c); IFX(X_PEND) { STRxw_U12(s1, xEmu, offsetof(x64emu_t, res)); } + IFX(X_OF) { + if(c==1) { + EORx_REG_LSR(s3, s4, s1, rex.w?63:31); // OF is set if sign changed + BFIw(xFlags, s3, F_OF, 1); + } + } + int need_tst = 0; + IFX(X_ZF) need_tst = 1; + IFXNATIVE(X_SF, NF_SF) need_tst = 1; + if(need_tst) TSTxw_REG(s1, s1); IFX(X_ZF) { - TSTxw_REG(s1, s1); - CSETw(s4, cEQ); - BFIw(xFlags, s4, F_ZF, 1); + IFNATIVE(NF_EQ) {} else { + CSETw(s4, cEQ); + BFIw(xFlags, s4, F_ZF, 1); + } } IFX(X_SF) { - LSRxw(s4, s1, (rex.w)?63:31); - BFIx(xFlags, s4, F_SF, 1); - } - IFX(X_OF) { - if(c==1) { - UBFXx(s3, s1, rex.w?63:31, 1); - EORw_REG_LSL(xFlags, xFlags, s3, F_OF); // OF is set if sign changed - } else { - BFCw(xFlags, F_OF, 1); + IFNATIVE(NF_SF) {} else { + LSRxw(s4, s1, (rex.w)?63:31); + BFIx(xFlags, s4, F_SF, 1); } } + if(box64_dynarec_test) { + IFX(X_AF) {BFCw(xFlags, F_AF, 1);} + IFX(X_OF) if(c>1) {BFCw(xFlags, F_OF, 1);} + } IFX(X_PF) { emit_pf(dyn, ninst, s1, s4); } @@ -1333,16 +1368,32 @@ void emit_shrd32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s } IFX(X_OF) { LSRxw(s4, s1, rex.w?63:31); - BFIw(xFlags, s4, F_OF, 1); // store sign fr now } - LSRxw_REG(s3, s1, s5); - SUBxw_U12(s4, s5, rex.w?64:32); - NEGxw_REG(s4, s4); - LSLxw_REG(s4, s2, s4); - ORRxw_REG(s1, s3, s4); + if(s1==s2) { + RORxw_REG(s1, s1, s5); + } else { + LSRxw_REG(s1, s1, s5); + SUBxw_U12(s3, s5, rex.w?64:32); + NEGxw_REG(s3, s3); + LSLxw_REG(s3, s2, s3); + ORRxw_REG(s1, s1, s3); + } IFX(X_PEND) { STRxw_U12(s1, xEmu, offsetof(x64emu_t, res)); } + IFX(X_OF) { + if(box64_dynarec_test) { + CMPSw_U12(s5, 1); + EORxw_REG_LSR(s3, s4, s1, rex.w?63:31); // OF is set if sign changed + CSELw(s3, s3, xZR, cEQ); + BFIw(xFlags, s3, F_OF, 1); + } else { + //CMPSw_U12(s5, 1); + EORxw_REG_LSR(s3, s4, s1, rex.w?63:31); // OF is set if sign changed + // CSELw(s3, s3, xZR, cEQ); + BFIw(xFlags, s3, F_OF, 1); + } + } int need_tst = 0; IFX(X_ZF) need_tst = 1; IFXNATIVE(X_SF, NF_SF) need_tst = 1; @@ -1359,11 +1410,8 @@ 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_OF) { - SUBw_U12(s3, s5, 1); - CBNZw(s3, 4+2*4); //flagless jump - UBFXx(s3, s1, rex.w?63:31, 1); - EORw_REG_LSL(xFlags, xFlags, s3, F_OF); // OF is set if sign changed + if(box64_dynarec_test) { + IFX(X_AF) {BFCw(xFlags, F_AF, 1);} } IFX(X_PF) { emit_pf(dyn, ninst, s1, s4); @@ -1387,15 +1435,33 @@ void emit_shld32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s } IFX(X_OF) { LSRxw(s4, s1, rex.w?63:31); - BFIw(xFlags, s4, F_OF, 1); // store current sign for later use } - LSLxw_REG(s4, s1, s5); - LSRxw_REG(s3, s2, s3); - ORRxw_REG(s1, s3, s4); + if(s1==s2) { + SUBw_U12(s3, s5, rex.w?64:32); + SUBw_REG(s3, xZR, s3); + RORxw_REG(s1, s1, s3); + } else { + LSLxw_REG(s1, s1, s5); + LSRxw_REG(s3, s2, s3); + ORRxw_REG(s1, s3, s1); + } IFX(X_PEND) { STRxw_U12(s1, xEmu, offsetof(x64emu_t, res)); } + IFX(X_OF) { + if(box64_dynarec_test) { + CMPSw_U12(s5, 1); + EORx_REG_LSR(s3, s4, s1, rex.w?63:31); // OF is set if sign changed + CSELw(s3, s3, xZR, cEQ); + BFIw(xFlags, s3, F_OF, 1); + } else { + //CMPSw_U12(s5, 1); + EORx_REG_LSR(s3, s4, s1, rex.w?63:31); // OF is set if sign changed + // CSELw(s3, s3, xZR, cEQ); + BFIw(xFlags, s3, F_OF, 1); + } + } int need_tst = 0; IFX(X_ZF) need_tst = 1; IFXNATIVE(X_SF, NF_SF) need_tst = 1; @@ -1412,11 +1478,8 @@ 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_OF) { - SUBw_U12(s3, s5, 1); - CBNZw(s3, 4+2*4); //flagless jump - UBFXx(s3, s1, rex.w?63:31, 1); - EORw_REG_LSL(xFlags, xFlags, s3, F_OF); // OF is set if sign changed + if(box64_dynarec_test) { + IFX(X_AF) {BFCw(xFlags, F_AF, 1);} } IFX(X_PF) { emit_pf(dyn, ninst, s1, s4); @@ -1448,7 +1511,6 @@ void emit_shrd16c(dynarec_arm_t* dyn, int ninst, int s1, int s2, uint32_t c, int IFX(X_OF) { if(c==1) { LSRw(s4, s1, 15); - BFIw(xFlags, s4, F_OF, 1); // store sign for later use } } RORw(s1, s1, c); @@ -1458,10 +1520,14 @@ void emit_shrd16c(dynarec_arm_t* dyn, int ninst, int s1, int s2, uint32_t c, int COMP_ZFSF(s1, 16) IFX(X_OF) { if(c==1) { - UBFXw(s3, s1, 15, 1); - EORw_REG_LSL(xFlags, xFlags, s3, F_OF); // OF is set if sign changed + EORx_REG_LSR(s3, s4, s1, 15); // OF is set if sign changed + BFIw(xFlags, s3, F_OF, 1); } } + if(box64_dynarec_test) { + IFX(X_AF) {BFCw(xFlags, F_AF, 1);} + IFX(X_OF) if(c>1) {BFCw(xFlags, F_OF, 1);} + } IFX(X_PF) { emit_pf(dyn, ninst, s1, s4); } @@ -1486,19 +1552,25 @@ void emit_shrd16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s5, int s3, } IFX(X_OF) { LSRw(s4, s1, 15); - BFIw(xFlags, s4, F_OF, 1); // store sign fr now } RORw_REG(s1, s1, s5); IFX(X_PEND) { STRH_U12(s1, xEmu, offsetof(x64emu_t, res)); } - COMP_ZFSF(s1, 16) IFX(X_OF) { - SUBw_U12(s3, s5, 1); - CBNZw(s3, 4+2*4); - UBFXw(s3, s1, 15, 1); - EORw_REG_LSL(xFlags, xFlags, s3, F_OF); // OF is set if sign changed + if(box64_dynarec_test) { + CMPSw_U12(s5, 1); + EORw_REG_LSR(s3, s4, s1, 15); // OF is set if sign changed + CSELw(s3, s3, xZR, cEQ); + BFIw(xFlags, s3, F_OF, 1); + } else { + //CMPSw_U12(s5, 1); + EORw_REG_LSR(s3, s4, s1, 15); // OF is set if sign changed + // CSELw(s3, s3, xZR, cEQ); + BFIw(xFlags, s3, F_OF, 1); + } } + COMP_ZFSF(s1, 16) IFX(X_PF) { emit_pf(dyn, ninst, s1, s4); } @@ -1524,7 +1596,7 @@ void emit_shld16c(dynarec_arm_t* dyn, int ninst, int s1, int s2, uint32_t c, int } return; } - ORRw_REG_LSL(s1, s1, s2, 16); // create concat first + BFIw(s1, s2, 16, 16); // create concat first IFX(X_CF) { if(c<16) LSRw(s3, s1, 16-c); @@ -1533,8 +1605,7 @@ void emit_shld16c(dynarec_arm_t* dyn, int ninst, int s1, int s2, uint32_t c, int BFIw(xFlags, s3, F_CF, 1); } IFX(X_OF) { - LSRw(s3, s1, 15); - BFIw(xFlags, s3, F_OF, 1); // store current sign for later use + LSRw(s4, s1, 15); } RORw(s1, s1, 32-c); @@ -1544,12 +1615,14 @@ void emit_shld16c(dynarec_arm_t* dyn, int ninst, int s1, int s2, uint32_t c, int COMP_ZFSF(s1, 16) IFX(X_OF) { if(c==1) { - UBFXw(s3, s1, 15, 1); - EORw_REG_LSL(xFlags, xFlags, s3, F_OF); // OF is set if sign changed - } else { - BFCw(xFlags, F_OF, 1); + EORw_REG_LSR(s3, s4, s1, 15); // OF is set if sign changed + BFIw(xFlags, s3, F_OF, 1); } } + if(box64_dynarec_test) { + IFX(X_AF) {BFCw(xFlags, F_AF, 1);} + IFX(X_OF) if(c>1) {BFCw(xFlags, F_OF, 1);} + } IFX(X_PF) { emit_pf(dyn, ninst, s1, s4); } @@ -1572,10 +1645,9 @@ void emit_shld16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s5, int s3, BFIw(xFlags, s3, F_CF, 1); } IFX(X_OF) { - LSRw(s3, s1, 15); - BFIw(xFlags, s3, F_OF, 1); // store current sign for later use + LSRw(s4, s1, 15); } - ORRw_REG_LSL(s1, s1, s2, 16); // create concat first + BFIw(s1, s2, 16, 16); // create concat first MOV32w(s3, 32); SUBw_REG(s3, s3, s5); RORw_REG(s1, s1, s3); @@ -1583,12 +1655,22 @@ void emit_shld16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s5, int s3, IFX(X_PEND) { STRH_U12(s1, xEmu, offsetof(x64emu_t, res)); } - COMP_ZFSF(s1, 16) IFX(X_OF) { - SUBw_U12(s3, s5, 1); - CBNZw(s3, 4+2*4); - UBFXw(s3, s1, 15, 1); - EORw_REG_LSL(xFlags, xFlags, s3, F_OF); // OF is set if sign changed + if(box64_dynarec_test) { + CMPSw_U12(s5, 1); + EORw_REG_LSR(s3, s4, s1, 15); // OF is set if sign changed + CSELw(s3, s3, xZR, cEQ); + BFIw(xFlags, s3, F_OF, 1); + } else { + //CMPSw_U12(s5, 1); + EORw_REG_LSR(s3, s4, s1, 15); // OF is set if sign changed + // CSELw(s3, s3, xZR, cEQ); + BFIw(xFlags, s3, F_OF, 1); + } + } + COMP_ZFSF(s1, 16) + if(box64_dynarec_test) { + IFX(X_AF) {BFCw(xFlags, F_AF, 1);} } IFX(X_PF) { emit_pf(dyn, ninst, s1, s4); diff --git a/src/emu/x64primop.c b/src/emu/x64primop.c index 9f5092e4..4898a0d8 100644 --- a/src/emu/x64primop.c +++ b/src/emu/x64primop.c @@ -104,6 +104,8 @@ #include "x64emu_private.h" #include "x64run_private.h" +extern int box64_dynarec_test; + /*------------------------- Global Variables ------------------------------*/ #define PARITY(x) (((emu->x64emu_parity_tab[(x) / 32] >> ((x) % 32)) & 1) == 0) @@ -778,6 +780,8 @@ uint8_t rol8(x64emu_t *emu, uint8_t d, uint8_t s) /* OF flag is set if s == 1; OF = CF _XOR_ MSB of result */ if(s == 1) { CONDITIONAL_SET_FLAG((d + (d >> 7)) & 1, F_OF); + } else if(box64_dynarec_test) { + CLEAR_FLAG(F_OF); } /* set new CF; note that it is the LSB of the result */ @@ -801,6 +805,8 @@ uint16_t rol16(x64emu_t *emu, uint16_t d, uint8_t s) /* OF flag is set if s == 1; OF = CF _XOR_ MSB of result */ if(s == 1) { CONDITIONAL_SET_FLAG((d + (d >> 15)) & 1, F_OF); + } else if(box64_dynarec_test) { + CLEAR_FLAG(F_OF); } /* set new CF; note that it is the LSB of the result */ @@ -824,6 +830,8 @@ uint32_t rol32(x64emu_t *emu, uint32_t d, uint8_t s) /* OF flag is set if s == 1; OF = CF _XOR_ MSB of result */ if(s == 1) { CONDITIONAL_SET_FLAG((d + (d >> 31)) & 1, F_OF); + } else if(box64_dynarec_test) { + CLEAR_FLAG(F_OF); } /* set new CF; note that it is the LSB of the result */ @@ -847,6 +855,8 @@ uint64_t rol64(x64emu_t *emu, uint64_t d, uint8_t s) /* OF flag is set if s == 1; OF = CF _XOR_ MSB of result */ if(s == 1) { CONDITIONAL_SET_FLAG((d + (d >> 63)) & 1, F_OF); + } else if(box64_dynarec_test) { + CLEAR_FLAG(F_OF); } /* set new CF; note that it is the LSB of the result */ @@ -874,6 +884,8 @@ uint8_t ror8(x64emu_t *emu, uint8_t d, uint8_t s) /* OF flag is set if s == 1; OF = MSB _XOR_ (M-1)SB of result */ if(s == 1) { CONDITIONAL_SET_FLAG(XOR2(d >> 6), F_OF); + } else if(box64_dynarec_test) { + CLEAR_FLAG(F_OF); } /* set new CF; note that it is the MSB of the result */ @@ -897,6 +909,8 @@ uint16_t ror16(x64emu_t *emu, uint16_t d, uint8_t s) /* OF flag is set if s == 1; OF = MSB _XOR_ (M-1)SB of result */ if(s == 1) { CONDITIONAL_SET_FLAG(XOR2(d >> 14), F_OF); + } else if(box64_dynarec_test) { + CLEAR_FLAG(F_OF); } /* set new CF; note that it is the MSB of the result */ @@ -920,6 +934,8 @@ uint32_t ror32(x64emu_t *emu, uint32_t d, uint8_t s) /* OF flag is set if s == 1; OF = MSB _XOR_ (M-1)SB of result */ if(s == 1) { CONDITIONAL_SET_FLAG(XOR2(d >> 30), F_OF); + } else if(box64_dynarec_test) { + CLEAR_FLAG(F_OF); } /* set new CF; note that it is the MSB of the result */ @@ -943,6 +959,8 @@ uint64_t ror64(x64emu_t *emu, uint64_t d, uint8_t s) /* OF flag is set if s == 1; OF = MSB _XOR_ (M-1)SB of result */ if(s == 1) { CONDITIONAL_SET_FLAG(XOR2(d >> 62), F_OF); + } else if(box64_dynarec_test) { + CLEAR_FLAG(F_OF); } /* set new CF; note that it is the MSB of the result */ @@ -977,7 +995,7 @@ uint16_t shld16 (x64emu_t *emu, uint16_t d, uint16_t fill, uint8_t s) if (cnt == 1) { CONDITIONAL_SET_FLAG(((res ^ d) >> 15)&1, F_OF); } else { - CONDITIONAL_SET_FLAG((d >> 15)&1, F_OF); + CLEAR_FLAG(F_OF); } } else { res = (fill << (cnt)) | (d >> (16 - cnt)); @@ -991,6 +1009,8 @@ uint16_t shld16 (x64emu_t *emu, uint16_t d, uint16_t fill, uint8_t s) CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); CLEAR_FLAG(F_OF); } + if(box64_dynarec_test) + CLEAR_FLAG(F_AF); return (uint16_t)res; } @@ -1016,8 +1036,10 @@ uint32_t shld32 (x64emu_t *emu, uint32_t d, uint32_t fill, uint8_t s) if (cnt == 1) { CONDITIONAL_SET_FLAG(((res ^ d) >> 31)&1, F_OF); } else { - CONDITIONAL_SET_FLAG((d >> 31)&1, F_OF); + CLEAR_FLAG(F_OF); } + if(box64_dynarec_test) + CLEAR_FLAG(F_AF); return res; } @@ -1043,8 +1065,10 @@ uint64_t shld64 (x64emu_t *emu, uint64_t d, uint64_t fill, uint8_t s) if (cnt == 1) { CONDITIONAL_SET_FLAG(((res ^ d) >> 63)&1, F_OF); } else { - CONDITIONAL_SET_FLAG((d >> 63)&1, F_OF); + CLEAR_FLAG(F_OF); } + if(box64_dynarec_test) + CLEAR_FLAG(F_AF); return res; } @@ -1076,7 +1100,7 @@ uint16_t shrd16 (x64emu_t *emu, uint16_t d, uint16_t fill, uint8_t s) if (cnt == 1) { CONDITIONAL_SET_FLAG(((res ^ d) >> 15)&1, F_OF); } else { - CONDITIONAL_SET_FLAG((d >> 15)&1, F_OF); + CLEAR_FLAG(F_OF); } } else { if(s==16) @@ -1098,6 +1122,8 @@ uint16_t shrd16 (x64emu_t *emu, uint16_t d, uint16_t fill, uint8_t s) CLEAR_FLAG(F_PF); #endif } + if(box64_dynarec_test) + CLEAR_FLAG(F_AF); return (uint16_t)res; } @@ -1123,8 +1149,10 @@ uint32_t shrd32 (x64emu_t *emu, uint32_t d, uint32_t fill, uint8_t s) if (cnt == 1) { CONDITIONAL_SET_FLAG(((res ^ d) >> 31)&1, F_OF); } else { - CONDITIONAL_SET_FLAG((d >> 31)&1, F_OF); + CLEAR_FLAG(F_OF); } + if(box64_dynarec_test) + CLEAR_FLAG(F_AF); return res; } @@ -1151,8 +1179,10 @@ uint64_t shrd64 (x64emu_t *emu, uint64_t d, uint64_t fill, uint8_t s) if (cnt == 1) { CONDITIONAL_SET_FLAG(((res ^ d) >> 63)&1, F_OF); } else { - CONDITIONAL_SET_FLAG((d >> 63)&1, F_OF); + CLEAR_FLAG(F_OF); } + if(box64_dynarec_test) + CLEAR_FLAG(F_AF); return res; } /**************************************************************************** diff --git a/src/emu/x64run_private.c b/src/emu/x64run_private.c index 8bc99819..5cfc4625 100644 --- a/src/emu/x64run_private.c +++ b/src/emu/x64run_private.c @@ -656,7 +656,7 @@ void UpdateFlags(x64emu_t *emu) CONDITIONAL_SET_FLAG(!emu->res.u8, F_ZF); CONDITIONAL_SET_FLAG(PARITY(emu->res.u8), F_PF); CONDITIONAL_SET_FLAG(emu->res.u8 & 0x80, F_SF); - if(emu->op2.u8==1) + if(emu->op2.u8==1 || box64_dynarec_test) CLEAR_FLAG(F_OF); if(box64_dynarec_test) { CLEAR_FLAG(F_AF); @@ -670,7 +670,7 @@ void UpdateFlags(x64emu_t *emu) CONDITIONAL_SET_FLAG(!emu->res.u16, F_ZF); CONDITIONAL_SET_FLAG(emu->res.u16 & 0x8000, F_SF); CONDITIONAL_SET_FLAG(PARITY(emu->res.u8), F_PF); - if(emu->op2.u16==1) + if(emu->op2.u16==1 || box64_dynarec_test) CLEAR_FLAG(F_OF); if(box64_dynarec_test) { CLEAR_FLAG(F_AF); @@ -684,7 +684,7 @@ void UpdateFlags(x64emu_t *emu) CONDITIONAL_SET_FLAG(!emu->res.u32, F_ZF); CONDITIONAL_SET_FLAG(emu->res.u32 & 0x80000000, F_SF); CONDITIONAL_SET_FLAG(PARITY(emu->res.u8), F_PF); - if(emu->op2.u32==1) + if(emu->op2.u32==1 || box64_dynarec_test) CLEAR_FLAG(F_OF); if(box64_dynarec_test) { CLEAR_FLAG(F_AF); @@ -698,7 +698,7 @@ void UpdateFlags(x64emu_t *emu) CONDITIONAL_SET_FLAG(!emu->res.u64, F_ZF); CONDITIONAL_SET_FLAG(emu->res.u64 & 0x8000000000000000LL, F_SF); CONDITIONAL_SET_FLAG(PARITY(emu->res.u8), F_PF); - if(emu->op2.u64==1) + if(emu->op2.u64==1 || box64_dynarec_test) CLEAR_FLAG(F_OF); if(box64_dynarec_test) { CLEAR_FLAG(F_AF); @@ -715,6 +715,9 @@ void UpdateFlags(x64emu_t *emu) CONDITIONAL_SET_FLAG(PARITY(emu->res.u8), F_PF); if(box64_dynarec_test) { CLEAR_FLAG(F_AF); + if(cnt>1) { + CLEAR_FLAG(F_OF); + } } } if (cnt == 1) { @@ -731,6 +734,9 @@ void UpdateFlags(x64emu_t *emu) CONDITIONAL_SET_FLAG(PARITY(emu->res.u8), F_PF); if(box64_dynarec_test) { CLEAR_FLAG(F_AF); + if(cnt>1) { + CLEAR_FLAG(F_OF); + } } } if (cnt == 1) { @@ -747,6 +753,9 @@ void UpdateFlags(x64emu_t *emu) CONDITIONAL_SET_FLAG(PARITY(emu->res.u8), F_PF); if(box64_dynarec_test) { CLEAR_FLAG(F_AF); + if(cnt>1) { + CLEAR_FLAG(F_OF); + } } } if (cnt == 1) { @@ -766,6 +775,9 @@ void UpdateFlags(x64emu_t *emu) } if(box64_dynarec_test) { CLEAR_FLAG(F_AF); + if(cnt>1) { + CLEAR_FLAG(F_OF); + } } } break; @@ -779,7 +791,9 @@ void UpdateFlags(x64emu_t *emu) CONDITIONAL_SET_FLAG(PARITY(emu->res.u8), F_PF); if (cnt == 1) { CONDITIONAL_SET_FLAG((emu->op1.u16 ^ emu->res.u16) & 0x8000, F_OF); - } + } else { + CLEAR_FLAG(F_OF); + } } break; case d_shrd32: @@ -792,6 +806,8 @@ void UpdateFlags(x64emu_t *emu) CONDITIONAL_SET_FLAG(PARITY(emu->res.u8), F_PF); if (cnt == 1) { CONDITIONAL_SET_FLAG((emu->op1.u32 ^ emu->res.u32) & 0x80000000, F_OF); + } else { + CLEAR_FLAG(F_OF); } } break; @@ -805,6 +821,8 @@ void UpdateFlags(x64emu_t *emu) CONDITIONAL_SET_FLAG(PARITY(emu->res.u8), F_PF); if (cnt == 1) { CONDITIONAL_SET_FLAG((emu->op1.u64 ^ emu->res.u64) & 0x8000000000000000LL, F_OF); + } else { + CLEAR_FLAG(F_OF); } } break; |