about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorYang Liu <numbksco@gmail.com>2024-05-23 02:00:22 +0800
committerGitHub <noreply@github.com>2024-05-22 20:00:22 +0200
commit229cae16d1801b83bdee0a95c5515858df209876 (patch)
treeb887d9b22e9c92e2abc3f20f319d48c482420d95
parent9edb89fc222e06e76e3299871bd7c34c9910879f (diff)
downloadbox64-229cae16d1801b83bdee0a95c5515858df209876.tar.gz
box64-229cae16d1801b83bdee0a95c5515858df209876.zip
[LA64_DYNAREC] Fixed some non-lbt flags comutation issues (#1520)
-rw-r--r--src/dynarec/la64/dynarec_la64_emit_math.c8
-rw-r--r--src/dynarec/la64/dynarec_la64_emit_shift.c3
-rw-r--r--src/dynarec/la64/la64_emitter.h16
3 files changed, 17 insertions, 10 deletions
diff --git a/src/dynarec/la64/dynarec_la64_emit_math.c b/src/dynarec/la64/dynarec_la64_emit_math.c
index bee0acfa..50a8b103 100644
--- a/src/dynarec/la64/dynarec_la64_emit_math.c
+++ b/src/dynarec/la64/dynarec_la64_emit_math.c
@@ -285,7 +285,7 @@ void emit_add8(dynarec_la64_t* dyn, int ninst, int s1, int s2, int s3, int s4)
 
     IFX(X_AF | X_OF) {
         ANDN(s3, s3, s1); // s3 = ~res & (op1 | op2)
-        OR(s3, s3, s2);   // cc = (~res & (op1 | op2)) | (op1 & op2)
+        OR(s3, s3, s4);   // cc = (~res & (op1 | op2)) | (op1 & op2)
         IFX(X_AF) {
             ANDI(s4, s3, 0x08); // AF: cc & 0x08
             BEQZ(s4, 8);
@@ -985,7 +985,7 @@ void emit_neg32(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s
         return;
     }
 
-    CLEAR_FLAGS(s3);
+    CLEAR_FLAGS(s2);
     IFX (X_CF) {
         BEQZ(s1, 8);
         ORI(xFlags, xFlags, 1 << F_CF);
@@ -1059,6 +1059,8 @@ void emit_adc32(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s
             AND(s5, xMASK, s1);
             AND(s4, xMASK, s2);
             ADD_D(s5, s5, s4); // lo
+            ANDI(s3, xFlags, 1);
+            ADD_D(s5, s5, s3); // add carry
             SRLI_D(s3, s1, 0x20);
             SRLI_D(s4, s2, 0x20);
             ADD_D(s4, s4, s3);
@@ -1069,6 +1071,8 @@ void emit_adc32(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s
             AND(s3, s1, xMASK);
             AND(s4, s2, xMASK);
             ADD_D(s5, s3, s4);
+            ANDI(s3, xFlags, 1);
+            ADD_D(s5, s5, s3); // add carry
             SRLI_D(s6, s5, 0x20);
         }
     }
diff --git a/src/dynarec/la64/dynarec_la64_emit_shift.c b/src/dynarec/la64/dynarec_la64_emit_shift.c
index 28f8b849..1fe8aba8 100644
--- a/src/dynarec/la64/dynarec_la64_emit_shift.c
+++ b/src/dynarec/la64/dynarec_la64_emit_shift.c
@@ -721,6 +721,9 @@ void emit_rol32(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s
         ANDI(s4, s2, 0x1f);
     }
 
+    if (!rex.w) ZEROUP(s1);
+    BEQ_NEXT(s4, xZR);
+
     SLLxw(s3, s1, s4);
     NEG_D(s4, s4);
     ADDI_D(s4, s4, rex.w ? 64 : 32);
diff --git a/src/dynarec/la64/la64_emitter.h b/src/dynarec/la64/la64_emitter.h
index 29713ca6..6e2139e3 100644
--- a/src/dynarec/la64/la64_emitter.h
+++ b/src/dynarec/la64/la64_emitter.h
@@ -362,14 +362,14 @@ f24-f31  fs0-fs7   Static registers                Callee
         }                         \
     } while (0)
 // Shift Right Logical Immediate
-#define SRLIxw(rd, rs1, imm)          \
-    do {                              \
-        if (rex.w) {                  \
-            SRLI_D(rd, rs1, imm);     \
-        } else {                      \
-            SRLI_W(rd, rs1, imm);     \
-            if (imm == 0) ZEROUP(rd); \
-        }                             \
+#define SRLIxw(rd, rs1, imm)            \
+    do {                                \
+        if (rex.w) {                    \
+            SRLI_D(rd, rs1, imm);       \
+        } else {                        \
+            SRLI_W(rd, rs1, imm);       \
+            if ((imm) == 0) ZEROUP(rd); \
+        }                               \
     } while (0)
 
 // Shift Right Arithmetic Immediate