The argument to SymEvalSemantics::addWithCarries for unsign-extending
[dyninst.git] / dataflowAPI / rose / semantics / SymEvalSemantics.C
1 //
2 // Created by ssunny on 7/1/16.
3 //
4
5 #include "SymEvalSemantics.h"
6
7 using namespace rose::BinaryAnalysis::InstructionSemantics2;
8
9 ///////////////////////////////////////////////////////
10 //                                           StateARM64
11 ///////////////////////////////////////////////////////
12
13 BaseSemantics::SValuePtr SymEvalSemantics::StateARM64::readRegister(const RegisterDescriptor &desc,
14                                                                     const BaseSemantics::SValuePtr &/*dflt*/, BaseSemantics::RiscOperators */*ops*/) {
15     ASSERT_require(desc.is_valid());
16     SymEvalSemantics::RegisterStateARM64Ptr registers = SymEvalSemantics::RegisterStateARM64::promote(registerState());
17     return registers->readRegister(desc, addr);
18 }
19
20 void SymEvalSemantics::StateARM64::writeRegister(const RegisterDescriptor &reg, const BaseSemantics::SValuePtr &value,
21                                                  BaseSemantics::RiscOperators */*ops*/) {
22     ASSERT_require(reg.is_valid());
23     ASSERT_not_null(value);
24     SymEvalSemantics::RegisterStateARM64Ptr registers = SymEvalSemantics::RegisterStateARM64::promote(registerState());
25     registers->writeRegister(reg, value, res, aaMap);
26 }
27
28 void SymEvalSemantics::StateARM64::writeMemory(const BaseSemantics::SValuePtr &addr,
29                                                const BaseSemantics::SValuePtr &value,
30                                                BaseSemantics::RiscOperators */*addrOps*/,
31                                                BaseSemantics::RiscOperators */*valOps*/) {
32     ASSERT_not_null(addr);
33     ASSERT_not_null(value);
34     SymEvalSemantics::MemoryStateARM64Ptr memory = SymEvalSemantics::MemoryStateARM64::promote(memoryState());
35     memory->writeMemory(addr, value, res, aaMap);
36 }
37
38 ///////////////////////////////////////////////////////
39 //                                   RegisterStateARM64
40 ///////////////////////////////////////////////////////
41
42 BaseSemantics::SValuePtr SymEvalSemantics::RegisterStateARM64::readRegister(const RegisterDescriptor &reg,
43                                                                             Dyninst::Address addr) {
44     if(reg.get_major() != armv8_regclass_simd_fpr) {
45         ARMv8GeneralPurposeRegister r = static_cast<ARMv8GeneralPurposeRegister>(reg.get_minor());
46         unsigned int size = reg.get_nbits();
47         return SymEvalSemantics::SValue::instance(wrap(convert(r, size), addr));
48     } else {
49         ASSERT_not_implemented("readRegister not yet implemented for categories other than GPR");
50     }
51 }
52
53 BaseSemantics::SValuePtr SymEvalSemantics::RegisterStateARM64::readRegister(const RegisterDescriptor &reg,
54                                                                             const BaseSemantics::SValuePtr &/*dflt*/,
55                                                                             BaseSemantics::RiscOperators */*ops*/) {
56     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.");
57 }
58
59 void SymEvalSemantics::RegisterStateARM64::writeRegister(const RegisterDescriptor &reg,
60                                                          const BaseSemantics::SValuePtr &value,
61                                                          Dyninst::DataflowAPI::Result_t &res,
62                                                          std::map<Dyninst::Absloc, Dyninst::Assignment::Ptr> &aaMap) {
63     if(reg.get_major() != armv8_regclass_simd_fpr) {
64         ARMv8GeneralPurposeRegister r = static_cast<ARMv8GeneralPurposeRegister>(reg.get_minor());
65
66         std::map<Dyninst::Absloc, Dyninst::Assignment::Ptr>::iterator i = aaMap.find(convert(r, reg.get_nbits()));
67         if (i != aaMap.end()) {
68             SymEvalSemantics::SValuePtr value_ = SymEvalSemantics::SValue::promote(value);
69             res[i->second] = value_->get_expression();
70         }
71     } else {
72         ASSERT_not_implemented("writeRegister not yet implemented for categories other than GPR");
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(ARMv8GeneralPurposeRegister r, unsigned int size) {
83     Dyninst::MachRegister mreg;
84
85     if(r != armv8_gpr_zr) {
86         mreg = (size == 32)?Dyninst::aarch64::wzr:Dyninst::aarch64::zr;
87     } else {
88         mreg = (size == 32)?Dyninst::aarch64::w0:Dyninst::aarch64::x0;
89         mreg = Dyninst::MachRegister(mreg.val() + (r - armv8_gpr_r0));
90     }
91
92     return Dyninst::Absloc(mreg);
93 }
94
95 ///////////////////////////////////////////////////////
96 //                                     MemoryStateARM64
97 ///////////////////////////////////////////////////////
98
99 //TODO: what is Len in this case?
100
101 BaseSemantics::SValuePtr SymEvalSemantics::MemoryStateARM64::readMemory(const BaseSemantics::SValuePtr &address,
102                                                                         const BaseSemantics::SValuePtr &/*dflt*/,
103                                                                         BaseSemantics::RiscOperators */*addrOps*/,
104                                                                         BaseSemantics::RiscOperators */*valOps*/) {
105     SymEvalSemantics::SValuePtr addr = SymEvalSemantics::SValue::promote(address);
106     return SymEvalSemantics::SValue::instance(Dyninst::DataflowAPI::RoseAST::create(Dyninst::DataflowAPI::ROSEOperation(Dyninst::DataflowAPI::ROSEOperation::derefOp),
107                                                  addr->get_expression(),
108                                                  Dyninst::DataflowAPI::ConstantAST::create(Dyninst::DataflowAPI::Constant(1, 1))));
109 }
110
111 void SymEvalSemantics::MemoryStateARM64::writeMemory(const BaseSemantics::SValuePtr &address,
112                                                      const BaseSemantics::SValuePtr &value,
113                                                      Dyninst::DataflowAPI::Result_t &res,
114                                                      std::map<Dyninst::Absloc, Dyninst::Assignment::Ptr> &aaMap) {
115     std::map<Dyninst::Absloc, Dyninst::Assignment::Ptr>::iterator i = aaMap.find(Dyninst::Absloc(0));
116     SymEvalSemantics::SValuePtr addr = SymEvalSemantics::SValue::promote(address);
117
118     if (i != aaMap.end()) {
119         i->second->out().setGenerator(addr->get_expression());
120         //i->second->out().setSize(Len);
121
122         SymEvalSemantics::SValuePtr data = SymEvalSemantics::SValue::promote(value);
123         res[i->second] = data->get_expression();
124     }
125 }
126
127 void SymEvalSemantics::MemoryStateARM64::writeMemory(const BaseSemantics::SValuePtr &/*addr*/,
128                                                      const BaseSemantics::SValuePtr &/*value*/,
129                                                      BaseSemantics::RiscOperators */*addrOps*/,
130                                                      BaseSemantics::RiscOperators */*valOps*/) {
131     ASSERT_always_forbid("overridden MemoryState::writeMemory() should never be called for ARM64, always use the non-virtual writeRegister that also takes additional parameters.");
132 }
133
134 ///////////////////////////////////////////////////////
135 //                                        RiscOperators
136 ///////////////////////////////////////////////////////
137
138 BaseSemantics::SValuePtr SymEvalSemantics::RiscOperatorsARM64::and_(const BaseSemantics::SValuePtr &a_,
139                                                                const BaseSemantics::SValuePtr &b_) {
140     return createBinaryAST(Dyninst::DataflowAPI::ROSEOperation::andOp, a_, b_);
141 }
142
143 BaseSemantics::SValuePtr SymEvalSemantics::RiscOperatorsARM64::or_(const BaseSemantics::SValuePtr &a_,
144                                                               const BaseSemantics::SValuePtr &b_) {
145     return createBinaryAST(Dyninst::DataflowAPI::ROSEOperation::orOp, a_, b_);
146 }
147
148 BaseSemantics::SValuePtr SymEvalSemantics::RiscOperatorsARM64::xor_(const BaseSemantics::SValuePtr &a_,
149                                                                const BaseSemantics::SValuePtr &b_) {
150     return createBinaryAST(Dyninst::DataflowAPI::ROSEOperation::xorOp, a_, b_);
151 }
152
153 BaseSemantics::SValuePtr SymEvalSemantics::RiscOperatorsARM64::invert(const BaseSemantics::SValuePtr &a_) {
154     return createUnaryAST(Dyninst::DataflowAPI::ROSEOperation::invertOp, a_);
155 }
156
157 BaseSemantics::SValuePtr SymEvalSemantics::RiscOperatorsARM64::extract(const BaseSemantics::SValuePtr &a_, size_t begin,
158                                                                   size_t end) {
159     BaseSemantics::SValuePtr begin_ = SymEvalSemantics::SValue::instance(64, begin);
160     BaseSemantics::SValuePtr end_ = SymEvalSemantics::SValue::instance(64, end);
161
162     return createTernaryAST(Dyninst::DataflowAPI::ROSEOperation::extractOp, a_, begin_, end_, end - begin);
163 }
164
165 BaseSemantics::SValuePtr SymEvalSemantics::RiscOperatorsARM64::ite(const BaseSemantics::SValuePtr &sel_,
166                                                               const BaseSemantics::SValuePtr &a_,
167                                                               const BaseSemantics::SValuePtr &b_) {
168     return createTernaryAST(Dyninst::DataflowAPI::ROSEOperation::ifOp, sel_, a_, b_);
169 }
170
171 BaseSemantics::SValuePtr SymEvalSemantics::RiscOperatorsARM64::concat(const BaseSemantics::SValuePtr &a_,
172                                                                  const BaseSemantics::SValuePtr &b_) {
173     //TODO: should be able to specify number of bits to concat for each expression
174     return createBinaryAST(Dyninst::DataflowAPI::ROSEOperation::concatOp, a_, b_);
175 }
176
177 BaseSemantics::SValuePtr SymEvalSemantics::RiscOperatorsARM64::leastSignificantSetBit(const BaseSemantics::SValuePtr &a_) {
178     return createUnaryAST(Dyninst::DataflowAPI::ROSEOperation::LSBSetOp, a_);
179 }
180
181 BaseSemantics::SValuePtr SymEvalSemantics::RiscOperatorsARM64::mostSignificantSetBit(const BaseSemantics::SValuePtr &a_) {
182     return createUnaryAST(Dyninst::DataflowAPI::ROSEOperation::MSBSetOp, a_);
183 }
184
185 BaseSemantics::SValuePtr SymEvalSemantics::RiscOperatorsARM64::rotateLeft(const BaseSemantics::SValuePtr &a_,
186                                                                      const BaseSemantics::SValuePtr &b_) {
187     return createBinaryAST(Dyninst::DataflowAPI::ROSEOperation::rotateLOp, a_, b_);
188 }
189
190 BaseSemantics::SValuePtr SymEvalSemantics::RiscOperatorsARM64::rotateRight(const BaseSemantics::SValuePtr &a_,
191                                                                       const BaseSemantics::SValuePtr &b_) {
192     return createBinaryAST(Dyninst::DataflowAPI::ROSEOperation::rotateROp, a_, b_);
193 }
194
195 BaseSemantics::SValuePtr SymEvalSemantics::RiscOperatorsARM64::shiftLeft(const BaseSemantics::SValuePtr &a_,
196                                                                     const BaseSemantics::SValuePtr &b_) {
197     return createBinaryAST(Dyninst::DataflowAPI::ROSEOperation::shiftLOp, a_, b_);
198 }
199
200 BaseSemantics::SValuePtr SymEvalSemantics::RiscOperatorsARM64::shiftRight(const BaseSemantics::SValuePtr &a_,
201                                                                      const BaseSemantics::SValuePtr &b_) {
202     return createBinaryAST(Dyninst::DataflowAPI::ROSEOperation::shiftROp, a_, b_);
203 }
204
205 BaseSemantics::SValuePtr SymEvalSemantics::RiscOperatorsARM64::shiftRightArithmetic(const BaseSemantics::SValuePtr &a_,
206                                                                                const BaseSemantics::SValuePtr &b_) {
207     return createBinaryAST(Dyninst::DataflowAPI::ROSEOperation::shiftRArithOp, a_, b_);
208 }
209
210 BaseSemantics::SValuePtr SymEvalSemantics::RiscOperatorsARM64::equalToZero(const BaseSemantics::SValuePtr &a_) {
211     return createUnaryAST(Dyninst::DataflowAPI::ROSEOperation::equalToZeroOp, a_);
212 }
213
214 BaseSemantics::SValuePtr SymEvalSemantics::RiscOperatorsARM64::signExtend(const BaseSemantics::SValuePtr &a_,
215                                                                      size_t newwidth) {
216     BaseSemantics::SValuePtr width_ = SymEvalSemantics::SValue::instance(64, newwidth);
217
218     return createBinaryAST(Dyninst::DataflowAPI::ROSEOperation::signExtendOp, a_, width_);
219 }
220
221 BaseSemantics::SValuePtr SymEvalSemantics::RiscOperatorsARM64::add(const BaseSemantics::SValuePtr &a_,
222                                                               const BaseSemantics::SValuePtr &b_) {
223     return createBinaryAST(Dyninst::DataflowAPI::ROSEOperation::addOp, a_, b_);
224 }
225
226 BaseSemantics::SValuePtr SymEvalSemantics::RiscOperatorsARM64::addWithCarries(const BaseSemantics::SValuePtr &a_,
227                                                                          const BaseSemantics::SValuePtr &b_,
228                                                                          const BaseSemantics::SValuePtr &c_,
229                                                                          BaseSemantics::SValuePtr &carry_out) {
230     BaseSemantics::SValuePtr aa_ = unsignedExtend(a_, a_->get_width() + 1);
231     BaseSemantics::SValuePtr bb_ = unsignedExtend(b_, b_->get_width() + 1);
232     BaseSemantics::SValuePtr sum_ = createBinaryAST(Dyninst::DataflowAPI::ROSEOperation::addOp, aa_,
233                                                     createBinaryAST(Dyninst::DataflowAPI::ROSEOperation::addOp, bb_, c_));
234
235     BaseSemantics::SValuePtr cc_ = createBinaryAST(Dyninst::DataflowAPI::ROSEOperation::xorOp, aa_,
236                                                    createBinaryAST(Dyninst::DataflowAPI::ROSEOperation::xorOp, bb_, sum_));
237     carry_out = extract(cc_, 1, a_->get_width() + 1);
238
239     return extract(sum_, 0, a_->get_width());
240 }
241
242 BaseSemantics::SValuePtr SymEvalSemantics::RiscOperatorsARM64::negate(const BaseSemantics::SValuePtr &a_) {
243     return createUnaryAST(Dyninst::DataflowAPI::ROSEOperation::negateOp, a_);
244 }
245
246 BaseSemantics::SValuePtr SymEvalSemantics::RiscOperatorsARM64::signedDivide(const BaseSemantics::SValuePtr &a_,
247                                                                        const BaseSemantics::SValuePtr &b_) {
248     return createBinaryAST(Dyninst::DataflowAPI::ROSEOperation::sDivOp, a_, b_);
249 }
250
251 BaseSemantics::SValuePtr SymEvalSemantics::RiscOperatorsARM64::signedModulo(const BaseSemantics::SValuePtr &a_,
252                                                                        const BaseSemantics::SValuePtr &b_) {
253     return createBinaryAST(Dyninst::DataflowAPI::ROSEOperation::sModOp, a_, b_);
254 }
255
256 BaseSemantics::SValuePtr SymEvalSemantics::RiscOperatorsARM64::signedMultiply(const BaseSemantics::SValuePtr &a_,
257                                                                          const BaseSemantics::SValuePtr &b_) {
258     return createBinaryAST(Dyninst::DataflowAPI::ROSEOperation::sMultOp, a_, b_);
259 }
260
261 BaseSemantics::SValuePtr SymEvalSemantics::RiscOperatorsARM64::unsignedDivide(const BaseSemantics::SValuePtr &a_,
262                                                                        const BaseSemantics::SValuePtr &b_) {
263     return createBinaryAST(Dyninst::DataflowAPI::ROSEOperation::uDivOp, a_, b_);
264 }
265
266 BaseSemantics::SValuePtr SymEvalSemantics::RiscOperatorsARM64::unsignedModulo(const BaseSemantics::SValuePtr &a_,
267                                                                        const BaseSemantics::SValuePtr &b_) {
268     return createBinaryAST(Dyninst::DataflowAPI::ROSEOperation::uModOp, a_, b_);
269 }
270
271 BaseSemantics::SValuePtr SymEvalSemantics::RiscOperatorsARM64::unsignedMultiply(const BaseSemantics::SValuePtr &a_,
272                                                                          const BaseSemantics::SValuePtr &b_) {
273     return createBinaryAST(Dyninst::DataflowAPI::ROSEOperation::uMultOp, a_, b_);
274 }
275
276 //TODO: do we deal with byte ordering?
277 BaseSemantics::SValuePtr SymEvalSemantics::RiscOperatorsARM64::readMemory(const RegisterDescriptor &/*segreg*/,
278                                                                      const BaseSemantics::SValuePtr &addr,
279                                                                      const BaseSemantics::SValuePtr &dflt,
280                                                                      const BaseSemantics::SValuePtr &/*cond*/) {
281     return currentState()->readMemory(addr, dflt, this, this);
282 }
283
284 void SymEvalSemantics::RiscOperatorsARM64::writeMemory(const RegisterDescriptor &/*segreg*/,
285                                                   const BaseSemantics::SValuePtr &addr,
286                                                   const BaseSemantics::SValuePtr &data,
287                                                   const BaseSemantics::SValuePtr &/*cond*/) {
288     currentState()->writeMemory(addr, data, this, this);
289 }