about summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
authorptitSeb <sebastien.chev@gmail.com>2023-05-07 22:00:53 +0200
committerptitSeb <sebastien.chev@gmail.com>2023-05-07 22:00:53 +0200
commit404bfdc78271bf15db14e6b5539d22026f2bc964 (patch)
treecca4b9683f041948aecdf2f79f3f70a70053eb79 /src
parentb74a1b5a3287907d123d05d7ddef1fa2dd7592e2 (diff)
downloadbox64-404bfdc78271bf15db14e6b5539d22026f2bc964.tar.gz
box64-404bfdc78271bf15db14e6b5539d22026f2bc964.zip
[ARM64_DYNAREC] Added F3 0F B8 opcode
Diffstat (limited to 'src')
-rwxr-xr-xsrc/dynarec/arm64/arm64_emitter.h5
-rwxr-xr-xsrc/dynarec/arm64/dynarec_arm64_f30f.c36
2 files changed, 41 insertions, 0 deletions
diff --git a/src/dynarec/arm64/arm64_emitter.h b/src/dynarec/arm64/arm64_emitter.h
index 2d552874..d480d2d9 100755
--- a/src/dynarec/arm64/arm64_emitter.h
+++ b/src/dynarec/arm64/arm64_emitter.h
@@ -1691,6 +1691,11 @@
 #define UADDLV_16(Rd, Rn)           EMIT(ADDLV_vector(0, 1, 0b01, Rn, Rd))
 #define UADDLV_32(Rd, Rn)           EMIT(ADDLV_vector(0, 1, 0b10, Rn, Rd))
 
+// Population Count per byte
+#define CNT_vector(Q, size, Rn, Rd)     ((Q)<<30 | 0b01110<<24 | (size)<<22 | 0b10000<<17 | 0b00101<<12 | 0b10<<10 | (Rn)<<5 | (Rd))
+#define CNT_8(Rd, Rn)               EMIT(CNT_vector(0, 0b00, Rn, Rd))
+#define CNTQ_8(Rd, Rn)              EMIT(CNT_vector(1, 0b00, Rn, Rd))
+
 // MOV Immediate
 #define MOVI_vector(Q, op, abc, cmode, defgh, Rd)   ((Q)<<30 | (op)<<29 | 0b0111100000<<19 | (abc)<<16 | (cmode)<<12 | 1<<10 | (defgh)<<5 | (Rd))
 #define MOVIQ_8(Rd, imm8)           EMIT(MOVI_vector(1, 0, (((imm8)>>5)&0b111), 0b1110, ((imm8)&0b11111), Rd))
diff --git a/src/dynarec/arm64/dynarec_arm64_f30f.c b/src/dynarec/arm64/dynarec_arm64_f30f.c
index ca5ef767..5b3aa85e 100755
--- a/src/dynarec/arm64/dynarec_arm64_f30f.c
+++ b/src/dynarec/arm64/dynarec_arm64_f30f.c
@@ -378,6 +378,42 @@ uintptr_t dynarec64_F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
             }

             break;

 

+        case 0xB8:

+            INST_NAME("POPCNT Gd, Ed");

+            SETFLAGS(X_ALL, SF_SET);

+            SET_DFNONE(x1);

+            nextop = F8;

+            v1 = fpu_get_scratch(dyn);

+            GETGD;

+            if(MODREG) {

+                GETED(0);

+                if(rex.w)

+                    VMOVQDfrom(v1, 0, ed);

+                else {

+                    MOVxw_REG(x1, ed);  // need to clear uper part

+                    VMOVQDfrom(v1, 0, x1);

+                }

+            } else {

+                if(rex.w) {

+                    SMREAD();

+                    addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, &unscaled, 0xfff<<3, 7, rex, NULL, 0, 0);

+                    VLD64(v1, ed, fixedaddress);

+                } else {

+                    GETED(0);   // just load and clear the upper part

+                    VMOVQDfrom(v1, 0, ed);

+                }

+            }

+            CNT_8(v1, v1);

+            UADDLV_8(v1, v1);

+            VMOVQDto(gd, v1, 0);

+            IFX(X_ALL) {

+                MOV32w(x1, (1<<F_OF) | (1<<F_SF) | (1<<F_ZF) | (1<<F_AF) | (1<<F_CF) | (1<<F_PF));

+                BICw(xFlags, xFlags, x1);

+                CBNZx(gd, 4+4);

+                BFIw(xFlags, xFlags, F_ZF, 1);

+            }

+            break;

+

         case 0xBC:

             INST_NAME("TZCNT Gd, Ed");

             SETFLAGS(X_CF|X_ZF, SF_SUBSET);