summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHendiadyoin1 <leon2002.la@gmail.com>2021-04-10 23:32:12 +0200
committerAndreas Kling <kling@serenityos.org>2021-04-23 22:50:53 +0200
commit39d34fb1f15dc801cf6905cdef1d48442c7969e0 (patch)
tree4ef15ac07186a35fa25766cc9e3a9f8c722f2840
parentf1957bb86bd0535025bb9757b0b9f18a638e8d38 (diff)
downloadserenity-39d34fb1f15dc801cf6905cdef1d48442c7969e0.zip
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
-rw-r--r--Userland/DevTools/UserspaceEmulator/SoftCPU.cpp32
1 files changed, 30 insertions, 2 deletions
diff --git a/Userland/DevTools/UserspaceEmulator/SoftCPU.cpp b/Userland/DevTools/UserspaceEmulator/SoftCPU.cpp
index c41b6eaf40..d37476c119 100644
--- a/Userland/DevTools/UserspaceEmulator/SoftCPU.cpp
+++ b/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)
{