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_avx_0f.c72
-rw-r--r--src/dynarec/la64/dynarec_la64_avx_66_0f.c93
-rw-r--r--src/dynarec/la64/dynarec_la64_avx_f2_0f.c98
-rw-r--r--src/dynarec/la64/dynarec_la64_avx_f3_0f.c76
-rw-r--r--src/dynarec/la64/la64_emitter.h46
5 files changed, 385 insertions, 0 deletions
diff --git a/src/dynarec/la64/dynarec_la64_avx_0f.c b/src/dynarec/la64/dynarec_la64_avx_0f.c
index 3a9c9822..01ae9f5b 100644
--- a/src/dynarec/la64/dynarec_la64_avx_0f.c
+++ b/src/dynarec/la64/dynarec_la64_avx_0f.c
@@ -269,6 +269,78 @@ uintptr_t dynarec64_AVX_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, in
             GETGY_empty_VYEY_xy(v0, v1, v2, 0);
             VXOR_Vxy(v0, v1, v2);
             break;
+        case 0x58:
+            INST_NAME("VADDPS Gx, Vx, Ex");
+            nextop = F8;
+            GETGY_empty_VYEY_xy(v0, v1, v2, 0);
+            if (!BOX64ENV(dynarec_fastnan)) {
+                d0 = fpu_get_scratch(dyn);
+                d1 = fpu_get_scratch(dyn);
+                VFCMPxy(S, d0, v1, v2, cUN);
+            }
+            VFADDxy(S, v0, v1, v2);
+            if (!BOX64ENV(dynarec_fastnan)) {
+                VFCMPxy(S, d1, v0, v0, cUN);
+                VANDN_Vxy(d0, d0, d1);
+                VLDIxy(d1, (0b010 << 9) | 0b1111111100);
+                VSLLIxy(W, d1, d1, 20); // broadcast 0xFFC00000
+                VBITSEL_Vxy(v0, v0, d1, d0);
+            }
+            break;
+        case 0x59:
+            INST_NAME("VMULPS Gx, Vx, Ex");
+            nextop = F8;
+            GETGY_empty_VYEY_xy(v0, v1, v2, 0);
+            if (!BOX64ENV(dynarec_fastnan)) {
+                d0 = fpu_get_scratch(dyn);
+                d1 = fpu_get_scratch(dyn);
+                VFCMPxy(S, d0, v1, v2, cUN);
+            }
+            VFMULxy(S, v0, v1, v2);
+            if (!BOX64ENV(dynarec_fastnan)) {
+                VFCMPxy(S, d1, v0, v0, cUN);
+                VANDN_Vxy(d0, d0, d1);
+                VLDIxy(d1, (0b010 << 9) | 0b1111111100);
+                VSLLIxy(W, d1, d1, 20); // broadcast 0xFFC00000
+                VBITSEL_Vxy(v0, v0, d1, d0);
+            }
+            break;
+        case 0x5C:
+            INST_NAME("VSUBPS Gx, Vx, Ex");
+            nextop = F8;
+            GETGY_empty_VYEY_xy(v0, v1, v2, 0);
+            if (!BOX64ENV(dynarec_fastnan)) {
+                d0 = fpu_get_scratch(dyn);
+                d1 = fpu_get_scratch(dyn);
+                VFCMPxy(S, d0, v1, v2, cUN);
+            }
+            VFSUBxy(S, v0, v1, v2);
+            if (!BOX64ENV(dynarec_fastnan)) {
+                VFCMPxy(S, d1, v0, v0, cUN);
+                VANDN_Vxy(d0, d0, d1);
+                VLDIxy(d1, (0b010 << 9) | 0b1111111100);
+                VSLLIxy(W, d1, d1, 20); // broadcast 0xFFC00000
+                VBITSEL_Vxy(v0, v0, d1, d0);
+            }
+            break;
+        case 0x5E:
+            INST_NAME("VDIVPS Gx, Vx, Ex");
+            nextop = F8;
+            GETGY_empty_VYEY_xy(v0, v1, v2, 0);
+            if (!BOX64ENV(dynarec_fastnan)) {
+                d0 = fpu_get_scratch(dyn);
+                d1 = fpu_get_scratch(dyn);
+                VFCMPxy(S, d0, v1, v2, cUN);
+            }
+            VFDIVxy(S, v0, v1, v2);
+            if (!BOX64ENV(dynarec_fastnan)) {
+                VFCMPxy(S, d1, v0, v0, cUN);
+                VANDN_Vxy(d0, d0, d1);
+                VLDIxy(d1, (0b010 << 9) | 0b1111111100);
+                VSLLIxy(W, d1, d1, 20); // broadcast 0xFFC00000
+                VBITSEL_Vxy(v0, v0, d1, d0);
+            }
+            break;
         case 0x77:
             if (!vex.l) {
                 INST_NAME("VZEROUPPER");
diff --git a/src/dynarec/la64/dynarec_la64_avx_66_0f.c b/src/dynarec/la64/dynarec_la64_avx_66_0f.c
index 13e9a359..d7e2ecf5 100644
--- a/src/dynarec/la64/dynarec_la64_avx_66_0f.c
+++ b/src/dynarec/la64/dynarec_la64_avx_66_0f.c
@@ -263,6 +263,78 @@ uintptr_t dynarec64_AVX_66_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip,
             GETGY_empty_VYEY_xy(v0, v1, v2, 0);
             VXOR_Vxy(v0, v1, v2);
             break;
+        case 0x58:
+            INST_NAME("VADDPD Gx, Vx, Ex");
+            nextop = F8;
+            GETGY_empty_VYEY_xy(v0, v1, v2, 0);
+            if (!BOX64ENV(dynarec_fastnan)) {
+                d0 = fpu_get_scratch(dyn);
+                d1 = fpu_get_scratch(dyn);
+                VFCMPxy(D, d0, v1, v2, cUN);
+            }
+            VFADDxy(D, v0, v1, v2);
+            if (!BOX64ENV(dynarec_fastnan)) {
+                VFCMPxy(D, d1, v0, v0, cUN);
+                VANDN_Vxy(d0, d0, d1);
+                VLDIxy(d1, (0b011 << 9) | 0b111111000);
+                VSLLIxy(D, d1, d1, 48); // broadcast 0xfff8000000000000
+                VBITSEL_Vxy(v0, v0, d1, d0);
+            }
+            break;
+        case 0x59:
+            INST_NAME("VMULPD Gx, Vx, Ex");
+            nextop = F8;
+            GETGY_empty_VYEY_xy(v0, v1, v2, 0);
+            if (!BOX64ENV(dynarec_fastnan)) {
+                d0 = fpu_get_scratch(dyn);
+                d1 = fpu_get_scratch(dyn);
+                VFCMPxy(D, d0, v1, v2, cUN);
+            }
+            VFMULxy(D, v0, v1, v2);
+            if (!BOX64ENV(dynarec_fastnan)) {
+                VFCMPxy(D, d1, v0, v0, cUN);
+                VANDN_Vxy(d0, d0, d1);
+                VLDIxy(d1, (0b011 << 9) | 0b111111000);
+                VSLLIxy(D, d1, d1, 48); // broadcast 0xfff8000000000000
+                VBITSEL_Vxy(v0, v0, d1, d0);
+            }
+            break;
+        case 0x5C:
+            INST_NAME("VSUBPD Gx, Vx, Ex");
+            nextop = F8;
+            GETGY_empty_VYEY_xy(v0, v1, v2, 0);
+            if (!BOX64ENV(dynarec_fastnan)) {
+                d0 = fpu_get_scratch(dyn);
+                d1 = fpu_get_scratch(dyn);
+                VFCMPxy(D, d0, v1, v2, cUN);
+            }
+            VFSUBxy(D, v0, v1, v2);
+            if (!BOX64ENV(dynarec_fastnan)) {
+                VFCMPxy(D, d1, v0, v0, cUN);
+                VANDN_Vxy(d0, d0, d1);
+                VLDIxy(d1, (0b011 << 9) | 0b111111000);
+                VSLLIxy(D, d1, d1, 48); // broadcast 0xfff8000000000000
+                VBITSEL_Vxy(v0, v0, d1, d0);
+            }
+            break;
+        case 0x5E:
+            INST_NAME("VDIVPD Gx, Vx, Ex");
+            nextop = F8;
+            GETGY_empty_VYEY_xy(v0, v1, v2, 0);
+            if (!BOX64ENV(dynarec_fastnan)) {
+                d0 = fpu_get_scratch(dyn);
+                d1 = fpu_get_scratch(dyn);
+                VFCMPxy(D, d0, v1, v2, cUN);
+            }
+            VFDIVxy(D, v0, v1, v2);
+            if (!BOX64ENV(dynarec_fastnan)) {
+                VFCMPxy(D, d1, v0, v0, cUN);
+                VANDN_Vxy(d0, d0, d1);
+                VLDIxy(d1, (0b011 << 9) | 0b111111000);
+                VSLLIxy(D, d1, d1, 48); // broadcast 0xfff8000000000000
+                VBITSEL_Vxy(v0, v0, d1, d0);
+            }
+            break;
         case 0x60:
             INST_NAME("VPUNPCKLBW Gx, Vx, Ex");
             nextop = F8;
@@ -599,6 +671,27 @@ uintptr_t dynarec64_AVX_66_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip,
                 VOR_V(v0, d0, d0);
             }
             break;
+        case 0xD0:
+            INST_NAME("VADDSUBPD Gx, Vx, Ex");
+            nextop = F8;
+            GETGY_empty_VYEY_xy(v0, v1, v2, 0);
+            if (!BOX64ENV(dynarec_fastnan)) {
+                d0 = fpu_get_scratch(dyn);
+                d1 = fpu_get_scratch(dyn);
+                VFCMPxy(D, d0, v1, v2, cUN);
+            }
+            q0 = fpu_get_scratch(dyn);
+            VFSUBxy(D, q0, v1, v2);
+            VFADDxy(D, v0, v1, v2);
+            VEXTRINSxy(D, v0, q0, 0);
+            if (!BOX64ENV(dynarec_fastnan)) {
+                VFCMPxy(D, d1, v0, v0, cUN);
+                VANDN_Vxy(d0, d0, d1);
+                VLDIxy(d1, (0b011 << 9) | 0b111111000);
+                VSLLIxy(D, d1, d1, 48); // broadcast 0xfff8000000000000
+                VBITSEL_Vxy(v0, v0, d1, d0);
+            }
+            break;
         case 0xD1:
             INST_NAME("VPSRLW Gx, Vx, Ex");
             nextop = F8;
diff --git a/src/dynarec/la64/dynarec_la64_avx_f2_0f.c b/src/dynarec/la64/dynarec_la64_avx_f2_0f.c
index 0b0eb1df..446ed244 100644
--- a/src/dynarec/la64/dynarec_la64_avx_f2_0f.c
+++ b/src/dynarec/la64/dynarec_la64_avx_f2_0f.c
@@ -116,6 +116,82 @@ uintptr_t dynarec64_AVX_F2_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip,
                 VREPLVE_D(q0, q1, 0);
             }
             break;
+        case 0x58:
+            INST_NAME("VADDSD Gx, Vx, Ex");
+            nextop = F8;
+            GETVYx(v1, 0);
+            GETEYSD(v2, 0, 0);
+            GETGYx_empty(v0);
+            d0 = fpu_get_scratch(dyn);
+            FADD_D(d0, v1, v2);
+            if (!BOX64ENV(dynarec_fastnan)) {
+                FCMP_D(fcc0, v1, v2, cUN);
+                BCNEZ_MARK(fcc0);
+                FCMP_D(fcc1, d0, d0, cOR);
+                BCNEZ_MARK(fcc1);
+                FNEG_D(d0, d0);
+            }
+            MARK;
+            VOR_V(v0, v1, v1);
+            VEXTRINS_D(v0, d0, 0);
+            break;
+        case 0x59:
+            INST_NAME("VMULSD Gx, Vx, Ex");
+            nextop = F8;
+            GETVYx(v1, 0);
+            GETEYSD(v2, 0, 0);
+            GETGYx_empty(v0);
+            d0 = fpu_get_scratch(dyn);
+            FMUL_D(d0, v1, v2);
+            if (!BOX64ENV(dynarec_fastnan)) {
+                FCMP_D(fcc0, v1, v2, cUN);
+                BCNEZ_MARK(fcc0);
+                FCMP_D(fcc1, d0, d0, cOR);
+                BCNEZ_MARK(fcc1);
+                FNEG_D(d0, d0);
+            }
+            MARK;
+            VOR_V(v0, v1, v1);
+            VEXTRINS_D(v0, d0, 0);
+            break;
+        case 0x5C:
+            INST_NAME("VSUBSD Gx, Vx, Ex");
+            nextop = F8;
+            GETVYx(v1, 0);
+            GETEYSD(v2, 0, 0);
+            GETGYx_empty(v0);
+            d0 = fpu_get_scratch(dyn);
+            FSUB_D(d0, v1, v2);
+            if (!BOX64ENV(dynarec_fastnan)) {
+                FCMP_D(fcc0, v1, v2, cUN);
+                BCNEZ_MARK(fcc0);
+                FCMP_D(fcc1, d0, d0, cOR);
+                BCNEZ_MARK(fcc1);
+                FNEG_D(d0, d0);
+            }
+            MARK;
+            VOR_V(v0, v1, v1);
+            VEXTRINS_D(v0, d0, 0);
+            break;
+        case 0x5E:
+            INST_NAME("VDIVSD Gx, Vx, Ex");
+            nextop = F8;
+            GETVYx(v1, 0);
+            GETEYSD(v2, 0, 0);
+            GETGYx_empty(v0);
+            d0 = fpu_get_scratch(dyn);
+            FDIV_D(d0, v1, v2);
+            if (!BOX64ENV(dynarec_fastnan)) {
+                FCMP_D(fcc0, v1, v2, cUN);
+                BCNEZ_MARK(fcc0);
+                FCMP_D(fcc1, d0, d0, cOR);
+                BCNEZ_MARK(fcc1);
+                FNEG_D(d0, d0);
+            }
+            MARK;
+            VOR_V(v0, v1, v1);
+            VEXTRINS_D(v0, d0, 0);
+            break;
         case 0x70:
             INST_NAME("VPSHUFLW Gx, Ex, Ib");
             nextop = F8;
@@ -130,6 +206,28 @@ uintptr_t dynarec64_AVX_F2_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip,
                 VEXTRINSxy(D, v0, d0, VEXTRINS_IMM_4_0(0, 0));
             }
             break;
+        case 0xD0:
+            INST_NAME("VADDSUBPS Gx, Vx, Ex");
+            nextop = F8;
+            GETGY_empty_VYEY_xy(v0, v1, v2, 0);
+            if (!BOX64ENV(dynarec_fastnan)) {
+                d0 = fpu_get_scratch(dyn);
+                d1 = fpu_get_scratch(dyn);
+                VFCMPxy(S, d0, v1, v2, cUN);
+            }
+            q0 = fpu_get_scratch(dyn);
+            VFSUBxy(S, q0, v1, v2);
+            VFADDxy(S, v0, v1, v2);
+            VEXTRINSxy(W, v0, q0, VEXTRINS_IMM_4_0(0, 0));
+            VEXTRINSxy(W, v0, q0, VEXTRINS_IMM_4_0(2, 2));
+            if (!BOX64ENV(dynarec_fastnan)) {
+                VFCMPxy(S, d1, v0, v0, cUN);
+                VANDN_Vxy(d0, d0, d1);
+                VLDIxy(d1, (0b010 << 9) | 0b1111111100);
+                VSLLIxy(W, d1, d1, 20); // broadcast 0xFFC00000
+                VBITSEL_Vxy(v0, v0, d1, d0);
+            }
+            break;
         case 0xF0:
             INST_NAME("VLDDQU Gx, Ex");
             nextop = F8;
diff --git a/src/dynarec/la64/dynarec_la64_avx_f3_0f.c b/src/dynarec/la64/dynarec_la64_avx_f3_0f.c
index b8332a4b..2e51ce90 100644
--- a/src/dynarec/la64/dynarec_la64_avx_f3_0f.c
+++ b/src/dynarec/la64/dynarec_la64_avx_f3_0f.c
@@ -100,6 +100,82 @@ uintptr_t dynarec64_AVX_F3_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip,
                 VPACKOD_W(q0, q1, q1);
             }
             break;
+        case 0x58:
+            INST_NAME("VADDSS Gx, Vx, Ex");
+            nextop = F8;
+            GETVYx(v1, 0);
+            GETEYSD(v2, 0, 0);
+            GETGYx_empty(v0);
+            d0 = fpu_get_scratch(dyn);
+            FADD_S(d0, v1, v2);
+            if (!BOX64ENV(dynarec_fastnan)) {
+                FCMP_S(fcc0, v1, v2, cUN);
+                BCNEZ_MARK(fcc0);
+                FCMP_S(fcc1, d0, d0, cOR);
+                BCNEZ_MARK(fcc1);
+                FNEG_S(d0, d0);
+            }
+            MARK;
+            VOR_V(v0, v1, v1);
+            VEXTRINS_W(v0, d0, 0);
+            break;
+        case 0x59:
+            INST_NAME("VMULSS Gx, Vx, Ex");
+            nextop = F8;
+            GETVYx(v1, 0);
+            GETEYSD(v2, 0, 0);
+            GETGYx_empty(v0);
+            d0 = fpu_get_scratch(dyn);
+            FMUL_S(d0, v1, v2);
+            if (!BOX64ENV(dynarec_fastnan)) {
+                FCMP_S(fcc0, v1, v2, cUN);
+                BCNEZ_MARK(fcc0);
+                FCMP_S(fcc1, d0, d0, cOR);
+                BCNEZ_MARK(fcc1);
+                FNEG_S(d0, d0);
+            }
+            MARK;
+            VOR_V(v0, v1, v1);
+            VEXTRINS_W(v0, d0, 0);
+            break;
+        case 0x5C:
+            INST_NAME("VSUBSS Gx, Vx, Ex");
+            nextop = F8;
+            GETVYx(v1, 0);
+            GETEYSD(v2, 0, 0);
+            GETGYx_empty(v0);
+            d0 = fpu_get_scratch(dyn);
+            FSUB_S(d0, v1, v2);
+            if (!BOX64ENV(dynarec_fastnan)) {
+                FCMP_S(fcc0, v1, v2, cUN);
+                BCNEZ_MARK(fcc0);
+                FCMP_S(fcc1, d0, d0, cOR);
+                BCNEZ_MARK(fcc1);
+                FNEG_S(d0, d0);
+            }
+            MARK;
+            VOR_V(v0, v1, v1);
+            VEXTRINS_W(v0, d0, 0);
+            break;
+        case 0x5E:
+            INST_NAME("VDIVSS Gx, Vx, Ex");
+            nextop = F8;
+            GETVYx(v1, 0);
+            GETEYSD(v2, 0, 0);
+            GETGYx_empty(v0);
+            d0 = fpu_get_scratch(dyn);
+            FDIV_S(d0, v1, v2);
+            if (!BOX64ENV(dynarec_fastnan)) {
+                FCMP_S(fcc0, v1, v2, cUN);
+                BCNEZ_MARK(fcc0);
+                FCMP_S(fcc1, d0, d0, cOR);
+                BCNEZ_MARK(fcc1);
+                FNEG_S(d0, d0);
+            }
+            MARK;
+            VOR_V(v0, v1, v1);
+            VEXTRINS_W(v0, d0, 0);
+            break;
         case 0x6F:
             INST_NAME("VMOVDQU Gx, Ex");
             nextop = F8;
diff --git a/src/dynarec/la64/la64_emitter.h b/src/dynarec/la64/la64_emitter.h
index 6fc25100..42899386 100644
--- a/src/dynarec/la64/la64_emitter.h
+++ b/src/dynarec/la64/la64_emitter.h
@@ -3152,4 +3152,50 @@ LSX instruction starts with V, LASX instruction starts with XV.
         }                             \
     } while (0)
 
+
+#define VFCMPxy(width, vd, vj, vk, cond)      \
+    do {                                      \
+        if (vex.l) {                          \
+            XVFCMP_##width(vd, vj, vk, cond); \
+        } else {                              \
+            VFCMP_##width(vd, vj, vk, cond);  \
+        }                                     \
+    } while (0)
+
+#define VFADDxy(width, vd, vj, vk)      \
+    do {                                \
+        if (vex.l) {                    \
+            XVFADD_##width(vd, vj, vk); \
+        } else {                        \
+            VFADD_##width(vd, vj, vk);  \
+        }                               \
+    } while (0)
+
+#define VFSUBxy(width, vd, vj, vk)      \
+    do {                                \
+        if (vex.l) {                    \
+            XVFSUB_##width(vd, vj, vk); \
+        } else {                        \
+            VFSUB_##width(vd, vj, vk);  \
+        }                               \
+    } while (0)
+
+#define VFMULxy(width, vd, vj, vk)      \
+    do {                                \
+        if (vex.l) {                    \
+            XVFMUL_##width(vd, vj, vk); \
+        } else {                        \
+            VFMUL_##width(vd, vj, vk);  \
+        }                               \
+    } while (0)
+
+#define VFDIVxy(width, vd, vj, vk)      \
+    do {                                \
+        if (vex.l) {                    \
+            XVFDIV_##width(vd, vj, vk); \
+        } else {                        \
+            VFDIV_##width(vd, vj, vk);  \
+        }                               \
+    } while (0)
+
 #endif //__ARM64_EMITTER_H__