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
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
|
#include "mov.h"
#include "codes.h"
#include <asm/assembler.h>
#include <asm/operators.h>
#include <asm/intel64/codes.h>
using namespace std::string_literals;
Op_mov::Op_mov(const Asm::Args& args)
{
if (args[0].type() == typeid(Asm::Args::Register8) && args[1].type() == typeid(Asm::Args::Register8)) { // mov reg8, reg8
// r/m8, r8: ModRM:r/m (w), ModRM:reg (r)
machine_code = std::vector<uint8_t>{ 0x88 } +
ModRM(std::any_cast<Asm::Args::Register8>(args[1]).name(), std::any_cast<Asm::Args::Register8>(args[0]).name());
} else if (args[0].type() == typeid(Asm::Args::Register16) && args[1].type() == typeid(Asm::Args::Register16)) { // mov reg16, reg16
// r/m16, r16: ModRM:r/m (w), ModRM:reg (r)
machine_code = OpSizePrefix() + std::vector<uint8_t>{ 0x89 } +
ModRM(std::any_cast<Asm::Args::Register16>(args[1]).name(), std::any_cast<Asm::Args::Register16>(args[0]).name());
} else if (args[0].type() == typeid(Asm::Args::Register32) && args[1].type() == typeid(Asm::Args::Register32)) { // mov reg32, reg32
// r/m32, r32: ModRM:r/m (w), ModRM:reg (r)
machine_code = std::vector<uint8_t>{ 0x89 } +
ModRM(std::any_cast<Asm::Args::Register32>(args[1]).name(), std::any_cast<Asm::Args::Register32>(args[0]).name());
} else if (args[0].type() == typeid(Asm::Args::Register64) && args[1].type() == typeid(Asm::Args::Register64)) { // mov reg64, reg64
// r/m64, r64: ModRM:r/m (w), ModRM:reg (r)
machine_code = REX("W") + std::vector<uint8_t>{ 0x89 } +
ModRM(std::any_cast<Asm::Args::Register64>(args[1]).name(), std::any_cast<Asm::Args::Register64>(args[0]).name());
} else if (args[0].type() == typeid(Asm::Args::Register32) && args[1].type() == typeid(Asm::Args::Immediate32)) { // mov reg32, imm32
machine_code = std::vector<uint8_t>{ static_cast<uint8_t>(0xB8 + RegNo(std::any_cast<Asm::Args::Register32>(args[0]).name())) } + std::any_cast<Asm::Args::Immediate32>(args[1]).getCode();
} else if (args[0].type() == typeid(Asm::Args::Register64) && args[1].type() == typeid(Asm::Args::Immediate64)) { // mov reg64, imm64
machine_code = std::vector<uint8_t>{ REX("W") + static_cast<uint8_t>(0xB8 + RegNo(std::any_cast<Asm::Args::Register64>(args[0]).name())) } + std::any_cast<Asm::Args::Immediate64>(args[1]).getCode();
} else if (args[0].type() == typeid(Asm::Args::Register32) && args[1].type() == typeid(Asm::Args::Mem32Ptr64)) { // mov reg32, [reg64]
Asm::Args::Mem32Ptr64 ptr{std::any_cast<Asm::Args::Mem32Ptr64>(args[1])};
machine_code = std::vector<uint8_t>{ 0x8B } + ModRM(std::any_cast<Asm::Args::Register32>(args[0]).name(), ptr.reg(), ptr.offs());
} else if (args[0].type() == typeid(Asm::Args::Register64) && args[1].type() == typeid(Asm::Args::Mem64Ptr64)) { // mov reg64, [reg64]
Asm::Args::Mem64Ptr64 ptr{std::any_cast<Asm::Args::Mem64Ptr64>(args[1])};
machine_code = REX("W") + std::vector<uint8_t>{ 0x8B } + ModRM(std::any_cast<Asm::Args::Register64>(args[0]).name(), ptr.reg(), ptr.offs());
} else if (args[0].type() == typeid(Asm::Args::Mem32Ptr64) && args[1].type() == typeid(Asm::Args::Register32)) { // mov [reg64], reg32
Asm::Args::Mem32Ptr64 ptr{std::any_cast<Asm::Args::Mem32Ptr64>(args[0])};
machine_code = std::vector<uint8_t>{ 0x89 } + ModRM(std::any_cast<Asm::Args::Register32>(args[1]).name(), ptr.reg(), ptr.offs());
} else if (args[0].type() == typeid(Asm::Args::Mem64Ptr64) && args[1].type() == typeid(Asm::Args::Register64)) { // mov [reg64], reg64
Asm::Args::Mem64Ptr64 ptr{std::any_cast<Asm::Args::Mem64Ptr64>(args[0])};
machine_code = REX("W") + std::vector<uint8_t>{ 0x89 } + ModRM(std::any_cast<Asm::Args::Register64>(args[1]).name(), ptr.reg(), ptr.offs());
} else if (args[0].type() == typeid(Asm::Args::Register64) && args[1].type() == typeid(Asm::Args::Immediate32)) { // mov reg64, imm32 (sign-extended)
machine_code = REX("W") + std::vector<uint8_t>{ 0xC7 } + ModRM("/0", std::any_cast<Asm::Args::Register64>(args[0]).name()) + std::any_cast<Asm::Args::Immediate32>(args[1]).getCode();
} else if (args[0].type() == typeid(Asm::Args::Mem8Ptr64) && args[1].type() == typeid(Asm::Args::Immediate8)) { // mov [reg64], imm8
Asm::Args::Mem8Ptr64 ptr{std::any_cast<Asm::Args::Mem8Ptr64>(args[0])};
machine_code = std::vector<uint8_t>{ 0xC6 } + ModRM("/0", ptr.reg(), ptr.offs()) + std::any_cast<Asm::Args::Immediate8>(args[1]).getCode();
} else if (args[0].type() == typeid(Asm::Args::Mem32Ptr64) && args[1].type() == typeid(Asm::Args::Immediate32)) { // mov [reg64], imm32
Asm::Args::Mem32Ptr64 ptr{std::any_cast<Asm::Args::Mem32Ptr64>(args[0])};
machine_code = std::vector<uint8_t>{ 0xC7 } + ModRM("/0", ptr.reg(), ptr.offs()) + std::any_cast<Asm::Args::Immediate32>(args[1]).getCode();
} else if (args[0].type() == typeid(Asm::Args::Mem64Ptr64) && args[1].type() == typeid(Asm::Args::Immediate32)) { // mov [reg64], imm32 (sign-extended to imm64)
Asm::Args::Mem64Ptr64 ptr{std::any_cast<Asm::Args::Mem64Ptr64>(args[0])};
machine_code = REX("W") + std::vector<uint8_t>{ 0xC7 } + ModRM("/0", ptr.reg(), ptr.offs()) + std::any_cast<Asm::Args::Immediate32>(args[1]).getCode();
} else if (args[0].type() == typeid(Asm::Args::Mem64Ptr64) && args[1].type() == typeid(Asm::Args::Immediate64)) { // mov [reg64], imm64 (cut to imm32)
Asm::Args::Mem64Ptr64 ptr{std::any_cast<Asm::Args::Mem64Ptr64>(args[0])};
Asm::Args::Immediate32 imm32{std::any_cast<Asm::Args::Immediate64>(args[1])};
machine_code = REX("W") + std::vector<uint8_t>{ 0xC7 } + ModRM("/0", ptr.reg(), ptr.offs()) + imm32.getCode();
} else {
throw std::runtime_error("Unimplemented: mov "s + args[0].type().name() + " "s + args[1].type().name());
}
}
namespace {
bool registered {
registerOp(mangleName<Asm::Args::Register8, Asm::Args::Register8>("mov"), [](const Asm::Args& args) -> std::shared_ptr<Op>{
return std::make_shared<Op_mov>(args);
}) &&
registerOp(mangleName<Asm::Args::Register16, Asm::Args::Register16>("mov"), [](const Asm::Args& args) -> std::shared_ptr<Op>{
return std::make_shared<Op_mov>(args);
}) &&
registerOp(mangleName<Asm::Args::Register32, Asm::Args::Register32>("mov"), [](const Asm::Args& args) -> std::shared_ptr<Op>{
return std::make_shared<Op_mov>(args);
}) &&
registerOp(mangleName<Asm::Args::Register64, Asm::Args::Register64>("mov"), [](const Asm::Args& args) -> std::shared_ptr<Op>{
return std::make_shared<Op_mov>(args);
}) &&
registerOp(mangleName<Asm::Args::Register32, Asm::Args::Immediate32>("mov"), [](const Asm::Args& args) -> std::shared_ptr<Op>{
return std::make_shared<Op_mov>(args);
}) &&
registerOp(mangleName<Asm::Args::Register64, Asm::Args::Immediate64>("mov"), [](const Asm::Args& args) -> std::shared_ptr<Op>{
return std::make_shared<Op_mov>(args);
}) &&
registerOp(mangleName<Asm::Args::Register32, Asm::Args::Mem32Ptr64>("mov"), [](const Asm::Args& args) -> std::shared_ptr<Op>{
return std::make_shared<Op_mov>(args);
}) &&
registerOp(mangleName<Asm::Args::Mem32Ptr64, Asm::Args::Register32>("mov"), [](const Asm::Args& args) -> std::shared_ptr<Op>{
return std::make_shared<Op_mov>(args);
}) &&
registerOp(mangleName<Asm::Args::Register64, Asm::Args::Mem64Ptr64>("mov"), [](const Asm::Args& args) -> std::shared_ptr<Op>{
return std::make_shared<Op_mov>(args);
}) &&
registerOp(mangleName<Asm::Args::Mem64Ptr64, Asm::Args::Register64>("mov"), [](const Asm::Args& args) -> std::shared_ptr<Op>{
return std::make_shared<Op_mov>(args);
}) &&
registerOp(mangleName<Asm::Args::Register64, Asm::Args::Immediate32>("mov"), [](const Asm::Args& args) -> std::shared_ptr<Op>{
return std::make_shared<Op_mov>(args);
}) &&
registerOp(mangleName<Asm::Args::Mem8Ptr64, Asm::Args::Immediate8>("mov"), [](const Asm::Args& args) -> std::shared_ptr<Op>{
return std::make_shared<Op_mov>(args);
}) &&
registerOp(mangleName<Asm::Args::Mem32Ptr64, Asm::Args::Immediate32>("mov"), [](const Asm::Args& args) -> std::shared_ptr<Op>{
return std::make_shared<Op_mov>(args);
}) &&
registerOp(mangleName<Asm::Args::Mem64Ptr64, Asm::Args::Immediate32>("mov"), [](const Asm::Args& args) -> std::shared_ptr<Op>{
return std::make_shared<Op_mov>(args);
}) &&
registerOp(mangleName<Asm::Args::Mem64Ptr64, Asm::Args::Immediate64>("mov"), [](const Asm::Args& args) -> std::shared_ptr<Op>{
return std::make_shared<Op_mov>(args);
})
};
}
|