Browse Source

UserspaceEmulator: Convert the XOR instruction to inline assembly

Andreas Kling 5 years ago
parent
commit
76b9fb258d
2 changed files with 31 additions and 6 deletions
  1. 25 6
      DevTools/UserspaceEmulator/SoftCPU.cpp
  2. 6 0
      DevTools/UserspaceEmulator/SoftCPU.h

+ 25 - 6
DevTools/UserspaceEmulator/SoftCPU.cpp

@@ -139,12 +139,31 @@ u32 SoftCPU::pop32()
 template<typename Destination, typename Source>
 static typename TypeDoubler<Destination>::type op_xor(SoftCPU& cpu, const Destination& dest, const Source& src)
 {
-    auto result = dest ^ src;
-    cpu.set_zf(dest == 0);
-    cpu.set_sf(dest & 0x80000000);
-    // FIXME: set_pf
-    cpu.set_of(false);
-    cpu.set_cf(false);
+    Destination result = 0;
+    u32 new_flags = 0;
+
+    if constexpr (sizeof(Destination) == 4) {
+        asm volatile("xorl %%ecx, %%eax\n"
+                     : "=a"(result)
+                     : "a"(dest), "c"(src));
+    } else if constexpr (sizeof(Destination) == 2) {
+        asm volatile("xor %%cx, %%ax\n"
+                     : "=a"(result)
+                     : "a"(dest), "c"(src));
+    } else if constexpr (sizeof(Destination) == 1) {
+        asm volatile("xorb %%cl, %%al\n"
+                     : "=a"(result)
+                     : "a"(dest), "c"(src));
+    } else {
+        ASSERT_NOT_REACHED();
+    }
+
+    asm volatile(
+        "pushf\n"
+        "pop %%ebx"
+        : "=b"(new_flags));
+
+    cpu.set_flags_oszpc(new_flags);
     return result;
 }
 

+ 6 - 0
DevTools/UserspaceEmulator/SoftCPU.h

@@ -213,6 +213,12 @@ public:
         m_eflags |= new_flags & (Flags::OF | Flags::SF | Flags::ZF | Flags::AF | Flags::PF);
     }
 
+    void set_flags_oszpc(u32 new_flags)
+    {
+        m_eflags &= ~(Flags::OF | Flags::SF | Flags::ZF | Flags::PF | Flags::CF);
+        m_eflags |= new_flags & (Flags::OF | Flags::SF | Flags::ZF | Flags::PF | Flags::CF);
+    }
+
     u16 cs() const { return m_segment[(int)X86::SegmentRegister::CS]; }
     u16 ds() const { return m_segment[(int)X86::SegmentRegister::DS]; }
     u16 es() const { return m_segment[(int)X86::SegmentRegister::ES]; }