diff --git a/src/dynarec/rv64/dynarec_rv64_66.c b/src/dynarec/rv64/dynarec_rv64_66.c index 5a35e1f21..dfb4a4b50 100644 --- a/src/dynarec/rv64/dynarec_rv64_66.c +++ b/src/dynarec/rv64/dynarec_rv64_66.c @@ -1077,13 +1077,17 @@ uintptr_t dynarec64_66(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni break; case 1: INST_NAME("ROR Ew, Ib"); - MESSAGE(LOG_DUMP, "Need Optimization\n"); - SETFLAGS(X_OF | X_CF, SF_SET_DF, NAT_FLAGS_NOFUSION); - GETEW(x1, 1); - u8 = F8; - MOV32w(x2, u8); - CALL_(ror16, x1, x3, x1, x2); - EWBACK; + if (geted_ib(dyn, addr, ninst, nextop) & 15) { + // removed PENDING on purpose + SETFLAGS(X_OF | X_CF, SF_SUBSET, NAT_FLAGS_FUSION); + GETEW(x1, 1); + u8 = (F8) & 0x1f; + emit_ror16c(dyn, ninst, x1, u8, x4, x5); + EWBACK; + } else { + FAKEED; + F8; + } break; case 2: INST_NAME("RCL Ew, Ib"); @@ -1195,11 +1199,10 @@ uintptr_t dynarec64_66(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni break; case 1: INST_NAME("ROR Ew, 1"); - MOV32w(x2, 1); - MESSAGE(LOG_DUMP, "Need Optimization\n"); - SETFLAGS(X_OF | X_CF, SF_SET_DF, NAT_FLAGS_NOFUSION); + // removed PENDING on purpose + SETFLAGS(X_OF | X_CF, SF_SUBSET, NAT_FLAGS_FUSION); GETEW(x1, 1); - CALL_(ror16, x1, x3, x1, x2); + emit_ror16c(dyn, ninst, x1, 1, x5, x4); EWBACK; break; case 2: diff --git a/src/dynarec/rv64/dynarec_rv64_emit_shift.c b/src/dynarec/rv64/dynarec_rv64_emit_shift.c index 8daa62dc2..54d4782e6 100644 --- a/src/dynarec/rv64/dynarec_rv64_emit_shift.c +++ b/src/dynarec/rv64/dynarec_rv64_emit_shift.c @@ -1141,6 +1141,41 @@ void emit_rol32c(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, uint32_t c, } } +// emit ROR16 instruction, from s1 , constant c, store result in s1 using s3 and s4 as scratch +void emit_ror16c(dynarec_rv64_t* dyn, int ninst, int s1, uint32_t c, int s3, int s4) +{ + if (!c) return; + + SET_DFNONE(); + + SRLI(s3, s1, c); + SLLI(s1, s1, 64 - c); + SRLI(s1, s1, 48); + OR(s1, s1, s3); + + if (dyn->insts[ninst].nat_flags_fusion) NAT_FLAGS_OPS(s1, xZR); + + IFX (X_CF | X_OF) { + ANDI(xFlags, xFlags, ~(1UL << F_CF | 1UL << F_OF2)); + } + + IFX (X_CF) { + SRLI(s3, s1, 15); + OR(xFlags, xFlags, s3); + } + + IFX (X_OF) { + if (c == 1) { + SRLI(s3, s1, 14); + SRLI(s4, s3, 1); + XOR(s3, s3, s4); + ANDI(s3, s3, 1); + SLLI(s3, s3, F_OF2); + OR(xFlags, xFlags, s3); + } + } +} + // emit ROR32 instruction, from s1 , constant c, store result in s1 using s3 and s4 as scratch void emit_ror32c(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, uint32_t c, int s3, int s4) { diff --git a/src/dynarec/rv64/dynarec_rv64_helper.h b/src/dynarec/rv64/dynarec_rv64_helper.h index a389f7b1d..b58caf0ef 100644 --- a/src/dynarec/rv64/dynarec_rv64_helper.h +++ b/src/dynarec/rv64/dynarec_rv64_helper.h @@ -1303,6 +1303,7 @@ void* rv64_next(void); #define emit_sar32c STEPNAME(emit_sar32c) #define emit_rol16c STEPNAME(emit_rol16c) #define emit_rol32 STEPNAME(emit_rol32) +#define emit_ror16c STEPNAME(emit_ror16c) #define emit_ror32 STEPNAME(emit_ror32) #define emit_rol32c STEPNAME(emit_rol32c) #define emit_ror32c STEPNAME(emit_ror32c) @@ -1472,6 +1473,7 @@ void emit_sar32c(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, uint32_t c, void emit_rol32(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4); void emit_ror32(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4); void emit_rol16c(dynarec_rv64_t* dyn, int ninst, int s1, uint32_t c, int s3, int s4); +void emit_ror16c(dynarec_rv64_t* dyn, int ninst, int s1, uint32_t c, int s3, int s4); void emit_rol32c(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, uint32_t c, int s3, int s4); void emit_ror32c(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, uint32_t c, int s3, int s4); void emit_shrd32c(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int s2, uint32_t c, int s3, int s4, int s5);