Added semantics for the following instructions:
[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     if(reg.get_major() != armv8_regclass_simd_fpr) {
57         ARMv8GeneralPurposeRegister r = static_cast<ARMv8GeneralPurposeRegister>(reg.get_minor());
58         unsigned int size = reg.get_nbits();
59         return SymEvalSemantics::SValue::instance(wrap(convert(reg), addr));
60     } else {
61         ASSERT_not_implemented("readRegister not yet implemented for categories other than GPR");
62     }
63 }
64
65 BaseSemantics::SValuePtr SymEvalSemantics::RegisterStateARM64::readRegister(const RegisterDescriptor &reg,
66                                                                             const BaseSemantics::SValuePtr &/*dflt*/,
67                                                                             BaseSemantics::RiscOperators */*ops*/) {
68     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.");
69 }
70
71 void SymEvalSemantics::RegisterStateARM64::writeRegister(const RegisterDescriptor &reg,
72                                                          const BaseSemantics::SValuePtr &value,
73                                                          Dyninst::DataflowAPI::Result_t &res,
74                                                          std::map<Dyninst::Absloc, Dyninst::Assignment::Ptr> &aaMap) {
75     if(reg.get_major() != armv8_regclass_simd_fpr) {
76         std::map<Dyninst::Absloc, Dyninst::Assignment::Ptr>::iterator i = aaMap.find(convert(reg));
77         if (i != aaMap.end()) {
78             SymEvalSemantics::SValuePtr value_ = SymEvalSemantics::SValue::promote(value);
79             res[i->second] = value_->get_expression();
80         }
81     } else {
82         ASSERT_not_implemented("writeRegister not yet implemented for categories other than GPR");
83     }
84 }
85
86 void SymEvalSemantics::RegisterStateARM64::writeRegister(const RegisterDescriptor &/*reg*/,
87                                                          const BaseSemantics::SValuePtr &/*value*/,
88                                                          BaseSemantics::RiscOperators */*ops*/) {
89     ASSERT_always_forbid("overridden RegisterState::writeRegister() should never be called for ARM64, always use the non-virtual writeRegister that also takes additional parameters.");
90 }
91
92 Dyninst::Absloc SymEvalSemantics::RegisterStateARM64::convert(const RegisterDescriptor &reg) {
93     Dyninst::MachRegister mreg;
94
95     unsigned int major = reg.get_major();
96     unsigned int size = reg.get_nbits();
97
98     switch (major) {
99         case armv8_regclass_gpr: {
100             unsigned int minor = reg.get_minor();
101
102             if (minor == armv8_gpr_zr) {
103                 mreg = Dyninst::MachRegister((size == 32) ? Dyninst::aarch64::wzr : Dyninst::aarch64::zr);
104             } else {
105                 Dyninst::MachRegister base = (size == 32) ? Dyninst::aarch64::w0 : Dyninst::aarch64::x0;
106                 mreg = Dyninst::MachRegister(base.val() + (minor - armv8_gpr_r0));
107             }
108         }
109             break;
110         case armv8_regclass_pc:
111             mreg = Dyninst::MachRegister(Dyninst::aarch64::pc);
112             break;
113         case armv8_regclass_sp:
114             mreg = Dyninst::MachRegister((size == 32) ? Dyninst::aarch64::wsp : Dyninst::aarch64::sp);
115             break;
116         case armv8_regclass_pstate: {
117             unsigned int offset = reg.get_offset();
118             if (offset == armv8_pstatefield_nzcv) {
119                 mreg = Dyninst::MachRegister(Dyninst::aarch64::pstate);
120             } else {
121                 ASSERT_always_forbid("No part of the PSTATE register other than NZCV should be used.");
122             }
123         }
124             break;
125         default:
126             ASSERT_always_forbid("Unexpected register major type.");
127     }
128
129     return Dyninst::Absloc(mreg);
130 }
131
132 ///////////////////////////////////////////////////////
133 //                                     MemoryStateARM64
134 ///////////////////////////////////////////////////////
135
136 //TODO: what is Len in this case?
137
138 BaseSemantics::SValuePtr SymEvalSemantics::MemoryStateARM64::readMemory(const BaseSemantics::SValuePtr &address,
139                                                                         size_t readSize) {
140     SymEvalSemantics::SValuePtr addr = SymEvalSemantics::SValue::promote(address);
141     return SymEvalSemantics::SValue::instance(Dyninst::DataflowAPI::RoseAST::create(Dyninst::DataflowAPI::ROSEOperation(Dyninst::DataflowAPI::ROSEOperation::derefOp, readSize),
142                                                                                     addr->get_expression(),
143                                                                                     Dyninst::DataflowAPI::ConstantAST::create(Dyninst::DataflowAPI::Constant(1, 1))));
144 }
145
146 BaseSemantics::SValuePtr SymEvalSemantics::MemoryStateARM64::readMemory(const BaseSemantics::SValuePtr &address,
147                                                                         const BaseSemantics::SValuePtr &/*dflt*/,
148                                                                         BaseSemantics::RiscOperators */*addrOps*/,
149                                                                         BaseSemantics::RiscOperators */*valOps*/) {
150     ASSERT_always_forbid("overridden MemoryState::readMemory() should never be called for ARM64, always use the non-virtual readMemory that also takes additional parameters.");
151 }
152
153 void SymEvalSemantics::MemoryStateARM64::writeMemory(const BaseSemantics::SValuePtr &address,
154                                                      const BaseSemantics::SValuePtr &value,
155                                                      Dyninst::DataflowAPI::Result_t &res,
156                                                      std::map<Dyninst::Absloc, Dyninst::Assignment::Ptr> &aaMap,
157                                                      size_t writeSize) {
158     std::map<Dyninst::Absloc, Dyninst::Assignment::Ptr>::iterator i = aaMap.find(Dyninst::Absloc(0));
159     SymEvalSemantics::SValuePtr addr = SymEvalSemantics::SValue::promote(address);
160
161     if (i != aaMap.end()) {
162         i->second->out().setGenerator(addr->get_expression());
163         //i->second->out().setSize(Len);
164
165         SymEvalSemantics::SValuePtr data = SymEvalSemantics::SValue::promote(value);
166         res[i->second] = data->get_expression();
167     }
168 }
169
170 void SymEvalSemantics::MemoryStateARM64::writeMemory(const BaseSemantics::SValuePtr &/*addr*/,
171                                                      const BaseSemantics::SValuePtr &/*value*/,
172                                                      BaseSemantics::RiscOperators */*addrOps*/,
173                                                      BaseSemantics::RiscOperators */*valOps*/) {
174     ASSERT_always_forbid("overridden MemoryState::writeMemory() should never be called for ARM64, always use the non-virtual writeMemory that also takes additional parameters.");
175 }
176
177 ///////////////////////////////////////////////////////
178 //                                        RiscOperators
179 ///////////////////////////////////////////////////////
180
181 BaseSemantics::SValuePtr SymEvalSemantics::RiscOperatorsARM64::and_(const BaseSemantics::SValuePtr &a_,
182                                                                const BaseSemantics::SValuePtr &b_) {
183     return createBinaryAST(Dyninst::DataflowAPI::ROSEOperation::andOp, a_, b_);
184 }
185
186 BaseSemantics::SValuePtr SymEvalSemantics::RiscOperatorsARM64::or_(const BaseSemantics::SValuePtr &a_,
187                                                               const BaseSemantics::SValuePtr &b_) {
188     return createBinaryAST(Dyninst::DataflowAPI::ROSEOperation::orOp, a_, b_);
189 }
190
191 BaseSemantics::SValuePtr SymEvalSemantics::RiscOperatorsARM64::xor_(const BaseSemantics::SValuePtr &a_,
192                                                                const BaseSemantics::SValuePtr &b_) {
193     return createBinaryAST(Dyninst::DataflowAPI::ROSEOperation::xorOp, a_, b_);
194 }
195
196 BaseSemantics::SValuePtr SymEvalSemantics::RiscOperatorsARM64::invert(const BaseSemantics::SValuePtr &a_) {
197     return createUnaryAST(Dyninst::DataflowAPI::ROSEOperation::invertOp, a_);
198 }
199
200 BaseSemantics::SValuePtr SymEvalSemantics::RiscOperatorsARM64::extract(const BaseSemantics::SValuePtr &a_, size_t begin,
201                                                                   size_t end) {
202     BaseSemantics::SValuePtr begin_ = SymEvalSemantics::SValue::instance(64, begin);
203     BaseSemantics::SValuePtr end_ = SymEvalSemantics::SValue::instance(64, end);
204
205     return createTernaryAST(Dyninst::DataflowAPI::ROSEOperation::extractOp, a_, begin_, end_, end - begin);
206 }
207
208 BaseSemantics::SValuePtr SymEvalSemantics::RiscOperatorsARM64::ite(const BaseSemantics::SValuePtr &sel_,
209                                                               const BaseSemantics::SValuePtr &a_,
210                                                               const BaseSemantics::SValuePtr &b_) {
211     return createTernaryAST(Dyninst::DataflowAPI::ROSEOperation::ifOp, sel_, a_, b_);
212 }
213
214 BaseSemantics::SValuePtr SymEvalSemantics::RiscOperatorsARM64::concat(const BaseSemantics::SValuePtr &a_,
215                                                                  const BaseSemantics::SValuePtr &b_) {
216     //TODO: should be able to specify number of bits to concat for each expression
217     return createBinaryAST(Dyninst::DataflowAPI::ROSEOperation::concatOp, a_, b_);
218 }
219
220 BaseSemantics::SValuePtr SymEvalSemantics::RiscOperatorsARM64::leastSignificantSetBit(const BaseSemantics::SValuePtr &a_) {
221     return createUnaryAST(Dyninst::DataflowAPI::ROSEOperation::LSBSetOp, a_);
222 }
223
224 BaseSemantics::SValuePtr SymEvalSemantics::RiscOperatorsARM64::mostSignificantSetBit(const BaseSemantics::SValuePtr &a_) {
225     return createUnaryAST(Dyninst::DataflowAPI::ROSEOperation::MSBSetOp, a_);
226 }
227
228 BaseSemantics::SValuePtr SymEvalSemantics::RiscOperatorsARM64::rotateLeft(const BaseSemantics::SValuePtr &a_,
229                                                                      const BaseSemantics::SValuePtr &b_) {
230     return createBinaryAST(Dyninst::DataflowAPI::ROSEOperation::rotateLOp, a_, b_);
231 }
232
233 BaseSemantics::SValuePtr SymEvalSemantics::RiscOperatorsARM64::rotateRight(const BaseSemantics::SValuePtr &a_,
234                                                                       const BaseSemantics::SValuePtr &b_) {
235     return createBinaryAST(Dyninst::DataflowAPI::ROSEOperation::rotateROp, a_, b_);
236 }
237
238 BaseSemantics::SValuePtr SymEvalSemantics::RiscOperatorsARM64::shiftLeft(const BaseSemantics::SValuePtr &a_,
239                                                                     const BaseSemantics::SValuePtr &b_) {
240     return createBinaryAST(Dyninst::DataflowAPI::ROSEOperation::shiftLOp, a_, b_);
241 }
242
243 BaseSemantics::SValuePtr SymEvalSemantics::RiscOperatorsARM64::shiftRight(const BaseSemantics::SValuePtr &a_,
244                                                                      const BaseSemantics::SValuePtr &b_) {
245     return createBinaryAST(Dyninst::DataflowAPI::ROSEOperation::shiftROp, a_, b_);
246 }
247
248 BaseSemantics::SValuePtr SymEvalSemantics::RiscOperatorsARM64::shiftRightArithmetic(const BaseSemantics::SValuePtr &a_,
249                                                                                const BaseSemantics::SValuePtr &b_) {
250     return createBinaryAST(Dyninst::DataflowAPI::ROSEOperation::shiftRArithOp, a_, b_);
251 }
252
253 BaseSemantics::SValuePtr SymEvalSemantics::RiscOperatorsARM64::equalToZero(const BaseSemantics::SValuePtr &a_) {
254     return createUnaryAST(Dyninst::DataflowAPI::ROSEOperation::equalToZeroOp, a_);
255 }
256
257 BaseSemantics::SValuePtr SymEvalSemantics::RiscOperatorsARM64::signExtend(const BaseSemantics::SValuePtr &a_,
258                                                                      size_t newwidth) {
259     BaseSemantics::SValuePtr width_ = SymEvalSemantics::SValue::instance(64, newwidth);
260
261     return createBinaryAST(Dyninst::DataflowAPI::ROSEOperation::signExtendOp, a_, width_);
262 }
263
264 BaseSemantics::SValuePtr SymEvalSemantics::RiscOperatorsARM64::add(const BaseSemantics::SValuePtr &a_,
265                                                               const BaseSemantics::SValuePtr &b_) {
266     return createBinaryAST(Dyninst::DataflowAPI::ROSEOperation::addOp, a_, b_);
267 }
268
269 BaseSemantics::SValuePtr SymEvalSemantics::RiscOperatorsARM64::addWithCarries(const BaseSemantics::SValuePtr &a_,
270                                                                          const BaseSemantics::SValuePtr &b_,
271                                                                          const BaseSemantics::SValuePtr &c_,
272                                                                          BaseSemantics::SValuePtr &carry_out) {
273     BaseSemantics::SValuePtr aa_ = unsignedExtend(a_, a_->get_width() + 1);
274     BaseSemantics::SValuePtr bb_ = unsignedExtend(a_, b_->get_width() + 1);
275     BaseSemantics::SValuePtr sum_ = createBinaryAST(Dyninst::DataflowAPI::ROSEOperation::addOp, aa_,
276                                                     createBinaryAST(Dyninst::DataflowAPI::ROSEOperation::addOp, bb_, c_));
277
278     BaseSemantics::SValuePtr cc_ = createBinaryAST(Dyninst::DataflowAPI::ROSEOperation::xorOp, aa_,
279                                                    createBinaryAST(Dyninst::DataflowAPI::ROSEOperation::xorOp, bb_, sum_));
280     carry_out = extract(cc_, 1, a_->get_width() + 1);
281
282     return extract(sum_, 0, a_->get_width());
283 }
284
285 BaseSemantics::SValuePtr SymEvalSemantics::RiscOperatorsARM64::negate(const BaseSemantics::SValuePtr &a_) {
286     return createUnaryAST(Dyninst::DataflowAPI::ROSEOperation::negateOp, a_);
287 }
288
289 BaseSemantics::SValuePtr SymEvalSemantics::RiscOperatorsARM64::signedDivide(const BaseSemantics::SValuePtr &a_,
290                                                                        const BaseSemantics::SValuePtr &b_) {
291     return createBinaryAST(Dyninst::DataflowAPI::ROSEOperation::sDivOp, a_, b_);
292 }
293
294 BaseSemantics::SValuePtr SymEvalSemantics::RiscOperatorsARM64::signedModulo(const BaseSemantics::SValuePtr &a_,
295                                                                        const BaseSemantics::SValuePtr &b_) {
296     return createBinaryAST(Dyninst::DataflowAPI::ROSEOperation::sModOp, a_, b_);
297 }
298
299 BaseSemantics::SValuePtr SymEvalSemantics::RiscOperatorsARM64::signedMultiply(const BaseSemantics::SValuePtr &a_,
300                                                                          const BaseSemantics::SValuePtr &b_) {
301     return createBinaryAST(Dyninst::DataflowAPI::ROSEOperation::sMultOp, a_, b_);
302 }
303
304 BaseSemantics::SValuePtr SymEvalSemantics::RiscOperatorsARM64::unsignedDivide(const BaseSemantics::SValuePtr &a_,
305                                                                        const BaseSemantics::SValuePtr &b_) {
306     return createBinaryAST(Dyninst::DataflowAPI::ROSEOperation::uDivOp, a_, b_);
307 }
308
309 BaseSemantics::SValuePtr SymEvalSemantics::RiscOperatorsARM64::unsignedModulo(const BaseSemantics::SValuePtr &a_,
310                                                                        const BaseSemantics::SValuePtr &b_) {
311     return createBinaryAST(Dyninst::DataflowAPI::ROSEOperation::uModOp, a_, b_);
312 }
313
314 BaseSemantics::SValuePtr SymEvalSemantics::RiscOperatorsARM64::unsignedMultiply(const BaseSemantics::SValuePtr &a_,
315                                                                          const BaseSemantics::SValuePtr &b_) {
316     return createBinaryAST(Dyninst::DataflowAPI::ROSEOperation::uMultOp, a_, b_);
317 }
318
319 //TODO: do we deal with byte ordering?
320 BaseSemantics::SValuePtr SymEvalSemantics::RiscOperatorsARM64::readMemory(const RegisterDescriptor &/*segreg*/,
321                                                                      const BaseSemantics::SValuePtr &addr,
322                                                                      const BaseSemantics::SValuePtr &dflt,
323                                                                      const BaseSemantics::SValuePtr &/*cond*/) {
324     return currentState()->readMemory(addr, dflt, this, this);
325 }
326
327 void SymEvalSemantics::RiscOperatorsARM64::writeMemory(const RegisterDescriptor &/*segreg*/,
328                                                   const BaseSemantics::SValuePtr &addr,
329                                                   const BaseSemantics::SValuePtr &data,
330                                                   const BaseSemantics::SValuePtr &/*cond*/) {
331     currentState()->writeMemory(addr, data, this, this);
332 }