about summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
authorptitSeb <sebastien.chev@gmail.com>2021-03-24 16:49:27 +0100
committerptitSeb <sebastien.chev@gmail.com>2021-03-24 16:49:27 +0100
commit12ee624358632c25c6f891c5d4e7c9cf886d0798 (patch)
tree4bc25cb24bb7578985411e91ea5454b0c55a7d73 /src
parent571de7f07f026aa955f7ffb926124e87c737aba1 (diff)
downloadbox64-12ee624358632c25c6f891c5d4e7c9cf886d0798.tar.gz
box64-12ee624358632c25c6f891c5d4e7c9cf886d0798.zip
[DYNAREC] Added 0F BA opcode
Diffstat (limited to 'src')
-rwxr-xr-xsrc/dynarec/dynarec_arm64_0f.c105
-rwxr-xr-xsrc/dynarec/dynarec_arm64_helper.h8
2 files changed, 110 insertions, 3 deletions
diff --git a/src/dynarec/dynarec_arm64_0f.c b/src/dynarec/dynarec_arm64_0f.c
index 25ffec7e..3ebf3cd7 100755
--- a/src/dynarec/dynarec_arm64_0f.c
+++ b/src/dynarec/dynarec_arm64_0f.c
@@ -476,7 +476,7 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
                     case 0:

                         INST_NAME("FXSAVE Ed");

                         fpu_purgecache(dyn, ninst, x1, x2, x3);

-                        if((nextop&0xC0)==0xC0) {

+                        if(MODREG) {

                             DEFAULT;

                         } else {

                             addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, rex, 0, 0);

@@ -487,7 +487,7 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
                     case 1:

                         INST_NAME("FXRSTOR Ed");

                         fpu_purgecache(dyn, ninst, x1, x2, x3);

-                        if((nextop&0xC0)==0xC0) {

+                        if(MODREG) {

                             DEFAULT;

                         } else {

                             addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, rex, 0, 0);

@@ -502,7 +502,7 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
                         break;

                     case 3:

                         INST_NAME("STMXCSR Md");

-                        if((nextop&0xC0)==0xC0) {

+                        if(MODREG) {

                             ed = xRAX+(nextop&7)+(rex.b<<3);

                             LDRw_U12(ed, xEmu, offsetof(x64emu_t, mxcsr));

                         } else {

@@ -617,6 +617,105 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
             }

             break;

 

+        case 0xBA:

+            nextop = F8;

+            switch((nextop>>3)&7) {

+                case 4:

+                    INST_NAME("BT Ed, Ib");

+                    SETFLAGS(X_CF, SF_SUBSET);

+                    gd = x2;

+                    if(MODREG) {

+                        ed = xRAX+(nextop&7)+(rex.b<<3);

+                        u8 = F8;

+                    } else {

+                        addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xff0<<2, 3, rex, 0, 0);

+                        u8 = F8;

+                        fixedaddress+=(u8>>(rex.w?6:5))*(rex.w?8:4);

+                        LDRxw_U12(x1, wback, fixedaddress);

+                        ed = x1;

+                    }

+                    u8&=rex.w?0x3f:0x1f;

+                    if(u8) {

+                        LSRxw(x1, ed, u8);

+                        ed = x1;

+                    }

+                    BFIw(xFlags, ed, F_CF, 1);

+                    break;

+                case 5:

+                    INST_NAME("BTS Ed, Ib");

+                    SETFLAGS(X_CF, SF_SUBSET);

+                    if(MODREG) {

+                        ed = xRAX+(nextop&7)+(rex.b<<3);

+                        u8 = F8;

+                        wback = 0;

+                    } else {

+                        addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xff0<<2, 3, rex, 0, 0);

+                        u8 = F8;

+                        fixedaddress+=(u8>>(rex.w?6:5))*(rex.w?8:4);

+                        LDRxw_U12(x1, wback, fixedaddress);

+                        ed = x1;

+                    }

+                    LSRxw(x4, ed, u8&(rex.w?0x3f:0x1f));

+                    BFIw(xFlags, x4, F_CF, 1);

+                    TBNZ_MARK3(x4, 0); // bit already set, jump to next instruction

+                    MOV32w(x4, 1);

+                    EORxw_REG_LSL(ed, ed, x4, u8&(rex.w?0x3f:0x1f));

+                    if(wback) {

+                        STRxw_U12(ed, wback, fixedaddress);

+                    }

+                    MARK3;

+                    break;

+                case 6:

+                    INST_NAME("BTR Ed, Ib");

+                    SETFLAGS(X_CF, SF_SUBSET);

+                    if(MODREG) {

+                        ed = xRAX+(nextop&7)+(rex.b<<3);

+                        u8 = F8;

+                        wback = 0;

+                    } else {

+                        addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xff0<<2, 3, rex, 0, 0);

+                        u8 = F8;

+                        fixedaddress+=(u8>>(rex.w?6:5))*(rex.w?8:4);

+                        LDRxw_U12(x1, wback, fixedaddress);

+                        ed = x1;

+                    }

+                    LSRxw(x4, ed, u8&(rex.w?0x3f:0x1f));

+                    BFIw(xFlags, x4, F_CF, 1);

+                    TBZ_MARK3(x4, 0); // bit already clear, jump to next instruction

+                    //MOVW(x14, 1); // already 0x01

+                    EORxw_REG_LSL(ed, ed, x4, u8&(rex.w?0x3f:0x1f));

+                    if(wback) {

+                        STRxw_U12(ed, wback, fixedaddress);

+                    }

+                    MARK3;

+                    break;

+                case 7:

+                    INST_NAME("BTC Ed, Ib");

+                    SETFLAGS(X_CF, SF_SUBSET);

+                    if(MODREG) {

+                        ed = xRAX+(nextop&7)+(rex.b<<3);

+                        u8 = F8;

+                        wback = 0;

+                    } else {

+                        addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xff0<<2, 3, rex, 0, 0);

+                        u8 = F8;

+                        fixedaddress+=(u8>>(rex.w?6:5))*(rex.w?8:4);

+                        LDRxw_U12(x1, wback, fixedaddress);

+                        ed = x1;

+                    }

+                    LSRxw(x4, ed, u8&(rex.w?0x3f:0x1f));

+                    BFIw(xFlags, x4, F_CF, 1);

+                    MOV32w(x4, 1);

+                    EORxw_REG_LSL(ed, ed, x4, u8&(rex.w?0x3f:0x1f));

+                    if(wback) {

+                        STRxw_U12(ed, wback, fixedaddress);

+                    }

+                    MARK3;

+                    break;

+                default:

+                    DEFAULT;

+            }

+            break;

         case 0xBB:

             INST_NAME("BTC Ed, Gd");

             SETFLAGS(X_CF, SF_SET);

diff --git a/src/dynarec/dynarec_arm64_helper.h b/src/dynarec/dynarec_arm64_helper.h
index 53f8da67..d51260bf 100755
--- a/src/dynarec/dynarec_arm64_helper.h
+++ b/src/dynarec/dynarec_arm64_helper.h
@@ -300,6 +300,14 @@
 #define CBNZx_MARK3(reg)            \
     j32 = GETMARK3-(dyn->arm_size); \
     CBNZx(reg, j32)
+// Test bit N of A and branch to MARK3 if set
+#define TBNZ_MARK3(A, N)            \
+    j32 = GETMARK3-(dyn->arm_size); \
+    TBNZ(A, N, j32)
+// Test bit N of A and branch to MARK3 if not set
+#define TBZ_MARK3(A, N)             \
+    j32 = GETMARK3-(dyn->arm_size); \
+    TBZ(A, N, j32)
 // Branch to next instruction if cond (use j32)
 #define B_NEXT(cond)     \
     j32 = (dyn->insts)?(dyn->insts[ninst].epilog-(dyn->arm_size)):0; \