about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorptitSeb <sebastien.chev@gmail.com>2021-10-05 23:06:58 +0200
committerptitSeb <sebastien.chev@gmail.com>2021-10-05 23:06:58 +0200
commit8d69c1783931384c1598421df7b1a36d3d564bde (patch)
tree11a25597053bed0d3a476a054e4d1cb9c07dda5a
parent348cb57240efe51690e420a4fdf3a012e3251d44 (diff)
downloadbox64-8d69c1783931384c1598421df7b1a36d3d564bde.tar.gz
box64-8d69c1783931384c1598421df7b1a36d3d564bde.zip
[DYNAREC] Added 67 89/C1/F7 opcodes
-rwxr-xr-xsrc/dynarec/dynarec_arm64_67.c232
-rwxr-xr-xsrc/dynarec/dynarec_arm64_helper.h37
2 files changed, 266 insertions, 3 deletions
diff --git a/src/dynarec/dynarec_arm64_67.c b/src/dynarec/dynarec_arm64_67.c
index 22466181..c1e33cf8 100755
--- a/src/dynarec/dynarec_arm64_67.c
+++ b/src/dynarec/dynarec_arm64_67.c
@@ -32,11 +32,12 @@ uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
 

     uint8_t opcode = F8;

     uint8_t nextop;

-    uint8_t gd, ed;

+    uint8_t gd, ed, wback, wb;

     int64_t fixedaddress;

     int8_t  i8;

+    uint8_t u8;

     int32_t i32;

-    int64_t j64;

+    int64_t j64, i64;

     int v0, s0;

     MAYUSE(i32);

     MAYUSE(j64);

@@ -88,6 +89,18 @@ uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
             }

             break;

 

+        case 0x89:

+            INST_NAME("MOV Ed, Gd");

+            nextop=F8;

+            GETGD;

+            if(MODREG) {   // reg <= reg

+                MOVxw_REG(xRAX+(nextop&7)+(rex.b<<3), gd);

+            } else {                    // mem <= reg

+                addr = geted32(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0xfff<<(2+rex.w), (1<<(2+rex.w))-1, rex, 0, 0);

+                STRxw_U12(gd, ed, fixedaddress);

+            }

+            break;

+

         case 0x8D:

             INST_NAME("LEA Gd, Ed");

             nextop=F8;

@@ -103,6 +116,79 @@ uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
             }

             break;

 

+        case 0xC1:

+            nextop = F8;

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

+                case 0:

+                    INST_NAME("ROL Ed, Ib");

+                    SETFLAGS(X_OF|X_CF, SF_SUBSET);

+                    GETED32(1);

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

+                    emit_rol32c(dyn, ninst, rex, ed, u8, x3, x4);

+                    if(u8) { WBACK; }

+                    break;

+                case 1:

+                    INST_NAME("ROR Ed, Ib");

+                    SETFLAGS(X_OF|X_CF, SF_SUBSET);

+                    GETED32(1);

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

+                    emit_ror32c(dyn, ninst, rex, ed, u8, x3, x4);

+                    if(u8) { WBACK; }

+                    break;

+                case 2:

+                    INST_NAME("RCL Ed, Ib");

+                    MESSAGE(LOG_DUMP, "Need Optimization\n");

+                    READFLAGS(X_CF);

+                    SETFLAGS(X_OF|X_CF, SF_SET);

+                    GETED32W(x4, x1, 1);

+                    u8 = F8;

+                    MOV32w(x2, u8);

+                    CALL_(rex.w?((void*)rcl64):((void*)rcl32), ed, x4);

+                    WBACK;

+                    break;

+                case 3:

+                    INST_NAME("RCR Ed, Ib");

+                    MESSAGE(LOG_DUMP, "Need Optimization\n");

+                    READFLAGS(X_CF);

+                    SETFLAGS(X_OF|X_CF, SF_SET);

+                    GETED32W(x4, x1, 1);

+                    u8 = F8;

+                    MOV32w(x2, u8);

+                    CALL_(rex.w?((void*)rcr64):((void*)rcr32), ed, x4);

+                    WBACK;

+                    break;

+                case 4:

+                case 6:

+                    INST_NAME("SHL Ed, Ib");

+                    SETFLAGS(X_ALL, SF_SET_PENDING);    // some flags are left undefined

+                    GETED32(1);

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

+                    emit_shl32c(dyn, ninst, rex, ed, u8, x3, x4);

+                    WBACK;

+                    break;

+                case 5:

+                    INST_NAME("SHR Ed, Ib");

+                    SETFLAGS(X_ALL, SF_SET_PENDING);    // some flags are left undefined

+                    GETED32(1);

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

+                    emit_shr32c(dyn, ninst, rex, ed, u8, x3, x4);

+                    if(u8) {

+                        WBACK;

+                    }

+                    break;

+                case 7:

+                    INST_NAME("SAR Ed, Ib");

+                    SETFLAGS(X_ALL, SF_SET_PENDING);    // some flags are left undefined

+                    GETED32(1);

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

+                    emit_sar32c(dyn, ninst, rex, ed, u8, x3, x4);

+                    if(u8) {

+                        WBACK;

+                    }

+                    break;

+            }

+            break;

+            

         #define GO(NO, YES)   \

             BARRIER(2); \

             JUMP(addr+i8);\

@@ -160,6 +246,148 @@ uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
         case 0xE8:

             return dynarec64_00(dyn, addr-1, ip, ninst, rex, rep, ok, need_epilog); // addr-1, to "put back" opcode)

 

+        case 0xF7:

+            nextop = F8;

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

+                case 0:

+                case 1:

+                    INST_NAME("TEST Ed, Id");

+                    SETFLAGS(X_ALL, SF_SET_PENDING);

+                    GETED32H(x1, 4);

+                    i64 = F32S;

+                    MOV64xw(x2, i64);

+                    emit_test32(dyn, ninst, rex, ed, x2, x3, x4);

+                    break;

+                case 2:

+                    INST_NAME("NOT Ed");

+                    GETED32(4);

+                    MVNxw_REG(ed, ed);

+                    WBACK;

+                    break;

+                case 3:

+                    INST_NAME("NEG Ed");

+                    SETFLAGS(X_ALL, SF_SET_PENDING);

+                    GETED32(0);

+                    emit_neg32(dyn, ninst, rex, ed, x3, x4);

+                    WBACK;

+                    break;

+                case 4:

+                    INST_NAME("MUL EAX, Ed");

+                    SETFLAGS(X_ALL, SF_PENDING);

+                    UFLAG_DF(x2, rex.w?d_mul64:d_mul32);

+                    GETED32(0);

+                    if(rex.w) {

+                        if(ed==xRDX) gd=x3; else gd=xRDX;

+                        UMULH(gd, xRAX, ed);

+                        MULx(xRAX, xRAX, ed);

+                        if(gd!=xRDX) {MOVx_REG(xRDX, gd);}

+                    } else {

+                        UMULL(xRDX, xRAX, ed);  //64 <- 32x32

+                        MOVw_REG(xRAX, xRDX);

+                        LSRx(xRDX, xRDX, 32);

+                    }

+                    UFLAG_RES(xRAX);

+                    UFLAG_OP1(xRDX);

+                    break;

+                case 5:

+                    INST_NAME("IMUL EAX, Ed");

+                    SETFLAGS(X_ALL, SF_PENDING);

+                    UFLAG_DF(x2, rex.w?d_imul64:d_imul32);

+                    GETED32(0);

+                    if(rex.w) {

+                        if(ed==xRDX) gd=x3; else gd=xRDX;

+                        SMULH(gd, xRAX, ed);

+                        MULx(xRAX, xRAX, ed);

+                        if(gd!=xRDX) {MOVx_REG(xRDX, gd);}

+                    } else {

+                        SMULL(xRDX, xRAX, ed);  //64 <- 32x32

+                        MOVw_REG(xRAX, xRDX);

+                        LSRx(xRDX, xRDX, 32);

+                    }

+                    UFLAG_RES(xRAX);

+                    UFLAG_OP1(xRDX);

+                    break;

+                case 6:

+                    INST_NAME("DIV Ed");

+                    SETFLAGS(X_ALL, SF_SET);

+                    if(!rex.w) {

+                        SET_DFNONE(x2);

+                        GETED32(0);

+                        MOVw_REG(x3, xRAX);

+                        ORRx_REG_LSL(x3, x3, xRDX, 32);

+                        if(MODREG) {

+                            MOVw_REG(x4, ed);

+                            ed = x4;

+                        }

+                        UDIVx(x2, x3, ed);

+                        MSUBx(x4, x2, ed, xRAX);

+                        MOVw_REG(xRAX, x2);

+                        MOVw_REG(xRDX, x4);

+                    } else {

+                        if(ninst && dyn->insts 

+                           && dyn->insts[ninst-1].x64.addr 

+                           && *(uint8_t*)(dyn->insts[ninst-1].x64.addr)==0x31 

+                           && *(uint8_t*)(dyn->insts[ninst-1].x64.addr+1)==0xD2) {

+                            SET_DFNONE(x2);

+                            GETED32(0);

+                            UDIVx(x2, xRAX, ed);

+                            MSUBx(xRDX, x2, ed, xRAX);

+                            MOVx_REG(xRAX, x2);

+                        } else {

+                            GETED32H(x1, 0);  // get edd changed addr, so cannot be called 2 times for same op...

+                            CBZxw_MARK(xRDX);

+                            if(ed!=x1) {MOVx_REG(x1, ed);}

+                            CALL(div64, -1);

+                            B_NEXT_nocond;

+                            MARK;

+                            UDIVx(x2, xRAX, ed);

+                            MSUBx(xRDX, x2, ed, xRAX);

+                            MOVx_REG(xRAX, x2);

+                            SET_DFNONE(x2);

+                        }

+                    }

+                    break;

+                case 7:

+                    INST_NAME("IDIV Ed");

+                    SETFLAGS(X_ALL, SF_SET);

+                    if(!rex.w) {

+                        SET_DFNONE(x2)

+                        GETSED32w(0);

+                        MOVw_REG(x3, xRAX);

+                        ORRx_REG_LSL(x3, x3, xRDX, 32);

+                        SDIVx(x2, x3, wb);

+                        MSUBx(x4, x2, wb, x3);

+                        MOVw_REG(xRAX, x2);

+                        MOVw_REG(xRDX, x4);

+                    } else {

+                        if(ninst && dyn->insts

+                           &&  dyn->insts[ninst-1].x64.addr 

+                           && *(uint8_t*)(dyn->insts[ninst-1].x64.addr)==0x48

+                           && *(uint8_t*)(dyn->insts[ninst-1].x64.addr+1)==0x99) {

+                            SET_DFNONE(x2)

+                            GETED32(0);

+                            SDIVx(x2, xRAX, ed);

+                            MSUBx(xRDX, x2, ed, xRAX);

+                            MOVx_REG(xRAX, x2);

+                        } else {

+                            GETED32H(x1, 0);  // get edd changed addr, so cannot be called 2 times for same op...

+                            CBZxw_MARK(xRDX);

+                            MVNx_REG(x2, xRDX);

+                            CBZxw_MARK(x2);

+                            if(ed!=x1) {MOVx_REG(x1, ed);}

+                            CALL((void*)idiv64, -1);

+                            B_NEXT_nocond;

+                            MARK;

+                            SDIVx(x2, xRAX, ed);

+                            MSUBx(xRDX, x2, ed, xRAX);

+                            MOVx_REG(xRAX, x2);

+                            SET_DFNONE(x2)

+                        }

+                    }

+                    break;

+            }

+            break;

+

         default:

             DEFAULT;

     }

diff --git a/src/dynarec/dynarec_arm64_helper.h b/src/dynarec/dynarec_arm64_helper.h
index a005d90d..1ec25bc7 100755
--- a/src/dynarec/dynarec_arm64_helper.h
+++ b/src/dynarec/dynarec_arm64_helper.h
@@ -69,6 +69,24 @@
                     LDRSW_U12(x1, wback, fixedaddress); \
                     wb = ed = x1;                       \
                 }
+#define GETED32(D)  if(MODREG) {                        \
+                    ed = xRAX+(nextop&7)+(rex.b<<3);    \
+                    wback = 0;                          \
+                } else {                                \
+                    addr = geted32(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0xfff<<(2+rex.w), (1<<(2+rex.w))-1, rex, 0, D); \
+                    LDRxw_U12(x1, wback, fixedaddress); \
+                    ed = x1;                            \
+                }
+#define GETSED32w(D)  if((nextop&0xC0)==0xC0) {         \
+                    ed = xRAX+(nextop&7)+(rex.b<<3);    \
+                    SXTWx(x1, ed);                      \
+                    wb = x1;                            \
+                    wback = 0;                          \
+                } else {                                \
+                    addr = geted32(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0xfff<<2, 3, rex, 0, D); \
+                    LDRSW_U12(x1, wback, fixedaddress); \
+                    wb = ed = x1;                       \
+                }
 //GETEDH can use hint for ed, and r1 or r2 for wback (depending on hint). wback is 0 if ed is xEAX..xEDI
 #define GETEDH(hint, D) if(MODREG) {                    \
                     ed = xRAX+(nextop&7)+(rex.b<<3);    \
@@ -78,8 +96,16 @@
                     LDRxw_U12(hint, wback, fixedaddress); \
                     ed = hint;                            \
                 }
+#define GETED32H(hint, D) if(MODREG) {                  \
+                    ed = xRAX+(nextop&7)+(rex.b<<3);    \
+                    wback = 0;                          \
+                } else {                                \
+                    addr = geted32(dyn, addr, ninst, nextop, &wback, (hint==x2)?x1:x2, &fixedaddress, 0xfff<<(2+rex.w), (1<<(2+rex.w))-1, rex, 0, D); \
+                    LDRxw_U12(hint, wback, fixedaddress); \
+                    ed = hint;                            \
+                }
 //GETEDW can use hint for wback and ret for ed. wback is 0 if ed is xEAX..xEDI
-#define GETEDW(hint, ret, D)   if(MODREG) {              \
+#define GETEDW(hint, ret, D)   if(MODREG) {             \
                     ed = xRAX+(nextop&7)+(rex.b<<3);    \
                     MOVxw_REG(ret, ed);                 \
                     wback = 0;                          \
@@ -88,6 +114,15 @@
                     ed = ret;                           \
                     LDRxw_U12(ed, wback, fixedaddress); \
                 }
+#define GETED32W(hint, ret, D)   if(MODREG) {           \
+                    ed = xRAX+(nextop&7)+(rex.b<<3);    \
+                    MOVxw_REG(ret, ed);                 \
+                    wback = 0;                          \
+                } else {                                \
+                    addr = geted32(dyn, addr, ninst, nextop, &wback, hint, &fixedaddress, 0xfff<<(2+rex.w), (1<<(2+rex.w))-1, rex, 0, D); \
+                    ed = ret;                           \
+                    LDRxw_U12(ed, wback, fixedaddress); \
+                }
 // Write back ed in wback (if wback not 0)
 #define WBACK       if(wback) {STRxw_U12(ed, wback, fixedaddress);}
 // Write back ed in wback (if wback not 0)