about summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
authorYang Liu <liuyang22@iscas.ac.cn>2023-04-28 22:11:16 +0800
committerGitHub <noreply@github.com>2023-04-28 16:11:16 +0200
commit93abd016b451d63355dbc02fdbed431f6eacc810 (patch)
treea6da54df1b9ef91dafb9c8e635e2050f98a37603 /src
parent2ebde976db3337a0b78e1df0dd475c7bd5355511 (diff)
downloadbox64-93abd016b451d63355dbc02fdbed431f6eacc810.tar.gz
box64-93abd016b451d63355dbc02fdbed431f6eacc810.zip
[RV64_DYNAREC] Added more opcodes (#745)
* Added 66 0F 3A 0E PBLENDW opcode

* Added 66 0F 3A 22 PINSRD opcode

* Added 66 0F 7C HADDPD opcode

* Added 0F 53 RCPPS opcode

* Added 0F 51 SQRTPS opcode

* Added 66 0F 3A 0F PALIGNR opcode

* Added 66 0F 3A 16 PEXTRD/Q opcodes

* Added 9B FWAIT opcode

* Added a DD opcodes and some fixes

* Added DF FUCOMIP opcode

* Added DD D8 FSTP opcode

* Added D9 FC FRNDINT opcode and a small fix to ROUNDSD

* Added DF /7 FISTP opcode

* Added DB /3 FISTP opcode

* Added DD /3 FSTP opcode

* Fixed DF /3 FISTP opcode
Diffstat (limited to 'src')
-rw-r--r--src/dynarec/rv64/dynarec_rv64_00_2.c3
-rw-r--r--src/dynarec/rv64/dynarec_rv64_00_3.c4
-rw-r--r--src/dynarec/rv64/dynarec_rv64_0f.c27
-rw-r--r--src/dynarec/rv64/dynarec_rv64_660f.c138
-rw-r--r--src/dynarec/rv64/dynarec_rv64_d9.c45
-rw-r--r--src/dynarec/rv64/dynarec_rv64_db.c19
-rw-r--r--src/dynarec/rv64/dynarec_rv64_dd.c150
-rw-r--r--src/dynarec/rv64/dynarec_rv64_df.c47
-rw-r--r--src/dynarec/rv64/dynarec_rv64_helper.h2
9 files changed, 420 insertions, 15 deletions
diff --git a/src/dynarec/rv64/dynarec_rv64_00_2.c b/src/dynarec/rv64/dynarec_rv64_00_2.c
index 806b0b6d..93dda7ef 100644
--- a/src/dynarec/rv64/dynarec_rv64_00_2.c
+++ b/src/dynarec/rv64/dynarec_rv64_00_2.c
@@ -473,6 +473,9 @@ uintptr_t dynarec64_00_2(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
                 ZEROUP(xRDX);
             }
             break;
+        case 0x9B:
+            INST_NAME("FWAIT");
+            break;
         case 0x9C:
             INST_NAME("PUSHF");
             READFLAGS(X_ALL);
diff --git a/src/dynarec/rv64/dynarec_rv64_00_3.c b/src/dynarec/rv64/dynarec_rv64_00_3.c
index a19f3f68..e9a3d0e0 100644
--- a/src/dynarec/rv64/dynarec_rv64_00_3.c
+++ b/src/dynarec/rv64/dynarec_rv64_00_3.c
@@ -518,6 +518,10 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
             addr = dynarec64_DB(dyn, addr, ip, ninst, rex, rep, ok, need_epilog);
             break;
 
+        case 0xDD:
+            addr = dynarec64_DD(dyn, addr, ip, ninst, rex, rep, ok, need_epilog);
+            break;
+
         case 0xDE:
             addr = dynarec64_DE(dyn, addr, ip, ninst, rex, rep, ok, need_epilog);
             break;
diff --git a/src/dynarec/rv64/dynarec_rv64_0f.c b/src/dynarec/rv64/dynarec_rv64_0f.c
index a3d9efc1..be6ec046 100644
--- a/src/dynarec/rv64/dynarec_rv64_0f.c
+++ b/src/dynarec/rv64/dynarec_rv64_0f.c
@@ -342,6 +342,33 @@ uintptr_t dynarec64_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
                 OR(gd, gd, x2);
             }
             break;
+        case 0x51:
+            INST_NAME("SQRTPS Gx, Ex");
+            nextop = F8;
+            GETGX(x1);
+            GETEX(x2, 0);
+            d0 = fpu_get_scratch(dyn);
+            for(int i=0; i<4; ++i) {
+                FLW(d0, wback, fixedaddress+4*i);
+                FSQRTS(d0, d0);
+                FSW(d0, gback, 4*i);
+            }
+            break;
+        case 0x53:
+            INST_NAME("RCPPS Gx, Ex");
+            nextop = F8;
+            GETGX(x1);
+            GETEX(x2, 0);
+            d0 = fpu_get_scratch(dyn);
+            d1 = fpu_get_scratch(dyn);
+            LUI(x3, 0x3f800);
+            FMVWX(d0, x3); // 1.0f
+            for(int i=0; i<4; ++i) {
+                FLW(d1, wback, fixedaddress+4*i);
+                FDIVS(d1, d0, d1);
+                FSW(d1, gback, 4*i);
+            }
+            break;
         case 0x54:
             INST_NAME("ANDPS Gx, Ex");
             nextop = F8;
diff --git a/src/dynarec/rv64/dynarec_rv64_660f.c b/src/dynarec/rv64/dynarec_rv64_660f.c
index 260ea32b..19c12bfd 100644
--- a/src/dynarec/rv64/dynarec_rv64_660f.c
+++ b/src/dynarec/rv64/dynarec_rv64_660f.c
@@ -372,6 +372,102 @@ uintptr_t dynarec64_660F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
                         FCVTLD(x5, d0, round_round[u8&3]);
                         FCVTDL(v0, x5, round_round[u8&3]);
                     }
+                    FSGNJD(v0, v0, d0);
+                    break;
+                case 0x0E:
+                    INST_NAME("PBLENDW Gx, Ex, Ib");
+                    nextop = F8;
+                    GETGX(x1);
+                    GETEX(x2, 1);
+                    u8 = F8;
+                    i32 = 0;
+                    if (MODREG && gd==ed) break;
+                    while (u8)
+                        if(u8&1) {
+                            if(!(i32&1) && u8&2) {
+                                if(!(i32&3) && (u8&0xf)==0xf) {
+                                    // whole 64bits
+                                    LD(x3, wback, fixedaddress+8*(i32>>2));
+                                    SD(x3, gback, 8*(i32>>2));
+                                    i32+=4;
+                                    u8>>=4;
+                                } else {
+                                    // 32bits
+                                    LWU(x3, wback, fixedaddress+4*(i32>>1));
+                                    SW(x3, gback, 4*(i32>>1));
+                                    i32+=2;
+                                    u8>>=2;
+                                }
+                            } else {
+                                // 16 bits
+                                LHU(x3, wback, fixedaddress+2*i32);
+                                SH(x3, gback, 2*i32);
+                                i32++;
+                                u8>>=1;
+                            }
+                        } else {
+                            // nope
+                            i32++;
+                            u8>>=1;
+                        }
+                    break;
+                case 0x0F:
+                    INST_NAME("PALIGNR Gx, Ex, Ib");
+                    nextop = F8;
+                    GETGX(x1);
+                    GETEX(x2, 1);
+                    u8 = F8;
+                    sse_forget_reg(dyn, ninst, x5);
+                    ADDI(x5, xEmu, offsetof(x64emu_t, scratch));
+                    // perserve gd
+                    LD(x3, gback, 0);
+                    LD(x4, gback, 8);
+                    SD(x3, x5, 0);
+                    SD(x4, x5, 8);
+                    if(u8>31) {
+                        SD(xZR, gback, 0);
+                        SD(xZR, gback, 8);
+                    } else {
+                        for (int i=0; i<16; ++i, ++u8) {
+                            if (u8>15) {
+                                if(u8>31) {
+                                    SB(xZR, gback, i);
+                                    continue;
+                                }
+                                else LBU(x3, x5, u8-16);
+                            } else {
+                                LBU(x3, wback, fixedaddress+u8);
+                            }
+                            SB(x3, gback, i);
+                        }
+                    }
+                    break;
+                case 0x16:
+                    if(rex.w) {INST_NAME("PEXTRQ Ed, Gx, Ib");} else {INST_NAME("PEXTRD Ed, Gx, Ib");}
+                    nextop = F8;
+                    GETGX(x1);
+                    GETED(1);
+                    u8 = F8;
+                    if(rex.w)
+                        LD(ed, gback, 8*(u8&1));
+                    else
+                        LWU(ed, gback, 4*(u8&3));
+                    if (wback) {
+                        SDxw(ed, wback, fixedaddress);
+                        SMWRITE2();
+                    }
+                    break;
+                case 0x22:
+                    INST_NAME("PINSRD Gx, ED, Ib");
+                    nextop = F8;
+                    GETGX(x1);
+                    GETED(1);
+                    u8 = F8;
+                    if(rex.w) {
+                        SD(ed, gback, 8*(u8&0x1));
+                    } else {
+                        SW(ed, gback, 4*(u8&0x3));
+                    }
                     break;
                 default:
                     DEFAULT;
@@ -1122,6 +1218,48 @@ uintptr_t dynarec64_660F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
             GETEX(x2, 0);
             SSE_LOOP_D(x3, x4, XOR(x3, x3, x4); SNEZ(x3, x3); ADDI(x3, x3, -1));
             break;
+        case 0x7C:
+            INST_NAME("HADDPD Gx, Ex");
+            nextop = F8;
+            GETGX(x1);
+            d0 = fpu_get_scratch(dyn);
+            d1 = fpu_get_scratch(dyn);
+            FLD(d0, gback, 0);
+            FLD(d1, gback, 8);
+            if(!box64_dynarec_fastnan) {
+                FEQD(x3, d0, d0);
+                FEQD(x4, d1, d1);
+                AND(x3, x3, x4);
+            }
+            FADDD(d0, d0, d1);
+            if(!box64_dynarec_fastnan) {
+                FEQD(x4, d0, d0);
+                BEQZ(x3, 12);
+                BNEZ(x4, 8);
+                FNEGD(d0, d0);
+            }
+            FSD(d0, gback, 0);
+            if(MODREG && gd==(nextop&7)+(rex.b<<3)) {
+                FSD(d0, gback, 8);
+            } else {
+                GETEX(x2, 0);
+                FLD(d0, wback, fixedaddress+0);
+                FLD(d1, wback, fixedaddress+8);
+                if(!box64_dynarec_fastnan) {
+                    FEQD(x3, d0, d0);
+                    FEQD(x4, d1, d1);
+                    AND(x3, x3, x4);
+                }
+                FADDD(d0, d0, d1);
+                if(!box64_dynarec_fastnan) {
+                    FEQD(x4, d0, d0);
+                    BEQZ(x3, 12);
+                    BNEZ(x4, 8);
+                    FNEGD(d0, d0);
+                }
+                FSD(d0, gback, 8);
+            }
+            break;
         case 0x7E:
             INST_NAME("MOVD Ed,Gx");
             nextop = F8;
diff --git a/src/dynarec/rv64/dynarec_rv64_d9.c b/src/dynarec/rv64/dynarec_rv64_d9.c
index 9378c650..a6a7898e 100644
--- a/src/dynarec/rv64/dynarec_rv64_d9.c
+++ b/src/dynarec/rv64/dynarec_rv64_d9.c
@@ -34,13 +34,16 @@ uintptr_t dynarec64_D9(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
     uint8_t u8;
     int64_t fixedaddress;
     int unscaled;
-    int v1, v2;
+    int v0, v1, v2;
     int s0;
     int i1, i2, i3;
+    int64_t j64;
 
     MAYUSE(s0);
-    MAYUSE(v2);
+    MAYUSE(v0);
     MAYUSE(v1);
+    MAYUSE(v2);
+    MAYUSE(j64);
 
     switch(nextop) {
         case 0xC0:
@@ -271,7 +274,43 @@ uintptr_t dynarec64_D9(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
             break;
         case 0xFC:
             INST_NAME("FRNDINT");
-            DEFAULT;
+            v0 = x87_get_st(dyn, ninst, x1, x2, 0, X87_ST0);
+            v1 = fpu_get_scratch(dyn);
+            v2 = fpu_get_scratch(dyn);
+            u8 = x87_setround(dyn, ninst, x1, x2);
+
+            if(ST_IS_F(0)) {
+                FEQS(x2, v0, v0);
+                BNEZ_MARK(x2);
+                B_NEXT_nocond;
+                MARK; // v0 is not nan
+                FABSS(v1, v0);
+                MOV64x(x3, 1ULL << __FLT_MANT_DIG__);
+                FCVTSL(v2, x3, RD_RTZ);
+                FLTS(x3, v1, v2);
+                BNEZ_MARK2(x3);
+                B_NEXT_nocond;
+                MARK2;
+                FCVTLS(x3, v0, RD_DYN);
+                FCVTSL(v1, x3, RD_DYN);
+                FSGNJS(v0, v1, v0);
+            } else {
+                FEQD(x2, v0, v0);
+                BNEZ_MARK(x2);
+                B_NEXT_nocond;
+                MARK; // v0 is not nan
+                FABSD(v1, v0);
+                MOV64x(x3, 1ULL << __DBL_MANT_DIG__);
+                FCVTDL(v2, x3, RD_RTZ);
+                FLTD(x3, v1, v2);
+                BNEZ_MARK2(x3);
+                B_NEXT_nocond;
+                MARK2;
+                FCVTLD(x3, v0, RD_DYN);
+                FCVTDL(v1, x3, RD_DYN);
+                FSGNJD(v0, v1, v0);
+            }
+            x87_restoreround(dyn, ninst, u8);
             break;
         case 0xFD:
             INST_NAME("FSCALE");
diff --git a/src/dynarec/rv64/dynarec_rv64_db.c b/src/dynarec/rv64/dynarec_rv64_db.c
index 95e350c0..e037c3dd 100644
--- a/src/dynarec/rv64/dynarec_rv64_db.c
+++ b/src/dynarec/rv64/dynarec_rv64_db.c
@@ -191,7 +191,24 @@ uintptr_t dynarec64_DB(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
                     break;
                 case 3:
                     INST_NAME("FISTP Ed, ST0");
-                    DEFAULT;
+                    v1 = x87_get_st(dyn, ninst, x1, x2, 0, EXT_CACHE_ST_D);
+                    u8 = x87_setround(dyn, ninst, x1, x2);
+                    addr = geted(dyn, addr, ninst, nextop, &wback, x2, x3, &fixedaddress, rex, NULL, 1, 0);
+                    v2 = fpu_get_scratch(dyn);
+                    if(!box64_dynarec_fastround) {
+                        FSFLAGSI(xZR); // reset all bits
+                    }
+                    FCVTWD(x4, v1, RD_DYN);
+                    x87_restoreround(dyn, ninst, u8);
+                    if(!box64_dynarec_fastround) {
+                        FRFLAGS(x5);   // get back FPSR to check the IOC bit
+                        ANDI(x5, x5, 1<<FR_NV);
+                        BEQ_MARK2(x5, xZR);
+                        MOV32w(x4, 0x80000000);
+                    }
+                    MARK2;
+                    SW(x4, wback, fixedaddress);
+                    x87_do_pop(dyn, ninst, x3);
                     break;
                 case 5:
                     INST_NAME("FLD tbyte");
diff --git a/src/dynarec/rv64/dynarec_rv64_dd.c b/src/dynarec/rv64/dynarec_rv64_dd.c
new file mode 100644
index 00000000..71b1740a
--- /dev/null
+++ b/src/dynarec/rv64/dynarec_rv64_dd.c
@@ -0,0 +1,150 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <pthread.h>
+#include <errno.h>
+
+#include "debug.h"
+#include "box64context.h"
+#include "dynarec.h"
+#include "emu/x64emu_private.h"
+#include "emu/x64run_private.h"
+#include "x64run.h"
+#include "x64emu.h"
+#include "box64stack.h"
+#include "callback.h"
+#include "emu/x64run_private.h"
+#include "x64trace.h"
+#include "emu/x87emu_private.h"
+#include "dynarec_native.h"
+
+#include "rv64_printer.h"
+#include "dynarec_rv64_private.h"
+#include "dynarec_rv64_helper.h"
+#include "dynarec_rv64_functions.h"
+
+
+uintptr_t dynarec64_DD(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog)
+{
+    (void)ip; (void)rep; (void)need_epilog;
+
+    uint8_t nextop = F8;
+    uint8_t ed, wback;
+    int64_t fixedaddress;
+    int unscaled;
+    int v1, v2;
+    int s0;
+    int64_t j64;
+
+    MAYUSE(s0);
+    MAYUSE(v2);
+    MAYUSE(v1);
+    MAYUSE(j64);
+
+    switch(nextop) {
+        case 0xC0:
+        case 0xC1:
+        case 0xC2:
+        case 0xC3:
+        case 0xC4:
+        case 0xC5:
+        case 0xC6:
+        case 0xC7:
+            INST_NAME("FFREE STx");
+            DEFAULT;
+            break;
+        case 0xD0:
+        case 0xD1:
+        case 0xD2:
+        case 0xD3:
+        case 0xD4:
+        case 0xD5:
+        case 0xD6:
+        case 0xD7:
+            INST_NAME("FST ST0, STx");
+            DEFAULT;
+            break;
+        case 0xD8:
+            INST_NAME("FSTP ST0, ST0");
+            x87_do_pop(dyn, ninst, x3);
+            break;
+        case 0xD9:
+        case 0xDA:
+        case 0xDB:
+        case 0xDC:
+        case 0xDD:
+        case 0xDE:
+        case 0xDF:
+            INST_NAME("FSTP ST0, STx");
+            DEFAULT;
+            break;
+        case 0xE0:
+        case 0xE1:
+        case 0xE2:
+        case 0xE3:
+        case 0xE4:
+        case 0xE5:
+        case 0xE6:
+        case 0xE7:
+            INST_NAME("FUCOM ST0, STx");
+            DEFAULT;
+            break;
+        case 0xE8:
+        case 0xE9:
+        case 0xEA:
+        case 0xEB:
+        case 0xEC:
+        case 0xED:
+        case 0xEE:
+        case 0xEF:
+            INST_NAME("FUCOMP ST0, STx");
+            DEFAULT;
+            break;
+        case 0xC8:
+        case 0xC9:
+        case 0xCA:
+        case 0xCB:
+        case 0xCC:
+        case 0xCD:
+        case 0xCE:
+        case 0xCF:
+        case 0xF0:
+        case 0xF1:
+        case 0xF2:
+        case 0xF3:
+        case 0xF4:
+        case 0xF5:
+        case 0xF6:
+        case 0xF7:
+        case 0xF8:
+        case 0xF9:
+        case 0xFA:
+        case 0xFB:
+        case 0xFC:
+        case 0xFD:
+        case 0xFE:
+        case 0xFF:
+            DEFAULT;
+            break;
+
+        default:
+            switch((nextop>>3)&7) {
+                case 0:
+                    INST_NAME("FLD double");
+                    v1 = x87_do_push(dyn, ninst, x1, EXT_CACHE_ST_D);
+                    addr = geted(dyn, addr, ninst, nextop, &wback, x2, x1, &fixedaddress, rex, NULL, 1, 0);
+                    FLD(v1, wback, fixedaddress);
+                    break;
+                case 3:
+                    INST_NAME("FSTP double");
+                    v1 = x87_get_st(dyn, ninst, x1, x2, 0, EXT_CACHE_ST_D);
+                    addr = geted(dyn, addr, ninst, nextop, &wback, x2, x1, &fixedaddress, rex, NULL, 1, 0);
+                    FSD(v1, wback, fixedaddress);
+                    x87_do_pop(dyn, ninst, x3);
+                    break;
+                default:
+                    DEFAULT;
+            }
+    }
+    return addr;
+}
diff --git a/src/dynarec/rv64/dynarec_rv64_df.c b/src/dynarec/rv64/dynarec_rv64_df.c
index a96a45f1..61546975 100644
--- a/src/dynarec/rv64/dynarec_rv64_df.c
+++ b/src/dynarec/rv64/dynarec_rv64_df.c
@@ -41,15 +41,21 @@ uintptr_t dynarec64_DF(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
 
     switch(nextop) {
         case 0xC0 ... 0xC7:
-        
+            INST_NAME("FFREEP STx");
+            DEFAULT;
+            break;
+
         case 0xE0:
-        
-        case 0xE8 ... 0xEF:
+            INST_NAME("FNSTSW AX");
             DEFAULT;
             break;
-        
-        case 0xF0 ... 0xF7:
-            INST_NAME("FCOMIP ST0, STx");
+
+        case 0xE8 ... 0xF7:
+            if (nextop < 0xF0) {
+                INST_NAME("FUCOMIP ST0, STx");
+            } else {
+                INST_NAME("FCOMIP ST0, STx");
+            }
             SETFLAGS(X_ALL, SF_SET);
             SET_DFNONE();
             v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop&7));
@@ -114,7 +120,7 @@ uintptr_t dynarec64_DF(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
                 case 1:
                     INST_NAME("FISTTP Ew, ST0");
                     v1 = x87_get_st(dyn, ninst, x1, x2, 0, EXT_CACHE_ST_F);
-                    addr = geted(dyn, addr, ninst, nextop, &wback, x3, x4, &fixedaddress, rex, NULL, 0, 0);
+                    addr = geted(dyn, addr, ninst, nextop, &wback, x3, x4, &fixedaddress, rex, NULL, 1, 0);
                     if(!box64_dynarec_fastround) {
                         FSFLAGSI(xZR); // reset all bits
                     }
@@ -136,12 +142,12 @@ uintptr_t dynarec64_DF(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
                 case 3:
                     INST_NAME("FISTP Ew, ST0");
                     v1 = x87_get_st(dyn, ninst, x1, x2, 0, EXT_CACHE_ST_F);
-                    addr = geted(dyn, addr, ninst, nextop, &wback, x3, x4, &fixedaddress, rex, NULL, 0, 0);
-                    u8 = sse_setround(dyn, ninst, x2, x3);
+                    u8 = x87_setround(dyn, ninst, x1, x2);
+                    addr = geted(dyn, addr, ninst, nextop, &wback, x2, x3, &fixedaddress, rex, NULL, 1, 0);
                     if(!box64_dynarec_fastround) {
                         FSFLAGSI(xZR); // reset all bits
                     }
-                    FCVTWD(x4, v1, RD_RM);
+                    FCVTWD(x4, v1, RD_DYN);
                     x87_restoreround(dyn, ninst, u8);
                     if(!box64_dynarec_fastround) {
                         FRFLAGS(x5);   // get back FPSR to check the IOC bit
@@ -157,6 +163,27 @@ uintptr_t dynarec64_DF(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
                     SH(x4, wback, fixedaddress);
                     x87_do_pop(dyn, ninst, x3);
                     break;
+                case 7:
+                    INST_NAME("FISTP i64, ST0");
+                    v1 = x87_get_st(dyn, ninst, x1, x2, 0, EXT_CACHE_ST_D);
+                    u8 = x87_setround(dyn, ninst, x1, x2);
+                    addr = geted(dyn, addr, ninst, nextop, &wback, x2, x3, &fixedaddress, rex, NULL, 1, 0);
+                    v2 = fpu_get_scratch(dyn);
+                    if(!box64_dynarec_fastround) {
+                        FSFLAGSI(xZR); // reset all bits
+                    }
+                    FCVTLD(x4, v1, RD_DYN);
+                    x87_restoreround(dyn, ninst, u8);
+                    if(!box64_dynarec_fastround) {
+                        FRFLAGS(x5);   // get back FPSR to check the IOC bit
+                        ANDI(x5, x5, 1<<FR_NV);
+                        BEQ_MARK2(x5, xZR);
+                        MOV64x(x4, 0x8000000000000000LL);
+                    }
+                    MARK2;
+                    SD(x4, wback, fixedaddress);
+                    x87_do_pop(dyn, ninst, x3);
+                    break;
                 default:
                     DEFAULT;
                     break;
diff --git a/src/dynarec/rv64/dynarec_rv64_helper.h b/src/dynarec/rv64/dynarec_rv64_helper.h
index b12ee96b..f4fde7dd 100644
--- a/src/dynarec/rv64/dynarec_rv64_helper.h
+++ b/src/dynarec/rv64/dynarec_rv64_helper.h
@@ -1091,7 +1091,7 @@ uintptr_t dynarec64_D9(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
 //uintptr_t dynarec64_DA(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog);
 uintptr_t dynarec64_DB(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog);
 //uintptr_t dynarec64_DC(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog);
-//uintptr_t dynarec64_DD(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog);
+uintptr_t dynarec64_DD(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog);
 uintptr_t dynarec64_DE(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog);
 uintptr_t dynarec64_DF(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog);
 uintptr_t dynarec64_F0(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog);