diff options
| author | ptitSeb <sebastien.chev@gmail.com> | 2024-05-09 22:03:25 +0200 |
|---|---|---|
| committer | ptitSeb <sebastien.chev@gmail.com> | 2024-05-09 22:03:25 +0200 |
| commit | ff755facc0c0ec502b4476d1144b61055abb3e7b (patch) | |
| tree | 911d30c96c337df8fa401cb405eed1e24ecd6bf9 /src | |
| parent | d38f659f428544de524fe6f2a49355a104055555 (diff) | |
| download | box64-ff755facc0c0ec502b4476d1144b61055abb3e7b.tar.gz box64-ff755facc0c0ec502b4476d1144b61055abb3e7b.zip | |
[ARM64_DYNAREC] Fix and improvments on rcl/rcr helper
Diffstat (limited to 'src')
| -rw-r--r-- | src/dynarec/arm64/dynarec_arm64_66.c | 41 | ||||
| -rw-r--r-- | src/dynarec/arm64/dynarec_arm64_emit_shift.c | 146 | ||||
| -rw-r--r-- | src/emu/x64run_private.c | 15 |
3 files changed, 95 insertions, 107 deletions
diff --git a/src/dynarec/arm64/dynarec_arm64_66.c b/src/dynarec/arm64/dynarec_arm64_66.c index 709605f1..d06665a2 100644 --- a/src/dynarec/arm64/dynarec_arm64_66.c +++ b/src/dynarec/arm64/dynarec_arm64_66.c @@ -961,7 +961,6 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin break; case 1: INST_NAME("ROR Ew, Ib"); - u8 = geted_ib(dyn, addr, ninst, nextop) & 15; if (geted_ib(dyn, addr, ninst, nextop) & 15) { SETFLAGS(X_CF | X_OF, SF_SUBSET_PENDING); GETEW(x1, 1); @@ -974,22 +973,32 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin } break; case 2: - INST_NAME("RCL Ew, 1"); - READFLAGS(X_CF); - SETFLAGS(X_OF|X_CF, SF_SUBSET_PENDING); - GETEW(x1, 1); - u8 = F8; - emit_rcl8c(dyn, ninst, ed, u8, x4, x5); - EWBACK; + INST_NAME("RCL Ew, Ib"); + if (geted_ib(dyn, addr, ninst, nextop) & 31) { + READFLAGS(X_CF); + SETFLAGS(X_OF|X_CF, SF_SUBSET_PENDING); + GETEW(x1, 1); + u8 = F8; + emit_rcl16c(dyn, ninst, ed, u8, x4, x5); + EWBACK; + } else { + FAKEED; + F8; + } break; case 3: - INST_NAME("RCR Ew, 1"); - READFLAGS(X_CF); - SETFLAGS(X_OF|X_CF, SF_SUBSET_PENDING); - GETEW(x1, 1); - u8 = F8; - emit_rcr8c(dyn, ninst, ed, u8, x4, x5); - EWBACK; + INST_NAME("RCR Ew, Ib"); + if (geted_ib(dyn, addr, ninst, nextop) & 31) { + READFLAGS(X_CF); + SETFLAGS(X_OF|X_CF, SF_SUBSET_PENDING); + GETEW(x1, 1); + u8 = F8; + emit_rcr16c(dyn, ninst, ed, u8, x4, x5); + EWBACK; + } else { + FAKEED; + F8; + } break; case 4: case 6: @@ -1070,6 +1079,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin break; case 2: INST_NAME("RCL Ew, 1"); + READFLAGS(X_CF); SETFLAGS(X_OF|X_CF, SF_SUBSET_PENDING); GETEW(x1, 0); emit_rcl16c(dyn, ninst, x1, 1, x5, x4); @@ -1077,6 +1087,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin break; case 3: INST_NAME("RCR Ew, 1"); + READFLAGS(X_CF); SETFLAGS(X_OF|X_CF, SF_SUBSET_PENDING); GETEW(x1, 0); emit_rcr16c(dyn, ninst, x1, 1, x5, x4); diff --git a/src/dynarec/arm64/dynarec_arm64_emit_shift.c b/src/dynarec/arm64/dynarec_arm64_emit_shift.c index 486555f1..4b614a94 100644 --- a/src/dynarec/arm64/dynarec_arm64_emit_shift.c +++ b/src/dynarec/arm64/dynarec_arm64_emit_shift.c @@ -197,12 +197,6 @@ void emit_shr32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, uint32_t c, i } else IFX(X_ALL) { SET_DFNONE(s4); } - if(!c) { - IFX(X_PEND) { - STRxw_U12(s1, xEmu, offsetof(x64emu_t, res)); - } - return; - } IFX(X_CF) { if(c==1) { BFIw(xFlags, s1, 0, 1); @@ -252,12 +246,6 @@ void emit_sar32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, uint32_t c, i } else IFX(X_ALL) { SET_DFNONE(s4); } - if(!c) { - IFX(X_PEND) { - STRxw_U12(s1, xEmu, offsetof(x64emu_t, res)); - } - return; - } IFX(X_CF) { ASRxw(s3, s1, c-1); BFIw(xFlags, s3, 0, 1); @@ -1001,7 +989,7 @@ void emit_rcl8c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int s { MAYUSE(s1); MAYUSE(s3); MAYUSE(s4); - if (!c) return; + if (!(c%9)) return; IFX(X_PEND) { MOV32w(s3, c); @@ -1011,27 +999,24 @@ void emit_rcl8c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int s } else IFX(X_ALL) { SET_DFNONE(s4); } + c%=9; BFIw(s1, xFlags, 8, 1); // insert cf IFX(X_OF|X_CF) { - if(c%9) { - if(c%9!=8) { - LSRw_IMM(s3, s1, 8-(c%9)); - } else { - MOVw_REG(s3, s1); - } + if(c!=8) { + LSRw_IMM(s3, s1, 8-c); } else { - MOVw_REG(s3, xFlags); + MOVw_REG(s3, s1); } } ORRw_REG_LSL(s1, s1, s1, 9); // insert s1 again - if(c%9) { - LSRw_IMM(s1, s1, 9-(c%9)); // do the rcl - } + LSRw_IMM(s1, s1, 9-c); // do the rcl IFX(X_PEND) { STRB_U12(s1, xEmu, offsetof(x64emu_t, res)); } IFX(X_OF|X_CF) { - BFIw(xFlags, s3, F_CF, 1); + IFX(X_CF) { + BFIw(xFlags, s3, F_CF, 1); + } IFX(X_OF) { if(c==1) { EORw_REG_LSR(s3, s3, s1, 7); @@ -1046,7 +1031,7 @@ void emit_rcr8c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int s { MAYUSE(s1); MAYUSE(s3); MAYUSE(s4); - if (!c) return; + if (!(c%9)) return; IFX(X_PEND) { MOV32w(s3, c); @@ -1056,34 +1041,27 @@ void emit_rcr8c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int s } else IFX(X_ALL) { SET_DFNONE(s4); } - IFX(X_OF|X_CF) { - if(c%9) { - if((c%9)==1) { - MOVx_REG(s3, s1); - } else { - LSRw_IMM(s3, s1, (c%9)-1); - } - } else { - MOVw_REG(s3, xFlags); - } + c%=9; + IFX(X_OF) { + MOVw_REG(s3, wFlags); } BFIw(s1, xFlags, 8, 1); // insert cf - ORRw_REG_LSL(s1, s1, s1, 9); // insert s1 again - if(c%9) { - LSRw_IMM(s1, s1, (c%9)); // do the rcr + IFX(X_CF) { + BFXILw(xFlags, s1, c-1, 1); } - IFX(X_PEND) { - STRB_U12(s1, xEmu, offsetof(x64emu_t, res)); + if(c>1) { + ORRw_REG_LSL(s1, s1, s1, 9); // insert s1 again } - IFX(X_OF|X_CF) { - BFIw(xFlags, s3, F_CF, 1); - IFX(X_OF) { - if(c==1) { - EORw_REG_LSR(s3, s3, s1, 7); - BFIw(xFlags, s3, F_OF, 1); - } + LSRw_IMM(s1, s1, c); // do the rcr + IFX(X_OF) { + if(c==1) { + EORw_REG_LSR(s3, s3, s1, 7); + BFIw(xFlags, s3, F_OF, 1); } } + IFX(X_PEND) { + STRB_U12(s1, xEmu, offsetof(x64emu_t, res)); + } } // emit RCL16 instruction, from s1 , constant c, store result in s1 using s3 and s4 as scratch @@ -1091,7 +1069,7 @@ 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) return; + if (!(c%17)) return; IFX(X_PEND) { MOV32w(s3, c); @@ -1101,32 +1079,27 @@ void emit_rcl16c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int } else IFX(X_ALL) { SET_DFNONE(s4); } + c%=17; BFIw(s1, xFlags, 16, 1); // insert cf IFX(X_OF|X_CF) { - if(c%17) { - if(c%17!=16) { - LSRw_IMM(s3, s1, 16-(c%17)); - } else { - MOVw_REG(s3, s1); - } + if(c!=16) { + LSRw_IMM(s3, s1, 16-c); } else { - MOVw_REG(s3, xFlags); + MOVw_REG(s3, s1); } } - ORRw_REG_LSL(s1, s1, s1, 17); // insert s1 again - if(c%17) { - LSRw_IMM(s1, s1, 17-(c%17)); // do the rcl - } + ORRx_REG_LSL(s1, s1, s1, 17); // insert s1 again + LSRx_IMM(s1, s1, 17-c); // do the rcl IFX(X_PEND) { - STRB_U12(s1, xEmu, offsetof(x64emu_t, res)); + STRH_U12(s1, xEmu, offsetof(x64emu_t, res)); } - IFX(X_OF|X_CF) { + IFX(X_CF) { BFIw(xFlags, s3, F_CF, 1); - IFX(X_OF) { - if(c==1) { - EORw_REG_LSR(s3, s3, s1, 15); - BFIw(xFlags, s3, F_OF, 1); - } + } + IFX(X_OF) { + if(c==1) { + EORw_REG_LSR(s3, s3, s1, 15); + BFIw(xFlags, s3, F_OF, 1); } } } @@ -1136,7 +1109,7 @@ 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) return; + if (!(c%17)) return; IFX(X_PEND) { MOV32w(s3, c); @@ -1146,34 +1119,27 @@ void emit_rcr16c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int } else IFX(X_ALL) { SET_DFNONE(s4); } - IFX(X_OF|X_CF) { - if(c%17) { - if((c%17)==1) { - MOVx_REG(s3, s1); - } else { - LSRw_IMM(s3, s1, (c%17)-1); - } - } else { - MOVw_REG(s3, xFlags); - } + c%=17; + BFIw(s1, xFlags, 16, 1); // insert cf + IFX(X_OF) { + MOVw_REG(s3, wFlags); } - BFIw(s1, xFlags, 17, 1); // insert cf - ORRw_REG_LSL(s1, s1, s1, 17); // insert s1 again - if(c%17) { - LSRw_IMM(s1, s1, (c%17)); // do the rcr + IFX(X_CF) { + BFXILx(xFlags, s1, c-1, 1); } - IFX(X_PEND) { - STRB_U12(s1, xEmu, offsetof(x64emu_t, res)); + if(c>1) { + ORRx_REG_LSL(s1, s1, s1, 17); // insert s1 again } - IFX(X_OF|X_CF) { - BFIw(xFlags, s3, F_CF, 1); - IFX(X_OF) { - if(c==1) { - EORw_REG_LSR(s3, s3, s1, 15); - BFIw(xFlags, s3, F_OF, 1); - } + LSRx_IMM(s1, s1, c); // do the rcr + IFX(X_OF) { + if(c==1) { + EORw_REG_LSR(s3, s3, s1, 15); + BFIw(xFlags, s3, F_OF, 1); } } + IFX(X_PEND) { + STRH_U12(s1, xEmu, offsetof(x64emu_t, res)); + } } // emit SHRD32 instruction, from s1, fill s2 , constant c, store result in s1 using s3 and s4 as scratch void emit_shrd32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, uint32_t c, int s3, int s4) diff --git a/src/emu/x64run_private.c b/src/emu/x64run_private.c index 2891b04c..016092b3 100644 --- a/src/emu/x64run_private.c +++ b/src/emu/x64run_private.c @@ -1064,11 +1064,22 @@ void UpdateFlags(x64emu_t *emu) // new CF CONDITIONAL_SET_FLAG(((cnt==1)?emu->op1.u8:(emu->op1.u8>>(cnt-1))) & 1, F_CF); break; - case d_rcl16: + cnt = emu->op2.u16%17; + CONDITIONAL_SET_FLAG(emu->op1.u16>>(17-cnt) & 1, F_CF); + // should for cnt==1 + CONDITIONAL_SET_FLAG(((emu->res.u16>>15) ^ ACCESS_FLAG(F_CF)) & 1, F_OF); + break; + case d_rcr16: + cnt = emu->op2.u16%17; + // should for cnt==1, using "before" CF + CONDITIONAL_SET_FLAG(((emu->res.u16>>15) ^ ACCESS_FLAG(F_CF)) & 1, F_OF); + // new CF + CONDITIONAL_SET_FLAG(((cnt==1)?emu->op1.u16:(emu->op1.u16>>(cnt-1))) & 1, F_CF); + break; + case d_rcl32: case d_rcl64: - case d_rcr16: case d_rcr32: case d_rcr64: case d_unknown: |