Patch: Fix bus access alignment issue, modrm byte handler enhanced.

This commit is contained in:
0x221E
2026-02-04 22:28:36 +01:00
parent 4671a62ddf
commit b1a012fb82
14 changed files with 202 additions and 111 deletions

View File

@@ -5,8 +5,9 @@
#include <iomanip>
#include <stdlib.h>
#include <array>
#include <cassert>
CPU::CPU(std::shared_ptr<Bus> bus) : m_Bus(bus), m_Context({m_Instruction, m_InstructionPointer, m_Flags, m_Registers, m_Bus}){
CPU::CPU(std::shared_ptr<Bus> bus) : m_Bus(bus), m_IsHalted(false), m_Context({m_Instruction, m_InstructionPointer, m_Flags, m_Registers, m_Bus, m_IsHalted}) {
m_InstructionPointer = 0x00008000;
for(int i = 0; i < 16; i++)
@@ -15,48 +16,39 @@ CPU::CPU(std::shared_ptr<Bus> bus) : m_Bus(bus), m_Context({m_Instruction, m_Ins
}
}
void CPU::Step(){
void CPU::Step() {
FetchDecode();
Execute();
}
void CPU::FetchDecode(){
std::cout << "Fetching instruction: " << std::hex << m_InstructionPointer << std::endl;
m_InstructionRaw = m_Bus->AccessX<uint64_t>(m_InstructionPointer); // Slice of 8 bytes.
void CPU::FetchDecode() {
uint8_t opcode_raw = m_Bus->AccessX<uint8_t>(m_InstructionPointer);
Opcode opcode = static_cast<Opcode>(opcode_raw);
std::cout << "Context window fetched: " << std::hex << m_InstructionRaw << std::endl; // Start Decode Instruction
uint64_t first_byte = m_InstructionRaw & 0xFF;
std::cout << "Decoded first byte: " << std::hex << first_byte << std::endl;
Opcode opcode = static_cast<Opcode>(first_byte);
if(first_byte >= 0xB8 && first_byte <= 0xBF)
{
m_Instruction.m_Operand1 = first_byte - 0xB8;
opcode = Opcode::MOV_R_IMM32;
}
switch(opcode){
case Opcode::NOP: m_Instruction.m_Length = 1; break;
case Opcode::HLT: m_Instruction.m_Length = 1; break;
case Opcode::MOV_R_IMM32:
switch(opcode_raw) {
case Opcode::MOV_R_IMM32 ... 0xBF: // 0xB8 to 0xBF
m_Instruction.m_Opcode = Opcode::MOV_R_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;
break;
case Opcode::ADD_RM32_R32:
m_Instruction.m_Operand1 = m_Bus->AccessX<uint8_t>(m_InstructionPointer + 1);
m_Instruction.m_Operand2 = m_Bus->AccessX<uint32_t>(m_InstructionPointer + 2);
m_Instruction.m_Length = 6;
case Opcode::NOP:
case Opcode::HLT:
m_Instruction.m_Opcode = opcode;
m_Instruction.m_Length = 1;
break;
default:
std::runtime_error("Decode encountered unexpected opcode.");
case Opcode::ADD_RM32_R32:
m_Instruction.m_Opcode = opcode;
m_Instruction.optional.m_ModRM = x86::process_modrm(m_Bus->AccessX<uint8_t>(m_InstructionPointer + 1));
m_Instruction.m_Length = 2;
FetchModRMFields();
break;
}
m_Instruction.m_Opcode = opcode;
m_InstructionPointer += m_Instruction.m_Length;
}
void CPU::Execute(){
void CPU::Execute() {
std::cout << "Executing... \n";
uint8_t opcode_value = static_cast<uint8_t>(m_Instruction.m_Opcode);
auto& exec_table = GetExecutorTable();
@@ -67,3 +59,24 @@ void CPU::Execute(){
}
throw std::runtime_error("Opcode not found!");
}
void CPU::FetchModRMFields() {
assert(m_Instruction.m_Length != 0); // FetchDecode() must set m_Length before calling FetchModRMFields()
x86::ModRMState state = m_Instruction.optional.m_ModRM.m_State;
switch(state) {
case x86::ModRMState::LR:
case x86::ModRMState::R:
break;
case x86::ModRMState::DISP32:
case x86::ModRMState::LR_DISP32:
m_Instruction.m_Operand1 = m_Bus->AccessX<uint32_t>(m_InstructionPointer + m_Instruction.m_Length);
m_Instruction.m_Length += 4;
break;
case x86::ModRMState::LR_DISP8:
m_Instruction.m_Operand1 = m_Bus->AccessX<uint8_t>(m_InstructionPointer + m_Instruction.m_Length);
m_Instruction.m_Length += 1;
break;
default:
throw std::runtime_error("Instruction could not be modified according to the modrm field!");
}
}