diff options
| author | Yang Liu <numbksco@gmail.com> | 2024-05-03 03:42:41 +0800 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-05-02 21:42:41 +0200 |
| commit | 0f6654bf950c45c8bc80ee4966fc161b1e3d1998 (patch) | |
| tree | 15cc64f03b8c73e005599eba062659034a1809a4 | |
| parent | fa27ddecc5ae8a5e8c049ba78a19a0928e028e28 (diff) | |
| download | box64-0f6654bf950c45c8bc80ee4966fc161b1e3d1998.tar.gz box64-0f6654bf950c45c8bc80ee4966fc161b1e3d1998.zip | |
[LA64_DYNAREC] Added more opcodes (#1486)
| -rw-r--r-- | src/dynarec/la64/dynarec_la64_66.c | 25 | ||||
| -rw-r--r-- | src/dynarec/la64/dynarec_la64_660f.c | 52 | ||||
| -rw-r--r-- | src/dynarec/la64/dynarec_la64_emit_logic.c | 78 | ||||
| -rw-r--r-- | src/dynarec/la64/dynarec_la64_f30f.c | 18 | ||||
| -rw-r--r-- | src/dynarec/la64/dynarec_la64_helper.h | 4 |
5 files changed, 177 insertions, 0 deletions
diff --git a/src/dynarec/la64/dynarec_la64_66.c b/src/dynarec/la64/dynarec_la64_66.c index 03fdd13c..2d6d0f81 100644 --- a/src/dynarec/la64/dynarec_la64_66.c +++ b/src/dynarec/la64/dynarec_la64_66.c @@ -76,6 +76,15 @@ uintptr_t dynarec64_66(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni emit_sbb16(dyn, ninst, x1, x2, x4, x5, x6); EWBACK; break; + case 0x31: + INST_NAME("XOR Ew, Gw"); + SETFLAGS(X_ALL, SF_SET_PENDING); + nextop = F8; + GETGW(x2); + GETEW(x1, 0); + emit_xor16(dyn, ninst, x1, x2, x4, x5, x6); + EWBACK; + break; case 0x39: INST_NAME("CMP Ew, Gw"); SETFLAGS(X_ALL, SF_SET_PENDING); @@ -104,6 +113,22 @@ uintptr_t dynarec64_66(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni emit_add16(dyn, ninst, ed, x5, x2, x4, x6); EWBACK; break; + case 1: // OR + if (opcode == 0x81) { + INST_NAME("OR Ew, Iw"); + } else { + INST_NAME("OR Ew, Ib"); + } + SETFLAGS(X_ALL, SF_SET_PENDING); + GETEW(x1, (opcode == 0x81) ? 2 : 1); + if (opcode == 0x81) + i16 = F16S; + else + i16 = F8S; + MOV64x(x5, i16); + emit_or16(dyn, ninst, x1, x5, x2, x4); + EWBACK; + break; case 5: // SUB if (opcode == 0x81) { INST_NAME("SUB Ew, Iw"); diff --git a/src/dynarec/la64/dynarec_la64_660f.c b/src/dynarec/la64/dynarec_la64_660f.c index 487e8195..3bac9e1f 100644 --- a/src/dynarec/la64/dynarec_la64_660f.c +++ b/src/dynarec/la64/dynarec_la64_660f.c @@ -51,6 +51,20 @@ uintptr_t dynarec64_660F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int MAYUSE(j64); switch (opcode) { + case 0x14: + INST_NAME("UNPCKLPD Gx, Ex"); + nextop = F8; + GETGX(v0, 1); + if (MODREG) { + v1 = sse_get_reg(dyn, ninst, x1, (nextop & 7) + (rex.b << 3), 0); + } else { + SMREAD(); + addr = geted(dyn, addr, ninst, nextop, &ed, x2, x3, &fixedaddress, rex, NULL, 1, 0); + v1 = fpu_get_scratch(dyn); + FLD_D(v1, ed, fixedaddress); + } + VEXTRINS_D(v0, v1, 0x10); + break; case 0x1F: INST_NAME("NOP (multibyte)"); nextop = F8; @@ -194,6 +208,17 @@ uintptr_t dynarec64_660F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int DEFAULT; } break; + case 0x5A: + INST_NAME("CVTPD2PS Gx, Ex"); + nextop = F8; + GETEX(v1, 0, 0); + GETGX_empty(v0); + // TODO: is there any way to support !box64_dynarec_fastround? + q0 = fpu_get_scratch(dyn); + VFCVT_S_D(q0, v1, v1); + VXOR_V(v0, v0, v0); + VEXTRINS_D(v0, q0, 0); + break; case 0x60: INST_NAME("PUNPCKLBW Gx,Ex"); nextop = F8; @@ -285,6 +310,20 @@ uintptr_t dynarec64_660F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int } VILVL_D(v0, v1, v0); // v0[127:64] = v1[63:0] break; + case 0x6D: + INST_NAME("PUNPCKHQDQ Gx,Ex"); + nextop = F8; + GETGX(v0, 1); + if (MODREG) { + v1 = sse_get_reg(dyn, ninst, x1, (nextop & 7) + (rex.b << 3), 0); + } else { + v1 = fpu_get_scratch(dyn); + addr = geted(dyn, addr, ninst, nextop, &ed, x2, x3, &fixedaddress, rex, NULL, 8, 0); + FLD_D(v1, ed, fixedaddress + 8); + VEXTRINS_D(v1, v1, 0x10); + } + VILVH_D(v0, v1, v0); + break; case 0x6E: INST_NAME("MOVD Gx, Ed"); nextop = F8; @@ -509,6 +548,19 @@ uintptr_t dynarec64_660F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int } } break; + case 0x7F: + INST_NAME("MOVDQA Ex, Gx"); + nextop = F8; + GETGX(v0, 0); + if (MODREG) { + v1 = sse_get_reg(dyn, ninst, x1, (nextop & 7) + (rex.b << 3), 1); + VOR_V(v1, v0, v0); + } else { + addr = geted(dyn, addr, ninst, nextop, &ed, x2, x3, &fixedaddress, rex, NULL, 1, 0); + VST(v0, ed, fixedaddress); + SMWRITE2(); + } + break; case 0xBE: INST_NAME("MOVSX Gw, Eb"); nextop = F8; diff --git a/src/dynarec/la64/dynarec_la64_emit_logic.c b/src/dynarec/la64/dynarec_la64_emit_logic.c index dc6995e4..0b3e6904 100644 --- a/src/dynarec/la64/dynarec_la64_emit_logic.c +++ b/src/dynarec/la64/dynarec_la64_emit_logic.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" @@ -98,6 +99,46 @@ void emit_xor8c(dynarec_la64_t* dyn, int ninst, int s1, int32_t c, int s3, int s } } +// emit XOR16 instruction, from s1, s2, store result in s1 using s3 and s4 as scratch, s4 can be same as s2 (and so s2 destroyed) +void emit_xor16(dynarec_la64_t* dyn, int ninst, int s1, int s2, int s3, int s4, int s5) +{ + IFX (X_PEND) { + SET_DF(s4, d_xor16); + } else IFX (X_ALL) { + SET_DFNONE(); + } + + + IFXA (X_ALL, la64_lbt) { + X64_XOR_W(s1, s2); + } + + XOR(s1, s1, s2); + BSTRINS_D(s1, s1, 15, 0); + + IFX (X_PEND) { + ST_H(s1, xEmu, offsetof(x64emu_t, res)); + } + + if (la64_lbt) return; + + CLEAR_FLAGS(s3); + IFX (X_ZF | X_SF) { + IFX (X_ZF) { + BNEZ(s1, 8); + ORI(xFlags, xFlags, 1 << F_ZF); + } + IFX (X_SF) { + SRLI_D(s3, s1, 15); + BEQZ(s3, 8); + ORI(xFlags, xFlags, 1 << F_SF); + } + } + IFX (X_PF) { + emit_pf(dyn, ninst, s1, s3, s4); + } +} + // emit XOR32 instruction, from s1, s2, store result in s1 using s3 and s4 as scratch void emit_xor32(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4) { @@ -379,6 +420,43 @@ void emit_and32c(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, int64_t c, i } +// emit OR16 instruction, from s1, s2, store result in s1 using s3 and s4 as scratch, s4 can be same as s2 (and so s2 destroyed) +void emit_or16(dynarec_la64_t* dyn, int ninst, int s1, int s2, int s3, int s4) +{ + IFX (X_PEND) { + SET_DF(s3, d_or16); + } else IFX (X_ALL) { + SET_DFNONE(); + } + + IFXA (X_ALL, la64_lbt) { + X64_OR_W(s1, s2); + } + + OR(s1, s1, s2); + BSTRPICK_D(s1, s1, 15, 0); + IFX (X_PEND) { + ST_D(s1, xEmu, offsetof(x64emu_t, res)); + } + + if (la64_lbt) return; + + CLEAR_FLAGS(s3); + IFX (X_SF) { + SRLI_D(s3, s1, 15); + BEQZ(s3, 8); + ORI(xFlags, xFlags, 1 << F_SF); + } + + IFX (X_ZF) { + BNEZ(s1, 8); + ORI(xFlags, xFlags, 1 << F_ZF); + } + IFX (X_PF) { + emit_pf(dyn, ninst, s1, s3, s4); + } +} + // emit OR32 instruction, from s1, s2, store result in s1 using s3 and s4 as scratch void emit_or32(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4) { diff --git a/src/dynarec/la64/dynarec_la64_f30f.c b/src/dynarec/la64/dynarec_la64_f30f.c index b3be296f..f0433cd7 100644 --- a/src/dynarec/la64/dynarec_la64_f30f.c +++ b/src/dynarec/la64/dynarec_la64_f30f.c @@ -128,6 +128,24 @@ uintptr_t dynarec64_F30F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int } } break; + case 0x51: + INST_NAME("SQRTSS Gx, Ex"); + nextop = F8; + GETGX(v0, 1); + d1 = fpu_get_scratch(dyn); + GETEXSS(d0, 0, 0); + FSQRT_S(d1, d0); + VEXTRINS_W(v0, d1, 0); + break; + case 0x58: + INST_NAME("ADDSS Gx, Ex"); + nextop = F8; + GETGX(v0, 1); + d1 = fpu_get_scratch(dyn); + GETEXSS(d0, 0, 0); + FADD_S(d1, v0, d0); + VEXTRINS_W(v0, d1, 0); + break; case 0x59: INST_NAME("MULSS Gx, Ex"); nextop = F8; diff --git a/src/dynarec/la64/dynarec_la64_helper.h b/src/dynarec/la64/dynarec_la64_helper.h index 2ac88693..8828f8b8 100644 --- a/src/dynarec/la64/dynarec_la64_helper.h +++ b/src/dynarec/la64/dynarec_la64_helper.h @@ -746,8 +746,10 @@ void* la64_next(x64emu_t* emu, uintptr_t addr); #define emit_or32c STEPNAME(emit_or32c) #define emit_or8 STEPNAME(emit_or8) #define emit_or8c STEPNAME(emit_or8c) +#define emit_or16 STEPNAME(emit_or16) #define emit_xor8 STEPNAME(emit_xor8) #define emit_xor8c STEPNAME(emit_xor8c) +#define emit_xor16 STEPNAME(emit_xor16) #define emit_xor32 STEPNAME(emit_xor32) #define emit_xor32c STEPNAME(emit_xor32c) #define emit_and8 STEPNAME(emit_and8) @@ -826,8 +828,10 @@ void emit_or32(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3 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); void emit_or8c(dynarec_la64_t* dyn, int ninst, int s1, int32_t c, int s2, int s3, int s4); +void emit_or16(dynarec_la64_t* dyn, int ninst, int s1, int s2, int s3, int s4); void emit_xor8(dynarec_la64_t* dyn, int ninst, int s1, int s2, int s3, int s4); void emit_xor8c(dynarec_la64_t* dyn, int ninst, int s1, int32_t c, int s3, int s4); +void emit_xor16(dynarec_la64_t* dyn, int ninst, int s1, int s2, int s3, int s4, int s5); void emit_xor32c(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, int64_t c, int s3, int s4); void emit_xor32(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4); void emit_and8(dynarec_la64_t* dyn, int ninst, int s1, int s2, int s3, int s4); |