* Bugfix: InstrucIter no longer used for int_function iteration.
[dyninst.git] / dyninstAPI / src / InstrucIter-x86.C
1 /*
2  * Copyright (c) 1996-2004 Barton P. Miller
3  * 
4  * We provide the Paradyn Parallel Performance Tools (below
5  * described as "Paradyn") on an AS IS basis, and do not warrant its
6  * validity or performance.  We reserve the right to update, modify,
7  * or discontinue this software at any time.  We shall have no
8  * obligation to supply such updates or modifications or any other
9  * form of support to you.
10  * 
11  * This license is for research uses.  For such uses, there is no
12  * charge. We define "research use" to mean you may freely use it
13  * inside your organization for whatever purposes you see fit. But you
14  * may not re-distribute Paradyn or parts of Paradyn, in any form
15  * source or binary (including derivatives), electronic or otherwise,
16  * to any other organization or entity without our permission.
17  * 
18  * (for other uses, please contact us at paradyn@cs.wisc.edu)
19  * 
20  * All warranties, including without limitation, any warranty of
21  * merchantability or fitness for a particular purpose, are hereby
22  * excluded.
23  * 
24  * By your use of Paradyn, you understand and agree that we (or any
25  * other person or entity with proprietary rights in Paradyn) are
26  * under no obligation to provide either maintenance services,
27  * update services, notices of latent defects, or correction of
28  * defects for Paradyn.
29  * 
30  * Even if advised of the possibility of such damages, under no
31  * circumstances shall we (or any other person or entity with
32  * proprietary rights in the software licensed hereunder) be liable
33  * to you or any third party for direct, indirect, or consequential
34  * damages of any character regardless of type of action, including,
35  * without limitation, loss of profits, loss of use, loss of good
36  * will, or computer failure or malfunction.  You agree to indemnify
37  * us (and any other person or entity with proprietary rights in the
38  * software licensed hereunder) for any and all liability it may
39  * incur to third parties resulting from your use of Paradyn.
40  */
41
42 #include <stdio.h>
43 #include <stdlib.h>
44 #include <assert.h>
45 #include <string.h>
46 #include "boost/assign/list_of.hpp"
47 #include <set>
48
49 #include "common/h/Types.h"
50 #include "common/h/Vector.h"
51 #include "common/h/Dictionary.h"
52
53 #include "arch.h"
54 #include "arch-x86.h"
55 #include "util.h"
56 #include "process.h"
57 #include "symtab.h"
58 #include "instPoint.h"
59 #include "InstrucIter.h"
60 #include "inst-x86.h"
61
62 #include "BPatch_Set.h"
63 #include <common/h/Annotatable.h>
64
65 #include "BPatch_instruction.h"
66 #include "BPatch_memoryAccess_NP.h"
67
68 //some more function used to identify the properties of the instruction
69 /**  the instruction used to return from the functions
70  * @param i the instruction value 
71  */
72 bool InstrucIter::isALeaveInstruction()
73 {
74   assert(instPtr);
75   return getInstruction().isLeave();
76 }
77
78 bool InstrucIter::isAReturnInstruction()
79 {
80   assert(instPtr);
81   return getInstruction().isReturn();
82 }
83
84 /** is the instruction used to return from the functions,
85     dependent upon a condition register
86     * @param i the instruction value 
87     */
88 bool InstrucIter::isACondReturnInstruction()
89 {
90   return false; // Not implemented yet
91 }
92
93 /** is the instruction an indirect jump instruction 
94  * @param i the instruction value 
95  */
96
97 bool InstrucIter::isAIndirectJumpInstruction()
98 {
99   assert(instPtr);
100   if((getInstruction().type() & IS_JUMP) && (getInstruction().type() & INDIR))
101   {
102     /* since there are two is_jump and indirect instructions
103        we are looking for the one with the indirect register
104        addressing mode one of which ModR/M contains 4 in its
105        reg/opcode field */
106     const unsigned char* ptr = getInstruction().op_ptr();
107     assert(*ptr == 0xff);
108     ptr++;
109     if((*ptr & 0x38) == 0x20) 
110       return true;
111   }
112   return false;
113 }
114
115 bool InstrucIter::isStackFramePreamble(int & /*unused*/)
116 {
117   instruction i = getInstruction();
118   return ::isStackFramePreamble( i );
119 }
120
121 bool InstrucIter::isFramePush()
122 {
123   assert(instPtr);
124   // test for
125   // push %ebp (or push %rbp for 64-bit)
126   return (getInstruction().size() == 1 && getInstruction().ptr()[0] == 0x55);
127 }
128
129 bool InstrucIter::isFrameSetup()
130 {
131   assert(instPtr);
132   //test for
133   // movl %esp,%ebp
134
135   // 64-bit:
136   // movq %rsp, %rbp
137
138   if (!ia32_is_mode_64()) {
139     return (getInstruction().size() == 2 && 
140             getInstruction().ptr()[0] == 0x89 && getInstruction().ptr()[1] == 0xe5);
141   }
142   else {
143     return (getInstruction().size() == 3 &&
144             getInstruction().ptr()[0] == 0x48 &&
145             getInstruction().ptr()[1] == 0x89 &&
146             getInstruction().ptr()[2] == 0xe5);
147   }
148 }
149
150 /** is the instruction a conditional branch instruction 
151  * @param i the instruction value 
152  */ 
153 bool InstrucIter::isACondBranchInstruction()
154 {
155   assert(instPtr);
156   if(getInstruction().type() & IS_JCC)
157     return true;
158   return false;
159 }
160
161 /** is the instruction an unconditional branch instruction 
162  * @param i the instruction value 
163  */
164 bool InstrucIter::isAJumpInstruction()
165 {
166   assert(instPtr);
167   getInstruction().setInstruction( (unsigned char *)instPtr );
168   if((getInstruction().type() & IS_JUMP) &&
169      !(getInstruction().type() & INDIR) && 
170      !(getInstruction().type() & PTR_WX))
171     return true;
172   return false;
173 }
174
175 /** is the instruction a call instruction 
176  * @param i the instruction value 
177  */
178 bool InstrucIter::isACallInstruction()
179 {
180   assert(instPtr);
181   return getInstruction().isCall();
182 }
183
184 bool InstrucIter::isADynamicCallInstruction()
185 {
186   assert(instPtr);
187   return getInstruction().isCall() && getInstruction().isIndir();
188 }
189
190 bool InstrucIter::isSyscall() {
191     assert(instPtr);
192     return getInstruction().isSysCallInsn();
193 }
194
195 bool InstrucIter::isANopInstruction()
196 {
197   assert(instPtr);
198   return getInstruction().isNop();
199 }
200
201 bool InstrucIter::isAnAbortInstruction()
202 {
203   assert(instPtr);
204   const unsigned char *ptr = getInstruction().op_ptr();
205
206   // FIXME this all needs to be more general!
207   // hlt
208   return(*ptr == 0xf4 || getInstruction().isIllegal());
209 }
210
211 bool InstrucIter::isAnAllocInstruction()
212 {
213   return false;
214 }
215
216 bool InstrucIter::isAnneal()
217 {
218   return true;
219 }
220
221 bool InstrucIter::isDelaySlot()
222 {
223   return false;
224 }
225
226 /** function which returns the offset of control transfer instructions
227  * @param i the instruction value 
228  */
229 Address InstrucIter::getBranchTargetOffset()
230 {
231   assert(instPtr);
232   // getTarget returns displacement+address parameter
233   return getInstruction().getTarget(0);
234 }
235
236 Address InstrucIter::getBranchTargetAddress(bool *)
237 {
238   assert(instPtr);
239   return getInstruction().getTarget(current);
240 }
241
242 void initOpCodeInfo()
243 {
244 }
245
246 BPatch_memoryAccess* InstrucIter::isLoadOrStore()
247 {
248   assert(instPtr);
249   static unsigned int log2[] = { 0, 0, 1, 1, 2, 2, 2, 2, 3 };
250     
251   // TODO 16-bit registers
252     
253   int nac = 0;
254     
255   ia32_memacc mac[3];
256   ia32_condition cnd;
257   ia32_instruction i(mac, &cnd);
258     
259   const unsigned char* addr = getInstruction().ptr();
260   BPatch_memoryAccess* bmap = BPatch_memoryAccess::none;
261     
262   ia32_decode(IA32_DECODE_MEMACCESS|IA32_DECODE_CONDITION, addr, i);
263   
264   bool first = true;
265
266   for(int j=0; j<3; ++j) {
267     ia32_memacc& mac = const_cast<ia32_memacc&>(i.getMac(j));
268     const ia32_condition& cond = i.getCond();
269     int bmapcond = cond.is ? cond.tttn : -1;
270     if(mac.is) {
271
272       // here, we can set the correct address for RIP-relative addressing
273       if (mac.regs[0] == mRIP) {
274         mac.imm = peekNext() + mac.imm;
275       }
276
277       if(first) {
278         if(mac.prefetch) {
279           if(mac.prefetchlvl > 0) // Intel
280             bmap = new BPatch_memoryAccess(getInsnPtr(), current,
281                                            false, false,
282                                            mac.imm, mac.regs[0], mac.regs[1], mac.scale,
283                                            0, -1, -1, 0,
284                                            bmapcond, false, mac.prefetchlvl);
285           else // AMD
286             bmap = new BPatch_memoryAccess(getInsnPtr(), current,
287                                            false, false,
288                                            mac.imm, mac.regs[0], mac.regs[1], mac.scale,
289                                            0, -1, -1, 0,
290                                            bmapcond, false, mac.prefetchstt + IA32AMDprefetch);
291         }
292         else switch(mac.sizehack) { // translation to pseudoregisters
293         case 0:
294           bmap = new BPatch_memoryAccess(getInsnPtr(), current,
295                                          mac.read, mac.write,
296                                          mac.size, mac.imm, mac.regs[0], mac.regs[1], mac.scale, 
297                                          bmapcond, mac.nt);
298           break;
299         case shREP: // use ECX register to compute final size as mac.size * ECX
300           bmap = new BPatch_memoryAccess(getInsnPtr(), current,
301                                          mac.read, mac.write,
302                                          mac.imm, mac.regs[0], mac.regs[1], mac.scale,
303                                          0, -1, 1 , log2[mac.size],
304                                          bmapcond, false);
305           break;
306         case shREPESCAS:
307           bmap = new BPatch_memoryAccess(getInsnPtr(), current,
308                                          mac.read, mac.write,
309                                          mac.imm, mac.regs[0], mac.regs[1], mac.scale,
310                                          0, -1, IA32_ESCAS, log2[mac.size],
311                                          bmapcond, false);
312           break;
313         case shREPNESCAS:
314           bmap = new BPatch_memoryAccess(getInsnPtr(), current,
315                                          mac.read, mac.write,
316                                          mac.imm, mac.regs[0], mac.regs[1], mac.scale,
317                                          0, -1, IA32_NESCAS, log2[mac.size],
318                                          bmapcond, false);
319           break;
320         case shREPECMPS:
321           bmap = new BPatch_memoryAccess(getInsnPtr(), current,
322                                          mac.read, mac.write,
323                                          mac.imm, mac.regs[0], mac.regs[1], mac.scale,
324                                          0, -1, IA32_ECMPS, log2[mac.size],
325                                          bmapcond, false);
326           break;
327         case shREPNECMPS:
328           bmap = new BPatch_memoryAccess(getInsnPtr(), current,
329                                          mac.read, mac.write,
330                                          mac.imm, mac.regs[0], mac.regs[1], mac.scale,
331                                          0, -1, IA32_NECMPS, log2[mac.size],
332                                          bmapcond, false);
333           break;
334         default:
335           assert(!"Unknown size hack");
336         }
337         first = false;
338       }
339       else
340         switch(mac.sizehack) { // translation to pseudoregisters
341         case 0:
342           bmap->set2nd(mac.read, mac.write, mac.size, mac.imm,
343                        mac.regs[0], mac.regs[1], mac.scale);
344           break;
345         case shREP: // use ECX register to compute final size as mac.size * ECX
346           bmap->set2nd(mac.read, mac.write,
347                        mac.imm, mac.regs[0], mac.regs[1], mac.scale,
348                        0, -1, 1 , log2[mac.size],
349                        bmapcond, false);
350           break;
351         case shREPESCAS:
352         case shREPNESCAS:
353           assert(!"Cannot happen");
354           break;
355         case shREPECMPS:
356           bmap->set2nd(mac.read, mac.write,
357                        mac.imm, mac.regs[0], mac.regs[1], mac.scale,
358                        0, -1, IA32_ECMPS, log2[mac.size],
359                        bmapcond, false);
360           break;
361         case shREPNECMPS:
362           //fprintf(stderr, "In set2nd[shREPNECMPS]!!!\n");
363           bmap->set2nd(mac.read, mac.write,
364                        mac.imm, mac.regs[0], mac.regs[1], mac.scale,
365                        0, -1, IA32_NECMPS, log2[mac.size],
366                        bmapcond, false);
367           break;
368         default:
369           assert(!"Unknown size hack");
370         }
371       ++nac;
372     }
373   }
374   assert(nac < 3);
375   return bmap;
376 }
377
378 // return target addresses from a jump table
379 // tableInsn - instruction that load address of table entry into a register,
380 //             the displacement will give us the table's base address
381 // maxSwitchInsn - compare instrction that does a range check on the
382 //                 jump table index, gives us number of entries in immediate
383 // branchInsn - the branch instruction, which we need for the condition code
384 //              that will help us avoid off-by-one errors in our target
385 //              calculation
386 bool InstrucIter::getMultipleJumpTargets(BPatch_Set<Address>& result,
387                                          instruction& tableInsn, 
388                                          instruction& maxSwitchInsn,
389                                          instruction& branchInsn,
390                                          bool isAddressInJmp )
391
392   int addrWidth;
393   if(!instructions_)
394   {
395     fprintf(stderr, "InstrucIter::getMultipleJumpTargets() called on invalid iter (no instruction source)\n");
396     assert(instructions_);
397   }
398   
399   addrWidth = instructions_->getAddressWidth();
400
401   Address backupAddress = current;
402     
403   unsigned maxSwitch = 0;
404
405   ia32_prefixes pref;
406   const unsigned char* ptr = skip_headers(maxSwitchInsn.ptr(), &pref);
407   bool isWordAddr = pref.getAddrSzPrefix();
408   bool isWordOp = pref.getOperSzPrefix();
409     
410   //get the imm value from the compare instruction and store it in 
411   //maxSwitch
412   if( *ptr == 0x3d )
413   {
414     ptr++;
415     if(isWordOp)
416     {
417       maxSwitch |= *(ptr+1);
418       maxSwitch <<= 8;
419       maxSwitch |= *ptr;
420     }
421     else
422       maxSwitch = *(const unsigned*)ptr;
423   }
424   else if( *ptr == 0x3c )
425   {
426     ptr++;
427     maxSwitch = *ptr;
428   }
429   else if( *ptr == 0x83 || *ptr == 0x80 || *ptr == 0x81 ) 
430   {
431     ptr++;
432     if((*ptr & 0x38) == 0x38)
433     {
434       unsigned modRM = *ptr;
435       unsigned Mod,Reg,RM;
436       bool hasSIB = insn_hasSIB(modRM,Mod,Reg,RM);
437       ptr++;
438       if(hasSIB)
439         ptr++;
440       if ( insn_hasDisp8(modRM) ) 
441       {
442         ptr++;
443       }
444       else if( insn_hasDisp32( modRM ) )
445       {
446         ptr += 4;
447       }
448       maxSwitch = *ptr;
449     }
450   }
451     
452   if( !maxSwitch )
453   {
454     result += backupAddress;    
455     return false;
456   }
457
458   parsing_printf("maxSwitch set to %d\n",maxSwitch);
459
460   const unsigned char * p = branchInsn.op_ptr();
461   if( *p == 0x0f ) {
462     // skip to second byte of opcode
463     p++;
464   }
465   // Test whether we have a ja or jg; if so, we want to add one to
466   // the switch index. The Portland Group compiler generally uses jge,
467   // so the value is an accurate count of the entries in the jump table,
468   // while gcc uses ja, so the value is one less than the number of entries
469   // in the table. *This is assuming the jump table is indexed from zero,
470   // which is the only type of jump table we can currently handle*.
471   //
472   // Fact: we really should be testing whether this is an upper bound
473   // before even getting into this code.
474   if( (*p & 0x0f) == 0x07 || (*p & 0x0f) == 0x0f ) {
475     maxSwitch++;
476   } 
477     
478   Address jumpTable = 0;
479   ptr = tableInsn.op_ptr();
480
481   if(isAddressInJmp || (!isAddressInJmp && (*ptr == 0x8b)))
482   {
483     ptr++;
484
485     if(
486        ( ((*ptr & 0xc7) == 0x04) &&
487          ( ((*(ptr+1) & 0xc7) == 0x85) || ((*(ptr+1) & 0xc7) == 0xc5) ) ) ||
488        ((*ptr & 0xc7) == 0x80) )
489     {
490       if((*ptr & 0xc7) == 0x80)
491         ptr += 1;
492       else
493         ptr += 2;
494             
495       if(isWordAddr) {
496         jumpTable |= *(ptr+1);
497         jumpTable <<= 8;
498         jumpTable |= *ptr;
499         //fprintf(stderr,"okay... %lx\n",jumpTable);
500
501       } else {
502         jumpTable = *(const int *)ptr;
503       }
504     }
505   }
506
507   if(!jumpTable)
508   {
509     result += backupAddress;    
510     return false;
511   }
512   else if( !instructions_->isValidAddress(jumpTable) )
513   {
514     // If the "jump table" has a start address that is outside
515     // of the valid range of the binary, we can say with high
516     // probability that we have misinterpreted some other
517     // construct (such as a function pointer comparison & tail
518     // call, for example) as a jump table. Give up now.
519     result += backupAddress;
520     return false;
521   }
522
523   for(unsigned int i=0;i<maxSwitch;i++)
524   {
525     Address tableEntry = jumpTable + (i * addrWidth);
526     int jumpAddress = 0;
527     if(instructions_->isValidAddress(tableEntry))
528     {
529       if(addrWidth == sizeof(Address))
530       {
531         jumpAddress = *(const Address *)instructions_->getPtrToInstruction(tableEntry);
532       }
533       else
534       {
535         jumpAddress = *(const int *)instructions_->getPtrToInstruction(tableEntry);
536       }
537     }
538     if (jumpAddress)
539       result += jumpAddress;
540   }
541   return true;
542 }
543
544 bool InstrucIter::delayInstructionSupported()
545 {
546   return false;
547 }
548
549 Address InstrucIter::peekPrev()
550 {
551   if (prevInsns.size()) {
552     return prevInsns.back().first;
553   }
554   else 
555     return 0;
556 }
557
558 Address InstrucIter::peekNext() {
559   assert(instPtr);
560   Address tmp = current;
561   tmp += getInstruction().size();
562   return tmp;
563 }
564
565 void InstrucIter::setCurrentAddress(Address addr)
566 {
567   // Make sure the new addr is aligned
568   // This is unsafe if we're looking at anything more than a basic block;
569   // best-effort.
570   if (current < addr) {
571     while (current != addr) {
572       if (current > addr) {
573         // We missed; oops.
574         current = addr;
575         break;
576       }
577       assert(current < addr);
578
579       // Copied from ++(*this) - it was making copies and thus slow.
580       prevInsns.push_back(std::make_pair(current, instPtr));
581       current = peekNext();
582       initializeInsn();
583     }
584   }
585   else if (current > addr) {
586     while (current != addr) {
587       if (current < addr) {
588         current = addr;
589         break;
590       }
591       // See above
592       if(hasPrev()) {
593           //assert(instructions_ && instructions_->isValidAddress(peekPrev()));
594           current = peekPrev();
595           instPtr = prevInsns.back().second;
596           prevInsns.pop_back();
597       }
598       
599     }
600   }
601   initializeInsn();
602 }
603
604 #if defined(i386_unknown_linux2_0) \
605  || defined(x86_64_unknown_linux2_4) /* Blind duplication - Ray */ \
606  || defined(i386_unknown_nt4_0)
607 bool InstrucIter::isInstruction()
608 {
609   return false;
610 }
611 #endif
612
613 instruction InstrucIter::getInstruction()
614 {
615   return insn;
616 }
617
618 instruction *InstrucIter::getInsnPtr() {
619   instruction *insnPtr = new instruction(insn);
620   return insnPtr;
621 }
622
623 bool operandIsRead(int opsema, int operand)
624 {
625   switch(operand)
626   {
627   case 0:
628     return opsema == s1R || opsema == s1RW || opsema == s1R2R ||
629     opsema == s1RW2R || opsema == s1RW2RW || opsema == s1RW2R3R ||
630     opsema == s1RW2RW3R;
631   case 1:
632     return opsema == s1R2R || opsema == s1W2R || opsema == s1RW2R ||
633     opsema == s1RW2RW || opsema == s1W2R3R || opsema == s1RW2R3R ||
634     opsema == s1RW2RW3R || opsema == s1W2RW3R || opsema == s1W2R3RW;
635   case 2:
636     return opsema == s1W2R3R || opsema == s1W2W3R || opsema == s1W2RW3R ||
637     opsema == s1W2R3RW || opsema == s1RW2R3R || opsema == s1RW2RW3R;
638   default:
639     return false;
640   };
641 }
642
643 bool operandIsWritten(int opsema, int operand)
644 {
645   switch(operand)
646   {
647   case 0:
648     return opsema == s1W || opsema == s1RW || opsema == s1W2R ||
649     opsema == s1RW2R || opsema == s1RW2RW || opsema == s1W2R3R || 
650     opsema == s1W2W3R || opsema == s1RW2R3R || opsema == s1RW2RW3R ||
651     opsema == s1W2RW3R || opsema == s1W2R3R;
652   case 1:
653     return opsema == s1RW2RW || opsema == s1W2W3R || opsema == s1W2RW3R ||
654     opsema == s1RW2RW3R;
655   case 2:
656     return opsema == s1W2R3RW;
657   default:
658     return false;
659   };
660 }
661 static RegisterID IntelRegTable[][8] = {
662   {
663     r_AL, r_CL, r_DL, r_BL, r_AH, r_CH, r_DH, r_BH
664   },
665   {
666     r_AX, r_eCX, r_DX, r_eBX, r_eSP, r_eBP, r_eSI, r_eDI
667   },
668   {
669     r_EAX, r_ECX, r_EDX, r_EBX, r_ESP, r_EBP, r_ESI, r_EDI
670   },
671   {
672     r_ES, r_CS, r_SS, r_DS, r_FS, r_GS, r_Reserved, r_Reserved
673   },
674   {
675     r_R8, r_R9, r_R10, r_R11, r_R12, r_R13, r_R14, r_R15
676   }
677   
678 };
679
680 RegisterID makeRegisterID(unsigned int intelReg, unsigned int opType, bool is64bitMode, bool isExtendedRegister)
681 {
682   if(is64bitMode && isExtendedRegister)
683   {
684     return IntelRegTable[4][intelReg];
685   }
686   
687   switch(opType)
688   {
689   case op_b:
690     // since we're doing this for liveness, up-cast to 32-bit registers
691     //    return IntelRegTable[0][intelReg];
692     {
693       if(intelReg < 4 || is64bitMode)
694       {
695         return IntelRegTable[2][intelReg];
696       }
697       else
698       {
699         return IntelRegTable[2][intelReg - 4];
700       }
701     }
702     
703   case op_d:
704   case op_si:
705   case op_w:
706   default:
707     return IntelRegTable[2][intelReg];
708     break;
709   }
710 }
711
712 const unsigned int modrm_use_sib = 0x04;
713 const unsigned int sib_base_only = 0x04;
714
715 void addSIBRegisters(std::set<RegisterID>& regs, const ia32_locations& locs, unsigned int opType)
716 {
717   unsigned scale;
718   Register index, base;
719   decode_SIB(locs.sib_byte, scale, index, base);
720   regs.insert(makeRegisterID(base, opType, locs.rex_byte, locs.rex_b));
721   if(index != sib_base_only)
722   {
723     regs.insert(makeRegisterID(index, opType, locs.rex_byte, locs.rex_x));
724   }
725 }
726
727
728 void addModRMRegisters(std::set<RegisterID>& regs, const ia32_locations& locs, unsigned int opType)
729 {
730   if(locs.modrm_rm != modrm_use_sib)
731   {
732     regs.insert(makeRegisterID(locs.modrm_rm, opType, locs.rex_byte, locs.rex_b));
733   }
734   else
735   {
736     addSIBRegisters(regs, locs, opType);
737   }
738 }
739
740
741 void parseRegisters(std::set<RegisterID>& readArray, std::set<RegisterID>& writeArray,
742                     ia32_instruction& ii, int opsema)
743 {
744   ia32_entry * entry = ii.getEntry();
745   const ia32_locations& locs(ii.getLocationInfo());
746   if(!entry) return;
747   for(int i = 0; i < 3; ++i)
748   {
749     ia32_operand operand = entry->operands[i];
750     bool isRead = operandIsRead(opsema, i);
751     bool isWritten = operandIsWritten(opsema, i);
752     switch(operand.admet)
753     {
754       // mod r/m byte addressing, mod and r/m fields
755     case am_E:
756       switch(locs.modrm_mod)
757       {
758         // modrm_mod is a 2-bit value.  We know that in the 00, 01, and 10 cases, am_E
759         // will dereference whatever modrm_mod and modrm_rm dictate, and in the 11 case
760         // it will directly access the register they determine.  Therefore, we treat the other
761         // three cases as read-only regardless of whether the memory is read/written.
762       case 0x03:
763         if(isRead) 
764         {
765           readArray.insert(makeRegisterID(locs.modrm_rm, operand.optype, locs.rex_byte, locs.rex_r));
766         } 
767         if(isWritten)
768         {
769           writeArray.insert(makeRegisterID(locs.modrm_rm, operand.optype, locs.rex_byte, locs.rex_r));
770         }
771         break;
772       default:
773         addModRMRegisters(readArray, locs, operand.optype);
774       };
775       break;
776       // mod r/m byte, reg field, general register
777     case am_G:
778       if(isRead) 
779       {
780         readArray.insert(makeRegisterID(locs.modrm_reg, operand.optype, locs.rex_byte, locs.rex_r));
781       }
782       if(isWritten)
783       {
784         writeArray.insert(makeRegisterID(locs.modrm_reg, operand.optype, locs.rex_byte, locs.rex_r));
785       }
786       break;
787       // same as am_E, except that we ignore the mod field and assume it's 11b
788     case am_M:
789         // mod r/m must refer to memory
790         // so it must have a mod field of 0, 1, or 2
791         // and it will only read the registers used in the effective address calcs
792         switch(locs.modrm_mod) {
793         case 0x03:
794             // technically a can't happen, but don't assert because some punk can
795             // do unnatural things
796             break;
797         default:
798             addModRMRegisters(readArray, locs, operand.optype);
799             break;
800         }
801         break;
802     case am_R:
803       if(isRead) 
804       {
805         readArray.insert(makeRegisterID(locs.modrm_rm, operand.optype, locs.rex_byte, locs.rex_b));
806       } 
807       if(isWritten)
808       {
809         writeArray.insert(makeRegisterID(locs.modrm_rm, operand.optype, locs.rex_byte, locs.rex_b));
810       }
811       break;
812     case am_S:
813       // segment register in modRM reg field
814       if(isRead) 
815       {
816         if(locs.rex_r)
817         {
818           readArray.insert(IntelRegTable[4][locs.modrm_reg]);
819         }
820         else
821         {
822           readArray.insert(IntelRegTable[3][locs.modrm_reg]);
823         }
824       }
825       if(isWritten) 
826       {
827         if(locs.rex_r)
828         {
829           writeArray.insert(IntelRegTable[4][locs.modrm_reg]);
830         }
831         else
832         {
833           writeArray.insert(IntelRegTable[3][locs.modrm_reg]);
834         }
835       }
836       break;
837     case am_W:
838         // This could be memory as per the mod r/m byte.  We want to do the same thing as the
839         // am_E case, except that if it comes back with "register" we don't care
840         // as the FP saves are still done all-or-nothing.
841         switch(locs.modrm_mod) {
842         case 0x03:
843             // working directly with a floating point register
844             break;
845         default:
846             // we read anything that's used in the effective address calcs
847             addModRMRegisters(readArray, locs, operand.optype);
848             break;
849         };
850         break;
851     case am_X:
852       // memory addressed by DS:SI, so we read those regardless of semantics
853       readArray.insert(r_DS);
854       readArray.insert(r_ESI);
855       break;
856     case am_Y:
857       // memory addressed by ES:DI, so again read those regardless of operand semantics
858       readArray.insert(r_ES);
859       readArray.insert(r_EDI);
860       break;
861     case am_reg:
862       if(isRead) 
863       {
864         readArray.insert(RegisterID(operand.optype));
865       }
866       if(isWritten)
867       {
868         writeArray.insert(RegisterID(operand.optype));
869       }
870       break;
871     default:
872       // do nothing
873       break;
874     };
875   }
876 }
877
878
879 Address InstrucIter::getCallTarget()
880 {
881   return getInstruction().getTarget(current);
882 }
883
884
885 bool InstrucIter::isFPWrite()
886 {
887   instruction i = getInstruction();
888   ia32_instruction ii;
889   
890   const unsigned char * addr = i.ptr();
891        
892   ia32_decode(0, addr,ii);    
893   ia32_entry * entry = ii.getEntry();
894
895   assert(entry != NULL);
896   
897   /* X87 Floating Point Operations ... we don't care about the specifics */
898   if (entry->otable == t_coprocEsc)
899     return true;
900
901   for ( int a = 0; a <  3; a++)
902   {
903     if (entry->operands[a].admet == am_P || /*64-bit MMX selected by ModRM reg field */
904         entry->operands[a].admet == am_Q || /*64-bit MMX selected by ModRM byte */
905         entry->operands[a].admet == am_V || /*128-bit XMM selected by ModRM reg field*/
906         entry->operands[a].admet == am_W )  /*128-bit XMM selected by ModRM byte */
907     {
908       return true;
909     }
910   }
911   return false;
912 }
913
914 #define FPOS 16
915 void InstrucIter::readWriteRegisters(int* readRegs, int* writeRegs)
916 {
917   // deprecating this; use getAllRegistersUsedAndDefined instead
918   // start with doing nothing, then we'll go around removing it and converting the call sites and stuff
919   //assert(0);
920 }
921
922 using namespace boost::assign;
923
924 map<RegisterID, Register> reverseRegisterLookup = map_list_of
925 (r_EAX, REGNUM_RAX)
926     (r_ECX, REGNUM_RCX)
927     (r_EDX, REGNUM_RDX)
928     (r_EBX, REGNUM_RBX)
929     (r_ESP, REGNUM_RSP)
930     (r_EBP, REGNUM_RBP)
931     (r_ESI, REGNUM_RSI)
932     (r_EDI, REGNUM_RDI)
933     (r_R8, REGNUM_R8)
934     (r_R9, REGNUM_R9)
935     (r_R10, REGNUM_R10)
936     (r_R11, REGNUM_R11)
937     (r_R12, REGNUM_R12)
938     (r_R13, REGNUM_R13)
939     (r_R14, REGNUM_R14)
940     (r_R15, REGNUM_R15)
941     (r_DummyFPR, REGNUM_DUMMYFPR)
942     (r_OF, REGNUM_OF)
943     (r_SF, REGNUM_SF)
944     (r_ZF, REGNUM_ZF)
945     (r_AF, REGNUM_AF)
946     (r_PF, REGNUM_PF)
947     (r_CF, REGNUM_CF)
948     (r_TF, REGNUM_TF)
949     (r_IF, REGNUM_IF)
950     (r_DF, REGNUM_DF)
951     (r_NT, REGNUM_NT)
952     (r_RF, REGNUM_RF)
953     (r_AH, REGNUM_RAX)
954     (r_BH, REGNUM_RBX)
955     (r_CH, REGNUM_RCX)
956     (r_DH, REGNUM_RDX)
957     (r_AL, REGNUM_RAX)
958     (r_BL, REGNUM_RBX)
959     (r_CL, REGNUM_RCX)
960     (r_DL, REGNUM_RDX)
961     (r_eAX, REGNUM_RAX)
962     (r_eBX, REGNUM_RBX)
963     (r_eCX, REGNUM_RCX)
964     (r_eDX, REGNUM_RDX)
965     (r_AX, REGNUM_RAX)
966     (r_DX, REGNUM_RDX)
967     (r_eSP, REGNUM_RSP)
968     (r_eBP, REGNUM_RBP)
969     (r_eSI, REGNUM_RSI)
970     (r_eDI, REGNUM_RDI)
971     // These are wrong, need to extend to make cmpxch8b work right
972     (r_EDXEAX, REGNUM_RAX)
973     (r_ECXEBX, REGNUM_RCX)
974     (r_CS, REGNUM_IGNORED)
975     (r_DS, REGNUM_IGNORED)
976     (r_ES, REGNUM_IGNORED)
977     (r_FS, REGNUM_IGNORED)
978     (r_GS, REGNUM_IGNORED)
979     (r_SS, REGNUM_IGNORED)
980 ;
981
982 Register dummyConverter(RegisterID toBeConverted)
983 {
984     map<RegisterID, Register>::const_iterator found = 
985         reverseRegisterLookup.find(toBeConverted);
986     if(found == reverseRegisterLookup.end()) {
987         fprintf(stderr, "Register ID %d not found in reverseRegisterLookup!\n", toBeConverted);
988         assert(!"Bad register ID");
989     }
990     return found->second;
991 }
992
993 void InstrucIter::getAllRegistersUsedAndDefined(std::set<Register> &used, 
994                                                 std::set<Register> &defined)
995 {
996     // We need to map between the internal register encoding and the one expected
997     // by codegen.
998     std::set<RegisterID> localUsed;
999     std::set<RegisterID> localDefined;
1000
1001     ia32_locations locs;
1002     ia32_memacc mac[3];
1003     ia32_condition cond;
1004   ia32_instruction detailedInsn(mac, &cond, &locs);
1005   instruction tmp = getInstruction();
1006   ia32_decode(IA32_FULL_DECODER, tmp.ptr(), detailedInsn);
1007   ia32_entry * entry = detailedInsn.getEntry();  
1008   if(entry)
1009   {
1010     entry->flagsUsed(localUsed, localDefined);
1011     unsigned int opsema = entry->opsema & ((1<<FPOS) -1);//0xFF;
1012     parseRegisters(localUsed, localDefined, detailedInsn, opsema);
1013   }
1014   if(isFPWrite())
1015   {
1016       localDefined.insert(r_DummyFPR);
1017   }
1018   if(detailedInsn.getPrefixCount())
1019   {
1020     unsigned char repPrefix = detailedInsn.getPrefix()->getPrefix(RepGroup);
1021     switch(repPrefix)
1022     {
1023     case PREFIX_REPNZ:
1024       localUsed.insert(r_ZF);
1025       // fall through
1026     case PREFIX_REP:
1027       localUsed.insert(r_DF);
1028       localUsed.insert(r_ECX);
1029       localDefined.insert(r_ECX);
1030       break;
1031     default:
1032       break;
1033     }
1034   }
1035   std::transform(localUsed.begin(), localUsed.end(), inserter(used, used.begin()),
1036                  dummyConverter);
1037   std::transform(localDefined.begin(), localDefined.end(), inserter(defined, defined.begin()),
1038                  dummyConverter);
1039
1040
1041 }