about summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
authorptitSeb <sebastien.chev@gmail.com>2024-03-08 12:05:09 +0100
committerptitSeb <sebastien.chev@gmail.com>2024-03-08 12:05:09 +0100
commitc0f78342e1571306f5d30087ccd8f0b289ea949e (patch)
tree4ad01c7b2c25a5d3f2b7bd4668ea3a19b4c22a88 /src
parent75494978ad84b8a0523b2560328466525f770288 (diff)
downloadbox64-c0f78342e1571306f5d30087ccd8f0b289ea949e.tar.gz
box64-c0f78342e1571306f5d30087ccd8f0b289ea949e.zip
[ARM64_DYNAREC] Improved MOV32w and MOV64x with a funciton with more speciall cases
Diffstat (limited to 'src')
-rw-r--r--src/dynarec/arm64/arm64_emitter.h25
-rw-r--r--src/dynarec/arm64/dynarec_arm64_helper.c76
-rw-r--r--src/dynarec/arm64/dynarec_arm64_helper.h6
3 files changed, 84 insertions, 23 deletions
diff --git a/src/dynarec/arm64/arm64_emitter.h b/src/dynarec/arm64/arm64_emitter.h
index 46de26cf..05728675 100644
--- a/src/dynarec/arm64/arm64_emitter.h
+++ b/src/dynarec/arm64/arm64_emitter.h
@@ -116,29 +116,8 @@ int convert_bitmask(uint64_t bitmask);
 #define MOVKw(Rd, imm16)                    EMIT(MOVK_gen(0, 0, ((uint16_t)(imm16))&0xffff, Rd))
 #define MOVKw_LSL(Rd, imm16, shift)         EMIT(MOVK_gen(0, (shift)/16, ((uint16_t)(imm16))&0xffff, Rd))
 
-// This macro will give a -Wsign-compare warning, probably bug #38341
-#define MOV32w(Rd, imm32) \
-    if(~((uint32_t)(imm32))<0xffffu) {                                                                        \
-        MOVNw(Rd, (~(uint32_t)(imm32))&0xffff);                                                               \
-    } else if((uint32_t)(imm32)>0xffff && convert_bitmask_w(imm32)) {                                        \
-        int mask = convert_bitmask_w(imm32);                                                                  \
-        ORRw_mask(Rd, xZR, mask&0x3F, (mask>>6)&0x3F);                                                        \
-    } else {                                                                                                  \
-        MOVZw(Rd, (imm32)&0xffff);                                                                            \
-        if((imm32)&0xffff0000) {MOVKw_LSL(Rd, ((imm32)>>16)&0xffff, 16);}                                     \
-    }
-#define MOV64x(Rd, imm64) \
-    if(~((uint64_t)(imm64))<0xffff) {                                                                        \
-        MOVNx(Rd, (~(uint64_t)(imm64))&0xffff);                                                              \
-    } else if((uint64_t)(imm64)>0xffff && convert_bitmask_x(imm64)) {                                      \
-        int mask = convert_bitmask_x(imm64);                                                                 \
-        ORRx_mask(Rd, xZR, (mask>>12)&1, mask&0x3F, (mask>>6)&0x3F);                                         \
-    } else {                                                                                                 \
-        MOVZx(Rd, ((uint64_t)(imm64))&0xffff);                                                               \
-        if(((uint64_t)(imm64))&0xffff0000) {MOVKx_LSL(Rd, (((uint64_t)(imm64))>>16)&0xffff, 16);}            \
-        if(((uint64_t)(imm64))&0xffff00000000LL) {MOVKx_LSL(Rd, (((uint64_t)(imm64))>>32)&0xffff, 32);}      \
-        if(((uint64_t)(imm64))&0xffff000000000000LL) {MOVKx_LSL(Rd, (((uint64_t)(imm64))>>48)&0xffff, 48);}  \
-    }
+#define MOV32w(Rd, imm32) arm64_move32(dyn, ninst, Rd, imm32)
+#define MOV64x(Rd, imm64) arm64_move64(dyn, ninst, Rd, imm64)
 
 #define MOV64xw(Rd, imm64)   if(rex.w) {MOV64x(Rd, imm64);} else {MOV32w(Rd, imm64);}
 #define MOV64z(Rd, imm64)    if(rex.is32bits) {MOV32w(Rd, imm64);} else {MOV64x(Rd, imm64);}
diff --git a/src/dynarec/arm64/dynarec_arm64_helper.c b/src/dynarec/arm64/dynarec_arm64_helper.c
index b6dff229..27a73238 100644
--- a/src/dynarec/arm64/dynarec_arm64_helper.c
+++ b/src/dynarec/arm64/dynarec_arm64_helper.c
@@ -2145,6 +2145,82 @@ void emit_pf(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4)
     BFIw(xFlags, s4, F_PF, 1);
 }
 
+void arm64_move32(dynarec_arm_t* dyn, int ninst, int reg, uint32_t val)
+{
+    // simple cases with only 1 operations
+    for(int i=0; i<2; ++i)
+        if((val&(0xFFFF<<(i*16)))==val) {
+            MOVZw_LSL(reg, (val>>(i*16))&0xFFFF, i*16);
+            return;
+        }
+    // same but with negation
+    for(int i=0; i<2; ++i)
+        if(((~val)&(0xFFFF<<(i*16)))==(~val)) {
+            MOVNw_LSL(reg, ((~val)>>(i*16))&0xFFFF, i*16);
+            return;
+        }
+    // generic cases
+    int mask = convert_bitmask_w(val);
+    if(mask) {
+        ORRw_mask(reg, xZR, mask&0x3F, (mask>>6)&0x3F);
+    } else {
+        MOVZw(reg, val&0xFFFF);
+        MOVKw_LSL(reg, (val>>16)&0xFFFF, 16);
+    }
+}
+void arm64_move64(dynarec_arm_t* dyn, int ninst, int reg, uint64_t val)
+{
+    // simple cases with only 1 operations
+    for(int i=0; i<4; ++i)
+        if((val&(0xFFFFLL<<(i*16)))==val) {
+            MOVZx_LSL(reg, (val>>(i*16))&0xFFFF, i*16);
+            return;
+        }
+    // same but with negation
+    for(int i=0; i<4; ++i)
+        if(((~val)&(0xFFFFLL<<(i*16)))==(~val)) {
+            MOVNx_LSL(reg, ((~val)>>(i*16))&0xFFFF, i*16);
+            return;
+        }
+    // mask
+    int mask = convert_bitmask_x(val);
+    if(mask) {
+        ORRx_mask(reg, xZR, (mask>>12)&1, mask&0x3F, (mask>>6)&0x3F);
+        return;
+    }
+    // 32bit value?
+    if((val&0xFFFFFFFF)==val) {
+        arm64_move32(dyn, ninst, reg, val);
+        return;
+    }
+    int n = 0;
+    // negatives values
+    if((val&0xFFFF000000000000LL)==0xFFFF000000000000LL) {
+        for(int i=0; i<3; ++i) {
+            if(((~val)>>(i*16))&0xFFFF) {
+                if(n) {
+                    MOVKx_LSL(reg, (val>>(i*16))&0xFFFF, i*16);
+                } else {
+                    MOVNx_LSL(reg, ((~val)>>(i*16))&0xFFFF, i*16);
+                    n = 1;
+                }
+            }
+        }
+        return;
+    }
+    // positive values
+    for(int i=0; i<4; ++i) {
+        if((val>>(i*16))&0xFFFF) {
+            if(n) {
+                MOVKx_LSL(reg, (val>>(i*16))&0xFFFF, i*16);
+            } else {
+                MOVZx_LSL(reg, (val>>(i*16))&0xFFFF, i*16);
+                n = 1;
+            }
+        }
+    }
+}
+
 
 void fpu_reset_cache(dynarec_arm_t* dyn, int ninst, int reset_n)
 {
diff --git a/src/dynarec/arm64/dynarec_arm64_helper.h b/src/dynarec/arm64/dynarec_arm64_helper.h
index 563327e8..46a6a750 100644
--- a/src/dynarec/arm64/dynarec_arm64_helper.h
+++ b/src/dynarec/arm64/dynarec_arm64_helper.h
@@ -1130,6 +1130,9 @@ void* arm64_next(x64emu_t* emu, uintptr_t addr);
 
 #define CacheTransform       STEPNAME(CacheTransform)
 
+#define arm64_move32        STEPNAME(arm64_move32)
+#define arm64_move64        STEPNAME(arm64_move64)
+
 /* setup r2 to address pointed by */
 uintptr_t geted(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop, uint8_t* ed, uint8_t hint, int64_t* fixaddress, int* unscaled, int absmax, uint32_t mask, rex_t rex, int* l, int s, int delta);
 
@@ -1283,6 +1286,9 @@ int sse_setround(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3);
 
 void CacheTransform(dynarec_arm_t* dyn, int ninst, int cacheupd, int s1, int s2, int s3);
 
+void arm64_move32(dynarec_arm_t* dyn, int ninst, int reg, uint32_t val);
+void arm64_move64(dynarec_arm_t* dyn, int ninst, int reg, uint64_t val);
+
 #if STEP < 2
 #define CHECK_CACHE()   0
 #else