Update copyright to LGPL on all files
[dyninst.git] / dyninstAPI / src / InstrucIter-sparc.C
1 /*
2  * Copyright (c) 1996-2009 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  * By your use of Paradyn, you understand and agree that we (or any
12  * other person or entity with proprietary rights in Paradyn) are
13  * under no obligation to provide either maintenance services,
14  * update services, notices of latent defects, or correction of
15  * defects for Paradyn.
16  * 
17  * This library is free software; you can redistribute it and/or
18  * modify it under the terms of the GNU Lesser General Public
19  * License as published by the Free Software Foundation; either
20  * version 2.1 of the License, or (at your option) any later version.
21  * 
22  * This library is distributed in the hope that it will be useful,
23  * but WITHOUT ANY WARRANTY; without even the implied warranty of
24  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
25  * Lesser General Public License for more details.
26  * 
27  * You should have received a copy of the GNU Lesser General Public
28  * License along with this library; if not, write to the Free Software
29  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
30  */
31
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <assert.h>
35 #include <string.h>
36
37 #include "Annotatable.h"
38 #include "common/h/Types.h"
39 #include "common/h/Vector.h"
40 #include "common/h/Dictionary.h"
41
42 #include "arch.h"
43 #include "util.h"
44 #include "process.h"
45 #include "symtab.h"
46 #include "instPoint.h"
47 #include "InstrucIter.h"
48
49 #include "BPatch_Set.h"
50
51 #include "BPatch_instruction.h"
52 #include "BPatch_memoryAccess_NP.h"
53
54 //some more function used to identify the properties of the instruction
55 /** is the instruction a save instruction
56  * @param i the instruction value 
57  */
58 bool InstrucIter::isASaveInstruction()
59 {
60   const instruction i = getInstruction();
61   if(((*i).resti.op == RESTop) && ((*i).resti.op3 == SAVEop3))
62     return true;
63   return false;  
64 }
65
66 /** is the instruction a restore instruction
67  * @param i the instruction value 
68  */
69 bool InstrucIter::isARestoreInstruction()
70 {
71   const instruction i = getInstruction();
72   if(((*i).resti.op == RESTop) && ((*i).resti.op3 == RESTOREop3))
73     return true;
74   return false;  
75 }
76
77 /** is the instruction used to return from the functions
78  * @param i the instruction value 
79  */
80 bool InstrucIter::isAReturnInstruction()
81 {
82   const instruction i = getInstruction();
83
84   if(((*i).resti.op == 0x2) && ((*i).resti.op3 == 0x38) &&
85      ((*i).resti.rd == 0) && ((*i).resti.i == 0x1) &&
86      (((*i).resti.rs1 == 0xf) || ((*i).resti.rs1 == 0x1f)) &&
87      (((*i).resti.simm13 == 8) || ((*i).resti.simm13 == 12)))
88     return true;
89   return false;
90 }
91
92 /* The setup functions for works sharing either do a MOV
93    with 0x101 (Section) or 0x100 (Do/for) */
94 bool InstrucIter::isAOMPDoFor()
95 {
96   const instruction i = getInstruction();
97   
98   if ( ((*i).resti.op3 == 2) &&  ((*i).resti.simm13 == 0x100))
99     return true;
100   else
101     return false;
102 }
103
104
105 /** is the instruction used to return from the functions,
106     dependent upon a condition register
107     * @param i the instruction value 
108     */
109 bool InstrucIter::isACondReturnInstruction()
110 {
111   return false; // Not implemented yet
112 }
113
114 /** is the instruction an indirect jump instruction 
115  * @param i the instruction value 
116  */
117 bool InstrucIter::isAIndirectJumpInstruction()
118 {
119   const instruction i = getInstruction();
120
121   if(((*i).resti.op == 0x2) && ((*i).resti.op3 == 0x38) &&
122      ((*i).resti.rd == 0) && ((*i).resti.rs1 != 0xf) && 
123      ((*i).resti.rs1 != 0x1f))
124   {
125     if((!(*i).resti.i && ((*i).restix.rs2 == 0)) ||
126        ((*i).resti.i && ((*i).resti.simm13 == 0)))
127       return true;
128   }
129   return false;
130 }
131
132 /** is the instruction a conditional branch instruction 
133  * @param i the instruction value 
134  */ 
135 bool InstrucIter::isACondBranchInstruction()
136 {
137   const instruction i = getInstruction();
138
139   if(((*i).branch.op == 0) &&
140      ((*i).branch.op2 == 2 || (*i).branch.op2 == 6) &&
141      ((*i).branch.cond != 0) && ((*i).branch.cond != 8))
142     return true;
143   return false;
144 }
145
146
147 // Use for diagnosing a loop body in OpenMP
148 bool InstrucIter::isACondBLEInstruction()
149 {
150   const instruction i = getInstruction();
151   
152   if(((*i).branch.op == 0) &&
153      ((*i).branch.op2 == 2 && (*i).branch.cond == 2))
154     return true;
155   return false;
156 }
157
158 /** is the instruction an unconditional branch instruction 
159  * @param i the instruction value 
160  */
161 bool InstrucIter::isAJumpInstruction()
162 {
163   const instruction i = getInstruction();
164   
165   if(((*i).branch.op == 0) &&
166      ((*i).branch.op2 == 2 || (*i).branch.op2 == 6) &&
167      ((*i).branch.cond == 8))
168     return true;
169   return false;
170 }
171 /** is the instruction a call instruction 
172  * @param i the instruction value 
173  */
174 bool InstrucIter::isACallInstruction()
175 {
176   const instruction i = getInstruction();
177   
178   if((*i).call.op == 0x1)
179     return true;
180   return false;
181 }
182
183 bool InstrucIter::isAnneal()
184 {
185   const instruction i = getInstruction();
186
187   if((*i).branch.anneal)
188     return true;
189   return false;
190 }
191
192 void initOpCodeInfo()
193 {
194   // none needed on SPARC
195 }
196
197 // TODO: maybe figure out a closed form for these functions
198 const unsigned int fpBytes[][2] = { { 4, 4 }, { 4, 8 }, { 16, 16 }, { 8, 8 } };
199 const unsigned int intBytes[] = { 4, 1, 2, 8 };
200 const unsigned int fishyBytes[] = { 0, 1, 8, 4 };
201
202 #define btst(x, bit) ((x) & (1<<(bit)))
203
204 #define MK_LDi0(bytes, in, rs1, rs2) (new BPatch_memoryAccess(i,current, true, false, (bytes), 0, (rs1), (rs2)))
205 #define MK_STi0(bytes, in, rs1, rs2) (new BPatch_memoryAccess(i,current, false, true, (bytes), 0, (rs1), (rs2)))
206 #define MK_LDi1(bytes, in, rs1, simm13) (new BPatch_memoryAccess(i,current, true, false, (bytes), (simm13), (rs1), -1))
207 #define MK_STi1(bytes, in, rs1, simm13) (new BPatch_memoryAccess(i,current, false, true, (bytes), (simm13), (rs1), -1))
208 #define MK_PFi0(in, rs1, rs2, f) (new BPatch_memoryAccess(i,current, false, false, true, 0, (rs1), (rs2), \
209                                            0, -1, -1, (f)))
210 #define MK_PFi1(in, rs1, simm13, f) (new BPatch_memoryAccess(i,current, false, false, true, (simm13), (rs1), -1, \
211                                               0, -1, -1, (f)))
212
213 #define MK_LD(bytes, in) ((**in).rest.i ? MK_LDi1(bytes, in, (**in).resti.rs1, (**in).resti.simm13) : \
214                                       MK_LDi0(bytes, in, (**in).rest.rs1, (**in).rest.rs2))
215 #define MK_ST(bytes, in) ((**in).rest.i ? MK_STi1(bytes, in, (**in).resti.rs1, (**in).resti.simm13) : \
216                                       MK_STi0(bytes, in, (**in).rest.rs1, (**in).rest.rs2))
217 #define MK_MA(bytes, in, load, store) \
218           ((**in).rest.i ? \
219               new BPatch_memoryAccess(i, current,(load), (store), (bytes), (**in).resti.simm13, (**in).resti.rs1, -1) \
220               : \
221               new BPatch_memoryAccess(i, current,(load), (store), (bytes), 0, (**in).rest.rs1, (**in).rest.rs2))
222 #define MK_PF(in) ((**in).rest.i ? MK_PFi1(in, (**in).resti.rs1, (**in).resti.simm13, (**in).resti.rd) : \
223                                MK_PFi0(in, (**in).rest.rs1, (**in).rest.rs2, (**in).rest.rd))
224
225
226 // VG(09/20/01): SPARC V9 decoding after the architecture manual.
227 BPatch_memoryAccess* InstrucIter::isLoadOrStore()
228 {
229   instruction *i = getInsnPtr();
230
231   if((**i).rest.op != 0x3) // all memory opcodes have op bits 11
232     return BPatch_memoryAccess::none;
233
234   unsigned int op3 = (**i).rest.op3;
235
236   if(btst(op3, 4)) { // bit 4 set means alternate space
237     if((**i).rest.i) {
238       logLine("SPARC: Alternate space instruction using ASI register currently unhandled...");
239       return BPatch_memoryAccess::none;
240     }
241     else if((**i).rest.unused != ASI_PRIMARY) { // unused is actually imm_asi
242       logLine("SPARC: Alternate space instruction using ASI != PRIMARY currently unhandled...");
243       return BPatch_memoryAccess::none;
244     }
245     // else it is handled below assuming that endianness is big
246   }
247
248   if(btst(op3, 5)) { // bit 5 set means dig more
249     if(btst(op3, 3)) { // bit 3 set means PREFETCH or CAS(X)
250       // Actually CAS(X) is not implemented, it a synthetic
251       // instruction that should be coded as CAS(X)A on ASI_P.
252       assert(btst(op3,2)); // Catch reserved opcodes
253       if(btst(op3, 0)) { // PREFETCH
254         assert(!btst(op3, 1)); // Catch reserved opcode
255         return MK_PF(i);
256       }
257       else { // CAS(X)A
258         // XXX: the manual seems to have a bug not listed in the errata:
259         // it claims that CASA uses the *word* in r[rs1] as address. IMHO
260         // the address should always be a doubleword on V9...
261         unsigned int b = btst(op3, 1) ? 8 : 4;
262         // VG(12/08/01): CAS(X)A uses rs2 as value not address...
263         return new BPatch_memoryAccess(i, current,true, 
264                                        true, b, 0, (**i).resti.rs1, -1);
265       }
266     }
267     else { // bit 3 zero (1u0xyz) means fp memory op
268       bool isStore = btst(op3, 2); // bit 2 gives L/S
269       // bits 0-1 encode #bytes except for state register ops,
270       // where the number of bits is given by bit 0 from rd
271       unsigned int b = fpBytes[op3 & 0x3][(**i).rest.rd & 0x1];
272       return isStore ? MK_ST(b, i) : MK_LD(b, i);
273     }
274   }
275   else { // bit 5 zero means interger memory op
276     // bit 2 almost gives L/S, except LDSTUB (load-store) and SWAP
277     // also look like a store. (SWAP is deprecated on V9)
278     bool isStore = btst(op3, 2);
279     // bit 3 gives signed/unsigned for LOADS, but we ignore that;
280     // for stores, it has no clear meaning: there are 5 pure store
281     // opcodes, two more that are also loads, and one is reserved.
282     // (see p. 269 in manual)
283     if(isStore && btst(op3, 3)) { // fishy
284       bool isLoad = btst(op3, 0); // SWAP & LDSTUB are both load and store
285       unsigned int b = fishyBytes[op3 & 0x3];
286       assert(b); // Catch reserved opcode
287       return MK_MA(b, i, isLoad, isStore);
288     }
289     // else simple store, therefore continue
290     unsigned int b = intBytes[op3 & 0x3]; // bits 0-1 encode #bytes
291     return isStore ? MK_ST(b, i) : MK_LD(b, i);
292   }
293   return BPatch_memoryAccess::none;
294 }
295
296 /** function which returns the offset of control transfer instructions
297  * @param i the instruction value 
298  */
299 Address InstrucIter::getBranchTargetOffset()
300 {
301   const instruction i = getInstruction();
302
303   return i.getOffset();
304 }
305
306 Address InstrucIter::getBranchTargetAddress(bool *) {
307   const instruction i = getInstruction();
308   return i.getTarget(current);
309 }
310
311 bool InstrucIter::getMultipleJumpTargets(BPatch_Set<Address>& result){
312   Address oldCurrent = current;
313   instruction src = getInstruction();
314   while(hasPrev()){
315     instruction check = getInstruction();
316     // Check if the destination register of the sethi ins matches with the src of the indirect jump :giri 2/14/2007
317     if(((*check).sethi.op == 0x0) && 
318        ((*check).sethi.op2 == 0x4) &&
319        ((*check).sethi.rd == (*src).resti.rs1))
320     {
321       register signed offset = (*check).sethi.imm22 << 10;
322       ++(*this);
323       check = getInstruction();
324       --(*this);
325       if(((*check).resti.op == 0x2) &&
326          ((*check).resti.op3 == 0x2) &&
327          ((*check).resti.i == 0x1)){
328         register signed lowData = (*check).resti.simm13 & 0x3ff;
329         offset |= lowData;
330
331         image* img = dynamic_cast<image*>(instructions_);
332         while(true) { // Probably should calculate max table size
333           // as on other platforms.
334           void *targetPtr = NULL;
335           if(!instructions_->isValidAddress(offset)) return false;
336           if(img && !img->isCode(offset)) return false;
337           targetPtr = instructions_->getPtrToInstruction(offset);
338                     
339           if (targetPtr == NULL) return false;
340
341           // This is a horrid way to catch the end of the table;
342           // however, I don't know enough about SPARC to fix it.
343                     
344           Address target = *((Address *)targetPtr);
345           bool valid = true;
346
347           // I've seen this as well, when they pad
348           // jump tables.
349           if (img && (!img->isCode(target) || target == img->imageOffset())) {
350               valid = false;
351           }
352           else {
353             if (!instructions_->isValidAddress(target) || !instructions_->getPtrToInstruction(target))
354               valid = false;
355           }
356
357           instruction check(target);
358           if (check.valid()) {
359             // Apparently, we've hit the end of the... something.
360             valid = false;
361           }
362           if (target == 0) {
363             // What?
364             valid = false;
365           }
366           if (!valid) {
367             break;
368           }
369           
370           parsing_printf("\t0x%lx => 0x%lx\n", offset, target);
371           result += target;
372           offset += instruction::size();
373         }
374
375         setCurrentAddress(oldCurrent);
376         return !result.empty();
377       }
378     }
379     --(*this);
380   }
381   setCurrentAddress(oldCurrent);
382   return false;
383 }
384 bool InstrucIter::delayInstructionSupported(){
385   return true;
386 }
387
388 Address InstrucIter::peekPrev() {
389   // What about delay slots?
390   Address ret = current-instruction::size();
391   return ret;
392 }
393
394 Address InstrucIter::peekNext() {
395   // Delay slot?
396   Address ret = current + instruction::size();
397   return ret;
398 }
399
400 void InstrucIter::setCurrentAddress(Address addr){
401   current = addr;
402   //initializeInsn();
403 }
404
405 instruction InstrucIter::getInstruction(){
406   return insn;
407 }
408
409 instruction *InstrucIter::getInsnPtr() {
410   instruction *insnPtr = new instruction(insn);
411   return insnPtr;
412 }
413
414 // Check to see if we make a stack frame; in Sparc terms,
415 // execute a save instruction
416 bool InstrucIter::isStackFramePreamble(int &) {
417   assert(instPtr);
418   while (!isAReturnInstruction() &&
419          !isACondBranchInstruction() &&
420          !isACallInstruction() &&
421          !isADynamicCallInstruction() &&
422          !isAJumpInstruction() &&
423          insn.valid()) {
424     if (insn.isInsnType(SAVEmask, SAVEmatch)) 
425       return true;
426     (*this)++;
427   }
428   return false;
429 }
430
431 bool InstrucIter::isADynamicCallInstruction() {
432   instruction i = getInstruction();
433   return i.isInsnType(CALLImask, CALLImatch);
434 }
435
436 void InstrucIter::getAndSkipDSandAgg(instruction* &ds,
437                                      instruction* &agg) {
438   assert(instPtr);
439   instruction insn = getInstruction();
440   if (!insn.isDCTI())
441     return;
442   // Get the next two instructions, by address
443   // since we don't know where we are in the bbl.
444
445   ds = NULL;
446   agg = NULL;
447     
448   void *dsPtr = NULL;
449   void *aggPtr = NULL;
450
451
452   assert(instructions_); 
453   if (!instructions_->isValidAddress(current + instruction::size())) {
454     fprintf(stderr, "Error: addr 0x%x is not valid!\n",
455             instructions_);
456   }
457   else
458   {
459     dsPtr = instructions_->getPtrToInstruction(current + instruction::size());
460     aggPtr = instructions_->getPtrToInstruction(current + 2*instruction::size());
461     
462
463   }
464
465
466   // Skip delay slot...
467   (*this)++;
468
469   assert(dsPtr);
470   ds = new instruction(*(unsigned int *)dsPtr);
471     
472   /* Cases where an unimp 0 actually follows a delay slot */
473   if (!aggPtr)
474   {
475     (*this)++;
476     agg = NULL;
477     return;
478   }      
479
480   agg = new instruction(*(unsigned int *)aggPtr);
481   if (!agg->valid()) {
482     if ((**agg).raw != 0x0) {
483       // Skip aggregate...
484       (*this)++;
485       return;
486     }
487   }
488   // Otherwise, not what we want.
489   delete agg;
490   agg = NULL;
491   return;
492 }
493
494 bool InstrucIter::isTstInsn()
495 {
496   const instruction i = getInstruction();
497
498   if ((*i).resti.op3 == 18)
499     return true;
500
501   return false;
502 }
503
504 bool InstrucIter::isDelaySlot()
505 {
506   assert(instPtr);
507   return insn.isDCTI();
508 }
509
510 bool InstrucIter::isFrameSetup()
511 {
512   return false;
513 }
514
515 bool InstrucIter::isALeaveInstruction()
516 {
517   return false;
518 }
519
520 bool InstrucIter::isFramePush()
521 {
522   return false;
523 }
524
525 bool InstrucIter::isAnAllocInstruction()
526 {
527   return false;
528 }
529
530 bool InstrucIter::isAnInterruptInstruction()
531 {
532     // TODO: not implemented
533     return false;
534 }
535
536 bool InstrucIter::isAnAbortInstruction()
537 {
538   assert(instPtr);
539   return insn.isIllegal();
540 }
541
542 int adjustFPRegNumbers(int reg, int* registers, int i/*next available cell in registers*/, int word_size) {
543   if(word_size == SINGLE) {
544     registers[i] = reg + FLOAT_OFFSET;
545     return i+1;
546   }
547   else if(word_size == DOUBLE) {
548     if(reg < 32) {
549       registers[i] = reg + FLOAT_OFFSET;
550       registers[i+1] = reg+1 + FLOAT_OFFSET;
551       return i+2;
552     }
553     else {
554       registers[i] = reg + FLOAT_OFFSET;
555       return i+1;
556     }
557   }
558   else if(word_size == QUAD) {
559     if(reg>=32) {
560       registers[i] = reg + FLOAT_OFFSET;
561       registers[i+1] = reg+2 + FLOAT_OFFSET;
562       return i+2;
563     }
564     else {
565       registers[i] = reg + FLOAT_OFFSET;
566       registers[i+1] = reg+1 + FLOAT_OFFSET;
567       registers[i+2] = reg+2 + FLOAT_OFFSET;
568       registers[i+3] = reg+3 + FLOAT_OFFSET;
569       return i+4;
570     }
571   }
572   else {
573     fprintf(stderr,"Should have never reached here!\n");
574     return i;
575   }
576 }
577
578 int getRegisterNumber(int n, InsnRegister::RegisterType type) {
579   if(type == InsnRegister::FloatReg)
580     return n+FLOAT_OFFSET;
581   // if GlobalIntReg, CoProcReg, SpecialReg, or NoneReg, return what we have
582   return n;
583 }
584
585 void InstrucIter::readWriteRegisters(int* readRegs, int* writeRegs) 
586 {
587    instruction insn = getInstruction();
588    insn.get_register_operands();
589    std::vector<InsnRegister> *read_regs_p = NULL;
590    std::vector<InsnRegister> *write_regs_p = NULL;
591
592    extern AnnotationClass<std::vector<InsnRegister> > RegisterReadSetAnno;
593
594    bool have_read_regs = insn.getAnnotation(read_regs_p, RegisterReadSetAnno);
595    bool have_write_regs = insn.getAnnotation(write_regs_p, RegisterReadSetAnno);
596 #if 0
597    Annotatable<InsnRegister, register_read_set_a> &read_regs = insn;
598    Annotatable<InsnRegister, register_write_set_a> &write_regs = insn;
599
600   InsnRegister* reads = (InsnRegister*)malloc(sizeof(InsnRegister)*7);//[7];
601   InsnRegister* writes = (InsnRegister*)malloc(sizeof(InsnRegister)*5);
602   getInstruction().get_register_operands(reads, writes);
603 #endif
604
605   int c=0;
606
607   if (have_read_regs)
608   {
609      assert(read_regs_p);
610      std::vector<InsnRegister> &read_regs = *read_regs_p;
611      unsigned int reads_size = read_regs.size();
612      assert(reads_size < 9);
613
614      for (unsigned int i  = 0; i < reads_size; ++i) {
615
616         InsnRegister &read_reg = read_regs[i];
617         int regNum = read_reg.getNumber();
618         if (regNum == -1)
619            break;
620
621         regNum = getRegisterNumber(regNum, read_reg.getType());
622
623         if (regNum != 0) {
624            for (unsigned int j=0, wC=read_reg.getWordCount(); j<wC; j++,c++) {
625               readRegs[c] = regNum + j;
626            }
627         }
628      }
629   }
630
631 #if 0
632   int c=0;
633   int wC;
634   int i, j;
635   for(i=0; i<7; i++) {
636     int regNum = reads[i].getNumber();
637     if(regNum != -1) {
638       regNum = getRegisterNumber(regNum, reads[i].getType());
639       if(regNum != 0)
640         for(j=0, wC=reads[i].getWordCount(); j<wC; j++,c++) {
641           readRegs[c] = regNum + j;
642         }
643     }
644     else
645       break;
646   }
647 #endif
648
649   c=0;
650   if (have_write_regs)
651   {
652      assert(write_regs_p);
653      std::vector<InsnRegister> &write_regs = *write_regs_p;
654      unsigned int writes_size = write_regs.size();
655      assert(writes_size < 7);
656
657      for (unsigned int i  = 0; i < writes_size; ++i) {
658
659         InsnRegister &write_reg = write_regs[i];
660         int regNum = write_reg.getNumber();
661         if (regNum == -1)
662            break;
663
664         regNum = getRegisterNumber(regNum, write_reg.getType());
665
666         if (regNum != 0) {
667            for (unsigned int j=0, wC=write_reg.getWordCount(); j<wC; j++,c++) {
668               writeRegs[c] = regNum + j;
669            }
670         }
671      }
672   }
673
674 #if 0
675   c=0;
676   for(i=0; i<5; i++) {
677      int regNum = writes[i].getNumber();
678      if(regNum != -1) {
679         regNum = getRegisterNumber(regNum, writes[i].getType());
680         if(regNum != 0)
681            for(j=0, wC=writes[i].getWordCount(); j<wC; j++,c++) {
682           writeRegs[c] = regNum + j;
683         }
684     }
685     else
686       break;
687   }
688 #endif
689 }
690
691 void InstrucIter::adjustRegNumbers(int* readRegs, int* writeRegs,int window) {
692   int i=0;
693   if(isASaveInstruction()) {
694     for(i=0; i<2; i++) {
695       if(readRegs[i] <32 && readRegs[i] > 7)
696         readRegs[i] += WIN_SIZE*(MAX_SETS - window);
697     }
698     writeRegs[0] += WIN_SIZE*(MAX_SETS - window-1);
699   }
700   else if(isARestoreInstruction()) {
701     for(i=0; i<2; i++) {
702       if(readRegs[i] <32 && readRegs[i] > 7)
703         readRegs[i] += WIN_SIZE*(MAX_SETS - window);
704     }
705     writeRegs[0] += WIN_SIZE*(MAX_SETS - window+1);
706   }
707   else {
708     for(i=0; i<4; i++) {
709       if(readRegs[i] <32 && readRegs[i] > 7)
710         readRegs[i] += WIN_SIZE*(MAX_SETS - window);
711       if(writeRegs[i] <32 && writeRegs[i] > 7)
712         writeRegs[i] += WIN_SIZE*(MAX_SETS - window);
713     }
714   }
715 }
716
717 int InstrucIter::adjustRegNumbers(int regNum, int window) {
718   if(regNum <32 && regNum > 7)
719     return regNum + WIN_SIZE*(MAX_SETS - window);
720   return regNum;
721 }
722
723 bool InstrucIter::isANopInstruction()
724 {
725    return false;
726 }
727
728 bool InstrucIter::isSyscall()
729 {
730   // not implemented
731   return false;
732 }
733