From a7ded59393ad97959b572f4c97bae6f91d318b1e Mon Sep 17 00:00:00 2001 From: Yang Liu Date: Thu, 26 Dec 2024 17:14:54 +0800 Subject: [PATCH] [LA64_DYNAREC] Added more opcodes (#2214) --- src/dynarec/la64/dynarec_la64_66.c | 66 ++++++++++++++++++++++++++++ src/dynarec/la64/dynarec_la64_660f.c | 34 ++++++++++++++ 2 files changed, 100 insertions(+) diff --git a/src/dynarec/la64/dynarec_la64_66.c b/src/dynarec/la64/dynarec_la64_66.c index 2cedcf4e4..27999e66d 100644 --- a/src/dynarec/la64/dynarec_la64_66.c +++ b/src/dynarec/la64/dynarec_la64_66.c @@ -625,6 +625,65 @@ uintptr_t dynarec64_66(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni ADD_D(xRDI, xRDI, x3); } break; + case 0xAF: + switch (rep) { + case 1: + case 2: + if (rep == 1) { + INST_NAME("REPNZ SCASW"); + } else { + INST_NAME("REPZ SCASW"); + } + MAYSETFLAGS(); + SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION); + CBZ_NEXT(xRCX); + GETDIR(x3, x1, rex.w ? 8 : 2); + if (rex.w) { + MARK; + LD_D(x2, xRDI, 0); + ADD_D(xRDI, xRDI, x3); + ADDI_D(xRCX, xRCX, -1); + if (rep == 1) { + BEQ_MARK3(xRAX, x2); + } else { + BNE_MARK3(xRAX, x2); + } + BNE_MARK(xRCX, xZR); + MARK3; + emit_cmp32(dyn, ninst, rex, xRAX, x2, x3, x4, x5, x6); + } else { + BSTRPICK_D(x1, xRAX, 15, 0); + MARK; + LD_HU(x2, xRDI, 0); + ADD_D(xRDI, xRDI, x3); + ADDI_D(xRCX, xRCX, -1); + if (rep == 1) { + BEQ_MARK3(x1, x2); + } else { + BNE_MARK3(x1, x2); + } + BNE_MARK(xRCX, xZR); + MARK3; + emit_cmp16(dyn, ninst, x1, x2, x3, x4, x5, x6); + } + break; + default: + INST_NAME("SCASW"); + SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION); + GETDIR(x3, x1, rex.w ? 8 : 2); + if (rex.w) { + LD_D(x2, xRDI, 0); + ADD_D(xRDI, xRDI, x3); + emit_cmp32(dyn, ninst, rex, xRAX, x2, x3, x4, x5, x6); + } else { + BSTRPICK_D(x1, xRAX, 15, 0); + LD_HU(x2, xRDI, 0); + ADD_D(xRDI, xRDI, x3); + emit_cmp16(dyn, ninst, x1, x2, x3, x4, x5, x6); + } + break; + } + break; case 0xB8: case 0xB9: case 0xBA: @@ -790,6 +849,13 @@ uintptr_t dynarec64_66(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni MOV32w(x2, u16); emit_test16(dyn, ninst, x1, x2, x3, x4, x5); break; + case 2: + INST_NAME("NOT Ew"); + GETEW(x1, 0); + MOV32w(x5, 0xffff); + XOR(ed, ed, x5); // No flags affected + EWBACK; + break; case 3: INST_NAME("NEG Ew"); SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION); diff --git a/src/dynarec/la64/dynarec_la64_660f.c b/src/dynarec/la64/dynarec_la64_660f.c index d2024ba3e..da3bb5407 100644 --- a/src/dynarec/la64/dynarec_la64_660f.c +++ b/src/dynarec/la64/dynarec_la64_660f.c @@ -22,6 +22,7 @@ #include "dynarec_la64_private.h" #include "dynarec_la64_functions.h" #include "../dynarec_helper.h" +#include "emu/x64compstrings.h" uintptr_t dynarec64_660F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int* ok, int* need_epilog) { @@ -728,6 +729,39 @@ uintptr_t dynarec64_660F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int MOV32w(x4, u8); CALL(native_pclmul, -1); break; + case 0x63: + INST_NAME("PCMPISTRI Gx, Ex, Ib"); + SETFLAGS(X_ALL, SF_SET_DF, NAT_FLAGS_NOFUSION); + nextop = F8; + GETG; + if (gd > 7) sse_reflect_reg(dyn, ninst, gd); + ADDI_D(x2, xEmu, offsetof(x64emu_t, xmm[gd])); + if (MODREG) { + ed = (nextop & 7) + (rex.b << 3); + if (ed > 7) sse_reflect_reg(dyn, ninst, ed); + ADDI_D(x1, xEmu, offsetof(x64emu_t, xmm[ed])); + } else { + addr = geted(dyn, addr, ninst, nextop, &ed, x1, x2, &fixedaddress, rex, NULL, 0, 1); + if (ed != x1) MV(x1, ed); + } + u8 = F8; + MOV32w(x3, u8); + CALL(sse42_compare_string_implicit_len, x1); + BNEZ_MARK(x1); + MOV32w(xRCX, (u8 & 1) ? 8 : 16); + B_NEXT_nocond; + MARK; + if (u8 & 0b1000000) { + CLZ_W(xRCX, x1); + ADDI_D(x2, xZR, 31); + SUB_D(xRCX, x2, xRCX); + } else { + if (rex.w) + CTZ_D(xRCX, x1); + else + CTZ_W(xRCX, x1); + } + break; case 0xDF: INST_NAME("AESKEYGENASSIST Gx, Ex, Ib"); // AES-NI nextop = F8;