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/rv64/dynarec_rv64_66.c42
-rw-r--r--src/dynarec/rv64/dynarec_rv64_d8.c55
-rw-r--r--src/dynarec/rv64/dynarec_rv64_dc.c50
-rw-r--r--src/dynarec/rv64/dynarec_rv64_f0.c52
4 files changed, 179 insertions, 20 deletions
diff --git a/src/dynarec/rv64/dynarec_rv64_66.c b/src/dynarec/rv64/dynarec_rv64_66.c
index 6e13c867..e78310f9 100644
--- a/src/dynarec/rv64/dynarec_rv64_66.c
+++ b/src/dynarec/rv64/dynarec_rv64_66.c
@@ -651,6 +651,48 @@ uintptr_t dynarec64_66(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
                 ADD(xRDI, xRDI, x3);
             }
             break;
+        case 0xA7:
+            switch (rep) {
+                case 1:
+                case 2:
+                    if (rep == 1) { INST_NAME("REPNZ CMPSW"); } else { INST_NAME("REPZ CMPSW"); }
+                    MAYSETFLAGS();
+                    SETFLAGS(X_ALL, SF_SET_PENDING);
+                    CBZ_NEXT(xRCX);
+                    ANDI(x1, xFlags, 1 << F_DF);
+                    BNEZ_MARK2(x1);
+                    MARK; // Part with DF==0
+                    LHU(x1, xRSI, 0);
+                    ADDI(xRSI, xRSI, 2);
+                    LHU(x2, xRDI, 0);
+                    ADDI(xRDI, xRDI, 2);
+                    SUBI(xRCX, xRCX, 1);
+                    if (rep == 1) { BEQ_MARK3(x1, x2); } else { BNE_MARK3(x1, x2); }
+                    BNEZ_MARK(xRCX);
+                    B_MARK3_nocond;
+                    MARK2; // Part with DF==1
+                    LHU(x1, xRSI, 0);
+                    SUBI(xRSI, xRSI, 2);
+                    LHU(x2, xRDI, 0);
+                    SUBI(xRDI, xRDI, 2);
+                    SUBI(xRCX, xRCX, 1);
+                    if (rep == 1) { BEQ_MARK3(x1, x2); } else { BNE_MARK3(x1, x2); }
+                    BNEZ_MARK2(xRCX);
+                    MARK3; // end
+                    emit_cmp16(dyn, ninst, x1, x2, x3, x4, x5, x6);
+                    break;
+                default:
+                    INST_NAME("CMPSW");
+                    SETFLAGS(X_ALL, SF_SET_PENDING);
+                    GETDIR(x3, x1, 2);
+                    LHU(x1, xRSI, 0);
+                    LHU(x2, xRDI, 0);
+                    ADD(xRSI, xRSI, x3);
+                    ADD(xRDI, xRDI, x3);
+                    emit_cmp16(dyn, ninst, x1, x2, x3, x4, x5, x6);
+                    break;
+            }
+            break;
         case 0xA9:
             INST_NAME("TEST AX,Iw");
             SETFLAGS(X_ALL, SF_SET_PENDING);
diff --git a/src/dynarec/rv64/dynarec_rv64_d8.c b/src/dynarec/rv64/dynarec_rv64_d8.c
index 3f7f2314..885eebfd 100644
--- a/src/dynarec/rv64/dynarec_rv64_d8.c
+++ b/src/dynarec/rv64/dynarec_rv64_d8.c
@@ -53,10 +53,24 @@ uintptr_t dynarec64_D8(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
             }
             break;
         case 0xC8 ... 0xCF:
-            DEFAULT;
+            INST_NAME("FMUL ST0, STx");
+            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));
+            if (ST_IS_F(0)) {
+                FMULS(v1, v1, v2);
+            } else {
+                FMULD(v1, v1, v2);
+            }
             break;
         case 0xD0 ... 0xD7:
-            DEFAULT;
+            INST_NAME("FCOM ST0, STx");
+            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));
+            if (ST_IS_F(0)) {
+                FCOMS(v1, v2, x1, x2, x3, x4, x5);
+            } else {
+                FCOMD(v1, v2, x1, x2, x3, x4, x5);
+            }
             break;
         case 0xD8 ... 0xDF:
             INST_NAME("FCOMP ST0, STx");
@@ -80,12 +94,19 @@ uintptr_t dynarec64_D8(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
             }
             break;
         case 0xE8 ... 0xEF:
-            DEFAULT;
+            INST_NAME("FSUBR ST0, STx");
+            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));
+            if (ST_IS_F(0)) {
+                FSUBS(v1, v2, v1);
+            } else {
+                FSUBD(v1, v2, v1);
+            }
             break;
         case 0xF0 ... 0xF7:
             INST_NAME("FDIV ST0, STx");
-            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));
+            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));
             if(ST_IS_F(0)) {
                 FDIVS(v1, v1, v2);
             } else {
@@ -93,7 +114,14 @@ uintptr_t dynarec64_D8(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
             }
             break;
         case 0xF8 ... 0xFF:
-            DEFAULT;
+            INST_NAME("FDIVR ST0, STx");
+            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));
+            if (ST_IS_F(0)) {
+                FDIVS(v1, v2, v1);
+            } else {
+                FDIVD(v1, v2, v1);
+            }
             break;
 
         default:
@@ -164,6 +192,19 @@ uintptr_t dynarec64_D8(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
                         FSUBD(v1, v1, s0);
                     }
                     break;
+                case 5:
+                    INST_NAME("FSUBR ST0, float[ED]");
+                    v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_ST0);
+                    s0 = fpu_get_scratch(dyn);
+                    addr = geted(dyn, addr, ninst, nextop, &ed, x2, x1, &fixedaddress, rex, NULL, 1, 0);
+                    FLW(s0, ed, fixedaddress);
+                    if (ST_IS_F(0)) {
+                        FSUBS(v1, s0, v1);
+                    } else {
+                        FCVTDS(s0, s0);
+                        FSUBD(v1, s0, v1);
+                    }
+                    break;
                 case 6:
                     INST_NAME("FDIV ST0, float[ED]");
                     v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_ST0);
@@ -190,8 +231,6 @@ uintptr_t dynarec64_D8(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
                         FDIVD(v1, s0, v1);
                     }
                     break;
-                default:
-                    DEFAULT;
             }
     }
     return addr;
diff --git a/src/dynarec/rv64/dynarec_rv64_dc.c b/src/dynarec/rv64/dynarec_rv64_dc.c
index 7f680f00..006587b3 100644
--- a/src/dynarec/rv64/dynarec_rv64_dc.c
+++ b/src/dynarec/rv64/dynarec_rv64_dc.c
@@ -114,6 +114,30 @@ uintptr_t dynarec64_DC(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
             break;
         default:
             switch((nextop>>3)&7) {
+                case 0:
+                    INST_NAME("FADD ST0, double[ED]");
+                    v1 = x87_get_st(dyn, ninst, x1, x2, 0, EXT_CACHE_ST_D);
+                    v2 = fpu_get_scratch(dyn);
+                    addr = geted(dyn, addr, ninst, nextop, &wback, x2, x1, &fixedaddress, rex, NULL, 1, 0);
+                    FLD(v2, wback, fixedaddress);
+                    FADDD(v1, v1, v2);
+                    break;
+                case 1:
+                    INST_NAME("FMUL ST0, double[ED]");
+                    v1 = x87_get_st(dyn, ninst, x1, x2, 0, EXT_CACHE_ST_D);
+                    v2 = fpu_get_scratch(dyn);
+                    addr = geted(dyn, addr, ninst, nextop, &wback, x2, x1, &fixedaddress, rex, NULL, 1, 0);
+                    FLD(v2, wback, fixedaddress);
+                    FMULD(v1, v1, v2);
+                    break;
+                case 2:
+                    INST_NAME("FCOM ST0, double[ED]");
+                    v1 = x87_get_st(dyn, ninst, x1, x2, 0, EXT_CACHE_ST_D);
+                    v2 = fpu_get_scratch(dyn);
+                    addr = geted(dyn, addr, ninst, nextop, &wback, x2, x1, &fixedaddress, rex, NULL, 1, 0);
+                    FLD(v2, wback, fixedaddress);
+                    FCOMD(v1, v2, x1, x6, x3, x4, x5);
+                    break;
                 case 3:
                     INST_NAME("FCOMP ST0, double[ED]");
                     v1 = x87_get_st(dyn, ninst, x1, x2, 0, EXT_CACHE_ST_D);
@@ -123,6 +147,22 @@ uintptr_t dynarec64_DC(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
                     FCOMD(v1, v2, x1, x6, x3, x4, x5);
                     X87_POP_OR_FAIL(dyn, ninst, x3);
                     break;
+                case 4:
+                    INST_NAME("FSUB ST0, double[ED]");
+                    v1 = x87_get_st(dyn, ninst, x1, x2, 0, EXT_CACHE_ST_D);
+                    v2 = fpu_get_scratch(dyn);
+                    addr = geted(dyn, addr, ninst, nextop, &wback, x2, x1, &fixedaddress, rex, NULL, 1, 0);
+                    FLD(v2, wback, fixedaddress);
+                    FSUBD(v1, v1, v2);
+                    break;
+                case 5:
+                    INST_NAME("FSUBR ST0, double[ED]");
+                    v1 = x87_get_st(dyn, ninst, x1, x2, 0, EXT_CACHE_ST_D);
+                    v2 = fpu_get_scratch(dyn);
+                    addr = geted(dyn, addr, ninst, nextop, &wback, x2, x1, &fixedaddress, rex, NULL, 1, 0);
+                    FLD(v2, wback, fixedaddress);
+                    FSUBD(v1, v2, v1);
+                    break;
                 case 6:
                     INST_NAME("FDIV ST0, double[ED]");
                     v1 = x87_get_st(dyn, ninst, x1, x2, 0, EXT_CACHE_ST_D);
@@ -131,8 +171,14 @@ uintptr_t dynarec64_DC(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
                     FLD(v2, wback, fixedaddress);
                     FDIVD(v1, v1, v2);
                     break;
-                default:
-                    DEFAULT;
+                case 7:
+                    INST_NAME("FDIVR ST0, double[ED]");
+                    v1 = x87_get_st(dyn, ninst, x1, x2, 0, EXT_CACHE_ST_D);
+                    v2 = fpu_get_scratch(dyn);
+                    addr = geted(dyn, addr, ninst, nextop, &wback, x2, x1, &fixedaddress, rex, NULL, 1, 0);
+                    FLD(v2, wback, fixedaddress);
+                    FDIVD(v1, v2, v1);
+                    break;
             }
     }
     return addr;
diff --git a/src/dynarec/rv64/dynarec_rv64_f0.c b/src/dynarec/rv64/dynarec_rv64_f0.c
index 469ae5bb..d90aa34e 100644
--- a/src/dynarec/rv64/dynarec_rv64_f0.c
+++ b/src/dynarec/rv64/dynarec_rv64_f0.c
@@ -49,8 +49,9 @@ uintptr_t dynarec64_F0(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
 
     GETREX();
 
-    // TODO: Take care of unligned memory access for all the LOCK ones.
-    // https://github.com/ptitSeb/box64/pull/604
+    // TODO: Add support for unligned memory access for all the LOCK ones.
+    // TODO: Add support for BOX4_DYNAREC_ALIGNED_ATOMICS.
+
     switch(opcode) {
         case 0x01:
             INST_NAME("LOCK ADD Ed, Gd");
@@ -214,7 +215,6 @@ uintptr_t dynarec64_F0(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
                             } else {
                                 SMDMB();
                                 addr = geted(dyn, addr, ninst, nextop, &wback, x2, x1, &fixedaddress, rex, LOCK_LOCK, 0, 0);
-                                // TODO: Add support for BOX4_DYNAREC_ALIGNED_ATOMICS.
                                 ANDI(x1, wback, (1 << (rex.w + 2)) - 1);
                                 BNEZ_MARK3(x1);
                                 // Aligned
@@ -553,7 +553,8 @@ uintptr_t dynarec64_F0(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
                         SMDMB();
                         addr = geted(dyn, addr, ninst, nextop, &wback, x2, x1, &fixedaddress, rex, LOCK_LOCK, 0, (opcode==0x81)?4:1);
                         if(opcode==0x81) i64 = F32S; else i64 = F8S;
-                        // TODO: Add support for BOX4_DYNAREC_ALIGNED_ATOMICS.
+                        if (i64 < -2048 || i64 >= 2048)
+                            MOV64xw(x4, i64);
                         ANDI(x1, wback, (1 << (rex.w + 2)) - 1);
                         BNEZ_MARK3(x1);
                         // Aligned
@@ -561,10 +562,8 @@ uintptr_t dynarec64_F0(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
                         LRxw(x1, wback, 1, 1);
                         if (i64 >= -2048 && i64 < 2048)
                             ADDIxw(x4, x1, i64);
-                        else {
-                            MOV64xw(x4, i64);
+                        else
                             ADDxw(x4, x1, x4);
-                        }
                         SCxw(x3, x4, wback, 1, 1);
                         BNEZ_MARKLOCK(x3);
                         B_MARK_nocond;
@@ -576,10 +575,8 @@ uintptr_t dynarec64_F0(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
                         LRxw(x1, x5, 1, 1);
                         if (i64 >= -2048 && i64 < 2048)
                             ADDIxw(x4, x6, i64);
-                        else {
-                            MOV64xw(x4, i64);
+                        else
                             ADDxw(x4, x6, x4);
-                        }
                         SCxw(x3, x1, x5, 1, 1);
                         BNEZ_MARK2(x3);
                         SDxw(x4, wback, 0);
@@ -680,6 +677,41 @@ uintptr_t dynarec64_F0(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
             }
             SMDMB();
             break;
+        case 0x87:
+            INST_NAME("LOCK XCHG Ed, Gd");
+            nextop = F8;
+            if (MODREG) {
+                GETGD;
+                GETED(0);
+                MV(x1, gd);
+                MV(gd, ed);
+                MV(ed, x1);
+            } else {
+                SMDMB();
+                GETGD;
+                addr = geted(dyn, addr, ninst, nextop, &wback, x2, x1, &fixedaddress, rex, LOCK_LOCK, 0, 0);
+                ANDI(x1, wback, (1 << (rex.w + 2)) - 1);
+                BNEZ_MARK3(x1);
+                // Aligned
+                MARKLOCK;
+                LRxw(x1, wback, 1, 1);
+                SCxw(x4, gd, wback, 1, 1);
+                BNEZ_MARKLOCK(x4);
+                B_MARK_nocond;
+                MARK3;
+                // Unaligned
+                ANDI(x5, wback, -(1 << (rex.w + 2)));
+                MARK2; // Use MARK2 as a "MARKLOCK" since we're running out of marks.
+                LDxw(x1, wback, 0);
+                LRxw(x3, x5, 1, 1);
+                SCxw(x4, x3, x5, 1, 1);
+                BNEZ_MARK2(x4);
+                SDxw(gd, wback, 0);
+                MARK;
+                MVxw(gd, x1);
+                SMDMB();
+            }
+            break;
         case 0xFF:
             nextop = F8;
             switch((nextop>>3)&7)