-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathlowlevel_formatter.cpp
More file actions
109 lines (85 loc) · 2.96 KB
/
lowlevel_formatter.cpp
File metadata and controls
109 lines (85 loc) · 2.96 KB
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
#include <cassert>
#include "instruction.h"
#include "exceptions.h"
#include "lowlevel.h"
#include "lowlevel_formatter.h"
namespace {
const int BYTE = 0;
const int WORD = 1;
const int DWORD = 2;
const int QUAD = 3;
// names of machine registers for the 8 bit, 16 bit,
// 32 bit, and 64 bit sizes
const char *mreg_operand_names[][4] = {
{ "al", "ax", "eax", "rax" },
{ "bl", "bx", "ebx", "rbx" },
{ "cl", "cx", "ecx", "rcx" },
{ "dl", "dx", "edx", "rdx" },
{ "sil", "si", "esi", "rsi" },
{ "dil", "di", "edi", "rdi" },
{ "spl", "sp", "esp", "rsp" },
{ "bpl", "bp", "ebp", "rbp" },
{ "r8b", "r8w", "r8d", "r8" },
{ "r9b", "r9w", "r9d", "r9" },
{ "r10b", "r10w", "r10d", "r10" },
{ "r11b", "r11w", "r11d", "r11" },
{ "r12b", "r12w", "r12d", "r12" },
{ "r13b", "r13w", "r13d", "r13" },
{ "r14b", "r14w", "r14d", "r14" },
{ "r15b", "r15w", "r15d", "r15" },
};
const int num_mregs = sizeof(mreg_operand_names) / sizeof(mreg_operand_names[0]);
std::string format_reg(int regnum, int size) {
assert(regnum >= 0 && regnum < num_mregs);
assert(size >= BYTE && size <= QUAD);
return std::string("%") + mreg_operand_names[regnum][size];
}
}
LowLevelFormatter::LowLevelFormatter() {
}
LowLevelFormatter::~LowLevelFormatter() {
}
std::string LowLevelFormatter::format_operand(const Operand &operand) const {
if (operand.is_non_reg()) {
// non-register operands are handled by the base class
return Formatter::format_operand(operand);
}
switch (operand.get_kind()) {
case Operand::MREG8:
return format_reg(operand.get_base_reg(), BYTE);
case Operand::MREG16:
return format_reg(operand.get_base_reg(), WORD);
case Operand::MREG32:
return format_reg(operand.get_base_reg(), DWORD);
case Operand::MREG64:
return format_reg(operand.get_base_reg(), QUAD);
case Operand::MREG64_MEM:
return "(" + format_reg(operand.get_base_reg(), QUAD) + ")";
case Operand::MREG64_MEM_IDX:
return "(" + format_reg(operand.get_base_reg(), QUAD) + "," + format_reg(operand.get_index_reg(), QUAD) + ")";
case Operand::MREG64_MEM_OFF:
return std::to_string(operand.get_offset()) + "(" + format_reg(operand.get_base_reg(), QUAD) + ")";
default:
assert(false);
return "<unknown operand kind>";
}
}
std::string LowLevelFormatter::format_instruction(const Instruction *ins) const {
LowLevelOpcode opcode = LowLevelOpcode(ins->get_opcode());
const char *mnemonic_ptr = lowlevel_opcode_to_str(opcode);
if (mnemonic_ptr == nullptr)
RuntimeError::raise("Unknown low level opcode: %d", int(opcode));
std::string mnemonic(mnemonic_ptr);
std::string buf;
buf += mnemonic;
// pad mnemonics to 8 characters
unsigned padding = (mnemonic.size() < 8U) ? 8U - mnemonic.size() : 0;
buf += (" " + (8U - padding));
for (unsigned i = 0; i < ins->get_num_operands(); i++) {
if (i > 0) {
buf += ", ";
}
buf += format_operand(ins->get_operand(i));
}
return buf;
}