about summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
authorptitSeb <sebastien.chev@gmail.com>2023-03-22 10:50:16 +0000
committerptitSeb <sebastien.chev@gmail.com>2023-03-22 10:50:16 +0000
commit5c4f0de1d0de47f619c192d85c538b6f85d00843 (patch)
tree822fcef43e13d76870e8b911c93c12b24964dc09 /src
parentb9c1b1a5eacd444a00e5837ec44d6ba42ef65bb6 (diff)
downloadbox64-5c4f0de1d0de47f619c192d85c538b6f85d00843.tar.gz
box64-5c4f0de1d0de47f619c192d85c538b6f85d00843.zip
[RV64_DYNAREC] Added some x87 D9 opcodes
Diffstat (limited to 'src')
-rw-r--r--src/dynarec/rv64/dynarec_rv64_00.c4
-rw-r--r--src/dynarec/rv64/dynarec_rv64_db.c249
-rw-r--r--src/dynarec/rv64/dynarec_rv64_helper.h2
-rw-r--r--src/dynarec/rv64/rv64_emitter.h11
4 files changed, 265 insertions, 1 deletions
diff --git a/src/dynarec/rv64/dynarec_rv64_00.c b/src/dynarec/rv64/dynarec_rv64_00.c
index 7d382802..ec46d1e5 100644
--- a/src/dynarec/rv64/dynarec_rv64_00.c
+++ b/src/dynarec/rv64/dynarec_rv64_00.c
@@ -1056,6 +1056,10 @@ uintptr_t dynarec64_00(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
             addr = dynarec64_D9(dyn, addr, ip, ninst, rex, rep, ok, need_epilog);
             break;
 
+        case 0xDB:
+            addr = dynarec64_DB(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_db.c b/src/dynarec/rv64/dynarec_rv64_db.c
new file mode 100644
index 00000000..b31ed9ad
--- /dev/null
+++ b/src/dynarec/rv64/dynarec_rv64_db.c
@@ -0,0 +1,249 @@
+#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_DB(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;
+    uint8_t wback;
+    uint8_t u8;
+    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("FCMOVNB ST0, STx");
+            READFLAGS(X_CF);
+            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));
+            ANDI(x1, xFlags, 1<<F_CF);
+            CBNZ_NEXT(x1);
+            if(ST_IS_F(0)) {
+                FMVS(v1, v2);
+            } else {
+                FMVD(v1, v2);    // F_CF==0
+            }
+            break;
+        case 0xC8:
+        case 0xC9:
+        case 0xCA:
+        case 0xCB:
+        case 0xCC:
+        case 0xCD:
+        case 0xCE:
+        case 0xCF:
+            INST_NAME("FCMOVNE ST0, STx");
+            READFLAGS(X_ZF);
+            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));
+            ANDI(x1, xFlags, 1<<F_ZF);
+            CBNZ_NEXT(x1);
+            if(ST_IS_F(0)) {
+                FMVS(v1, v2);
+            } else {
+                FMVD(v1, v2);        // F_ZF==0
+            }
+            break;
+        case 0xD0:
+        case 0xD1:
+        case 0xD2:
+        case 0xD3:
+        case 0xD4:
+        case 0xD5:
+        case 0xD6:
+        case 0xD7:
+            INST_NAME("FCMOVNBE ST0, STx");
+            READFLAGS(X_CF|X_ZF);
+            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));
+            ANDI(x1, xFlags, (1<<F_CF)|(1<<F_ZF));
+            CBNZ_NEXT(x1);
+            if(ST_IS_F(0)) {
+                FMVS(v1, v2);
+            } else {
+                FMVD(v1, v2);   // F_CF==0 & F_ZF==0
+            }
+            break;
+        case 0xD8:
+        case 0xD9:
+        case 0xDA:
+        case 0xDB:
+        case 0xDC:
+        case 0xDD:
+        case 0xDE:
+        case 0xDF:
+            INST_NAME("FCMOVNU ST0, STx");
+            READFLAGS(X_PF);
+            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));
+            ANDI(x1, xFlags, 1<<F_PF);
+            CBNZ_NEXT(x1);
+            if(ST_IS_F(0)) {
+                FMVS(v1, v2);
+            } else {
+                FMVD(v1, v2);        // F_PF==0
+            }
+            break;
+        case 0xE1:
+            INST_NAME("FDISI8087_NOP"); // so.. NOP?
+            break;
+        case 0xE2:
+            INST_NAME("FNCLEX");
+            LH(x2, xEmu, offsetof(x64emu_t, sw));
+            ANDI(x2, x2, ~(0xff));  // IE .. PE, SF, ES
+            MOV32w(x1, ~(1<<15));   // B
+            AND(x2, x2, x1);
+            SH(x2, xEmu, offsetof(x64emu_t, sw));
+            break;
+        case 0xE3:
+            INST_NAME("FNINIT");
+            MESSAGE(LOG_DUMP, "Need Optimization\n");
+            x87_purgecache(dyn, ninst, 0, x1, x2, x3);
+            CALL(reset_fpu, -1);
+            break;
+        case 0xE8:
+        case 0xE9:
+        case 0xEA:
+        case 0xEB:
+        case 0xEC:
+        case 0xED:
+        case 0xEE:
+        case 0xEF:
+            INST_NAME("FUCOMI ST0, STx");
+            DEFAULT;
+            break;
+        case 0xF0:  
+        case 0xF1:
+        case 0xF2:
+        case 0xF3:
+        case 0xF4:
+        case 0xF5:
+        case 0xF6:
+        case 0xF7:
+            INST_NAME("FCOMI ST0, STx");
+            DEFAULT;
+            break;
+
+        case 0xE0:
+        case 0xE4:
+        case 0xE5:
+        case 0xE6:
+        case 0xE7:
+            DEFAULT;
+            break;
+
+        default:
+            switch((nextop>>3)&7) {
+                case 0:
+                    INST_NAME("FILD ST0, Ed");
+                    v1 = x87_do_push(dyn, ninst, x1, EXT_CACHE_ST_D);
+                    addr = geted(dyn, addr, ninst, nextop, &ed, x2, x1, &fixedaddress, rex, NULL, 1, 0);
+                    LW(x1, ed, fixedaddress);
+                    FCVTDW(v1, x1);    // i32 -> double
+                    break;
+                case 1:
+                    INST_NAME("FISTTP Ed, ST0");
+                    DEFAULT;
+                    break;
+                case 2:
+                    INST_NAME("FIST Ed, ST0");
+                    DEFAULT;
+                    break;
+                case 3:
+                    INST_NAME("FISTP Ed, ST0");
+                    DEFAULT;
+                    break;
+                case 5:
+                    INST_NAME("FLD tbyte");
+                    addr = geted(dyn, addr, ninst, nextop, &ed, x1, x2, &fixedaddress, rex, NULL, 0, 0);
+                    if((PK(0)==0xDB && ((PK(1)>>3)&7)==7) || (PK(0)>=0x40 && PK(0)<=0x4f && PK(1)==0xDB && ((PK(2)>>3)&7)==7)) {
+                        // the FLD is immediatly followed by an FSTP
+                        LD(x5, ed, 0);
+                        LH(x6, ed, 8);
+                        // no persistant scratch register, so unrool both instruction here...
+                        MESSAGE(LOG_DUMP, "\tHack: FSTP tbyte\n");
+                        nextop = F8;    // 0xDB or rex
+                        if(nextop>=0x40 && nextop<=0x4f) {
+                            rex.rex = nextop;
+                            nextop = F8;    //0xDB
+                        } else
+                            rex.rex = 0;
+                        nextop = F8;    //modrm
+                        addr = geted(dyn, addr, ninst, nextop, &ed, x1, x2, &fixedaddress, rex, NULL, 0, 0);
+                        SD(x5, ed, 0);
+                        SH(x6, ed, 8);
+                    } else {
+                        if(box64_x87_no80bits) {
+                            v1 = x87_do_push(dyn, ninst, x1, EXT_CACHE_ST_D);
+                            FLD(v1, ed, fixedaddress);
+                        } else {
+                            if(ed!=x1) {
+                                MV(x1, ed);
+                            }
+                            x87_do_push_empty(dyn, ninst, x3);
+                            CALL(native_fld, -1);
+                        }
+                    }
+                    break;
+                case 7:
+                    INST_NAME("FSTP tbyte");
+                    if(box64_x87_no80bits) {
+                        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);
+                    } else {
+                        x87_forget(dyn, ninst, x1, x3, 0);
+                        addr = geted(dyn, addr, ninst, nextop, &ed, x1, x2, &fixedaddress, rex, NULL, 0, 0);
+                        if(ed!=x1) {
+                            MV(x1, ed);
+                        }
+                        CALL(native_fstp, -1);
+                    }
+                    x87_do_pop(dyn, ninst, x3);
+                    break;
+                default:
+                    DEFAULT;
+            }
+    }
+    return addr;
+}
diff --git a/src/dynarec/rv64/dynarec_rv64_helper.h b/src/dynarec/rv64/dynarec_rv64_helper.h
index d803da35..eb758e5f 100644
--- a/src/dynarec/rv64/dynarec_rv64_helper.h
+++ b/src/dynarec/rv64/dynarec_rv64_helper.h
@@ -892,7 +892,7 @@ uintptr_t dynarec64_66(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
 //uintptr_t dynarec64_D8(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_D9(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_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_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_DE(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog);
diff --git a/src/dynarec/rv64/rv64_emitter.h b/src/dynarec/rv64/rv64_emitter.h
index ab12fa55..242f27ee 100644
--- a/src/dynarec/rv64/rv64_emitter.h
+++ b/src/dynarec/rv64/rv64_emitter.h
@@ -382,6 +382,13 @@ f28–31  ft8–11  FP temporaries                  Caller
 #define FMVXW(rd, frs1)             EMIT(R_type(0b1110000, 0b00000, frs1, 0b000, rd, 0b1010011))
 // Move to Single
 #define FMVWX(frd, rs1)             EMIT(R_type(0b1111000, 0b00000, rs1, 0b000, frd, 0b1010011))
+// Convert from signed 32bits to Single
+#define FCVTSW(frd, rs1)             EMIT(R_type(0b1101000, 0b00000, rs1, 0b000, frd, 0b1010011))
+
+// RV64F
+// Convert from signed 64bits to Single
+#define FCVTSL(frd, rs1)             EMIT(R_type(0b1101000, 0b00010, rs1, 0b000, frd, 0b1010011))
+
 
 // RV32D
 // load double precision from rs1+imm12 to frd
@@ -404,11 +411,15 @@ f28–31  ft8–11  FP temporaries                  Caller
 #define FSGNJXD(rd, rs1, rs2)       EMIT(R_type(0b0010001, rs2, rs1, 0b010, rd, 0b1010011))
 // |rs1| => rd
 #define FABSD(rd, rs1)              FSGNJXD(rd, rs1, rs1)
+// Convert from signed 32bits to Double
+#define FCVTDW(frd, rs1)             EMIT(R_type(0b1101001, 0b00000, rs1, 0b000, frd, 0b1010011))
 
 //RV64D
 // Move from Double
 #define FMVXD(rd, frs1)             EMIT(R_type(0b1110001, 0b00000, frs1, 0b000, rd, 0b1010011))
 // Move to Double
 #define FMVDX(frd, rs1)             EMIT(R_type(0b1111001, 0b00000, rs1, 0b000, frd, 0b1010011))
+// Convert from signed 64bits to Double
+#define FCVTDL(frd, rs1)             EMIT(R_type(0b1101001, 0b00010, rs1, 0b000, frd, 0b1010011))
 
 #endif //__RV64_EMITTER_H__