diff options
| author | xctan <xctan@cirno.icu> | 2023-04-14 14:44:59 +0800 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2023-04-14 08:44:59 +0200 |
| commit | 9413d5deb4ef1223dedc9b650885abb47e7077b1 (patch) | |
| tree | 7a9aaaafd52a2b0dc8736c79ffc20ec96f1c4f40 /src | |
| parent | 8a903f1e2cfe16634c60ade801410303d2d08723 (diff) | |
| download | box64-9413d5deb4ef1223dedc9b650885abb47e7077b1.tar.gz box64-9413d5deb4ef1223dedc9b650885abb47e7077b1.zip | |
[RV64_DYNAREC] Added more opcodes for SV (#699)
* [RV64_DYNAREC] Added D1 /0 ROL opcode
* [RV64_DYNAREC] Added D1 /1 ROR opcode
* [RV64_DYNAREC] Added {D0,D2} /1 ROR opcode
* [RV64_DYNAREC] Added C1 /1 ROR opcode
* [RV64_DYNAREC] Fixed ROR/ROL flagsDiffstat (limited to 'src')
| -rw-r--r-- | src/dynarec/rv64/dynarec_rv64_00_3.c | 43 | ||||
| -rw-r--r-- | src/dynarec/rv64/dynarec_rv64_emit_shift.c | 50 | ||||
| -rw-r--r-- | src/dynarec/rv64/dynarec_rv64_helper.h | 2 |
3 files changed, 90 insertions, 5 deletions
diff --git a/src/dynarec/rv64/dynarec_rv64_00_3.c b/src/dynarec/rv64/dynarec_rv64_00_3.c index 3259f231..2b25db74 100644 --- a/src/dynarec/rv64/dynarec_rv64_00_3.c +++ b/src/dynarec/rv64/dynarec_rv64_00_3.c @@ -141,6 +141,14 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int if(u8) { WBACK; } if(!wback && !rex.w) ZEROUP(ed); break; + case 1: + INST_NAME("ROR Ed, Ib"); + SETFLAGS(X_OF|X_CF, SF_SUBSET_PENDING); + GETED(1); + u8 = (F8)&(rex.w?0x3f:0x1f); + emit_ror32c(dyn, ninst, rex, ed, u8, x3, x4); + if(u8) { WBACK; } + break; case 4: case 6: INST_NAME("SHL Ed, Ib"); @@ -331,6 +339,25 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int case 0xD2: // TODO: Jump if CL is 0 nextop = F8; switch((nextop>>3)&7) { + case 1: + if(opcode==0xD0) { + INST_NAME("ROR Eb, 1"); + MOV32w(x2, 1); + } else { + INST_NAME("ROR Eb, CL"); + ANDI(x2, xRCX, 7); + } + SETFLAGS(X_OF|X_CF, SF_PENDING); + GETEB(x1, 0); + UFLAG_OP12(ed, x2); + SRL(x3, ed, x2); + SLLI(x4, ed, 8); + SRL(x4, x4, x2); + OR(ed, x3, x4); + EBBACK(x5, 1); + UFLAG_RES(ed); + UFLAG_DF(x3, d_ror8); + break; case 5: if(opcode==0xD0) { INST_NAME("SHR Eb, 1"); @@ -370,6 +397,22 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int case 0xD1: nextop = F8; switch((nextop>>3)&7) { + case 0: + INST_NAME("ROL Ed, 1"); + SETFLAGS(X_OF|X_CF, SF_SUBSET_PENDING); + GETED(0); + emit_rol32c(dyn, ninst, rex, ed, 1, x3, x4); + WBACK; + if(!wback && !rex.w) ZEROUP(ed); + break; + case 1: + INST_NAME("ROR Ed, 1"); + SETFLAGS(X_OF|X_CF, SF_SUBSET_PENDING); + GETED(0); + emit_rol32c(dyn, ninst, rex, ed, rex.w?63:31, x3, x4); + WBACK; + if(!wback && !rex.w) ZEROUP(ed); + break; case 4: case 6: INST_NAME("SHL Ed, 1"); diff --git a/src/dynarec/rv64/dynarec_rv64_emit_shift.c b/src/dynarec/rv64/dynarec_rv64_emit_shift.c index 04d73f10..be84894c 100644 --- a/src/dynarec/rv64/dynarec_rv64_emit_shift.c +++ b/src/dynarec/rv64/dynarec_rv64_emit_shift.c @@ -312,8 +312,8 @@ 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) { int64_t j64; - IFX(X_CF) { - ANDI(xFlags, xFlags, ~(1UL<<F_CF)); + IFX(X_CF | X_OF) { + ANDI(xFlags, xFlags, ~(1UL<<F_CF | 1UL<<F_OF2)); } IFX(X_PEND) { @@ -355,8 +355,8 @@ void emit_rol32(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s // emit ROL32 instruction, from s1 , constant c, store result in s1 using s3 and s4 as scratch void emit_rol32c(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, uint32_t c, int s3, int s4) { - IFX(X_CF) { - ANDI(xFlags, xFlags, ~(1UL<<F_CF)); + IFX(X_CF | X_OF) { + ANDI(xFlags, xFlags, ~(1UL<<F_CF | 1UL<<F_OF2)); } IFX(X_PEND) { @@ -394,6 +394,48 @@ void emit_rol32c(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, uint32_t c, } } +// 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) +{ + IFX(X_CF | X_OF) { + ANDI(xFlags, xFlags, ~(1UL<<F_CF | 1UL<<F_OF2)); + } + + IFX(X_PEND) { + MOV32w(s3, c); + SDxw(s3, xEmu, offsetof(x64emu_t, op2)); + SET_DF(s4, rex.w?d_ror64:d_ror32); + } else IFX(X_ALL) { + SET_DFNONE(); + } + if(!c) { + IFX(X_PEND) { + SDxw(s1, xEmu, offsetof(x64emu_t, res)); + } + return; + } + SRLIxw(s3, s1, c); + SLLIxw(s1, s1, (rex.w?64:32)-c); + OR(s1, s3, s1); + IFX(X_PEND) { + SDxw(s1, xEmu, offsetof(x64emu_t, res)); + } + IFX(X_CF) { + SRLI(s3, s1, rex.w?63:31); + AND(xFlags, xFlags, s3); + } + IFX(X_OF) { + if(c==1) { + SRLI(s3, s1, rex.w?62:30); + SRLI(s4, s3, 1); + XOR(s3, s3, s4); + ANDI(s3, s3, 1); + SLLI(s3, s3, F_OF2); + OR(xFlags, xFlags, s3); + } + } +} + // emit SHRD32 instruction, from s1, fill s2 , constant c, store result in s1 using s3 and s4 as scratch void emit_shrd32c(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int s2, 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 d80d52b3..18e425e3 100644 --- a/src/dynarec/rv64/dynarec_rv64_helper.h +++ b/src/dynarec/rv64/dynarec_rv64_helper.h @@ -968,7 +968,7 @@ void emit_shr32c(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, uint32_t c, void emit_sar32c(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, uint32_t c, int s3, int s4); void emit_rol32(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int s2, 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_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); void emit_shld32c(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int s2, uint32_t c, int s3, int s4, int s5); |