1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-05-29 17:35:06 +00:00

UserspaceEmulator: First cut of generic instruction implementations

Let's use C++ templates to implement the generic parts of instructions.
There are tons of them with the same set of inputs, just different
behavior. Templates are perfect for this.
This commit is contained in:
Andreas Kling 2020-07-10 16:30:37 +02:00
parent 30ef30ca09
commit f8b38eabeb
2 changed files with 92 additions and 13 deletions

View file

@ -32,6 +32,34 @@
namespace UserspaceEmulator {
template<typename T>
struct TypeDoubler {
};
template<>
struct TypeDoubler<u8> {
typedef u16 type;
};
template<>
struct TypeDoubler<u16> {
typedef u32 type;
};
template<>
struct TypeDoubler<u32> {
typedef u64 type;
};
template<>
struct TypeDoubler<i8> {
typedef i16 type;
};
template<>
struct TypeDoubler<i16> {
typedef i32 type;
};
template<>
struct TypeDoubler<i32> {
typedef i64 type;
};
SoftCPU::SoftCPU(Emulator& emulator)
: m_emulator(emulator)
{
@ -78,6 +106,45 @@ u32 SoftCPU::pop32()
return value;
}
template<typename Destination, typename Source>
static typename TypeDoubler<Destination>::type op_xor(SoftCPU& cpu, Destination& dest, const Source& src)
{
auto result = dest ^ src;
cpu.set_zf(dest == 0);
cpu.set_sf(dest & 0x80000000);
// FIXME: set_pf
cpu.set_of(false);
cpu.set_cf(false);
return 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_RM32_imm32(Op op, const X86::Instruction& insn)
{
auto dest = insn.modrm().read32(*this, insn);
auto src = insn.imm32();
auto result = op(*this, dest, src);
insn.modrm().write32(*this, insn, result);
}
template<typename Op>
void SoftCPU::generic_RM32_imm8(Op op, const X86::Instruction& insn)
{
auto dest = insn.modrm().read32(*this, insn);
auto src = insn.imm8();
auto result = op(*this, dest, src);
insn.modrm().write32(*this, insn, result);
}
void SoftCPU::AAA(const X86::Instruction&) { TODO(); }
void SoftCPU::AAD(const X86::Instruction&) { TODO(); }
void SoftCPU::AAM(const X86::Instruction&) { TODO(); }
@ -548,27 +615,32 @@ void SoftCPU::XCHG_reg16_RM16(const X86::Instruction&) { TODO(); }
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_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(); }
void SoftCPU::XOR_RM32_imm32(const X86::Instruction&) { TODO(); }
void SoftCPU::XOR_RM32_imm8(const X86::Instruction&) { TODO(); }
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)
{
ASSERT(insn.modrm().is_register());
auto& dest = gpr32(insn.modrm().reg32());
auto src = gpr32(insn.reg32());
dest ^= src;
set_cf(false);
set_of(false);
set_zf(dest == 0);
set_sf(dest & 0x80000000);
// FIXME: set_pf
generic_RM32_reg32(op_xor<u32, u32>, insn);
}
void SoftCPU::XOR_RM8_imm8(const X86::Instruction&) { TODO(); }