diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/dynarec/rv64/dynarec_rv64_00.c | 6 | ||||
| -rw-r--r-- | src/dynarec/rv64/dynarec_rv64_emit_math.c | 56 | ||||
| -rw-r--r-- | src/dynarec/rv64/dynarec_rv64_helper.h | 2 |
3 files changed, 62 insertions, 2 deletions
diff --git a/src/dynarec/rv64/dynarec_rv64_00.c b/src/dynarec/rv64/dynarec_rv64_00.c index 8fb6a9ae..926f3d6a 100644 --- a/src/dynarec/rv64/dynarec_rv64_00.c +++ b/src/dynarec/rv64/dynarec_rv64_00.c @@ -1059,7 +1059,11 @@ uintptr_t dynarec64_00(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni nextop = F8; switch((nextop>>3)&7) { case 0: // INC Ed - DEFAULT; + INST_NAME("INC Ed"); + SETFLAGS(X_ALL&~X_CF, SF_SUBSET_PENDING); + GETED(0); + emit_inc32(dyn, ninst, rex, ed, x3, x4, x5, x6); + WBACK; break; case 1: //DEC Ed DEFAULT; diff --git a/src/dynarec/rv64/dynarec_rv64_emit_math.c b/src/dynarec/rv64/dynarec_rv64_emit_math.c index a201d639..8b735f32 100644 --- a/src/dynarec/rv64/dynarec_rv64_emit_math.c +++ b/src/dynarec/rv64/dynarec_rv64_emit_math.c @@ -294,3 +294,59 @@ void emit_sub32c(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int64_t c, i emit_pf(dyn, ninst, s1, s3, s4); } } + +// emit INC32 instruction, from s1, store result in s1 using s3 and s4 as scratch +void emit_inc32(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4, int s5) +{ + IFX(X_ALL) { + ANDI(xFlags, xFlags, ~((1UL<<F_AF) | (1UL<<F_OF2) | (1UL<<F_ZF) | (1UL<<F_SF) | (1UL<<F_PF))); + } + IFX(X_PEND) { + SDxw(s1, xEmu, offsetof(x64emu_t, op1)); + SET_DF(s3, rex.w?d_inc64:d_inc32); + } else IFX(X_ALL) { + SET_DFNONE(s3); + } + IFX(X_AF | X_OF) { + ORI(s3, s1, 1); // s3 = op1 | op2 + ANDI(s5, s1, 1); // s5 = op1 & op2 + } + + ADDIxw(s1, s1, 1); + + IFX(X_PEND) { + SDxw(s1, xEmu, offsetof(x64emu_t, res)); + } + IFX(X_AF | X_OF) { + NOT(s2, s1); // s2 = ~res + AND(s3, s2, s3); // s3 = ~res & (op1 | op2) + OR(s3, s3, s5); // cc = (~res & (op1 | op2)) | (op1 & op2) + IFX(X_AF) { + ANDI(s2, s3, 0x08); // AF: cc & 0x08 + BEQZ(s2, 8); + ORI(xFlags, xFlags, 1 << F_AF); + } + IFX(X_OF) { + SRLI(s3, s3, rex.w?62:30); + SRLI(s2, s3, 1); + XOR(s3, s3, s2); + ANDI(s3, s3, 1); // OF: xor of two MSB's of cc + BEQZ(s3, 8); + ORI(xFlags, xFlags, 1 << F_OF2); + } + } + IFX(X_SF) { + BGE(s1, xZR, 8); + ORI(xFlags, xFlags, 1 << F_SF); + } + if (!rex.w) { + ZEROUP(s1); + } + IFX(X_PF) { + emit_pf(dyn, ninst, s1, s3, s2); + } + IFX(X_ZF) { + BNEZ(s1, 8); + ORI(xFlags, xFlags, 1 << F_ZF); + } +} diff --git a/src/dynarec/rv64/dynarec_rv64_helper.h b/src/dynarec/rv64/dynarec_rv64_helper.h index 4eae5870..dca0f1da 100644 --- a/src/dynarec/rv64/dynarec_rv64_helper.h +++ b/src/dynarec/rv64/dynarec_rv64_helper.h @@ -646,7 +646,7 @@ void emit_and32c(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int64_t c, i //void emit_xor16c(dynarec_rv64_t* dyn, int ninst, int s1, int32_t c, int s3, int s4); //void emit_and16(dynarec_rv64_t* dyn, int ninst, int s1, int s2, int s3, int s4); //void emit_and16c(dynarec_rv64_t* dyn, int ninst, int s1, int32_t c, int s3, int s4); -//void emit_inc32(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int s3, int s4); +void emit_inc32(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4, int s5); //void emit_inc16(dynarec_rv64_t* dyn, int ninst, int s1, int s3, int s4); //void emit_inc8(dynarec_rv64_t* dyn, int ninst, int s1, int s3, int s4); //void emit_dec32(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int s3, int s4); |