summaryrefslogtreecommitdiff
path: root/src/Instruction.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/Instruction.h')
-rw-r--r--src/Instruction.h110
1 files changed, 110 insertions, 0 deletions
diff --git a/src/Instruction.h b/src/Instruction.h
new file mode 100644
index 0000000..c80d2ca
--- /dev/null
+++ b/src/Instruction.h
@@ -0,0 +1,110 @@
+#pragma once
+
+#include <string>
+#include <cstdint>
+
+#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;
+};