diff options
| author | ptitSeb <sebastien.chev@gmail.com> | 2023-11-16 11:00:09 +0100 |
|---|---|---|
| committer | ptitSeb <sebastien.chev@gmail.com> | 2023-11-16 11:00:09 +0100 |
| commit | 19a24c2171cd943e7b1398c5636c666e07efe6d4 (patch) | |
| tree | fb5f66a9a0f2a00b64e24dfa401f44dfda4d6935 /src | |
| parent | f7d75ca641ec6de4a35421fe206f8608ee531a20 (diff) | |
| download | box64-19a24c2171cd943e7b1398c5636c666e07efe6d4.tar.gz box64-19a24c2171cd943e7b1398c5636c666e07efe6d4.zip | |
[ARM64_DYNAREC] Optimized 66 AC opcode
Diffstat (limited to 'src')
| -rw-r--r-- | src/dynarec/arm64/dynarec_arm64_660f.c | 20 | ||||
| -rw-r--r-- | src/dynarec/arm64/dynarec_arm64_emit_shift.c | 54 | ||||
| -rw-r--r-- | src/dynarec/arm64/dynarec_arm64_helper.h | 2 | ||||
| -rw-r--r-- | src/emu/x64run_private.c | 14 |
4 files changed, 78 insertions, 12 deletions
diff --git a/src/dynarec/arm64/dynarec_arm64_660f.c b/src/dynarec/arm64/dynarec_arm64_660f.c index ba330878..47586faf 100644 --- a/src/dynarec/arm64/dynarec_arm64_660f.c +++ b/src/dynarec/arm64/dynarec_arm64_660f.c @@ -2207,22 +2207,22 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n } break; case 0xAC: + INST_NAME("SHRD Ew, Gw, Ib"); + SETFLAGS(X_ALL, SF_SET_PENDING); + GETEW(x1, 1); + GETGW(x2); + u8 = F8; + emit_shrd16c(dyn, ninst, ed, gd, u8, x4, x5); + EWBACK; + break; case 0xAD: nextop = F8; - if(opcode==0xAC) { - INST_NAME("SHRD Ew, Gw, Ib"); - } else { - INST_NAME("SHRD Ew, Gw, CL"); - UXTBw(x3, xRCX); - } + INST_NAME("SHRD Ew, Gw, CL"); + UXTBw(x3, xRCX); MESSAGE(LOG_DUMP, "Need Optimization\n"); SETFLAGS(X_ALL, SF_SET); GETEWW(x4, x1, (opcode==0xAC)?1:0); GETGW(x2); - if(opcode==0xAC) { - u8 = F8; - MOV32w(x3, u8); - } CALL_(shrd16, x1, wback); EWBACKW(x1); break; diff --git a/src/dynarec/arm64/dynarec_arm64_emit_shift.c b/src/dynarec/arm64/dynarec_arm64_emit_shift.c index 7b504321..bab869b7 100644 --- a/src/dynarec/arm64/dynarec_arm64_emit_shift.c +++ b/src/dynarec/arm64/dynarec_arm64_emit_shift.c @@ -1005,7 +1005,6 @@ void emit_shrd32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, uint MOV32w(s3, c); STRxw_U12(s1, xEmu, offsetof(x64emu_t, op1)); STRxw_U12(s3, xEmu, offsetof(x64emu_t, op2)); - // same flags computation as with shl64/shl32 SET_DF(s4, rex.w?d_shrd64:d_shrd32); } else IFX(X_ALL) { SET_DFNONE(s4); @@ -1152,3 +1151,56 @@ void emit_shrd32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s emit_pf(dyn, ninst, s1, s3, s4); } } + +// emit SHRD16 instruction, from s1, fill s2 , constant c, store result in s1 using s3 and s4 as scratch +void emit_shrd16c(dynarec_arm_t* dyn, int ninst, int s1, int s2, uint32_t c, int s3, int s4) +{ + c&=0x1f; + IFX(X_PEND) { + MOV32w(s3, c); + STRH_U12(s1, xEmu, offsetof(x64emu_t, op1)); + STRH_U12(s3, xEmu, offsetof(x64emu_t, op2)); + SET_DF(s4, d_shrd16); + } else IFX(X_ALL) { + SET_DFNONE(s4); + } + if(!c) { + IFX(X_PEND) { + STRH_U12(s1, xEmu, offsetof(x64emu_t, res)); + } + return; + } + IFX(X_CF) { + BFXILw(xFlags, s1, c-1, 1); // set CF + } + IFX(X_OF) { + if(c==1) { + LSRw(s4, s1, 15); + BFIw(xFlags, s4, F_OF, 1); // store sign for later use + } + } + ORRw_REG_LSL(s1, s1, s2, 16); + LSRw_IMM(s1, s1, c); + IFX(X_PEND) { + STRH_U12(s1, xEmu, offsetof(x64emu_t, res)); + } + IFX(X_ZF) { + TSTw_mask(s1, 0, 15); // 0xffff + CSETw(s4, cEQ); + BFIw(xFlags, s4, F_ZF, 1); + } + IFX(X_SF) { + LSRw(s4, s1, 15); + BFIw(xFlags, s4, F_SF, 1); + } + IFX(X_OF) { + if(c==1) { + LSRw(s4, s1, 15); + EORw_REG_LSR(s4, s4, xFlags, F_OF); // set if sign changed + BFIw(xFlags, s4, F_OF, 1); + } + } + IFX(X_PF) { + emit_pf(dyn, ninst, s1, s3, s4); + } +} diff --git a/src/dynarec/arm64/dynarec_arm64_helper.h b/src/dynarec/arm64/dynarec_arm64_helper.h index 91273cea..6102c9bc 100644 --- a/src/dynarec/arm64/dynarec_arm64_helper.h +++ b/src/dynarec/arm64/dynarec_arm64_helper.h @@ -1044,6 +1044,7 @@ void* arm64_next(x64emu_t* emu, uintptr_t addr); #define emit_shrd32c STEPNAME(emit_shrd32c) #define emit_shld32c STEPNAME(emit_shld32c) #define emit_shrd32 STEPNAME(emit_shrd32) +#define emit_shrd16c STEPNAME(emit_shrd16c) #define emit_pf STEPNAME(emit_pf) @@ -1190,6 +1191,7 @@ void emit_ror16c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int void emit_shrd32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, uint32_t c, int s3, int s4); void emit_shld32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, uint32_t c, int s3, int s4); void emit_shrd32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s5, int s3, int s4); +void emit_shrd16c(dynarec_arm_t* dyn, int ninst, int s1, int s2, uint32_t c, int s3, int s4); void emit_pf(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4); diff --git a/src/emu/x64run_private.c b/src/emu/x64run_private.c index f50c32cc..a5a588c2 100644 --- a/src/emu/x64run_private.c +++ b/src/emu/x64run_private.c @@ -692,6 +692,19 @@ void UpdateFlags(x64emu_t *emu) } } break; + case d_shrd16: + cnt = emu->op2.u16; + if (cnt > 0) { + cc = emu->op1.u16 & (1 << (cnt - 1)); + CONDITIONAL_SET_FLAG(cc, F_CF); + CONDITIONAL_SET_FLAG(!emu->res.u16, F_ZF); + CONDITIONAL_SET_FLAG(emu->res.u16 & 0x8000, F_SF); + CONDITIONAL_SET_FLAG(PARITY(emu->res.u16 & 0xff), F_PF); + if (cnt == 1) { + CONDITIONAL_SET_FLAG((emu->op1.u16 ^ emu->res.u16) & 0x8000, F_OF); + } + } + break; case d_shrd32: cnt = emu->op2.u32; if (cnt > 0) { @@ -1001,7 +1014,6 @@ void UpdateFlags(x64emu_t *emu) case d_rcr16: case d_rcr32: case d_rcr64: - case d_shrd16: case d_unknown: printf_log(LOG_NONE, "Box64: %p trying to evaluate Unknown deferred Flags\n", (void*)R_RIP); break; |