mirror of
https://github.com/RGBCube/serenity
synced 2025-07-25 16:37:35 +00:00
UserspaceEmulator: Tidy up SoftCPU's general purpose registers
This patch adds a PartAddressableRegister type, which divides a 32-bit value into separate parts needed for the EAX/AX/AL/AH register splits. Clean up the code around register access to make it a little less cumbersome to use.
This commit is contained in:
parent
b02d33bd63
commit
4d8683b632
3 changed files with 79 additions and 55 deletions
|
@ -34,21 +34,13 @@ namespace UserspaceEmulator {
|
|||
SoftCPU::SoftCPU(Emulator& emulator)
|
||||
: m_emulator(emulator)
|
||||
{
|
||||
m_reg32_table[X86::RegisterEAX] = &m_eax;
|
||||
m_reg32_table[X86::RegisterEBX] = &m_ebx;
|
||||
m_reg32_table[X86::RegisterECX] = &m_ecx;
|
||||
m_reg32_table[X86::RegisterEDX] = &m_edx;
|
||||
m_reg32_table[X86::RegisterEBP] = &m_ebp;
|
||||
m_reg32_table[X86::RegisterESP] = &m_esp;
|
||||
m_reg32_table[X86::RegisterESI] = &m_esi;
|
||||
m_reg32_table[X86::RegisterEDI] = &m_edi;
|
||||
}
|
||||
|
||||
void SoftCPU::dump() const
|
||||
{
|
||||
printf("eax=%08x ebx=%08x ecx=%08x edx=%08x ", m_eax, m_ebx, m_ecx, m_edx);
|
||||
printf("ebp=%08x esp=%08x esi=%08x edi=%08x ", m_ebp, m_esp, m_esi, m_edi);
|
||||
printf("o=%u s=%u z=%u a=%u p=%u c=%u\n", m_of, m_sf, m_zf, m_af, m_pf, m_cf);
|
||||
printf("eax=%08x ebx=%08x ecx=%08x edx=%08x ", eax(), ebx(), ecx(), edx());
|
||||
printf("ebp=%08x esp=%08x esi=%08x edi=%08x ", ebp(), esp(), esi(), edi());
|
||||
printf("o=%u s=%u z=%u a=%u p=%u c=%u\n", of(), sf(), zf(), af(), pf(), cf());
|
||||
}
|
||||
|
||||
u32 SoftCPU::read_memory32(X86::LogicalAddress address)
|
||||
|
@ -68,14 +60,14 @@ void SoftCPU::write_memory32(X86::LogicalAddress address, u32 value)
|
|||
|
||||
void SoftCPU::push32(u32 value)
|
||||
{
|
||||
m_esp -= sizeof(value);
|
||||
write_memory32({ get_ss(), get_esp() }, value);
|
||||
set_esp(esp() - sizeof(value));
|
||||
write_memory32({ ss(), esp() }, value);
|
||||
}
|
||||
|
||||
u32 SoftCPU::pop32()
|
||||
{
|
||||
auto value = read_memory32({ get_ss(), get_esp() });
|
||||
m_esp += sizeof(value);
|
||||
auto value = read_memory32({ ss(), esp() });
|
||||
set_esp(esp() + sizeof(value));
|
||||
return value;
|
||||
}
|
||||
|
||||
|
@ -228,7 +220,7 @@ void SoftCPU::INTO(const X86::Instruction&) { TODO(); }
|
|||
void SoftCPU::INT_imm8(const X86::Instruction& insn)
|
||||
{
|
||||
ASSERT(insn.imm8() == 0x82);
|
||||
m_eax = m_emulator.virt_syscall(m_eax, m_edx, m_ecx, m_ebx);
|
||||
set_eax(m_emulator.virt_syscall(eax(), edx(), ecx(), ebx()));
|
||||
}
|
||||
|
||||
void SoftCPU::INVLPG(const X86::Instruction&) { TODO(); }
|
||||
|
@ -303,7 +295,7 @@ void SoftCPU::MOV_RM32_imm32(const X86::Instruction&) { TODO(); }
|
|||
void SoftCPU::MOV_RM32_reg32(const X86::Instruction& insn)
|
||||
{
|
||||
ASSERT(insn.modrm().is_register());
|
||||
*m_reg32_table[insn.modrm().register_index()] = *m_reg32_table[insn.register_index()];
|
||||
gpr32(insn.modrm().reg32()) = gpr32(insn.reg32());
|
||||
}
|
||||
|
||||
void SoftCPU::MOV_RM8_imm8(const X86::Instruction&) { TODO(); }
|
||||
|
@ -319,7 +311,7 @@ void SoftCPU::MOV_reg32_RM32(const X86::Instruction&) { TODO(); }
|
|||
|
||||
void SoftCPU::MOV_reg32_imm32(const X86::Instruction& insn)
|
||||
{
|
||||
*m_reg32_table[insn.register_index()] = insn.imm32();
|
||||
gpr32(insn.reg32()) = insn.imm32();
|
||||
}
|
||||
|
||||
void SoftCPU::MOV_reg8_RM8(const X86::Instruction&) { TODO(); }
|
||||
|
@ -377,7 +369,7 @@ void SoftCPU::POP_reg16(const X86::Instruction&) { TODO(); }
|
|||
|
||||
void SoftCPU::POP_reg32(const X86::Instruction& insn)
|
||||
{
|
||||
*m_reg32_table[insn.register_index()] = pop32();
|
||||
gpr32(insn.reg32()) = pop32();
|
||||
}
|
||||
|
||||
void SoftCPU::PUSHA(const X86::Instruction&) { TODO(); }
|
||||
|
@ -400,7 +392,7 @@ void SoftCPU::PUSH_reg16(const X86::Instruction&) { TODO(); }
|
|||
|
||||
void SoftCPU::PUSH_reg32(const X86::Instruction& insn)
|
||||
{
|
||||
push32(*m_reg32_table[insn.register_index()]);
|
||||
push32(gpr32(insn.reg32()));
|
||||
}
|
||||
|
||||
void SoftCPU::RCL_RM16_1(const X86::Instruction&) { TODO(); }
|
||||
|
@ -561,8 +553,8 @@ void SoftCPU::XOR_RM32_imm8(const X86::Instruction&) { TODO(); }
|
|||
void SoftCPU::XOR_RM32_reg32(const X86::Instruction& insn)
|
||||
{
|
||||
ASSERT(insn.modrm().is_register());
|
||||
auto& dest = *m_reg32_table[insn.modrm().register_index()];
|
||||
auto src = *m_reg32_table[insn.register_index()];
|
||||
auto& dest = gpr32(insn.modrm().reg32());
|
||||
auto src = gpr32(insn.reg32());
|
||||
dest ^= src;
|
||||
|
||||
set_cf(false);
|
||||
|
|
|
@ -33,6 +33,21 @@ namespace UserspaceEmulator {
|
|||
|
||||
class Emulator;
|
||||
|
||||
union PartAddressableRegister {
|
||||
struct {
|
||||
u32 full_u32 { 0 };
|
||||
};
|
||||
struct {
|
||||
u16 low_u16;
|
||||
u16 high_u16;
|
||||
};
|
||||
struct {
|
||||
u8 low_u8;
|
||||
u8 high_u8;
|
||||
u16 also_high_u16;
|
||||
};
|
||||
};
|
||||
|
||||
class SoftCPU final : public X86::Interpreter {
|
||||
public:
|
||||
explicit SoftCPU(Emulator&);
|
||||
|
@ -41,13 +56,45 @@ public:
|
|||
void push32(u32);
|
||||
u32 pop32();
|
||||
|
||||
u32 get_esp() const { return m_esp; }
|
||||
void set_esp(u32 value) { m_esp = value; }
|
||||
u32 gpr32(X86::RegisterIndex32 reg) const { return m_gpr[reg].full_u32; }
|
||||
u32& gpr32(X86::RegisterIndex32 reg) { return m_gpr[reg].full_u32; }
|
||||
|
||||
u16 get_cs() const { return 0x18; }
|
||||
u16 get_ds() const { return 0x20; }
|
||||
u16 get_es() const { return 0x20; }
|
||||
u16 get_ss() const { return 0x20; }
|
||||
u32 eax() const { return gpr32(X86::RegisterEAX); }
|
||||
u32 ebx() const { return gpr32(X86::RegisterEBX); }
|
||||
u32 ecx() const { return gpr32(X86::RegisterECX); }
|
||||
u32 edx() const { return gpr32(X86::RegisterEDX); }
|
||||
u32 esp() const { return gpr32(X86::RegisterESP); }
|
||||
u32 ebp() const { return gpr32(X86::RegisterEBP); }
|
||||
u32 esi() const { return gpr32(X86::RegisterESI); }
|
||||
u32 edi() const { return gpr32(X86::RegisterEDI); }
|
||||
|
||||
void set_eax(u32 value) { gpr32(X86::RegisterEAX) = value; }
|
||||
void set_ebx(u32 value) { gpr32(X86::RegisterEBX) = value; }
|
||||
void set_ecx(u32 value) { gpr32(X86::RegisterECX) = value; }
|
||||
void set_edx(u32 value) { gpr32(X86::RegisterEDX) = value; }
|
||||
void set_ebp(u32 value) { gpr32(X86::RegisterEBP) = value; }
|
||||
void set_esp(u32 value) { gpr32(X86::RegisterESP) = value; }
|
||||
void set_esi(u32 value) { gpr32(X86::RegisterESI) = value; }
|
||||
void set_edi(u32 value) { gpr32(X86::RegisterEDI) = value; }
|
||||
|
||||
bool of() const { return m_of; }
|
||||
bool sf() const { return m_sf; }
|
||||
bool zf() const { return m_zf; }
|
||||
bool af() const { return m_af; }
|
||||
bool pf() const { return m_pf; }
|
||||
bool cf() const { return m_cf; }
|
||||
|
||||
void set_of(bool value) { m_of = value; }
|
||||
void set_sf(bool value) { m_sf = value; }
|
||||
void set_zf(bool value) { m_zf = value; }
|
||||
void set_af(bool value) { m_af = value; }
|
||||
void set_pf(bool value) { m_pf = value; }
|
||||
void set_cf(bool value) { m_cf = value; }
|
||||
|
||||
u16 cs() const { return 0x18; }
|
||||
u16 ds() const { return 0x20; }
|
||||
u16 es() const { return 0x20; }
|
||||
u16 ss() const { return 0x20; }
|
||||
|
||||
u32 read_memory32(X86::LogicalAddress);
|
||||
void write_memory32(X86::LogicalAddress, u32);
|
||||
|
@ -526,30 +573,7 @@ private:
|
|||
private:
|
||||
Emulator& m_emulator;
|
||||
|
||||
bool get_of() const { return m_of; }
|
||||
bool get_sf() const { return m_sf; }
|
||||
bool get_zf() const { return m_zf; }
|
||||
bool get_af() const { return m_af; }
|
||||
bool get_pf() const { return m_pf; }
|
||||
bool get_cf() const { return m_cf; }
|
||||
|
||||
void set_of(bool value) { m_of = value; }
|
||||
void set_sf(bool value) { m_sf = value; }
|
||||
void set_zf(bool value) { m_zf = value; }
|
||||
void set_af(bool value) { m_af = value; }
|
||||
void set_pf(bool value) { m_pf = value; }
|
||||
void set_cf(bool value) { m_cf = value; }
|
||||
|
||||
u32* m_reg32_table[8];
|
||||
|
||||
u32 m_eax { 0 };
|
||||
u32 m_ebx { 0 };
|
||||
u32 m_ecx { 0 };
|
||||
u32 m_edx { 0 };
|
||||
u32 m_esp { 0 };
|
||||
u32 m_ebp { 0 };
|
||||
u32 m_esi { 0 };
|
||||
u32 m_edi { 0 };
|
||||
PartAddressableRegister m_gpr[8];
|
||||
|
||||
bool m_of { false };
|
||||
bool m_sf { false };
|
||||
|
|
|
@ -124,7 +124,7 @@ enum MMXRegisterIndex {
|
|||
|
||||
class LogicalAddress {
|
||||
public:
|
||||
LogicalAddress() {}
|
||||
LogicalAddress() { }
|
||||
LogicalAddress(u16 selector, u32 offset)
|
||||
: m_selector(selector)
|
||||
, m_offset(offset)
|
||||
|
@ -200,6 +200,10 @@ public:
|
|||
bool is_register() const { return m_register_index != 0xffffffff; }
|
||||
|
||||
unsigned register_index() const { return m_register_index; }
|
||||
RegisterIndex32 reg32() const { return static_cast<RegisterIndex32>(register_index()); }
|
||||
RegisterIndex16 reg16() const { return static_cast<RegisterIndex16>(register_index()); }
|
||||
RegisterIndex8 reg8() const { return static_cast<RegisterIndex8>(register_index()); }
|
||||
|
||||
SegmentRegister segment() const
|
||||
{
|
||||
ASSERT(!is_register());
|
||||
|
@ -208,7 +212,7 @@ public:
|
|||
u32 offset();
|
||||
|
||||
private:
|
||||
MemoryOrRegisterReference() {}
|
||||
MemoryOrRegisterReference() { }
|
||||
|
||||
String to_string() const;
|
||||
String to_string_a16() const;
|
||||
|
@ -245,7 +249,7 @@ typedef void (Interpreter::*InstructionHandler)(const Instruction&);
|
|||
class Instruction {
|
||||
public:
|
||||
static Instruction from_stream(InstructionStream&, bool o32, bool a32);
|
||||
~Instruction() {}
|
||||
~Instruction() { }
|
||||
|
||||
MemoryOrRegisterReference& modrm() const
|
||||
{
|
||||
|
@ -321,6 +325,10 @@ public:
|
|||
bool has_sub_op() const { return m_has_sub_op; }
|
||||
|
||||
unsigned register_index() const { return m_register_index; }
|
||||
RegisterIndex32 reg32() const { return static_cast<RegisterIndex32>(register_index()); }
|
||||
RegisterIndex16 reg16() const { return static_cast<RegisterIndex16>(register_index()); }
|
||||
RegisterIndex8 reg8() const { return static_cast<RegisterIndex8>(register_index()); }
|
||||
|
||||
SegmentRegister segment_register() const { return static_cast<SegmentRegister>(register_index()); }
|
||||
|
||||
u8 cc() const { return m_has_sub_op ? m_sub_op & 0xf : m_op & 0xf; }
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue