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
|
//: Having to manually translate numbers into hex and enter them in
//: little-endian order is tedious and error-prone. Let's automate the
//: translation.
:(scenario translate_immediate_constants)
# opcode ModR/M SIB displacement immediate
# instruction mod, reg, Reg/Mem bits scale, index, base
# 1-3 bytes 0/1 byte 0/1 byte 0/1/2/4 bytes 0/1/2/4 bytes
bb 42/imm32
+translate: converting '42/imm32' to '2a 00 00 00'
+run: copy imm32 0x0000002a to EBX
#: we don't have a testable instruction using 8-bit immediates yet, so can't run this instruction
:(scenarios transform)
:(scenario translate_imm8)
cd 128/imm8
+translate: converting '128/imm8' to '80'
:(scenarios run)
:(before "End One-time Setup")
Transform.push_back(transform_immediate);
:(code)
void transform_immediate(const string& input, string& output) {
istringstream in(input);
in >> std::noskipws;
ostringstream out;
while (has_data(in)) {
string word = next_word(in);
if (word.find("/imm") == string::npos)
out << word << ' ';
else {
string output = transform_immediate(word);
trace("translate") << "converting '" << word << "' to '" << output << "'" << end();
out << output << ' ';
}
}
out.str().swap(output);
}
string transform_immediate(const string& word) {
istringstream in(word); // 'word' is guaranteed to have no whitespace
string data = slurp_until(in, '/');
istringstream in2(data);
int value = 0;
in2 >> value;
ostringstream out;
string type = next_word(in);
if (type == "imm32") emit_octets(value, 4, out);
else if (type == "imm8") emit_octets(value, 1, out);
else raise << "unknown immediate tag /" << type << '\n' << end();
return out.str();
}
void emit_octets(int value, int num_octets, ostream& out) {
for (int i = 0; i < num_octets; ++i) {
if (i > 0) out << ' ';
out << HEXBYTE << (value & 0xff);
value = value >> 8;
}
}
string slurp_until(istream& in, char delim) {
ostringstream out;
char c;
while (in >> c) {
if (c == delim) {
// drop the delim
break;
}
out << c;
}
return out.str();
}
string next_word(istream& in) {
skip_whitespace_and_comments(in);
string result;
in >> result;
return result;
}
void skip_whitespace_and_comments(istream& in) {
while (true) {
char c = in.peek();
if (isspace(c)) { in.get(); continue; }
else if (c == '#') skip_comment(in);
else return;
}
}
void skip_comment(istream& in) {
assert(in.peek() == '#');
char c = '\0';
do {
in >> c;
} while (c != '\n');
}
// helper
void transform(string/*copy*/ in) {
perform_all_transforms(in);
}
|