Added instruction iterator
[dyninst.git] / dyninstAPI / src / InstrucIter-power.C
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <assert.h>
4 #include <string.h>
5
6 #include "common/h/Types.h"
7 #include "common/h/Vector.h"
8 #include "common/h/Dictionary.h"
9
10 #include "arch.h"
11 #include "util.h"
12 #include "process.h"
13 #include "symtab.h"
14 #include "instPoint.h"
15 #include "InstrucIter.h"
16
17 #include "BPatch_memoryAccess_NP.h"
18 #include "BPatch_Set.h"
19
20 //some more function used to identify the properties of the instruction
21 /** is the instruction used to return from the functions
22   * @param i the instruction value 
23   */
24 bool InstrucIter::isAReturnInstruction()
25 {
26   const instruction i = getInstruction();
27         if((i.xlform.op == BCLRop) &&
28            (i.xlform.xo == BCLRxop) && 
29            (i.xlform.bt & 0x10) && (i.xlform.bt & 0x4))
30                 return true;
31         return false;
32 }
33
34 /** is the instruction an indirect jump instruction 
35   * @param i the instruction value 
36   */
37 bool InstrucIter::isAIndirectJumpInstruction(InstrucIter ah)
38 {
39   const instruction i = getInstruction();
40         if((i.xlform.op == BCLRop) && (i.xlform.xo == BCCTRxop) &&
41            !i.xlform.lk && (i.xlform.bt & 0x10) && (i.xlform.bt & 0x4))
42                 return true;
43
44         if((i.xlform.op == BCLRop) && (i.xlform.xo == BCLRxop) &&
45            (i.xlform.bt & 0x10) && (i.xlform.bt & 0x4)){
46                 --ah;--ah;
47                 if(!ah.hasMore())
48                         return false;
49                 instruction j = ah.getInstruction();
50                 if((j.xfxform.op == 31) && (j.xfxform.xo == 467) &&
51                    (j.xfxform.spr == 0x100))
52                         return true;
53         }
54         return false;
55 }
56
57 /** is the instruction a conditional branch instruction 
58   * @param i the instruction value 
59   */ 
60 bool InstrucIter::isACondBranchInstruction()
61 {
62   const instruction i = getInstruction();
63         if((i.bform.op == BCop) && !i.bform.lk &&
64            !((i.bform.bo & 0x10) && (i.bform.bo & 0x4)))
65                 return true;
66         return false;
67 }
68 /** is the instruction an unconditional branch instruction 
69   * @param i the instruction value 
70   */
71 bool InstrucIter::isAJumpInstruction()
72 {
73   const instruction i = getInstruction();
74         if((i.iform.op == Bop) && !i.iform.lk)
75                 return true;
76         if((i.bform.op == BCop) && !i.bform.lk &&
77            (i.bform.bo & 0x10) && (i.bform.bo & 0x4))
78                 return true;
79         return false;
80 }
81 /** is the instruction a call instruction 
82   * @param i the instruction value 
83   */
84 bool InstrucIter::isACallInstruction()
85 {
86   const instruction i = getInstruction();
87         if(i.iform.lk && 
88            ((i.iform.op == Bop) || (i.bform.op == BCop) ||
89             ((i.xlform.op == BCLRop) && 
90              ((i.xlform.xo == 16) || (i.xlform.xo == 528))))){
91                 return true;
92         }
93         return false;
94 }
95 bool InstrucIter::isAnneal(){
96   return true;
97 }
98
99 #define MK_LD1(bytes, imm, ra) (BPatch_memoryAccess(true, false, (bytes), (imm), (ra), -1))
100 #define MK_SD1(bytes, imm, ra) (BPatch_memoryAccess(false, true, (bytes), (imm), (ra), -1))
101
102 #define MK_LX1(bytes, ra, rb) (BPatch_memoryAccess(true, false, (bytes), 0, (ra), (rb)))
103 #define MK_SX1(bytes, ra, rb) (BPatch_memoryAccess(false, true, (bytes), 0, (ra), (rb)))
104
105 #define MK_LD(bytes, i) (MK_LD1((bytes), i.dform.d_or_si, (signed)i.dform.ra))
106 #define MK_SD(bytes, i) (MK_SD1((bytes), i.dform.d_or_si, (signed)i.dform.ra))
107
108 // VG(11/20/01): X-forms ignore ra if 0, but not rb...
109 #define MK_LX(bytes, i) (MK_LX1((bytes), (i.xform.ra ? (signed)i.xform.ra : -1), i.xform.rb))
110 #define MK_SX(bytes, i) (MK_SX1((bytes), (i.xform.ra ? (signed)i.xform.ra : -1), i.xform.rb))
111
112 #define MK_LDS(bytes, i) (MK_LD1((bytes), (i.dsform.d << 2), (signed)i.dsform.ra))
113 #define MK_SDS(bytes, i) (MK_SD1((bytes), (i.dsform.d << 2), (signed)i.dsform.ra))
114
115 #define MK_LI(bytes, i) (MK_LX1((bytes), i.xform.ra, -1))
116 #define MK_SI(bytes, i) (MK_SX1((bytes), i.xform.ra, -1))
117
118 struct opCodeInfo {
119   unsigned int bytes; //: 4;
120   unsigned int direc; //: 1; // 0 == load, 1 == store
121 public:
122   opCodeInfo(unsigned b, unsigned d) : bytes(b), direc(d) {}
123   opCodeInfo() : bytes(0), direc(0) {}
124 };
125
126 opCodeInfo *xopCodes[1024];
127
128 void initOpCodeInfo()
129 {
130   xopCodes[LWARXxop]    = new opCodeInfo(4, 0);
131   xopCodes[LDXxop]      = new opCodeInfo(8, 0);
132   xopCodes[LXxop]       = new opCodeInfo(4, 0);
133   xopCodes[LDUXxop]     = new opCodeInfo(8, 0);
134   xopCodes[LUXxop]      = new opCodeInfo(4, 0);
135   xopCodes[LDARXxop]    = new opCodeInfo(8, 0);
136   xopCodes[LBZXxop]     = new opCodeInfo(1, 0);
137   xopCodes[LBZUXxop]    = new opCodeInfo(1, 0);
138
139   xopCodes[STDXxop]     = new opCodeInfo(8, 1);
140   xopCodes[STWCXxop]    = new opCodeInfo(4, 1);
141   xopCodes[STXxop]      = new opCodeInfo(4, 1);
142   xopCodes[STDUXxop]    = new opCodeInfo(8, 1);
143   xopCodes[STUXxop]     = new opCodeInfo(4, 1);
144   xopCodes[STDCXxop]    = new opCodeInfo(8, 1);
145   xopCodes[STBXxop]     = new opCodeInfo(1, 1);
146   xopCodes[STBUXxop]    = new opCodeInfo(1, 1);
147
148   xopCodes[LHZXxop]     = new opCodeInfo(2, 0);
149   xopCodes[LHZUXxop]    = new opCodeInfo(2, 0);
150   xopCodes[LHAXxop]     = new opCodeInfo(2, 0);
151   xopCodes[LWAXxop]     = new opCodeInfo(4, 0);
152   xopCodes[LWAUXxop]    = new opCodeInfo(4, 0);
153   xopCodes[LHAUXxop]    = new opCodeInfo(2, 0);
154
155   xopCodes[STHXxop]     = new opCodeInfo(2, 1);
156   xopCodes[STHUXxop]    = new opCodeInfo(2, 1);
157
158   xopCodes[LSXxop]      = new opCodeInfo(0, 0); // count field only available at runtime
159   xopCodes[LWBRXxop]    = new opCodeInfo(4, 0);
160   xopCodes[LFSXxop]     = new opCodeInfo(4, 0);
161   xopCodes[LFSUXxop]    = new opCodeInfo(4, 0);
162   xopCodes[LSIxop]      = new opCodeInfo(0, 0); // count field needs to be computed
163   xopCodes[LFDXxop]     = new opCodeInfo(8, 0);
164   xopCodes[LFDUXxop]    = new opCodeInfo(8, 0);
165
166   xopCodes[STSXxop]     = new opCodeInfo(0, 1); // count field only available at runtime
167   xopCodes[STBRXxop]    = new opCodeInfo(4, 1);
168   xopCodes[STFSXxop]    = new opCodeInfo(4, 1);
169   xopCodes[STFSUXxop]   = new opCodeInfo(4, 1);
170   xopCodes[STSIxop]     = new opCodeInfo(0, 1); // bytes field needs to be computed
171   xopCodes[STFDXxop]    = new opCodeInfo(8, 1);
172   xopCodes[STFDUXxop]   = new opCodeInfo(8, 1);
173
174   xopCodes[LHBRXxop]    = new opCodeInfo(2, 0);
175
176   xopCodes[STHBRXxop]   = new opCodeInfo(2, 1);
177
178   xopCodes[STFIWXxop]   = new opCodeInfo(4, 1);
179
180   //fprintf(stderr, "POWER opcode info initialized.\n");
181 }
182
183
184 /* return NULL if instruction is not load/store, else returns
185    a class that contains info about the load/store */
186
187 // VG (09/11/01): I tried to optimize this somewhat. Not sure how much...
188 // It is a hard-coded binary search that assumes all opcodes have the same
189 // probability to appear. Probably not realistic, but I don't have statistics
190 // for Power... Due to the interleaving of load and store opcodes on Power,
191 // it seems cheaper to have only one function to decide if it is load or store
192 // Alternatively one could write this based on bits in opcode. E.g. if bit 3
193 // is 0 then the instruction is most likely a load, else it is likely a store.
194 // I also assume that no invalid instructions occur: e.g.: LU with RA=0, etc.
195
196 #define logIS_A(x) 
197 //#define logIS_A(x) logLine((x))
198
199 BPatch_memoryAccess InstrucIter::isLoadOrStore()
200 {
201   const instruction i = getInstruction();
202
203   int op = i.dform.op;
204   int  b;
205
206   if(op > LXop) { // try D-forms
207     if(op < STHop)
208       if(op < STop) {
209         logIS_A("IS_A: l-lbzu");
210         b = op < LBZop ? 4 : 1;
211         return MK_LD(b, i);
212       } else if (op < LHZop) {
213         logIS_A("IS_A: st-stbu");
214         b = op < STBop ? 4 : 1;
215         return MK_SD(b, i);
216       } else {
217         logIS_A("IS_A: lhz-lhau");
218         return MK_LD(2, i);
219       }
220     else if(op < STFSop)
221       if(op < LFSop)
222         if(op < LMop) {
223           logIS_A("IS_A: sth-sthu");
224           return MK_SD(2, i);
225         }
226         else if(op < STMop) {
227           logIS_A("IS_A: lm");
228           return MK_LD((32 - i.dform.rt)*4, i);
229         }
230         else {
231           logIS_A("IS_A: stm");
232           return MK_SD((32 - i.dform.rt)*4, i);
233         }
234       else {
235         logIS_A("IS_A: lfs-lfdu");
236         b = op < LFDop ? 4 : 8;
237         return MK_LD(b, i);
238       }
239     else if(op <= STFDUop) {
240       logIS_A("IS_A: stfs-stfdu");
241       b = op < STFDop ? 4 : 8;
242       return MK_SD(b, i);
243     }
244     else if(op == LDop) {
245       logIS_A("IS_A: ld-lwa");
246       b = i.dsform.xo < 2 ? 8 : 4;
247       assert(i.dsform.xo < 3);
248       return MK_LDS(b, i);
249     }
250     else if(op == STDop) {
251       logIS_A("IS_A: std-stdu");
252       assert(i.dsform.xo < 2);
253       return MK_SDS(8, i);
254     }
255     else
256       return BPatch_memoryAccess::none;
257   }
258   else if(op == LXop) { // X-forms
259     unsigned int xop = i.xform.xo;
260     //char buf[100];
261
262     //snprintf(buf, 100, "XOP:: %d\n", xop);
263     //logIS_A(buf);
264
265     opCodeInfo *oci = xopCodes[xop];
266
267     if(oci->bytes > 0)
268       return oci->direc ? MK_SX(oci->bytes, i) : MK_LX(oci->bytes, i);
269     else if(xop == LSIxop || xop == STSIxop) {
270       b = i.xform.rb == 0 ? 32 : i.xform.rb; 
271       return oci->direc ? MK_SI(b, i) : MK_LI(b, i);
272     }
273     else if(xop == LSXxop || xop == STSXxop) {
274       return BPatch_memoryAccess(oci->direc == 0, oci->direc == 1,
275                            0, i.xform.ra, i.xform.rb,
276                            0, 9999, -1); // FIXME map this 9999 to XER_25:31
277     }
278   }
279   return BPatch_memoryAccess::none;
280 }
281
282 /** function which returns the offset of control transfer instructions
283   * @param i the instruction value 
284   */
285 Address InstrucIter::getBranchTargetAddress(Address pos)
286 {
287   const instruction i = getInstruction();
288         Address ret = 0;
289         if((i.iform.op == Bop) || (i.bform.op == BCop)){
290                 int disp = 0;
291                 if(i.iform.op == Bop)
292                         disp = i.iform.li;
293                 else if(i.bform.op == BCop)
294                         disp = i.bform.bd;
295                 disp <<= 2;
296                 if(i.iform.aa)
297                         ret = (Address)disp;
298                 else
299                         ret = (Address)(pos+disp);
300         }
301         return (Address)ret;
302 }
303
304
305 void InstrucIter::getMultipleJumpTargets(BPatch_Set<Address>& result)
306 {
307         (*this)--;
308         Address initialAddress = currentAddress;
309         Address TOC_address = (addressImage->getObject()).getTOCoffset();
310
311         instruction check;
312         Address jumpStartAddress = 0;
313         while(hasMore()){
314                 check = getInstruction();
315                 if((check.dform.op == Lop) && (check.dform.ra == 2)){
316                         jumpStartAddress = 
317                                 (Address)(TOC_address + check.dform.d_or_si);
318                         break;
319                 }
320                 (*this)--;
321         }
322         (*this)--;
323         Address adjustEntry = 0;
324         check = getInstruction();
325         if((check.dform.op == Lop))
326                 adjustEntry = check.dform.d_or_si;
327
328         Address tableStartAddress = 0;
329         while(hasMore()){
330                 instruction check = getInstruction();
331                 if((check.dform.op == Lop) && (check.dform.ra == 2)){
332                         tableStartAddress = 
333                                 (Address)(TOC_address + check.dform.d_or_si);
334                         break;
335                 }
336                 (*this)--;
337         }
338
339         setCurrentAddress(initialAddress);
340         int maxSwitch = 0;
341         while(hasMore()){
342                 instruction check = getInstruction();
343                 if((check.bform.op == BCop) && 
344                    !check.bform.aa && !check.bform.lk){
345                         (*this)--;
346                         check = getInstruction();
347                         if(10 != check.dform.op)
348                                 break;
349                         maxSwitch = check.dform.d_or_si + 1;
350                         break;
351                 }
352                 (*this)--;
353         }
354         if(!maxSwitch){
355                 result += (initialAddress + sizeof(instruction));
356                 return;
357         }
358
359         Address jumpStart = 
360                 (Address)addressImage->get_instruction(jumpStartAddress);
361         Address tableStart = 
362                 (Address)addressImage->get_instruction(tableStartAddress);
363
364         for(int i=0;i<maxSwitch;i++){
365                 Address tableEntry = adjustEntry + tableStart + (i * sizeof(instruction));
366                 int jumpOffset = (int)addressImage->get_instruction(tableEntry);
367                 result += (Address)(jumpStart+jumpOffset);
368         }
369 }
370
371 bool InstrucIter::delayInstructionSupported()
372 {
373         return false;
374 }
375
376 bool InstrucIter::hasMore()
377 {
378         if((currentAddress < (baseAddress + range )) &&
379            (currentAddress >= baseAddress))
380                 return true;
381         return false;
382 }
383
384 bool InstrucIter::hasPrev()
385 {
386     if((currentAddress < (baseAddress + range )) &&
387        (currentAddress > baseAddress))
388         return true;
389     return false;
390 }
391
392 Address InstrucIter::prevAddress()
393 {
394         Address ret = currentAddress-sizeof(instruction);
395         return ret;
396 }
397
398 Address InstrucIter::nextAddress()
399 {
400         Address ret = currentAddress + sizeof(instruction);
401         return ret;
402 }
403
404 void InstrucIter::setCurrentAddress(Address addr)
405 {
406         currentAddress = addr;
407 }
408
409 instruction InstrucIter::getInstruction()
410 {
411         instruction ret;
412         ret.raw = addressImage->get_instruction(currentAddress);
413         return ret;
414 }
415
416 instruction InstrucIter::getNextInstruction()
417 {
418         instruction ret;
419         ret.raw = addressImage->get_instruction(currentAddress+sizeof(instruction));
420         return ret;
421 }
422
423 instruction InstrucIter::getPrevInstruction()
424 {
425         instruction ret;
426         ret.raw = addressImage->get_instruction(currentAddress-sizeof(instruction));
427         return ret;
428 }
429
430 Address InstrucIter::operator++()
431 {
432         currentAddress += sizeof(instruction);
433         return currentAddress;
434 }
435
436 Address InstrucIter::operator--()
437 {
438         currentAddress -= sizeof(instruction);
439         return currentAddress;
440 }
441
442 Address InstrucIter::operator++(int)
443 {
444         Address ret = currentAddress;
445         currentAddress += sizeof(instruction);
446         return ret;
447 }
448
449 Address InstrucIter::operator--(int)
450 {
451         Address ret = currentAddress;
452         currentAddress -= sizeof(instruction);
453         return ret;
454 }
455
456 Address InstrucIter::operator*(){
457         return currentAddress;
458 }