about summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/dynarec/la64/dynarec_la64_64.c146
-rw-r--r--src/dynarec/la64/dynarec_la64_660f.c21
-rw-r--r--src/dynarec/la64/dynarec_la64_f20f.c8
-rw-r--r--src/dynarec/la64/dynarec_la64_helper.c4
-rw-r--r--src/dynarec/la64/dynarec_la64_helper.h13
-rw-r--r--src/dynarec/la64/la64_emitter.h8
6 files changed, 197 insertions, 3 deletions
diff --git a/src/dynarec/la64/dynarec_la64_64.c b/src/dynarec/la64/dynarec_la64_64.c
index 46f0ef06..152db7b3 100644
--- a/src/dynarec/la64/dynarec_la64_64.c
+++ b/src/dynarec/la64/dynarec_la64_64.c
@@ -79,6 +79,152 @@ uintptr_t dynarec64_64(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
             GETEDO(x4, 0);
             emit_xor32(dyn, ninst, rex, gd, ed, x3, x4);
             break;
+        case 0x81:
+        case 0x83:
+            nextop = F8;
+            grab_segdata(dyn, addr, ninst, x6, seg);
+            switch ((nextop >> 3) & 7) {
+                case 0:
+                    if (opcode == 0x81) {
+                        INST_NAME("ADD Ed, Id");
+                    } else {
+                        INST_NAME("ADD Ed, Ib");
+                    }
+                    SETFLAGS(X_ALL, SF_SET_PENDING);
+                    GETEDO(x6, (opcode == 0x81) ? 4 : 1);
+                    if (opcode == 0x81)
+                        i64 = F32S;
+                    else
+                        i64 = F8S;
+                    emit_add32c(dyn, ninst, rex, ed, i64, x3, x4, x5, xMASK);
+                    IFXA (X_CF, !la64_lbt)
+                        REGENERATE_MASK(); // use xMASK as a scratch
+                    WBACKO(x6);
+                    break;
+                case 1:
+                    if (opcode == 0x81) {
+                        INST_NAME("OR Ed, Id");
+                    } else {
+                        INST_NAME("OR Ed, Ib");
+                    }
+                    SETFLAGS(X_ALL, SF_SET_PENDING);
+                    GETEDO(x6, (opcode == 0x81) ? 4 : 1);
+                    if (opcode == 0x81)
+                        i64 = F32S;
+                    else
+                        i64 = F8S;
+                    emit_or32c(dyn, ninst, rex, ed, i64, x3, x4);
+                    WBACKO(x6);
+                    break;
+                case 2:
+                    if (opcode == 0x81) {
+                        INST_NAME("ADC Ed, Id");
+                    } else {
+                        INST_NAME("ADC Ed, Ib");
+                    }
+                    READFLAGS(X_CF);
+                    SETFLAGS(X_ALL, SF_SET_PENDING);
+                    GETEDO(x6, (opcode == 0x81) ? 4 : 1);
+                    if (opcode == 0x81)
+                        i64 = F32S;
+                    else
+                        i64 = F8S;
+                    MOV64xw(x5, i64);
+                    IFXA (X_ALL, !la64_lbt)
+                        ST_D(x6, xEmu, offsetof(x64emu_t, scratch));
+                    emit_adc32(dyn, ninst, rex, ed, x5, x3, x4, x6, xMASK);
+                    IFXA (X_ALL, !la64_lbt) {
+                        LD_D(x6, xEmu, offsetof(x64emu_t, scratch));
+                        REGENERATE_MASK(); // use xMASK as a scratch
+                    }
+                    WBACKO(x6);
+                    break;
+                case 3:
+                    if (opcode == 0x81) {
+                        INST_NAME("SBB Ed, Id");
+                    } else {
+                        INST_NAME("SBB Ed, Ib");
+                    }
+                    READFLAGS(X_CF);
+                    SETFLAGS(X_ALL, SF_SET_PENDING);
+                    GETEDO(x6, (opcode == 0x81) ? 4 : 1);
+                    if (opcode == 0x81)
+                        i64 = F32S;
+                    else
+                        i64 = F8S;
+                    MOV64xw(x5, i64);
+                    emit_sbb32(dyn, ninst, rex, ed, x5, x3, x4, xMASK);
+                    IFXA (X_CF, !la64_lbt)
+                        REGENERATE_MASK(); // use xMASK as a scratch
+                    WBACKO(x6);
+                    break;
+                case 4:
+                    if (opcode == 0x81) {
+                        INST_NAME("AND Ed, Id");
+                    } else {
+                        INST_NAME("AND Ed, Ib");
+                    }
+                    SETFLAGS(X_ALL, SF_SET_PENDING);
+                    GETEDO(x6, (opcode == 0x81) ? 4 : 1);
+                    if (opcode == 0x81)
+                        i64 = F32S;
+                    else
+                        i64 = F8S;
+                    emit_and32c(dyn, ninst, rex, ed, i64, x3, x4);
+                    WBACKO(x6);
+                    break;
+                case 5:
+                    if (opcode == 0x81) {
+                        INST_NAME("SUB Ed, Id");
+                    } else {
+                        INST_NAME("SUB Ed, Ib");
+                    }
+                    SETFLAGS(X_ALL, SF_SET_PENDING);
+                    GETEDO(x6, (opcode == 0x81) ? 4 : 1);
+                    if (opcode == 0x81)
+                        i64 = F32S;
+                    else
+                        i64 = F8S;
+                    emit_sub32c(dyn, ninst, rex, ed, i64, x3, x4, x5, xMASK);
+                    IFXA (X_CF, !la64_lbt)
+                        REGENERATE_MASK(); // use xMASK as a scratch
+                    WBACKO(x6);
+                    break;
+                case 6:
+                    if (opcode == 0x81) {
+                        INST_NAME("XOR Ed, Id");
+                    } else {
+                        INST_NAME("XOR Ed, Ib");
+                    }
+                    SETFLAGS(X_ALL, SF_SET_PENDING);
+                    GETEDO(x6, (opcode == 0x81) ? 4 : 1);
+                    if (opcode == 0x81)
+                        i64 = F32S;
+                    else
+                        i64 = F8S;
+                    emit_xor32c(dyn, ninst, rex, ed, i64, x3, x4);
+                    WBACKO(x6);
+                    break;
+                case 7:
+                    if (opcode == 0x81) {
+                        INST_NAME("CMP Ed, Id");
+                    } else {
+                        INST_NAME("CMP Ed, Ib");
+                    }
+                    SETFLAGS(X_ALL, SF_SET_PENDING);
+                    GETEDO(x6, (opcode == 0x81) ? 4 : 1);
+                    if (opcode == 0x81)
+                        i64 = F32S;
+                    else
+                        i64 = F8S;
+                    if (i64) {
+                        MOV64xw(x2, i64);
+                        emit_cmp32(dyn, ninst, rex, ed, x2, x3, x4, x5, x6);
+                    } else
+                        emit_cmp32_0(dyn, ninst, rex, ed, x3, x4);
+                    break;
+            }
+            break;
         case 0x89:
             INST_NAME("MOV Seg:Ed, Gd");
             grab_segdata(dyn, addr, ninst, x4, seg);
diff --git a/src/dynarec/la64/dynarec_la64_660f.c b/src/dynarec/la64/dynarec_la64_660f.c
index 6f2b2490..08fbde4e 100644
--- a/src/dynarec/la64/dynarec_la64_660f.c
+++ b/src/dynarec/la64/dynarec_la64_660f.c
@@ -51,6 +51,20 @@ uintptr_t dynarec64_660F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int
     MAYUSE(j64);
 
     switch (opcode) {
+        case 0x11:
+            INST_NAME("MOVUPD Ex,Gx");
+            nextop = F8;
+            GETG;
+            v0 = sse_get_reg(dyn, ninst, x1, gd, 0);
+            if (MODREG) {
+                v1 = sse_get_reg_empty(dyn, ninst, x1, (nextop & 7) + (rex.b << 3));
+                VOR_V(v1, v0, v0);
+            } else {
+                addr = geted(dyn, addr, ninst, nextop, &ed, x2, x3, &fixedaddress, rex, NULL, 1, 0);
+                VST(v0, ed, fixedaddress);
+                SMWRITE2();
+            }
+            break;
         case 0x12:
             INST_NAME("MOVLPD Gx, Eq");
             nextop = F8;
@@ -915,6 +929,13 @@ uintptr_t dynarec64_660F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int
                 VXOR_V(q0, q0, q1);
             }
             break;
+        case 0xF4:
+            INST_NAME("PMULUDQ Gx,Ex");
+            nextop = F8;
+            GETGX(v0, 1);
+            GETEX(v1, 0, 0);
+            VMULWEV_D_WU(v0, v0, v1);
+            break;
         case 0xF8:
             INST_NAME("PSUBB Gx,Ex");
             nextop = F8;
diff --git a/src/dynarec/la64/dynarec_la64_f20f.c b/src/dynarec/la64/dynarec_la64_f20f.c
index 6d0a5107..7c14361d 100644
--- a/src/dynarec/la64/dynarec_la64_f20f.c
+++ b/src/dynarec/la64/dynarec_la64_f20f.c
@@ -257,6 +257,14 @@ uintptr_t dynarec64_F20F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int
             VEXTRINS_D(v0, v1, 0);
             MARK2;
             break;
+        case 0x70:
+            INST_NAME("PSHUFLW Gx, Ex, Ib");
+            nextop = F8;
+            GETEX(v1, 0, 1);
+            GETGX(v0, 1);
+            u8 = F8;
+            VSHUF4I_H(v0, v1, u8);
+            break;
         case 0xC2:
             INST_NAME("CMPSD Gx, Ex, Ib");
             nextop = F8;
diff --git a/src/dynarec/la64/dynarec_la64_helper.c b/src/dynarec/la64/dynarec_la64_helper.c
index f6b6a72e..5c0b3879 100644
--- a/src/dynarec/la64/dynarec_la64_helper.c
+++ b/src/dynarec/la64/dynarec_la64_helper.c
@@ -685,9 +685,7 @@ void call_c(dynarec_la64_t* dyn, int ninst, void* fnc, int reg, int ret, int sav
             LD_D(xRIP, xEmu, offsetof(x64emu_t, ip));
 #undef GO
     }
-    // regenerate mask
-    ADDI_W(xMASK, xZR, -1);
-    LU32I_D(xMASK, 0);
+    REGENERATE_MASK();
 
     fpu_popcache(dyn, ninst, reg, 0);
     if (saveflags) {
diff --git a/src/dynarec/la64/dynarec_la64_helper.h b/src/dynarec/la64/dynarec_la64_helper.h
index def57335..060917ce 100644
--- a/src/dynarec/la64/dynarec_la64_helper.h
+++ b/src/dynarec/la64/dynarec_la64_helper.h
@@ -202,6 +202,13 @@
             ST_W(ed, wback, fixedaddress); \
         SMWRITE();                         \
     }
+
+#define WBACKO(O)            \
+    if (wback) {             \
+        SDXxw(ed, wback, O); \
+        SMWRITE2();          \
+    }
+
 // GETSEW will use i for ed, and can use r3 for wback. This is the Signed version
 #define GETSEW(i, D)                                                                           \
     if (MODREG) {                                                                              \
@@ -1106,6 +1113,12 @@ uintptr_t dynarec64_F20F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int
         }                                  \
     } while (0)
 
+#define REGENERATE_MASK()       \
+    do {                        \
+        ADDI_W(xMASK, xZR, -1); \
+        LU32I_D(xMASK, 0);      \
+    } while (0)
+
 #define PURGE_YMM()    /* TODO */
 
 #endif //__DYNAREC_LA64_HELPER_H__
\ No newline at end of file
diff --git a/src/dynarec/la64/la64_emitter.h b/src/dynarec/la64/la64_emitter.h
index e9756faf..c912f666 100644
--- a/src/dynarec/la64/la64_emitter.h
+++ b/src/dynarec/la64/la64_emitter.h
@@ -2059,6 +2059,14 @@ LSX instruction starts with V, LASX instruction starts with XV.
             ST_W(rd, rj, imm12); \
     } while (0)
 
+#define SDXxw(rd, rj, rk)      \
+    do {                       \
+        if (rex.w)             \
+            STX_D(rd, rj, rk); \
+        else                   \
+            STX_W(rd, rj, rk); \
+    } while (0)
+
 #define SDz(rd, rj, imm12)       \
     do {                         \
         if (rex.is32bits)        \