From 8a982e8b5e9cbf12ee6e30b83f0014ceb8cd22ea Mon Sep 17 00:00:00 2001 From: Yang Liu Date: Wed, 18 Dec 2024 16:15:21 +0800 Subject: [LA64_DYNAREC] Added POPCNT opcode and fixed an issue too (#2164) --- src/dynarec/la64/dynarec_la64_f0.c | 4 +--- src/dynarec/la64/dynarec_la64_f30f.c | 40 ++++++++++++++++++++++++++++++++++++ src/dynarec/la64/la64_emitter.h | 14 +++++++++++++ 3 files changed, 55 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/dynarec/la64/dynarec_la64_f0.c b/src/dynarec/la64/dynarec_la64_f0.c index be32d783..0178ca00 100644 --- a/src/dynarec/la64/dynarec_la64_f0.c +++ b/src/dynarec/la64/dynarec_la64_f0.c @@ -162,9 +162,7 @@ uintptr_t dynarec64_F0(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni // done MARK; UFLAG_IF { emit_cmp8(dyn, ninst, x6, x4, x1, x2, x3, x5); } - // load m8 into AL - ANDI(xRAX, xRAX, ~0xff); - OR(xRAX, xRAX, x4); + BSTRINS_D(xRAX, x4, 7, 0); } SMDMB(); break; diff --git a/src/dynarec/la64/dynarec_la64_f30f.c b/src/dynarec/la64/dynarec_la64_f30f.c index 280821d8..1fff4be3 100644 --- a/src/dynarec/la64/dynarec_la64_f30f.c +++ b/src/dynarec/la64/dynarec_la64_f30f.c @@ -331,6 +331,46 @@ uintptr_t dynarec64_F30F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int SMWRITE2(); } break; + case 0xB8: + INST_NAME("POPCNT Gd, Ed"); + SETFLAGS(X_ALL, SF_SET); + SET_DFNONE(); + nextop = F8; + v1 = fpu_get_scratch(dyn); + GETGD; + if (MODREG) { + GETED(0); + if (rex.w) { + VINSGR2VR_D(v1, ed, 0); + } else { + VINSGR2VR_W(v1, ed, 0); + } + } else { + SMREAD(); + addr = geted(dyn, addr, ninst, nextop, &ed, x1, x2, &fixedaddress, rex, NULL, 1, 0); + FLDxw(v1, ed, fixedaddress); + } + if (rex.w) { + VPCNT_D(v1, v1); + MOVFR2GR_D(gd, v1); + } else { + VPCNT_W(v1, v1); + VPICKVE2GR_WU(gd, v1, 0); + } + IFX (X_ALL) { + if (la64_lbt) { + X64_SET_EFLAGS(xZR, X_ALL); + BNEZ_MARK(gd); + ADDI_D(x3, xZR, 1 << F_ZF); + X64_SET_EFLAGS(x3, X_ZF); + } else { + CLEAR_FLAGS(x2); + BNEZ_MARK(gd); + ORI(xFlags, xFlags, 1 << F_ZF); + } + MARK; + } + break; case 0xBC: INST_NAME("TZCNT Gd, Ed"); SETFLAGS(X_ZF, SF_SUBSET); diff --git a/src/dynarec/la64/la64_emitter.h b/src/dynarec/la64/la64_emitter.h index 3cb2e4c5..d199a393 100644 --- a/src/dynarec/la64/la64_emitter.h +++ b/src/dynarec/la64/la64_emitter.h @@ -1825,6 +1825,20 @@ LSX instruction starts with V, LASX instruction starts with XV. #define XVSRLNI_H_W(vd, vj, imm5) EMIT(type_2RI5(0b01110111010000001, imm5, vj, vd)) #define XVSRLI_W(vd, vj, imm5) EMIT(type_2RI5(0b01110111001100001, imm5, vj, vd)) #define VSETEQZ_V(cd, vj) EMIT(type_2R(0b0111001010011100100110, vj, cd & 0b111)) +#define VINSGR2VR_D(vd, rj, imm1) EMIT(type_2RI1(0b011100101110101111110, imm1, rj, vd)) +#define VINSGR2VR_W(vd, rj, imm2) EMIT(type_2RI2(0b01110010111010111110, imm2, rj, vd)) +#define VPCNT_B(vd, vj) EMIT(type_2R(0b0111001010011100001000, vj, vd)) +#define VPCNT_H(vd, vj) EMIT(type_2R(0b0111001010011100001001, vj, vd)) +#define VPCNT_W(vd, vj) EMIT(type_2R(0b0111001010011100001010, vj, vd)) +#define VPCNT_D(vd, vj) EMIT(type_2R(0b0111001010011100001011, vj, vd)) +#define VPICKVE2GR_B(rd, vj, imm4) EMIT(type_2RI4(0b011100101110111110, imm4, vj, rd)) +#define VPICKVE2GR_H(rd, vj, imm3) EMIT(type_2RI3(0b0111001011101111110, imm3, vj, rd)) +#define VPICKVE2GR_W(rd, vj, imm2) EMIT(type_2RI1(0b01110010111011111110, imm2, vj, rd)) +#define VPICKVE2GR_D(rd, vj, imm1) EMIT(type_2RI1(0b011100101110111111110, imm1, vj, rd)) +#define VPICKVE2GR_BU(rd, vj, imm4) EMIT(type_2RI4(0b011100101110001110, imm4, vj, rd)) +#define VPICKVE2GR_HU(rd, vj, imm3) EMIT(type_2RI3(0b0111001011100011110, imm3, vj, rd)) +#define VPICKVE2GR_WU(rd, vj, imm2) EMIT(type_2RI1(0b01110010111000111110, imm2, vj, rd)) +#define VPICKVE2GR_DU(rd, vj, imm1) EMIT(type_2RI1(0b011100101110001111110, imm1, vj, rd)) //////////////////////////////////////////////////////////////////////////////// // (undocumented) LBT extension instructions -- cgit 1.4.1