瀏覽代碼

UE: Implement FLD_RM80 and FSTP_RM80

We do a bit too big reads and writes, but this should not be that bad
although it may taint memory graphs
Hendiadyoin1 4 年之前
父節點
當前提交
39d34fb1f1
共有 1 個文件被更改,包括 30 次插入2 次删除
  1. 30 2
      Userland/DevTools/UserspaceEmulator/SoftCPU.cpp

+ 30 - 2
Userland/DevTools/UserspaceEmulator/SoftCPU.cpp

@@ -1798,7 +1798,18 @@ void SoftCPU::FNDISI(const X86::Instruction&) { TODO_INSN(); }
 void SoftCPU::FNCLEX(const X86::Instruction&) { TODO_INSN(); }
 void SoftCPU::FNINIT(const X86::Instruction&) { TODO_INSN(); }
 void SoftCPU::FNSETPM(const X86::Instruction&) { TODO_INSN(); }
-void SoftCPU::FLD_RM80(const X86::Instruction&) { TODO_INSN(); }
+
+void SoftCPU::FLD_RM80(const X86::Instruction& insn)
+{
+    VERIFY(!insn.modrm().is_register());
+
+    // long doubles can be up to 128 bits wide in memory for reasons (alignment) and only uses 80 bits of precision
+    // gcc uses 12 byte in 32 bit and 16 byte in 64 bit mode
+    // so in the 32 bit case we read a bit to much, but that shouldnt be that bad
+    auto new_f80 = insn.modrm().read128(*this, insn);
+    // FIXME: Respect shadow values
+    fpu_push(*(long double*)new_f80.value().bytes());
+}
 
 void SoftCPU::FUCOMI(const X86::Instruction& insn)
 {
@@ -1835,7 +1846,24 @@ void SoftCPU::FCOMI(const X86::Instruction& insn)
     m_flags_tainted = false;
 }
 
-void SoftCPU::FSTP_RM80(const X86::Instruction&) { TODO_INSN(); }
+void SoftCPU::FSTP_RM80(const X86::Instruction& insn)
+{
+    if (insn.modrm().is_register()) {
+        fpu_set(insn.modrm().register_index(), fpu_pop());
+    } else {
+        // FIXME: Respect shadow values
+        // long doubles can be up to 128 bits wide in memory for reasons (alignment) and only uses 80 bits of precision
+        // gcc uses 12 byte in 32 bit and 16 byte in 64 bit mode
+        // so in the 32 bit case we have to read first, to not override data on the overly big write
+        u128 f80 {};
+        if constexpr (sizeof(long double) == 12)
+            f80 = insn.modrm().read128(*this, insn).value();
+
+        *(long double*)f80.bytes() = fpu_pop();
+
+        insn.modrm().write128(*this, insn, shadow_wrap_as_initialized(f80));
+    }
+}
 
 void SoftCPU::FADD_RM64(const X86::Instruction& insn)
 {