about summary refs log tree commit diff stats
path: root/src/dynarec/rv64/dynarec_rv64_dd.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/dynarec/rv64/dynarec_rv64_dd.c')
-rw-r--r--src/dynarec/rv64/dynarec_rv64_dd.c179
1 files changed, 179 insertions, 0 deletions
diff --git a/src/dynarec/rv64/dynarec_rv64_dd.c b/src/dynarec/rv64/dynarec_rv64_dd.c
new file mode 100644
index 00000000..044f9aab
--- /dev/null
+++ b/src/dynarec/rv64/dynarec_rv64_dd.c
@@ -0,0 +1,179 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <stddef.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");
+            MESSAGE(LOG_DUMP, "Need Optimization\n");
+            x87_purgecache(dyn, ninst, 0, x1, x2, x3);
+            MOV32w(x1, nextop&7);
+            CALL(fpu_do_free, -1);
+            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");
+            // copy the cache value for st0 to stx
+            x87_get_st_empty(dyn, ninst, x1, x2, nextop&7, X87_ST(nextop&7));
+            x87_get_st(dyn, ninst, x1, x2, 0, X87_ST0);
+            x87_swapreg(dyn, ninst, x1, x2, 0, nextop&7);
+            x87_do_pop(dyn, ninst, x3);
+            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 2:
+                    INST_NAME("FST 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);
+                    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;
+                case 7:
+                    INST_NAME("FNSTSW m2byte");
+                    fpu_purgecache(dyn, ninst, 0, x1, x2, x3);
+                    addr = geted(dyn, addr, ninst, nextop, &ed, x4, x6, &fixedaddress, rex, NULL, 0, 0);
+                    LWU(x2, xEmu, offsetof(x64emu_t, top));
+                    LHU(x3, xEmu, offsetof(x64emu_t, sw));
+                    if(dyn->e.x87stack) {
+                        // update top
+                        ADDI(x2, x2, -dyn->e.x87stack);
+                        ANDI(x2, x2, 7);
+                    }
+                    MOV32w(x5, ~0x3800);
+                    AND(x3, x3, x5);    // mask out TOP
+                    SLLI(x2, x2, 11);   // shift TOP to bit 11
+                    OR(x3, x3, x2);     // inject TOP
+                    SH(x3, ed, fixedaddress);   // store whole sw flags
+                    break;
+                default:
+                    DEFAULT;
+            }
+    }
+    return addr;
+}