diff options
| author | Yang Liu <numbksco@gmail.com> | 2024-05-23 16:51:07 +0800 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-05-23 10:51:07 +0200 |
| commit | 080cc772083be446132557e3b2e6aad1b59c0e3f (patch) | |
| tree | 43ba80b09892ce59c8d4143f99248146132eb25e /src | |
| parent | 7ebd92be7dab9f3959c8c25f73d3637ddcd72149 (diff) | |
| download | box64-080cc772083be446132557e3b2e6aad1b59c0e3f.tar.gz box64-080cc772083be446132557e3b2e6aad1b59c0e3f.zip | |
[LA64_DYNAREC] Added more opcodes (#1525)
Diffstat (limited to 'src')
| -rw-r--r-- | src/core.c | 2 | ||||
| -rw-r--r-- | src/dynarec/la64/dynarec_la64_00.c | 14 | ||||
| -rw-r--r-- | src/dynarec/la64/dynarec_la64_emit_math.c | 139 | ||||
| -rw-r--r-- | src/dynarec/la64/dynarec_la64_helper.h | 4 |
4 files changed, 158 insertions, 1 deletions
diff --git a/src/core.c b/src/core.c index b1a552bb..c8a56384 100644 --- a/src/core.c +++ b/src/core.c @@ -473,7 +473,7 @@ HWCAP2_ECV if (la64_lbt = (cpucfg2 >> 18) & 0b1) printf_log(LOG_INFO, " LBT_X86"); if (la64_lam_bh = (cpucfg2 >> 27) & 0b1) - printf_log(LOG_INFO, " LAM_BT"); + printf_log(LOG_INFO, " LAM_BH"); if (la64_lamcas = (cpucfg2 >> 28) & 0b1) printf_log(LOG_INFO, " LAMCAS"); if (la64_scq = (cpucfg2 >> 30) & 0b1) diff --git a/src/dynarec/la64/dynarec_la64_00.c b/src/dynarec/la64/dynarec_la64_00.c index 570db990..4ed4e271 100644 --- a/src/dynarec/la64/dynarec_la64_00.c +++ b/src/dynarec/la64/dynarec_la64_00.c @@ -2055,6 +2055,20 @@ uintptr_t dynarec64_00(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni case 0xFF: nextop = F8; switch ((nextop >> 3) & 7) { + case 0: // INC Ed + 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 + INST_NAME("DEC Ed"); + SETFLAGS(X_ALL & ~X_CF, SF_SUBSET_PENDING); + GETED(0); + emit_dec32(dyn, ninst, rex, ed, x3, x4, x5, x6); + WBACK; + break; case 2: INST_NAME("CALL Ed"); PASS2IF((box64_dynarec_safeflags > 1) || ((ninst && dyn->insts[ninst - 1].x64.set_flags) || ((ninst > 1) && dyn->insts[ninst - 2].x64.set_flags)), 1) diff --git a/src/dynarec/la64/dynarec_la64_emit_math.c b/src/dynarec/la64/dynarec_la64_emit_math.c index 50a8b103..cd94673e 100644 --- a/src/dynarec/la64/dynarec_la64_emit_math.c +++ b/src/dynarec/la64/dynarec_la64_emit_math.c @@ -1126,3 +1126,142 @@ void emit_adc32(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s ORI(xFlags, xFlags, 1 << F_ZF); } } + +// emit INC32 instruction, from s1, store result in s1 using s3 and s4 as scratch +void emit_inc32(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4, int s5) +{ + 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(); + } + + IFXA (X_AF | X_OF, !la64_lbt) { + ORI(s3, s1, 1); // s3 = op1 | op2 + ANDI(s5, s1, 1); // s5 = op1 & op2 + } + + IFXA (X_ALL, la64_lbt) { + if (rex.w) { + X64_INC_D(s1); + } else { + X64_INC_W(s1); + } + } + + ADDIxw(s1, s1, 1); + + IFX (X_PEND) { + SDxw(s1, xEmu, offsetof(x64emu_t, res)); + } + + if (la64_lbt) return; + + IFX (X_ALL) { + // preserving CF + MOV64x(s4, (1UL << F_AF) | (1UL << F_OF) | (1UL << F_ZF) | (1UL << F_SF) | (1UL << F_PF)); + ANDN(xFlags, xFlags, s4); + } + IFX (X_AF | X_OF) { + ANDN(s3, s3, s1); // 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_D(s3, s3, rex.w ? 62 : 30); + SRLI_D(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_OF); + } + } + 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); + } +} + +// emit DEC32 instruction, from s1, store result in s1 using s3 and s4 as scratch +void emit_dec32(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4, int s5) +{ + IFX (X_PEND) { + SDxw(s1, xEmu, offsetof(x64emu_t, op1)); + SET_DF(s3, rex.w ? d_dec64 : d_dec32); + } else IFX (X_ALL) { + SET_DFNONE(); + } + IFXA (X_AF | X_OF, !la64_lbt) { + NOR(s5, xZR, s1); + ORI(s3, s5, 1); // s3 = ~op1 | op2 + ANDI(s5, s5, 1); // s5 = ~op1 & op2 + } + + IFXA (X_ALL, la64_lbt) { + if (rex.w) { + X64_DEC_D(s1); + } else { + X64_DEC_W(s1); + } + } + + + ADDIxw(s1, s1, -1); + + IFX (X_PEND) { + SDxw(s1, xEmu, offsetof(x64emu_t, res)); + } + + if (la64_lbt) return; + + IFX (X_ALL) { + // preserving CF + MOV64x(s4, (1UL << F_AF) | (1UL << F_OF) | (1UL << F_ZF) | (1UL << F_SF) | (1UL << F_PF)); + ANDN(xFlags, xFlags, s4); + } + IFX (X_AF | X_OF) { + AND(s3, s1, 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_D(s3, s3, rex.w ? 62 : 30); + SRLI_D(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_OF); + } + } + 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/la64/dynarec_la64_helper.h b/src/dynarec/la64/dynarec_la64_helper.h index a8bd4018..cb74bcdf 100644 --- a/src/dynarec/la64/dynarec_la64_helper.h +++ b/src/dynarec/la64/dynarec_la64_helper.h @@ -764,6 +764,8 @@ void* la64_next(x64emu_t* emu, uintptr_t addr); #define emit_sbb32 STEPNAME(emit_sbb32) #define emit_neg8 STEPNAME(emit_neg8) #define emit_neg32 STEPNAME(emit_neg32) +#define emit_inc32 STEPNAME(emit_inc32) +#define emit_dec32 STEPNAME(emit_dec32) #define emit_or32 STEPNAME(emit_or32) #define emit_or32c STEPNAME(emit_or32c) #define emit_or8 STEPNAME(emit_or8) @@ -853,6 +855,8 @@ void emit_sbb16(dynarec_la64_t* dyn, int ninst, int s1, int s2, int s3, int s4, void emit_sbb32(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4, int s5); void emit_neg8(dynarec_la64_t* dyn, int ninst, int s1, int s3, int s4); void emit_neg32(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3); +void emit_inc32(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4, int s5); +void emit_dec32(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4, int s5); void emit_or32(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4); void emit_or32c(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, int64_t c, int s3, int s4); void emit_or8(dynarec_la64_t* dyn, int ninst, int s1, int s2, int s3, int s4); |