diff options
| author | 0x221E <0x221E@0xinfinity.dev> | 2026-04-12 16:59:40 +0200 |
|---|---|---|
| committer | 0x221E <0x221E@0xinfinity.dev> | 2026-04-12 16:59:40 +0200 |
| commit | a66c7433c2c11b8b6c99142277ed4e16b1a2a465 (patch) | |
| tree | e54bcfb59c303acf6118fd11f06d5c0bd5f24e5d /src/CPU.cpp | |
Diffstat (limited to 'src/CPU.cpp')
| -rw-r--r-- | src/CPU.cpp | 142 |
1 files changed, 142 insertions, 0 deletions
diff --git a/src/CPU.cpp b/src/CPU.cpp new file mode 100644 index 0000000..dd03a19 --- /dev/null +++ b/src/CPU.cpp @@ -0,0 +1,142 @@ +#include "CPU.h" + +#include <stdexcept> +#include <iostream> +#include <iomanip> +#include <bitset> +#include <stdlib.h> +#include <array> +#include <cassert> + +#include "Exceptions.h" +#include "InstructionModifierLookup.h" + +static const Instruction s_EmptyInstruction{}; + +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 < 8; i++) { + m_Registers[i] = 0; + } + + for(int i = 0; i < 8; i++) { + m_SegmentRegisters[i] = 0; + } +} + +void CPU::Step() { + FetchDecode(); + Execute(); +} + +void CPU::Dump() { + std::cout << "--TRACE-- "; + std::cout << std::endl; + + for(uint8_t i = 0; i < 8; i++) + { + std::cout << x86::Register2Str((x86::Register)i) << ": " << m_Registers[i] << " | "; + } + + std::cout << std::endl; + + std::bitset<32> flags(m_Flags); + std::cout << "IP: " << std::hex << m_InstructionPointer << " | FLAGS: " << flags; + + std::cout << std::endl; +} + +void CPU::Reset() { + for(uint8_t i = 0; i < 8; i++) + { + m_Registers[i] = 0; + m_SegmentRegisters[i] = 0; + } + + m_InstructionPointer = 0x8000; + m_Flags = 0; + + std::cout << "[CPU] State Flushed!" << std::endl; + m_IsHalted = false; + m_Instruction = s_EmptyInstruction; +} + +CPUStatus CPU::GetStatus() { + return (CPUStatus){.m_Registers = m_Registers, .m_IP = m_InstructionPointer, .m_Instruction = m_Instruction}; +} + +void CPU::FetchDecode() { + m_Instruction = s_EmptyInstruction; + + uint8_t opcode_raw = m_Bus->AccessX<uint8_t>(m_InstructionPointer); + Opcode opcode = static_cast<Opcode>(opcode_raw); + + auto& instruction_table = GetInstructionTable(); + if(instruction_table[opcode_raw].m_Executor == nullptr) { + std::cout << "Encoding: " << opcode_raw << std::endl; + std::string exception = "[CPU] [FetchDecode] Opcode is not in instruction table! Opcode_raw: " + std::to_string(opcode_raw); + throw CPUException(exception); + } + + auto& instruction = instruction_table[opcode_raw]; + + uint8_t encoding_mask = 0b00001111; + uint8_t encoding = instruction.m_Encoding & encoding_mask; + uint8_t immediate = instruction.m_Encoding & ~encoding_mask; + + m_Instruction.m_Opcode = opcode; + + switch(encoding) { + case OI: + if (immediate == I32) { + m_Instruction.m_Operand1 = m_Bus->AccessX<uint32_t>(m_InstructionPointer + 1); + m_Instruction.m_Length = 5; + } else if (immediate == I16) { + m_Instruction.m_Operand1 = m_Bus->AccessX<uint16_t>(m_InstructionPointer + 1); + m_Instruction.m_Length = 3; + } else if (immediate == I8) { + m_Instruction.m_Operand1 = m_Bus->AccessX<uint8_t>(m_InstructionPointer + 1); + m_Instruction.m_Length = 2; + } else { + throw CPUException("[CPU] [FetchDecode] OI instruction encoding only supports imm8,imm16,imm32."); + } + break; + case ZO: + m_Instruction.m_Length = 1; + break; + case RM: + case MR: { + uint8_t modrm = m_Bus->AccessX<uint8_t>(m_InstructionPointer + 1); + m_Instruction.m_ModRM = x86::ProcessMODRM(modrm); + m_Instruction.m_Length = 2; + FetchModRMFields(modrm); + if (m_Instruction.m_ModRM.m_SIB) { + uint8_t sib = m_Bus->AccessX<uint8_t>(m_InstructionPointer + m_Instruction.m_Length); + m_Instruction.m_Length += 1; + m_Instruction.m_SIB = x86::ProcessSIB(sib); + } + break; + } + default: + throw CPUException("[CPU] [FetchDecode] Encoding was not found!"); + } + + m_Instruction.m_Func = instruction.m_Executor; + m_InstructionPointer += m_Instruction.m_Length; +} + +void CPU::Execute() { + if(m_Instruction.m_Func != nullptr) + { + m_Instruction.m_Func(m_Context); + return; + } + throw std::runtime_error("[CPU] [Execute] m_Func is nullptr!"); +} + +void CPU::FetchModRMFields(uint8_t modrm) { + assert(m_Instruction.m_Length != 0); // FetchDecode() must set m_Length before calling FetchModRMFields() + auto modrm_table = GetMod32Table(); + modrm_table[modrm](m_Context); +} |
