diff --git a/src/Arithmetic.cpp b/src/Arithmetic.cpp new file mode 100644 index 0000000..d4b6648 --- /dev/null +++ b/src/Arithmetic.cpp @@ -0,0 +1,41 @@ +#include "Arithmetic.h" + +#include "ExecutorCases.h" +#include "Instruction.h" +#include "Bus.h" + +#include + +namespace executor_cases { + + void Add_rm32_r32(CPUContext& cc){ + x86::ModRM modrm = cc.m_Instruction.optional.m_ModRM; + + switch(modrm.m_State) { + case x86::ModRMState::R: + cc.m_Registers[modrm.m_Rm] += cc.m_Registers[modrm.m_Reg]; + break; + case x86::ModRMState::LR: + helpers::Add_rm_dst(cc, cc.m_Registers[modrm.m_Rm]); + break; + case x86::ModRMState::LR_DISP8: + case x86::ModRMState::LR_DISP32: + helpers::Add_rm_dst(cc, (uint32_t)(cc.m_Registers[modrm.m_Rm] + cc.m_Instruction.m_Operand1)); + break; + case x86::ModRMState::DISP32: + helpers::Add_rm_dst(cc, cc.m_Instruction.m_Operand1); + break; + default: + throw std::runtime_error("Invalid ModRM State encountered during Add_rm32_r32"); + } + } + + namespace helpers { + void Add_rm_dst(CPUContext& cc, uint32_t address) { + uint32_t dstPrevValue = cc.m_Bus->AccessX(address); + uint32_t currRegValue = cc.m_Registers[cc.m_Instruction.optional.m_ModRM.m_Reg]; + uint32_t result = dstPrevValue + currRegValue; + cc.m_Bus->WriteX(address, result); + } + } +} diff --git a/src/Arithmetic.h b/src/Arithmetic.h new file mode 100644 index 0000000..81a6489 --- /dev/null +++ b/src/Arithmetic.h @@ -0,0 +1,15 @@ +#pragma once + +#include + +struct CPUContext; + +namespace executor_cases { + void Add_rm32_r32(CPUContext& cc); + + namespace helpers { + void Add_rm_dst(CPUContext& cc, uint32_t address); + } +} + + diff --git a/src/CPU.cpp b/src/CPU.cpp index b7e973c..0a39267 100644 --- a/src/CPU.cpp +++ b/src/CPU.cpp @@ -26,8 +26,8 @@ void CPU::FetchDecode() { Opcode opcode = static_cast(opcode_raw); switch(opcode_raw) { - case Opcode::MOV_R_IMM32 ... 0xBF: // 0xB8 to 0xBF - m_Instruction.m_Opcode = Opcode::MOV_R_IMM32; + case Opcode::MOV_R32_IMM32 ... 0xBF: // 0xB8 to 0xBF + m_Instruction.m_Opcode = Opcode::MOV_R32_IMM32; m_Instruction.m_Operand1 = opcode_raw - 0xB8; m_Instruction.m_Operand2 = m_Bus->AccessX(m_InstructionPointer + 1); m_Instruction.m_Length = 5; diff --git a/src/CPU.h b/src/CPU.h index 7a0db13..61fe5a2 100644 --- a/src/CPU.h +++ b/src/CPU.h @@ -14,6 +14,8 @@ public: public: void Step(); + + bool IsHalted() { return m_IsHalted; } private: void FetchDecode(); diff --git a/src/ControlFlow.cpp b/src/ControlFlow.cpp new file mode 100644 index 0000000..dbbb0d0 --- /dev/null +++ b/src/ControlFlow.cpp @@ -0,0 +1,12 @@ +#include "ControlFlow.h" + +#include "ExecutorCases.h" + +#include + +namespace executor_cases { + void Hlt(CPUContext& cc){ + std::cout << "Program halted!" << std::endl; + cc.m_IsHalted = true; + } +} diff --git a/src/ControlFlow.h b/src/ControlFlow.h new file mode 100644 index 0000000..0f8aa87 --- /dev/null +++ b/src/ControlFlow.h @@ -0,0 +1,7 @@ +#pragma once + +struct CPUContext; + +namespace executor_cases { + void Hlt(CPUContext& cc); +} diff --git a/src/DataTransfer.cpp b/src/DataTransfer.cpp new file mode 100644 index 0000000..0799c14 --- /dev/null +++ b/src/DataTransfer.cpp @@ -0,0 +1,10 @@ +#include "DataTransfer.h" + +#include "ExecutorCases.h" +#include "Instruction.h" + +namespace executor_cases { + void Mov_r32_imm32(CPUContext& cc) { + cc.m_Registers[cc.m_Instruction.m_Operand1] = cc.m_Instruction.m_Operand2; + } +} diff --git a/src/DataTransfer.h b/src/DataTransfer.h new file mode 100644 index 0000000..00ee5a1 --- /dev/null +++ b/src/DataTransfer.h @@ -0,0 +1,7 @@ +#pragma once + +struct CPUContext; + +namespace executor_cases { + void Mov_r32_imm32(CPUContext& cc); +} diff --git a/src/ExecutorCases.cpp b/src/ExecutorCases.cpp index 1e06b54..74c4bc6 100644 --- a/src/ExecutorCases.cpp +++ b/src/ExecutorCases.cpp @@ -1,5 +1,10 @@ #include "ExecutorCases.h" +#include "DataTransfer.h" +#include "ControlFlow.h" +#include "Arithmetic.h" +#include "Misc.h" + #include "Instruction.h" #include "Bus.h" @@ -10,70 +15,11 @@ CPUContext::CPUContext(Instruction& i, uint32_t& ip, uint32_t& flags, uint32_t* CPUContext::~CPUContext() = default; -// NO SIB SUPPORT YET -namespace executor_cases { - void Nop(CPUContext& cc){ - std::cout << "No op" << std::endl; - } - - void Hlt(CPUContext& cc){ - std::cout << "Program halted!" << std::endl; - exit(0); - } - - void Mov_r32_imm32(CPUContext& cc){ - cc.m_Registers[cc.m_Instruction.m_Operand1] = cc.m_Instruction.m_Operand2; - } - - void Add_rm32_r32(CPUContext& cc){ - x86::ModRM modrm = cc.m_Instruction.optional.m_ModRM; - - switch(modrm.m_State) { - case x86::ModRMState::R: - { - cc.m_Registers[modrm.m_Rm] += cc.m_Registers[modrm.m_Reg]; - break; - } - case x86::ModRMState::LR: - { - uint32_t dstPrevValue = cc.m_Bus->AccessX(cc.m_Registers[modrm.m_Rm]); - uint32_t currRegValue = cc.m_Registers[modrm.m_Reg]; - uint32_t result = dstPrevValue + currRegValue; - cc.m_Bus->WriteX(cc.m_Registers[modrm.m_Rm], result); - break; - } - case x86::ModRMState::LR_DISP8: - case x86::ModRMState::LR_DISP32: - { - uint32_t dstAddress = cc.m_Registers[modrm.m_Rm] + cc.m_Instruction.m_Operand1; - uint32_t dstPrevValue = cc.m_Bus->AccessX(dstAddress); - uint32_t currRegValue = cc.m_Registers[modrm.m_Reg]; - uint32_t result = dstPrevValue + currRegValue; - cc.m_Bus->WriteX(dstAddress, result); - break; - } - case x86::ModRMState::DISP32: - { - uint32_t dstAddress = cc.m_Instruction.m_Operand1; - uint32_t dstPrevValue = cc.m_Bus->AccessX(dstAddress); - uint32_t currRegValue = cc.m_Registers[modrm.m_Reg]; - uint32_t result = dstPrevValue + currRegValue; - cc.m_Bus->WriteX(dstAddress, result); - break; - } - default: - { - throw std::runtime_error("Invalid ModRM State encountered during Add_rm32_r32"); - } - } - } -} - constexpr std::array GenerateExecutorTable(){ std::array table{}; table[Opcode::NOP] = executor_cases::Nop; table[Opcode::HLT] = executor_cases::Hlt; - table[Opcode::MOV_R_IMM32] = executor_cases::Mov_r32_imm32; + table[Opcode::MOV_R32_IMM32] = executor_cases::Mov_r32_imm32; table[Opcode::ADD_RM32_R32] = executor_cases::Add_rm32_r32; return table; } diff --git a/src/Instruction.cpp b/src/Instruction.cpp index ff7a7e7..0c1b2d5 100644 --- a/src/Instruction.cpp +++ b/src/Instruction.cpp @@ -53,10 +53,10 @@ namespace x86 { std::string Opcode2Str(Opcode op) { switch(op) { - case Opcode::ADD_RM32_R32: return "ADD_RM32_R32"; - case Opcode::MOV_R_IMM32: return "MOV_R_IMM32"; - case Opcode::NOP: return "NOP"; - case Opcode::HLT: return "HLT"; + case Opcode::ADD_RM32_R32: return "ADD_RM32_R32"; + case Opcode::MOV_R32_IMM32: return "MOV_R32_IMM32"; + case Opcode::NOP: return "NOP"; + case Opcode::HLT: return "HLT"; } throw std::runtime_error("Opcode Invalid!"); } diff --git a/src/Instruction.h b/src/Instruction.h index 27fd774..b190821 100644 --- a/src/Instruction.h +++ b/src/Instruction.h @@ -36,7 +36,7 @@ namespace x86 { enum Opcode : uint8_t { NOP = 0x90, HLT = 0xF4, - MOV_R_IMM32 = 0xB8, + MOV_R32_IMM32 = 0xB8, ADD_RM32_R32 = 0x01, }; diff --git a/src/Metal.cpp b/src/Metal.cpp index 6b606ef..a0f11ad 100644 --- a/src/Metal.cpp +++ b/src/Metal.cpp @@ -14,7 +14,7 @@ void Metal::Upload2Memory(uint8_t bytes[], size_t len) { void Metal::Run() { m_Running = true; - while(m_Running) { + while(m_Running && !m_CPU.IsHalted()) { m_CPU.Step(); } } diff --git a/src/Misc.cpp b/src/Misc.cpp new file mode 100644 index 0000000..b89d906 --- /dev/null +++ b/src/Misc.cpp @@ -0,0 +1,11 @@ +#include "Misc.h" + +#include "ExecutorCases.h" + +#include + +namespace executor_cases { + void Nop(CPUContext& cc){ + std::cout << "No op" << std::endl; + } +} diff --git a/src/Misc.h b/src/Misc.h new file mode 100644 index 0000000..8f52706 --- /dev/null +++ b/src/Misc.h @@ -0,0 +1,7 @@ +#pragma once + +struct CPUContext; + +namespace executor_cases { + void Nop(CPUContext& cc); +} diff --git a/src/main.cpp b/src/main.cpp index 5d52a7a..3b85100 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -4,7 +4,7 @@ // mov eax, 0xF4 // mov ecx, 0x8000 -// add [ecx + 0x0010], eax +// add [0x8010], eax uint8_t test[] = { 0xB8, 0xF4, 0x00, 0x00, 0x00, 0xB9, 0x00, 0x80, 0x00, 0x00,