about summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
authorxctan <xctan@cirno.icu>2024-02-27 22:13:00 +0800
committerGitHub <noreply@github.com>2024-02-27 15:13:00 +0100
commitd8affd85642d03b21b871243831667089b9057ad (patch)
tree1e449555ca693bfb4f8ddc0ef0c7bb6c72cf4b4d /src
parentf3d4a1e1c3d470fe6be4a02d9a1929738e9b5055 (diff)
downloadbox64-d8affd85642d03b21b871243831667089b9057ad.tar.gz
box64-d8affd85642d03b21b871243831667089b9057ad.zip
[RV64_DYNAREC] Optimized XOR Ew, Gw when Ew == Gw (#1289)
Diffstat (limited to 'src')
-rw-r--r--src/dynarec/rv64/dynarec_rv64_66.c70
1 files changed, 62 insertions, 8 deletions
diff --git a/src/dynarec/rv64/dynarec_rv64_66.c b/src/dynarec/rv64/dynarec_rv64_66.c
index 59350bcb..419df8ff 100644
--- a/src/dynarec/rv64/dynarec_rv64_66.c
+++ b/src/dynarec/rv64/dynarec_rv64_66.c
@@ -253,19 +253,73 @@ uintptr_t dynarec64_66(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
             INST_NAME("XOR Ew, Gw");
             SETFLAGS(X_ALL, SF_SET_PENDING);
             nextop = F8;
-            GETGW(x2);
-            GETEW(x1, 0);
-            emit_xor16(dyn, ninst, x1, x2, x4, x5, x6);
-            EWBACK;
+            // try to determine ed and gd
+            ed = 0;
+            GETGD;
+            if (MODREG) {
+                GETED(0);
+            }
+            if (ed == gd) {
+                // optimize XOR Gw, Gw
+                CLEAR_FLAGS();
+                IFX(X_PEND) {
+                    SET_DF(x6, d_xor16);
+                } else IFX(X_ALL) {
+                    SET_DFNONE();
+                }
+                SRLI(ed, ed, 16);
+                SLLI(ed, ed, 16);
+                IFX(X_PEND) {
+                    SH(ed, xEmu, offsetof(x64emu_t, res));
+                }
+                IFX(X_ZF) {
+                    ORI(xFlags, xFlags, 1 << F_ZF);
+                }
+                IFX(X_PF) {
+                    ORI(xFlags, xFlags, 1 << F_PF);
+                }
+            } else {
+                GETGW(x2);
+                GETEW(x1, 0);
+                emit_xor16(dyn, ninst, x1, x2, x4, x5, x6);
+                EWBACK;
+            }
             break;
         case 0x33:
             INST_NAME("XOR Gw, Ew");
             SETFLAGS(X_ALL, SF_SET_PENDING);
             nextop = F8;
-            GETGW(x1);
-            GETEW(x2, 0);
-            emit_xor16(dyn, ninst, x1, x2, x4, x5, x6);
-            GWBACK;
+            // try to determine ed and gd
+            ed = 0;
+            GETGD;
+            if (MODREG) {
+                GETED(0);
+            }
+            if (ed == gd) {
+                // optimize XOR Gw, Gw
+                CLEAR_FLAGS();
+                IFX(X_PEND) {
+                    SET_DF(x6, d_xor16);
+                } else IFX(X_ALL) {
+                    SET_DFNONE();
+                }
+                SRLI(ed, ed, 16);
+                SLLI(ed, ed, 16);
+                IFX(X_PEND) {
+                    SH(ed, xEmu, offsetof(x64emu_t, res));
+                }
+                IFX(X_ZF) {
+                    ORI(xFlags, xFlags, 1 << F_ZF);
+                }
+                IFX(X_PF) {
+                    ORI(xFlags, xFlags, 1 << F_PF);
+                }
+            } else {
+                GETGW(x1);
+                GETEW(x2, 0);
+                emit_xor16(dyn, ninst, x1, x2, x4, x5, x6);
+                GWBACK;
+            }
             break;
         case 0x35:
             INST_NAME("XOR AX, Iw");