diff options
| author | Yang Liu <numbksco@gmail.com> | 2024-05-02 00:09:44 +0800 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-05-01 18:09:44 +0200 |
| commit | 817408d2471819f0c5f34f787b479dd11324b489 (patch) | |
| tree | 0a924ae77fcdcb480804084da743d18fdff9b710 /src | |
| parent | 8d77e39f4aaacf2c00c7196d8a3a50a29f83503b (diff) | |
| download | box64-817408d2471819f0c5f34f787b479dd11324b489.tar.gz box64-817408d2471819f0c5f34f787b479dd11324b489.zip | |
[LA64_DYNAREC] Added more opcodes (#1481)
Diffstat (limited to 'src')
| -rw-r--r-- | src/dynarec/la64/dynarec_la64_00.c | 25 | ||||
| -rw-r--r-- | src/dynarec/la64/dynarec_la64_0f.c | 16 | ||||
| -rw-r--r-- | src/dynarec/la64/dynarec_la64_66.c | 10 | ||||
| -rw-r--r-- | src/dynarec/la64/dynarec_la64_emit_math.c | 116 | ||||
| -rw-r--r-- | src/dynarec/la64/dynarec_la64_helper.h | 4 |
5 files changed, 171 insertions, 0 deletions
diff --git a/src/dynarec/la64/dynarec_la64_00.c b/src/dynarec/la64/dynarec_la64_00.c index 47a0548d..f934c5f3 100644 --- a/src/dynarec/la64/dynarec_la64_00.c +++ b/src/dynarec/la64/dynarec_la64_00.c @@ -1403,6 +1403,14 @@ uintptr_t dynarec64_00(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni case 0xD1: nextop = F8; switch ((nextop >> 3) & 7) { + case 4: + case 6: + INST_NAME("SHL Ed, 1"); + SETFLAGS(X_ALL, SF_SET_PENDING); // some flags are left undefined + GETED(0); + emit_shl32c(dyn, ninst, rex, ed, 1, x3, x4, x5); + WBACK; + break; case 5: INST_NAME("SHR Ed, 1"); SETFLAGS(X_ALL, SF_SET_PENDING); // some flags are left undefined @@ -1695,6 +1703,23 @@ uintptr_t dynarec64_00(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni MOV32w(x2, u8); emit_test8(dyn, ninst, x1, x2, x3, x4, x5); break; + case 3: + INST_NAME("NEG Eb"); + SETFLAGS(X_ALL, SF_SET_PENDING); + GETEB(x1, 0); + emit_neg8(dyn, ninst, x1, x2, x4); + EBBACK(); + break; + case 4: + INST_NAME("MUL AL, Ed"); + SETFLAGS(X_ALL, SF_PENDING); + UFLAG_DF(x1, d_mul8); + GETEB(x1, 0); + ANDI(x2, xRAX, 0xff); + MUL_W(x1, x2, x1); + UFLAG_RES(x1); + BSTRINS_D(xRAX, x1, 15, 0); + break; default: DEFAULT; } diff --git a/src/dynarec/la64/dynarec_la64_0f.c b/src/dynarec/la64/dynarec_la64_0f.c index 65bf7881..731e0f72 100644 --- a/src/dynarec/la64/dynarec_la64_0f.c +++ b/src/dynarec/la64/dynarec_la64_0f.c @@ -8,6 +8,7 @@ #include "dynarec.h" #include "emu/x64emu_private.h" #include "emu/x64run_private.h" +#include "la64_emitter.h" #include "x64run.h" #include "x64emu.h" #include "box64stack.h" @@ -118,6 +119,21 @@ uintptr_t dynarec64_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni SMWRITE2(); } break; + case 0x12: + nextop = F8; + if (MODREG) { + INST_NAME("MOVHLPS Gx,Ex"); + GETGX(v0, 1); + v1 = sse_get_reg(dyn, ninst, x1, (nextop & 7) + (rex.b << 3), 0); + VEXTRINS_D(v0, v1, 1); + } else { + INST_NAME("MOVLPS Gx,Ex"); + GETGX(v0, 1); + SMREAD(); + GETEX(q1, 0, 0); + VEXTRINS_D(v0, q1, 0); + } + break; case 0x16: nextop = F8; if (MODREG) { diff --git a/src/dynarec/la64/dynarec_la64_66.c b/src/dynarec/la64/dynarec_la64_66.c index 626e33d7..0e0a3db0 100644 --- a/src/dynarec/la64/dynarec_la64_66.c +++ b/src/dynarec/la64/dynarec_la64_66.c @@ -65,6 +65,16 @@ uintptr_t dynarec64_66(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni DEFAULT; } break; + case 0x19: + INST_NAME("SBB Ew, Gw"); + READFLAGS(X_CF); + SETFLAGS(X_ALL, SF_SET_PENDING); + nextop = F8; + GETGW(x2); + GETEW(x1, 0); + emit_sbb16(dyn, ninst, x1, x2, x4, x5, x6); + EWBACK; + break; case 0x39: INST_NAME("CMP Ew, Gw"); SETFLAGS(X_ALL, SF_SET_PENDING); diff --git a/src/dynarec/la64/dynarec_la64_emit_math.c b/src/dynarec/la64/dynarec_la64_emit_math.c index 23a2acf9..d9958f27 100644 --- a/src/dynarec/la64/dynarec_la64_emit_math.c +++ b/src/dynarec/la64/dynarec_la64_emit_math.c @@ -8,6 +8,7 @@ #include "dynarec.h" #include "emu/x64emu_private.h" #include "emu/x64run_private.h" +#include "la64_emitter.h" #include "x64run.h" #include "x64emu.h" #include "box64stack.h" @@ -770,6 +771,59 @@ void emit_sbb8c(dynarec_la64_t* dyn, int ninst, int s1, int c, int s3, int s4, i emit_sbb8(dyn, ninst, s1, s6, s3, s4, s5); } +// emit SBB16 instruction, from s1, s2, store result in s1 using s3, s4 and s5 as scratch +void emit_sbb16(dynarec_la64_t* dyn, int ninst, int s1, int s2, int s3, int s4, int s5) +{ + IFX (X_PEND) { + ST_H(s1, xEmu, offsetof(x64emu_t, op1)); + ST_H(s2, xEmu, offsetof(x64emu_t, op2)); + SET_DF(s3, d_sbb16); + } else IFX (X_ALL) { + SET_DFNONE(); + } + + IFXA (X_ALL, la64_lbt) { + SBC_H(s3, s1, s2); + + IFX (X_ALL) { + X64_SBC_H(s1, s2); + } + BSTRPICK_D(s1, s3, 15, 0); + IFX (X_PEND) + ST_H(s1, xEmu, offsetof(x64emu_t, res)); + return; + } + + IFX (X_AF | X_CF | X_OF) { + // for later flag calculation + NOR(s5, xZR, s1); + } + + SUB_W(s1, s1, s2); + ANDI(s3, xFlags, 1 << F_CF); + SUB_W(s1, s1, s3); + + CLEAR_FLAGS(s3); + SLLI_W(s1, s1, 16); + IFX (X_SF) { + BGE(s1, xZR, 8); + ORI(xFlags, xFlags, 1 << F_SF); + } + SRLI_W(s1, s1, 16); + + IFX (X_PEND) { + ST_H(s1, xEmu, offsetof(x64emu_t, res)); + } + + CALC_SUB_FLAGS(s5, s2, s1, s3, s4, 16); + IFX (X_ZF) { + BNEZ(s1, 8); + ORI(xFlags, xFlags, 1 << F_ZF); + } + IFX (X_PF) { + emit_pf(dyn, ninst, s1, s3, s4); + } +} // emit SBB32 instruction, from s1, s2, store result in s1 using s3, s4 and s5 as scratch void emit_sbb32(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4, int s5) @@ -834,6 +888,68 @@ void emit_sbb32(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s } +// emit NEG8 instruction, from s1, store result in s1 using s2 and s3 as scratch +void emit_neg8(dynarec_la64_t* dyn, int ninst, int s1, int s2, int s3) +{ + IFX (X_PEND) { + ST_B(s1, xEmu, offsetof(x64emu_t, op1)); + SET_DF(s3, d_neg8); + } else IFX (X_ALL) { + SET_DFNONE(); + } + IFX (X_AF | X_OF) { + MV(s3, s1); // s3 = op1 + } + + IFXA (X_ALL, la64_lbt) { + X64_SUB_B(xZR, s1); + } + + NEG_D(s1, s1); + ANDI(s1, s1, 0xff); + IFX (X_PEND) { + ST_B(s1, xEmu, offsetof(x64emu_t, res)); + } + + if (la64_lbt) return; + + CLEAR_FLAGS(s2); + IFX (X_CF) { + BEQZ(s1, 8); + ORI(xFlags, xFlags, 1 << F_CF); + } + + IFX (X_AF | X_OF) { + OR(s3, s1, s3); // s3 = res | op1 + IFX (X_AF) { + /* af = bc & 0x8 */ + ANDI(s2, s3, 8); + BEQZ(s2, 8); + ORI(xFlags, xFlags, 1 << F_AF); + } + IFX (X_OF) { + /* of = ((bc >> (width-2)) ^ (bc >> (width-1))) & 0x1; */ + SRLI_D(s2, s3, 6); + SRLI_D(s3, s2, 1); + XOR(s2, s2, s3); + ANDI(s2, s2, 1); + BEQZ(s2, 8); + ORI(xFlags, xFlags, 1 << F_OF); + } + } + IFX (X_SF) { + ANDI(s3, s1, 1 << F_SF); // 1<<F_SF is sign bit, so just mask + OR(xFlags, xFlags, s3); + } + IFX (X_PF) { + emit_pf(dyn, ninst, s1, s3, s2); + } + IFX (X_ZF) { + BNEZ(s1, 8); + ORI(xFlags, xFlags, 1 << F_ZF); + } +} + // emit NEG32 instruction, from s1, store result in s1 using s2 and s3 as scratch void emit_neg32(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3) { diff --git a/src/dynarec/la64/dynarec_la64_helper.h b/src/dynarec/la64/dynarec_la64_helper.h index 50405c1c..2ac88693 100644 --- a/src/dynarec/la64/dynarec_la64_helper.h +++ b/src/dynarec/la64/dynarec_la64_helper.h @@ -738,7 +738,9 @@ void* la64_next(x64emu_t* emu, uintptr_t addr); #define emit_sub8c STEPNAME(emit_sub8c) #define emit_sbb8 STEPNAME(emit_sbb8) #define emit_sbb8c STEPNAME(emit_sbb8c) +#define emit_sbb16 STEPNAME(emit_sbb16) #define emit_sbb32 STEPNAME(emit_sbb32) +#define emit_neg8 STEPNAME(emit_neg8) #define emit_neg32 STEPNAME(emit_neg32) #define emit_or32 STEPNAME(emit_or32) #define emit_or32c STEPNAME(emit_or32c) @@ -816,7 +818,9 @@ void emit_sub8(dynarec_la64_t* dyn, int ninst, int s1, int s2, int s3, int s4, i void emit_sub8c(dynarec_la64_t* dyn, int ninst, int s1, int32_t c, int s2, int s3, int s4, int s5); void emit_sbb8(dynarec_la64_t* dyn, int ninst, int s1, int s2, int s3, int s4, int s5); void emit_sbb8c(dynarec_la64_t* dyn, int ninst, int s1, int32_t c, int s3, int s4, int s5, int s6); +void emit_sbb16(dynarec_la64_t* dyn, int ninst, int s1, int s2, int s3, int s4, int s5); 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_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); |