#pragma once #include #include #include "ExecutorCases.h" #include "Exceptions.h" namespace x86 { enum Register : uint8_t { EAX = 0, ECX = 1, EDX = 2, EBX = 3, ESP = 4, EBP = 5, ESI = 6, EDI = 7, SIB_DISP = 254, SIB_NONE = 255, }; enum class ModRMState : uint8_t { INVALID = 0, LR = 1, LR_DISP8 = 2, LR_DISP32 = 3, DISP32 = 4, R = 5 }; struct ModRM { ModRMState m_State; x86::Register m_Reg; uint8_t m_Rm; bool m_SIB; }; struct SIB { uint8_t m_Scale; x86::Register m_Index; x86::Register m_Base; }; constexpr ModRM ProcessMODRM(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; bool SIB = false; switch(mod) { case 0b00000000: state = ModRMState::LR; if(rm == 0b00000101) state = ModRMState::DISP32; else if(rm == 0b00000100) SIB = true; break; case 0b01000000: state = ModRMState::LR_DISP8; if(rm == 0b00000100) SIB = true; break; case 0b10000000: state = ModRMState::LR_DISP32; if(rm == 0b00000100) SIB = true; break; case 0b11000000: state = ModRMState::R; break; default: throw CPUException("Mod R/M Unknown exception!"); } return {.m_State = state, .m_Reg = (x86::Register)reg, .m_Rm = rm, .m_SIB = SIB}; } SIB ProcessSIB(uint8_t sib); // Helpers std::string Register2Str(x86::Register reg); } enum Opcode : uint8_t { INVALID = 0, NOP = 0x90, HLT = 0xF4, MOV_R32_IMM32 = 0xB8, MOV_RM32_R32 = 0x89, ADD_RM32_R32 = 0x01, ADD_R32_RM32 = 0x03, }; std::string Opcode2Str(Opcode op); struct Instruction{ ExecutorCase m_Func; uint8_t m_Prefix; Opcode m_Opcode; size_t m_Length; uint32_t m_Operand1; uint32_t m_Operand2; x86::ModRM m_ModRM; x86::SIB m_SIB; uint8_t m_Displacement[4]; uint8_t m_DisplacementSize; };