about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorptitSeb <sebastien.chev@gmail.com>2024-03-08 18:01:33 +0100
committerptitSeb <sebastien.chev@gmail.com>2024-03-08 18:01:33 +0100
commit3737abe081c8de2ffb8d4fd10fea01c046c4787b (patch)
tree2e01ad5060ebd97aadcb4b9f6654dbc079616cba
parentd0013c07007e8aa6e243443961ec2fab9daac624 (diff)
downloadbox64-3737abe081c8de2ffb8d4fd10fea01c046c4787b.tar.gz
box64-3737abe081c8de2ffb8d4fd10fea01c046c4787b.zip
[ARM64_DYNAREC][RV64_DYNAREC] Fixed some case where MOVS/B/W/D/Q is used on a protected page of code, and SI gets wrongly incremented (for #1347)
-rw-r--r--src/dynarec/arm64/dynarec_arm64_6764_32.c3
-rw-r--r--src/dynarec/rv64/dynarec_rv64_00_2.c4
-rw-r--r--src/dynarec/rv64/dynarec_rv64_66.c4
-rw-r--r--src/libtools/signals.c51
4 files changed, 57 insertions, 5 deletions
diff --git a/src/dynarec/arm64/dynarec_arm64_6764_32.c b/src/dynarec/arm64/dynarec_arm64_6764_32.c
index 12f74409..58abbf4b 100644
--- a/src/dynarec/arm64/dynarec_arm64_6764_32.c
+++ b/src/dynarec/arm64/dynarec_arm64_6764_32.c
@@ -90,11 +90,12 @@ uintptr_t dynarec64_6764_32(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, in
         case 0x8F:
             INST_NAME("POP Seg:Ed");
             nextop=F8;
-            POP1_32(x1);
             if(MODREG) {   // reg <= reg
+                POP1_32(x1);
                 MOVxw_REG(xRAX+(nextop&7)+(rex.b<<3), x1);
             } else {                    // mem <= reg
                 grab_segdata(dyn, addr, ninst, x4, seg);
+                POP1_32(x1);
                 addr = geted16(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, NULL, 0, 0, 0);
                 STRw_REG(x1, ed, x4);
             }
diff --git a/src/dynarec/rv64/dynarec_rv64_00_2.c b/src/dynarec/rv64/dynarec_rv64_00_2.c
index e75e56d5..6dc4f3c5 100644
--- a/src/dynarec/rv64/dynarec_rv64_00_2.c
+++ b/src/dynarec/rv64/dynarec_rv64_00_2.c
@@ -590,16 +590,16 @@ uintptr_t dynarec64_00_2(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
                 BNEZ_MARK2(x1);
                 MARK;   // Part with DF==0
                 LDxw(x1, xRSI, 0);
-                ADDI(xRSI, xRSI, rex.w?8:4);
                 SDxw(x1, xRDI, 0);
+                ADDI(xRSI, xRSI, rex.w?8:4);
                 ADDI(xRDI, xRDI, rex.w?8:4);
                 SUBI(xRCX, xRCX, 1);
                 BNEZ_MARK(xRCX);
                 B_NEXT_nocond;
                 MARK2;  // Part with DF==1
                 LDxw(x1, xRSI, 0);
-                SUBI(xRSI, xRSI, rex.w?8:4);
                 SDxw(x1, xRDI, 0);
+                SUBI(xRSI, xRSI, rex.w?8:4);
                 SUBI(xRDI, xRDI, rex.w?8:4);
                 SUBI(xRCX, xRCX, 1);
                 BNEZ_MARK2(xRCX);
diff --git a/src/dynarec/rv64/dynarec_rv64_66.c b/src/dynarec/rv64/dynarec_rv64_66.c
index 24b3bfb0..06ac0fe1 100644
--- a/src/dynarec/rv64/dynarec_rv64_66.c
+++ b/src/dynarec/rv64/dynarec_rv64_66.c
@@ -752,8 +752,8 @@ uintptr_t dynarec64_66(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
                 BNEZ_MARK2(x1);
                 MARK;   // Part with DF==0
                 LH(x1, xRSI, 0);
-                ADDI(xRSI, xRSI, 2);
                 SH(x1, xRDI, 0);
+                ADDI(xRSI, xRSI, 2);
                 ADDI(xRDI, xRDI, 2);
                 SUBI(xRCX, xRCX, 1);
                 BNEZ_MARK(xRCX);
@@ -767,7 +767,7 @@ uintptr_t dynarec64_66(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
                 BNEZ_MARK2(xRCX);
                 // done
             } else {
-                INST_NAME("MOVSD");
+                INST_NAME("MOVSW");
                 GETDIR(x3, x1, 2);
                 LH(x1, xRSI, 0);
                 SH(x1, xRDI, 0);
diff --git a/src/libtools/signals.c b/src/libtools/signals.c
index 5ca91776..a9336ed8 100644
--- a/src/libtools/signals.c
+++ b/src/libtools/signals.c
@@ -509,6 +509,56 @@ x64emu_t* getEmuSignal(x64emu_t* emu, ucontext_t* p, dynablock_t* db)
 }
 #endif
 
+void adjustregs(x64emu_t* emu) {
+// tests some special cases
+    uint8_t* mem = (uint8_t*)R_RIP;
+    rex_t rex = {0};
+    int rep = 0;
+    int is66 = 0;
+    int idx = 0;
+    rex.is32bits = (R_CS==0x0023);
+    while ((mem[idx]>=0x40 && mem[idx]<=0x4f && !rex.is32bits) || mem[idx]==0xF2 || mem[idx]==0xF3 || mem[idx]==0x66) {
+        switch(mem[idx]) {
+            case 0x40 ... 0x4f:
+                rex.rex = mem[idx];
+                break;
+            case 0xF2:
+            case 0xF3:
+                rep = mem[idx]-0xF1;
+                break;
+            case 0x66:
+                is66 = 1;
+                break;
+        }
+        ++idx;
+    }
+#ifdef DYNAREC
+#ifdef ARM64
+    if(mem[idx+0]==0xA4) {
+        // (rep) movsb, read done, write not...
+        if(emu->eflags.f._F_DF)
+            R_RSI++;
+        else
+            R_RSI--;
+        return;
+    }
+    if(mem[idx+0]==0xA5) {
+        // (rep) movsd, read done, write not...
+        int step = (emu->eflags.f._F_DF)?-1:+1;
+        if(rex.w) step*=8;
+        else if(is66) step *=2;
+        else step*=4;
+        R_RSI-=step;
+        return;
+    }
+#elif defined(LA64)
+#elif defined(RV64)
+#else
+#error  Unsupported architecture
+#endif
+#endif
+}
+
 void copyUCTXreg2Emu(x64emu_t* emu, ucontext_t* p, uintptr_t ip) {
 #ifdef DYNAREC
 #ifdef ARM64
@@ -1356,6 +1406,7 @@ void my_box64signalhandler(int32_t sig, siginfo_t* info, void * ucntx)
             // dynablock got auto-dirty! need to get out of it!!!
             if(emu->jmpbuf) {
                 copyUCTXreg2Emu(emu, p, getX64Address(db, (uintptr_t)pc));
+                adjustregs(emu);
 #ifdef ARM64
                 //TODO: Need proper SIMD/x87 register traking!
                 /*if(fpsimd) {