Division and Multiplication Semantics
[dyninst.git] / dataflowAPI / src / RoseInsnFactory.C
1 /*
2  * See the dyninst/COPYRIGHT file for copyright information.
3  * 
4  * We provide the Paradyn Tools (below described as "Paradyn")
5  * on an AS IS basis, and do not warrant its validity or performance.
6  * We reserve the right to update, modify, or discontinue this
7  * software at any time.  We shall have no obligation to supply such
8  * updates or modifications or any other form of support to you.
9  * 
10  * By your use of Paradyn, you understand and agree that we (or any
11  * other person or entity with proprietary rights in Paradyn) are
12  * under no obligation to provide either maintenance services,
13  * update services, notices of latent defects, or correction of
14  * defects for Paradyn.
15  * 
16  * This library is free software; you can redistribute it and/or
17  * modify it under the terms of the GNU Lesser General Public
18  * License as published by the Free Software Foundation; either
19  * version 2.1 of the License, or (at your option) any later version.
20  * 
21  * This library is distributed in the hope that it will be useful,
22  * but WITHOUT ANY WARRANTY; without even the implied warranty of
23  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
24  * Lesser General Public License for more details.
25  * 
26  * You should have received a copy of the GNU Lesser General Public
27  * License along with this library; if not, write to the Free Software
28  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
29  */
30 #include "RoseInsnFactory.h"
31 //#include "../rose/x86InstructionSemantics.h"
32 //#include "../rose/powerpcInstructionSemantics.h"
33
34 #include "Instruction.h"
35 #include "Operand.h"
36 #include "Expression.h"
37 #include "Dereference.h"
38 #include "Immediate.h"
39 #include <vector>
40
41 #include "../rose/SgAsmInstruction.h"
42 #include "../rose/SgAsmPowerpcInstruction.h"
43 #include "../rose/SgAsmx86Instruction.h"
44 #include "../rose/SgAsmExpression.h"
45
46 #include "ExpressionConversionVisitor.h"
47
48 using namespace Dyninst;
49 using namespace InstructionAPI;
50 using namespace DataflowAPI;
51
52 SgAsmInstruction *RoseInsnFactory::convert(const InstructionAPI::Instruction::Ptr &insn, uint64_t addr) {
53   SgAsmInstruction *rinsn = createInsn();
54   
55   rinsn->set_address(addr);
56   rinsn->set_mnemonic(insn->format());
57   setOpcode(rinsn, insn->getOperation().getID(), insn->getOperation().getPrefixID(), insn->getOperation().format());
58
59   // semantics don't support 64-bit code
60   setSizes(rinsn);
61
62   //rinsn->set_operandSize(x86_insnsize_32);
63   //rinsn->set_addressSize(x86_insnsize_32);
64   
65   std::vector<unsigned char> rawBytes;
66   for (unsigned i = 0; i < insn->size(); ++i) rawBytes.push_back(insn->rawByte(i));
67   rinsn->set_raw_bytes(rawBytes);
68   
69   // operand list
70   SgAsmOperandList *roperands = new SgAsmOperandList;
71   
72   // std::cerr << "Converting " << insn->format(addr) << " @" << std::hex << addr << std::dec << std::endl;
73   
74   // std::cerr << "checking instruction: " << insn->format(addr) << " for special handling" << std::endl;
75   if (handleSpecialCases(insn->getOperation().getID(), rinsn, roperands)) {
76       rinsn->set_operandList(roperands);
77       return rinsn;
78   }
79
80   // std::cerr << "no special handling by opcode, checking if we should mangle operands..." << std::endl;
81   std::vector<InstructionAPI::Operand> operands;
82   insn->getOperands(operands);
83 //  std::cerr << "\t " << operands.size() << " operands" << std::endl;
84   massageOperands(insn, operands);
85   int i = 0;
86 //  std::cerr << "converting insn " << insn->format(addr) << std::endl;
87   for (std::vector<InstructionAPI::Operand>::iterator opi = operands.begin();
88        opi != operands.end();
89        ++opi, ++i) {
90       InstructionAPI::Operand &currOperand = *opi;
91 //      std::cerr << "Converting operand " << currOperand.format(Arch_x86, addr) << std::endl;
92       roperands->append_operand(convertOperand(currOperand.getValue(), addr));
93   }  
94   rinsn->set_operandList(roperands);
95   return rinsn;
96 }
97
98 SgAsmExpression *RoseInsnFactory::convertOperand(const Expression::Ptr expression, uint64_t addr) {
99   if(!expression) return NULL;
100   ExpressionConversionVisitor visitor(arch(), addr);
101   expression->apply(&visitor);
102   return visitor.getRoseExpression();
103 }
104
105 ///////////// X86 //////////////////
106
107 SgAsmInstruction *RoseInsnX86Factory::createInsn() {
108   return new SgAsmx86Instruction;
109 }
110
111 // Note: convertKind is defined in convertOpcodes.C
112
113 void RoseInsnX86Factory::setOpcode(SgAsmInstruction *insn, entryID opcode, prefixEntryID prefix, std::string) {
114   SgAsmx86Instruction *tmp = static_cast<SgAsmx86Instruction *>(insn);
115   
116   tmp->set_kind(convertKind(opcode, prefix));
117 }
118
119 void RoseInsnX86Factory::setSizes(SgAsmInstruction *insn) {
120   // FIXME when we go 64-bit...
121   SgAsmx86Instruction *tmp = static_cast<SgAsmx86Instruction *>(insn);
122   tmp->set_operandSize(x86_insnsize_32);
123   tmp->set_addressSize(x86_insnsize_32);
124 }
125
126 bool RoseInsnX86Factory::handleSpecialCases(entryID, SgAsmInstruction *, SgAsmOperandList *) {
127   // Does nothing?
128
129   return false;
130 }
131
132 void RoseInsnX86Factory::massageOperands(const InstructionAPI::Instruction::Ptr &insn, 
133                                          std::vector<InstructionAPI::Operand> &operands) {
134   switch (insn->getOperation().getID()) {
135   case e_lea: {
136     // ROSE expects there to be a "memory reference" statement wrapping the
137     // address calculation. It then unwraps it. 
138     Dereference::Ptr tmp = Dereference::Ptr(new Dereference(operands[1].getValue(), u32));
139     operands[1] = Operand(tmp, operands[1].isRead(), operands[1].isWritten());
140     operands.resize(2);
141     break;  
142   }
143   case e_push:
144   case e_pop:
145     operands.resize(1);
146     break;
147   case e_cmpxch:
148     operands.resize(2);
149     break;
150   case e_movsb:
151   case e_movsd:
152   case e_movsw:
153     // No operands
154     operands.clear();
155     break;
156   case e_cmpsb:
157   case e_cmpsw:
158   case e_cmpsd:
159     // No operands
160     operands.clear();
161     break;
162   case e_scasb:
163   case e_scasd:
164   case e_scasw:
165     // Same here
166     operands.clear();
167     break;
168   case e_stosb:
169   case e_stosd:
170   case e_stosw:
171     // Also, no operands
172     operands.clear();
173     break;
174   case e_jcxz_jec:
175     operands.resize(1);
176     break;
177   case e_cbw:
178   case e_cwde:
179   case e_cdq:
180     // Nada
181     operands.clear();
182     break;
183   case e_popad:
184   case e_pushfd:
185     operands.clear();
186     break;
187   case e_lodsd:
188   case e_lodsb:
189   case e_lodsw:
190       operands.clear();
191       break;
192   case e_pushad:
193       operands.clear();
194       break;
195   case e_loop:
196   case e_loope:
197   case e_loopn:
198       operands.resize(1);
199       break;
200   case e_ret_far:
201   case e_ret_near:
202           if (operands.size() == 2) {
203                   operands[0]=operands[1];
204           }
205           operands.resize(1);
206           break;
207   case e_div:
208   case e_idiv:
209   case e_imul:
210   case e_mul:
211     // remove implicit operands.
212     if (operands.size() == 3) {
213       operands[0] = operands[2];
214       operands.resize(1);
215     }
216     break;
217   default:
218     break;
219   }
220 }
221
222
223 //////////// PPC ///////////////////
224 // Note: convertKind is defined in convertOpcodes.C
225
226 SgAsmInstruction *RoseInsnPPCFactory::createInsn() {
227   return new SgAsmPowerpcInstruction;
228 }
229
230 void RoseInsnPPCFactory::setOpcode(SgAsmInstruction *insn, entryID opcode, prefixEntryID /*prefix*/, std::string mnem) {
231   SgAsmPowerpcInstruction *tmp = static_cast<SgAsmPowerpcInstruction *>(insn);
232   kind = convertKind(opcode, mnem);
233   tmp->set_kind(kind);
234 }
235
236
237 void RoseInsnPPCFactory::setSizes(SgAsmInstruction *) {
238 }
239
240
241 bool RoseInsnPPCFactory::handleSpecialCases(entryID iapi_opcode, 
242                                             SgAsmInstruction *insn, 
243                                             SgAsmOperandList *rose_operands) {
244   SgAsmPowerpcInstruction *rose_insn = static_cast<SgAsmPowerpcInstruction *>(insn);
245
246   switch(iapi_opcode) {
247   case power_op_b:
248   case power_op_bc:
249   case power_op_bcctr:
250   case power_op_bclr: {
251     unsigned int raw = 0;
252     int branch_target = 0;
253     unsigned int bo = 0, bi = 0;
254     std::vector<unsigned char> bytes = rose_insn->get_raw_bytes();
255     for(unsigned i = 0; i < bytes.size(); i++) {
256       raw = raw << 8;
257       raw |= bytes[i];
258     }
259     bool isAbsolute = (bool)(raw & 0x00000002);
260     bool isLink = (bool)(raw & 0x00000001);
261     rose_insn->set_kind(makeRoseBranchOpcode(iapi_opcode, isAbsolute, isLink));
262     if(power_op_b == iapi_opcode) {
263       branch_target = ((raw >> 2) & 0x00FFFFFF) << 2;
264       branch_target = (branch_target << 8) >> 8;
265     } else {
266       if(power_op_bc == iapi_opcode) {
267         branch_target = ((raw >> 2) & 0x00003FFF) << 2;
268         branch_target = (branch_target << 18) >> 18;
269         //cerr << "14-bit branch target: " << branch_target << endl;
270       }
271       bo = ((raw >> 21) & 0x0000001F);
272       bi = ((raw >> 16) & 0x0000001F);
273       rose_operands->append_operand(new SgAsmByteValueExpression(bo));
274       rose_operands->append_operand(new SgAsmPowerpcRegisterReferenceExpression(powerpc_regclass_cr, bi,
275                                                                                 powerpc_condreggranularity_bit));
276     }
277     if(branch_target) {
278       rose_operands->append_operand(new SgAsmDoubleWordValueExpression(branch_target));
279     } else if(power_op_bcctr == iapi_opcode) {
280       rose_operands->append_operand(new SgAsmPowerpcRegisterReferenceExpression(powerpc_regclass_spr, powerpc_spr_ctr));
281     } else {
282       assert(power_op_bclr == iapi_opcode);
283       rose_operands->append_operand(new SgAsmPowerpcRegisterReferenceExpression(powerpc_regclass_spr, powerpc_spr_lr));
284     }
285     return true;
286   }
287     break;
288   case power_op_sc:
289   case power_op_svcs: {
290     //cerr << "special-casing syscall insn" << endl;
291     unsigned int raw = 0;
292     std::vector<unsigned char> bytes = rose_insn->get_raw_bytes();
293     for(unsigned i = 0; i < bytes.size(); i++) {
294       raw = raw << 8;
295       raw |= bytes[i];
296     }
297     unsigned int lev = (raw >> 5) & 0x7F;
298     rose_operands->append_operand(new SgAsmByteValueExpression(lev));
299     //cerr << "LEV = " << lev << endl;
300     return true;
301   }
302   default:
303     return false;
304   }
305   
306 }  
307
308 void RoseInsnPPCFactory::massageOperands(const InstructionAPI::Instruction::Ptr &insn, 
309                                          std::vector<InstructionAPI::Operand> &operands) {
310   /*
311   if(insn->writesMemory())
312     std::swap(operands[0], operands[1]);
313   */
314   entryID opcode = insn->getOperation().getID();
315   // Anything that's writing RA, ROSE expects in RA, RS, RB/immediates form.
316   // Any store, however, ROSE expects in RS, RA, RB/displacement form.  Very confusing,
317   // but we handle it cleanly here.
318   if(!operands[0].isWritten() && operands.size() >= 2 &&
319      operands[1].isWritten() && !operands[1].writesMemory()) {
320     //std::cerr << "swapping RS and RA in " << insn->format() << std::endl;
321     std::swap(operands[0], operands[1]);
322   }
323   if(opcode == power_op_cmp ||
324      opcode == power_op_cmpl ||
325      opcode == power_op_cmpi ||
326      opcode == power_op_cmpli) {
327     operands.push_back(Operand(Immediate::makeImmediate(Result(u8, 1)), false, false));
328     std::swap(operands[2], operands[3]);
329     std::swap(operands[1], operands[2]);
330   }
331   if(insn->getOperation().format().find(".") != std::string::npos &&
332      insn->getOperation().getID() != power_op_stwcx_rc) {
333     operands.pop_back();
334   }
335
336   // Convert to ROSE so we can use numeric greater than/less than
337
338   if(kind >= powerpc_lbz && kind <= powerpc_lwzx) {
339     operands.resize(2);
340   }
341   if(kind >= powerpc_stb && kind <= powerpc_stwx) {
342     operands.resize(2);
343   }
344
345   return;
346 }
347