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);
|
Opcode opcode = static_cast<Opcode>(opcode_raw);
|
||||||
|
|
||||||
switch(opcode_raw) {
|
switch(opcode_raw) {
|
||||||
case Opcode::MOV_R_IMM32 ... 0xBF: // 0xB8 to 0xBF
|
case Opcode::MOV_R32_IMM32 ... 0xBF: // 0xB8 to 0xBF
|
||||||
m_Instruction.m_Opcode = Opcode::MOV_R_IMM32;
|
m_Instruction.m_Opcode = Opcode::MOV_R32_IMM32;
|
||||||
m_Instruction.m_Operand1 = opcode_raw - 0xB8;
|
m_Instruction.m_Operand1 = opcode_raw - 0xB8;
|
||||||
m_Instruction.m_Operand2 = m_Bus->AccessX<uint32_t>(m_InstructionPointer + 1);
|
m_Instruction.m_Operand2 = m_Bus->AccessX<uint32_t>(m_InstructionPointer + 1);
|
||||||
m_Instruction.m_Length = 5;
|
m_Instruction.m_Length = 5;
|
||||||
|
|||||||
@@ -15,6 +15,8 @@ public:
|
|||||||
public:
|
public:
|
||||||
void Step();
|
void Step();
|
||||||
|
|
||||||
|
bool IsHalted() { return m_IsHalted; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void FetchDecode();
|
void FetchDecode();
|
||||||
void Execute();
|
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 "ExecutorCases.h"
|
||||||
|
|
||||||
|
#include "DataTransfer.h"
|
||||||
|
#include "ControlFlow.h"
|
||||||
|
#include "Arithmetic.h"
|
||||||
|
#include "Misc.h"
|
||||||
|
|
||||||
#include "Instruction.h"
|
#include "Instruction.h"
|
||||||
#include "Bus.h"
|
#include "Bus.h"
|
||||||
|
|
||||||
@@ -10,70 +15,11 @@ CPUContext::CPUContext(Instruction& i, uint32_t& ip, uint32_t& flags, uint32_t*
|
|||||||
|
|
||||||
CPUContext::~CPUContext() = default;
|
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(){
|
constexpr std::array<ExecutorCase, 255> GenerateExecutorTable(){
|
||||||
std::array<ExecutorCase, 255> table{};
|
std::array<ExecutorCase, 255> table{};
|
||||||
table[Opcode::NOP] = executor_cases::Nop;
|
table[Opcode::NOP] = executor_cases::Nop;
|
||||||
table[Opcode::HLT] = executor_cases::Hlt;
|
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;
|
table[Opcode::ADD_RM32_R32] = executor_cases::Add_rm32_r32;
|
||||||
return table;
|
return table;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -54,7 +54,7 @@ namespace x86 {
|
|||||||
std::string Opcode2Str(Opcode op) {
|
std::string Opcode2Str(Opcode op) {
|
||||||
switch(op) {
|
switch(op) {
|
||||||
case Opcode::ADD_RM32_R32: return "ADD_RM32_R32";
|
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::NOP: return "NOP";
|
||||||
case Opcode::HLT: return "HLT";
|
case Opcode::HLT: return "HLT";
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ namespace x86 {
|
|||||||
enum Opcode : uint8_t {
|
enum Opcode : uint8_t {
|
||||||
NOP = 0x90,
|
NOP = 0x90,
|
||||||
HLT = 0xF4,
|
HLT = 0xF4,
|
||||||
MOV_R_IMM32 = 0xB8,
|
MOV_R32_IMM32 = 0xB8,
|
||||||
ADD_RM32_R32 = 0x01,
|
ADD_RM32_R32 = 0x01,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ void Metal::Upload2Memory(uint8_t bytes[], size_t len) {
|
|||||||
|
|
||||||
void Metal::Run() {
|
void Metal::Run() {
|
||||||
m_Running = true;
|
m_Running = true;
|
||||||
while(m_Running) {
|
while(m_Running && !m_CPU.IsHalted()) {
|
||||||
m_CPU.Step();
|
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 eax, 0xF4
|
||||||
// mov ecx, 0x8000
|
// mov ecx, 0x8000
|
||||||
// add [ecx + 0x0010], eax
|
// add [0x8010], eax
|
||||||
uint8_t test[] = {
|
uint8_t test[] = {
|
||||||
0xB8, 0xF4, 0x00, 0x00, 0x00,
|
0xB8, 0xF4, 0x00, 0x00, 0x00,
|
||||||
0xB9, 0x00, 0x80, 0x00, 0x00,
|
0xB9, 0x00, 0x80, 0x00, 0x00,
|
||||||
|
|||||||
Reference in New Issue
Block a user