summaryrefslogtreecommitdiff
path: root/src/Instruction.h
blob: c80d2ca9713fea864d2beff851e1cd8e01da4f86 (plain)
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;
};