-
Notifications
You must be signed in to change notification settings - Fork 8
/
Copy pathisa.cpp
179 lines (134 loc) · 7.54 KB
/
isa.cpp
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
#include "isa.h"
using namespace z3;
// ====================================================================================================================
// ====================================================================================================================
void fmt_reg_reg(const int opcodeIdx, const int instrIdx, const EvalOperands& opers)
{
printf(" r%d = %s r%d r%d\n", instrIdx, ISA_OpName(opcodeIdx), opers.x, opers.y);
}
void fmt_reg_imm(const int opcodeIdx, const int instrIdx, const EvalOperands& opers)
{
printf(" r%d = %s r%d 0x%x\n", instrIdx, ISA_OpName(opcodeIdx), opers.x, opers.imm32);
}
void fmt_imm(const int opcodeIdx, const int instrIdx, const EvalOperands& opers)
{
printf(" r%d = %s 0x%x\n", instrIdx, ISA_OpName(opcodeIdx), opers.imm32);
}
// ====================================================================================================================
// ====================================================================================================================
expr sim_set(SimOperands& opers) { return opers.imm32; }
expr sim_add(SimOperands& opers) { return opers.x + opers.y; }
expr sim_sub(SimOperands& opers) { return opers.x - opers.y; }
expr sim_mul(SimOperands& opers) { return opers.x * opers.y; }
expr sim_xor(SimOperands& opers) { return opers.x ^ opers.y; }
expr sim_and(SimOperands& opers) { return opers.x & opers.y; }
expr sim_or (SimOperands& opers) { return opers.x | opers.y; }
expr sim_xor_not(SimOperands& opers) { return opers.x ^ (~opers.y); }
expr sim_and_not(SimOperands& opers) { return opers.x & ~opers.y; }
expr sim_or_not (SimOperands& opers) { return opers.x | ~opers.y; }
expr sim_shl(SimOperands& opers) { return to_expr(opers.ctx, Z3_mk_bvshl(opers.ctx, opers.x, opers.imm32)); }
expr sim_shr(SimOperands& opers) { return to_expr(opers.ctx, Z3_mk_bvashr(opers.ctx, opers.x, opers.imm32)); }
expr sim_gt(SimOperands& opers)
{
// a more complicated/powerful instruction: return either ~0 or 0 as the result of a comparison
// "ite" is if-then-else: if the comparison is true return ~0 else 0
return ite(opers.x > opers.y, opers.ctx.bv_val(0xffffffff, 32), opers.ctx.bv_val(0, 32));
}
// ====================================================================================================================
// ====================================================================================================================
ValueType eval_set(const EvalOperands& opers) { return opers.imm32; }
ValueType eval_add(const EvalOperands& opers) { return opers.x + opers.y; }
ValueType eval_sub(const EvalOperands& opers) { return opers.x - opers.y; }
ValueType eval_mul(const EvalOperands& opers) { return opers.x * opers.y; }
ValueType eval_xor(const EvalOperands& opers) { return opers.x ^ opers.y; }
ValueType eval_and(const EvalOperands& opers) { return opers.x & opers.y; }
ValueType eval_or (const EvalOperands& opers) { return opers.x | opers.y; }
ValueType eval_xor_not(const EvalOperands& opers) { return opers.x ^ (~opers.y); }
ValueType eval_and_not(const EvalOperands& opers) { return opers.x & ~opers.y; }
ValueType eval_or_not (const EvalOperands& opers) { return opers.x | ~opers.y; }
ValueType eval_shl(const EvalOperands& opers) { return opers.x << opers.imm32; }
ValueType eval_shr(const EvalOperands& opers) { return opers.x >> opers.imm32; }
// the C version is much simpler!
ValueType eval_gt(const EvalOperands& opers) { return opers.x > opers.y ? 0xffffffff : 0; }
// ====================================================================================================================
// ====================================================================================================================
static const Instruction ISA[] =
{
// rather than having multiple versions of each opcode with different operands
// a single opcode is implemented to allow an immediate value to be introduced
// into the instruction stream (this signficantly reduces the search space)
Instruction( "set", fmt_imm, sim_set, eval_set ),
Instruction( "add", fmt_reg_reg, sim_add, eval_add ),
Instruction( "sub", fmt_reg_reg, sim_sub, eval_sub ),
Instruction( "mul", fmt_reg_reg, sim_mul, eval_mul ),
Instruction( "xor", fmt_reg_reg, sim_xor, eval_xor ),
Instruction( "and", fmt_reg_reg, sim_and, eval_and ),
Instruction( "or" , fmt_reg_reg, sim_or, eval_or ),
Instruction( "xor_not", fmt_reg_reg, sim_xor_not, eval_xor_not ),
Instruction( "and_not", fmt_reg_reg, sim_and_not, eval_and_not ),
Instruction( "or_not" , fmt_reg_reg, sim_or_not, eval_or_not ),
Instruction( "shl", fmt_reg_imm, sim_shl, eval_shl, Instruction::Kind_Shift ),
Instruction( "shr", fmt_reg_imm, sim_shr, eval_shr, Instruction::Kind_Shift ),
Instruction( "gt", fmt_reg_reg, sim_gt, eval_gt ),
};
// ====================================================================================================================
// ====================================================================================================================
int ISA_NumOpCodes()
{
return sizeof(ISA) / sizeof(ISA[0]);
}
// ====================================================================================================================
// ====================================================================================================================
const char* ISA_OpName(const int opCode)
{
return ISA[opCode].name_;
}
// ====================================================================================================================
// ====================================================================================================================
int ISA_OpCodeForName(const char* name)
{
for (int i = 0; i < ISA_NumOpCodes(); i++)
{
if (strcmp(ISA[i].name_, name) == 0)
{
return i;
}
}
printf("Unknown opcode name: %s\n", name);
exit(1);
return -1;
}
// ====================================================================================================================
// ====================================================================================================================
void ISA_FormatOp(const int opcodeIdx, const int instrIdx, const EvalOperands& operands)
{
ISA[opcodeIdx].fmt_(opcodeIdx, instrIdx, operands);
}
// ====================================================================================================================
// ====================================================================================================================
z3::expr ISA_SimulateOp(const int opcodeIdx, SimOperands& operands)
{
return ISA[opcodeIdx].sim_(operands);
}
// ====================================================================================================================
// ====================================================================================================================
ValueType ISA_EvaluateOp(const int opcodeIdx, const EvalOperands& operands)
{
return ISA[opcodeIdx].eval_(operands);
}
// ====================================================================================================================
// ====================================================================================================================
std::vector<int> ISA_OpCodesForKindMask(const int kindMask)
{
std::vector<int> opCodes;
for (int idx = 0; idx < ISA_NumOpCodes(); idx++)
{
if (ISA[idx].kindMask & kindMask)
{
opCodes.push_back(idx);
}
}
return opCodes;
}
// ====================================================================================================================
// ====================================================================================================================