瀏覽代碼

UserspaceEmulator: SoftCPU: Add support for several x86 FPU instructions

F2XM1
FYL2X
FYL2XP1
FDECSTP
FINCSTP
FSCALE
Brendan Coles 4 年之前
父節點
當前提交
ec1fdef818
共有 1 個文件被更改,包括 45 次插入8 次删除
  1. 45 8
      Userland/DevTools/UserspaceEmulator/SoftCPU.cpp

+ 45 - 8
Userland/DevTools/UserspaceEmulator/SoftCPU.cpp

@@ -1613,14 +1613,49 @@ void SoftCPU::FLDZ(const X86::Instruction&)
 }
 
 void SoftCPU::FNSTENV(const X86::Instruction&) { TODO_INSN(); }
-void SoftCPU::F2XM1(const X86::Instruction&) { TODO_INSN(); }
-void SoftCPU::FYL2X(const X86::Instruction&) { TODO_INSN(); }
+
+void SoftCPU::F2XM1(const X86::Instruction&)
+{
+    // FIXME: validate ST(0) is in range –1.0 to +1.0
+    auto f32 = fpu_get(0);
+    // FIXME: Set C0, C2, C3 in FPU status word.
+    fpu_set(0, powf(2, f32) - 1.0f);
+}
+
+void SoftCPU::FYL2X(const X86::Instruction&)
+{
+    // FIXME: Raise IA on +-infinity, +-0, raise Z on +-0
+    auto f32 = fpu_get(0);
+    // FIXME: Set C0, C2, C3 in FPU status word.
+    fpu_set(1, fpu_get(1) * log2f(f32));
+    fpu_pop();
+}
+
+void SoftCPU::FYL2XP1(const X86::Instruction&)
+{
+    // FIXME: validate ST(0) range
+    auto f32 = fpu_get(0);
+    // FIXME: Set C0, C2, C3 in FPU status word.
+    fpu_set(1, (fpu_get(1) * log2f(f32 + 1.0f)));
+    fpu_pop();
+}
+
 void SoftCPU::FPTAN(const X86::Instruction&) { TODO_INSN(); }
 void SoftCPU::FPATAN(const X86::Instruction&) { TODO_INSN(); }
 void SoftCPU::FXTRACT(const X86::Instruction&) { TODO_INSN(); }
 void SoftCPU::FPREM1(const X86::Instruction&) { TODO_INSN(); }
-void SoftCPU::FDECSTP(const X86::Instruction&) { TODO_INSN(); }
-void SoftCPU::FINCSTP(const X86::Instruction&) { TODO_INSN(); }
+
+void SoftCPU::FDECSTP(const X86::Instruction&)
+{
+    m_fpu_top = (m_fpu_top == 0) ? 7 : m_fpu_top - 1;
+    set_cf(0);
+}
+
+void SoftCPU::FINCSTP(const X86::Instruction&)
+{
+    m_fpu_top = (m_fpu_top == 7) ? 0 : m_fpu_top + 1;
+    set_cf(0);
+}
 
 void SoftCPU::FNSTCW(const X86::Instruction& insn)
 {
@@ -1628,7 +1663,6 @@ void SoftCPU::FNSTCW(const X86::Instruction& insn)
 }
 
 void SoftCPU::FPREM(const X86::Instruction&) { TODO_INSN(); }
-void SoftCPU::FYL2XP1(const X86::Instruction&) { TODO_INSN(); }
 
 void SoftCPU::FSQRT(const X86::Instruction&)
 {
@@ -1643,7 +1677,11 @@ void SoftCPU::FRNDINT(const X86::Instruction&)
     fpu_set(0, round(fpu_get(0)));
 }
 
-void SoftCPU::FSCALE(const X86::Instruction&) { TODO_INSN(); }
+void SoftCPU::FSCALE(const X86::Instruction&)
+{
+    // FIXME: set C1 upon stack overflow or if result was rounded
+    fpu_set(0, fpu_get(0) * powf(2, floorf(fpu_get(1))));
+}
 
 void SoftCPU::FSIN(const X86::Instruction&)
 {
@@ -1701,8 +1739,6 @@ void SoftCPU::FISUBR_RM32(const X86::Instruction& insn)
     fpu_set(0, (long double)m32int - fpu_get(0));
 }
 
-void SoftCPU::FUCOMPP(const X86::Instruction&) { TODO_INSN(); }
-
 void SoftCPU::FIDIV_RM32(const X86::Instruction& insn)
 {
     VERIFY(!insn.modrm().is_register());
@@ -1912,6 +1948,7 @@ void SoftCPU::FSTP_RM64(const X86::Instruction& insn)
 void SoftCPU::FRSTOR(const X86::Instruction&) { TODO_INSN(); }
 void SoftCPU::FUCOM(const X86::Instruction&) { TODO_INSN(); }
 void SoftCPU::FUCOMP(const X86::Instruction&) { TODO_INSN(); }
+void SoftCPU::FUCOMPP(const X86::Instruction&) { TODO_INSN(); }
 void SoftCPU::FNSAVE(const X86::Instruction&) { TODO_INSN(); }
 void SoftCPU::FNSTSW(const X86::Instruction&) { TODO_INSN(); }