#include "ExecutorCases.h" #include "Instruction.h" #include "Bus.h" #include #include CPUContext::CPUContext(Instruction& i, uint64_t& ip, uint64_t& flags, uint64_t* reg, std::shared_ptr& bus) : m_Instruction(i), m_InstructionPointer(ip), m_Flags(flags), m_Registers(reg), m_Bus(bus) { } CPUContext::~CPUContext() = default; // NO SIB SUPPORT YET ModRM process_modrm(uint8_t modrm){ uint8_t mod_mask = 0b11000000; uint8_t reg_mask = 0b00111000; uint8_t rm_mask = 0b00000111; uint8_t mod = modrm & mod_mask; uint8_t reg = (modrm & reg_mask) >> 3; uint8_t rm = modrm & rm_mask; ModRMState state = ModRMState::INVALID; switch(mod) { case 0b00000000: state = ModRMState::LR; break; case 0b01000000: state = ModRMState::LR_DISP8; break; case 0b10000000: state = ModRMState::LR_DISP32; break; case 0b11000000: state = ModRMState::R; break; default: throw std::runtime_error("Mod R/M does not support non-register operands right now!"); } return {.m_State = state, .m_Reg = reg, .m_Rm = rm}; } 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; std::cout << "Contents of " << x86::Register2Str((x86::Register)cc.m_Instruction.m_Operand1) << " changed to " << cc.m_Registers[cc.m_Instruction.m_Operand1] << std::endl; } //NO SIB SUPPORT YET void Add_rm32_r32(CPUContext& cc){ ModRM modrm = process_modrm(cc.m_Instruction.m_Operand1); switch(modrm.m_State) { case ModRMState::R: { cc.m_Registers[modrm.m_Rm] += cc.m_Registers[modrm.m_Reg]; std::cout << "Adding " << x86::Register2Str((x86::Register)modrm.m_Reg) << " to " << x86::Register2Str((x86::Register)modrm.m_Rm) << std::endl; break; } case ModRMState::LR: { uint32_t dstPrevValue = cc.m_Bus->AccessX(cc.m_Registers[modrm.m_Rm]); uint32_t currRegValue = cc.m_Registers[modrm.m_Reg]; uint32_t result = dstPrevValue + currRegValue; cc.m_Bus->WriteX(cc.m_Registers[modrm.m_Rm], result); std::cout << "Memory address " << std::hex << cc.m_Registers[modrm.m_Rm] << " modified to: " << result << std::endl; break; } case ModRMState::LR_DISP8: { } default: { throw std::runtime_error("Invalid ModRM State encountered during Add_rm32_r32"); } } } } constexpr std::array GenerateExecutorTable(){ std::array 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::ADD_RM32_R32] = executor_cases::Add_rm32_r32; return table; } static constexpr std::array s_ExecutorTable = GenerateExecutorTable(); const std::array& GetExecutorTable() { return s_ExecutorTable; }