about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorptitSeb <sebastien.chev@gmail.com>2021-03-19 16:16:23 +0100
committerptitSeb <sebastien.chev@gmail.com>2021-03-19 16:16:23 +0100
commitf1625c0d928c6da87fa0c6e72cade44ad34565a0 (patch)
tree070eb81cdc26905a7c454aa0917ab8d05b8ee83a
parent5c4b0baf8b368c68a9e88a685d7427061d785211 (diff)
downloadbox64-f1625c0d928c6da87fa0c6e72cade44ad34565a0.tar.gz
box64-f1625c0d928c6da87fa0c6e72cade44ad34565a0.zip
[DYNAREC] Added 68 PUSH Id and fixed 80/7 cmp (but ThimbleweedPark, IntoTheBreach and WorldOfGoo are still broken, vvvvv works)
-rwxr-xr-xsrc/dynarec/arm64_emitter.h13
-rwxr-xr-xsrc/dynarec/arm64_printer.c57
-rwxr-xr-xsrc/dynarec/dynarec_arm64_00.c17
-rwxr-xr-xsrc/dynarec/dynarec_arm64_0f.c2
-rwxr-xr-xsrc/dynarec/dynarec_arm64_emit_tests.c21
5 files changed, 93 insertions, 17 deletions
diff --git a/src/dynarec/arm64_emitter.h b/src/dynarec/arm64_emitter.h
index ede5ef25..591968a6 100755
--- a/src/dynarec/arm64_emitter.h
+++ b/src/dynarec/arm64_emitter.h
@@ -146,7 +146,9 @@
 #define SUBSx_REG(Rd, Rn, Rm)               EMIT(ADDSUB_REG_gen(1, 1, 1, 0b00, Rm, 0, Rn, Rd))
 #define SUBx_REG_LSL(Rd, Rn, Rm, lsl)       EMIT(ADDSUB_REG_gen(1, 1, 0, 0b00, Rm, lsl, Rn, Rd))
 #define SUBw_REG(Rd, Rn, Rm)                EMIT(ADDSUB_REG_gen(0, 1, 0, 0b00, Rm, 0, Rn, Rd))
+#define SUBw_REG_LSL(Rd, Rn, Rm, lsl)       EMIT(ADDSUB_REG_gen(0, 1, 0, 0b00, Rm, lsl, Rn, Rd))
 #define SUBSw_REG(Rd, Rn, Rm)               EMIT(ADDSUB_REG_gen(0, 1, 1, 0b00, Rm, 0, Rn, Rd))
+#define SUBSw_REG_LSL(Rd, Rn, Rm, lsl)      EMIT(ADDSUB_REG_gen(0, 1, 1, 0b00, Rm, lsl, Rn, Rd))
 #define SUBxw_REG(Rd, Rn, Rm)               EMIT(ADDSUB_REG_gen(rex.w, 1, 0, 0b00, Rm, 0, Rn, Rd))
 #define SUBSxw_REG(Rd, Rn, Rm)              EMIT(ADDSUB_REG_gen(rex.w, 1, 1, 0b00, Rm, 0, Rn, Rd))
 #define CMPSx_REG(Rn, Rm)                   SUBSx_REG(xZR, Rn, Rm)
@@ -180,6 +182,10 @@
 #define LDRB_S9_postindex(Rt, Rn, imm9)   EMIT(LDR_gen(0b00, 0b00, (imm9)&0x1ff, 0b01, Rn, Rt))
 #define LDRB_S9_preindex(Rt, Rn, imm9)    EMIT(LDR_gen(0b00, 0b00, (imm9)&0x1ff, 0b11, Rn, Rt))
 
+#define LDRS_gen(size, op1, imm9, op2, Rn, Rt)   ((size)<<30 | 0b111<<27 | (op1)<<24 | 0b10<<22 | (imm9)<<12 | (op2)<<10 | (Rn)<<5 | (Rt))
+#define LDRSW_S9_postindex(Rt, Rn, imm9)  EMIT(LDRS_gen(0b10, 0b00, (imm9)&0x1ff, 0b01, Rn, Rt))
+#define LDRSW_S9_preindex(Rt, Rn, imm9)   EMIT(LDRS_gen(0b10, 0b00, (imm9)&0x1ff, 0b11, Rn, Rt))
+
 #define LD_gen(size, op1, imm12, Rn, Rt)        ((size)<<30 | 0b111<<27 | (op1)<<24 | 0b01<<22 | (imm12)<<10 | (Rn)<<5 | (Rt))
 #define LDRx_U12(Rt, Rn, imm12)           EMIT(LD_gen(0b11, 0b01, ((uint32_t)(imm12>>3))&0xfff, Rn, Rt))
 #define LDRw_U12(Rt, Rn, imm12)           EMIT(LD_gen(0b10, 0b01, ((uint32_t)(imm12>>2))&0xfff, Rn, Rt))
@@ -187,6 +193,9 @@
 #define LDRH_U12(Rt, Rn, imm12)           EMIT(LD_gen(0b01, 0b01, ((uint32_t)(imm12>>1))&0xfff, Rn, Rt))
 #define LDRxw_U12(Rt, Rn, imm12)          EMIT(LD_gen((rex.w)?0b11:0b10, 0b01, ((uint32_t)(imm12>>(2+rex.w)))&0xfff, Rn, Rt))
 
+#define LDS_gen(size, op1, imm12, Rn, Rt)       ((size)<<30 | 0b111<<27 | (op1)<<24 | 0b10<<22 | (imm12)<<10 | (Rn)<<5 | (Rt))
+#define LDRSW_U12(Rt, Rn, imm12)          EMIT(LDS_gen(0b10, 0b01, ((uint32_t)(imm12>>2))&0xfff, Rn, Rt))
+
 #define LDR_REG_gen(size, Rm, option, S, Rn, Rt)    ((size)<<30 | 0b111<<27 | 0b01<<22 | 1<<21 | (Rm)<<16 | (option)<<13 | (S)<<12 | (0b10)<<10 | (Rn)<<5 | (Rt))
 #define LDRx_REG(Rt, Rn, Rm)            EMIT(LDR_REG_gen(0b11, Rm, 0b011, 0, Rn, Rt))
 #define LDRx_REG_LSL3(Rt, Rn, Rm)       EMIT(LDR_REG_gen(0b11, Rm, 0b011, 1, Rn, Rt))
@@ -197,8 +206,8 @@
 #define LDRH_REG(Rt, Rn, Rm)            EMIT(LDR_REG_gen(0b01, Rm, 0b011, 0, Rn, Rt))
 
 #define LDRSH_gen(size, op1, opc, imm9, op2, Rn, Rt)    ((size)<<30 | 0b111<<27 | (op1)<<24 | (opc)<<22 | (imm9)<<12 | (op2)<<10 | (Rn)<<5 | (Rt))
-#define LDRSHx_U12(Rt, Rn, imm12)           EMIT(LD_gen(0b01, 0b00, 0b10, ((uint32_t)(imm12>>2))&0xfff, Rn, Rt))
-#define LDRSHw_U12(Rt, Rn, imm12)           EMIT(LD_gen(0b01, 0b00, 0b11, ((uint32_t)(imm12>2))&0xfff, Rn, Rt))
+#define LDRSHx_U12(Rt, Rn, imm12)           EMIT(LD_gen(0b01, 0b00, 0b10, ((uint32_t)(imm12>>1))&0xfff, Rn, Rt))
+#define LDRSHw_U12(Rt, Rn, imm12)           EMIT(LD_gen(0b01, 0b00, 0b11, ((uint32_t)(imm12>>1))&0xfff, Rn, Rt))
 
 #define LDR_PC_gen(opc, imm19, Rt)      ((opc)<<30 | 0b011<<27 | (imm19)<<5 | (Rt))
 #define LDRx_literal(Rt, imm19)         EMIT(LDR_PC_gen(0b01, ((imm19)>>2)&0x7FFFF, Rt))
diff --git a/src/dynarec/arm64_printer.c b/src/dynarec/arm64_printer.c
index e4782b47..0578d7f0 100755
--- a/src/dynarec/arm64_printer.c
+++ b/src/dynarec/arm64_printer.c
@@ -172,7 +172,7 @@ const char* arm64_print(uint32_t opcode, uintptr_t addr)
     }

     if(isMask(opcode, "0x011000iiiiiiiiiiiiiiiiiiittttt", &a)) {

         int size = ((opcode>>30)&1)?3:2;

-        int offset = signExtend(imm, 9)<<2;

+        int offset = signExtend(imm, 9)<<size;

         snprintf(buff, sizeof(buff), "LDR %s, [#%+d]\t;%p", (size==2)?Wt[Rt]:Xt[Rt], offset, (void*)(addr+offset));

         return buff;

     }

@@ -217,7 +217,48 @@ const char* arm64_print(uint32_t opcode, uintptr_t addr)
             snprintf(buff, sizeof(buff), "STR %s, [%s, %s, %s %d]", (size==2)?Wt[Rt]:Xt[Rt], XtSp[Rn], ((option&1)==0)?Wt[Rm]:Xt[Rm], extend[option], amount);

         return buff;

     }

-    // --- MOV (REGS: see Logic MOV==ORR, MVN==ORN)

+    if(isMask(opcode, "0x111000010iiiiiiiii01nnnnnttttt", &a)) {

+        int size = a.x;

+        int offset = signExtend(imm, 9);

+        snprintf(buff, sizeof(buff), "LDR%c %s, [%s], %s0x%x", size?'H':'B', Xt[Rt], XtSp[Rn], (offset<0)?"-":"", abs(offset));

+        return buff;

+    }

+    if(isMask(opcode, "0x111000010iiiiiiiii11nnnnnttttt", &a)) {

+        int size = a.x;

+        int offset = signExtend(imm, 9);

+        snprintf(buff, sizeof(buff), "LDR%c %s, [%s, %s0x%x]!", size?'H':'B', Xt[Rt], XtSp[Rn], (offset<0)?"-":"", abs(offset));

+        return buff;

+    }

+    if(isMask(opcode, "0x11100101iiiiiiiiiiiinnnnnttttt", &a)) {

+        int size = a.x;

+        int offset = (imm)<<size;

+        if(offset)

+            snprintf(buff, sizeof(buff), "LDR%c %s, [%s, 0x%x]", size?'H':'B', Xt[Rt], XtSp[Rn], offset);

+        else

+            snprintf(buff, sizeof(buff), "LDR%c %s, [%s]", size?'H':'B', Xt[Rt], XtSp[Rn]);

+        return buff;

+    }

+    if(isMask(opcode, "0x111000000iiiiiiiii01nnnnnttttt", &a)) {

+        int size = a.x;

+        int offset = signExtend(imm, 9);

+        snprintf(buff, sizeof(buff), "STR%c %s, [%s], %s0x%x", size?'H':'B', Xt[Rt], XtSp[Rn], (offset<0)?"-":"", abs(offset));

+        return buff;

+    }

+    if(isMask(opcode, "0x111000000iiiiiiiii11nnnnnttttt", &a)) {

+        int size = a.x;

+        int offset = signExtend(imm, 9);

+        snprintf(buff, sizeof(buff), "STR%c %s, [%s, %s0x%x]!", size?'H':'B', Xt[Rt], XtSp[Rn], (offset<0)?"-":"", abs(offset));

+        return buff;

+    }

+    if(isMask(opcode, "0x11100100iiiiiiiiiiiinnnnnttttt", &a)) {

+        int size = a.x;

+        int offset = (imm)<<size;

+        if(offset)

+            snprintf(buff, sizeof(buff), "STR%c %s, [%s, 0x%x]", size?'H':'B', Xt[Rt], XtSp[Rn], offset);

+        else

+            snprintf(buff, sizeof(buff), "STR%c %s, [%s]", size?'H':'B', Xt[Rt], XtSp[Rn]);

+        return buff;

+    }    // --- MOV (REGS: see Logic MOV==ORR, MVN==ORN)

     if(isMask(opcode, "f10100101wwiiiiiiiiiiiiiiiiddddd", &a)) {

         if(!hw)

             snprintf(buff, sizeof(buff), "MOVZ %s, 0x%x", sf?Xt[Rd]:Wt[Rd], imm);

@@ -502,7 +543,7 @@ const char* arm64_print(uint32_t opcode, uintptr_t addr)
             else

                 snprintf(buff, sizeof(buff), "BFI %s, %s, %d, %d", sf?Xt[Rd]:Wt[Rd], sf?Xt[Rn]:Wt[Rn], lsb, width);

         } else

-            snprintf(buff, sizeof(buff), "BFM %s, %s, %d, %d", sf?Xt[Rd]:Wt[Rd], sf?Xt[Rn]:Wt[Rn], immr, imms);

+            snprintf(buff, sizeof(buff), "BFXIL %s, %s, %d, %d", sf?Xt[Rd]:Wt[Rd], sf?Xt[Rn]:Wt[Rn], immr, imms-immr+1);

         return buff;

     }

     // ---- BRANCH / TEST

@@ -534,6 +575,16 @@ const char* arm64_print(uint32_t opcode, uintptr_t addr)
         return buff;

     }

 

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

+        if(Rm!=31 && (cond&0b1110)!=0b1110 && Rn!=31 && Rn==Rm)

+            snprintf(buff, sizeof(buff), "CINC %s, %s, %s, %s", sf?Xt[Rd]:Wt[Rd], sf?Xt[Rn]:Wt[Rn], sf?Xt[Rm]:Wt[Rm], conds[cond^1]);    

+        else if(Rm==31 && (cond&0b1110)!=0b1110 && Rn==31)

+            snprintf(buff, sizeof(buff), "CSET %s,%s", sf?Xt[Rd]:Wt[Rd], conds[cond^1]);    

+        else

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

+        return buff;

+    }

+

     snprintf(buff, sizeof(buff), "%08X ???", __builtin_bswap32(opcode));

     return buff;

 }
\ No newline at end of file
diff --git a/src/dynarec/dynarec_arm64_00.c b/src/dynarec/dynarec_arm64_00.c
index b8c34ca8..6674b616 100755
--- a/src/dynarec/dynarec_arm64_00.c
+++ b/src/dynarec/dynarec_arm64_00.c
@@ -260,6 +260,20 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
             addr = dynarec64_66(dyn, addr, ip, ninst, rex, ok, need_epilog);
             break;
 
+        case 0x68:
+            INST_NAME("PUSH Id");
+            i64 = F32S;
+            if(PK(0)==0xC3) {
+                MESSAGE(LOG_DUMP, "PUSH then RET, using indirect\n");
+                TABLE64(x3, ip+1);
+                LDRSW_U12(x1, x3, 0);
+                PUSH1(x1);
+            } else {
+                MOV64x(x3, i64);
+                PUSH1(x3);
+            }
+            break;
+
         #define GO(GETFLAGS, NO, YES, F)    \
             READFLAGS(F);                   \
             i8 = F8S;   \
@@ -436,12 +450,13 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
                     GETEB(x1, 1);
                     u8 = F8;
                     if(u8) {
-                        MOV32w(x2, u8);
                         emit_cmp8(dyn, ninst, x1, x2, x3, x4, x5);
                     } else {
                         emit_cmp8_0(dyn, ninst, x1, x3, x4);
                     }
                     break;
+                default:
+                    DEFAULT;
             }
             break;
         case 0x81:
diff --git a/src/dynarec/dynarec_arm64_0f.c b/src/dynarec/dynarec_arm64_0f.c
index 37393753..5270d981 100755
--- a/src/dynarec/dynarec_arm64_0f.c
+++ b/src/dynarec/dynarec_arm64_0f.c
@@ -94,7 +94,7 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
             GETFLAGS;                               \

             nextop=F8;                              \

             GETGD;                                  \

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

+            if(MODREG) {                            \

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

                 CSELxw(gd, ed, gd, YES);            \

             } else { \

diff --git a/src/dynarec/dynarec_arm64_emit_tests.c b/src/dynarec/dynarec_arm64_emit_tests.c
index a6430847..c0ebea21 100755
--- a/src/dynarec/dynarec_arm64_emit_tests.c
+++ b/src/dynarec/dynarec_arm64_emit_tests.c
@@ -34,8 +34,7 @@ void emit_cmp32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3
         SET_DFNONE(s4);
     }
     IFX(X_AF) {
-        MVNxw_REG(s3, s1);
-        ORRxw_REG(s3, s3, s2);  // s3 = ~op1 | op2
+        ORNxw_REG(s3, s2, s1);  // s3 = ~op1 | op2
         BICxw(s4, s2, s1);      // s4 = ~op1 & op2
     }
     SUBSxw_REG(s5, s1, s2);   // res = s1 - s2
@@ -212,25 +211,27 @@ void emit_cmp8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4, in
     } else {
         SET_DFNONE(s4);
     }
-    SUBw_REG(s5, s1, s2);   // res = s1 - s2
+    IFX(X_ZF) {
+        SUBSw_REG(s5, s1, s2);   // res = s1 - s2
+    } else {
+        SUBw_REG(s5, s1, s2);   // res = s1 - s2
+    }
     IFX(X_PEND) {
-        STRB_REG(s5, xEmu, offsetof(x64emu_t, res));
+        STRB_U12(s5, xEmu, offsetof(x64emu_t, res));
     }
     IFX(X_ZF) {
-        ANDSw_mask(s1, s1, 0, 0b000111);    //mask=000000ff
         CSETw(s3, cEQ);
         BFIw(xFlags, s3, F_ZF, 1);
     }
     IFX(X_SF) {
-        LSRw(s5, s1, 7);
-        BFIw(xFlags, s5, F_SF, 1);
+        LSRw(s3, s5, 7);
+        BFIw(xFlags, s3, F_SF, 1);
     }
     // bc = (res & (~d | s)) | (~d & s)
     IFX(X_CF|X_AF|X_OF) {
-        MVNw_REG(s4, s1);       // s4 = ~d
-        ORRw_REG(s4, s4, s2);   // s4 = ~d | s
+        ORNw_REG(s4, s2, s1);   // s4 = ~d | s
         ANDw_REG(s4, s4, s5);   // s4 = res & (~d | s)
-        BICw_REG(s3, s2, s5);   // s3 = s & ~d
+        BICw_REG(s3, s2, s1);   // s3 = s & ~d
         ORRw_REG(s3, s4, s3);   // s3 = (res & (~d | s)) | (s & ~d)
         IFX(X_CF) {
             LSRw(s4, s3, 7);