about summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
authorxctan <xctan@cirno.icu>2023-03-30 18:08:40 +0800
committerGitHub <noreply@github.com>2023-03-30 12:08:40 +0200
commite82d5264144baa0236d751c63d8700c78eea0b46 (patch)
tree7aff076b8986fc0ffecc85380748eb9f5e20a6fe /src
parent0f11b55ba3c785ebf3bcb6998012621dae69d873 (diff)
downloadbox64-e82d5264144baa0236d751c63d8700c78eea0b46.tar.gz
box64-e82d5264144baa0236d751c63d8700c78eea0b46.zip
[RV64_DYNAREC] Added DF F0+i FCOMIP and DF /0 FILD opcodes (#649)
Diffstat (limited to 'src')
-rw-r--r--src/dynarec/rv64/dynarec_rv64_00.c4
-rw-r--r--src/dynarec/rv64/dynarec_rv64_d8.c15
-rw-r--r--src/dynarec/rv64/dynarec_rv64_df.c119
-rw-r--r--src/dynarec/rv64/dynarec_rv64_helper.h2
-rw-r--r--src/dynarec/rv64/rv64_emitter.h9
5 files changed, 141 insertions, 8 deletions
diff --git a/src/dynarec/rv64/dynarec_rv64_00.c b/src/dynarec/rv64/dynarec_rv64_00.c
index 20cb4ecd..a7be6681 100644
--- a/src/dynarec/rv64/dynarec_rv64_00.c
+++ b/src/dynarec/rv64/dynarec_rv64_00.c
@@ -1445,6 +1445,10 @@ uintptr_t dynarec64_00(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
             addr = dynarec64_DB(dyn, addr, ip, ninst, rex, rep, ok, need_epilog);
             break;
 
+        case 0xDF:
+            addr = dynarec64_DF(dyn, addr, ip, ninst, rex, rep, ok, need_epilog);
+            break;
+
         case 0xE8:
             INST_NAME("CALL Id");
             i32 = F32S;
diff --git a/src/dynarec/rv64/dynarec_rv64_d8.c b/src/dynarec/rv64/dynarec_rv64_d8.c
index f7232a18..beadb202 100644
--- a/src/dynarec/rv64/dynarec_rv64_d8.c
+++ b/src/dynarec/rv64/dynarec_rv64_d8.c
@@ -44,21 +44,22 @@ uintptr_t dynarec64_D8(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
 
     switch(nextop) {
         case 0xC0 ... 0xC7:
-            DEFAULT;
+        
         case 0xC8 ... 0xCF:
-            DEFAULT;
+
         case 0xD0 ... 0xD7:
-            DEFAULT;
+
         case 0xD8 ... 0xDF:
-            DEFAULT;
+
         case 0xE0 ... 0xE7:
-            DEFAULT;
+
         case 0xE8 ... 0xEF:
-            DEFAULT;
+
         case 0xF0 ... 0xF7:
-            DEFAULT;
+
         case 0xF8 ... 0xFF:
             DEFAULT;
+            break;
 
         default:
             switch((nextop>>3)&7) {
diff --git a/src/dynarec/rv64/dynarec_rv64_df.c b/src/dynarec/rv64/dynarec_rv64_df.c
new file mode 100644
index 00000000..47f9579c
--- /dev/null
+++ b/src/dynarec/rv64/dynarec_rv64_df.c
@@ -0,0 +1,119 @@
+#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_DF(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, u8;
+    int v1, v2;
+    int s0;
+    int64_t j64;
+    int64_t fixedaddress;
+
+    MAYUSE(s0);
+    MAYUSE(v2);
+    MAYUSE(v1);
+    MAYUSE(j64);
+
+    switch(nextop) {
+        case 0xC0 ... 0xC7:
+        
+        case 0xE0:
+        
+        case 0xE8 ... 0xEF:
+            DEFAULT;
+            break;
+        
+        case 0xF0 ... 0xF7:
+            INST_NAME("FCOMIP ST0, STx");
+            SETFLAGS(X_ALL, SF_SET);
+            v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop&7));
+            v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7, X87_COMBINE(0, nextop&7));
+            CLEAR_FLAGS();
+            IFX(F_ZF | F_PF | F_CF) {
+                if(ST_IS_F(0)) {
+                    FEQS(x5, v1, v1);
+                    FEQS(x4, v2, v2);
+                    AND(x5, x5, x4);
+                    BEQZ(x5, 24); // undefined/NaN
+                    FEQS(x5, v1, v2);
+                    BNEZ(x5, 24); // equal
+                    FLTS(x3, v1, v2); // x3 = (v1<v2)?1:0
+                    OR(xFlags, xFlags, x3); // CF is the least significant bit
+                    JAL_gen(xZR, 16); // end
+                    // NaN
+                    ORI(xFlags, xFlags, (1<<F_ZF) | (1<<F_PF) | (1<<F_CF));
+                    JAL_gen(xZR, 8); // end
+                    // equal
+                    ORI(xFlags, xFlags, 1<<F_ZF);
+                    // end
+                } else {
+                    FEQD(x5, v1, v1);
+                    FEQD(x4, v2, v2);
+                    AND(x5, x5, x4);
+                    BEQZ(x5, 24); // undefined/NaN
+                    FEQD(x5, v1, v2);
+                    BNEZ(x5, 24); // equal
+                    FLTD(x3, v1, v2); // x3 = (v1<v2)?1:0
+                    OR(xFlags, xFlags, x3); // CF is the least significant bit
+                    JAL_gen(xZR, 16); // end
+                    // NaN
+                    ORI(xFlags, xFlags, (1<<F_ZF) | (1<<F_PF) | (1<<F_CF));
+                    JAL_gen(xZR, 8); // end
+                    // equal
+                    ORI(xFlags, xFlags, 1<<F_ZF);
+                    // end
+                }
+            }
+            x87_do_pop(dyn, ninst, x3);
+            break;
+        case 0xC8 ... 0xDF:
+        case 0xE1 ... 0xE7:
+        case 0xF8 ... 0xFF:
+            DEFAULT;
+            break;
+
+        default:
+            switch((nextop>>3)&7) {
+                case 0:
+                    INST_NAME("FILD ST0, Ew");
+                    v1 = x87_do_push(dyn, ninst, x1, EXT_CACHE_ST_F);
+                    addr = geted(dyn, addr, ninst, nextop, &wback, x3, x4, &fixedaddress, rex, NULL, 1, 0);
+                    LH(x1, wback, fixedaddress);
+                    if(ST_IS_F(0)) {
+                        FCVTSL(v1, x1);
+                    } else {
+                        FCVTDL(v1, x1);
+                    }
+                    break;
+                default:
+                    DEFAULT;
+                    break;
+            }
+    }
+    return addr;
+}
\ No newline at end of file
diff --git a/src/dynarec/rv64/dynarec_rv64_helper.h b/src/dynarec/rv64/dynarec_rv64_helper.h
index 17c7187e..4c8651c3 100644
--- a/src/dynarec/rv64/dynarec_rv64_helper.h
+++ b/src/dynarec/rv64/dynarec_rv64_helper.h
@@ -1008,7 +1008,7 @@ uintptr_t dynarec64_DB(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
 //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_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_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);
 uintptr_t dynarec64_660F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int* ok, int* need_epilog);
 //uintptr_t dynarec64_6664(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int seg, int* ok, int* need_epilog);
diff --git a/src/dynarec/rv64/rv64_emitter.h b/src/dynarec/rv64/rv64_emitter.h
index 4f75e518..f3d2f4b1 100644
--- a/src/dynarec/rv64/rv64_emitter.h
+++ b/src/dynarec/rv64/rv64_emitter.h
@@ -396,6 +396,11 @@ f28–31  ft8–11  FP temporaries                  Caller
 #define FMINS(frd, frs1, frs2)      EMIT(R_type(0b0010100, frs2, frs1, 0b000, frd, 0b1010011))
 #define FMAXS(frd, frs1, frs2)      EMIT(R_type(0b0010100, frs2, frs1, 0b001, frd, 0b1010011))
 
+// compare
+#define FEQS(rd, frs1, frs2)        EMIT(R_type(0b1010000, frs2, frs1, 0b010, rd, 0b1010011))
+#define FLTS(rd, frs1, frs2)        EMIT(R_type(0b1010000, frs2, frs1, 0b001, rd, 0b1010011))
+#define FLES(rd, frs1, frs2)        EMIT(R_type(0b1010000, frs2, frs1, 0b000, rd, 0b1010011))
+
 // RV64F
 // Convert from signed 64bits to Single
 #define FCVTSL(frd, rs1)             EMIT(R_type(0b1101000, 0b00010, rs1, 0b000, frd, 0b1010011))
@@ -431,6 +436,10 @@ f28–31  ft8–11  FP temporaries                  Caller
 // Convert from signed 32bits to Double
 #define FCVTDW(frd, rs1)             EMIT(R_type(0b1101001, 0b00000, rs1, 0b000, frd, 0b1010011))
 
+#define FEQD(rd, frs1, frs2)        EMIT(R_type(0b1010001, frs2, frs1, 0b010, rd, 0b1010011))
+#define FLTD(rd, frs1, frs2)        EMIT(R_type(0b1010001, frs2, frs1, 0b001, rd, 0b1010011))
+#define FLED(rd, frs1, frs2)        EMIT(R_type(0b1010001, frs2, frs1, 0b000, rd, 0b1010011))
+
 #define FADDD(frd, frs1, frs2)      EMIT(R_type(0b0000001, frs2, frs1, 0b000, frd, 0b1010011))
 #define FSUBD(frd, frs1, frs2)      EMIT(R_type(0b0000101, frs2, frs1, 0b000, frd, 0b1010011))
 #define FMULD(frd, frs1, frs2)      EMIT(R_type(0b0001001, frs2, frs1, 0b000, frd, 0b1010011))