Browse Source

UserspaceEmulator: Add an initial stack and implement PUSH/POP reg32

Programs now start out with a 64 KB stack at 0x10000000. :^)
Andreas Kling 5 years ago
parent
commit
d10765bec3

+ 43 - 3
DevTools/UserspaceEmulator/Emulator.cpp

@@ -28,14 +28,54 @@
 #include "SoftCPU.h"
 #include "SoftCPU.h"
 #include <AK/LogStream.h>
 #include <AK/LogStream.h>
 #include <Kernel/API/Syscall.h>
 #include <Kernel/API/Syscall.h>
-#include <unistd.h>
 #include <stdio.h>
 #include <stdio.h>
+#include <unistd.h>
 
 
 namespace UserspaceEmulator {
 namespace UserspaceEmulator {
 
 
+static constexpr u32 stack_location = 0x10000000;
+static constexpr size_t stack_size = 64 * KB;
+
+class SimpleRegion final : public SoftMMU::Region {
+public:
+    SimpleRegion(u32 base, u32 size)
+        : Region(base, size)
+    {
+        m_data = (u8*)malloc(size);
+    }
+
+    ~SimpleRegion()
+    {
+        free(m_data);
+    }
+
+    virtual u32 read32(u32 offset) override
+    {
+        ASSERT(offset + 3 < size());
+        return *reinterpret_cast<const u32*>(m_data + offset);
+    }
+
+    virtual void write32(u32 offset, u32 value) override
+    {
+        ASSERT(offset + 3 < size());
+        *reinterpret_cast<u32*>(m_data + offset) = value;
+    }
+
+private:
+    u8* m_data { nullptr };
+};
+
 Emulator::Emulator()
 Emulator::Emulator()
     : m_cpu(*this)
     : m_cpu(*this)
 {
 {
+    setup_stack();
+}
+
+void Emulator::setup_stack()
+{
+    auto stack_region = make<SimpleRegion>(stack_location, stack_size);
+    m_mmu.add_region(move(stack_region));
+    m_cpu.set_esp(stack_location + stack_size);
 }
 }
 
 
 int Emulator::exec(X86::SimpleInstructionStream& stream, u32 base)
 int Emulator::exec(X86::SimpleInstructionStream& stream, u32 base)
@@ -59,8 +99,8 @@ int Emulator::exec(X86::SimpleInstructionStream& stream, u32 base)
 
 
 u32 Emulator::virt_syscall(u32 function, u32 arg1, u32 arg2, u32 arg3)
 u32 Emulator::virt_syscall(u32 function, u32 arg1, u32 arg2, u32 arg3)
 {
 {
-    (void) arg2;
-    (void) arg3;
+    (void)arg2;
+    (void)arg3;
 
 
     printf("Syscall: %s (%x)\n", Syscall::to_string((Syscall::Function)function), function);
     printf("Syscall: %s (%x)\n", Syscall::to_string((Syscall::Function)function), function);
     switch (function) {
     switch (function) {

+ 40 - 2
DevTools/UserspaceEmulator/SoftCPU.cpp

@@ -51,6 +51,34 @@ void SoftCPU::dump() const
     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("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);
 }
 }
 
 
+u32 SoftCPU::read_memory32(X86::LogicalAddress address)
+{
+    ASSERT(address.selector() == 0x20);
+    auto value = m_emulator.mmu().read32(address.offset());
+    printf("\033[36;1mread_memory32: @%08x -> %08x\033[0m\n", address.offset(), value);
+    return value;
+}
+
+void SoftCPU::write_memory32(X86::LogicalAddress address, u32 value)
+{
+    ASSERT(address.selector() == 0x20);
+    printf("\033[35;1mwrite_memory32: @%08x <- %08x\033[0m\n", address.offset(), value);
+    m_emulator.mmu().write32(address.offset(), value);
+}
+
+void SoftCPU::push32(u32 value)
+{
+    m_esp -= sizeof(value);
+    write_memory32({ get_ss(), get_esp() }, value);
+}
+
+u32 SoftCPU::pop32()
+{
+    auto value = read_memory32({ get_ss(), get_esp() });
+    m_esp += sizeof(value);
+    return value;
+}
+
 void SoftCPU::AAA(const X86::Instruction&) { TODO(); }
 void SoftCPU::AAA(const X86::Instruction&) { TODO(); }
 void SoftCPU::AAD(const X86::Instruction&) { TODO(); }
 void SoftCPU::AAD(const X86::Instruction&) { TODO(); }
 void SoftCPU::AAM(const X86::Instruction&) { TODO(); }
 void SoftCPU::AAM(const X86::Instruction&) { TODO(); }
@@ -346,7 +374,12 @@ void SoftCPU::POP_RM16(const X86::Instruction&) { TODO(); }
 void SoftCPU::POP_RM32(const X86::Instruction&) { TODO(); }
 void SoftCPU::POP_RM32(const X86::Instruction&) { TODO(); }
 void SoftCPU::POP_SS(const X86::Instruction&) { TODO(); }
 void SoftCPU::POP_SS(const X86::Instruction&) { TODO(); }
 void SoftCPU::POP_reg16(const X86::Instruction&) { TODO(); }
 void SoftCPU::POP_reg16(const X86::Instruction&) { TODO(); }
-void SoftCPU::POP_reg32(const X86::Instruction&) { TODO(); }
+
+void SoftCPU::POP_reg32(const X86::Instruction& insn)
+{
+    *m_reg32_table[insn.register_index()] = pop32();
+}
+
 void SoftCPU::PUSHA(const X86::Instruction&) { TODO(); }
 void SoftCPU::PUSHA(const X86::Instruction&) { TODO(); }
 void SoftCPU::PUSHAD(const X86::Instruction&) { TODO(); }
 void SoftCPU::PUSHAD(const X86::Instruction&) { TODO(); }
 void SoftCPU::PUSHF(const X86::Instruction&) { TODO(); }
 void SoftCPU::PUSHF(const X86::Instruction&) { TODO(); }
@@ -364,7 +397,12 @@ void SoftCPU::PUSH_imm16(const X86::Instruction&) { TODO(); }
 void SoftCPU::PUSH_imm32(const X86::Instruction&) { TODO(); }
 void SoftCPU::PUSH_imm32(const X86::Instruction&) { TODO(); }
 void SoftCPU::PUSH_imm8(const X86::Instruction&) { TODO(); }
 void SoftCPU::PUSH_imm8(const X86::Instruction&) { TODO(); }
 void SoftCPU::PUSH_reg16(const X86::Instruction&) { TODO(); }
 void SoftCPU::PUSH_reg16(const X86::Instruction&) { TODO(); }
-void SoftCPU::PUSH_reg32(const X86::Instruction&) { TODO(); }
+
+void SoftCPU::PUSH_reg32(const X86::Instruction& insn)
+{
+    push32(*m_reg32_table[insn.register_index()]);
+}
+
 void SoftCPU::RCL_RM16_1(const X86::Instruction&) { TODO(); }
 void SoftCPU::RCL_RM16_1(const X86::Instruction&) { TODO(); }
 void SoftCPU::RCL_RM16_CL(const X86::Instruction&) { TODO(); }
 void SoftCPU::RCL_RM16_CL(const X86::Instruction&) { TODO(); }
 void SoftCPU::RCL_RM16_imm8(const X86::Instruction&) { TODO(); }
 void SoftCPU::RCL_RM16_imm8(const X86::Instruction&) { TODO(); }

+ 16 - 0
DevTools/UserspaceEmulator/SoftCPU.h

@@ -26,6 +26,7 @@
 
 
 #pragma once
 #pragma once
 
 
+#include <LibX86/Instruction.h>
 #include <LibX86/Interpreter.h>
 #include <LibX86/Interpreter.h>
 
 
 namespace UserspaceEmulator {
 namespace UserspaceEmulator {
@@ -37,6 +38,21 @@ public:
     explicit SoftCPU(Emulator&);
     explicit SoftCPU(Emulator&);
     void dump() const;
     void dump() const;
 
 
+    void push32(u32);
+    u32 pop32();
+
+    u32 get_esp() const { return m_esp; }
+    void set_esp(u32 value) { m_esp = value; }
+
+    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 read_memory32(X86::LogicalAddress);
+    void write_memory32(X86::LogicalAddress, u32);
+
+private:
     virtual void AAA(const X86::Instruction&) override;
     virtual void AAA(const X86::Instruction&) override;
     virtual void AAD(const X86::Instruction&) override;
     virtual void AAD(const X86::Instruction&) override;
     virtual void AAM(const X86::Instruction&) override;
     virtual void AAM(const X86::Instruction&) override;