Refactor: Seperate executor cases to categories.
This commit is contained in:
41
src/Arithmetic.cpp
Normal file
41
src/Arithmetic.cpp
Normal 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
15
src/Arithmetic.h
Normal 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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -15,6 +15,8 @@ public:
|
||||
public:
|
||||
void Step();
|
||||
|
||||
bool IsHalted() { return m_IsHalted; }
|
||||
|
||||
private:
|
||||
void FetchDecode();
|
||||
void Execute();
|
||||
|
||||
12
src/ControlFlow.cpp
Normal file
12
src/ControlFlow.cpp
Normal 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
7
src/ControlFlow.h
Normal file
@@ -0,0 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
struct CPUContext;
|
||||
|
||||
namespace executor_cases {
|
||||
void Hlt(CPUContext& cc);
|
||||
}
|
||||
10
src/DataTransfer.cpp
Normal file
10
src/DataTransfer.cpp
Normal 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
7
src/DataTransfer.h
Normal file
@@ -0,0 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
struct CPUContext;
|
||||
|
||||
namespace executor_cases {
|
||||
void Mov_r32_imm32(CPUContext& cc);
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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";
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
};
|
||||
|
||||
|
||||
@@ -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
11
src/Misc.cpp
Normal 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
7
src/Misc.h
Normal file
@@ -0,0 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
struct CPUContext;
|
||||
|
||||
namespace executor_cases {
|
||||
void Nop(CPUContext& cc);
|
||||
}
|
||||
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user