diff options
-rw-r--r-- | DevTools/UserspaceEmulator/SoftCPU.cpp | 156 | ||||
-rw-r--r-- | DevTools/UserspaceEmulator/SoftCPU.h | 24 | ||||
-rw-r--r-- | Libraries/LibX86/Instruction.h | 64 |
3 files changed, 205 insertions, 39 deletions
diff --git a/DevTools/UserspaceEmulator/SoftCPU.cpp b/DevTools/UserspaceEmulator/SoftCPU.cpp index 9f5b1b03b9..df6f8b53dc 100644 --- a/DevTools/UserspaceEmulator/SoftCPU.cpp +++ b/DevTools/UserspaceEmulator/SoftCPU.cpp @@ -149,12 +149,57 @@ static typename TypeDoubler<Destination>::type op_xor(SoftCPU& cpu, Destination& } template<typename Op> -void SoftCPU::generic_RM32_reg32(Op op, const X86::Instruction& insn) +void SoftCPU::generic_AL_imm8(Op op, const X86::Instruction& insn) { - auto dest = insn.modrm().read32(*this, insn); - auto src = gpr32(insn.reg32()); + auto dest = al(); + auto src = insn.imm8(); auto result = op(*this, dest, src); - insn.modrm().write32(*this, insn, result); + set_al(result); +} + +template<typename Op> +void SoftCPU::generic_AX_imm16(Op op, const X86::Instruction& insn) +{ + auto dest = ax(); + auto src = insn.imm16(); + auto result = op(*this, dest, src); + set_ax(result); +} + +template<typename Op> +void SoftCPU::generic_EAX_imm32(Op op, const X86::Instruction& insn) +{ + auto dest = eax(); + auto src = insn.imm32(); + auto result = op(*this, dest, src); + set_eax(result); +} + +template<typename Op> +void SoftCPU::generic_RM16_imm16(Op op, const X86::Instruction& insn) +{ + auto dest = insn.modrm().read16(*this, insn); + auto src = insn.imm16(); + auto result = op(*this, dest, src); + insn.modrm().write16(*this, insn, result); +} + +template<typename Op> +void SoftCPU::generic_RM16_imm8(Op op, const X86::Instruction& insn) +{ + auto dest = insn.modrm().read16(*this, insn); + auto src = insn.imm8(); + auto result = op(*this, dest, src); + insn.modrm().write16(*this, insn, result); +} + +template<typename Op> +void SoftCPU::generic_RM16_reg16(Op op, const X86::Instruction& insn) +{ + auto dest = insn.modrm().read16(*this, insn); + auto src = gpr16(insn.reg16()); + auto result = op(*this, dest, src); + insn.modrm().write16(*this, insn, result); } template<typename Op> @@ -175,6 +220,60 @@ void SoftCPU::generic_RM32_imm8(Op op, const X86::Instruction& insn) insn.modrm().write32(*this, insn, result); } +template<typename Op> +void SoftCPU::generic_RM32_reg32(Op op, const X86::Instruction& insn) +{ + auto dest = insn.modrm().read32(*this, insn); + auto src = gpr32(insn.reg32()); + auto result = op(*this, dest, src); + insn.modrm().write32(*this, insn, result); +} + +template<typename Op> +void SoftCPU::generic_RM8_imm8(Op op, const X86::Instruction& insn) +{ + auto dest = insn.modrm().read8(*this, insn); + auto src = insn.imm8(); + auto result = op(*this, dest, src); + insn.modrm().write8(*this, insn, result); +} + +template<typename Op> +void SoftCPU::generic_RM8_reg8(Op op, const X86::Instruction& insn) +{ + auto dest = insn.modrm().read8(*this, insn); + auto src = gpr8(insn.reg8()); + auto result = op(*this, dest, src); + insn.modrm().write8(*this, insn, result); +} + +template<typename Op> +void SoftCPU::generic_reg16_RM16(Op op, const X86::Instruction& insn) +{ + auto dest = gpr16(insn.reg16()); + auto src = insn.modrm().read16(*this, insn); + auto result = op(*this, dest, src); + gpr16(insn.reg16()) = result; +} + +template<typename Op> +void SoftCPU::generic_reg32_RM32(Op op, const X86::Instruction& insn) +{ + auto dest = gpr32(insn.reg32()); + auto src = insn.modrm().read32(*this, insn); + auto result = op(*this, dest, src); + gpr32(insn.reg32()) = result; +} + +template<typename Op> +void SoftCPU::generic_reg8_RM8(Op op, const X86::Instruction& insn) +{ + auto dest = gpr8(insn.reg8()); + auto src = insn.modrm().read8(*this, insn); + auto result = op(*this, dest, src); + gpr8(insn.reg8()) = result; +} + void SoftCPU::AAA(const X86::Instruction&) { TODO(); } void SoftCPU::AAD(const X86::Instruction&) { TODO(); } void SoftCPU::AAM(const X86::Instruction&) { TODO(); } @@ -646,38 +745,24 @@ void SoftCPU::XCHG_reg32_RM32(const X86::Instruction&) { TODO(); } void SoftCPU::XCHG_reg8_RM8(const X86::Instruction&) { TODO(); } void SoftCPU::XLAT(const X86::Instruction&) { TODO(); } -void SoftCPU::XOR_AL_imm8(const X86::Instruction&) -{ - - TODO(); -} - -void SoftCPU::XOR_AX_imm16(const X86::Instruction&) { TODO(); } -void SoftCPU::XOR_EAX_imm32(const X86::Instruction&) { TODO(); } -void SoftCPU::XOR_RM16_imm16(const X86::Instruction&) { TODO(); } -void SoftCPU::XOR_RM16_imm8(const X86::Instruction&) { TODO(); } -void SoftCPU::XOR_RM16_reg16(const X86::Instruction&) { TODO(); } +#define DEFINE_GENERIC_INSN_HANDLERS(mnemonic, op) \ + void SoftCPU::mnemonic##_AL_imm8(const X86::Instruction& insn) { generic_AL_imm8(op<u8, u8>, insn); } \ + void SoftCPU::mnemonic##_AX_imm16(const X86::Instruction& insn) { generic_AX_imm16(op<u16, u16>, insn); } \ + void SoftCPU::mnemonic##_EAX_imm32(const X86::Instruction& insn) { generic_EAX_imm32(op<u32, u32>, insn); } \ + void SoftCPU::mnemonic##_RM16_imm16(const X86::Instruction& insn) { generic_RM16_imm16(op<u16, u16>, insn); } \ + void SoftCPU::mnemonic##_RM16_imm8(const X86::Instruction& insn) { generic_RM16_imm8(op<u16, u8>, insn); } \ + void SoftCPU::mnemonic##_RM16_reg16(const X86::Instruction& insn) { generic_RM16_reg16(op<u16, u16>, insn); } \ + void SoftCPU::mnemonic##_RM32_imm32(const X86::Instruction& insn) { generic_RM32_imm32(op<u32, u32>, insn); } \ + void SoftCPU::mnemonic##_RM32_imm8(const X86::Instruction& insn) { generic_RM32_imm8(op<u32, u8>, insn); } \ + void SoftCPU::mnemonic##_RM32_reg32(const X86::Instruction& insn) { generic_RM32_reg32(op<u32, u32>, insn); } \ + void SoftCPU::mnemonic##_RM8_imm8(const X86::Instruction& insn) { generic_RM8_imm8(op<u8, u8>, insn); } \ + void SoftCPU::mnemonic##_RM8_reg8(const X86::Instruction& insn) { generic_RM8_reg8(op<u8, u8>, insn); } \ + void SoftCPU::mnemonic##_reg16_RM16(const X86::Instruction& insn) { generic_reg16_RM16(op<u16, u16>, insn); } \ + void SoftCPU::mnemonic##_reg32_RM32(const X86::Instruction& insn) { generic_reg32_RM32(op<u32, u32>, insn); } \ + void SoftCPU::mnemonic##_reg8_RM8(const X86::Instruction& insn) { generic_reg8_RM8(op<u8, u8>, insn); } + +DEFINE_GENERIC_INSN_HANDLERS(XOR, op_xor) -void SoftCPU::XOR_RM32_imm32(const X86::Instruction& insn) -{ - generic_RM32_imm32(op_xor<u32, u32>, insn); -} - -void SoftCPU::XOR_RM32_imm8(const X86::Instruction& insn) -{ - generic_RM32_imm8(op_xor<u32, u8>, insn); -} - -void SoftCPU::XOR_RM32_reg32(const X86::Instruction& insn) -{ - generic_RM32_reg32(op_xor<u32, u32>, insn); -} - -void SoftCPU::XOR_RM8_imm8(const X86::Instruction&) { TODO(); } -void SoftCPU::XOR_RM8_reg8(const X86::Instruction&) { TODO(); } -void SoftCPU::XOR_reg16_RM16(const X86::Instruction&) { TODO(); } -void SoftCPU::XOR_reg32_RM32(const X86::Instruction&) { TODO(); } -void SoftCPU::XOR_reg8_RM8(const X86::Instruction&) { TODO(); } void SoftCPU::MOVQ_mm1_mm2m64(const X86::Instruction&) { TODO(); } void SoftCPU::EMMS(const X86::Instruction&) { TODO(); } void SoftCPU::MOVQ_mm1_m64_mm2(const X86::Instruction&) { TODO(); } @@ -690,5 +775,4 @@ void SoftCPU::wrap_0xD1_32(const X86::Instruction&) { TODO(); } void SoftCPU::wrap_0xD2(const X86::Instruction&) { TODO(); } void SoftCPU::wrap_0xD3_16(const X86::Instruction&) { TODO(); } void SoftCPU::wrap_0xD3_32(const X86::Instruction&) { TODO(); } - } diff --git a/DevTools/UserspaceEmulator/SoftCPU.h b/DevTools/UserspaceEmulator/SoftCPU.h index 37da19fde6..a8d167000a 100644 --- a/DevTools/UserspaceEmulator/SoftCPU.h +++ b/DevTools/UserspaceEmulator/SoftCPU.h @@ -664,11 +664,33 @@ private: virtual void wrap_0xD3_32(const X86::Instruction&) override; template<typename Op> - void generic_RM32_reg32(Op, const X86::Instruction&); + void generic_AL_imm8(Op, const X86::Instruction&); + template<typename Op> + void generic_AX_imm16(Op, const X86::Instruction&); + template<typename Op> + void generic_EAX_imm32(Op, const X86::Instruction&); + template<typename Op> + void generic_RM16_imm16(Op, const X86::Instruction&); + template<typename Op> + void generic_RM16_imm8(Op, const X86::Instruction&); + template<typename Op> + void generic_RM16_reg16(Op, const X86::Instruction&); template<typename Op> void generic_RM32_imm32(Op, const X86::Instruction&); template<typename Op> void generic_RM32_imm8(Op, const X86::Instruction&); + template<typename Op> + void generic_RM32_reg32(Op, const X86::Instruction&); + template<typename Op> + void generic_RM8_imm8(Op, const X86::Instruction&); + template<typename Op> + void generic_RM8_reg8(Op, const X86::Instruction&); + template<typename Op> + void generic_reg16_RM16(Op, const X86::Instruction&); + template<typename Op> + void generic_reg32_RM32(Op, const X86::Instruction&); + template<typename Op> + void generic_reg8_RM8(Op, const X86::Instruction&); private: Emulator& m_emulator; diff --git a/Libraries/LibX86/Instruction.h b/Libraries/LibX86/Instruction.h index ea928ee3eb..17208a829b 100644 --- a/Libraries/LibX86/Instruction.h +++ b/Libraries/LibX86/Instruction.h @@ -205,9 +205,17 @@ public: RegisterIndex8 reg8() const { return static_cast<RegisterIndex8>(register_index()); } template<typename CPU> + void write8(CPU&, const Instruction&, u8); + template<typename CPU> + void write16(CPU&, const Instruction&, u16); + template<typename CPU> void write32(CPU&, const Instruction&, u32); template<typename CPU> + u8 read8(CPU&, const Instruction&); + template<typename CPU> + u16 read16(CPU&, const Instruction&); + template<typename CPU> u32 read32(CPU&, const Instruction&); private: @@ -227,6 +235,14 @@ private: LogicalAddress resolve32(const CPU&, Optional<SegmentRegister>); template<typename CPU> + LogicalAddress resolve(const CPU& cpu, Optional<SegmentRegister> segment_prefix) + { + if (m_a32) + return resolve32(cpu, segment_prefix); + return resolve16(cpu, segment_prefix); + } + + template<typename CPU> u32 evaluate_sib(const CPU&, SegmentRegister& default_segment) const; unsigned m_register_index { 0xffffffff }; @@ -560,6 +576,30 @@ inline u32 MemoryOrRegisterReference::evaluate_sib(const CPU& cpu, SegmentRegist } template<typename CPU> +inline void MemoryOrRegisterReference::write8(CPU& cpu, const Instruction& insn, u8 value) +{ + if (is_register()) { + cpu.gpr8(reg8()) = value; + return; + } + + auto address = resolve(cpu, insn.segment_prefix()); + cpu.write_memory8(address, value); +} + +template<typename CPU> +inline void MemoryOrRegisterReference::write16(CPU& cpu, const Instruction& insn, u16 value) +{ + if (is_register()) { + cpu.gpr16(reg16()) = value; + return; + } + + auto address = resolve(cpu, insn.segment_prefix()); + cpu.write_memory16(address, value); +} + +template<typename CPU> inline void MemoryOrRegisterReference::write32(CPU& cpu, const Instruction& insn, u32 value) { if (is_register()) { @@ -567,17 +607,37 @@ inline void MemoryOrRegisterReference::write32(CPU& cpu, const Instruction& insn return; } - auto address = resolve32(cpu, insn.segment_prefix()); + auto address = resolve(cpu, insn.segment_prefix()); cpu.write_memory32(address, value); } template<typename CPU> +inline u8 MemoryOrRegisterReference::read8(CPU& cpu, const Instruction& insn) +{ + if (is_register()) + return cpu.gpr8(reg8()); + + auto address = resolve(cpu, insn.segment_prefix()); + return cpu.read_memory8(address); +} + +template<typename CPU> +inline u16 MemoryOrRegisterReference::read16(CPU& cpu, const Instruction& insn) +{ + if (is_register()) + return cpu.gpr16(reg16()); + + auto address = resolve(cpu, insn.segment_prefix()); + return cpu.read_memory16(address); +} + +template<typename CPU> inline u32 MemoryOrRegisterReference::read32(CPU& cpu, const Instruction& insn) { if (is_register()) return cpu.gpr32(reg32()); - auto address = resolve32(cpu, insn.segment_prefix()); + auto address = resolve(cpu, insn.segment_prefix()); return cpu.read_memory32(address); } |