Refactor: Seperate executor cases to categories.

This commit is contained in:
0x221E
2026-02-05 00:42:25 +01:00
parent fe1370359e
commit ac6bf8cb46
15 changed files with 127 additions and 69 deletions

41
src/Arithmetic.cpp Normal file
View File

@@ -0,0 +1,41 @@
#include "Arithmetic.h"
#include "ExecutorCases.h"
#include "Instruction.h"
#include "Bus.h"
#include <stdexcept>
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<uint32_t>(address);
uint32_t currRegValue = cc.m_Registers[cc.m_Instruction.optional.m_ModRM.m_Reg];
uint32_t result = dstPrevValue + currRegValue;
cc.m_Bus->WriteX<uint32_t>(address, result);
}
}
}

15
src/Arithmetic.h Normal file
View File

@@ -0,0 +1,15 @@
#pragma once
#include <cstdint>
struct CPUContext;
namespace executor_cases {
void Add_rm32_r32(CPUContext& cc);
namespace helpers {
void Add_rm_dst(CPUContext& cc, uint32_t address);
}
}

View File

@@ -26,8 +26,8 @@ void CPU::FetchDecode() {
Opcode opcode = static_cast<Opcode>(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<uint32_t>(m_InstructionPointer + 1);
m_Instruction.m_Length = 5;

View File

@@ -15,6 +15,8 @@ public:
public:
void Step();
bool IsHalted() { return m_IsHalted; }
private:
void FetchDecode();
void Execute();

12
src/ControlFlow.cpp Normal file
View File

@@ -0,0 +1,12 @@
#include "ControlFlow.h"
#include "ExecutorCases.h"
#include <iostream>
namespace executor_cases {
void Hlt(CPUContext& cc){
std::cout << "Program halted!" << std::endl;
cc.m_IsHalted = true;
}
}

7
src/ControlFlow.h Normal file
View File

@@ -0,0 +1,7 @@
#pragma once
struct CPUContext;
namespace executor_cases {
void Hlt(CPUContext& cc);
}

10
src/DataTransfer.cpp Normal file
View File

@@ -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;
}
}

7
src/DataTransfer.h Normal file
View File

@@ -0,0 +1,7 @@
#pragma once
struct CPUContext;
namespace executor_cases {
void Mov_r32_imm32(CPUContext& cc);
}

View File

@@ -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<uint32_t>(cc.m_Registers[modrm.m_Rm]);
uint32_t currRegValue = cc.m_Registers[modrm.m_Reg];
uint32_t result = dstPrevValue + currRegValue;
cc.m_Bus->WriteX<uint32_t>(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<uint32_t>(dstAddress);
uint32_t currRegValue = cc.m_Registers[modrm.m_Reg];
uint32_t result = dstPrevValue + currRegValue;
cc.m_Bus->WriteX<uint32_t>(dstAddress, result);
break;
}
case x86::ModRMState::DISP32:
{
uint32_t dstAddress = cc.m_Instruction.m_Operand1;
uint32_t dstPrevValue = cc.m_Bus->AccessX<uint32_t>(dstAddress);
uint32_t currRegValue = cc.m_Registers[modrm.m_Reg];
uint32_t result = dstPrevValue + currRegValue;
cc.m_Bus->WriteX<uint32_t>(dstAddress, result);
break;
}
default:
{
throw std::runtime_error("Invalid ModRM State encountered during Add_rm32_r32");
}
}
}
}
constexpr std::array<ExecutorCase, 255> GenerateExecutorTable(){
std::array<ExecutorCase, 255> 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;
}

View File

@@ -54,7 +54,7 @@ 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::MOV_R32_IMM32: return "MOV_R32_IMM32";
case Opcode::NOP: return "NOP";
case Opcode::HLT: return "HLT";
}

View File

@@ -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,
};

View File

@@ -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();
}
}

11
src/Misc.cpp Normal file
View File

@@ -0,0 +1,11 @@
#include "Misc.h"
#include "ExecutorCases.h"
#include <iostream>
namespace executor_cases {
void Nop(CPUContext& cc){
std::cout << "No op" << std::endl;
}
}

7
src/Misc.h Normal file
View File

@@ -0,0 +1,7 @@
#pragma once
struct CPUContext;
namespace executor_cases {
void Nop(CPUContext& cc);
}

View File

@@ -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,