summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNico Weber <thakis@chromium.org>2020-07-28 17:05:57 -0400
committerAndreas Kling <kling@serenityos.org>2020-07-30 16:53:33 +0200
commit8593bdb711999f464cb8f92f21e48a16ddbd1ec1 (patch)
tree2333e00303b6859f69659c42bfc5b1b0bac7523d
parent06c59cce6f3849ef5d9599de5475c9b6fab98d26 (diff)
downloadserenity-8593bdb711999f464cb8f92f21e48a16ddbd1ec1.zip
LibX86: Disassemble most remaining FPU instructions
Some of the remaining instructions have different behavior for register and non-register ops. Since we already have the two-level flags tables, model this by setting all handlers in the two-level table to the register op handler, while the first-level flags table stores the action for the non-reg handler.
-rw-r--r--DevTools/UserspaceEmulator/SoftCPU.cpp67
-rw-r--r--DevTools/UserspaceEmulator/SoftCPU.h67
-rw-r--r--Libraries/LibX86/Instruction.cpp150
-rw-r--r--Libraries/LibX86/Instruction.h8
-rw-r--r--Libraries/LibX86/Interpreter.h67
5 files changed, 350 insertions, 9 deletions
diff --git a/DevTools/UserspaceEmulator/SoftCPU.cpp b/DevTools/UserspaceEmulator/SoftCPU.cpp
index e8c2b3a834..a06b8b60f0 100644
--- a/DevTools/UserspaceEmulator/SoftCPU.cpp
+++ b/DevTools/UserspaceEmulator/SoftCPU.cpp
@@ -1415,6 +1415,36 @@ void SoftCPU::FRNDINT(const X86::Instruction&) { TODO(); };
void SoftCPU::FSCALE(const X86::Instruction&) { TODO(); };
void SoftCPU::FSIN(const X86::Instruction&) { TODO(); };
void SoftCPU::FCOS(const X86::Instruction&) { TODO(); };
+void SoftCPU::FIADD_RM32(const X86::Instruction&) { TODO(); };
+void SoftCPU::FCMOVB(const X86::Instruction&) { TODO(); };
+void SoftCPU::FIMUL_RM32(const X86::Instruction&) { TODO(); };
+void SoftCPU::FCMOVE(const X86::Instruction&) { TODO(); };
+void SoftCPU::FICOM_RM32(const X86::Instruction&) { TODO(); };
+void SoftCPU::FCMOVBE(const X86::Instruction&) { TODO(); };
+void SoftCPU::FICOMP_RM32(const X86::Instruction&) { TODO(); };
+void SoftCPU::FCMOVU(const X86::Instruction&) { TODO(); };
+void SoftCPU::FISUB_RM32(const X86::Instruction&) { TODO(); };
+void SoftCPU::FISUBR_RM32(const X86::Instruction&) { TODO(); };
+void SoftCPU::FUCOMPP(const X86::Instruction&) { TODO(); };
+void SoftCPU::FIDIV_RM32(const X86::Instruction&) { TODO(); };
+void SoftCPU::FIDIVR_RM32(const X86::Instruction&) { TODO(); };
+void SoftCPU::FILD_RM32(const X86::Instruction&) { TODO(); };
+void SoftCPU::FCMOVNB(const X86::Instruction&) { TODO(); };
+void SoftCPU::FISTTP_RM32(const X86::Instruction&) { TODO(); };
+void SoftCPU::FCMOVNE(const X86::Instruction&) { TODO(); };
+void SoftCPU::FIST_RM32(const X86::Instruction&) { TODO(); };
+void SoftCPU::FCMOVNBE(const X86::Instruction&) { TODO(); };
+void SoftCPU::FISTP_RM32(const X86::Instruction&) { TODO(); };
+void SoftCPU::FCMOVNU(const X86::Instruction&) { TODO(); };
+void SoftCPU::FNENI(const X86::Instruction&) { TODO(); };
+void SoftCPU::FNDISI(const X86::Instruction&) { TODO(); };
+void SoftCPU::FNCLEX(const X86::Instruction&) { TODO(); };
+void SoftCPU::FNINIT(const X86::Instruction&) { TODO(); };
+void SoftCPU::FNSETPM(const X86::Instruction&) { TODO(); };
+void SoftCPU::FLD_RM80(const X86::Instruction&) { TODO(); };
+void SoftCPU::FUCOMI(const X86::Instruction&) { TODO(); };
+void SoftCPU::FCOMI(const X86::Instruction&) { TODO(); };
+void SoftCPU::FSTP_RM80(const X86::Instruction&) { TODO(); };
void SoftCPU::FADD_RM64(const X86::Instruction&) { TODO(); }
void SoftCPU::FMUL_RM64(const X86::Instruction&) { TODO(); }
void SoftCPU::FCOM_RM64(const X86::Instruction&) { TODO(); }
@@ -1423,6 +1453,43 @@ void SoftCPU::FSUB_RM64(const X86::Instruction&) { TODO(); }
void SoftCPU::FSUBR_RM64(const X86::Instruction&) { TODO(); }
void SoftCPU::FDIV_RM64(const X86::Instruction&) { TODO(); }
void SoftCPU::FDIVR_RM64(const X86::Instruction&) { TODO(); }
+void SoftCPU::FLD_RM64(const X86::Instruction&) { TODO(); }
+void SoftCPU::FFREE(const X86::Instruction&) { TODO(); }
+void SoftCPU::FISTTP_RM64(const X86::Instruction&) { TODO(); }
+void SoftCPU::FST_RM64(const X86::Instruction&) { TODO(); }
+void SoftCPU::FSTP_RM64(const X86::Instruction&) { TODO(); }
+void SoftCPU::FRSTOR(const X86::Instruction&) { TODO(); }
+void SoftCPU::FUCOM(const X86::Instruction&) { TODO(); }
+void SoftCPU::FUCOMP(const X86::Instruction&) { TODO(); }
+void SoftCPU::FNSAVE(const X86::Instruction&) { TODO(); }
+void SoftCPU::FNSTSW(const X86::Instruction&) { TODO(); }
+void SoftCPU::FIADD_RM16(const X86::Instruction&) { TODO(); }
+void SoftCPU::FADDP(const X86::Instruction&) { TODO(); }
+void SoftCPU::FIMUL_RM16(const X86::Instruction&) { TODO(); }
+void SoftCPU::FMULP(const X86::Instruction&) { TODO(); }
+void SoftCPU::FICOM_RM16(const X86::Instruction&) { TODO(); }
+void SoftCPU::FICOMP_RM16(const X86::Instruction&) { TODO(); }
+void SoftCPU::FCOMPP(const X86::Instruction&) { TODO(); }
+void SoftCPU::FISUB_RM16(const X86::Instruction&) { TODO(); }
+void SoftCPU::FSUBRP(const X86::Instruction&) { TODO(); }
+void SoftCPU::FISUBR_RM16(const X86::Instruction&) { TODO(); }
+void SoftCPU::FSUBP(const X86::Instruction&) { TODO(); }
+void SoftCPU::FIDIV_RM16(const X86::Instruction&) { TODO(); }
+void SoftCPU::FDIVRP(const X86::Instruction&) { TODO(); }
+void SoftCPU::FIDIVR_RM16(const X86::Instruction&) { TODO(); }
+void SoftCPU::FDIVP(const X86::Instruction&) { TODO(); }
+void SoftCPU::FILD_RM16(const X86::Instruction&) { TODO(); }
+void SoftCPU::FFREEP(const X86::Instruction&) { TODO(); }
+void SoftCPU::FISTTP_RM16(const X86::Instruction&) { TODO(); }
+void SoftCPU::FIST_RM16(const X86::Instruction&) { TODO(); }
+void SoftCPU::FISTP_RM16(const X86::Instruction&) { TODO(); }
+void SoftCPU::FBLD_M80(const X86::Instruction&) { TODO(); }
+void SoftCPU::FNSTSW_AX(const X86::Instruction&) { TODO(); }
+void SoftCPU::FILD_RM64(const X86::Instruction&) { TODO(); }
+void SoftCPU::FUCOMIP(const X86::Instruction&) { TODO(); }
+void SoftCPU::FBSTP_M80(const X86::Instruction&) { TODO(); }
+void SoftCPU::FCOMIP(const X86::Instruction&) { TODO(); }
+void SoftCPU::FISTP_RM64(const X86::Instruction&) { TODO(); }
void SoftCPU::HLT(const X86::Instruction&) { TODO(); }
void SoftCPU::IDIV_RM16(const X86::Instruction& insn)
diff --git a/DevTools/UserspaceEmulator/SoftCPU.h b/DevTools/UserspaceEmulator/SoftCPU.h
index b2687abec5..9ed0e84672 100644
--- a/DevTools/UserspaceEmulator/SoftCPU.h
+++ b/DevTools/UserspaceEmulator/SoftCPU.h
@@ -618,6 +618,36 @@ private:
virtual void FSCALE(const X86::Instruction&) override;
virtual void FSIN(const X86::Instruction&) override;
virtual void FCOS(const X86::Instruction&) override;
+ virtual void FIADD_RM32(const X86::Instruction&) override;
+ virtual void FCMOVB(const X86::Instruction&) override;
+ virtual void FIMUL_RM32(const X86::Instruction&) override;
+ virtual void FCMOVE(const X86::Instruction&) override;
+ virtual void FICOM_RM32(const X86::Instruction&) override;
+ virtual void FCMOVBE(const X86::Instruction&) override;
+ virtual void FICOMP_RM32(const X86::Instruction&) override;
+ virtual void FCMOVU(const X86::Instruction&) override;
+ virtual void FISUB_RM32(const X86::Instruction&) override;
+ virtual void FISUBR_RM32(const X86::Instruction&) override;
+ virtual void FUCOMPP(const X86::Instruction&) override;
+ virtual void FIDIV_RM32(const X86::Instruction&) override;
+ virtual void FIDIVR_RM32(const X86::Instruction&) override;
+ virtual void FILD_RM32(const X86::Instruction&) override;
+ virtual void FCMOVNB(const X86::Instruction&) override;
+ virtual void FISTTP_RM32(const X86::Instruction&) override;
+ virtual void FCMOVNE(const X86::Instruction&) override;
+ virtual void FIST_RM32(const X86::Instruction&) override;
+ virtual void FCMOVNBE(const X86::Instruction&) override;
+ virtual void FISTP_RM32(const X86::Instruction&) override;
+ virtual void FCMOVNU(const X86::Instruction&) override;
+ virtual void FNENI(const X86::Instruction&) override;
+ virtual void FNDISI(const X86::Instruction&) override;
+ virtual void FNCLEX(const X86::Instruction&) override;
+ virtual void FNINIT(const X86::Instruction&) override;
+ virtual void FNSETPM(const X86::Instruction&) override;
+ virtual void FLD_RM80(const X86::Instruction&) override;
+ virtual void FUCOMI(const X86::Instruction&) override;
+ virtual void FCOMI(const X86::Instruction&) override;
+ virtual void FSTP_RM80(const X86::Instruction&) override;
virtual void FADD_RM64(const X86::Instruction&) override;
virtual void FMUL_RM64(const X86::Instruction&) override;
virtual void FCOM_RM64(const X86::Instruction&) override;
@@ -626,6 +656,43 @@ private:
virtual void FSUBR_RM64(const X86::Instruction&) override;
virtual void FDIV_RM64(const X86::Instruction&) override;
virtual void FDIVR_RM64(const X86::Instruction&) override;
+ virtual void FLD_RM64(const X86::Instruction&) override;
+ virtual void FFREE(const X86::Instruction&) override;
+ virtual void FISTTP_RM64(const X86::Instruction&) override;
+ virtual void FST_RM64(const X86::Instruction&) override;
+ virtual void FSTP_RM64(const X86::Instruction&) override;
+ virtual void FRSTOR(const X86::Instruction&) override;
+ virtual void FUCOM(const X86::Instruction&) override;
+ virtual void FUCOMP(const X86::Instruction&) override;
+ virtual void FNSAVE(const X86::Instruction&) override;
+ virtual void FNSTSW(const X86::Instruction&) override;
+ virtual void FIADD_RM16(const X86::Instruction&) override;
+ virtual void FADDP(const X86::Instruction&) override;
+ virtual void FIMUL_RM16(const X86::Instruction&) override;
+ virtual void FMULP(const X86::Instruction&) override;
+ virtual void FICOM_RM16(const X86::Instruction&) override;
+ virtual void FICOMP_RM16(const X86::Instruction&) override;
+ virtual void FCOMPP(const X86::Instruction&) override;
+ virtual void FISUB_RM16(const X86::Instruction&) override;
+ virtual void FSUBRP(const X86::Instruction&) override;
+ virtual void FISUBR_RM16(const X86::Instruction&) override;
+ virtual void FSUBP(const X86::Instruction&) override;
+ virtual void FIDIV_RM16(const X86::Instruction&) override;
+ virtual void FDIVRP(const X86::Instruction&) override;
+ virtual void FIDIVR_RM16(const X86::Instruction&) override;
+ virtual void FDIVP(const X86::Instruction&) override;
+ virtual void FILD_RM16(const X86::Instruction&) override;
+ virtual void FFREEP(const X86::Instruction&) override;
+ virtual void FISTTP_RM16(const X86::Instruction&) override;
+ virtual void FIST_RM16(const X86::Instruction&) override;
+ virtual void FISTP_RM16(const X86::Instruction&) override;
+ virtual void FBLD_M80(const X86::Instruction&) override;
+ virtual void FNSTSW_AX(const X86::Instruction&) override;
+ virtual void FILD_RM64(const X86::Instruction&) override;
+ virtual void FUCOMIP(const X86::Instruction&) override;
+ virtual void FBSTP_M80(const X86::Instruction&) override;
+ virtual void FCOMIP(const X86::Instruction&) override;
+ virtual void FISTP_RM64(const X86::Instruction&) override;
virtual void HLT(const X86::Instruction&) override;
virtual void IDIV_RM16(const X86::Instruction&) override;
virtual void IDIV_RM32(const X86::Instruction&) override;
diff --git a/Libraries/LibX86/Instruction.cpp b/Libraries/LibX86/Instruction.cpp
index fdfb39ca88..d8f8ea43f7 100644
--- a/Libraries/LibX86/Instruction.cpp
+++ b/Libraries/LibX86/Instruction.cpp
@@ -136,8 +136,12 @@ static void build(InstructionDescriptor* table, u8 op, const char* mnemonic, Ins
case OP_RM32:
case OP_FPU:
case OP_FPU_reg:
+ case OP_FPU_mem:
+ case OP_FPU_AX16:
+ case OP_FPU_RM16:
case OP_FPU_RM32:
case OP_FPU_RM64:
+ case OP_FPU_M80:
case OP_RM8_reg8:
case OP_RM32_reg32:
case OP_reg32_RM32:
@@ -287,6 +291,12 @@ static void build_slash_rm(u8 op, u8 slash, u8 rm, const char* mnemonic, Instruc
build_slash_rm(s_table32, op, slash, rm, mnemonic, format, impl, lock_prefix_allowed);
}
+static void build_slash_reg(u8 op, u8 slash, const char* mnemonic, InstructionFormat format, InstructionHandler impl, IsLockPrefixAllowed lock_prefix_allowed = LockPrefixNotAllowed)
+{
+ for (int i = 0; i < 8; ++i)
+ build_slash_rm(op, slash, 0xc0 | (slash << 3) | i, mnemonic, format, impl, lock_prefix_allowed);
+}
+
[[gnu::constructor]] static void build_opcode_tables()
{
build(0x00, "ADD", OP_RM8_reg8, &Interpreter::ADD_RM8_reg8, LockPrefixAllowed);
@@ -487,7 +497,7 @@ static void build_slash_rm(u8 op, u8 slash, u8 rm, const char* mnemonic, Instruc
build_slash_rm(0xD9, 4, 0xE1, "FABS", OP_FPU, &Interpreter::FABS);
build_slash_rm(0xD9, 4, 0xE2, "FTST", OP_FPU, &Interpreter::FTST);
build_slash_rm(0xD9, 4, 0xE3, "FXAM", OP_FPU, &Interpreter::FXAM);
- build_slash(0xD9, 5, "FLDCW", OP_FPU_RM32, &Interpreter::FLDCW);
+ build_slash(0xD9, 5, "FLDCW", OP_FPU_RM16, &Interpreter::FLDCW);
build_slash_rm(0xD9, 5, 0xE8, "FLD1", OP_FPU, &Interpreter::FLD1);
build_slash_rm(0xD9, 5, 0xE9, "FLDL2T", OP_FPU, &Interpreter::FLDL2T);
build_slash_rm(0xD9, 5, 0xEA, "FLDL2E", OP_FPU, &Interpreter::FLDL2E);
@@ -505,7 +515,7 @@ static void build_slash_rm(u8 op, u8 slash, u8 rm, const char* mnemonic, Instruc
build_slash_rm(0xD9, 6, 0xF5, "FPREM1", OP_FPU, &Interpreter::FPREM1);
build_slash_rm(0xD9, 6, 0xF6, "FDECSTP", OP_FPU, &Interpreter::FDECSTP);
build_slash_rm(0xD9, 6, 0xF7, "FINCSTP", OP_FPU, &Interpreter::FINCSTP);
- build_slash(0xD9, 7, "FNSTCW", OP_FPU_RM32, &Interpreter::FNSTCW);
+ build_slash(0xD9, 7, "FNSTCW", OP_FPU_RM16, &Interpreter::FNSTCW);
// FIXME: Extraodinary prefix 0x9B + 0xD9/7: FSTCW
build_slash_rm(0xD9, 7, 0xF8, "FPREM", OP_FPU, &Interpreter::FPREM);
build_slash_rm(0xD9, 7, 0xF9, "FYL2XP1", OP_FPU, &Interpreter::FYL2XP1);
@@ -516,9 +526,40 @@ static void build_slash_rm(u8 op, u8 slash, u8 rm, const char* mnemonic, Instruc
build_slash_rm(0xD9, 7, 0xFE, "FSIN", OP_FPU, &Interpreter::FSIN);
build_slash_rm(0xD9, 7, 0xFF, "FCOS", OP_FPU, &Interpreter::FCOS);
- // FIXME
- build(0xDA, "FPU?", OP_RM8, &Interpreter::ESCAPE);
- build(0xDB, "FPU?", OP_RM8, &Interpreter::ESCAPE);
+ build_slash(0xDA, 0, "FIADD", OP_FPU_RM32, &Interpreter::FIADD_RM32);
+ build_slash_reg(0xDA, 0, "FCMOVB", OP_FPU_reg, &Interpreter::FCMOVB);
+ build_slash(0xDA, 1, "FIMUL", OP_FPU_RM32, &Interpreter::FIMUL_RM32);
+ build_slash_reg(0xDA, 1, "FCMOVE", OP_FPU_reg, &Interpreter::FCMOVE);
+ build_slash(0xDA, 2, "FICOM", OP_FPU_RM32, &Interpreter::FICOM_RM32);
+ build_slash_reg(0xDA, 2, "FCMOVBE", OP_FPU_reg, &Interpreter::FCMOVBE);
+ build_slash(0xDA, 3, "FICOMP", OP_FPU_RM32, &Interpreter::FICOMP_RM32);
+ build_slash_reg(0xDA, 3, "FCMOVU", OP_FPU_reg, &Interpreter::FCMOVU);
+ build_slash(0xDA, 4, "FISUB", OP_FPU_RM32, &Interpreter::FISUB_RM32);
+ build_slash(0xDA, 5, "FISUBR", OP_FPU_RM32, &Interpreter::FISUBR_RM32);
+ build_slash_rm(0xDA, 5, 0xE9, "FUCOMPP", OP_FPU, &Interpreter::FUCOMPP);
+ build_slash(0xDA, 6, "FIDIV", OP_FPU_RM32, &Interpreter::FIDIV_RM32);
+ build_slash(0xDA, 7, "FIDIVR", OP_FPU_RM32, &Interpreter::FIDIVR_RM32);
+
+ build_slash(0xDB, 0, "FILD", OP_FPU_RM32, &Interpreter::FILD_RM32);
+ build_slash_reg(0xDB, 0, "FCMOVNB", OP_FPU_reg, &Interpreter::FCMOVNB);
+ build_slash(0xDB, 1, "FISTTP", OP_FPU_RM32, &Interpreter::FISTTP_RM32);
+ build_slash_reg(0xDB, 1, "FCMOVNE", OP_FPU_reg, &Interpreter::FCMOVNE);
+ build_slash(0xDB, 2, "FIST", OP_FPU_RM32, &Interpreter::FIST_RM32);
+ build_slash_reg(0xDB, 2, "FCMOVNBE", OP_FPU_reg, &Interpreter::FCMOVNBE);
+ build_slash(0xDB, 3, "FISTP", OP_FPU_RM32, &Interpreter::FISTP_RM32);
+ build_slash_reg(0xDB, 3, "FCMOVNU", OP_FPU_reg, &Interpreter::FCMOVNU);
+ build_slash(0xDB, 4, "FUNASSIGNED", OP_FPU, &Interpreter::ESCAPE);
+ build_slash_rm(0xDB, 4, 0xE0, "FNENI", OP_FPU_reg, &Interpreter::FNENI);
+ build_slash_rm(0xDB, 4, 0xE1, "FNDISI", OP_FPU_reg, &Interpreter::FNDISI);
+ build_slash_rm(0xDB, 4, 0xE2, "FNCLEX", OP_FPU_reg, &Interpreter::FNCLEX);
+ // FIXME: Extraodinary prefix 0x9B + 0xDB/4: FCLEX
+ build_slash_rm(0xDB, 4, 0xE3, "FNINIT", OP_FPU_reg, &Interpreter::FNINIT);
+ // FIXME: Extraodinary prefix 0x9B + 0xDB/4: FINIT
+ build_slash_rm(0xDB, 4, 0xE4, "FNSETPM", OP_FPU_reg, &Interpreter::FNSETPM);
+ build_slash(0xDB, 5, "FLD", OP_FPU_M80, &Interpreter::FLD_RM80);
+ build_slash_reg(0xDB, 5, "FUCOMI", OP_FPU_reg, &Interpreter::FUCOMI);
+ build_slash(0xDB, 6, "FCOMI", OP_FPU_reg, &Interpreter::FCOMI);
+ build_slash(0xDB, 7, "FSTP", OP_FPU_M80, &Interpreter::FSTP_RM80);
build_slash(0xDC, 0, "FADD", OP_FPU_RM64, &Interpreter::FADD_RM64);
build_slash(0xDC, 1, "FMUL", OP_FPU_RM64, &Interpreter::FMUL_RM64);
@@ -529,10 +570,61 @@ static void build_slash_rm(u8 op, u8 slash, u8 rm, const char* mnemonic, Instruc
build_slash(0xDC, 6, "FDIV", OP_FPU_RM64, &Interpreter::FDIV_RM64);
build_slash(0xDC, 7, "FDIVR", OP_FPU_RM64, &Interpreter::FDIVR_RM64);
- // FIXME
- build(0xDD, "FPU?", OP_RM8, &Interpreter::ESCAPE);
- build(0xDE, "FPU?", OP_RM8, &Interpreter::ESCAPE);
- build(0xDF, "FPU?", OP_RM8, &Interpreter::ESCAPE);
+ build_slash(0xDD, 0, "FLD", OP_FPU_RM64, &Interpreter::FLD_RM64);
+ build_slash_reg(0xDD, 0, "FFREE", OP_FPU_reg, &Interpreter::FFREE);
+ build_slash(0xDD, 1, "FISTTP", OP_FPU_RM64, &Interpreter::FISTTP_RM64);
+ build_slash_reg(0xDD, 1, "FXCH4", OP_FPU_reg, &Interpreter::FXCH);
+ build_slash(0xDD, 2, "FST", OP_FPU_RM64, &Interpreter::FST_RM64);
+ build_slash(0xDD, 3, "FSTP", OP_FPU_RM64, &Interpreter::FSTP_RM64);
+ build_slash(0xDD, 4, "FRSTOR", OP_FPU_mem, &Interpreter::FRSTOR);
+ build_slash_reg(0xDD, 4, "FUCOM", OP_FPU_reg, &Interpreter::FUCOM);
+ // FIXME: DD/4 E1 (...but isn't this what DD/4 does naturally, with E1 just being normal R/M?)
+ build_slash(0xDD, 5, "FUCOMP", OP_FPU_reg, &Interpreter::FUCOMP);
+ // FIXME: DD/5 E9 (...but isn't this what DD/5 does naturally, with E9 just being normal R/M?)
+ build_slash(0xDD, 6, "FNSAVE", OP_FPU_mem, &Interpreter::FNSAVE);
+ // FIXME: Extraodinary prefix 0x9B + 0xDD/6: FSAVE
+ build_slash(0xDD, 7, "FNSTSW", OP_FPU_RM16, &Interpreter::FNSTSW);
+ // FIXME: Extraodinary prefix 0x9B + 0xDD/7: FSTSW
+
+ build_slash(0xDE, 0, "FIADD", OP_FPU_RM16, &Interpreter::FIADD_RM16);
+ build_slash_reg(0xDE, 0, "FADDP", OP_FPU_reg, &Interpreter::FADDP);
+ // FIXME: DE/0 C1 (...but isn't this what DE/0 does naturally, with C1 just being normal R/M?)
+ build_slash(0xDE, 1, "FIMUL", OP_FPU_RM16, &Interpreter::FIMUL_RM16);
+ build_slash_reg(0xDE, 1, "FMULP", OP_FPU_reg, &Interpreter::FMULP);
+ // FIXME: DE/1 C9 (...but isn't this what DE/1 does naturally, with C9 just being normal R/M?)
+ build_slash(0xDE, 2, "FICOM", OP_FPU_RM16, &Interpreter::FICOM_RM16);
+ build_slash_reg(0xDE, 2, "FCOMP5", OP_FPU_reg, &Interpreter::FCOMP_RM32);
+ build_slash(0xDE, 3, "FICOMP", OP_FPU_RM16, &Interpreter::FICOMP_RM16);
+ build_slash_reg(0xDE, 3, "FCOMPP", OP_FPU_reg, &Interpreter::FCOMPP);
+ build_slash(0xDE, 4, "FISUB", OP_FPU_RM16, &Interpreter::FISUB_RM16);
+ build_slash_reg(0xDE, 4, "FSUBRP", OP_FPU_reg, &Interpreter::FSUBRP);
+ // FIXME: DE/4 E1 (...but isn't this what DE/4 does naturally, with E1 just being normal R/M?)
+ build_slash(0xDE, 5, "FISUBR", OP_FPU_RM16, &Interpreter::FISUBR_RM16);
+ build_slash_reg(0xDE, 5, "FSUBP", OP_FPU_reg, &Interpreter::FSUBP);
+ // FIXME: DE/5 E9 (...but isn't this what DE/5 does naturally, with E9 just being normal R/M?)
+ build_slash(0xDE, 6, "FIDIV", OP_FPU_RM16, &Interpreter::FIDIV_RM16);
+ build_slash_reg(0xDE, 6, "FDIVRP", OP_FPU_reg, &Interpreter::FDIVRP);
+ // FIXME: DE/6 F1 (...but isn't this what DE/6 does naturally, with F1 just being normal R/M?)
+ build_slash(0xDE, 7, "FIDIVR", OP_FPU_RM16, &Interpreter::FIDIVR_RM16);
+ build_slash_reg(0xDE, 7, "FDIVP", OP_FPU_reg, &Interpreter::FDIVP);
+ // FIXME: DE/7 F9 (...but isn't this what DE/7 does naturally, with F9 just being normal R/M?)
+
+ build_slash(0xDF, 0, "FILD", OP_FPU_RM32, &Interpreter::FILD_RM16);
+ build_slash_reg(0xDF, 0, "FFREEP", OP_FPU_reg, &Interpreter::FFREEP);
+ build_slash(0xDF, 1, "FISTTP", OP_FPU_RM32, &Interpreter::FISTTP_RM16);
+ build_slash_reg(0xDF, 1, "FXCH7", OP_FPU_reg, &Interpreter::FXCH);
+ build_slash(0xDF, 2, "FIST", OP_FPU_RM32, &Interpreter::FIST_RM16);
+ build_slash_reg(0xDF, 2, "FSTP8", OP_FPU_reg, &Interpreter::FSTP_RM32);
+ build_slash(0xDF, 3, "FISTP", OP_FPU_RM32, &Interpreter::FISTP_RM16);
+ build_slash_reg(0xDF, 3, "FSTP9", OP_FPU_reg, &Interpreter::FSTP_RM32);
+ build_slash(0xDF, 4, "FBLD", OP_FPU_M80, &Interpreter::FBLD_M80);
+ build_slash_reg(0xDF, 4, "FNSTSW", OP_FPU_AX16, &Interpreter::FNSTSW_AX);
+ // FIXME: Extraodinary prefix 0x9B + 0xDF/e: FSTSW_AX
+ build_slash(0xDF, 5, "FILD", OP_FPU_RM64, &Interpreter::FILD_RM64);
+ build_slash_reg(0xDF, 5, "FUCOMIP", OP_FPU_reg, &Interpreter::FUCOMIP);
+ build_slash(0xDF, 6, "FBSTP", OP_FPU_M80, &Interpreter::FBSTP_M80);
+ build_slash_reg(0xDF, 6, "FCOMIP", OP_FPU_reg, &Interpreter::FCOMIP);
+ build_slash(0xDF, 7, "FISTP", OP_FPU_RM64, &Interpreter::FISTP_RM64);
build(0xE0, "LOOPNZ", OP_imm8, &Interpreter::LOOPNZ_imm8);
build(0xE1, "LOOPZ", OP_imm8, &Interpreter::LOOPZ_imm8);
@@ -849,6 +941,25 @@ String MemoryOrRegisterReference::to_string_fpu_reg() const
return register_name(reg_fpu());
}
+String MemoryOrRegisterReference::to_string_fpu_mem(const Instruction& insn) const
+{
+ ASSERT(!is_register());
+ return String::format("[%s]", to_string(insn).characters());
+}
+
+String MemoryOrRegisterReference::to_string_fpu_ax16() const
+{
+ ASSERT(is_register());
+ return register_name(reg16());
+}
+
+String MemoryOrRegisterReference::to_string_fpu16(const Instruction& insn) const
+{
+ if (is_register())
+ return register_name(reg_fpu());
+ return String::format("word ptr [%s]", to_string(insn).characters());
+}
+
String MemoryOrRegisterReference::to_string_fpu32(const Instruction& insn) const
{
if (is_register())
@@ -863,6 +974,11 @@ String MemoryOrRegisterReference::to_string_fpu64(const Instruction& insn) const
return String::format("qword ptr [%s]", to_string(insn).characters());
}
+String MemoryOrRegisterReference::to_string_fpu80(const Instruction& insn) const
+{
+ ASSERT(!is_register());
+ return String::format("tbyte ptr [%s]", to_string(insn).characters());
+}
String MemoryOrRegisterReference::to_string_mm(const Instruction& insn) const
{
if (is_register())
@@ -1153,8 +1269,12 @@ String Instruction::to_string_internal(u32 origin, const SymbolProvider* symbol_
auto append_rm16 = [&] { builder.append(m_modrm.to_string_o16(*this)); };
auto append_rm32 = [&] { builder.append(m_modrm.to_string_o32(*this)); };
auto append_fpu_reg = [&] { builder.append(m_modrm.to_string_fpu_reg()); };
+ auto append_fpu_mem = [&] { builder.append(m_modrm.to_string_fpu_mem(*this)); };
+ auto append_fpu_ax16 = [&] { builder.append(m_modrm.to_string_fpu_ax16()); };
+ auto append_fpu_rm16 = [&] { builder.append(m_modrm.to_string_fpu16(*this)); };
auto append_fpu_rm32 = [&] { builder.append(m_modrm.to_string_fpu32(*this)); };
auto append_fpu_rm64 = [&] { builder.append(m_modrm.to_string_fpu64(*this)); };
+ auto append_fpu_rm80 = [&] { builder.append(m_modrm.to_string_fpu80(*this)); };
auto append_imm8 = [&] { builder.appendf("%#02x", imm8()); };
auto append_imm8_2 = [&] { builder.appendf("%#02x", imm8_2()); };
auto append_imm16 = [&] { builder.appendf("%#04x", imm16()); };
@@ -1423,12 +1543,24 @@ String Instruction::to_string_internal(u32 origin, const SymbolProvider* symbol_
case OP_FPU_reg:
append_fpu_reg();
break;
+ case OP_FPU_mem:
+ append_fpu_mem();
+ break;
+ case OP_FPU_AX16:
+ append_fpu_ax16();
+ break;
+ case OP_FPU_RM16:
+ append_fpu_rm16();
+ break;
case OP_FPU_RM32:
append_fpu_rm32();
break;
case OP_FPU_RM64:
append_fpu_rm64();
break;
+ case OP_FPU_M80:
+ append_fpu_rm80();
+ break;
case OP_RM8_reg8:
append_rm8();
append(", ");
diff --git a/Libraries/LibX86/Instruction.h b/Libraries/LibX86/Instruction.h
index cd259077c6..93cab62ba4 100644
--- a/Libraries/LibX86/Instruction.h
+++ b/Libraries/LibX86/Instruction.h
@@ -83,8 +83,12 @@ enum InstructionFormat {
OP_RM32,
OP_FPU,
OP_FPU_reg,
+ OP_FPU_mem,
+ OP_FPU_AX16,
+ OP_FPU_RM16,
OP_FPU_RM32,
OP_FPU_RM64,
+ OP_FPU_M80,
OP_RM8_reg8,
OP_RM32_reg32,
OP_reg32_RM32,
@@ -359,8 +363,12 @@ public:
String to_string_o16(const Instruction&) const;
String to_string_o32(const Instruction&) const;
String to_string_fpu_reg() const;
+ String to_string_fpu_mem(const Instruction&) const;
+ String to_string_fpu_ax16() const;
+ String to_string_fpu16(const Instruction&) const;
String to_string_fpu32(const Instruction&) const;
String to_string_fpu64(const Instruction&) const;
+ String to_string_fpu80(const Instruction&) const;
String to_string_mm(const Instruction&) const;
bool is_register() const { return m_register_index != 0xffffffff; }
diff --git a/Libraries/LibX86/Interpreter.h b/Libraries/LibX86/Interpreter.h
index ae0e6133ef..efbf4164d8 100644
--- a/Libraries/LibX86/Interpreter.h
+++ b/Libraries/LibX86/Interpreter.h
@@ -200,6 +200,36 @@ public:
virtual void FSCALE(const Instruction&) = 0;
virtual void FSIN(const Instruction&) = 0;
virtual void FCOS(const Instruction&) = 0;
+ virtual void FIADD_RM32(const Instruction&) = 0;
+ virtual void FADDP(const Instruction&) = 0;
+ virtual void FIMUL_RM32(const Instruction&) = 0;
+ virtual void FCMOVE(const Instruction&) = 0;
+ virtual void FICOM_RM32(const Instruction&) = 0;
+ virtual void FCMOVBE(const Instruction&) = 0;
+ virtual void FICOMP_RM32(const Instruction&) = 0;
+ virtual void FCMOVU(const Instruction&) = 0;
+ virtual void FISUB_RM32(const Instruction&) = 0;
+ virtual void FISUBR_RM32(const Instruction&) = 0;
+ virtual void FUCOMPP(const Instruction&) = 0;
+ virtual void FIDIV_RM32(const Instruction&) = 0;
+ virtual void FIDIVR_RM32(const Instruction&) = 0;
+ virtual void FILD_RM32(const Instruction&) = 0;
+ virtual void FCMOVNB(const Instruction&) = 0;
+ virtual void FISTTP_RM32(const Instruction&) = 0;
+ virtual void FCMOVNE(const Instruction&) = 0;
+ virtual void FIST_RM32(const Instruction&) = 0;
+ virtual void FCMOVNBE(const Instruction&) = 0;
+ virtual void FISTP_RM32(const Instruction&) = 0;
+ virtual void FCMOVNU(const Instruction&) = 0;
+ virtual void FNENI(const Instruction&) = 0;
+ virtual void FNDISI(const Instruction&) = 0;
+ virtual void FNCLEX(const Instruction&) = 0;
+ virtual void FNINIT(const Instruction&) = 0;
+ virtual void FNSETPM(const Instruction&) = 0;
+ virtual void FLD_RM80(const Instruction&) = 0;
+ virtual void FUCOMI(const Instruction&) = 0;
+ virtual void FCOMI(const Instruction&) = 0;
+ virtual void FSTP_RM80(const Instruction&) = 0;
virtual void FADD_RM64(const Instruction&) = 0;
virtual void FMUL_RM64(const Instruction&) = 0;
virtual void FCOM_RM64(const Instruction&) = 0;
@@ -208,6 +238,43 @@ public:
virtual void FSUBR_RM64(const Instruction&) = 0;
virtual void FDIV_RM64(const Instruction&) = 0;
virtual void FDIVR_RM64(const Instruction&) = 0;
+ virtual void FLD_RM64(const Instruction&) = 0;
+ virtual void FFREE(const Instruction&) = 0;
+ virtual void FISTTP_RM64(const Instruction&) = 0;
+ virtual void FST_RM64(const Instruction&) = 0;
+ virtual void FSTP_RM64(const Instruction&) = 0;
+ virtual void FRSTOR(const Instruction&) = 0;
+ virtual void FUCOM(const Instruction&) = 0;
+ virtual void FUCOMP(const Instruction&) = 0;
+ virtual void FNSAVE(const Instruction&) = 0;
+ virtual void FNSTSW(const Instruction&) = 0;
+ virtual void FIADD_RM16(const Instruction&) = 0;
+ virtual void FCMOVB(const Instruction&) = 0;
+ virtual void FIMUL_RM16(const Instruction&) = 0;
+ virtual void FMULP(const Instruction&) = 0;
+ virtual void FICOM_RM16(const Instruction&) = 0;
+ virtual void FICOMP_RM16(const Instruction&) = 0;
+ virtual void FCOMPP(const Instruction&) = 0;
+ virtual void FISUB_RM16(const Instruction&) = 0;
+ virtual void FSUBRP(const Instruction&) = 0;
+ virtual void FISUBR_RM16(const Instruction&) = 0;
+ virtual void FSUBP(const Instruction&) = 0;
+ virtual void FIDIV_RM16(const Instruction&) = 0;
+ virtual void FDIVRP(const Instruction&) = 0;
+ virtual void FIDIVR_RM16(const Instruction&) = 0;
+ virtual void FDIVP(const Instruction&) = 0;
+ virtual void FILD_RM16(const Instruction&) = 0;
+ virtual void FFREEP(const Instruction&) = 0;
+ virtual void FISTTP_RM16(const Instruction&) = 0;
+ virtual void FIST_RM16(const Instruction&) = 0;
+ virtual void FISTP_RM16(const Instruction&) = 0;
+ virtual void FBLD_M80(const Instruction&) = 0;
+ virtual void FNSTSW_AX(const Instruction&) = 0;
+ virtual void FILD_RM64(const Instruction&) = 0;
+ virtual void FUCOMIP(const Instruction&) = 0;
+ virtual void FBSTP_M80(const Instruction&) = 0;
+ virtual void FCOMIP(const Instruction&) = 0;
+ virtual void FISTP_RM64(const Instruction&) = 0;
virtual void HLT(const Instruction&) = 0;
virtual void IDIV_RM16(const Instruction&) = 0;
virtual void IDIV_RM32(const Instruction&) = 0;