about summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
authorptitSeb <sebastien.chev@gmail.com>2021-03-25 15:06:48 +0100
committerptitSeb <sebastien.chev@gmail.com>2021-03-25 15:06:48 +0100
commit3c07dd58eb9974e6c2fb70cb1f51b5116451a9d7 (patch)
tree553edf79c66a1b62577be19c372d65bd051ee699 /src
parentfcdd8fc383cace94ce970bd8af2385ab77d24def (diff)
downloadbox64-3c07dd58eb9974e6c2fb70cb1f51b5116451a9d7.tar.gz
box64-3c07dd58eb9974e6c2fb70cb1f51b5116451a9d7.zip
Added F3 0F BC opcode ([DYNAREC] too)
Diffstat (limited to 'src')
-rwxr-xr-xsrc/dynarec/dynarec_arm64_f30f.c18
-rwxr-xr-xsrc/dynarec/dynarec_arm64_helper.h4
-rw-r--r--src/emu/x64runf30f.c38
3 files changed, 60 insertions, 0 deletions
diff --git a/src/dynarec/dynarec_arm64_f30f.c b/src/dynarec/dynarec_arm64_f30f.c
index 3caf0f64..c4b698b6 100755
--- a/src/dynarec/dynarec_arm64_f30f.c
+++ b/src/dynarec/dynarec_arm64_f30f.c
@@ -50,6 +50,7 @@ uintptr_t dynarec64_F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
     int q0, q1;

     int d0, d1;

     int fixedaddress;

+    int j32;

 

     MAYUSE(d0);

     MAYUSE(d1);

@@ -57,6 +58,7 @@ uintptr_t dynarec64_F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
     MAYUSE(q1);

     MAYUSE(v0);

     MAYUSE(v1);

+    MAYUSE(j32);

 

     switch(opcode) {

 

@@ -257,6 +259,22 @@ uintptr_t dynarec64_F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
             }

             break;

 

+        case 0xBC:

+            INST_NAME("TZCNT Gd, Ed");

+            SETFLAGS(X_CF|X_ZF, SF_SET);

+            nextop = F8;

+            GETED(0);

+            GETGD;

+            SET_DFNONE(x1);

+            TSTxw_REG(ed, ed);

+            BFIw(xFlags, x1, F_CF, 1);  // CF = is source 0?

+            RBITxw(x1, ed);   // reverse

+            CLZxw(gd, x1);    // x2 gets leading 0 == TZCNT

+            TSTxw_REG(gd, gd);

+            CSETw(x1, cEQ);

+            BFIw(xFlags, x1, F_ZF, 1);  // ZF = is dest 0?

+            break;

+

         case 0xC2:

             INST_NAME("CMPSS Gx, Ex, Ib");

             nextop = F8;

diff --git a/src/dynarec/dynarec_arm64_helper.h b/src/dynarec/dynarec_arm64_helper.h
index a06d54ea..2b588fef 100755
--- a/src/dynarec/dynarec_arm64_helper.h
+++ b/src/dynarec/dynarec_arm64_helper.h
@@ -264,6 +264,10 @@
 #define B_MARK_nocond               \
     j32 = GETMARK-(dyn->arm_size);  \
     B(j32)
+// Branch to MARK if reg is 0 (use j32)
+#define CBZxw_MARK(reg)             \
+    j32 = GETMARK-(dyn->arm_size);  \
+    CBZxw(reg, j32)
 // Branch to MARK if reg is not 0 (use j32)
 #define CBNZx_MARK(reg)             \
     j32 = GETMARK-(dyn->arm_size);  \
diff --git a/src/emu/x64runf30f.c b/src/emu/x64runf30f.c
index f18aa951..aa3c9d76 100644
--- a/src/emu/x64runf30f.c
+++ b/src/emu/x64runf30f.c
@@ -28,6 +28,8 @@ int RunF30F(x64emu_t *emu, rex_t rex)
     uint8_t nextop;

     int8_t tmp8s;

     uint8_t tmp8u;

+    uint32_t tmp32u;

+    uint64_t tmp64u;

     reg64_t *oped, *opgd;

     sse_regs_t *opex, *opgx, eax1;

     mmx87_regs_t *opem;

@@ -236,6 +238,42 @@ int RunF30F(x64emu_t *emu, rex_t rex)
         memcpy(EX, GX, 16);    // unaligned...

         break;

 

+    case 0xBC:  /* TZCNT Ed,Gd */

+        CHECK_FLAGS(emu);

+        nextop = F8;

+        GETED(0);

+        GETGD;

+        if(rex.w) {

+            tmp64u = ED->q[0];

+            if(tmp64u) {

+                CLEAR_FLAG(F_ZF);

+                tmp8u = 0;

+                while(!(tmp64u&(1LL<<tmp8u))) ++tmp8u;

+                GD->q[0] = tmp8u;

+                CONDITIONAL_SET_FLAG(tmp8u==0, F_ZF);

+                CLEAR_FLAG(F_CF);

+            } else {

+                CLEAR_FLAG(F_ZF);

+                SET_FLAG(F_CF);

+                GD->q[0] = 64;

+            }

+        } else {

+            tmp32u = ED->dword[0];

+            if(tmp32u) {

+                CLEAR_FLAG(F_ZF);

+                tmp8u = 0;

+                while(!(tmp32u&(1<<tmp8u))) ++tmp8u;

+                GD->dword[0] = tmp8u;

+                CONDITIONAL_SET_FLAG(tmp8u==0, F_ZF);

+                CLEAR_FLAG(F_CF);

+            } else {

+                CLEAR_FLAG(F_ZF);

+                SET_FLAG(F_CF);

+                GD->dword[0] = 32;

+            }

+        }

+        break;

+

     case 0xC2:  /* CMPSS Gx, Ex, Ib */

         nextop = F8;

         GETEX(1);