about summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
authorptitSeb <sebastien.chev@gmail.com>2025-01-07 09:58:13 +0100
committerptitSeb <sebastien.chev@gmail.com>2025-01-07 09:58:13 +0100
commita61888e06cd4dadc06717b8ca58c161f85ce7fb8 (patch)
tree96ebb328f44af5554275d1ccf1bcd4621dc73954 /src
parent691259ec0d612d45b77c0544d947a5a15e4becaa (diff)
downloadbox64-a61888e06cd4dadc06717b8ca58c161f85ce7fb8.tar.gz
box64-a61888e06cd4dadc06717b8ca58c161f85ce7fb8.zip
[ARM64_DYNAREC] Optimized 8bits OR when no flags is needed
Diffstat (limited to 'src')
-rw-r--r--src/dynarec/arm64/dynarec_arm64_00.c71
-rw-r--r--src/dynarec/arm64/dynarec_arm64_helper.h21
2 files changed, 77 insertions, 15 deletions
diff --git a/src/dynarec/arm64/dynarec_arm64_00.c b/src/dynarec/arm64/dynarec_arm64_00.c
index b711230f..dc04a661 100644
--- a/src/dynarec/arm64/dynarec_arm64_00.c
+++ b/src/dynarec/arm64/dynarec_arm64_00.c
@@ -126,10 +126,23 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
             INST_NAME("OR Eb, Gb");
             SETFLAGS(X_ALL, SF_SET_PENDING);
             nextop = F8;
-            GETEB(x1, 0);
-            GETGB(x2);
-            emit_or8(dyn, ninst, x1, x2, x4, x5);
-            EBBACK;
+            UFLAG_IF {
+                GETEB(x1, 0);
+                GETGB(x2);
+                emit_or8(dyn, ninst, x1, x2, x4, x5);
+                EBBACK;
+            } else {
+                if(MODREG) {
+                    GETGB(x2);
+                    CALCEB();
+                    ORRx_REG_LSL(wback, wback, x2, wb2);
+                } else {
+                    GETEB(x1, 0);
+                    CALCGB();
+                    ORRw_REG_LSR(x1, x1, gb1, 8*gb2);
+                    EBBACK;
+                }
+            }
             break;
         case 0x09:
             INST_NAME("OR Ed, Gd");
@@ -144,10 +157,16 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
             INST_NAME("OR Gb, Eb");
             SETFLAGS(X_ALL, SF_SET_PENDING);
             nextop = F8;
-            GETEB(x2, 0);
-            GETGB(x1);
-            emit_or8(dyn, ninst, x1, x2, x3, x4);
-            GBBACK;
+            UFLAG_IF {
+                GETEB(x2, 0);
+                GETGB(x1);
+                emit_or8(dyn, ninst, x1, x2, x3, x4);
+                GBBACK;
+            } else {
+                GETEB(x2, 0);
+                CALCGB();
+                ORRx_REG_LSL(gb1, gb1, x2, gb2*8);
+            }
             break;
         case 0x0B:
             INST_NAME("OR Gd, Ed");
@@ -161,9 +180,19 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
             INST_NAME("OR AL, Ib");
             SETFLAGS(X_ALL, SF_SET_PENDING);
             u8 = F8;
-            UXTBw(x1, xRAX);
-            emit_or8c(dyn, ninst, x1, u8, x3, x4);
-            BFIx(xRAX, x1, 0, 8);
+            UFLAG_IF {
+                UXTBw(x1, xRAX);
+                emit_or8c(dyn, ninst, x1, u8, x3, x4);
+                BFIx(xRAX, x1, 0, 8);
+            } else {
+                int mask = convert_bitmask_x(u8);
+                if(mask)
+                    ORRx_mask(xRAX, xRAX, (mask>>12)&1, mask&0x3F, (mask>>6)&0x3F);
+                else {
+                    MOV32w(x1, u8);
+                    ORRx_REG(xRAX, xRAX, x1);
+                }
+            }
             break;
         case 0x0D:
             INST_NAME("OR EAX, Id");
@@ -1024,10 +1053,22 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
                 case 1: //OR
                     INST_NAME("OR Eb, Ib");
                     SETFLAGS(X_ALL, SF_SET_PENDING);
-                    GETEB(x1, 1);
-                    u8 = F8;
-                    emit_or8c(dyn, ninst, x1, u8, x2, x4);
-                    EBBACK;
+                    UFLAG_IF2(|| !MODREG) {
+                        GETEB(x1, 1);
+                        u8 = F8;
+                        emit_or8c(dyn, ninst, x1, u8, x2, x4);
+                        EBBACK;
+                    } else {
+                        CALCEB();
+                        u8 = F8;
+                        int mask = convert_bitmask_x(((uint32_t)u8)<<wb2);
+                        if(mask)
+                            ORRx_mask(wback, wback, (mask>>12)&1, mask&0x3F, (mask>>6)&0x3F);
+                        else {
+                            MOV32w(x1, ((uint32_t)u8)<<wb2);
+                            ORRx_REG(wback, wback, x1);
+                        }
+                    }
                     break;
                 case 2: //ADC
                     INST_NAME("ADC Eb, Ib");
diff --git a/src/dynarec/arm64/dynarec_arm64_helper.h b/src/dynarec/arm64/dynarec_arm64_helper.h
index 0f6f132a..403f1535 100644
--- a/src/dynarec/arm64/dynarec_arm64_helper.h
+++ b/src/dynarec/arm64/dynarec_arm64_helper.h
@@ -322,6 +322,16 @@
 #define EWBACKW(w)   if(wb1) {STH(w, wback, fixedaddress); SMWRITE();} else {BFIx(wback, w, 0, 16);}
 // Write back gd in correct register
 #define GWBACK BFIx(TO_NAT(((nextop & 0x38) >> 3) + (rex.r << 3)), gd, 0, 16);
+// no fetch version of GETEB for MODREG path only
+#define CALCEB()                                                                                             \
+    if (rex.rex) {                                                                                           \
+        wback = TO_NAT((nextop & 7) + (rex.b << 3));                                                         \
+        wb2 = 0;                                                                                             \
+    } else {                                                                                                 \
+        wback = (nextop & 7);                                                                                \
+        wb2 = (wback >> 2) * 8;                                                                              \
+        wback = TO_NAT(wback & 3);                                                                           \
+    }                                                                                                        \
 //GETEB will use i for ed, and can use r3 for wback.
 #define GETEB(i, D)                                                                                              \
     if (MODREG) {                                                                                                \
@@ -410,6 +420,16 @@
     }
 // Write eb (ed) back to original register / memory
 #define EBBACK   if(wb1) {STB(ed, wback, fixedaddress); SMWRITE();} else {BFIx(wback, ed, wb2, 8);}
+// no fetch version of GETGB
+#define CALCGB()                                             \
+    if (rex.rex) {                                           \
+        gb1 = TO_NAT(((nextop & 0x38) >> 3) + (rex.r << 3)); \
+        gb2 = 0;                                             \
+    } else {                                                 \
+        gd = (nextop & 0x38) >> 3;                           \
+        gb2 = ((gd & 4) << 1);                               \
+        gb1 = TO_NAT(gd & 3);                                \
+    }                                                        \
 //GETGB will use i for gd
 #define GETGB(i)                                             \
     if (rex.rex) {                                           \
@@ -1169,6 +1189,7 @@
 #define UFLAG_RES(A) if(dyn->insts[ninst].x64.gen_flags) {STRxw_U12(A, xEmu, offsetof(x64emu_t, res));}
 #define UFLAG_DF(r, A) if(dyn->insts[ninst].x64.gen_flags) {SET_DF(r, A)}
 #define UFLAG_IF if(dyn->insts[ninst].x64.gen_flags)
+#define UFLAG_IF2(A) if(dyn->insts[ninst].x64.gen_flags A)
 #ifndef DEFAULT
 #define DEFAULT      *ok = -1; BARRIER(2)
 #endif