1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
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;
};
|