about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorYang Liu <numbksco@gmail.com>2024-03-01 00:10:47 +0800
committerGitHub <noreply@github.com>2024-02-29 17:10:47 +0100
commit8cba5d55cef4c9a0f047b6cd81e440144fb12e8f (patch)
treedbbeadd2df5922d0dc3aa5d93a677f0bd895447c
parentda1ac7beee6c1710329f6794a27a8b1296d649ce (diff)
downloadbox64-8cba5d55cef4c9a0f047b6cd81e440144fb12e8f.tar.gz
box64-8cba5d55cef4c9a0f047b6cd81e440144fb12e8f.zip
[LA64_DYNAREC] Added LBT support to all implemented emit functions and fixed some typos (#1303)
-rw-r--r--src/dynarec/la64/dynarec_la64_emit_math.c124
1 files changed, 100 insertions, 24 deletions
diff --git a/src/dynarec/la64/dynarec_la64_emit_math.c b/src/dynarec/la64/dynarec_la64_emit_math.c
index 45e09758..e5efec62 100644
--- a/src/dynarec/la64/dynarec_la64_emit_math.c
+++ b/src/dynarec/la64/dynarec_la64_emit_math.c
@@ -25,8 +25,7 @@
 void emit_add32(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4, int s5)
 {
     CLEAR_FLAGS();
-    IFX(X_PEND)
-    {
+    IFX(X_PEND) {
         if (rex.w) {
             ST_D(s1, xEmu, offsetof(x64emu_t, op1));
             ST_D(s2, xEmu, offsetof(x64emu_t, op2));
@@ -35,9 +34,7 @@ void emit_add32(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s
             ST_W(s2, xEmu, offsetof(x64emu_t, op2));
         }
         SET_DF(s3, rex.w ? d_add64 : d_add32b);
-    }
-    else IFX(X_ALL)
-    {
+    } else IFX(X_ALL) {
         SET_DFNONE();
     }
 
@@ -145,7 +142,7 @@ void emit_add32c(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, int64_t c, i
     IFX(X_PEND | X_AF | X_CF | X_OF)
     {
         MOV64xw(s2, c);
-    }
+    } else if (la64_lbt) MOV64xw(s2, c);
     IFX(X_PEND)
     {
         SDxw(s1, xEmu, offsetof(x64emu_t, op1));
@@ -156,6 +153,21 @@ void emit_add32c(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, int64_t c, i
     {
         SET_DFNONE();
     }
+
+    if (la64_lbt) {
+        IFX(X_ALL) {
+            X64_ADD_WU(s1, s2);
+            X64_GET_EFLAGS(s3, X_ALL);
+            ORI(xFlags, xFlags, s3);
+        }
+        ADDxw(s1, s1, s2);
+        if (!rex.w) ZEROUP(s1);
+
+        IFX(X_PEND)
+            SDxw(s1, xEmu, offsetof(x64emu_t, res));
+        return;
+    }
+
     IFX(X_CF)
     {
         if (rex.w) {
@@ -242,16 +254,28 @@ void emit_add32c(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, int64_t c, i
 void emit_add8(dynarec_la64_t* dyn, int ninst, int s1, int s2, int s3, int s4)
 {
     CLEAR_FLAGS();
-    IFX(X_PEND)
-    {
-        SUB_D(s1, xEmu, offsetof(x64emu_t, op1));
-        SUB_D(s2, xEmu, offsetof(x64emu_t, op2));
+    IFX(X_PEND) {
+        ST_B(s1, xEmu, offsetof(x64emu_t, op1));
+        ST_B(s2, xEmu, offsetof(x64emu_t, op2));
         SET_DF(s3, d_add8);
-    }
-    else IFX(X_ALL)
-    {
+    } else IFX(X_ALL) {
         SET_DFNONE();
     }
+
+    if (la64_lbt) {
+        IFX(X_ALL) {
+            X64_ADD_B(s1, s2);
+            X64_GET_EFLAGS(s3, X_ALL);
+            ORI(xFlags, xFlags, s3);
+        }
+        ADD_D(s1, s1, s2);
+        ANDI(s1, s1, 0xff);
+
+        IFX(X_PEND)
+            ST_H(s1, xEmu, offsetof(x64emu_t, res));
+        return;
+    }
+
     IFX(X_AF | X_OF)
     {
         OR(s3, s1, s2);  // s3 = op1 | op2
@@ -311,28 +335,37 @@ void emit_add8(dynarec_la64_t* dyn, int ninst, int s1, int s2, int s3, int s4)
 void emit_add8c(dynarec_la64_t* dyn, int ninst, int s1, int c, int s2, int s3, int s4)
 {
     CLEAR_FLAGS();
-    IFX(X_PEND)
-    {
+    IFX(X_PEND) {
         MOV32w(s4, c & 0xff);
         ST_B(s1, xEmu, offsetof(x64emu_t, op1));
         ST_B(s4, xEmu, offsetof(x64emu_t, op2));
         SET_DF(s3, d_add8);
-    }
-    else IFX(X_ALL)
-    {
+    } else IFX(X_ALL) {
         SET_DFNONE();
     }
+
+    if (la64_lbt) {
+        IFX(X_ALL) {
+            IFX(X_PEND) {} else { MOV32w(s4, c & 0xff); }
+            X64_ADD_B(s1, s4);
+            X64_GET_EFLAGS(s3, X_ALL);
+            ORI(xFlags, xFlags, s3);
+        }
+        ADDI_D(s1, s1, c & 0xff);
+        ANDI(s1, s1, 0xff);
+
+        IFX(X_PEND)
+            ST_H(s1, xEmu, offsetof(x64emu_t, res));
+        return;
+    }
+
     IFX(X_AF | X_OF)
     {
-        IFX(X_PEND) { }
-        else
-        {
-            MOV32w(s4, c & 0xff);
-        }
+        IFX(X_PEND) {} else { MOV32w(s4, c & 0xff); }
         OR(s3, s1, s4);  // s3 = op1 | op2
         AND(s4, s1, s4); // s4 = op1 & op2
     }
-    ADDI_D(s1, s1, c);
+    ADDI_D(s1, s1, c & 0xff);
 
     IFX(X_AF | X_OF)
     {
@@ -394,6 +427,20 @@ void emit_sub8(dynarec_la64_t* dyn, int ninst, int s1, int s2, int s3, int s4, i
         SET_DFNONE();
     }
 
+    if (la64_lbt) {
+        IFX(X_ALL) {
+            X64_SUB_B(s1, s2);
+            X64_GET_EFLAGS(s3, X_ALL);
+            ORI(xFlags, xFlags, s3);
+        }
+        SUB_D(s1, s1, s2);
+        ANDI(s1, s1, 0xff);
+
+        IFX(X_PEND)
+            ST_H(s1, xEmu, offsetof(x64emu_t, res));
+        return;
+    }
+
     IFX(X_AF | X_CF | X_OF) {
         // for later flag calculation
         NOT(s5, s1);
@@ -438,6 +485,20 @@ void emit_sub32(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s
         SET_DFNONE();
     }
 
+    if (la64_lbt) {
+        IFX(X_ALL) {
+            X64_SUB_WU(s1, s2);
+            X64_GET_EFLAGS(s3, X_ALL);
+            ORI(xFlags, xFlags, s3);
+        }
+        SUBxw(s1, s1, s2);
+        if (!rex.w) ZEROUP(s1);
+
+        IFX(X_PEND)
+            SDxw(s1, xEmu, offsetof(x64emu_t, res));
+        return;
+    }
+
     IFX(X_AF | X_CF | X_OF) {
         // for later flag calculation
         NOT(s5, s1);
@@ -489,6 +550,21 @@ void emit_sub32c(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, int64_t c, i
         SET_DFNONE();
     }
 
+    if (la64_lbt) {
+        IFX(X_ALL) {
+            IFX(X_PEND) {} else {MOV64xw(s2, c);}
+            X64_SUB_WU(s1, s2);
+            X64_GET_EFLAGS(s3, X_ALL);
+            ORI(xFlags, xFlags, s3);
+        }
+        SUBxw(s1, s1, s2);
+        if (!rex.w) ZEROUP(s1);
+
+        IFX(X_PEND)
+            SDxw(s1, xEmu, offsetof(x64emu_t, res));
+        return;
+    }
+
     IFX(X_AF | X_CF | X_OF) {
         // for later flag calculation
         NOT(s5, s1);