forked from facebook/hermes
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathInstDecode.cpp
More file actions
195 lines (168 loc) · 6.6 KB
/
InstDecode.cpp
File metadata and controls
195 lines (168 loc) · 6.6 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
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#include "hermes/Inst/InstDecode.h"
#include "hermes/Support/Conversions.h"
#include "llvh/Support/Format.h"
#include "llvh/Support/raw_ostream.h"
namespace hermes {
namespace inst {
/// Store the structure of each opcode: size, number of operands and their
/// types.
static const struct {
/// Size of the entire instruction in bytes.
uint8_t size;
/// Number of operands.
uint8_t numOperands;
/// The type of each operand.
OperandType operandType[INST_MAX_OPERANDS];
} meta[] = {
#define DEFINE_OPCODE_0(name) {sizeof(inst::name##Inst), 0, {}},
#define DEFINE_OPCODE_1(name, t1) \
{sizeof(inst::name##Inst), 1, {OperandType::t1}},
#define DEFINE_OPCODE_2(name, t1, t2) \
{sizeof(inst::name##Inst), 2, {OperandType::t1, OperandType::t2}},
#define DEFINE_OPCODE_3(name, t1, t2, t3) \
{sizeof(inst::name##Inst), \
3, \
{OperandType::t1, OperandType::t2, OperandType::t3}},
#define DEFINE_OPCODE_4(name, t1, t2, t3, t4) \
{sizeof(inst::name##Inst), \
4, \
{OperandType::t1, OperandType::t2, OperandType::t3, OperandType::t4}},
#define DEFINE_OPCODE_5(name, t1, t2, t3, t4, t5) \
{sizeof(inst::name##Inst), \
5, \
{OperandType::t1, \
OperandType::t2, \
OperandType::t3, \
OperandType::t4, \
OperandType::t5}},
#define DEFINE_OPCODE_6(name, t1, t2, t3, t4, t5, t6) \
{sizeof(inst::name##Inst), \
6, \
{OperandType::t1, \
OperandType::t2, \
OperandType::t3, \
OperandType::t4, \
OperandType::t5, \
OperandType::t6}},
#include "hermes/BCGen/HBC/BytecodeList.def"
};
InstMetaData getInstMetaData(OpCode opCode) {
assert(opCode < OpCode::_last && "invalid OpCode");
const auto *pm = meta + (int)opCode;
InstMetaData res;
res.opCode = opCode;
res.size = pm->size;
res.numOperands = pm->numOperands;
std::copy(
pm->operandType, pm->operandType + pm->numOperands, res.operandType);
return res;
}
uint8_t getInstSize(OpCode opCode) {
assert(opCode < OpCode::_last && "invalid OpCode");
return meta[(int)opCode].size;
}
uint8_t getOperandSize(OperandType type) {
#define DEFINE_OPERAND_TYPE(name, ctype) \
case OperandType::name: \
return sizeof(ctype);
switch (type) {
#include "hermes/BCGen/HBC/BytecodeList.def"
}
llvm_unreachable("Invalid operand type");
}
DecodedInstruction decodeInstruction(const Inst *inst) {
DecodedInstruction decoded;
decoded.meta = getInstMetaData(inst->opCode);
switch (inst->opCode) {
#define DEFINE_OPCODE_0(name) \
case OpCode::name: \
break;
#define DEFINE_OPCODE_1(name, op1type) \
case OpCode::name: \
decoded.operandValue[0].set(inst->i##name.op1); \
break;
#define DEFINE_OPCODE_2(name, op1type, op2type) \
case OpCode::name: \
decoded.operandValue[0].set(inst->i##name.op1); \
decoded.operandValue[1].set(inst->i##name.op2); \
break;
#define DEFINE_OPCODE_3(name, op1type, op2type, op3type) \
case OpCode::name: \
decoded.operandValue[0].set(inst->i##name.op1); \
decoded.operandValue[1].set(inst->i##name.op2); \
decoded.operandValue[2].set(inst->i##name.op3); \
break;
#define DEFINE_OPCODE_4(name, op1type, op2type, op3type, op4type) \
case OpCode::name: \
decoded.operandValue[0].set(inst->i##name.op1); \
decoded.operandValue[1].set(inst->i##name.op2); \
decoded.operandValue[2].set(inst->i##name.op3); \
decoded.operandValue[3].set(inst->i##name.op4); \
break;
#define DEFINE_OPCODE_5(name, op1type, op2type, op3type, op4type, op5type) \
case OpCode::name: \
decoded.operandValue[0].set(inst->i##name.op1); \
decoded.operandValue[1].set(inst->i##name.op2); \
decoded.operandValue[2].set(inst->i##name.op3); \
decoded.operandValue[3].set(inst->i##name.op4); \
decoded.operandValue[4].set(inst->i##name.op5); \
break;
#define DEFINE_OPCODE_6( \
name, op1type, op2type, op3type, op4type, op5type, op6type) \
case OpCode::name: \
decoded.operandValue[0].set(inst->i##name.op1); \
decoded.operandValue[1].set(inst->i##name.op2); \
decoded.operandValue[2].set(inst->i##name.op3); \
decoded.operandValue[3].set(inst->i##name.op4); \
decoded.operandValue[4].set(inst->i##name.op5); \
decoded.operandValue[5].set(inst->i##name.op6); \
break;
#include "hermes/BCGen/HBC/BytecodeList.def"
default:
llvm_unreachable("invalid instruction");
}
return decoded;
}
void dumpOperand(llvh::raw_ostream &OS, OperandType type, OperandValue value) {
switch (type) {
case OperandType::Reg8:
case OperandType::Reg32:
OS << "r" << value.integer;
break;
case OperandType::UInt8:
case OperandType::UInt16:
case OperandType::UInt32:
OS << "$" << value.integer;
break;
case OperandType::Addr8:
case OperandType::Addr32:
OS << "@" << value.integer;
break;
case OperandType::Imm32:
OS << value.integer;
break;
case OperandType::Double:
char buf[NUMBER_TO_STRING_BUF_SIZE];
hermes::numberToString(value.floating, buf, sizeof(buf));
OS << buf;
break;
}
}
llvh::raw_ostream &operator<<(
llvh::raw_ostream &OS,
const DecodedInstruction &decoded) {
OS << llvh::left_justify(getOpCodeString(decoded.meta.opCode), 17);
for (unsigned i = 0; i < decoded.meta.numOperands; ++i) {
OS << (i == 0 ? " " : ", ");
dumpOperand(OS, decoded.meta.operandType[i], decoded.operandValue[i]);
}
return OS;
}
} // namespace inst
} // namespace hermes