Added ability to convert the ARM64 SIMD/FP registers between ROSE(semantics) and...
[dyninst.git] / dataflowAPI / rose / semantics / SymEvalSemantics.C
1 //
2 // Created by ssunny on 7/1/16.
3 //
4
5 #include <Register.h>
6 #include "SymEvalSemantics.h"
7
8 using namespace rose::BinaryAnalysis::InstructionSemantics2;
9
10 ///////////////////////////////////////////////////////
11 //                                           StateARM64
12 ///////////////////////////////////////////////////////
13
14 BaseSemantics::SValuePtr SymEvalSemantics::StateARM64::readRegister(const RegisterDescriptor &desc,
15                                                                     const BaseSemantics::SValuePtr &/*dflt*/, BaseSemantics::RiscOperators */*ops*/) {
16     ASSERT_require(desc.is_valid());
17     SymEvalSemantics::RegisterStateARM64Ptr registers = SymEvalSemantics::RegisterStateARM64::promote(registerState());
18     return registers->readRegister(desc, addr);
19 }
20
21 void SymEvalSemantics::StateARM64::writeRegister(const RegisterDescriptor &reg, const BaseSemantics::SValuePtr &value,
22                                                  BaseSemantics::RiscOperators */*ops*/) {
23     ASSERT_require(reg.is_valid());
24     ASSERT_not_null(value);
25     SymEvalSemantics::RegisterStateARM64Ptr registers = SymEvalSemantics::RegisterStateARM64::promote(registerState());
26     registers->writeRegister(reg, value, res, aaMap);
27 }
28
29 BaseSemantics::SValuePtr SymEvalSemantics::StateARM64::readMemory(const BaseSemantics::SValuePtr &address,
30                                                                   const BaseSemantics::SValuePtr &/*dflt*/,
31                                                                   BaseSemantics::RiscOperators */*addrOps*/,
32                                                                   BaseSemantics::RiscOperators */*valOps*/,
33                                                                   size_t readSize) {
34     ASSERT_not_null(address);
35     SymEvalSemantics::MemoryStateARM64Ptr memory = SymEvalSemantics::MemoryStateARM64::promote(memoryState());
36     return memory->readMemory(address, readSize);
37 }
38
39 void SymEvalSemantics::StateARM64::writeMemory(const BaseSemantics::SValuePtr &addr,
40                                                const BaseSemantics::SValuePtr &value,
41                                                BaseSemantics::RiscOperators */*addrOps*/,
42                                                BaseSemantics::RiscOperators */*valOps*/,
43                                                size_t writeSize) {
44     ASSERT_not_null(addr);
45     ASSERT_not_null(value);
46     SymEvalSemantics::MemoryStateARM64Ptr memory = SymEvalSemantics::MemoryStateARM64::promote(memoryState());
47     memory->writeMemory(addr, value, res, aaMap, writeSize);
48 }
49
50 ///////////////////////////////////////////////////////
51 //                                   RegisterStateARM64
52 ///////////////////////////////////////////////////////
53
54 BaseSemantics::SValuePtr SymEvalSemantics::RegisterStateARM64::readRegister(const RegisterDescriptor &reg,
55                                                                             Dyninst::Address addr) {
56     return SymEvalSemantics::SValue::instance(wrap(convert(reg), addr));
57 }
58
59 BaseSemantics::SValuePtr SymEvalSemantics::RegisterStateARM64::readRegister(const RegisterDescriptor &reg,
60                                                                             const BaseSemantics::SValuePtr &/*dflt*/,
61                                                                             BaseSemantics::RiscOperators */*ops*/) {
62     ASSERT_always_forbid("overridden RegisterState::readRegister() should never be called for ARM64, always use the non-virtual readRegister that takes Dyninst::Address as an argument.");
63 }
64
65 void SymEvalSemantics::RegisterStateARM64::writeRegister(const RegisterDescriptor &reg,
66                                                          const BaseSemantics::SValuePtr &value,
67                                                          Dyninst::DataflowAPI::Result_t &res,
68                                                          std::map<Dyninst::Absloc, Dyninst::Assignment::Ptr> &aaMap) {
69     std::map<Dyninst::Absloc, Dyninst::Assignment::Ptr>::iterator i = aaMap.find(convert(reg));
70     if (i != aaMap.end()) {
71         SymEvalSemantics::SValuePtr value_ = SymEvalSemantics::SValue::promote(value);
72         res[i->second] = value_->get_expression();
73     }
74 }
75
76 void SymEvalSemantics::RegisterStateARM64::writeRegister(const RegisterDescriptor &/*reg*/,
77                                                          const BaseSemantics::SValuePtr &/*value*/,
78                                                          BaseSemantics::RiscOperators */*ops*/) {
79     ASSERT_always_forbid("overridden RegisterState::writeRegister() should never be called for ARM64, always use the non-virtual writeRegister that also takes additional parameters.");
80 }
81
82 Dyninst::Absloc SymEvalSemantics::RegisterStateARM64::convert(const RegisterDescriptor &reg) {
83     Dyninst::MachRegister mreg;
84
85     unsigned int major = reg.get_major();
86     unsigned int size = reg.get_nbits();
87
88     switch (major) {
89         case armv8_regclass_gpr: {
90             unsigned int minor = reg.get_minor();
91
92             if (minor == armv8_gpr_zr) {
93                 mreg = Dyninst::MachRegister((size == 32) ? Dyninst::aarch64::wzr : Dyninst::aarch64::zr);
94             } else {
95                 Dyninst::MachRegister base = (size == 32) ? Dyninst::aarch64::w0 : Dyninst::aarch64::x0;
96                 mreg = Dyninst::MachRegister(base.val() + (minor - armv8_gpr_r0));
97             }
98         }
99             break;
100         case armv8_regclass_simd_fpr: {
101             Dyninst::MachRegister base;
102             unsigned int minor = reg.get_minor();
103
104             switch(size) {
105                 case 8: base = Dyninst::aarch64::b0;
106                     break;
107                 case 16: base = Dyninst::aarch64::h0;
108                     break;
109                 case 32: base = Dyninst::aarch64::s0;
110                     break;
111                 case 64:
112                     if (reg.get_offset() == 64) {
113                         base = Dyninst::aarch64::hq0;
114                     } else {
115                         base = Dyninst::aarch64::d0;
116                     }
117                     break;
118                 case 128: base = Dyninst::aarch64::q0;
119                     break;
120                 default:assert(!"invalid size of RegisterDescriptor!");
121                     break;
122             }
123             mreg = Dyninst::MachRegister(base.val() + (minor - armv8_simdfpr_v0));
124         }
125             break;
126         case armv8_regclass_pc:
127             mreg = Dyninst::MachRegister(Dyninst::aarch64::pc);
128             break;
129         case armv8_regclass_sp:
130             mreg = Dyninst::MachRegister((size == 32) ? Dyninst::aarch64::wsp : Dyninst::aarch64::sp);
131             break;
132         case armv8_regclass_pstate: {
133             unsigned int offset = reg.get_offset();
134             switch (offset) {
135                 case armv8_pstatefield_n:
136                     mreg = Dyninst::MachRegister(Dyninst::aarch64::n);
137                     break;
138                 case armv8_pstatefield_z:
139                     mreg = Dyninst::MachRegister(Dyninst::aarch64::z);
140                     break;
141                 case armv8_pstatefield_c:
142                     mreg = Dyninst::MachRegister(Dyninst::aarch64::c);
143                     break;
144                 case armv8_pstatefield_v:
145                     mreg = Dyninst::MachRegister(Dyninst::aarch64::v);
146                     break;
147                 default:
148                     ASSERT_always_forbid("No part of the PSTATE register other than NZCV should be used.");
149                     break;
150             }
151         }
152             break;
153         default:
154             ASSERT_always_forbid("Unexpected register major type.");
155     }
156
157     return Dyninst::Absloc(mreg);
158 }
159
160 ///////////////////////////////////////////////////////
161 //                                     MemoryStateARM64
162 ///////////////////////////////////////////////////////
163
164 //TODO: what is Len in this case?
165
166 BaseSemantics::SValuePtr SymEvalSemantics::MemoryStateARM64::readMemory(const BaseSemantics::SValuePtr &address,
167                                                                         size_t readSize) {
168     SymEvalSemantics::SValuePtr addr = SymEvalSemantics::SValue::promote(address);
169     return SymEvalSemantics::SValue::instance(Dyninst::DataflowAPI::RoseAST::create(Dyninst::DataflowAPI::ROSEOperation(Dyninst::DataflowAPI::ROSEOperation::derefOp, readSize),
170                                                                                     addr->get_expression(),
171                                                                                     Dyninst::DataflowAPI::ConstantAST::create(Dyninst::DataflowAPI::Constant(1, 1))));
172 }
173
174 BaseSemantics::SValuePtr SymEvalSemantics::MemoryStateARM64::readMemory(const BaseSemantics::SValuePtr &address,
175                                                                         const BaseSemantics::SValuePtr &/*dflt*/,
176                                                                         BaseSemantics::RiscOperators */*addrOps*/,
177                                                                         BaseSemantics::RiscOperators */*valOps*/) {
178     ASSERT_always_forbid("overridden MemoryState::readMemory() should never be called for ARM64, always use the non-virtual readMemory that also takes additional parameters.");
179 }
180
181 void SymEvalSemantics::MemoryStateARM64::writeMemory(const BaseSemantics::SValuePtr &address,
182                                                      const BaseSemantics::SValuePtr &value,
183                                                      Dyninst::DataflowAPI::Result_t &res,
184                                                      std::map<Dyninst::Absloc, Dyninst::Assignment::Ptr> &aaMap,
185                                                      size_t writeSize) {
186     std::map<Dyninst::Absloc, Dyninst::Assignment::Ptr>::iterator i = aaMap.find(Dyninst::Absloc(0));
187     SymEvalSemantics::SValuePtr addr = SymEvalSemantics::SValue::promote(address);
188
189     if (i != aaMap.end()) {
190         i->second->out().setGenerator(addr->get_expression());
191         //i->second->out().setSize(Len);
192
193         SymEvalSemantics::SValuePtr data = SymEvalSemantics::SValue::promote(value);
194         res[i->second] = data->get_expression();
195     }
196 }
197
198 void SymEvalSemantics::MemoryStateARM64::writeMemory(const BaseSemantics::SValuePtr &/*addr*/,
199                                                      const BaseSemantics::SValuePtr &/*value*/,
200                                                      BaseSemantics::RiscOperators */*addrOps*/,
201                                                      BaseSemantics::RiscOperators */*valOps*/) {
202     ASSERT_always_forbid("overridden MemoryState::writeMemory() should never be called for ARM64, always use the non-virtual writeMemory that also takes additional parameters.");
203 }
204
205 ///////////////////////////////////////////////////////
206 //                                        RiscOperators
207 ///////////////////////////////////////////////////////
208
209 BaseSemantics::SValuePtr SymEvalSemantics::RiscOperatorsARM64::and_(const BaseSemantics::SValuePtr &a_,
210                                                                const BaseSemantics::SValuePtr &b_) {
211     return createBinaryAST(Dyninst::DataflowAPI::ROSEOperation::andOp, a_, b_);
212 }
213
214 BaseSemantics::SValuePtr SymEvalSemantics::RiscOperatorsARM64::or_(const BaseSemantics::SValuePtr &a_,
215                                                               const BaseSemantics::SValuePtr &b_) {
216     return createBinaryAST(Dyninst::DataflowAPI::ROSEOperation::orOp, a_, b_);
217 }
218
219 BaseSemantics::SValuePtr SymEvalSemantics::RiscOperatorsARM64::xor_(const BaseSemantics::SValuePtr &a_,
220                                                                const BaseSemantics::SValuePtr &b_) {
221     return createBinaryAST(Dyninst::DataflowAPI::ROSEOperation::xorOp, a_, b_);
222 }
223
224 BaseSemantics::SValuePtr SymEvalSemantics::RiscOperatorsARM64::invert(const BaseSemantics::SValuePtr &a_) {
225     return createUnaryAST(Dyninst::DataflowAPI::ROSEOperation::invertOp, a_);
226 }
227
228 BaseSemantics::SValuePtr SymEvalSemantics::RiscOperatorsARM64::extract(const BaseSemantics::SValuePtr &a_, size_t begin,
229                                                                   size_t end) {
230     BaseSemantics::SValuePtr begin_ = SymEvalSemantics::SValue::instance(64, begin);
231     BaseSemantics::SValuePtr end_ = SymEvalSemantics::SValue::instance(64, end);
232
233     return createTernaryAST(Dyninst::DataflowAPI::ROSEOperation::extractOp, a_, begin_, end_, end - begin);
234 }
235
236 BaseSemantics::SValuePtr SymEvalSemantics::RiscOperatorsARM64::ite(const BaseSemantics::SValuePtr &sel_,
237                                                               const BaseSemantics::SValuePtr &a_,
238                                                               const BaseSemantics::SValuePtr &b_) {
239     return createTernaryAST(Dyninst::DataflowAPI::ROSEOperation::ifOp, sel_, a_, b_);
240 }
241
242 BaseSemantics::SValuePtr SymEvalSemantics::RiscOperatorsARM64::concat(const BaseSemantics::SValuePtr &a_,
243                                                                  const BaseSemantics::SValuePtr &b_) {
244     //TODO: should be able to specify number of bits to concat for each expression
245     return createBinaryAST(Dyninst::DataflowAPI::ROSEOperation::concatOp, a_, b_);
246 }
247
248 BaseSemantics::SValuePtr SymEvalSemantics::RiscOperatorsARM64::leastSignificantSetBit(const BaseSemantics::SValuePtr &a_) {
249     return createUnaryAST(Dyninst::DataflowAPI::ROSEOperation::LSBSetOp, a_);
250 }
251
252 BaseSemantics::SValuePtr SymEvalSemantics::RiscOperatorsARM64::mostSignificantSetBit(const BaseSemantics::SValuePtr &a_) {
253     return createUnaryAST(Dyninst::DataflowAPI::ROSEOperation::MSBSetOp, a_);
254 }
255
256 BaseSemantics::SValuePtr SymEvalSemantics::RiscOperatorsARM64::rotateLeft(const BaseSemantics::SValuePtr &a_,
257                                                                      const BaseSemantics::SValuePtr &b_) {
258     return createBinaryAST(Dyninst::DataflowAPI::ROSEOperation::rotateLOp, a_, b_);
259 }
260
261 BaseSemantics::SValuePtr SymEvalSemantics::RiscOperatorsARM64::rotateRight(const BaseSemantics::SValuePtr &a_,
262                                                                       const BaseSemantics::SValuePtr &b_) {
263     return createBinaryAST(Dyninst::DataflowAPI::ROSEOperation::rotateROp, a_, b_);
264 }
265
266 BaseSemantics::SValuePtr SymEvalSemantics::RiscOperatorsARM64::shiftLeft(const BaseSemantics::SValuePtr &a_,
267                                                                     const BaseSemantics::SValuePtr &b_) {
268     return createBinaryAST(Dyninst::DataflowAPI::ROSEOperation::shiftLOp, a_, b_);
269 }
270
271 BaseSemantics::SValuePtr SymEvalSemantics::RiscOperatorsARM64::shiftRight(const BaseSemantics::SValuePtr &a_,
272                                                                      const BaseSemantics::SValuePtr &b_) {
273     return createBinaryAST(Dyninst::DataflowAPI::ROSEOperation::shiftROp, a_, b_);
274 }
275
276 BaseSemantics::SValuePtr SymEvalSemantics::RiscOperatorsARM64::shiftRightArithmetic(const BaseSemantics::SValuePtr &a_,
277                                                                                const BaseSemantics::SValuePtr &b_) {
278     return createBinaryAST(Dyninst::DataflowAPI::ROSEOperation::shiftRArithOp, a_, b_);
279 }
280
281 BaseSemantics::SValuePtr SymEvalSemantics::RiscOperatorsARM64::equalToZero(const BaseSemantics::SValuePtr &a_) {
282     return createUnaryAST(Dyninst::DataflowAPI::ROSEOperation::equalToZeroOp, a_);
283 }
284
285 BaseSemantics::SValuePtr SymEvalSemantics::RiscOperatorsARM64::signExtend(const BaseSemantics::SValuePtr &a_,
286                                                                      size_t newwidth) {
287     BaseSemantics::SValuePtr width_ = SymEvalSemantics::SValue::instance(64, newwidth);
288
289     return createBinaryAST(Dyninst::DataflowAPI::ROSEOperation::signExtendOp, a_, width_);
290 }
291
292 BaseSemantics::SValuePtr SymEvalSemantics::RiscOperatorsARM64::add(const BaseSemantics::SValuePtr &a_,
293                                                               const BaseSemantics::SValuePtr &b_) {
294     return createBinaryAST(Dyninst::DataflowAPI::ROSEOperation::addOp, a_, b_);
295 }
296
297 BaseSemantics::SValuePtr SymEvalSemantics::RiscOperatorsARM64::addWithCarries(const BaseSemantics::SValuePtr &a_,
298                                                                          const BaseSemantics::SValuePtr &b_,
299                                                                          const BaseSemantics::SValuePtr &c_,
300                                                                          BaseSemantics::SValuePtr &carry_out) {
301     BaseSemantics::SValuePtr aa_ = unsignedExtend(a_, a_->get_width() + 1);
302     BaseSemantics::SValuePtr bb_ = unsignedExtend(b_, b_->get_width() + 1);
303     BaseSemantics::SValuePtr sum_ = createBinaryAST(Dyninst::DataflowAPI::ROSEOperation::addOp, aa_,
304                                                     createBinaryAST(Dyninst::DataflowAPI::ROSEOperation::addOp, bb_, c_));
305
306     BaseSemantics::SValuePtr cc_ = createBinaryAST(Dyninst::DataflowAPI::ROSEOperation::xorOp, aa_,
307                                                    createBinaryAST(Dyninst::DataflowAPI::ROSEOperation::xorOp, bb_, sum_));
308     carry_out = extract(cc_, 1, a_->get_width() + 1);
309
310     return extract(sum_, 0, a_->get_width());
311 }
312
313 BaseSemantics::SValuePtr SymEvalSemantics::RiscOperatorsARM64::negate(const BaseSemantics::SValuePtr &a_) {
314     return createUnaryAST(Dyninst::DataflowAPI::ROSEOperation::negateOp, a_);
315 }
316
317 BaseSemantics::SValuePtr SymEvalSemantics::RiscOperatorsARM64::signedDivide(const BaseSemantics::SValuePtr &a_,
318                                                                        const BaseSemantics::SValuePtr &b_) {
319     return createBinaryAST(Dyninst::DataflowAPI::ROSEOperation::sDivOp, a_, b_);
320 }
321
322 BaseSemantics::SValuePtr SymEvalSemantics::RiscOperatorsARM64::signedModulo(const BaseSemantics::SValuePtr &a_,
323                                                                        const BaseSemantics::SValuePtr &b_) {
324     return createBinaryAST(Dyninst::DataflowAPI::ROSEOperation::sModOp, a_, b_);
325 }
326
327 BaseSemantics::SValuePtr SymEvalSemantics::RiscOperatorsARM64::signedMultiply(const BaseSemantics::SValuePtr &a_,
328                                                                          const BaseSemantics::SValuePtr &b_) {
329     return createBinaryAST(Dyninst::DataflowAPI::ROSEOperation::sMultOp, a_, b_);
330 }
331
332 BaseSemantics::SValuePtr SymEvalSemantics::RiscOperatorsARM64::unsignedDivide(const BaseSemantics::SValuePtr &a_,
333                                                                        const BaseSemantics::SValuePtr &b_) {
334     return createBinaryAST(Dyninst::DataflowAPI::ROSEOperation::uDivOp, a_, b_);
335 }
336
337 BaseSemantics::SValuePtr SymEvalSemantics::RiscOperatorsARM64::unsignedModulo(const BaseSemantics::SValuePtr &a_,
338                                                                        const BaseSemantics::SValuePtr &b_) {
339     return createBinaryAST(Dyninst::DataflowAPI::ROSEOperation::uModOp, a_, b_);
340 }
341
342 BaseSemantics::SValuePtr SymEvalSemantics::RiscOperatorsARM64::unsignedMultiply(const BaseSemantics::SValuePtr &a_,
343                                                                          const BaseSemantics::SValuePtr &b_) {
344     return createBinaryAST(Dyninst::DataflowAPI::ROSEOperation::uMultOp, a_, b_);
345 }
346
347 //TODO: do we deal with byte ordering?
348 BaseSemantics::SValuePtr SymEvalSemantics::RiscOperatorsARM64::readMemory(const RegisterDescriptor &/*segreg*/,
349                                                                      const BaseSemantics::SValuePtr &addr,
350                                                                      const BaseSemantics::SValuePtr &dflt,
351                                                                      const BaseSemantics::SValuePtr &/*cond*/) {
352     return currentState()->readMemory(addr, dflt, this, this);
353 }
354
355 void SymEvalSemantics::RiscOperatorsARM64::writeMemory(const RegisterDescriptor &/*segreg*/,
356                                                   const BaseSemantics::SValuePtr &addr,
357                                                   const BaseSemantics::SValuePtr &data,
358                                                   const BaseSemantics::SValuePtr &/*cond*/) {
359     currentState()->writeMemory(addr, data, this, this);
360 }