about summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
authorYang Liu <liuyang22@iscas.ac.cn>2023-04-08 20:49:35 +0800
committerGitHub <noreply@github.com>2023-04-08 14:49:35 +0200
commit24a374500c3f0aa3579949c26fba24702ada74c8 (patch)
treee38b8b009a7e9e7bbd5cfbee4a2c4d1a4d70e94f /src
parentb9cd6d3505b567dc4f5e0848e74f495961de397a (diff)
downloadbox64-24a374500c3f0aa3579949c26fba24702ada74c8.tar.gz
box64-24a374500c3f0aa3579949c26fba24702ada74c8.zip
[RV64_DYNAREC] Added more opcodes for Stardew Valley and some fixes (#674)
* [RV64_DYNAREC] Added 86 (LOCK)XCHG opcode

* [RV64_DYNAREC] Added 66 0F 61 PUNPCKLWD opcode

* [RV64_DYNAREC] Added 66 0F 72 /4 PSRAD opcode

* [RV64_DYNAREC] Added F0 81,83 /5 LOCK SUB opcode

* [RV64_DYNAREC] Fixed 86 (LOCK) XCHG opcode

* [RV64_DYNAREC] Fixed 87 (LOCK) XCHG opcode again

* [RV64_DYNAREC] Fixed 86 (LOCK) XCHG opcode again

* [RV64_DYNAREC] Fixed 66 0F 72 /4 PSRAD opcode
Diffstat (limited to 'src')
-rw-r--r--src/dynarec/rv64/dynarec_rv64_00.c25
-rw-r--r--src/dynarec/rv64/dynarec_rv64_660f.c33
-rw-r--r--src/dynarec/rv64/dynarec_rv64_f0.c34
3 files changed, 87 insertions, 5 deletions
diff --git a/src/dynarec/rv64/dynarec_rv64_00.c b/src/dynarec/rv64/dynarec_rv64_00.c
index 0dae504d..2454662d 100644
--- a/src/dynarec/rv64/dynarec_rv64_00.c
+++ b/src/dynarec/rv64/dynarec_rv64_00.c
@@ -723,7 +723,28 @@ uintptr_t dynarec64_00(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
             GETED(0);
             emit_test32(dyn, ninst, rex, ed, gd, x3, x4, x5);
             break;
-
+        case 0x86:
+            INST_NAME("(LOCK)XCHG Eb, Gb");
+            nextop = F8;
+            if(MODREG) {
+                GETGB(x1);
+                GETEB(x2, 0);
+                MV(x4, gd);
+                MV(gd, ed);
+                MV(ed, x4);
+                GBBACK(x4);
+                EBBACK(x4, 0);
+            } else {
+                GETGB(x3);
+                addr = geted(dyn, addr, ninst, nextop, &ed, x2, x1, &fixedaddress, rex, LOCK_LOCK, 0, 0);
+                SMDMB();
+                LBU(x1, ed, 0);
+                SB(gd, ed, 0);
+                SMDMB();
+                gd = x1;
+                GBBACK(x3);
+            }
+            break;
         case 0x87:
             INST_NAME("(LOCK)XCHG Ed, Gd");
             nextop = F8;
@@ -738,7 +759,7 @@ uintptr_t dynarec64_00(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
                 addr = geted(dyn, addr, ninst, nextop, &ed, x2, x1, &fixedaddress, rex, LOCK_LOCK, 0, 0);
                 SMDMB();
                 ANDI(x3, ed, (1<<(2+rex.w))-1);
-                BEQ_MARK(x3, xZR);
+                BNE_MARK(x3, xZR);
                 MARKLOCK;
                 LRxw(x1, ed, 1, 0);
                 SCxw(x3, gd, ed, 0, 1);
diff --git a/src/dynarec/rv64/dynarec_rv64_660f.c b/src/dynarec/rv64/dynarec_rv64_660f.c
index 0de4e4eb..cbffe1c1 100644
--- a/src/dynarec/rv64/dynarec_rv64_660f.c
+++ b/src/dynarec/rv64/dynarec_rv64_660f.c
@@ -155,6 +155,30 @@ uintptr_t dynarec64_660F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
             GETGX(x2);
             SSE_LOOP_Q(x3, x4, XOR(x3, x3, x4));
             break;
+        case 0x61:
+            INST_NAME("PUNPCKLWD Gx,Ex");
+            nextop = F8;
+            GETEX(x1, 0);
+            GETGX(x2);
+            for(int i=3; i>0; --i) {
+                // GX->uw[2 * i] = GX->uw[i];
+                LHU(x3, gback, i*2);
+                SH(x3, gback, 2*i*2);
+            }
+            if (MODREG && (ed==gd)) {
+                for(int i=0; i<4; ++i) {
+                    // GX->uw[2 * i + 1] = GX->uw[2 * i];
+                    LHU(x3, gback, 2*i*2);
+                    SH(x3, gback, (2*i+1)*2);
+                }
+            } else {
+                for(int i=0; i<4; ++i) {
+                    // GX->uw[2 * i + 1] = EX->uw[i];
+                    LHU(x3, wback, fixedaddress+i*2);
+                    SH(x3, gback, (2*i+1)*2);
+                }
+            }
+            break;
         case 0x62:
             INST_NAME("PUNPCKLDQ Gx,Ex");
             nextop = F8;
@@ -256,6 +280,15 @@ uintptr_t dynarec64_660F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
                         }
                     }
                     break;
+                case 4:
+                    INST_NAME("PSRAD Ex, Ib");
+                    GETEX(x1, 1);
+                    u8 = F8;
+                    if(u8>31) u8=31;
+                    if (u8) {
+                        SSE_LOOP_DS(x3, SRAIW(x3, x3, u8));
+                    }
+                    break;
                 case 6:
                     INST_NAME("PSLLD Ex, Ib");
                     GETEX(x1, 1);
diff --git a/src/dynarec/rv64/dynarec_rv64_f0.c b/src/dynarec/rv64/dynarec_rv64_f0.c
index a14b4b18..ec3fb824 100644
--- a/src/dynarec/rv64/dynarec_rv64_f0.c
+++ b/src/dynarec/rv64/dynarec_rv64_f0.c
@@ -156,11 +156,11 @@ uintptr_t dynarec64_F0(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
                         if(opcode==0x81) i64 = F32S; else i64 = F8S;
                         MARKLOCK;
                         LRxw(x1, wback, 1, 1);
-                        if(i64>-2048 && i64<2047)
-                            ADDI(x4, x1, i64);
+                        if(i64>=-2048 && i64<2048)
+                            ADDIxw(x4, x1, i64);
                         else {
                             MOV64xw(x4, i64);
-                            ADD(x4, x1, x4);
+                            ADDxw(x4, x1, x4);
                         }
                         SCxw(x3, x4, wback, 1, 1);
                         BNEZ_MARKLOCK(x3);
@@ -168,6 +168,34 @@ uintptr_t dynarec64_F0(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
                             emit_add32c(dyn, ninst, rex, x1, i64, x3, x4, x5, x6);
                     }
                     break;
+                case 5: // SUB
+                    if(opcode==0x81) {
+                        INST_NAME("LOCK SUB Ed, Id");
+                    } else {
+                        INST_NAME("LOCK SUB Ed, Ib");
+                    }
+                    SETFLAGS(X_ALL, SF_SET_PENDING);
+                    if(MODREG) {
+                        if(opcode==0x81) i64 = F32S; else i64 = F8S;
+                        ed = xRAX+(nextop&7)+(rex.b<<3);
+                        emit_sub32(dyn, ninst, rex, ed, i64, x3, x4, x5);
+                    } else {
+                        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;
+                        MARKLOCK;
+                        LRxw(x1, wback, 1, 1);
+                        if (i64>-2048 && i64<=2048) {
+                            ADDIxw(x4, x1, -i64);
+                        } else {
+                            MOV64xw(x4, i64);
+                            SUBxw(x4, x1, x4);
+                        }
+                        SCxw(x3, x4, wback, 1, 1);
+                        BNEZ_MARKLOCK(x3);
+                        IFX(X_ALL|X_PEND)
+                            emit_sub32c(dyn, ninst, rex, x1, i64, x3, x4, x5, x6);
+                    }
+                    break;
                 default: 
                     DEFAULT;
             }