about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorptitSeb <sebastien.chev@gmail.com>2021-03-20 21:54:51 +0100
committerptitSeb <sebastien.chev@gmail.com>2021-03-20 21:54:51 +0100
commit89a3c359a632995db02b7481c029a1e98e997003 (patch)
tree737d7a7fe3a80c3861823cd2e9a470a0fde24a80
parent848390d9eb960175f4063cfe45a5fc2061116771 (diff)
downloadbox64-89a3c359a632995db02b7481c029a1e98e997003.tar.gz
box64-89a3c359a632995db02b7481c029a1e98e997003.zip
[DYNAREC] Added (66) 0F BC/BD opcodes
-rwxr-xr-xsrc/dynarec/arm64_emitter.h14
-rwxr-xr-xsrc/dynarec/arm64_printer.c11
-rwxr-xr-xsrc/dynarec/dynarec_arm64_0f.c31
-rwxr-xr-xsrc/dynarec/dynarec_arm64_660f.c35
4 files changed, 90 insertions, 1 deletions
diff --git a/src/dynarec/arm64_emitter.h b/src/dynarec/arm64_emitter.h
index 50455be3..08117512 100755
--- a/src/dynarec/arm64_emitter.h
+++ b/src/dynarec/arm64_emitter.h
@@ -488,6 +488,20 @@
 #define MULw(Rd, Rn, Rm)                MADDw(Rd, Rn, Rm, xZR)
 #define MULxw(Rd, Rn, Rm)               MADDxw(Rd, Rn, Rm, xZR)
 
+// CLZ
+#define CL_gen(sf, op, Rn, Rd)          ((sf)<<31 | 1<<30 | 0b11010110<<21 | 0b00010<<11 | (op)<<10 | (Rn)<<5 | (Rd))
+#define CLZx(Rd, Rn)                    EMIT(CL_gen(1, 0, Rn, Rd))
+#define CLZw(Rd, Rn)                    EMIT(CL_gen(0, 0, Rn, Rd))
+#define CLZxw(Rd, Rn)                   EMIT(CL_gen(rex.w, 0, Rn, Rd))
+#define CLSx(Rd, Rn)                    EMIT(CL_gen(1, 1, Rn, Rd))
+#define CLSw(Rd, Rn)                    EMIT(CL_gen(0, 1, Rn, Rd))
+#define CLSxw(Rd, Rn)                   EMIT(CL_gen(rex.w, 1, Rn, Rd))
+
+// RBIT
+#define RBIT_gen(sf, Rn, Rd)            ((sf)<<31 | 1<<30 | 0b11010110<<21 | (Rn)<<5 | (Rd))
+#define RBITx(Rd, Rn)                   EMIT(RBIT_gen(1, Rn, Rd))
+#define RBITw(Rd, Rn)                   EMIT(RBIT_gen(0, Rn, Rd))
+#define RBITxw(Rd, Rn)                  EMIT(RBIT_gen(rex.w, Rn, Rd))
 
 // MRS
 #define MRS_gen(L, o0, op1, CRn, CRm, op2, Rt)  (0b1101010100<<22 | (L)<<21 | 1<<20 | (o0)<<19 | (op1)<<16 | (CRn)<<12 | (CRm)<<8 | (op2)<<5 | (Rt))
diff --git a/src/dynarec/arm64_printer.c b/src/dynarec/arm64_printer.c
index 53d72975..00fd4476 100755
--- a/src/dynarec/arm64_printer.c
+++ b/src/dynarec/arm64_printer.c
@@ -641,6 +641,17 @@ const char* arm64_print(uint32_t opcode, uintptr_t addr)
         return buff;

     }

 

+    // MISC Bits

+    if(isMask(opcode, "f10110101100000000010onnnnnddddd", &a)) {

+        snprintf(buff, sizeof(buff), "CL%c %s, %s", option?'S':'Z', sf?Xt[Rd]:Wt[Rd], sf?Xt[Rn]:Wt[Rn]);

+        return buff;

+    }

+    if(isMask(opcode, "f101101011000000000000nnnnnddddd", &a)) {

+        snprintf(buff, sizeof(buff), "RBIT %s, %s", sf?Xt[Rd]:Wt[Rd], sf?Xt[Rn]:Wt[Rn]);

+        return buff;

+    }

+

+

     // MULL ADD

     if(isMask(opcode, "10011011U01mmmmm0aaaaannnnnddddd", &a)) {

         if(Ra==31)

diff --git a/src/dynarec/dynarec_arm64_0f.c b/src/dynarec/dynarec_arm64_0f.c
index 8e00682e..4694db51 100755
--- a/src/dynarec/dynarec_arm64_0f.c
+++ b/src/dynarec/dynarec_arm64_0f.c
@@ -310,6 +310,37 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
                 STRxw_U12(ed, wback, fixedaddress);

             }

             break;

+        case 0xBC:

+            INST_NAME("BSF Gd, Ed");

+            SETFLAGS(X_ZF, SF_SET);

+            nextop = F8;

+            GETED(0);

+            GETGD;

+            TSTxw_REG(ed, ed);

+            B_MARK(cEQ);

+            RBITxw(x1, ed);   // reverse

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

+            MARK;

+            CSETw(x1, cEQ);    //ZF not set

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

+            SET_DFNONE(x1);

+            break;

+        case 0xBD:

+            INST_NAME("BSR Gd, Ed");

+            SETFLAGS(X_ZF, SF_SET);

+            nextop = F8;

+            GETED(0);

+            GETGD;

+            TSTxw_REG(ed, ed);

+            B_MARK(cEQ);

+            CLZxw(gd, ed);    // x2 gets leading 0

+            SUBxw_U12(gd, gd, rex.w?63:31);

+            NEGxw_REG(gd, gd);   // complement

+            MARK;

+            CSETw(x1, cEQ);    //ZF not set

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

+            SET_DFNONE(x1);

+            break;

 

         default:

             DEFAULT;

diff --git a/src/dynarec/dynarec_arm64_660f.c b/src/dynarec/dynarec_arm64_660f.c
index 475bcab1..b768af74 100755
--- a/src/dynarec/dynarec_arm64_660f.c
+++ b/src/dynarec/dynarec_arm64_660f.c
@@ -166,7 +166,40 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
             EORxw_REG(ed, ed, x1);

             EWBACK;

             break;

-

+        case 0xBC:

+            INST_NAME("BSF Ew,Gw");

+            SETFLAGS(X_ZF, SF_SET);

+            nextop = F8;

+            GETGD;

+            GETEW(x1, 0);  // Get EW

+            TSTw_REG(x1, x1);

+            B_MARK(cEQ);

+            RBITw(x1, x1);   // reverse

+            CLZw(x2, x1);    // x2 gets leading 0 == BSF

+            BFIw(gd, x2, 0, 16);

+            MARK;

+            CSETw(x1, cEQ);    //ZF not set

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

+            SET_DFNONE(x1);

+            break;

+        case 0xBD:

+            INST_NAME("BSR Ew,Gw");

+            SETFLAGS(X_ZF, SF_SET);

+            nextop = F8;

+            GETGD;

+            GETEW(x1, 0);  // Get EW

+            TSTw_REG(x1, x1);

+            B_MARK(cEQ);

+            LSLw(x1, x1, 16);   // put bits on top

+            CLZw(x2, x1);       // x2 gets leading 0

+            SUBw_U12(x2, x2, 15);

+            NEGw_REG(x2, x2);   // complement

+            BFIx(gd, x2, 0, 16);

+            MARK;

+            CSETw(x1, cEQ);    //ZF not set

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

+            SET_DFNONE(x1);

+            break;

         default:

             DEFAULT;

     }