summaryrefslogtreecommitdiffhomepage
path: root/asm/intel64/jmp.cpp
blob: 30ae546c8e0ffc46c94fbc3aa24a82ba6174a8d2 (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
#include "jmp.h"

#include "codes.h"

#include <asm/assembler.h>
#include <asm/operators.h>

#include <asm/intel64/codes.h>

using namespace std::string_literals;

namespace {
 struct Jump {
  std::string name;
  OP_T jmp8;  ///< if empty, not available
  OP_T jmp32; ///< if empty, not available
 };

 std::vector<Jump> jumpOps {
  // Call Procedure
  {"call",  OP_T{},       OP_T{ 0xE8 }      }, // no addr8 version

  // Unconditional Jump
  {"jmp",   OP_T{ 0xEB }, OP_T{ 0xE9 }      },

  // Conditional Jumps
  {"ja",    OP_T{ 0x77 }, OP_T{ 0x0F, 0x87 }},
  {"jae",   OP_T{ 0x73 }, OP_T{ 0x0F, 0x83 }},
  {"jb",    OP_T{ 0x72 }, OP_T{ 0x0F, 0x82 }},
  {"jbe",   OP_T{ 0x76 }, OP_T{ 0x0F, 0x86 }},
  {"jc",    OP_T{ 0x72 }, OP_T{ 0x0F, 0x82 }},
  {"jecxz", OP_T{ 0xE3 }, OP_T{}            }, // no addr32 version
  {"jrcxz", OP_T{ 0xE3 }, OP_T{}            }, // no addr32 version
  {"je",    OP_T{ 0x74 }, OP_T{ 0x0F, 0x84 }},
  {"jg",    OP_T{ 0x7F }, OP_T{ 0x0F, 0x8F }},
  {"jge",   OP_T{ 0x7D }, OP_T{ 0x0F, 0x8D }},
  {"jl",    OP_T{ 0x7C }, OP_T{ 0x0F, 0x8C }},
  {"jle",   OP_T{ 0x7E }, OP_T{ 0x0F, 0x8E }},
  {"jna",   OP_T{ 0x76 }, OP_T{ 0x0F, 0x86 }},
  {"jnae",  OP_T{ 0x72 }, OP_T{ 0x0F, 0x82 }},
  {"jnb",   OP_T{ 0x73 }, OP_T{ 0x0F, 0x83 }},
  {"jnbe",  OP_T{ 0x77 }, OP_T{ 0x0F, 0x87 }},
  {"jnc",   OP_T{ 0x73 }, OP_T{ 0x0F, 0x83 }},
  {"jne",   OP_T{ 0x75 }, OP_T{ 0x0F, 0x85 }},
  {"jng",   OP_T{ 0x7E }, OP_T{ 0x0F, 0x8E }},
  {"jnge",  OP_T{ 0x7C }, OP_T{ 0x0F, 0x8C }},
  {"jnl",   OP_T{ 0x7D }, OP_T{ 0x0F, 0x8D }},
  {"jnle",  OP_T{ 0x7F }, OP_T{ 0x0F, 0x8F }},
  {"jno",   OP_T{ 0x71 }, OP_T{ 0x0F, 0x81 }},
  {"jnp",   OP_T{ 0x7B }, OP_T{ 0x0F, 0x8B }},
  {"jns",   OP_T{ 0x79 }, OP_T{ 0x0F, 0x89 }},
  {"jnz",   OP_T{ 0x75 }, OP_T{ 0x0F, 0x85 }},
  {"jo",    OP_T{ 0x70 }, OP_T{ 0x0F, 0x80 }},
  {"jp",    OP_T{ 0x7A }, OP_T{ 0x0F, 0x8A }},
  {"jpe",   OP_T{ 0x7A }, OP_T{ 0x0F, 0x8A }},
  {"jpo",   OP_T{ 0x7B }, OP_T{ 0x0F, 0x8B }},
  {"js",    OP_T{ 0x78 }, OP_T{ 0x0F, 0x88 }},
  {"jz",    OP_T{ 0x74 }, OP_T{ 0x0F, 0x84 }},
 };

 bool registerOps() {
  bool result{true};
  for (const auto& jumpOp: jumpOps) {
   result &= registerOp(mangleName<AsmArgs::Label>(jumpOp.name), [&](AsmArgs& args) -> std::shared_ptr<Op>{
                        return std::make_shared<Op_jmp>(jumpOp.name, args, jumpOp.jmp8, jumpOp.jmp32);
                       });
  }
  return result;
 }

 bool registered {
  registerOps()
 };
}

Op_jmp::Op_jmp(const std::string& name, AsmArgs& args, const OP_T& jmp8, const OP_T& jmp32)
{
 label = std::any_cast<AsmArgs::Label>(args[0]).name();

 if (!jmp32.empty()) { // set machine_code
  machine_code = jmp32 + OP_T{size_t(4), uint8_t(0)};
  addr_size = 4;
  addr_offs = jmp32.size();
  if (!jmp8.empty()) { // also provide alternative
   alternative_code = jmp8 + OP_T{size_t(1), uint8_t(0)};
   alternative_size = 1;
   alternative_offs = jmp8.size();
  }
 }

 if (machine_code.empty() && !jmp8.empty()) {
  machine_code = jmp8 + OP_T{size_t(1), uint8_t(0)};
  addr_size = 1;
  addr_offs = jmp8.size();
 }

 if (machine_code.empty()) {
  throw std::runtime_error("Unimplemented: "s + name);
 }

 // actual address not set, yet!
}