diff options
| author | ptitSeb <sebastien.chev@gmail.com> | 2024-05-02 15:44:14 +0200 |
|---|---|---|
| committer | ptitSeb <sebastien.chev@gmail.com> | 2024-05-02 15:44:14 +0200 |
| commit | 85458d1f2045324c669cf4a283d21ac46c5f2e48 (patch) | |
| tree | c7e71eaae1dd1f62e1cdd56423b959b43a064076 /src | |
| parent | 5b5723c5a50a607331787a14081c47ba8e7d9400 (diff) | |
| download | box64-85458d1f2045324c669cf4a283d21ac46c5f2e48.tar.gz box64-85458d1f2045324c669cf4a283d21ac46c5f2e48.zip | |
[ARM64_DYNAREC] Added rcr16 / rcl16 emitter, plus some tiny fixes to other rotate operations
Diffstat (limited to 'src')
| -rw-r--r-- | src/dynarec/arm64/dynarec_arm64_00.c | 8 | ||||
| -rw-r--r-- | src/dynarec/arm64/dynarec_arm64_66.c | 32 | ||||
| -rw-r--r-- | src/dynarec/arm64/dynarec_arm64_emit_shift.c | 99 | ||||
| -rw-r--r-- | src/dynarec/arm64/dynarec_arm64_helper.h | 4 |
4 files changed, 114 insertions, 29 deletions
diff --git a/src/dynarec/arm64/dynarec_arm64_00.c b/src/dynarec/arm64/dynarec_arm64_00.c index 7f0aff2f..54f59b0d 100644 --- a/src/dynarec/arm64/dynarec_arm64_00.c +++ b/src/dynarec/arm64/dynarec_arm64_00.c @@ -2420,14 +2420,14 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin switch((nextop>>3)&7) { case 0: INST_NAME("ROL Eb, 1"); - SETFLAGS(X_OF|X_CF, SF_SUBSET); + SETFLAGS(X_OF|X_CF, SF_SUBSET_PENDING); GETEB(x1, 0); emit_rol8c(dyn, ninst, ed, 1, x4, x5); EBBACK; break; case 1: INST_NAME("ROR Eb, 1"); - SETFLAGS(X_OF|X_CF, SF_SUBSET); + SETFLAGS(X_OF|X_CF, SF_SUBSET_PENDING); GETEB(x1, 0); emit_ror8c(dyn, ninst, ed, 1, x4, x5); EBBACK; @@ -2435,7 +2435,7 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin case 2: INST_NAME("RCL Eb, 1"); READFLAGS(X_CF); - SETFLAGS(X_OF|X_CF, SF_SUBSET); + SETFLAGS(X_OF|X_CF, SF_SUBSET_PENDING); GETEB(x1, 0); emit_rcl8c(dyn, ninst, ed, 1, x4, x5); EBBACK; @@ -2443,7 +2443,7 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin case 3: INST_NAME("RCR Eb, 1"); READFLAGS(X_CF); - SETFLAGS(X_OF|X_CF, SF_SUBSET); + SETFLAGS(X_OF|X_CF, SF_SUBSET_PENDING); GETEB(x1, 0); emit_rcr8c(dyn, ninst, ed, 1, x4, x5); EBBACK; diff --git a/src/dynarec/arm64/dynarec_arm64_66.c b/src/dynarec/arm64/dynarec_arm64_66.c index e6761c63..709605f1 100644 --- a/src/dynarec/arm64/dynarec_arm64_66.c +++ b/src/dynarec/arm64/dynarec_arm64_66.c @@ -974,27 +974,21 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin } break; case 2: - INST_NAME("RCL Ew, Ib"); - MESSAGE(LOG_DUMP, "Need Optimization\n"); + INST_NAME("RCL Ew, 1"); READFLAGS(X_CF); - u8 = geted_ib(dyn, addr, ninst, nextop) & 0x1f; - SETFLAGS(X_OF | X_CF, SF_SET_DF); + SETFLAGS(X_OF|X_CF, SF_SUBSET_PENDING); GETEW(x1, 1); u8 = F8; - MOV32w(x2, u8); - CALL_(rcl16, x1, x3); + emit_rcl8c(dyn, ninst, ed, u8, x4, x5); EWBACK; break; case 3: - INST_NAME("RCR Ew, Ib"); - MESSAGE(LOG_DUMP, "Need Optimization\n"); + INST_NAME("RCR Ew, 1"); READFLAGS(X_CF); - u8 = geted_ib(dyn, addr, ninst, nextop) & 0x1f; - SETFLAGS(X_OF | X_CF, SF_SET_DF); + SETFLAGS(X_OF|X_CF, SF_SUBSET_PENDING); GETEW(x1, 1); u8 = F8; - MOV32w(x2, u8); - CALL_(rcr16, x1, x3); + emit_rcr8c(dyn, ninst, ed, u8, x4, x5); EWBACK; break; case 4: @@ -1076,22 +1070,16 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin break; case 2: INST_NAME("RCL Ew, 1"); - MESSAGE(LOG_DUMP, "Need Optimization\n"); - READFLAGS(X_CF); - SETFLAGS(X_OF|X_CF, SF_SET_DF); - MOV32w(x2, 1); + SETFLAGS(X_OF|X_CF, SF_SUBSET_PENDING); GETEW(x1, 0); - CALL_(rcl16, x1, x3); + emit_rcl16c(dyn, ninst, x1, 1, x5, x4); EWBACK; break; case 3: INST_NAME("RCR Ew, 1"); - MESSAGE(LOG_DUMP, "Need Optimization\n"); - READFLAGS(X_CF); - SETFLAGS(X_OF|X_CF, SF_SET_DF); - MOV32w(x2, 1); + SETFLAGS(X_OF|X_CF, SF_SUBSET_PENDING); GETEW(x1, 0); - CALL_(rcr16, x1, x3); + emit_rcr16c(dyn, ninst, x1, 1, x5, x4); EWBACK; break; case 4: diff --git a/src/dynarec/arm64/dynarec_arm64_emit_shift.c b/src/dynarec/arm64/dynarec_arm64_emit_shift.c index a05eee0e..486555f1 100644 --- a/src/dynarec/arm64/dynarec_arm64_emit_shift.c +++ b/src/dynarec/arm64/dynarec_arm64_emit_shift.c @@ -1013,10 +1013,14 @@ void emit_rcl8c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int s } BFIw(s1, xFlags, 8, 1); // insert cf IFX(X_OF|X_CF) { - if(c%9!=8) { - LSRw_IMM(s3, s1, 8-(c%9)); + if(c%9) { + if(c%9!=8) { + LSRw_IMM(s3, s1, 8-(c%9)); + } else { + MOVw_REG(s3, s1); + } } else { - MOVw_REG(s3, s1); + MOVw_REG(s3, xFlags); } } ORRw_REG_LSL(s1, s1, s1, 9); // insert s1 again @@ -1082,6 +1086,95 @@ void emit_rcr8c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int s } } +// emit RCL16 instruction, from s1 , constant c, store result in s1 using s3 and s4 as scratch +void emit_rcl16c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int s4) +{ + MAYUSE(s1); MAYUSE(s3); MAYUSE(s4); + + if (!c) return; + + 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_rcl16); + } else IFX(X_ALL) { + SET_DFNONE(s4); + } + 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); + } + } else { + MOVw_REG(s3, xFlags); + } + } + ORRw_REG_LSL(s1, s1, s1, 17); // insert s1 again + if(c%17) { + LSRw_IMM(s1, s1, 17-(c%17)); // 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_OF) { + if(c==1) { + EORw_REG_LSR(s3, s3, s1, 15); + BFIw(xFlags, s3, F_OF, 1); + } + } + } +} + +// emit RCR16 instruction, from s1 , constant c, store result in s1 using s3 and s4 as scratch +void emit_rcr16c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int s4) +{ + MAYUSE(s1); MAYUSE(s3); MAYUSE(s4); + + if (!c) return; + + 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_rcr16); + } 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); + } + } + 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_PEND) { + STRB_U12(s1, xEmu, offsetof(x64emu_t, res)); + } + 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); + } + } + } +} // 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/dynarec/arm64/dynarec_arm64_helper.h b/src/dynarec/arm64/dynarec_arm64_helper.h index e4a7c94d..f19db163 100644 --- a/src/dynarec/arm64/dynarec_arm64_helper.h +++ b/src/dynarec/arm64/dynarec_arm64_helper.h @@ -1100,6 +1100,8 @@ void* arm64_next(x64emu_t* emu, uintptr_t addr); #define emit_ror16c STEPNAME(emit_ror16c) #define emit_rcl8c STEPNAME(emit_rcl8c) #define emit_rcr8c STEPNAME(emit_rcr8c) +#define emit_rcl16c STEPNAME(emit_rcl16c) +#define emit_rcr16c STEPNAME(emit_rcr16c) #define emit_shrd32c STEPNAME(emit_shrd32c) #define emit_shrd32 STEPNAME(emit_shrd32) #define emit_shld32c STEPNAME(emit_shld32c) @@ -1255,6 +1257,8 @@ void emit_rol16c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int void emit_ror16c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int s4); void emit_rcl8c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int s4); void emit_rcr8c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int s4); +void emit_rcl16c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int s4); +void emit_rcr16c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int s4); 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); |