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_66_0f38.c252
-rw-r--r--src/dynarec/la64/dynarec_la64_helper.h12
-rw-r--r--src/dynarec/la64/la64_emitter.h146
-rw-r--r--src/dynarec/la64/la64_printer.c64
4 files changed, 473 insertions, 1 deletions
diff --git a/src/dynarec/la64/dynarec_la64_avx_66_0f38.c b/src/dynarec/la64/dynarec_la64_avx_66_0f38.c
index 31246726..26808486 100644
--- a/src/dynarec/la64/dynarec_la64_avx_66_0f38.c
+++ b/src/dynarec/la64/dynarec_la64_avx_66_0f38.c
@@ -865,6 +865,258 @@ uintptr_t dynarec64_AVX_66_0F38(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t i
             }
             XVPERMI_Q(v0, v2, XVPERMI_IMM_4_0(1, 2));
             break;
+        case 0x96:
+            INST_NAME("VFMADDSUB132PS/D Gx, Vx, Ex");
+            nextop = F8;
+            GETGY_VYEY_xy(v0, v1, v2, 0);
+            q0 = fpu_get_scratch(dyn);
+            VFMADDxyxw(q0, v0, v2, v1);
+            VFMSUBxyxw(v0, v0, v2, v1);
+            if(rex.w){
+                VEXTRINSxy(D, v0, q0, VEXTRINS_IMM_4_0(1, 1));
+            } else {
+                VEXTRINSxy(W, v0, q0, VEXTRINS_IMM_4_0(1, 1));
+                VEXTRINSxy(W, v0, q0, VEXTRINS_IMM_4_0(3, 3));
+            }
+            break;
+        case 0x97:
+            INST_NAME("VFMSUBADD132PS/D Gx, Vx, Ex");
+            nextop = F8;
+            GETGY_VYEY_xy(v0, v1, v2, 0);
+            q0 = fpu_get_scratch(dyn);
+            VFMSUBxyxw(q0, v0, v2, v1);
+            VFMADDxyxw(v0, v0, v2, v1);
+            if(rex.w){
+                VEXTRINSxy(D, v0, q0, VEXTRINS_IMM_4_0(1, 1));
+            } else {
+                VEXTRINSxy(W, v0, q0, VEXTRINS_IMM_4_0(1, 1));
+                VEXTRINSxy(W, v0, q0, VEXTRINS_IMM_4_0(3, 3));
+            }
+            break;
+        case 0x98:
+            INST_NAME("VFMADD132PS/D Gx, Vx, Ex");
+            nextop = F8;
+            GETGY_VYEY_xy(v0, v1, v2, 0);
+            VFMADDxyxw(v0, v0, v2, v1);
+            break;
+        case 0x99:
+            INST_NAME("VFMADD132SS/D Gx, Vx, Ex");
+            nextop = F8;
+            GETGYx_VYx_EYxw(v0, v1, v2, 0);
+            d0 = fpu_get_scratch(dyn);
+            FMADDxw(d0, v0, v2, v1);
+            VEXTRINSxw(v0, d0, 0);
+            break;
+        case 0x9A:
+            INST_NAME("VFMSUB132PS/D Gx, Vx, Ex");
+            nextop = F8;
+            GETGY_VYEY_xy(v0, v1, v2, 0);
+            VFMSUBxyxw(v0, v0, v2, v1);
+            break;
+        case 0x9B:
+            INST_NAME("VFMSUB132SS/D Gx, Vx, Ex");
+            nextop = F8;
+            GETGYx_VYx_EYxw(v0, v1, v2, 0);
+            d0 = fpu_get_scratch(dyn);
+            FMSUBxw(d0, v0, v2, v1);
+            VEXTRINSxw(v0, d0, 0);
+            break;
+        case 0x9C:
+            INST_NAME("VFNMADD132PS/D Gx, Vx, Ex");
+            nextop = F8;
+            GETGY_VYEY_xy(v0, v1, v2, 0);
+            VFNMSUBxyxw(v0, v0, v2, v1);
+            break;
+        case 0x9D:
+            INST_NAME("VFNMADD132SS/D Gx, Vx, Ex");
+            nextop = F8;
+            GETGYx_VYx_EYxw(v0, v1, v2, 0);
+            d0 = fpu_get_scratch(dyn);
+            FNMSUBxw(d0, v0, v2, v1);
+            VEXTRINSxw(v0, d0, 0);
+            break;
+        case 0x9E:
+            INST_NAME("VFNMSUB132PS/D Gx, Vx, Ex");
+            nextop = F8;
+            GETGY_VYEY_xy(v0, v1, v2, 0);
+            VFNMADDxyxw(v0, v0, v2, v1);
+            break;
+        case 0x9F:
+            INST_NAME("VFNMSUB132SS/D Gx, Vx, Ex");
+            nextop = F8;
+            GETGYx_VYx_EYxw(v0, v1, v2, 0);
+            d0 = fpu_get_scratch(dyn);
+            FNMADDxw(d0, v0, v2, v1);
+            VEXTRINSxw(v0, d0, 0);
+            break;
+        case 0xA6:
+            INST_NAME("VFMADDSUB213PS/D Gx, Vx, Ex");
+            nextop = F8;
+            GETGY_VYEY_xy(v0, v1, v2, 0);
+            q0 = fpu_get_scratch(dyn);
+            VFMADDxyxw(q0, v1, v0, v2);
+            VFMSUBxyxw(v0, v1, v0, v2);
+            if(rex.w){
+                VEXTRINSxy(D, v0, q0, VEXTRINS_IMM_4_0(1, 1));
+            } else {
+                VEXTRINSxy(W, v0, q0, VEXTRINS_IMM_4_0(1, 1));
+                VEXTRINSxy(W, v0, q0, VEXTRINS_IMM_4_0(3, 3));
+            }
+            break;
+        case 0xA7:
+            INST_NAME("VFMSUBADD213PS/D Gx, Vx, Ex");
+            nextop = F8;
+            GETGY_VYEY_xy(v0, v1, v2, 0);
+            q0 = fpu_get_scratch(dyn);
+            VFMSUBxyxw(q0, v1, v0, v2);
+            VFMADDxyxw(v0, v1, v0, v2);
+            if(rex.w){
+                VEXTRINSxy(D, v0, q0, VEXTRINS_IMM_4_0(1, 1));
+            } else {
+                VEXTRINSxy(W, v0, q0, VEXTRINS_IMM_4_0(1, 1));
+                VEXTRINSxy(W, v0, q0, VEXTRINS_IMM_4_0(3, 3));
+            }
+            break;
+        case 0xA8:
+            INST_NAME("VFMADD213PS/D Gx, Vx, Ex");
+            nextop = F8;
+            GETGY_VYEY_xy(v0, v1, v2, 0);
+            VFMADDxyxw(v0, v1, v0, v2);
+            break;
+        case 0xA9:
+            INST_NAME("VFMADD213SS/D Gx, Vx, Ex");
+            nextop = F8;
+            GETGYx_VYx_EYxw(v0, v1, v2, 0);
+            d0 = fpu_get_scratch(dyn);
+            FMADDxw(d0, v1, v0, v2);
+            VEXTRINSxw(v0, d0, 0);
+            break;
+        case 0xAA:
+            INST_NAME("VFMSUB213PS/D Gx, Vx, Ex");
+            nextop = F8;
+            GETGY_VYEY_xy(v0, v1, v2, 0);
+            VFMSUBxyxw(v0, v1, v0, v2);
+            break;
+        case 0xAB:
+            INST_NAME("VFMSUB213SS/D Gx, Vx, Ex");
+            nextop = F8;
+            GETGYx_VYx_EYxw(v0, v1, v2, 0);
+            d0 = fpu_get_scratch(dyn);
+            FMSUBxw(d0, v1, v0, v2);
+            VEXTRINSxw(v0, d0, 0);
+            break;
+        case 0xAC:
+            INST_NAME("VFNMADD213PS/D Gx, Vx, Ex");
+            nextop = F8;
+            GETGY_VYEY_xy(v0, v1, v2, 0);
+            VFNMSUBxyxw(v0, v1, v0, v2);
+            break;
+        case 0xAD:
+            INST_NAME("VFNMADD213SS/D Gx, Vx, Ex");
+            nextop = F8;
+            GETGYx_VYx_EYxw(v0, v1, v2, 0);
+            d0 = fpu_get_scratch(dyn);
+            FNMSUBxw(d0, v1, v0, v2);
+            VEXTRINSxw(v0, d0, 0);
+            break;
+        case 0xAE:
+            INST_NAME("VFNMSUB213PS/D Gx, Vx, Ex");
+            nextop = F8;
+            GETGY_VYEY_xy(v0, v1, v2, 0);
+            VFNMADDxyxw(v0, v1, v0, v2);
+            break;
+        case 0xAF:
+            INST_NAME("VFNMSUB213SS/D Gx, Vx, Ex");
+            nextop = F8;
+            GETGYx_VYx_EYxw(v0, v1, v2, 0);
+            d0 = fpu_get_scratch(dyn);
+            FNMADDxw(d0, v1, v0, v2);
+            VEXTRINSxw(v0, d0, 0);
+            break;
+        case 0xB6:
+            INST_NAME("VFMADDSUB231PS/D Gx, Vx, Ex");
+            nextop = F8;
+            GETGY_VYEY_xy(v0, v1, v2, 0);
+            q0 = fpu_get_scratch(dyn);
+            VFMADDxyxw(q0, v1, v2, v0);
+            VFMSUBxyxw(v0, v1, v2, v0);
+            if(rex.w){
+                VEXTRINSxy(D, v0, q0, VEXTRINS_IMM_4_0(1, 1));
+            } else {
+                VEXTRINSxy(W, v0, q0, VEXTRINS_IMM_4_0(1, 1));
+                VEXTRINSxy(W, v0, q0, VEXTRINS_IMM_4_0(3, 3));
+            }
+            break;
+        case 0xB7:
+            INST_NAME("VFMSUBADD231PS/D Gx, Vx, Ex");
+            nextop = F8;
+            GETGY_VYEY_xy(v0, v1, v2, 0);
+            q0 = fpu_get_scratch(dyn);
+            VFMSUBxyxw(q0, v1, v2, v0);
+            VFMADDxyxw(v0, v1, v2, v0);
+            if(rex.w){
+                VEXTRINSxy(D, v0, q0, VEXTRINS_IMM_4_0(1, 1));
+            } else {
+                VEXTRINSxy(W, v0, q0, VEXTRINS_IMM_4_0(1, 1));
+                VEXTRINSxy(W, v0, q0, VEXTRINS_IMM_4_0(3, 3));
+            }
+            break;
+        case 0xB8:
+            INST_NAME("VFMADD231PS/D Gx, Vx, Ex");
+            nextop = F8;
+            GETGY_VYEY_xy(v0, v1, v2, 0);
+            VFMADDxyxw(v0, v1, v2, v0);
+            break;
+        case 0xB9:
+            INST_NAME("VFMADD231SS/D Gx, Vx, Ex");
+            nextop = F8;
+            GETGYx_VYx_EYxw(v0, v1, v2, 0);
+            d0 = fpu_get_scratch(dyn);
+            FMADDxw(d0, v1, v2, v0);
+            VEXTRINSxw(v0, d0, 0);
+            break;
+        case 0xBA:
+            INST_NAME("VFMSUB231PS/D Gx, Vx, Ex");
+            nextop = F8;
+            GETGY_VYEY_xy(v0, v1, v2, 0);
+            VFMSUBxyxw(v0, v1, v2, v0);
+            break;
+        case 0xBB:
+            INST_NAME("VFMSUB231SS/D Gx, Vx, Ex");
+            nextop = F8;
+            GETGYx_VYx_EYxw(v0, v1, v2, 0);
+            d0 = fpu_get_scratch(dyn);
+            FMSUBxw(d0, v1, v2, v0);
+            VEXTRINSxw(v0, d0, 0);
+            break;
+        case 0xBC:
+            INST_NAME("VFNMADD231PS/D Gx, Vx, Ex");
+            nextop = F8;
+            GETGY_VYEY_xy(v0, v1, v2, 0);
+            VFNMSUBxyxw(v0, v1, v2, v0);
+            break;
+        case 0xBD:
+            INST_NAME("VFNMADD231SS/D Gx, Vx, Ex");
+            nextop = F8;
+            GETGYx_VYx_EYxw(v0, v1, v2, 0);
+            d0 = fpu_get_scratch(dyn);
+            FNMSUBxw(d0, v1, v2, v0);
+            VEXTRINSxw(v0, d0, 0);
+            break;
+        case 0xBE:
+            INST_NAME("VFNMSUB231PS/D Gx, Vx, Ex");
+            nextop = F8;
+            GETGY_VYEY_xy(v0, v1, v2, 0);
+            VFNMADDxyxw(v0, v1, v2, v0);
+            break;
+        case 0xBF:
+            INST_NAME("VFNMSUB231SS/D Gx, Vx, Ex");
+            nextop = F8;
+            GETGYx_VYx_EYxw(v0, v1, v2, 0);
+            d0 = fpu_get_scratch(dyn);
+            FNMADDxw(d0, v1, v2, v0);
+            VEXTRINSxw(v0, d0, 0);
+            break;
         case 0xF7:
             INST_NAME("SHLX Gd, Ed, Vd");
             nextop = F8;
diff --git a/src/dynarec/la64/dynarec_la64_helper.h b/src/dynarec/la64/dynarec_la64_helper.h
index 9720cf25..68219e77 100644
--- a/src/dynarec/la64/dynarec_la64_helper.h
+++ b/src/dynarec/la64/dynarec_la64_helper.h
@@ -642,6 +642,16 @@
     GETGYxy(gx, 0);            \
     GETEYxy(ex, 1, D);
 
+// Get writable GYx, and non-written VYx, EYSD or EYSS , for FMA SD/SSinsts.
+#define GETGYx_VYx_EYxw(gx, vx, ex, D) \
+    GETVYx(vx, 0);                     \
+    if (rex.w) {                       \
+        GETEYSD(ex, 0, D)              \
+    } else {                           \
+        GETEYSS(ex, 0, D);             \
+    }                                  \
+    GETGYx(gx, 1);
+
 // Get direction with size Z and based of F_DF flag, on register r ready for load/store fetching
 // using s as scratch.
 // F_DF is not in LBT4.eflags, don't worry
@@ -874,7 +884,7 @@
         SET_DFNONE()
 
 #define SET_NODF() dyn->f.dfnone = 0
-#define SET_DFOK()     \
+#define SET_DFOK() \
     dyn->f.dfnone = 1
 
 #define CLEAR_FLAGS_(s)                                                                                       \
diff --git a/src/dynarec/la64/la64_emitter.h b/src/dynarec/la64/la64_emitter.h
index d1ba3b41..6fc25100 100644
--- a/src/dynarec/la64/la64_emitter.h
+++ b/src/dynarec/la64/la64_emitter.h
@@ -1880,6 +1880,7 @@ LSX instruction starts with V, LASX instruction starts with XV.
 #define XVILVH_H(vd, vj, vk)         EMIT(type_3R(0b01110101000111001, vk, vj, vd))
 #define XVILVH_W(vd, vj, vk)         EMIT(type_3R(0b01110101000111010, vk, vj, vd))
 #define XVILVH_D(vd, vj, vk)         EMIT(type_3R(0b01110101000111011, vk, vj, vd))
+#define XVSHUF_B(xd, xj, xk, xa)     EMIT(type_4R(0b000011010110, xa, xk, xj, xd))
 #define XVSHUF_H(vd, vj, vk)         EMIT(type_3R(0b01110101011110101, vk, vj, vd))
 #define XVSHUF_W(vd, vj, vk)         EMIT(type_3R(0b01110101011110110, vk, vj, vd))
 #define XVSHUF_D(vd, vj, vk)         EMIT(type_3R(0b01110101011110111, vk, vj, vd))
@@ -3006,4 +3007,149 @@ LSX instruction starts with V, LASX instruction starts with XV.
         else                         \
             VEXTRINS_W(xd, xj, imm); \
     } while (0)
+
+#define VFMADDxy(width, vd, vj, vk, va)      \
+    do {                                     \
+        if (vex.l) {                         \
+            XVFMADD_##width(vd, vj, vk, va); \
+        } else {                             \
+            VFMADD_##width(vd, vj, vk, va);  \
+        }                                    \
+    } while (0)
+
+#define VFMSUBxy(width, vd, vj, vk, va)      \
+    do {                                     \
+        if (vex.l) {                         \
+            XVFMSUB_##width(vd, vj, vk, va); \
+        } else {                             \
+            VFMSUB_##width(vd, vj, vk, va);  \
+        }                                    \
+    } while (0)
+
+#define VFNMADDxy(width, vd, vj, vk, va)      \
+    do {                                      \
+        if (vex.l) {                          \
+            XVFNMADD_##width(vd, vj, vk, va); \
+        } else {                              \
+            VFNMADD_##width(vd, vj, vk, va);  \
+        }                                     \
+    } while (0)
+
+#define VFNMSUBxy(width, vd, vj, vk, va)      \
+    do {                                      \
+        if (vex.l) {                          \
+            XVFNMSUB_##width(vd, vj, vk, va); \
+        } else {                              \
+            VFNMSUB_##width(vd, vj, vk, va);  \
+        }                                     \
+    } while (0)
+
+#define VFMADDxyxw(vd, vj, vk, va)       \
+    do {                                 \
+        if (rex.w) {                     \
+            VFMADDxy(D, vd, vj, vk, va); \
+        } else {                         \
+            VFMADDxy(S, vd, vj, vk, va); \
+        }                                \
+    } while (0)
+
+#define VFMSUBxyxw(vd, vj, vk, va)       \
+    do {                                 \
+        if (rex.w) {                     \
+            VFMSUBxy(D, vd, vj, vk, va); \
+        } else {                         \
+            VFMSUBxy(S, vd, vj, vk, va); \
+        }                                \
+    } while (0)
+
+#define VFNMADDxyxw(vd, vj, vk, va)       \
+    do {                                  \
+        if (rex.w) {                      \
+            VFNMADDxy(D, vd, vj, vk, va); \
+        } else {                          \
+            VFNMADDxy(S, vd, vj, vk, va); \
+        }                                 \
+    } while (0)
+
+#define VFNMSUBxyxw(vd, vj, vk, va)       \
+    do {                                  \
+        if (rex.w) {                      \
+            VFNMSUBxy(D, vd, vj, vk, va); \
+        } else {                          \
+            VFNMSUBxy(S, vd, vj, vk, va); \
+        }                                 \
+    } while (0)
+
+#define VPICKEVxyxw(vd, vj, vk)       \
+    do {                              \
+        if (rex.w) {                  \
+            VPICKEVxy(D, vd, vj, vk); \
+        } else {                      \
+            VPICKEVxy(W, vd, vj, vk); \
+        }                             \
+    } while (0)
+
+#define VPICKODxyxw(vd, vj, vk)       \
+    do {                              \
+        if (rex.w) {                  \
+            VPICKODxy(D, vd, vj, vk); \
+        } else {                      \
+            VPICKODxy(W, vd, vj, vk); \
+        }                             \
+    } while (0)
+
+#define VILVLxyxw(vd, vj, vk)       \
+    do {                            \
+        if (rex.w) {                \
+            VILVLxy(D, vd, vj, vk); \
+        } else {                    \
+            VILVLxy(W, vd, vj, vk); \
+        }                           \
+    } while (0)
+
+#define VILVHxyxw(vd, vj, vk)       \
+    do {                            \
+        if (rex.w) {                \
+            VILVHxy(D, vd, vj, vk); \
+        } else {                    \
+            VILVHxy(W, vd, vj, vk); \
+        }                           \
+    } while (0)
+
+#define FMADDxw(fd, fj, fk, fa)      \
+    do {                             \
+        if (rex.w) {                 \
+            FMADD_D(fd, fj, fk, fa); \
+        } else {                     \
+            FMADD_S(fd, fj, fk, fa); \
+        }                            \
+    } while (0)
+
+#define FMSUBxw(fd, fj, fk, fa)      \
+    do {                             \
+        if (rex.w) {                 \
+            FMSUB_D(fd, fj, fk, fa); \
+        } else {                     \
+            FMSUB_S(fd, fj, fk, fa); \
+        }                            \
+    } while (0)
+
+#define FNMADDxw(fd, fj, fk, fa)      \
+    do {                              \
+        if (rex.w) {                  \
+            FNMADD_D(fd, fj, fk, fa); \
+        } else {                      \
+            FNMADD_S(fd, fj, fk, fa); \
+        }                             \
+    } while (0)
+
+#define FNMSUBxw(fd, fj, fk, fa)      \
+    do {                              \
+        if (rex.w) {                  \
+            FNMSUB_D(fd, fj, fk, fa); \
+        } else {                      \
+            FNMSUB_S(fd, fj, fk, fa); \
+        }                             \
+    } while (0)
+
 #endif //__ARM64_EMITTER_H__
diff --git a/src/dynarec/la64/la64_printer.c b/src/dynarec/la64/la64_printer.c
index 60e3389c..6e21b93e 100644
--- a/src/dynarec/la64/la64_printer.c
+++ b/src/dynarec/la64/la64_printer.c
@@ -7460,6 +7460,70 @@ const char* la64_print(uint32_t opcode, uintptr_t addr)
         snprintf(buff, sizeof(buff), "%-15s %s, %s, 0x%lx", "VNORI.B", Vt[Rd], Vt[Rj], imm);
         return buff;
     }
+    if (isMask(opcode, "000010010001aaaaakkkkkjjjjjddddd", &a)) {
+        snprintf(buff, sizeof(buff), "%-15s %s, %s, %s, %s", "VFMADD.S", Vt[Rd], Vt[Rj], Vt[Rk], Vt[Ra]);
+        return buff;
+    }
+    if (isMask(opcode, "000010010101aaaaakkkkkjjjjjddddd", &a)) {
+        snprintf(buff, sizeof(buff), "%-15s %s, %s, %s, %s", "VFMSUB.S", Vt[Rd], Vt[Rj], Vt[Rk], Vt[Ra]);
+        return buff;
+    }
+    if (isMask(opcode, "000010011001aaaaakkkkkjjjjjddddd", &a)) {
+        snprintf(buff, sizeof(buff), "%-15s %s, %s, %s, %s", "VFNMADD.S", Vt[Rd], Vt[Rj], Vt[Rk], Vt[Ra]);
+        return buff;
+    }
+    if (isMask(opcode, "000010011101aaaaakkkkkjjjjjddddd", &a)) {
+        snprintf(buff, sizeof(buff), "%-15s %s, %s, %s, %s", "VFNMSUB.S", Vt[Rd], Vt[Rj], Vt[Rk], Vt[Ra]);
+        return buff;
+    }
+    if (isMask(opcode, "000010100001aaaaakkkkkjjjjjddddd", &a)) {
+        snprintf(buff, sizeof(buff), "%-15s %s, %s, %s, %s", "XVFMADD.S", XVt[Rd], XVt[Rj], XVt[Rk], XVt[Ra]);
+        return buff;
+    }
+    if (isMask(opcode, "000010100101aaaaakkkkkjjjjjddddd", &a)) {
+        snprintf(buff, sizeof(buff), "%-15s %s, %s, %s, %s", "XVFMSUB.S", XVt[Rd], XVt[Rj], XVt[Rk], XVt[Ra]);
+        return buff;
+    }
+    if (isMask(opcode, "000010101001aaaaakkkkkjjjjjddddd", &a)) {
+        snprintf(buff, sizeof(buff), "%-15s %s, %s, %s, %s", "XVFNMADD.S", XVt[Rd], XVt[Rj], XVt[Rk], XVt[Ra]);
+        return buff;
+    }
+    if (isMask(opcode, "000010101101aaaaakkkkkjjjjjddddd", &a)) {
+        snprintf(buff, sizeof(buff), "%-15s %s, %s, %s, %s", "XVFNMSUB.S", XVt[Rd], XVt[Rj], XVt[Rk], XVt[Ra]);
+        return buff;
+    }
+    if (isMask(opcode, "000010010010aaaaakkkkkjjjjjddddd", &a)) {
+        snprintf(buff, sizeof(buff), "%-15s %s, %s, %s, %s", "VFMADD.D", Vt[Rd], Vt[Rj], Vt[Rk], Vt[Ra]);
+        return buff;
+    }
+    if (isMask(opcode, "000010010110aaaaakkkkkjjjjjddddd", &a)) {
+        snprintf(buff, sizeof(buff), "%-15s %s, %s, %s, %s", "VFMSUB.D", Vt[Rd], Vt[Rj], Vt[Rk], Vt[Ra]);
+        return buff;
+    }
+    if (isMask(opcode, "000010011010aaaaakkkkkjjjjjddddd", &a)) {
+        snprintf(buff, sizeof(buff), "%-15s %s, %s, %s, %s", "VFNMADD.D", Vt[Rd], Vt[Rj], Vt[Rk], Vt[Ra]);
+        return buff;
+    }
+    if (isMask(opcode, "000010011110aaaaakkkkkjjjjjddddd", &a)) {
+        snprintf(buff, sizeof(buff), "%-15s %s, %s, %s, %s", "VFNMSUB.D", Vt[Rd], Vt[Rj], Vt[Rk], Vt[Ra]);
+        return buff;
+    }
+    if (isMask(opcode, "000010100010aaaaakkkkkjjjjjddddd", &a)) {
+        snprintf(buff, sizeof(buff), "%-15s %s, %s, %s, %s", "XVFMADD.D", XVt[Rd], XVt[Rj], XVt[Rk], XVt[Ra]);
+        return buff;
+    }
+    if (isMask(opcode, "000010100110aaaaakkkkkjjjjjddddd", &a)) {
+        snprintf(buff, sizeof(buff), "%-15s %s, %s, %s, %s", "XVFMSUB.D", XVt[Rd], XVt[Rj], XVt[Rk], XVt[Ra]);
+        return buff;
+    }
+    if (isMask(opcode, "000010101010aaaaakkkkkjjjjjddddd", &a)) {
+        snprintf(buff, sizeof(buff), "%-15s %s, %s, %s, %s", "XVFNMADD.D", XVt[Rd], XVt[Rj], XVt[Rk], XVt[Ra]);
+        return buff;
+    }
+    if (isMask(opcode, "000010101110aaaaakkkkkjjjjjddddd", &a)) {
+        snprintf(buff, sizeof(buff), "%-15s %s, %s, %s, %s", "XVFNMSUB.D", XVt[Rd], XVt[Rj], XVt[Rk], XVt[Ra]);
+        return buff;
+    }
     snprintf(buff, sizeof(buff), "%08X ???", __builtin_bswap32(opcode));
     return buff;
 }