Added instruction iterator
[dyninst.git] / dyninstAPI / src / InstrucIter-sparc.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_Set.h"
18
19 //some more function used to identify the properties of the instruction
20 /** is the instruction used to return from the functions
21  * @param i the instruction value 
22  */
23 bool InstrucIter::isAReturnInstruction()
24 {
25   const instruction i = getInstruction();
26
27   if((i.resti.op == 0x2) && (i.resti.op3 == 0x38) &&
28      (i.resti.rd == 0) && (i.resti.i == 0x1) &&
29      ((i.resti.rs1 == 0xf) || (i.resti.rs1 == 0x1f)) &&
30      ((i.resti.simm13 == 8) || (i.resti.simm13 == 12)))
31     return true;
32   return false;
33 }
34
35 /** is the instruction an indirect jump instruction 
36   * @param i the instruction value 
37   */
38 bool InstrucIter::isAIndirectJumpInstruction()
39 {
40   const instruction i = getInstruction();
41
42   if((i.resti.op == 0x2) && (i.resti.op3 == 0x38) &&
43      (i.resti.rd == 0) && (i.resti.rs1 != 0xf) && 
44      (i.resti.rs1 != 0x1f))
45     return true;
46   return false;
47 }
48
49 /** is the instruction a conditional branch instruction 
50   * @param i the instruction value 
51   */ 
52 bool InstrucIter::isACondBranchInstruction()
53 {
54   const instruction i = getInstruction();
55
56   if((i.branch.op == 0) &&
57      (i.branch.op2 == 2 || i.branch.op2 == 6) &&
58      (i.branch.cond != 0) && (i.branch.cond != 8))
59     return true;
60   return false;
61 }
62 /** is the instruction an unconditional branch instruction 
63   * @param i the instruction value 
64   */
65 bool InstrucIter::isAJumpInstruction()
66 {
67   const instruction i = getInstruction();
68
69   if((i.branch.op == 0) &&
70      (i.branch.op2 == 2 || i.branch.op2 == 6) &&
71      (i.branch.cond == 8))
72     return true;
73   return false;
74 }
75 /** is the instruction a call instruction 
76   * @param i the instruction value 
77   */
78 bool InstrucIter::isACallInstruction()
79 {
80   const instruction i = getInstruction();
81
82   if(i.call.op == 0x1)
83     return true;
84   return false;
85 }
86
87 bool InstrucIter::isAnneal()
88 {
89   const instruction i = getInstruction();
90
91   if(i.branch.anneal)
92     return true;
93   return false;
94 }
95
96 void initOpCodeInfo()
97 {
98   // none needed on SPARC
99 }
100
101 // TODO: maybe figure out a closed form for these functions
102 const unsigned int fpBytes[][2] = { { 4, 4 }, { 4, 8 }, { 16, 16 }, { 8, 8 } };
103 const unsigned int intBytes[] = { 4, 1, 2, 8 };
104 const unsigned int fishyBytes[] = { 0, 1, 8, 4 };
105
106 #define btst(x, bit) ((x) & (1<<(bit)))
107
108 #define MK_LDi0(bytes, rs1, rs2) (BPatch_memoryAccess(true, false, (bytes), 0, (rs1), (rs2)))
109 #define MK_STi0(bytes, rs1, rs2) (BPatch_memoryAccess(false, true, (bytes), 0, (rs1), (rs2)))
110 #define MK_LDi1(bytes, rs1, simm13) (BPatch_memoryAccess(true, false, (bytes), (simm13), (rs1), -1))
111 #define MK_STi1(bytes, rs1, simm13) (BPatch_memoryAccess(false, true, (bytes), (simm13), (rs1), -1))
112 #define MK_PFi0(rs1, rs2, f) (BPatch_memoryAccess(false, false, true, 0, (rs1), (rs2), \
113                                            0, -1, -1, (f)))
114 #define MK_PFi1(rs1, simm13, f) (BPatch_memoryAccess(false, false, true, (simm13), (rs1), -1, \
115                                               0, -1, -1, (f)))
116
117 #define MK_LD(bytes, in) (in.rest.i ? MK_LDi1(bytes, in.resti.rs1, in.resti.simm13) : \
118                                       MK_LDi0(bytes, in.rest.rs1, in.rest.rs2))
119 #define MK_ST(bytes, in) (in.rest.i ? MK_STi1(bytes, in.resti.rs1, in.resti.simm13) : \
120                                       MK_STi0(bytes, in.rest.rs1, in.rest.rs2))
121 #define MK_MA(bytes, in, load, store) \
122           (in.rest.i ? \
123               BPatch_memoryAccess((load), (store), (bytes), in.resti.simm13, in.resti.rs1, -1) \
124               : \
125               BPatch_memoryAccess((load), (store), (bytes), 0, in.rest.rs1, in.rest.rs2))
126 #define MK_PF(in) (in.rest.i ? MK_PFi1(in.resti.rs1, in.resti.simm13, in.resti.rd) : \
127                                MK_PFi0(in.rest.rs1, in.rest.rs2, in.rest.rd))
128
129 // VG(09/20/01): SPARC V9 decoding after the architecture manual.
130 // One can see this a Huffman tree...
131 BPatch_memoryAccess InstrucIter::isLoadOrStore()
132 {
133   const instruction i = getInstruction();
134
135   if(i.rest.op != 0x3) // all memory opcodes have op bits 11
136     return BPatch_memoryAccess::none;
137
138   unsigned int op3 = i.rest.op3;
139
140   if(btst(op3, 4)) { // bit 4 set means alternate space
141     if(i.rest.i) {
142       logLine("SPARC: Alternate space instruction using ASI register currently unhandled...");
143       return BPatch_memoryAccess::none;
144     }
145     else if(i.rest.unused != ASI_PRIMARY) { // unused is actually imm_asi
146       logLine("SPARC: Alternate space instruction using ASI != PRIMARY currently unhandled...");
147       return BPatch_memoryAccess::none;
148     }
149     // else it is handled below assuming that endianness is big
150   }
151
152   if(btst(op3, 5)) { // bit 5 set means dig more
153     if(btst(op3, 3)) { // bit 3 set means PREFETCH or CAS(X)
154       // Actually CAS(X) is not implemented, it a synthetic
155       // instruction that should be coded as CAS(X)A on ASI_P.
156       assert(btst(op3,2)); // Catch reserved opcodes
157       if(btst(op3, 0)) { // PREFETCH
158         assert(!btst(op3, 1)); // Catch reserved opcode
159         return MK_PF(i);
160       }
161       else { // CAS(X)A
162         // XXX: the manual seems to have a bug not listed in the errata:
163         // it claims that CASA uses the *word* in r[rs1] as address. IMHO
164         // the address should always be a doubleword on V9...
165         unsigned int b = btst(op3, 1) ? 8 : 4;
166         // VG(12/08/01): CAS(X)A uses rs2 as value not address...
167         return BPatch_memoryAccess(true, true, b, 0, i.resti.rs1, -1);
168       }
169     }
170     else { // bit 3 zero (1u0xyz) means fp memory op
171       bool isStore = btst(op3, 2); // bit 2 gives L/S
172       // bits 0-1 encode #bytes except for state register ops,
173       // where the number of bits is given by bit 0 from rd
174       unsigned int b = fpBytes[op3 & 0x3][i.rest.rd & 0x1];
175       return isStore ? MK_ST(b, i) : MK_LD(b, i);
176     }
177   }
178   else { // bit 5 zero means interger memory op
179     // bit 2 almost gives L/S, except LDSTUB (load-store) and SWAP
180     // also look like a store. (SWAP is deprecated on V9)
181     bool isStore = btst(op3, 2);
182     // bit 3 gives signed/unsigned for LOADS, but we ignore that;
183     // for stores, it has no clear meaning: there are 5 pure store
184     // opcodes, two more that are also loads, and one is reserved.
185     // (see p. 269 in manual)
186     if(isStore && btst(op3, 3)) { // fishy
187       bool isLoad = btst(op3, 0); // SWAP & LDSTUB are both load and store
188       unsigned int b = fishyBytes[op3 & 0x3];
189       assert(b); // Catch reserved opcode
190       return MK_MA(b, i, isLoad, isStore);
191     }
192     // else simple store, therefore continue
193     unsigned int b = intBytes[op3 & 0x3]; // bits 0-1 encode #bytes
194     return isStore ? MK_ST(b, i) : MK_LD(b, i);
195   }
196   return BPatch_memoryAccess::none;
197 }
198
199
200
201 /** function which returns the offset of control transfer instructions
202   * @param i the instruction value 
203   */
204 Address InstrucIter::getBranchTargetAddress(Address pos)
205 {
206   const instruction i = getInstruction();
207
208   int ret;
209   if(i.branch.op == 0)
210     ret = i.branch.disp22;
211   else if(i.call.op == 0x1)
212     ret = i.call.disp30;
213   ret <<= 2;
214   return (Address)(ret+pos);
215 }
216
217 void InstrucIter::getMultipleJumpTargets(BPatch_Set<Address>& result){
218   while(hasMore()){
219     instruction check = getInstruction();
220     if((check.sethi.op == 0x0) && 
221        (check.sethi.op2 == 0x4) &&
222        (check.sethi.rd != 0x0))
223       {
224         register signed offset = check.sethi.imm22 << 10;
225         check = getNextInstruction();
226         if((check.resti.op == 0x2) &&
227            (check.resti.op3 == 0x2) &&
228            (check.resti.i == 0x1)){
229           register signed lowData = check.resti.simm13 & 0x3ff;
230           offset |= lowData;
231           setCurrentAddress((Address)offset);
232           for(;;){
233             check = getInstruction();
234             if(IS_VALID_INSN(check))
235               break;
236             result += check.raw;
237             (*this)++;
238           }
239           return;
240         }
241       }
242     (*this)--;
243   }
244 }
245 bool InstrucIter::delayInstructionSupported(){
246   return true;
247 }
248 bool InstrucIter::hasMore(){
249   if((currentAddress < (baseAddress + range )) &&
250      (currentAddress >= baseAddress))
251     return true;
252   return false;
253 }
254 bool InstrucIter::hasPrev(){
255   if((currentAddress < (baseAddress + range )) &&
256      (currentAddress > baseAddress))
257     return true;
258   return false;
259 }
260 Address InstrucIter::prevAddress(){
261   Address ret = currentAddress-sizeof(instruction);
262   return ret;
263 }
264 Address InstrucIter::nextAddress(){
265   Address ret = currentAddress + sizeof(instruction);
266   return ret;
267 }
268 void InstrucIter::setCurrentAddress(Address addr){
269   currentAddress = addr;
270 }
271 instruction InstrucIter::getInstruction(){
272   instruction ret;
273   ret.raw = addressImage->get_instruction(currentAddress);
274   return ret;
275 }
276 instruction InstrucIter::getNextInstruction(){
277   instruction ret;
278   ret.raw = addressImage->get_instruction(currentAddress+sizeof(instruction));
279   return ret;
280 }
281 instruction InstrucIter::getPrevInstruction(){
282   instruction ret;
283   ret.raw = addressImage->get_instruction(currentAddress-sizeof(instruction));
284   return ret;
285 }
286 Address InstrucIter::operator++(){
287   currentAddress += sizeof(instruction);
288   return currentAddress;
289 }
290 Address InstrucIter::operator--(){
291   currentAddress -= sizeof(instruction);
292   return currentAddress;
293 }
294 Address InstrucIter::operator++(int){
295   Address ret = currentAddress;
296   currentAddress += sizeof(instruction);
297   return ret;
298 }
299 Address InstrucIter::operator--(int){
300   Address ret = currentAddress;
301   currentAddress -= sizeof(instruction);
302   return ret;
303 }
304 Address InstrucIter::operator*(){
305   return currentAddress;
306 }