about summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/dynarec/la64/dynarec_la64_f0.c4
-rw-r--r--src/dynarec/la64/dynarec_la64_f30f.c40
-rw-r--r--src/dynarec/la64/la64_emitter.h14
3 files changed, 55 insertions, 3 deletions
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