about summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
authorCorteX <30485844+Seas0@users.noreply.github.com>2022-01-07 16:52:54 +0800
committerGitHub <noreply@github.com>2022-01-07 16:52:54 +0800
commitf5d06338c73429f945881cf4e89920c5f2ca56c2 (patch)
tree77e7a3c57bda249e0a28fc2325bfe8240a3117f5 /src
parent42ab23a8332aaeee4e4a47e2608fba09833b46be (diff)
parente249a33d3e038f0e3c17f2f6c3eb5b8d7a21a2c3 (diff)
downloadbox64-f5d06338c73429f945881cf4e89920c5f2ca56c2.tar.gz
box64-f5d06338c73429f945881cf4e89920c5f2ca56c2.zip
Merge branch 'ptitSeb:main' into main
Diffstat (limited to 'src')
-rwxr-xr-xsrc/dynarec/arm64_emitter.h9
-rwxr-xr-xsrc/dynarec/arm64_printer.c15
-rwxr-xr-xsrc/dynarec/dynarec_arm64_00.c14
-rwxr-xr-xsrc/dynarec/dynarec_arm64_660f.c39
-rw-r--r--src/emu/x64run0f.c54
-rw-r--r--src/emu/x64runf0.c114
6 files changed, 160 insertions, 85 deletions
diff --git a/src/dynarec/arm64_emitter.h b/src/dynarec/arm64_emitter.h
index a063c958..b06aa319 100755
--- a/src/dynarec/arm64_emitter.h
+++ b/src/dynarec/arm64_emitter.h
@@ -1315,6 +1315,15 @@
 #define VUZP1Q_64(Rt, Rn, Rm)       EMIT(UZP_gen(1, 0b11, Rm, 0, Rn, Rt))
 #define VUZP2Q_64(Rt, Rn, Rm)       EMIT(UZP_gen(1, 0b11, Rm, 1, Rn, Rt))
 
+#define DUP_gen(Q, imm5, Rn, Rd)    ((Q)<<30 | 0b01110000<<21 | (imm5)<<16 | 1<<10 | (Rn)<<5 | (Rd))
+#define VDUP_8(Vd, Vn, idx)         EMIT(DUP_gen(0, ((idx)<<1|1), Vn, Vd))
+#define VDUPQ_8(Vd, Vn, idx)        EMIT(DUP_gen(1, ((idx)<<1|1), Vn, Vd))
+#define VDUP_16(Vd, Vn, idx)        EMIT(DUP_gen(0, ((idx)<<2|0b10), Vn, Vd))
+#define VDUPQ_16(Vd, Vn, idx)       EMIT(DUP_gen(1, ((idx)<<2|0b10), Vn, Vd))
+#define VDUP_32(Vd, Vn, idx)        EMIT(DUP_gen(0, ((idx)<<3|0b100), Vn, Vd))
+#define VDUPQ_32(Vd, Vn, idx)       EMIT(DUP_gen(1, ((idx)<<3|0b100), Vn, Vd))
+#define VDUPQ_64(Vd, Vn, idx)       EMIT(DUP_gen(1, ((idx)<<4|0b1000), Vn, Vd))
+
 // TBL
 #define TBL_gen(Q, Rm, len, op, Rn, Rd) ((Q)<<30 | 0b001110<<24 | (Rm)<<16 | (len)<<13 | (op)<<12 | (Rn)<<5 | (Rd))
 //Use Rm[] to pick from Rn element and store in Rd. Out-of-range element gets 0
diff --git a/src/dynarec/arm64_printer.c b/src/dynarec/arm64_printer.c
index c19b48ea..7849db23 100755
--- a/src/dynarec/arm64_printer.c
+++ b/src/dynarec/arm64_printer.c
@@ -1311,6 +1311,21 @@ const char* arm64_print(uint32_t opcode, uintptr_t addr)
             snprintf(buff, sizeof(buff), "%cSHLL%s V%d.%s, V%d.%s, #%d", a.U?'U':'S', a.Q?"2":"", Rd, Va, Rn, Vd, sh);

         return buff;

     }

+

+    // DUP

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

+        const char* Y[] = {"8B", "16B", "4H", "8H", "2S", "4S", "2D", "??"};

+        const char* Z[] = {"B", "H", "S", "D"};

+        int sz = 3;

+        if((imm&0b0001)==0b0001) sz=0;

+        else if((imm&0b0011)==0b0010) sz=1;

+        else if((imm&0b0111)==0b0100) sz=2;

+        int sh=imm - (1<<sz);

+        const char* Vd = Y[(sz<<1)|a.Q];

+        const char* Vn = Z[sz];

+        snprintf(buff, sizeof(buff), "DUP V%d.%s, V%d.%s[%d]", Rd, Vd, Rn, Vn, sh);

+        return buff;

+    }

     

     // AES

     if(isMask(opcode, "0100111000101000010f10nnnnnddddd", &a)) {

diff --git a/src/dynarec/dynarec_arm64_00.c b/src/dynarec/dynarec_arm64_00.c
index 77451bb1..fa6a58a1 100755
--- a/src/dynarec/dynarec_arm64_00.c
+++ b/src/dynarec/dynarec_arm64_00.c
@@ -1011,7 +1011,19 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
                 }
             }
             break;
-
+        case 0x8E:
+            INST_NAME("MOV Seg,Ew");
+            nextop = F8;
+            if((nextop&0xC0)==0xC0) {
+                ed = xRAX+(nextop&7)+(rex.b<<3);
+            } else {
+                addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0xfff<<2, 0, rex, 0, 0);
+                LDRH_U12(x1, ed, fixedaddress);
+                ed = x1;
+            }
+            STRw_U12(ed, xEmu, offsetof(x64emu_t, segs[(nextop&0x38)>>3]));
+            STRw_U12(wZR, xEmu, offsetof(x64emu_t, segs_serial[(nextop&0x38)>>3]));
+            break;
         case 0x8F:
             INST_NAME("POP Ed");
             nextop = F8;
diff --git a/src/dynarec/dynarec_arm64_660f.c b/src/dynarec/dynarec_arm64_660f.c
index 39467aa5..b1640609 100755
--- a/src/dynarec/dynarec_arm64_660f.c
+++ b/src/dynarec/dynarec_arm64_660f.c
@@ -236,6 +236,20 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
                     VANDQ(d0, d0, q1);  // mask the index

                     VTBLQ1_8(q0, q0, d0);

                     break;

+                case 0x01:

+                    INST_NAME("PHADDW Gx, Ex");

+                    nextop = F8;

+                    GETGX(q0);

+                    GETEX(q1, 0);

+                    VADDPQ_16(q0, q0, q1);

+                    break;

+                case 0x02:

+                    INST_NAME("PHADDD Gx, Ex");

+                    nextop = F8;

+                    GETGX(q0);

+                    GETEX(q1, 0);

+                    VADDPQ_32(q0, q0, q1);

+                    break;

 

                 case 0x04:

                     INST_NAME("PMADDUBSW Gx,Ex");

@@ -1507,17 +1521,24 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
             }

             break;

 

-

+        case 0xD1:

+            INST_NAME("PSRLW Gx,Ex");

+            nextop = F8;

+            GETGX(q0);

+            GETEX(q1, 0);

+            v0 = fpu_get_scratch(dyn);

+            VDUPQ_16(v0, q1, 0);

+            NEGQ_16(v0, v0);        // neg, because SHR

+            USHLQ_16(q0, q0, v0);   // SHR x8

+            break;

         case 0xD2:

             INST_NAME("PSRLD Gx,Ex");

             nextop = F8;

             GETGX(q0);

             GETEX(q1, 0);

             v0 = fpu_get_scratch(dyn);

-            SQSHRN_32(v0, q1, 0);   // S64x1->S32x1

-            VMOVeS(v0, 1, v0, 0);   // S32x1->S32x2

-            NEG_32(v0, v0);         // neg, because SHR

-            VMOVeD(v0, 1, v0, 0);   // S32x2->S32x4

+            VDUPQ_32(v0, q1, 0);

+            NEGQ_32(v0, v0);        // neg, because SHR

             USHLQ_32(q0, q0, v0);   // SHR x4

             break;

         case 0xD3:

@@ -1673,7 +1694,13 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
             VMOVeD(v0, 1, v0, 0);

             SSHLQ_32(q0, q0, v0);

             break;

-

+        case 0xE3:

+            INST_NAME("PAVGW Gx,Ex");

+            nextop = F8;

+            GETGX(v0);

+            GETEX(q0, 0);

+            URHADDQ_16(v0, v0, q0);

+            break;

         case 0xE4:

             INST_NAME("PMULHUW Gx,Ex");

             nextop = F8;

diff --git a/src/emu/x64run0f.c b/src/emu/x64run0f.c
index 977e6c73..e934c6c2 100644
--- a/src/emu/x64run0f.c
+++ b/src/emu/x64run0f.c
@@ -1221,30 +1221,36 @@ int Run0F(x64emu_t *emu, rex_t rex)
             CHECK_FLAGS(emu);

             nextop = F8;

             GETED(0);

-            if(rex.w) {

-                tmp64u = ED->q[0];

-                tmp64u2= ED->q[1];

-                if(R_RAX == tmp64u && R_RDX == tmp64u2) {

-                    SET_FLAG(F_ZF);

-                    ED->q[0] = R_EBX;

-                    ED->q[1] = R_ECX;

-                } else {

-                    CLEAR_FLAG(F_ZF);

-                    R_RAX = tmp64u;

-                    R_RDX = tmp64u2;

-                }

-            } else {

-                tmp32u = ED->dword[0];

-                tmp32u2= ED->dword[1];

-                if(R_EAX == tmp32u && R_EDX == tmp32u2) {

-                    SET_FLAG(F_ZF);

-                    ED->dword[0] = R_EBX;

-                    ED->dword[1] = R_ECX;

-                } else {

-                    CLEAR_FLAG(F_ZF);

-                    R_RAX = tmp32u;

-                    R_RDX = tmp32u2;

-                }

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

+                case 1:

+                    if(rex.w) {

+                        tmp64u = ED->q[0];

+                        tmp64u2= ED->q[1];

+                        if(R_RAX == tmp64u && R_RDX == tmp64u2) {

+                            SET_FLAG(F_ZF);

+                            ED->q[0] = R_EBX;

+                            ED->q[1] = R_ECX;

+                        } else {

+                            CLEAR_FLAG(F_ZF);

+                            R_RAX = tmp64u;

+                            R_RDX = tmp64u2;

+                        }

+                    } else {

+                        tmp32u = ED->dword[0];

+                        tmp32u2= ED->dword[1];

+                        if(R_EAX == tmp32u && R_EDX == tmp32u2) {

+                            SET_FLAG(F_ZF);

+                            ED->dword[0] = R_EBX;

+                            ED->dword[1] = R_ECX;

+                        } else {

+                            CLEAR_FLAG(F_ZF);

+                            R_RAX = tmp32u;

+                            R_RDX = tmp32u2;

+                        }

+                    }

+                    break;

+                default:

+                    return 1;

             }

             break;

         case 0xC8:

diff --git a/src/emu/x64runf0.c b/src/emu/x64runf0.c
index f3c0fb10..041c147a 100644
--- a/src/emu/x64runf0.c
+++ b/src/emu/x64runf0.c
@@ -634,66 +634,72 @@ int RunF0(x64emu_t *emu, rex_t rex)
                     break;

 

                 case 0xC7:                      /* CMPXCHG8B Gq */

-                    CHECK_FLAGS(emu);

                     nextop = F8;

                     GETED(0);

-                    GETGD;

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

+                        case 1:

+                            CHECK_FLAGS(emu);

+                            GETGD;

 #ifdef DYNAREC

-                    if(rex.w)

-                        do {

-                            arm64_lock_read_dq(&tmp64u, &tmp64u2, ED);

-                            if(R_RAX == tmp64u && R_RDX == tmp64u2) {

-                                SET_FLAG(F_ZF);

-                                tmp32s = arm64_lock_write_dq(R_RBX, R_RCX, ED);

-                            } else {

-                                CLEAR_FLAG(F_ZF);

-                                R_RAX = tmp64u;

-                                R_RDX = tmp64u2;

-                                tmp32s = 0;

-                            }

-                        } while(tmp32s);

-                    else

-                        do {

-                            tmp64u = arm64_lock_read_dd(ED);

-                            if((R_EAX == (tmp64u&0xffffffff)) && (R_EDX == ((tmp64u>>32)&0xffffffff))) {

-                                SET_FLAG(F_ZF);

-                                tmp32s = arm64_lock_write_dd(ED, R_EBX|(((uint64_t)R_ECX)<<32));

+                            if(rex.w)

+                                do {

+                                    arm64_lock_read_dq(&tmp64u, &tmp64u2, ED);

+                                    if(R_RAX == tmp64u && R_RDX == tmp64u2) {

+                                        SET_FLAG(F_ZF);

+                                        tmp32s = arm64_lock_write_dq(R_RBX, R_RCX, ED);

+                                    } else {

+                                        CLEAR_FLAG(F_ZF);

+                                        R_RAX = tmp64u;

+                                        R_RDX = tmp64u2;

+                                        tmp32s = 0;

+                                    }

+                                } while(tmp32s);

+                            else

+                                do {

+                                    tmp64u = arm64_lock_read_dd(ED);

+                                    if((R_EAX == (tmp64u&0xffffffff)) && (R_EDX == ((tmp64u>>32)&0xffffffff))) {

+                                        SET_FLAG(F_ZF);

+                                        tmp32s = arm64_lock_write_dd(ED, R_EBX|(((uint64_t)R_ECX)<<32));

+                                    } else {

+                                        CLEAR_FLAG(F_ZF);

+                                        R_RAX = tmp64u&0xffffffff;

+                                        R_RDX = (tmp64u>>32)&0xffffffff;

+                                        tmp32s = 0;

+                                    }

+                                } while(tmp32s);

+#else

+                            pthread_mutex_lock(&emu->context->mutex_lock);

+                            if(rex.w) {

+                                tmp64u = ED->q[0];

+                                tmp64u2= ED->q[1];

+                                if(R_RAX == tmp64u && R_RDX == tmp64u2) {

+                                    SET_FLAG(F_ZF);

+                                    ED->q[0] = R_RBX;

+                                    ED->q[1] = R_RCX;

+                                } else {

+                                    CLEAR_FLAG(F_ZF);

+                                    R_RAX = tmp64u;

+                                    R_RDX = tmp64u2;

+                                }

                             } else {

-                                CLEAR_FLAG(F_ZF);

-                                R_RAX = tmp64u&0xffffffff;

-                                R_RDX = (tmp64u>>32)&0xffffffff;

-                                tmp32s = 0;

+                                tmp32u = ED->dword[0];

+                                tmp32u2= ED->dword[1];

+                                if(R_EAX == tmp32u && R_EDX == tmp32u2) {

+                                    SET_FLAG(F_ZF);

+                                    ED->dword[0] = R_EBX;

+                                    ED->dword[1] = R_ECX;

+                                } else {

+                                    CLEAR_FLAG(F_ZF);

+                                    R_RAX = tmp32u;

+                                    R_RDX = tmp32u2;

+                                }

                             }

-                        } while(tmp32s);

-#else

-                    pthread_mutex_lock(&emu->context->mutex_lock);

-                    if(rex.w) {

-                        tmp64u = ED->q[0];

-                        tmp64u2= ED->q[1];

-                        if(R_RAX == tmp64u && R_RDX == tmp64u2) {

-                            SET_FLAG(F_ZF);

-                            ED->q[0] = R_RBX;

-                            ED->q[1] = R_RCX;

-                        } else {

-                            CLEAR_FLAG(F_ZF);

-                            R_RAX = tmp64u;

-                            R_RDX = tmp64u2;

-                        }

-                    } else {

-                        tmp32u = ED->dword[0];

-                        tmp32u2= ED->dword[1];

-                        if(R_EAX == tmp32u && R_EDX == tmp32u2) {

-                            SET_FLAG(F_ZF);

-                            ED->dword[0] = R_EBX;

-                            ED->dword[1] = R_ECX;

-                        } else {

-                            CLEAR_FLAG(F_ZF);

-                            R_RAX = tmp32u;

-                            R_RDX = tmp32u2;

-                        }

-                    }

-                    pthread_mutex_unlock(&emu->context->mutex_lock);

+                            pthread_mutex_unlock(&emu->context->mutex_lock);

 #endif

+                            break;

+                        default:

+                            return 1;

+                    }

                     break;

 

             default: