diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/dynarec/la64/dynarec_la64_64.c | 146 | ||||
| -rw-r--r-- | src/dynarec/la64/dynarec_la64_660f.c | 21 | ||||
| -rw-r--r-- | src/dynarec/la64/dynarec_la64_f20f.c | 8 | ||||
| -rw-r--r-- | src/dynarec/la64/dynarec_la64_helper.c | 4 | ||||
| -rw-r--r-- | src/dynarec/la64/dynarec_la64_helper.h | 13 | ||||
| -rw-r--r-- | src/dynarec/la64/la64_emitter.h | 8 |
6 files changed, 197 insertions, 3 deletions
diff --git a/src/dynarec/la64/dynarec_la64_64.c b/src/dynarec/la64/dynarec_la64_64.c index 46f0ef06..152db7b3 100644 --- a/src/dynarec/la64/dynarec_la64_64.c +++ b/src/dynarec/la64/dynarec_la64_64.c @@ -79,6 +79,152 @@ uintptr_t dynarec64_64(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni GETEDO(x4, 0); emit_xor32(dyn, ninst, rex, gd, ed, x3, x4); break; + case 0x81: + case 0x83: + nextop = F8; + grab_segdata(dyn, addr, ninst, x6, seg); + switch ((nextop >> 3) & 7) { + case 0: + if (opcode == 0x81) { + INST_NAME("ADD Ed, Id"); + } else { + INST_NAME("ADD Ed, Ib"); + } + SETFLAGS(X_ALL, SF_SET_PENDING); + GETEDO(x6, (opcode == 0x81) ? 4 : 1); + if (opcode == 0x81) + i64 = F32S; + else + i64 = F8S; + emit_add32c(dyn, ninst, rex, ed, i64, x3, x4, x5, xMASK); + IFXA (X_CF, !la64_lbt) + REGENERATE_MASK(); // use xMASK as a scratch + WBACKO(x6); + break; + case 1: + if (opcode == 0x81) { + INST_NAME("OR Ed, Id"); + } else { + INST_NAME("OR Ed, Ib"); + } + SETFLAGS(X_ALL, SF_SET_PENDING); + GETEDO(x6, (opcode == 0x81) ? 4 : 1); + if (opcode == 0x81) + i64 = F32S; + else + i64 = F8S; + emit_or32c(dyn, ninst, rex, ed, i64, x3, x4); + WBACKO(x6); + break; + case 2: + if (opcode == 0x81) { + INST_NAME("ADC Ed, Id"); + } else { + INST_NAME("ADC Ed, Ib"); + } + READFLAGS(X_CF); + SETFLAGS(X_ALL, SF_SET_PENDING); + GETEDO(x6, (opcode == 0x81) ? 4 : 1); + if (opcode == 0x81) + i64 = F32S; + else + i64 = F8S; + MOV64xw(x5, i64); + IFXA (X_ALL, !la64_lbt) + ST_D(x6, xEmu, offsetof(x64emu_t, scratch)); + emit_adc32(dyn, ninst, rex, ed, x5, x3, x4, x6, xMASK); + IFXA (X_ALL, !la64_lbt) { + LD_D(x6, xEmu, offsetof(x64emu_t, scratch)); + REGENERATE_MASK(); // use xMASK as a scratch + } + WBACKO(x6); + break; + case 3: + if (opcode == 0x81) { + INST_NAME("SBB Ed, Id"); + } else { + INST_NAME("SBB Ed, Ib"); + } + READFLAGS(X_CF); + SETFLAGS(X_ALL, SF_SET_PENDING); + GETEDO(x6, (opcode == 0x81) ? 4 : 1); + if (opcode == 0x81) + i64 = F32S; + else + i64 = F8S; + MOV64xw(x5, i64); + emit_sbb32(dyn, ninst, rex, ed, x5, x3, x4, xMASK); + IFXA (X_CF, !la64_lbt) + REGENERATE_MASK(); // use xMASK as a scratch + WBACKO(x6); + break; + case 4: + if (opcode == 0x81) { + INST_NAME("AND Ed, Id"); + } else { + INST_NAME("AND Ed, Ib"); + } + SETFLAGS(X_ALL, SF_SET_PENDING); + GETEDO(x6, (opcode == 0x81) ? 4 : 1); + if (opcode == 0x81) + i64 = F32S; + else + i64 = F8S; + emit_and32c(dyn, ninst, rex, ed, i64, x3, x4); + WBACKO(x6); + break; + case 5: + if (opcode == 0x81) { + INST_NAME("SUB Ed, Id"); + } else { + INST_NAME("SUB Ed, Ib"); + } + SETFLAGS(X_ALL, SF_SET_PENDING); + GETEDO(x6, (opcode == 0x81) ? 4 : 1); + if (opcode == 0x81) + i64 = F32S; + else + i64 = F8S; + emit_sub32c(dyn, ninst, rex, ed, i64, x3, x4, x5, xMASK); + IFXA (X_CF, !la64_lbt) + REGENERATE_MASK(); // use xMASK as a scratch + WBACKO(x6); + break; + case 6: + if (opcode == 0x81) { + INST_NAME("XOR Ed, Id"); + } else { + INST_NAME("XOR Ed, Ib"); + } + SETFLAGS(X_ALL, SF_SET_PENDING); + GETEDO(x6, (opcode == 0x81) ? 4 : 1); + if (opcode == 0x81) + i64 = F32S; + else + i64 = F8S; + emit_xor32c(dyn, ninst, rex, ed, i64, x3, x4); + WBACKO(x6); + break; + case 7: + if (opcode == 0x81) { + INST_NAME("CMP Ed, Id"); + } else { + INST_NAME("CMP Ed, Ib"); + } + SETFLAGS(X_ALL, SF_SET_PENDING); + GETEDO(x6, (opcode == 0x81) ? 4 : 1); + if (opcode == 0x81) + i64 = F32S; + else + i64 = F8S; + if (i64) { + MOV64xw(x2, i64); + emit_cmp32(dyn, ninst, rex, ed, x2, x3, x4, x5, x6); + } else + emit_cmp32_0(dyn, ninst, rex, ed, x3, x4); + break; + } + break; case 0x89: INST_NAME("MOV Seg:Ed, Gd"); grab_segdata(dyn, addr, ninst, x4, seg); diff --git a/src/dynarec/la64/dynarec_la64_660f.c b/src/dynarec/la64/dynarec_la64_660f.c index 6f2b2490..08fbde4e 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 0x11: + INST_NAME("MOVUPD Ex,Gx"); + nextop = F8; + GETG; + v0 = sse_get_reg(dyn, ninst, x1, gd, 0); + if (MODREG) { + v1 = sse_get_reg_empty(dyn, ninst, x1, (nextop & 7) + (rex.b << 3)); + 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 0x12: INST_NAME("MOVLPD Gx, Eq"); nextop = F8; @@ -915,6 +929,13 @@ uintptr_t dynarec64_660F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int VXOR_V(q0, q0, q1); } break; + case 0xF4: + INST_NAME("PMULUDQ Gx,Ex"); + nextop = F8; + GETGX(v0, 1); + GETEX(v1, 0, 0); + VMULWEV_D_WU(v0, v0, v1); + break; case 0xF8: INST_NAME("PSUBB Gx,Ex"); nextop = F8; diff --git a/src/dynarec/la64/dynarec_la64_f20f.c b/src/dynarec/la64/dynarec_la64_f20f.c index 6d0a5107..7c14361d 100644 --- a/src/dynarec/la64/dynarec_la64_f20f.c +++ b/src/dynarec/la64/dynarec_la64_f20f.c @@ -257,6 +257,14 @@ uintptr_t dynarec64_F20F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int VEXTRINS_D(v0, v1, 0); MARK2; break; + case 0x70: + INST_NAME("PSHUFLW Gx, Ex, Ib"); + nextop = F8; + GETEX(v1, 0, 1); + GETGX(v0, 1); + u8 = F8; + VSHUF4I_H(v0, v1, u8); + break; case 0xC2: INST_NAME("CMPSD Gx, Ex, Ib"); nextop = F8; diff --git a/src/dynarec/la64/dynarec_la64_helper.c b/src/dynarec/la64/dynarec_la64_helper.c index f6b6a72e..5c0b3879 100644 --- a/src/dynarec/la64/dynarec_la64_helper.c +++ b/src/dynarec/la64/dynarec_la64_helper.c @@ -685,9 +685,7 @@ void call_c(dynarec_la64_t* dyn, int ninst, void* fnc, int reg, int ret, int sav LD_D(xRIP, xEmu, offsetof(x64emu_t, ip)); #undef GO } - // regenerate mask - ADDI_W(xMASK, xZR, -1); - LU32I_D(xMASK, 0); + REGENERATE_MASK(); fpu_popcache(dyn, ninst, reg, 0); if (saveflags) { diff --git a/src/dynarec/la64/dynarec_la64_helper.h b/src/dynarec/la64/dynarec_la64_helper.h index def57335..060917ce 100644 --- a/src/dynarec/la64/dynarec_la64_helper.h +++ b/src/dynarec/la64/dynarec_la64_helper.h @@ -202,6 +202,13 @@ ST_W(ed, wback, fixedaddress); \ SMWRITE(); \ } + +#define WBACKO(O) \ + if (wback) { \ + SDXxw(ed, wback, O); \ + SMWRITE2(); \ + } + // GETSEW will use i for ed, and can use r3 for wback. This is the Signed version #define GETSEW(i, D) \ if (MODREG) { \ @@ -1106,6 +1113,12 @@ uintptr_t dynarec64_F20F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int } \ } while (0) +#define REGENERATE_MASK() \ + do { \ + ADDI_W(xMASK, xZR, -1); \ + LU32I_D(xMASK, 0); \ + } while (0) + #define PURGE_YMM() /* TODO */ #endif //__DYNAREC_LA64_HELPER_H__ \ No newline at end of file diff --git a/src/dynarec/la64/la64_emitter.h b/src/dynarec/la64/la64_emitter.h index e9756faf..c912f666 100644 --- a/src/dynarec/la64/la64_emitter.h +++ b/src/dynarec/la64/la64_emitter.h @@ -2059,6 +2059,14 @@ LSX instruction starts with V, LASX instruction starts with XV. ST_W(rd, rj, imm12); \ } while (0) +#define SDXxw(rd, rj, rk) \ + do { \ + if (rex.w) \ + STX_D(rd, rj, rk); \ + else \ + STX_W(rd, rj, rk); \ + } while (0) + #define SDz(rd, rj, imm12) \ do { \ if (rex.is32bits) \ |