about summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
authorYang Liu <numbksco@gmail.com>2024-04-10 00:33:41 +0800
committerGitHub <noreply@github.com>2024-04-09 18:33:41 +0200
commitdb35542706827c411db79a2db97f6d6ce58f6e5e (patch)
tree625431261702d644a25077cb3e5a61d5f47de0c1 /src
parenteda857cb10701ccb3f726118b8865b600484b708 (diff)
downloadbox64-db35542706827c411db79a2db97f6d6ce58f6e5e.tar.gz
box64-db35542706827c411db79a2db97f6d6ce58f6e5e.zip
[LA64_DYNAREC] Refined MOV64 macros (#1430)
Diffstat (limited to 'src')
-rw-r--r--src/dynarec/la64/dynarec_la64_helper.c28
-rw-r--r--src/dynarec/la64/dynarec_la64_helper.h5
-rw-r--r--src/dynarec/la64/la64_emitter.h43
3 files changed, 48 insertions, 28 deletions
diff --git a/src/dynarec/la64/dynarec_la64_helper.c b/src/dynarec/la64/dynarec_la64_helper.c
index 6c5b76b5..5bba9433 100644
--- a/src/dynarec/la64/dynarec_la64_helper.c
+++ b/src/dynarec/la64/dynarec_la64_helper.c
@@ -1067,3 +1067,31 @@ void CacheTransform(dynarec_la64_t* dyn, int ninst, int cacheupd, int s1, int s2
     if(cacheupd&1)
         flagsCacheTransform(dyn, ninst, s1);
 }
+
+void la64_move32(dynarec_la64_t* dyn, int ninst, int reg, int32_t val, int zeroup)
+{
+    if ((val & 0xfff) == val) {
+        ORI(reg, xZR, val);
+    } else if (((val << 20) >> 20) == val) {
+        ADDI_W(reg, xZR, val & 0xfff);
+    } else if ((val & 0xfff) == 0) {
+        LU12I_W(reg, (val >> 12) & 0xfffff);
+    } else {
+        LU12I_W(reg, (val >> 12) & 0xfffff);
+        ORI(reg, reg, val & 0xfff);
+    }
+    if (zeroup && val < 0) ZEROUP(reg);
+}
+
+void la64_move64(dynarec_la64_t* dyn, int ninst, int reg, int64_t val)
+{
+    la64_move32(dyn, ninst, reg, val, 0);
+    if (((val << 32) >> 32) == val) {
+        return;
+    }
+    LU32I_D(reg, (val >> 32) & 0xfffff);
+    if (((val << 12) >> 12) == val) {
+        return;
+    }
+    LU52I_D(reg, reg, (val >> 52) & 0xfff);
+}
\ No newline at end of file
diff --git a/src/dynarec/la64/dynarec_la64_helper.h b/src/dynarec/la64/dynarec_la64_helper.h
index 49229c09..8f306681 100644
--- a/src/dynarec/la64/dynarec_la64_helper.h
+++ b/src/dynarec/la64/dynarec_la64_helper.h
@@ -688,6 +688,8 @@ void* la64_next(x64emu_t* emu, uintptr_t addr);
 #define fpu_unreflectcache  STEPNAME(fpu_unreflectcache)
 
 #define CacheTransform STEPNAME(CacheTransform)
+#define la64_move64    STEPNAME(la64_move64)
+#define la64_move32    STEPNAME(la64_move32)
 
 /* setup r2 to address pointed by */
 uintptr_t geted(dynarec_la64_t* dyn, uintptr_t addr, int ninst, uint8_t nextop, uint8_t* ed, uint8_t hint, uint8_t scratch, int64_t* fixaddress, rex_t rex, int* l, int i12, int delta);
@@ -769,6 +771,9 @@ int sse_get_reg_empty(dynarec_la64_t* dyn, int ninst, int s1, int a);
 
 void CacheTransform(dynarec_la64_t* dyn, int ninst, int cacheupd, int s1, int s2, int s3);
 
+void la64_move64(dynarec_la64_t* dyn, int ninst, int reg, int64_t val);
+void la64_move32(dynarec_la64_t* dyn, int ninst, int reg, int32_t val, int zeroup);
+
 #if STEP < 2
 #define CHECK_CACHE() 0
 #else
diff --git a/src/dynarec/la64/la64_emitter.h b/src/dynarec/la64/la64_emitter.h
index be91b960..a948548b 100644
--- a/src/dynarec/la64/la64_emitter.h
+++ b/src/dynarec/la64/la64_emitter.h
@@ -1726,34 +1726,21 @@ LSX instruction starts with V, LASX instruction starts with XV.
         }                                     \
     } while (0)
 
-#define MOV32w(rd, imm32) MOV32w_(rd, imm32, 1)
-// GR[rd] = imm64
-#define MOV64x(rd, imm64)                               \
-    do {                                                \
-        MOV32w_(rd, imm64, 0);                          \
-        if (((uint64_t)(imm64)) > 0xffffffffu) {        \
-            LU32I_D(rd, ((uint64_t)(imm64)) >> 32);     \
-            LU52I_D(rd, rd, ((uint64_t)(imm64)) >> 52); \
-        }                                               \
-    } while (0)
-
-#define MOV64xw(A, B)     \
-    do {                  \
-        if (rex.w) {      \
-            MOV64x(A, B); \
-        } else {          \
-            MOV32w(A, B); \
-        }                 \
-    } while (0)
-
-#define MOV64z(A, B)        \
-    do {                    \
-        if (rex.is32bits) { \
-            MOV32w(A, B);   \
-        } else {            \
-            MOV64x(A, B);   \
-        }                   \
-    } while (0)
+// MOV64x/MOV32w is quite complex, so use a function for this
+#define MOV64x(A, B) la64_move64(dyn, ninst, A, B)
+#define MOV32w(A, B) la64_move32(dyn, ninst, A, B, 1)
+#define MOV64xw(A, B) \
+    if (rex.w) {      \
+        MOV64x(A, B); \
+    } else {          \
+        MOV32w(A, B); \
+    }
+#define MOV64z(A, B)    \
+    if (rex.is32bits) { \
+        MOV32w(A, B);   \
+    } else {            \
+        MOV64x(A, B);   \
+    }
 
 // rd[63:0] = rj[63:0] (pseudo instruction)
 #define MV(rd, rj) ADDI_D(rd, rj, 0)