about summary refs log tree commit diff stats
path: root/src/dynarec/arm64/dynarec_arm64_66.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/dynarec/arm64/dynarec_arm64_66.c')
-rw-r--r--src/dynarec/arm64/dynarec_arm64_66.c235
1 files changed, 218 insertions, 17 deletions
diff --git a/src/dynarec/arm64/dynarec_arm64_66.c b/src/dynarec/arm64/dynarec_arm64_66.c
index fa69a836..ff269cf2 100644
--- a/src/dynarec/arm64/dynarec_arm64_66.c
+++ b/src/dynarec/arm64/dynarec_arm64_66.c
@@ -1,7 +1,6 @@
 #include <stdio.h>

 #include <stdlib.h>

 #include <stddef.h>

-#include <pthread.h>

 #include <errno.h>

 

 #include "debug.h"

@@ -50,14 +49,9 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
         rep = opcode-0xF1;

         opcode = F8;

     }

-    // REX prefix before the 66 are ignored

-    rex.rex = 0;

-    while(opcode>=0x40 && opcode<=0x4f) {

-        rex.rex = opcode;

-        opcode = F8;

-    }

+    GETREX();

 

-    if(rex.w && opcode!=0x0f)   // rex.w cancels "66", but not for 66 0f type of prefix

+    if(rex.w && !(opcode==0x0f || opcode==0xf0 || opcode==0x64 || opcode==0x65))   // rex.w cancels "66", but not for 66 0f type of prefix

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

 

     switch(opcode) {

@@ -88,7 +82,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
             emit_add16(dyn, ninst, x1, x2, x3, x4);

             BFIx(xRAX, x1, 0, 16);

             break;

-                

+

         case 0x09:

             INST_NAME("OR Ew, Gw");

             SETFLAGS(X_ALL, SF_SET_PENDING);

@@ -295,6 +289,70 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
             }

             break;

 

+        case 0x40:

+        case 0x41:

+        case 0x42:

+        case 0x43:

+        case 0x44:

+        case 0x45:

+        case 0x46:

+        case 0x47:

+            INST_NAME("INC Reg16 (32bits)");

+            SETFLAGS(X_ALL&~X_CF, SF_SUBSET_PENDING);

+            gd = xRAX + (opcode&7);

+            UXTHw(x1, gd);

+            emit_inc16(dyn, ninst, x1, x2, x3);

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

+            break;

+        case 0x48:

+        case 0x49:

+        case 0x4A:

+        case 0x4B:

+        case 0x4C:

+        case 0x4D:

+        case 0x4E:

+        case 0x4F:

+            INST_NAME("DEC Reg16 (32bits)");

+            SETFLAGS(X_ALL&~X_CF, SF_SUBSET_PENDING);

+            gd = xRAX + (opcode&7);

+            UXTHw(x1, gd);

+            emit_dec16(dyn, ninst, x1, x2, x3);

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

+            break;

+

+        case 0x60:

+            if(rex.is32bits) {

+                INST_NAME("PUSHA 16 (32bits)");

+                MOVw_REG(x1, xRSP);

+                STRH_S9_preindex(xRAX, xRSP, -2);

+                STRH_S9_preindex(xRCX, xRSP, -2);

+                STRH_S9_preindex(xRDX, xRSP, -2);

+                STRH_S9_preindex(xRBX, xRSP, -2);

+                STRH_S9_preindex(x1, xRSP, -2);

+                STRH_S9_preindex(xRBP, xRSP, -2);

+                STRH_S9_preindex(xRSI, xRSP, -2);

+                STRH_S9_preindex(xRDI, xRSP, -2);

+            } else {

+                DEFAULT;

+            }

+            break;

+        case 0x61:

+            if(rex.is32bits) {

+                INST_NAME("POPA 16 (32bits)");

+                MOVw_REG(x1, xRSP);

+                LDRH_S9_postindex(xRDI, xRSP, 2);

+                LDRH_S9_postindex(xRSI, xRSP, 2);

+                LDRH_S9_postindex(xRBP, xRSP, 2);

+                LDRH_S9_postindex(x1, xRSP, 2);

+                LDRH_S9_postindex(xRBX, xRSP, 2);

+                LDRH_S9_postindex(xRDX, xRSP, 2);

+                LDRH_S9_postindex(xRCX, xRSP, 2);

+                LDRH_S9_postindex(xRAX, xRSP, 2);

+            } else {

+                DEFAULT;

+            }

+            break;

+

         case 0x64:

             addr = dynarec64_6664(dyn, addr, ip, ninst, rex, _FS, ok, need_epilog);

             break;

@@ -425,7 +483,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
                     break;

             }

             break;

-            

+

         case 0x85:

             INST_NAME("TEST Ew, Gw");

             SETFLAGS(X_ALL, SF_SET_PENDING);

@@ -463,7 +521,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
                 BFIx(gd, x1, 0, 16);

             }

             break;

-            

+

         case 0x89:

             INST_NAME("MOV Ew, Gw");

             nextop = F8;

@@ -495,6 +553,19 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
                 BFIx(gd, x1, 0, 16);

             }

             break;

+        case 0x8C:

+            INST_NAME("MOV EW, Seg");

+            nextop=F8;

+            u8 = (nextop&0x38)>>3;

+            LDRw_U12(x3, xEmu, offsetof(x64emu_t, segs[u8]));

+            if((nextop&0xC0)==0xC0) {   // reg <= seg

+                UXTHw(xRAX+(nextop&7)+(rex.b<<3), x3);

+            } else {                    // mem <= seg

+                addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, &unscaled, 0xfff<<1, 1, rex, NULL, 0, 0);

+                STH(x3, wback, fixedaddress);

+                SMWRITE2();

+            }

+            break;

 

             case 0x90:

             case 0x91:

@@ -521,18 +592,47 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
             BFIw(xRAX, x1, 0, 16);

             break;

 

+        case 0x9C:

+            INST_NAME("PUSHF");

+            READFLAGS(X_ALL);

+            PUSH1_16(xFlags);

+            break;

+        case 0x9D:

+            INST_NAME("POPF");

+            SETFLAGS(X_ALL, SF_SET);

+            POP1_16(x1);    // probably not usefull...

+            BFIw(xFlags, x1, 0, 16);

+            MOV32w(x1, 0x3F7FD7);

+            ANDw_REG(xFlags, xFlags, x1);

+            ORRw_mask(xFlags, xFlags, 0b011111, 0);   //mask=0x00000002

+            SET_DFNONE(x1);

+            if(box64_wine) {    // should this be done all the time?

+                TBZ_NEXT(xFlags, F_TF);

+                MOV64x(x1, addr);

+                STORE_XEMU_CALL(x1);

+                CALL(native_singlestep, -1);

+                BFCw(xFlags, F_TF, 1);

+            }

+            break;

+

         case 0xA1:

             INST_NAME("MOV EAX,Od");

-            u64 = F64;

-            MOV64x(x1, u64);

+            if(rex.is32bits)

+                u64 = F32;

+            else

+                u64 = F64;

+            MOV64z(x1, u64);

             LDRH_U12(x2, x1, 0);

             BFIx(xRAX, x2, 0, 16);

             break;

 

         case 0xA3:

             INST_NAME("MOV Od,EAX");

-            u64 = F64;

-            MOV64x(x1, u64);

+            if(rex.is32bits)

+                u64 = F32;

+            else

+                u64 = F64;

+            MOV64z(x1, u64);

             STRH_U12(xRAX, x1, 0);

             SMWRITE();

             break;

@@ -564,6 +664,46 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
             }

             break;

 

+        case 0xA7:

+            switch(rep) {

+            case 1:

+            case 2:

+                if(rep==1) {INST_NAME("REPNZ CMPSW");} else {INST_NAME("REPZ CMPSW");}

+                MAYSETFLAGS();

+                SETFLAGS(X_ALL, SF_SET_PENDING);

+                CBZx_NEXT(xRCX);

+                TBNZ_MARK2(xFlags, F_DF);

+                MARK;   // Part with DF==0

+                LDRH_S9_postindex(x1, xRSI, 2);

+                LDRH_S9_postindex(x2, xRDI, 2);

+                SUBx_U12(xRCX, xRCX, 1);

+                CMPSw_REG(x1, x2);

+                B_MARK3((rep==1)?cEQ:cNE);

+                CBNZx_MARK(xRCX);

+                B_MARK3_nocond;

+                MARK2;  // Part with DF==1

+                LDRH_S9_postindex(x1, xRSI, -2);

+                LDRH_S9_postindex(x2, xRDI, -2);

+                SUBx_U12(xRCX, xRCX, 1);

+                CMPSw_REG(x1, x2);

+                B_MARK3((rep==1)?cEQ:cNE);

+                CBNZx_MARK2(xRCX);

+                MARK3;  // end

+                emit_cmp16(dyn, ninst, x1, x2, x3, x4, x5);

+                break;

+            default:

+                INST_NAME("CMPSW");

+                SETFLAGS(X_ALL, SF_SET_PENDING);

+                GETDIR(x3, 2);

+                LDRH_U12(x1, xRSI, 0);

+                LDRH_U12(x2, xRDI, 0);

+                ADDx_REG(xRSI, xRSI, x3);

+                ADDx_REG(xRDI, xRDI, x3);

+                emit_cmp16(dyn, ninst, x1, x2, x3, x4, x5);

+                break;

+            }

+            break;

+

         case 0xA9:

             INST_NAME("TEST AX,Iw");

             SETFLAGS(X_ALL, SF_SET_PENDING);

@@ -596,6 +736,67 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
             }

             break;

 

+        case 0xAD:

+            if(rep) {

+                INST_NAME("REP LODSW");

+                CBZx_NEXT(xRCX);

+                TBNZ_MARK2(xFlags, F_DF);

+                MARK;   // Part with DF==0

+                LDRH_S9_postindex(xRAX, xRSI, 2);

+                SUBx_U12(xRCX, xRCX, 1);

+                CBNZx_MARK(xRCX);

+                B_NEXT_nocond;

+                MARK2;  // Part with DF==1

+                LDRH_S9_postindex(xRAX, xRSI, -2);

+                SUBx_U12(xRCX, xRCX, 1);

+                CBNZx_MARK2(xRCX);

+                // done

+            } else {

+                INST_NAME("STOSW");

+                GETDIR(x3, 2);

+                LDRH_U12(xRAX, xRSI, 0);

+                ADDx_REG(xRSI, xRSI, x3);

+            }

+            break;

+

+        case 0xAF:

+            switch(rep) {

+            case 1:

+            case 2:

+                if(rep==1) {INST_NAME("REPNZ SCASW");} else {INST_NAME("REPZ SCASW");}

+                MAYSETFLAGS();

+                SETFLAGS(X_ALL, SF_SET_PENDING);

+                CBZx_NEXT(xRCX);

+                UXTHw(x1, xRAX);

+                TBNZ_MARK2(xFlags, F_DF);

+                MARK;   // Part with DF==0

+                LDRH_S9_postindex(x2, xRDI, 2);

+                SUBx_U12(xRCX, xRCX, 1);

+                CMPSw_REG(x1, x2);

+                B_MARK3((rep==1)?cEQ:cNE);

+                CBNZx_MARK(xRCX);

+                B_MARK3_nocond;

+                MARK2;  // Part with DF==1

+                LDRH_S9_postindex(x2, xRDI, -2);

+                SUBx_U12(xRCX, xRCX, 1);

+                CMPSw_REG(x1, x2);

+                B_MARK3((rep==1)?cEQ:cNE);

+                CBNZx_MARK2(xRCX);

+                MARK3;  // end

+                emit_cmp16(dyn, ninst, x1, x2, x3, x4, x5);

+                break;

+            default:

+                INST_NAME("SCASW");

+                SETFLAGS(X_ALL, SF_SET_PENDING);

+                GETDIR(x3, 2);

+                UXTHw(x1, xRAX);

+                LDRH_U12(x2, xRDI, 0);

+                ADDx_REG(xRDI, xRDI, x3);

+                emit_cmp16(dyn, ninst, x1, x2, x3, x4, x5);

+                break;

+            }

+            break;

+

         case 0xB8:

         case 0xB9:

         case 0xBA:

@@ -822,7 +1023,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
                     break;

             }

             break;

-            

+

         case 0xF0:

             return dynarec64_66F0(dyn, addr, ip, ninst, rex, rep, ok, need_epilog);

 

@@ -898,7 +1099,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
                     break;

             }

             break;

-            

+

         case 0xFF:

             nextop = F8;

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