Moving files to dyninstAPI directory - naim
[dyninst.git] / paradynd / src / inst-sparc-solaris.C
1 /*
2  * Copyright (c) 1996 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 "paradynd/src/inst-sparc.h"
43
44 // Another constructor for the class instPoint. This one is called
45 // for the define the instPoints for regular functions which means
46 // multiple instructions is going to be moved to based trampoline.
47 // Since we will use the instruction CALL to branch to the base
48 // tramp(so it doesn't have any code size restriction), things are
49 // a little more complicated because instruction CALL changes the 
50 // value in the link register.
51 instPoint::instPoint(pdFunction *f, const instruction &instr, 
52                      const image *owner, Address &adr,
53                      bool delayOK, bool isLeaf, instPointType pointType)
54 : addr(adr), originalInstruction(instr), inDelaySlot(false), isDelayed(false),
55   callIndirect(false), callAggregate(false), callee(NULL), func(f),
56   leaf(isLeaf), ipType(pointType), image_ptr(owner), firstIsConditional(false),
57   relocated_(false), isLongJump(false)
58 {
59
60   isBranchOut = false;
61   size = 0;
62
63   // When the function is not a leaf function 
64   if (!leaf) {
65
66       // we will treat the first instruction after the SAVE instruction
67       // in the nonleaf procedure as the function entry.  
68       if (ipType == functionEntry) {
69
70           assert(isInsnType(instr, SAVEmask, SAVEmatch));
71           saveInsn.raw = owner->get_instruction(addr);
72           addr += 4;
73           originalInstruction.raw = owner->get_instruction(addr);
74           delaySlotInsn.raw = owner->get_instruction(addr+4);
75           size += 2*sizeof(instruction);
76
77           // If the second instruction is DCTI, we need to move the
78           // the instruction in the delayed slot.
79           if (IS_DELAYED_INST(delaySlotInsn)) {
80               isDelayed = true; 
81               isDelayedInsn.raw = owner->get_instruction(addr+8);
82               size += 1*sizeof(instruction);
83
84               // Life is hard. If the second instruction is actually
85               // an CALL instruction, we need to move the instruction
86               // after the instruction in the delayed slot if the 
87               // return value of this function is a aggregate value.
88               aggregateInsn.raw = owner->get_instruction(addr+12);
89               if (isCallInsn(delaySlotInsn)) {
90                   if (!IS_VALID_INSN(aggregateInsn) && aggregateInsn.raw != 0) {
91                       callAggregate = true;
92                       size += 1*sizeof(instruction);
93                   }
94               }
95           }
96
97       // The following are easier.        
98       } else if (ipType == callSite) {
99           delaySlotInsn.raw = owner->get_instruction(addr+4);
100           size += 2*sizeof(instruction);
101
102           aggregateInsn.raw = owner->get_instruction(addr+8);
103           if (!IS_VALID_INSN(aggregateInsn) && aggregateInsn.raw != 0) {
104               callAggregate = true;
105               size += 1*sizeof(instruction);
106           }
107       } else {
108           delaySlotInsn.raw = owner->get_instruction(addr+4);
109           size += 2*sizeof(instruction);
110       }
111   }
112
113   // When the function is a leaf function
114   else {
115
116       // For the leaf procedure, there are no function calls in
117       // this procdure. So we don't need to consider the 
118       // aggregate instuction.
119       if (ipType == functionEntry) {
120
121           otherInstruction.raw = owner->get_instruction(addr+4);
122           delaySlotInsn.raw = owner->get_instruction(addr+8);
123           size += 2*sizeof(instruction);
124
125           if (IS_DELAYED_INST(delaySlotInsn)) {
126               isDelayed = true;
127               isDelayedInsn.raw = owner->get_instruction(addr+12);
128               size += 2*sizeof(instruction);
129           }
130
131       } else if (ipType == functionExit) {
132           
133           addr -= 4;
134
135           if (owner->isValidAddress(addr-4)) {
136               instruction iplus1;
137               iplus1.raw = owner->get_instruction(addr-4);
138               if (IS_DELAYED_INST(iplus1) && !delayOK) {
139                   addr -= 4;
140                   inDelaySlot = true;
141                   size += 1*sizeof(instruction);
142                   if(isCondBranch(iplus1)){
143                       instruction previous_inst; 
144                       previous_inst.raw = owner->get_instruction(addr-4);
145                       firstIsConditional = true;
146                       addr -= sizeof(instruction);
147                       size += 1*sizeof(instruction);
148                   }
149               }
150           }
151
152           originalInstruction.raw = owner->get_instruction(addr);
153           otherInstruction.raw = owner->get_instruction(addr+4);
154           delaySlotInsn.raw = owner->get_instruction(addr+8);
155           size += 3*sizeof(instruction);
156
157           if (inDelaySlot) {
158               inDelaySlotInsn.raw = owner->get_instruction(addr+12);
159               if(firstIsConditional) {
160                   extraInsn.raw = owner->get_instruction(addr+16);
161               }
162           }
163
164       } else {
165           // Of course, the leaf function could not have call sites. 
166           logLine("Internal Error: in inst-sparc.C.");
167           abort();
168       }
169   }
170
171   // return the address in the code segment after this instruction
172   // sequence. (there's a -1 here because one will be added up later in
173   // the function findInstPoints)  
174   adr = addr + (size - 1*sizeof(instruction));
175 }
176
177
178 void AstNode::sysFlag(instPoint *location)
179 {
180     // astFlag = location->func->isTrapFunc();
181     if (astFlag == false)
182         astFlag = (location -> isLongJump)? false:true; 
183     if (loperand)
184         loperand->sysFlag(location);
185     if (roperand)
186         roperand->sysFlag(location); 
187
188     for (unsigned u = 0; u < operands.size(); u++) {
189         operands[u]->sysFlag(location);
190     }
191 }
192
193 // Determine if the called function is a "library" function or a "user" function
194 // This cannot be done until all of the functions have been seen, verified, and
195 // classified
196 //
197 void pdFunction::checkCallPoints() {
198   instPoint *p;
199   Address loc_addr;
200
201   vector<instPoint*> non_lib;
202
203   for (unsigned i=0; i<calls.size(); ++i) {
204     /* check to see where we are calling */
205     p = calls[i];
206     assert(p);
207
208     if (isInsnType(p->originalInstruction, CALLmask, CALLmatch)) {
209       // Direct call
210       loc_addr = p->addr + (p->originalInstruction.call.disp30 << 2);
211       pdFunction *pdf = (file_->exec())->findFunction(loc_addr);
212       if (pdf && !pdf->isLibTag()) {
213         p->callee = pdf;
214         non_lib += p;
215       } else if(!pdf){
216            // if this is a call outside the fuction, keep it
217            if((loc_addr < getAddress(0))||(loc_addr > (getAddress(0)+size()))){
218                 p->callIndirect = true;
219                 p->callee = NULL;
220                 non_lib += p;
221            }
222            else {
223                delete p;
224            }
225       } else {
226           delete p;
227       }
228     } else {
229       // Indirect call -- be conservative, assume it is a call to 
230       // an unnamed user function
231       assert(!p->callee); assert(p->callIndirect);
232       p->callee = NULL;
233       non_lib += p;
234     }
235   }
236   calls = non_lib;
237 }
238
239 // TODO we cannot find the called function by address at this point in time
240 // because the called function may not have been seen.
241 // reloc_info is 0 if the function is not currently being relocated
242 Address pdFunction::newCallPoint(Address &adr, const instruction instr,
243                                  const image *owner, bool &err, 
244                                  int &callId, Address &oldAddr,
245                                  relocatedFuncInfo *reloc_info,
246                                  const instPoint *&location)
247 {
248     Address ret=adr;
249     instPoint *point;
250
251     err = true;
252     if (isTrap) {
253         point = new instPoint(this, instr, owner, adr, false, callSite, oldAddr);
254     } else {
255         point = new instPoint(this, instr, owner, adr, false, false, callSite);
256     }
257
258     if (!isInsnType(instr, CALLmask, CALLmatch)) {
259       point->callIndirect = true;
260       point->callee = NULL;
261     } else{
262       point->callIndirect = false;
263     }
264
265     if (isTrap) {
266         if (!reloc_info) {
267             calls += point;
268             calls[callId] -> instId = callId++;
269         } else {
270             // calls to a location within the function are not
271             // kept in the calls vector
272             assert(callId >= 0);
273             assert(((u_int)callId) < calls.size());
274             point->relocated_ = true;
275             // if the location was this call site, then change its value
276             if(location && (calls[callId] == location)) { 
277                 assert(calls[callId]->instId  == location->instId);
278                 location = point; 
279             } 
280             point->instId = callId++;
281             reloc_info->addFuncCall(point);
282         }
283     } else {
284         if (!reloc_info) {
285             calls += point;
286         }
287         else {
288             point->relocated_ = true;
289             reloc_info->addFuncCall(point);
290         }
291     }
292     err = false;
293     return ret;
294 }
295
296 /*
297  * Given and instruction, relocate it to a new address, patching up
298  *   any relative addressing that is present.
299  *
300  */
301 void relocateInstruction(instruction *insn, u_int origAddr, u_int targetAddr,
302                          process *proc)
303 {
304     int newOffset;
305
306     // If the instruction is a CALL instruction, calculate the new
307     // offset
308     if (isInsnType(*insn, CALLmask, CALLmatch)) {
309         newOffset = origAddr  - targetAddr + (insn->call.disp30 << 2);
310         insn->call.disp30 = newOffset >> 2;
311     } else if (isInsnType(*insn, BRNCHmask, BRNCHmatch)||
312                isInsnType(*insn, FBRNCHmask, FBRNCHmatch)) {
313
314         // If the instruction is a Branch instruction, calculate the 
315         // new offset. If the new offset is out of reach after the 
316         // instruction is moved to the base Trampoline, we would do
317         // the following:
318         //    b  address  ......    address: save
319         //                                   call new_offset             
320         //                                   restore 
321         newOffset = origAddr - targetAddr + (insn->branch.disp22 << 2);
322
323         // if the branch is too far, then allocate more space in inferior
324         // heap for a call instruction to branch target.  The base tramp 
325         // will branch to this new inferior heap code, which will call the
326         // target of the branch
327         if (!offsetWithinRangeOfBranchInsn(newOffset)) {
328 //      if (ABS(newOffset) > getMaxBranch1Insn()) {
329             int ret = inferiorMalloc(proc,3*sizeof(instruction), textHeap);
330             u_int old_offset = insn->branch.disp22 << 2;
331             insn->branch.disp22  = (ret - targetAddr)>>2;
332             instruction insnPlus[3];
333             genImmInsn(insnPlus, SAVEop3, REG_SP, -112, REG_SP);
334             generateCallInsn(insnPlus+1, ret+sizeof(instruction), 
335                              origAddr+old_offset);
336             genSimpleInsn(insnPlus+2, RESTOREop3, 0, 0, 0); 
337             proc->writeDataSpace((caddr_t)ret, sizeof(insnPlus), 
338                          (caddr_t) insnPlus);
339         } else {
340             insn->branch.disp22 = newOffset >> 2;
341         }
342     } else if (isInsnType(*insn, TRAPmask, TRAPmatch)) {
343         // There should be no probelm for moving trap instruction
344         // logLine("attempt to relocate trap\n");
345     } 
346     /* The rest of the instructions should be fine as is */
347 }
348
349 /*
350  * Install a base tramp -- fill calls with nop's for now.
351  *
352  * This one install the base tramp for the regular functions.
353  *
354  */
355 trampTemplate *installBaseTramp(instPoint *&location, process *proc)
356 {
357     // cerr << location->func->prettyName() << ":\t" << location->ipType << endl;
358     unsigned baseAddr = inferiorMalloc(proc, baseTemplate.size, textHeap);
359
360     instruction *code = new instruction[baseTemplate.size];
361     assert(code);
362
363     memcpy((char *) code, (char*) baseTemplate.trampTemp, baseTemplate.size);
364
365     instruction *temp;
366     unsigned currAddr;
367     for (temp = code, currAddr = baseAddr; 
368         (currAddr - baseAddr) < (unsigned) baseTemplate.size;
369         temp++, currAddr += sizeof(instruction)) {
370
371         if (temp->raw == EMULATE_INSN) {
372
373             // Load the value of link register from stack 
374             // If it is a leaf function, genereate a RESTORE instruction
375             // since there's an instruction SAVE generated and put in the
376             // code segment.
377             if (location -> leaf) {
378
379                 Address baseAddress = 0;
380                 proc->getBaseAddress(location->image_ptr,baseAddress);
381                 baseAddress += location -> addr;
382
383                 if (in1BranchInsnRange(baseAddress, baseAddr) == false) {
384                     //cerr << "This happen very rarely, I suppose "<< endl;
385                     //cerr << "Let's see if this is going to be executed..." << endl;
386                     location -> isLongJump = true;
387                     genImmInsn(temp, RESTOREop3, 0, 0, 0);
388                 } else {
389                     generateNOOP(temp);
390                 }
391                 temp++;
392                 currAddr += sizeof(instruction);
393             } 
394             // Same for the leaf and nonleaf functions.
395             // First, relocate the "FIRST instruction" in the sequence;  
396             Address fromAddr = location->addr;
397
398             if (!location -> leaf)
399                 if (location -> ipType == functionEntry) {
400                     *temp = location -> saveInsn;
401                     temp++;
402                     currAddr += sizeof(instruction);
403                 }
404
405             *temp = location->originalInstruction;
406
407             // compute the real from address if this instrumentation
408             // point is from a shared object image
409             Address baseAddress = 0;
410             if(proc->getBaseAddress(location->image_ptr,baseAddress)){
411                 fromAddr += baseAddress;                
412             }
413             // If the instruction is a call instruction to a location somewhere 
414             // within the function, then the 07 regester must be saved and 
415             // resored around the relocated call from the base tramp...the call
416             // instruction changes the value of 07 to be the PC value, and if
417             // we move the call instruction to the base tramp, its value will
418             // be incorrect when we use it in the function.  We generate the
419             // following base tramp code:
420             //          original delay slot instruction 
421             //          save
422             //          original call instruction
423             //          restore
424             // This case should only occur for function entry points in
425             // functions from shared objects, and there should be no append
426             // trampolene code because the relocated call instruction will
427             // not return to the base tramp
428             if (isInsnType(*temp, CALLmask, CALLmatch)) {
429                 Address offset = fromAddr + (temp->call.disp30 << 2);
430                 if ((offset > (location->func->getAddress(0)+ baseAddress)) && 
431                     (offset < ((location->func->getAddress(0)+ baseAddress)+
432                                  location->func->size()))) {
433                     // offset > adr; "=" means recursive function which is allowed
434                     // offset < adr + size; "=" does not apply to this case
435
436                     // TODO: this assumes that the delay slot instruction is not
437                     // a call instruction....is this okay?
438                     
439                     // assume this situation only happens at function entry point 
440                     // for the shared library routine. And it is definately nees
441                     // long jump support
442                     assert(location -> ipType == functionEntry); 
443                     location -> isLongJump = true;
444                     
445                     // In this situcation, save instruction is discarded
446                     // Rollback!! 
447                     assert(location->leaf == false);
448                     temp--;
449                     currAddr -= sizeof(instruction);
450                     
451                     *temp = location->delaySlotInsn;  
452                     temp++; 
453                     currAddr += sizeof(instruction);
454                     genImmInsn(temp, SAVEop3, REG_SP, -112, REG_SP); 
455                     temp++; 
456                     currAddr += sizeof(instruction);  
457                     *temp = location->originalInstruction;
458                     relocateInstruction(temp,fromAddr,currAddr,(process *)proc);
459                     temp++; 
460                     fromAddr += sizeof(instruction); 
461                     currAddr += sizeof(instruction);
462                     genImmInsn(temp, RESTOREop3, 0, 0, 0);
463                     continue;
464                 }
465             }   
466
467             relocateInstruction(temp,fromAddr,currAddr,(process *)proc);
468
469             // Again, for leaf function, one more is needed to move for one
470             // more spot;
471             if (location->leaf) {
472                 fromAddr += sizeof(instruction);
473                 currAddr += sizeof(instruction);
474                 *++temp = location->otherInstruction;
475                 relocateInstruction(temp, fromAddr, currAddr, 
476                                     (process *)proc);
477             }     
478             
479             // Second, relocate the "NEXT instruction";
480             fromAddr += sizeof(instruction);
481             currAddr += sizeof(instruction);
482             *++temp = location->delaySlotInsn;
483             relocateInstruction(temp, fromAddr, currAddr,
484                                 (process *)proc);
485             
486             // Third, if the "NEXT instruction" is a DCTI, 
487             if (location->isDelayed) {
488                 fromAddr += sizeof(instruction);
489                 currAddr += sizeof(instruction);
490                 *++temp = location->isDelayedInsn;
491                 relocateInstruction(temp, fromAddr, currAddr,
492                                     (process *)proc);
493                 
494                 // Then, possibly, there's an callAggregate instruction
495                 // after this. 
496                 if (location->callAggregate) {
497                     currAddr += sizeof(instruction);
498                     *++temp = location->aggregateInsn;
499                     continue;
500                 }       
501             }
502             
503             // If the "FIRST instruction" is a DCTI, then our so called 
504             // "NEXT instruction" is in the delayed Slot and this might
505             // happen. (actullay, it happened)
506             if (location->callAggregate) {
507                 currAddr += sizeof(instruction);
508                 *++temp = location->aggregateInsn;
509                 continue;
510             }   
511             
512             // For the leaf function, if there's an inDelaySlot instruction,
513             // move this one to the base Tramp.(i.e. at the function exit,
514             // if the first instruction is in the delayed slot the previous
515             // instruction, we have to move that one too, so we count from 
516             // that one and the last one is this sequence is called inDelaySlot
517             // instruction.)
518             // Well, after all these, another SAVE instruction is generated
519             // so we are prepared to handle the returning to our application's
520             // code segment. 
521             if (location->leaf) {
522                 if (location->inDelaySlot) {
523                     fromAddr += sizeof(instruction);
524                     currAddr += sizeof(instruction);
525                     *++temp = location->inDelaySlotInsn;
526                     relocateInstruction(temp,fromAddr,currAddr,(process *)proc);
527                     if(location->firstIsConditional){
528                         fromAddr += sizeof(instruction);
529                         currAddr += sizeof(instruction);
530                         *++temp = location->extraInsn;
531                         relocateInstruction(temp, fromAddr, currAddr, proc);
532                     }
533                 } 
534                 
535                 genImmInsn(temp+1, SAVEop3, REG_SP, -112, REG_SP);
536             }
537             
538         } else if (temp->raw == RETURN_INSN) {
539             // compute the real from address if this instrumentation
540             // point is from a shared object image
541             Address baseAddress = 0;
542             if(proc->getBaseAddress(location->image_ptr,baseAddress)){
543             }
544             // Back to the code segement of the application.
545             // If the location is in the leaf procedure, generate an RESTORE
546             // instruction right after the CALL instruction to restore all
547             // the values in the registers.
548             if (location -> leaf) {
549                 generateCallInsn(temp, currAddr, 
550                                 (baseAddress + location->addr)+location->size);
551                 genImmInsn(temp+1, RESTOREop3, 0, 0, 0);
552             } else {
553                 generateCallInsn(temp, currAddr, 
554                                 (baseAddress + location->addr)+location->size);
555             }
556         } else if (temp->raw == SKIP_PRE_INSN) {
557             unsigned offset;
558             offset = baseAddr+baseTemplate.updateCostOffset-currAddr;
559             generateBranchInsn(temp,offset);
560
561         } else if (temp->raw == SKIP_POST_INSN) {
562             unsigned offset;
563             offset = baseAddr+baseTemplate.returnInsOffset-currAddr;
564             generateBranchInsn(temp,offset);
565
566         } else if (temp->raw == UPDATE_COST_INSN) {
567             
568             baseTemplate.costAddr = currAddr;
569             generateNOOP(temp);
570         } else if ((temp->raw == LOCAL_PRE_BRANCH) ||
571                    (temp->raw == GLOBAL_PRE_BRANCH) ||
572                    (temp->raw == LOCAL_POST_BRANCH) ||
573                    (temp->raw == GLOBAL_POST_BRANCH)) {
574 #if defined(MT_THREAD)
575             if ((temp->raw == LOCAL_PRE_BRANCH) ||
576                 (temp->raw == LOCAL_POST_BRANCH)) {
577                 temp -= NUM_INSN_MT_PREAMBLE;
578                 unsigned numIns=0;
579                 generateMTpreamble((char *)temp, numIns, proc);
580                 temp += NUM_INSN_MT_PREAMBLE;
581             }
582 #endif
583             /* fill with no-op */
584             generateNOOP(temp);
585         }
586     }
587     // TODO cast
588     proc->writeDataSpace((caddr_t)baseAddr, baseTemplate.size,(caddr_t) code);
589
590     delete [] code;
591
592     trampTemplate *baseInst = new trampTemplate;
593     *baseInst = baseTemplate;
594     baseInst->baseAddr = baseAddr;
595     return baseInst;
596 }
597
598 /*
599  * Install the base Tramp for the function relocated.
600  * (it means the base tramp that don't need to bother with long jump and
601  *  is the one we used before for all the functions(since there's no
602  *  long jumps)
603  *  for system calls
604  */ 
605 trampTemplate *installBaseTrampSpecial(const instPoint *&location,
606                              process *proc,
607                              vector<instruction> &extra_instrs) 
608 {
609     unsigned currAddr;
610     instruction *code;
611     instruction *temp;
612
613     unsigned baseAddr = inferiorMalloc(proc, baseTemplate.size, textHeap);
614
615     if(!(location->func->isInstalled(proc))) {
616         location->func->relocateFunction(proc,location,extra_instrs);
617     }
618     else if(!location->relocated_){
619         // need to find new instPoint for location...it has the pre-relocated
620         // address of the instPoint
621         location->func->modifyInstPoint(location,proc);      
622     }
623
624     code = new instruction[baseTemplate.size];
625     memcpy((char *) code, (char*) baseTemplate.trampTemp, baseTemplate.size);
626
627     for (temp = code, currAddr = baseAddr; 
628         (currAddr - baseAddr) < (unsigned) baseTemplate.size;
629         temp++, currAddr += sizeof(instruction)) {
630
631         if (temp->raw == EMULATE_INSN) {
632             if (location->isBranchOut) {
633                 // the original instruction is a branch that goes out of a 
634                 // function.  We don't relocate the original instruction. We 
635                 // only get to the tramp is the branch is taken, so we generate
636                 // a unconditional branch to the target of the original 
637                 // instruction here 
638                 assert(location->branchTarget);
639                 int disp = location->branchTarget - currAddr;
640
641                 generateBranchInsn(temp, disp);
642                 disp = temp->branch.disp22;
643                 continue;
644             }
645             else {
646                 *temp = location->originalInstruction;
647                 Address fromAddress = location->addr;
648                 relocateInstruction(temp, fromAddress, currAddr, proc);
649                 if (location->isDelayed) {
650                     /* copy delay slot instruction into tramp instance */
651                     currAddr += sizeof(instruction);  
652                     *++temp = location->delaySlotInsn;
653                 }
654                 if (location->callAggregate) {
655                     /* copy invalid insn with aggregate size in it */
656                     currAddr += sizeof(instruction);  
657                     *++temp = location->aggregateInsn;
658                 }
659             }
660         } else if (temp->raw == RETURN_INSN) {
661             generateBranchInsn(temp, 
662                 (location->addr+ sizeof(instruction) - currAddr));
663             if (location->isDelayed) {
664                 /* skip the delay slot instruction */
665                 temp->branch.disp22 += 1;
666             }
667             if (location->callAggregate) {
668                 /* skip the aggregate size slot */
669                 temp->branch.disp22 += 1;
670             }
671         } else if (temp->raw == SKIP_PRE_INSN) {
672           unsigned offset;
673           offset = baseAddr+baseTemplate.updateCostOffset-currAddr;
674           generateBranchInsn(temp,offset);
675         } else if (temp->raw == SKIP_POST_INSN) {
676           unsigned offset;
677           offset = baseAddr+baseTemplate.returnInsOffset-currAddr;
678           generateBranchInsn(temp,offset);
679         } else if (temp->raw == UPDATE_COST_INSN) {
680             
681             baseTemplate.costAddr = currAddr;
682             generateNOOP(temp);
683         } else if ((temp->raw == LOCAL_PRE_BRANCH) ||
684                    (temp->raw == GLOBAL_PRE_BRANCH) ||
685                    (temp->raw == LOCAL_POST_BRANCH) ||
686                    (temp->raw == GLOBAL_POST_BRANCH)) {
687 #if defined(MT_THREAD)
688             if ((temp->raw == LOCAL_PRE_BRANCH) ||
689                 (temp->raw == LOCAL_POST_BRANCH)) {
690                 temp -= NUM_INSN_MT_PREAMBLE;
691                 unsigned numIns=0;
692                 generateMTpreamble((char *)temp, numIns, proc);
693                 temp += NUM_INSN_MT_PREAMBLE;
694             }
695 #endif
696             /* fill with no-op */
697             generateNOOP(temp);
698         }
699     }
700     // TODO cast
701     proc->writeDataSpace((caddr_t)baseAddr, baseTemplate.size,(caddr_t) code);
702
703     delete [] code;
704
705     trampTemplate *baseInst = new trampTemplate;
706     *baseInst = baseTemplate;
707     baseInst->baseAddr = baseAddr;
708     return baseInst;
709 }
710
711 /*
712  * Allocate the space for the base Trampoline, and generate the instruction
713  * we need for modifying the code segment
714  *
715  */
716 trampTemplate *findAndInstallBaseTramp(process *proc, 
717                                  instPoint *&location,
718                                  returnInstance *&retInstance,
719                                  bool)
720 {
721     Address adr = location->addr;
722     trampTemplate *ret;
723     retInstance = NULL;
724     if (!proc->baseMap.defines((const instPoint *)location)) {
725
726         if (location->func->isTrapFunc()) {
727             // get the base Address of this function if it is a 
728             // shared object
729             Address baseAddress = 0;
730             if(!(proc->getBaseAddress(location->image_ptr,baseAddress))){
731                 // TODO: what should be done here?      
732                 logLine("Error:findAndInstallBaseTramp call getBaseAddress\n"); 
733             }
734             // Install Base Tramp for the functions which are 
735             // relocated to the heap.
736             vector<instruction> extra_instrs;
737
738             ret = installBaseTrampSpecial(location, proc,extra_instrs);
739
740             // add a branch from relocated function to the base tramp
741             // if function was just relocated than location has old address
742             // otherwise location will have address in already relocated func
743             if(!(location->func->isInstalled(proc))){
744                 if (location->isBranchOut){
745                     changeBranch(proc, location->addr, 
746                           (int) ret->baseAddr, location->originalInstruction);
747                 } else {
748                     generateBranch(proc, location->addr, (int)ret->baseAddr);
749                 }
750             }
751             else {  // location's address is correct...it is in the heap
752                 if (location->isBranchOut){
753                     changeBranch(proc, location->addr, 
754                           (int) ret->baseAddr, location->originalInstruction);
755                 } else {
756                     generateBranch(proc, location->addr, (int)ret->baseAddr);
757                 }
758             }
759
760             // If for this process, a call to the relocated function has not
761             // yet be installed in its original location, then genterate the
762             // following instructions at the begining of the function:
763             //   SAVE;             CALL;         RESTORE.
764             // so that it would jump the start of the relocated function
765             // which is in heap.
766             if(!(location->func->isInstalled(proc))){
767                 location->func->setInstalled(proc);
768                 u_int e_size = extra_instrs.size();
769                 instruction *insn = new instruction[3 + e_size];
770                 Address adr = location-> func -> getAddress(0);
771                 genImmInsn(insn, SAVEop3, REG_SP, -112, REG_SP);
772                 generateCallInsn(insn+1, adr+baseAddress+4, 
773                                  location->func->getAddress(proc));
774                 genSimpleInsn(insn+2, RESTOREop3, 0, 0, 0); 
775                 for(u_int i=0; i < e_size; i++){
776                     insn[3+i] = extra_instrs[i];
777                 }
778                 retInstance = new returnInstance((instructUnion *)insn, 
779                                          (3+e_size)*sizeof(instruction), 
780                                          adr+baseAddress, 
781                                          location->func->size());
782                 assert(retInstance);
783
784                 //cerr << "created a new return instance (relocated fn)!" << endl;
785             }
786
787         } else {
788
789             // compute the real from address if this instrumentation
790             // point is from a shared object image
791             Address baseAddress = 0;
792             if(proc->getBaseAddress(location->image_ptr,baseAddress)){
793                 adr += baseAddress;             
794             }
795
796             // Install base tramp for all the other regular functions. 
797             ret = installBaseTramp(location, proc);
798
799             if (location->leaf) {
800                 // if it is the leaf function, we need to generate
801                 // the following instruction sequence:
802                 //     SAVE;      CALL;      NOP.
803
804                 if (location -> isLongJump == false) {
805                     instruction *insn = new instruction;
806                     generateBranchInsn(insn, (int)(ret->baseAddr-location->addr));
807                     retInstance = new returnInstance((instructUnion *)insn,
808                                                      sizeof(instruction), adr, 
809                                                      sizeof(instruction));
810                 } else {
811                     instruction *insn = new instruction[3];
812                     genImmInsn(insn, SAVEop3, REG_SP, -112, REG_SP);
813                     generateCallInsn(insn+1, adr+4, (int) ret->baseAddr);
814                     generateNOOP(insn+2);
815                     retInstance = new returnInstance((instructUnion *)insn, 
816                                                      3*sizeof(instruction), adr, 
817                                                      3*sizeof(instruction));
818                     
819                 }
820                 
821                 assert(retInstance);
822
823                 //cerr << "created a new return instance (leaf)!" << endl;
824             } else {
825                 // Otherwise,
826                 // Generate branch instruction from the application to the
827                 // base trampoline and no SAVE instruction is needed
828                 
829                 if (in1BranchInsnRange(adr, ret->baseAddr)) {
830                     // make sure that the isLongJump won't be true
831                     // which only is possible for shlib entry point 
832                     assert(location->isLongJump == false);
833                     instruction *insn = new instruction;
834                     if (location -> ipType == functionEntry) {
835                         generateBranchInsn(insn, (int)(ret->baseAddr 
836                                         - location->addr+sizeof(instruction))); 
837                         retInstance = new returnInstance((instructUnion *)insn,
838                                                          sizeof(instruction), 
839                                                          adr - sizeof(instruction), 
840                                                          sizeof(instruction));
841                     } else {
842                         generateBranchInsn(insn, (int)(ret->baseAddr-location->addr));
843                         retInstance = new returnInstance((instructUnion *)insn,
844                                                          sizeof(instruction), 
845                                                          adr, 
846                                                          sizeof(instruction));
847                     }
848                 } else {
849                     instruction *insn = new instruction[2];     
850                     generateCallInsn(insn, adr, (int) ret->baseAddr);
851                     if (location -> ipType == functionEntry) {
852                         if (location -> isLongJump)
853                             generateNOOP(insn+1);
854                         else
855                             genSimpleInsn(insn+1, RESTOREop3, 0, 0, 0);
856                     } else
857                         generateNOOP(insn+1);
858                     retInstance = new returnInstance((instructUnion *)insn, 
859                                                      2*sizeof(instruction), adr, 
860                                                      2*sizeof(instruction));
861                     assert(retInstance);
862                     
863                     //cerr << "created a new return instance (normal)!" << endl;
864                 }
865             }
866         }
867
868         proc->baseMap[(const instPoint *)location] = ret;
869         
870     } else {
871         ret = proc->baseMap[(const instPoint *)location];
872     }
873     
874     return(ret);
875 }
876
877 /*
878  * Install a single tramp.
879  *
880  */
881 void installTramp(instInstance *inst, char *code, int codeSize) 
882 {
883     totalMiniTramps++;
884     insnGenerated += codeSize/sizeof(int);
885     
886     // TODO cast
887     (inst->proc)->writeDataSpace((caddr_t)inst->trampBase, codeSize, code);
888
889     unsigned atAddr;
890     if (inst->when == callPreInsn) {
891         if (inst->baseInstance->prevInstru == false) {
892             atAddr = inst->baseInstance->baseAddr+baseTemplate.skipPreInsOffset;
893             inst->baseInstance->cost += inst->baseInstance->prevBaseCost;
894             inst->baseInstance->prevInstru = true;
895             generateNoOp(inst->proc, atAddr);
896         }
897     } else {
898         if (inst->baseInstance->postInstru == false) {
899             atAddr = inst->baseInstance->baseAddr+baseTemplate.skipPostInsOffset; 
900             inst->baseInstance->cost += inst->baseInstance->postBaseCost;
901             inst->baseInstance->postInstru = true;
902             generateNoOp(inst->proc, atAddr);
903         }
904     }
905 }
906
907
908 unsigned emitFuncCall(opCode op, 
909                       registerSpace *rs,
910                       char *i, unsigned &base, 
911                       const vector<AstNode *> &operands, 
912                       const string &callee, process *proc,
913                       bool noCost)
914 {
915         assert(op == callOp);
916         unsigned addr;
917         bool err;
918         vector <reg> srcs;
919
920         addr = proc->findInternalAddress(callee, false, err);
921
922         if (err) {
923             pdFunction *func = proc->findOneFunction(callee);
924             if (!func) {
925                 ostrstream os(errorLine, 1024, ios::out);
926                 os << "Internal error: unable to find addr of " << callee << endl;
927                 logLine(errorLine);
928                 showErrorCallback(80, (const char *) errorLine);
929                 P_abort();
930             }
931             // TODO: is this correct or should we get relocated address?
932             addr = func->getAddress(0);
933         }
934         
935         for (unsigned u = 0; u < operands.size(); u++)
936             srcs += operands[u]->generateCode(proc, rs, i, base, noCost);
937
938         // TODO cast
939         instruction *insn = (instruction *) ((void*)&i[base]);
940
941         for (unsigned u=0; u<srcs.size(); u++){
942             if (u >= 5) {
943                  string msg = "Too many arguments to function call in instrumentation code: only 5 arguments can be passed on the sparc architecture.\n";
944                  fprintf(stderr, msg.string_of());
945                  showErrorCallback(94,msg);
946                  cleanUpAndExit(-1);
947             }
948             genSimpleInsn(insn, ORop3, 0, srcs[u], u+8); insn++;
949             base += sizeof(instruction);
950             rs->freeRegister(srcs[u]);
951         }
952
953         // As Ling pointed out to me, the following is rather inefficient.  It does:
954         //   sethi %hi(addr), %o5
955         //   jmpl %o5 + %lo(addr), %o7   ('call' pseudo-instr)
956         //   nop
957         // We can do better:
958         //   call <addr>    (but note that the call true-instr is pc-relative jump)
959         //   nop
960         generateSetHi(insn, addr, 13); insn++;
961         genImmInsn(insn, JMPLop3, 13, LOW10(addr), 15); insn++;
962         generateNOOP(insn);
963
964         base += 3 * sizeof(instruction);
965
966         // return value is the register with the return value from the
967         //   function.
968         // This needs to be %o0 since it is back in the callers scope.
969         return(8);
970 }
971  
972 unsigned emit(opCode op, reg src1, reg src2, reg dest, char *i, unsigned &base,
973               bool noCost)
974 {
975     // TODO cast
976     instruction *insn = (instruction *) ((void*)&i[base]);
977
978     if (op == loadConstOp) {
979       // dest = src1:imm    TODO
980       if (src1 > MAX_IMM13 || src1 < MIN_IMM13) {
981             // src1 is out of range of imm13, so we need an extra instruction
982             generateSetHi(insn, src1, dest);
983             base += sizeof(instruction);
984             insn++;
985
986             // or regd,imm,regd
987
988             // Chance for optimization: we should check for LOW10(src1)==0, and
989             // if so, don't generate the following bitwise-or instruction, since
990             // in that case nothing would be done.
991
992             genImmInsn(insn, ORop3, dest, LOW10(src1), dest);
993             base += sizeof(instruction);
994         } else {
995             // really or %g0,imm,regd
996             genImmInsn(insn, ORop3, 0, src1, dest);
997
998             base += sizeof(instruction);
999         }
1000     } else if (op ==  loadOp) {
1001         // dest = [src1]   TODO
1002         generateSetHi(insn, src1, dest);
1003         insn++;
1004
1005         generateLoad(insn, dest, LOW10(src1), dest);
1006
1007         base += sizeof(instruction)*2;
1008     } else if (op ==  loadIndirOp) {
1009         generateLoad(insn, src1, 0, dest);
1010         base += sizeof(instruction);
1011     } else if (op ==  storeOp) {
1012         insn->sethi.op = FMT2op;
1013         insn->sethi.rd = src2;
1014         insn->sethi.op2 = SETHIop2;
1015         insn->sethi.imm22 = HIGH22(dest);
1016         insn++;
1017
1018         generateStore(insn, src1, src2, LOW10(dest));
1019
1020         base += sizeof(instruction)*2;
1021     } else if (op ==  storeIndirOp) {
1022         generateStore(insn, src1, dest, 0);
1023         base += sizeof(instruction);
1024     } else if (op ==  ifOp) {
1025         // cmp src1,0
1026         genSimpleInsn(insn, SUBop3cc, src1, 0, 0); insn++;
1027
1028         insn->branch.op = 0;
1029         insn->branch.cond = BEcond;
1030         insn->branch.op2 = BICCop2;
1031         insn->branch.anneal = false;
1032         insn->branch.disp22 = dest/4;
1033         insn++;
1034
1035         generateNOOP(insn);
1036         base += sizeof(instruction)*3;
1037         return(base - 2*sizeof(instruction));
1038     } else if (op ==  updateCostOp) {
1039         // generate code to update the observed cost.
1040         if (!noCost) {
1041            // sethi %hi(dest), %l0
1042            generateSetHi(insn, dest, REG_L0);
1043            base += sizeof(instruction);
1044            insn++;
1045   
1046            // ld [%l0+ lo(dest)], %l1
1047            generateLoad(insn, REG_L0, LOW10(dest), REG_L1);
1048            base += sizeof(instruction);
1049            insn++;
1050   
1051            // update value (src1 holds the cost, in cycles; e.g. 19)
1052            if (src1 <= MAX_IMM13) {
1053               genImmInsn(insn, ADDop3, REG_L1, src1, REG_L1);
1054               base += sizeof(instruction);
1055               insn++;
1056
1057               generateNOOP(insn);
1058               base += sizeof(instruction);
1059               insn++;
1060
1061               generateNOOP(insn);
1062               base += sizeof(instruction);
1063               insn++;
1064            } else {
1065               // load in two parts
1066               generateSetHi(insn, src1, REG_L2);
1067               base += sizeof(instruction);
1068               insn++;
1069
1070               // or regd,imm,regd
1071               genImmInsn(insn, ORop3, REG_L2, LOW10(src1), REG_L2);
1072               base += sizeof(instruction);
1073               insn++;
1074
1075               // now add it
1076               genSimpleInsn(insn, ADDop3, REG_L1, REG_L2, REG_L1);
1077               base += sizeof(instruction);
1078               insn++;
1079            }
1080   
1081            // store result st %l1, [%l0+ lo(dest)];
1082            generateStore(insn, REG_L1, REG_L0, LOW10(dest));
1083            base += sizeof(instruction);
1084            insn++;
1085         } // if (!noCost)
1086     } else if (op ==  trampPreamble) {
1087 #ifdef ndef
1088         // save and restore are done inthe base tramp now
1089         genImmInsn(insn, SAVEop3, REG_SP, -112, REG_SP);
1090         base += sizeof(instruction);
1091         insn++;
1092
1093         // generate code to save global registers
1094         for (unsigned u = 0; u < 4; u++) {
1095           genStoreD(insn, 2*u, REG_FP, - (8 + 8*u));
1096           base += sizeof(instruction);
1097           insn++;
1098         }
1099 #endif
1100     } else if (op ==  trampTrailer) {
1101 #ifdef ndef
1102         // save and restore are done inthe base tramp now
1103         // generate code to restore global registers
1104         for (unsigned u = 0; u < 4; u++) {
1105           genLoadD(insn, REG_FP, - (8 + 8*u), 2*u);
1106           base += sizeof(instruction);
1107           insn++;
1108         }
1109
1110         // sequence: restore; nop; b,a back to base tramp; nop
1111         // we can do better.  How about putting the restore in
1112         // the delay slot of the branch instruction, as in:
1113         // b <back to base tramp>; restore
1114         genSimpleInsn(insn, RESTOREop3, 0, 0, 0); 
1115         base += sizeof(instruction);
1116         insn++;
1117
1118         generateNOOP(insn);
1119         base += sizeof(instruction);
1120         insn++;
1121 #endif
1122         // dest is in words of offset and generateBranchInsn is bytes offset
1123         generateBranchInsn(insn, dest << 2);
1124         base += sizeof(instruction);
1125         insn++;
1126
1127         // add no-op, SS-5 sometimes seems to try to decode this insn - jkh 2/14
1128         generateNOOP(insn);
1129         insn++;
1130         base += sizeof(instruction);
1131
1132         return(base -  2 * sizeof(instruction));
1133     } else if (op == noOp) {
1134         generateNOOP(insn);
1135         base += sizeof(instruction);
1136     } else if (op == getParamOp) {
1137 #if defined(MT_THREAD)
1138         // saving CT/vector address on the stack
1139         generateStore(insn, REG_MT, REG_FP, -40);
1140         insn++;
1141 #endif
1142         // first 8 parameters are in register 24 ....
1143         genSimpleInsn(insn, RESTOREop3, 0, 0, 0);
1144         insn++;
1145
1146         generateStore(insn, 24+src1, REG_SP, 68+4*src1); 
1147         insn++;
1148               
1149         genImmInsn(insn, SAVEop3, REG_SP, -112, REG_SP);
1150         insn++;
1151
1152         generateLoad(insn, REG_SP, 112+68+4*src1, 24+src1); 
1153         insn++;
1154
1155 #if defined(MT_THREAD)
1156         // restoring CT/vector address back in REG_MT
1157         generateLoad(insn, REG_FP, -40, REG_MT);
1158         insn++;
1159 #endif
1160
1161 #if defined(MT_THREAD)
1162         base += 6*sizeof(instruction);
1163 #else
1164         base += 4*sizeof(instruction);
1165 #endif
1166         
1167         if (src1 <= 8) {
1168             return(24+src1);
1169         }
1170         
1171         abort();
1172     } else if (op == getSysParamOp) {
1173         
1174         if (src1 <= 8) {
1175             return(24+src1);
1176         }       
1177     } else if (op == getRetValOp) {
1178         // return value is in register 24
1179         genSimpleInsn(insn, RESTOREop3, 0, 0, 0);
1180         insn++;
1181
1182         generateStore(insn, 24, REG_SP, 68); 
1183         insn++;
1184               
1185         genImmInsn(insn, SAVEop3, REG_SP, -112, REG_SP);
1186         insn++;
1187
1188         generateLoad(insn, REG_SP, 112+68, 24); 
1189         insn++;
1190
1191         base += 4*sizeof(instruction);
1192
1193         return(24);
1194
1195     } else if (op == getSysRetValOp) {
1196         return(24);
1197     } else if (op == saveRegOp) {
1198         // should never be called for this platform.
1199         abort();
1200     } else {
1201       int op3=-1;
1202         switch (op) {
1203             // integer ops
1204             case plusOp:
1205                 op3 = ADDop3;
1206                 break;
1207
1208             case minusOp:
1209                 op3 = SUBop3;
1210                 break;
1211
1212             case timesOp:
1213                 op3 = SMULop3;
1214                 break;
1215
1216             case divOp:
1217                 op3 = SDIVop3;
1218                 break;
1219
1220             // Bool ops
1221             case orOp:
1222                 op3 = ORop3;
1223                 break;
1224
1225             case andOp:
1226                 op3 = ANDop3;
1227                 break;
1228
1229             // rel ops
1230             // For a particular condition (e.g. <=) we need to use the
1231             // the opposite in order to get the right value (e.g. for >=
1232             // we need BLTcond) - naim
1233             case eqOp:
1234                 genRelOp(insn, BNEcond, src1, src2, dest, base);
1235                 return(0);
1236                 break;
1237
1238             case neOp:
1239                 genRelOp(insn, BEcond, src1, src2, dest, base);
1240                 return(0);
1241                 break;
1242
1243             case lessOp:
1244                 genRelOp(insn, BGEcond, src1, src2, dest, base);
1245                 return(0);
1246                 break;
1247
1248             case leOp:
1249                 genRelOp(insn, BGTcond, src1, src2, dest, base);
1250                 return(0);
1251                 break;
1252
1253             case greaterOp:
1254                 genRelOp(insn, BLEcond, src1, src2, dest, base);
1255                 return(0);
1256                 break;
1257
1258             case geOp:
1259                 genRelOp(insn, BLTcond, src1, src2, dest, base);
1260                 return(0);
1261                 break;
1262
1263             default:
1264                 abort();
1265                 break;
1266         }
1267         genSimpleInsn(insn, op3, src1, src2, dest);
1268
1269         base += sizeof(instruction);
1270       }
1271     return(0);
1272 }
1273
1274 /*
1275  * Find the instPoints of this function.
1276  */
1277 bool pdFunction::findInstPoints(const image *owner) {
1278
1279    if (size() == 0) {
1280      return false;
1281    }
1282
1283    leaf = true;
1284    Address adr;
1285    Address adr1 = getAddress(0);
1286    instruction instr;
1287    instr.raw = owner->get_instruction(adr1);
1288    if (!IS_VALID_INSN(instr))
1289      return false;
1290
1291    // If it contains an instruction, I assume it would be s system call
1292    // which will be treat differently. 
1293    isTrap = false;
1294    bool func_entry_found = false;
1295
1296    for ( ; adr1 < getAddress(0) + size(); adr1 += 4) {
1297        instr.raw = owner->get_instruction(adr1);
1298
1299        // If there's an TRAP instruction in the function, we 
1300        // assume that it is an system call and will relocate it 
1301        // to the heap
1302        if (isInsnType(instr, TRAPmask, TRAPmatch)) {
1303            isTrap = true;
1304            return findInstPoints(owner, getAddress(0), 0);
1305        } 
1306
1307        // TODO: This is a hacking for the solaris(solaris2.5 actually)
1308        // We will relocate that function if the function has been 
1309        // tail-call optimazed.
1310        // (Actully, the reason of this is that the system calls like 
1311        //  read, write, etc have the tail-call optimazation to call
1312        //  the _read, _write etc. which contain the TRAP instruction 
1313        //  This is only done if libc is statically linked...if the
1314        //  libTag is set, otherwise we instrument read and _read
1315        //  both for the dynamically linked case
1316        if (isLibTag()) {
1317            if (isCallInsn(instr)) {
1318                instruction nexti; 
1319                nexti.raw = owner->get_instruction(adr1+4);
1320                
1321                if (nexti.rest.op == 2 
1322                    && ((nexti.rest.op3 == ORop3 && nexti.rest.rd == 15)
1323                        || nexti.rest.op3 == RESTOREop3)) {
1324                    isTrap = true;
1325                    return findInstPoints(owner, getAddress(0), 0);
1326                }
1327            }   
1328        }
1329
1330        // The function Entry is defined as the first SAVE instruction plus
1331        // the instructions after this.
1332        // ( The first instruction for the nonleaf function is not 
1333        //   necessarily a SAVE instruction. ) 
1334        if (isInsnType(instr, SAVEmask, SAVEmatch) && !func_entry_found) {
1335
1336            leaf = false;
1337            func_entry_found = true;
1338            funcEntry_ = new instPoint(this, instr, owner, adr1, true, leaf, 
1339                                       functionEntry);
1340            adr = adr1;
1341            assert(funcEntry_);
1342        }
1343    }
1344
1345    // If there's no SAVE instruction found, this is a leaf function and
1346    // and function Entry will be defined from the first instruction
1347    if (leaf) {
1348        adr = getAddress(0);
1349        instr.raw = owner->get_instruction(adr);
1350        funcEntry_ = new instPoint(this, instr, owner, adr, true, leaf, functionEntry);
1351        assert(funcEntry_);
1352    }
1353
1354    for ( ; adr < getAddress(0) + size(); adr += sizeof(instruction)) {
1355
1356      instr.raw = owner->get_instruction(adr);
1357
1358      bool done;
1359
1360      // check for return insn and as a side affect decide if we are at the
1361      //   end of the function.
1362      if (isReturnInsn(owner, adr, done)) {
1363        // define the return point
1364        funcReturns += new instPoint(this, instr, owner, adr, false, leaf, 
1365                                     functionExit);
1366
1367      } else if (instr.branch.op == 0 
1368                 && (instr.branch.op2 == 2 || instr.branch.op2 == 6) 
1369                 && (instr.branch.cond == 0 ||instr.branch.cond == 8)) {
1370        // find if this branch is going out of the function
1371        int disp = instr.branch.disp22;
1372        Address target = adr +  (disp << 2);
1373        if ((target < (getAddress(0)))  
1374            || (target >= (getAddress(0) + size()))) {
1375          instPoint *point = new instPoint(this, instr, owner, adr, false, leaf, 
1376                                           functionExit);
1377          funcReturns += point;
1378        }
1379
1380      } else if (isCallInsn(instr)) {
1381
1382        // if the call target is the address of the call instruction
1383        // then this is not something that we can instrument...
1384        // this occurs in functions with code that is modifined when 
1385        // they are loaded by the run-time linker, or when the .init
1386        // section is executed.  In this case the instructions in the
1387        // parsed image file are different from the ones in the executable
1388        // process.
1389        if(instr.call.op == CALLop) { 
1390            Address call_target = adr + (instr.call.disp30 << 2);
1391            if(call_target == adr){ 
1392                 return false;
1393        }}
1394        // first, check for tail-call optimization: a call where the instruction 
1395        // in the delay slot write to register %o7(15), usually just moving
1396        // the caller's return address, or doing a restore
1397        // Tail calls are instrumented as return points, not call points.
1398
1399
1400        instruction nexti; 
1401        nexti.raw = owner->get_instruction(adr+4);
1402
1403        if (nexti.rest.op == 2 
1404            && ((nexti.rest.op3 == ORop3 && nexti.rest.rd == 15)
1405               || nexti.rest.op3 == RESTOREop3)) {
1406          //fprintf(stderr, "#### Tail-call optimization in function %s, addr %x\n",
1407          //     prettyName().string_of(), adr);
1408          funcReturns += new instPoint(this, instr, owner, adr, false, leaf, 
1409                                       functionExit);
1410
1411        } else {
1412          // define a call point
1413          // this may update address - sparc - aggregate return value
1414          // want to skip instructions
1415          bool err;
1416          int dummyId;
1417          instPoint *blah = 0;
1418          adr = newCallPoint(adr, instr, owner, err, dummyId, adr,0,blah);
1419        }
1420      }
1421
1422      else if (isInsnType(instr, JMPLmask, JMPLmatch)) {
1423        /* A register indirect jump. Some jumps may exit the function 
1424           (e.g. read/write on SunOS). In general, the only way to 
1425           know if a jump is exiting the function is to instrument
1426           the jump to test if the target is outside the current 
1427           function. Instead of doing this, we just check the 
1428           previous two instructions, to see if they are loading
1429           an address that is out of the current function.
1430           This should catch the most common cases (e.g. read/write).
1431           For other cases, we would miss a return point.
1432
1433           This is the case considered:
1434
1435              sethi addr_hi, r
1436              or addr_lo, r, r
1437              jump r
1438         */
1439
1440        reg jumpreg = instr.rest.rs1;
1441        instruction prev1;
1442        instruction prev2;
1443
1444        prev1.raw = owner->get_instruction(adr-4);
1445        prev2.raw = owner->get_instruction(adr-8);
1446
1447        unsigned targetAddr;
1448
1449        if (instr.rest.rd == 0 && (instr.rest.i == 1 || instr.rest.rs2 == 0)
1450            && prev2.sethi.op == FMT2op && prev2.sethi.op2 == SETHIop2 
1451            && prev2.sethi.rd == (unsigned)jumpreg
1452            && prev1.rest.op == RESTop 
1453            && prev1.rest.rd == (unsigned)jumpreg && prev1.rest.i == 1
1454            && prev1.rest.op3 == ORop3 && prev1.rest.rs1 == (unsigned)jumpreg) {
1455
1456          targetAddr = (prev2.sethi.imm22 << 10) & 0xfffffc00;
1457          targetAddr |= prev1.resti.simm13;
1458          if ((targetAddr<getAddress(0))||(targetAddr>=(getAddress(0)+size()))){
1459            instPoint *point = new instPoint(this, instr, owner, adr, false, 
1460                                             leaf, functionExit);
1461            funcReturns += point;
1462          }
1463        }
1464
1465      }
1466  }
1467
1468  return (checkInstPoints(owner)); 
1469 }
1470
1471 /*
1472  * Check all the instPoints within this function to see if there's 
1473  * any conficts happen.
1474  */
1475 bool pdFunction::checkInstPoints(const image *owner) {
1476
1477     // Our own library function, skip the test.
1478     if (prettyName_.prefixed_by("DYNINST")) 
1479         return true;
1480
1481     // The function is too small to be worthing instrumenting.
1482     if (size() <= 12)
1483         return false;
1484
1485     // No function return! return false;
1486     if (sizeof(funcReturns) == 0)
1487         return false;
1488
1489     instruction instr;
1490     Address adr = getAddress(0);
1491
1492     bool retl_inst = false;
1493     // Check if there's any branch instruction jump to the middle
1494     // of the instruction sequence in the function entry point
1495     // and function exit point.
1496     for ( ; adr < getAddress(0) + size(); adr += sizeof(instruction)) {
1497
1498         instr.raw = owner->get_instruction(adr);
1499         if(isInsnType(instr, RETLmask, RETLmatch)) retl_inst = true;
1500
1501         if (isInsnType(instr, BRNCHmask, BRNCHmatch)||
1502             isInsnType(instr, FBRNCHmask, FBRNCHmatch)) {
1503
1504             int disp = instr.branch.disp22;
1505             Address target = adr + (disp << 2);
1506
1507             if ((target > funcEntry_->addr)&&
1508                 (target < (funcEntry_->addr + funcEntry_->size))) {
1509                 if (adr > (funcEntry_->addr+funcEntry_->size))
1510                     //cout << "Function " << prettyName_ <<" entry" << endl;
1511                     return false;
1512             }
1513
1514             for (u_int i = 0; i < funcReturns.size(); i++) {
1515                 if ((target > funcReturns[i]->addr)&&
1516                     (target < (funcReturns[i]->addr + funcReturns[i]->size))) {
1517                     if ((adr < funcReturns[i]->addr)||
1518                         (adr > (funcReturns[i]->addr + funcReturns[i]->size)))
1519                         return false;
1520                 }
1521             }
1522         }
1523     }
1524
1525     // if there is a retl instruction and we don't think this is a leaf
1526     // function then this is a way messed up function...well, at least we
1527     // we can't deal with this...the only example I can find is _cerror
1528     // and _cerror64 in libc.so.1
1529     if(retl_inst && !leaf){
1530          return false;
1531     }
1532
1533     // check that no instrumentation points could overlap
1534     Address func_entry = funcEntry_->addr + funcEntry_->size; 
1535     for (u_int i = 0; i < funcReturns.size(); i++) {
1536         if(func_entry >= funcReturns[i]->addr){
1537            return false;
1538         }
1539         if(i > 1){ // check if return points overlap
1540             Address prev_exit = funcReturns[i-1]->addr+funcReturns[i-1]->size;  
1541             if(funcReturns[i]->addr >= prev_exit) {
1542                 return false;
1543             } 
1544         }
1545     }
1546
1547     return true;        
1548 }
1549
1550
1551 /* The maximum length of relocatable function is 1k instructions */  
1552 // This function is to find the inst Points for a function
1553 // that will be relocated if it is instrumented. 
1554 bool pdFunction::findInstPoints(const image *owner, Address newAdr, process*){
1555
1556    int i;
1557    if (size() == 0) {
1558      return false;
1559    }
1560    relocatable_ = true;
1561
1562    Address adr = getAddress(0);
1563    instruction instr;
1564    instr.raw = owner->get_instruction(adr);
1565    if (!IS_VALID_INSN(instr))
1566      return false;
1567    
1568    if (size() <= 3*sizeof(instruction)) 
1569        return false;
1570
1571    instPoint *point = new instPoint(this, instr, owner, newAdr, true, 
1572                                     functionEntry, adr);
1573
1574    funcEntry_ = point;
1575
1576    // if the second instruction in a relocated function is a call instruction
1577    // or a branch instruction, then we can't deal with this 
1578    if(size() > sizeof(instruction)){
1579        Address second_adr = adr + sizeof(instruction);
1580        instruction second_instr;
1581        second_instr.raw =  owner->get_instruction(second_adr); 
1582        if ((isCallInsn(second_instr)) || 
1583                       (second_instr.branch.op == 0 && 
1584                       (second_instr.branch.op2 == 2 || 
1585                       second_instr.branch.op2 == 6))) {
1586            return false;
1587        }
1588    }
1589    
1590    assert(funcEntry_);
1591    int retId = 0;
1592    int callsId = 0; 
1593
1594    for (i = 0; adr < getAddress(0) + size(); adr += sizeof(instruction),  
1595         newAdr += sizeof(instruction), i++) {
1596
1597      instr.raw = owner->get_instruction(adr);
1598      newInstr[i] = instr;
1599      bool done;
1600
1601      // check for return insn and as a side affect decide if we are at the
1602      //   end of the function.
1603      if (isReturnInsn(owner, adr, done)) {
1604        // define the return point
1605        instPoint *point = new instPoint(this, instr, owner, newAdr, false, 
1606                                         functionExit, adr);
1607        funcReturns += point;
1608        funcReturns[retId] -> instId = retId++;
1609      } else if (instr.branch.op == 0 
1610                 && (instr.branch.op2 == 2 || instr.branch.op2 == 6)) {
1611        // find if this branch is going out of the function
1612        int disp = instr.branch.disp22;
1613        Address target = adr + (disp << 2);
1614        if (target < getAddress(0) || target >= getAddress(0) + size()) {
1615            instPoint *point = new instPoint(this, newInstr[i], owner, 
1616                                             newAdr, false, 
1617                                             functionExit, adr);
1618            if ((instr.branch.cond != 0) && (instr.branch.cond != 8)) {  
1619                point->isBranchOut = true;
1620                point->branchTarget = target;
1621            }
1622            funcReturns += point;
1623            funcReturns[retId] -> instId = retId++;
1624        }
1625
1626      } else if (isCallInsn(instr)) {
1627
1628        // first, check for tail-call optimization: a call where the instruction 
1629        // in the delay slot write to register %o7(15), usually just moving
1630        // the caller's return address, or doing a restore
1631        // Tail calls are instrumented as return points, not call points.
1632        instruction nexti; 
1633        nexti.raw = owner->get_instruction(adr+4);
1634
1635        if (nexti.rest.op == 2 
1636            && ((nexti.rest.op3 == ORop3 && nexti.rest.rd == 15)
1637               || nexti.rest.op3 == RESTOREop3)) {
1638
1639            instPoint *point = new instPoint(this, instr, owner, newAdr, false,
1640                                       functionExit, adr);
1641            funcReturns += point;
1642            funcReturns[retId] -> instId = retId++;
1643
1644        } else {
1645          // if this is a call instr to a location within the function, and if 
1646          // the offest is not 8 then do not define this function 
1647          if(instr.call.op == CALLop){ 
1648            Address call_target = adr + (instr.call.disp30 << 2);
1649            if((call_target >= getAddress(0)) 
1650               && (call_target <= (getAddress(0)+size()))){ 
1651               if((instr.call.disp30 << 2) != 2*sizeof(instruction)) {
1652                 return false;
1653               }
1654            }
1655          }
1656          // define a call point
1657          // this may update address - sparc - aggregate return value
1658          // want to skip instructions
1659          bool err;
1660          instPoint *blah = 0;
1661          adr = newCallPoint(newAdr, instr, owner, err, callsId, adr,0,blah);
1662          if (err)
1663            return false;
1664        }
1665      }
1666
1667      else if (isInsnType(instr, JMPLmask, JMPLmatch)) {
1668        /* A register indirect jump. Some jumps may exit the function 
1669           (e.g. read/write on SunOS). In general, the only way to 
1670           know if a jump is exiting the function is to instrument
1671           the jump to test if the target is outside the current 
1672           function. Instead of doing this, we just check the 
1673           previous two instructions, to see if they are loading
1674           an address that is out of the current function.
1675           This should catch the most common cases (e.g. read/write).
1676           For other cases, we would miss a return point.
1677
1678           This is the case considered:
1679
1680              sethi addr_hi, r
1681              or addr_lo, r, r
1682              jump r
1683         */
1684
1685          reg jumpreg = instr.rest.rs1;
1686          instruction prev1;
1687          instruction prev2;
1688          
1689          prev1.raw = owner->get_instruction(adr-4);
1690          prev2.raw = owner->get_instruction(adr-8);
1691
1692          unsigned targetAddr;
1693
1694          if (instr.rest.rd == 0 && (instr.rest.i == 1 || instr.rest.rs2 == 0)
1695              && prev2.sethi.op == FMT2op && prev2.sethi.op2 == SETHIop2 
1696              && prev2.sethi.rd == (unsigned)jumpreg
1697              && prev1.rest.op == RESTop 
1698              && prev1.rest.rd == (unsigned)jumpreg && prev1.rest.i == 1
1699              && prev1.rest.op3 == ORop3 && prev1.rest.rs1 == (unsigned)jumpreg){
1700              
1701              targetAddr = (prev2.sethi.imm22 << 10) & 0xfffffc00;
1702              targetAddr |= prev1.resti.simm13;
1703              if ((targetAddr < getAddress(0)) 
1704                  || (targetAddr >= (getAddress(0)+size()))) {
1705                  instPoint *point = new instPoint(this, instr, owner, 
1706                                                   newAdr, false,
1707                                                   functionExit, adr);
1708                  funcReturns += point;
1709                  funcReturns[retId] -> instId = retId++;
1710              }
1711          }
1712      }
1713  }
1714  return true;
1715 }
1716
1717 // This function assigns new address to instrumentation points of  
1718 // a function that has been relocated
1719 bool pdFunction::findNewInstPoints(const image *owner, 
1720                                 const instPoint *&location,
1721                                 Address newAdr,
1722                                 process *proc,
1723                                 vector<instruction> &callInstrs,
1724                                 relocatedFuncInfo *reloc_info) {
1725
1726    int i;
1727    if (size() == 0) {
1728      return false;
1729    }
1730    assert(reloc_info);
1731
1732    Address adr = getAddress(0);
1733    instruction instr;
1734    instr.raw = owner->get_instruction(adr);
1735    if (!IS_VALID_INSN(instr))
1736      return false;
1737
1738    instPoint *point = new instPoint(this, instr, owner, newAdr, true, 
1739                                     functionEntry, adr);
1740    point->relocated_ = true;
1741    // if location was the entry point then change location's value to new pt
1742    if(location == funcEntry_) { 
1743         location = point;
1744    }
1745
1746    reloc_info->addFuncEntry(point);
1747    assert(reloc_info->funcEntry());
1748    int retId = 0;
1749    int callsId = 0; 
1750
1751    // get baseAddress if this is a shared object
1752    Address baseAddress = 0;
1753    if(!(proc->getBaseAddress(owner,baseAddress))){
1754         baseAddress =0;
1755    }
1756
1757    // if we have call instructions that need to be added after the instrs
1758    // to call the relocated instruction, the first address we can use is
1759    // the address of the 4th instruction in the function
1760    Address call_start_addr = getAddress(0)+baseAddress + 3*sizeof(instruction);
1761
1762    for (i = 0; adr < getAddress(0) + size(); adr += 4,  newAdr += 4, i++) {
1763     
1764      instr.raw = owner->get_instruction(adr);
1765      newInstr[i] = instr;
1766
1767      bool done;
1768
1769      // check for return insn and as a side affect decide if we are at the
1770      //   end of the function.
1771      if (isReturnInsn(owner, adr, done)) {
1772        // define the return point
1773        instPoint *point = new instPoint(this, instr, owner, newAdr, false, 
1774                                         functionExit, adr);
1775        point->relocated_ = true;
1776        // if location was this point, change it to new point
1777        if(location == funcReturns[retId]) { 
1778            location = point;
1779        }
1780        retId++;
1781        reloc_info->addFuncReturn(point);
1782      } else if (instr.branch.op == 0 
1783                 && (instr.branch.op2 == 2 || instr.branch.op2 == 6)) {
1784        // find if this branch is going out of the function
1785        int disp = instr.branch.disp22;
1786        Address target = adr + baseAddress + (disp << 2);
1787
1788        // getAddress(0) gives the addr of the fn before it's relocated
1789        if ((target < (getAddress(0) + baseAddress)) 
1790            || (target >= (getAddress(0) + baseAddress + size()))) {
1791            // the original branch went out of the function...
1792
1793            relocateInstruction(&newInstr[i],adr+baseAddress,newAdr,proc);
1794            instPoint *point = new instPoint(this, newInstr[i], owner, 
1795                                             newAdr, false, 
1796                                             functionExit, adr);
1797            point->relocated_ = true;
1798            disp = newInstr[i].branch.disp22;
1799            if ((instr.branch.cond != 0) && (instr.branch.cond != 8)) {  
1800                point->isBranchOut = true;
1801                point->branchTarget = adr + (disp<<2);
1802            }
1803            // if location was this point, change it to new point
1804            if(location == funcReturns[retId]) { 
1805                location = point;
1806            }
1807            retId++;
1808            reloc_info->addFuncReturn(point);
1809        }
1810
1811      } else if (isCallInsn(instr)) {
1812
1813        // first, check for tail-call optimization: a call where the instruction 
1814        // in the delay slot write to register %o7(15), usually just moving
1815        // the caller's return address, or doing a restore
1816        // Tail calls are instrumented as return points, not call points.
1817        instruction nexti; 
1818        nexti.raw = owner->get_instruction(adr+4);
1819
1820        if (nexti.rest.op == 2 
1821            && ((nexti.rest.op3 == ORop3 && nexti.rest.rd == 15)
1822               || nexti.rest.op3 == RESTOREop3)) {
1823
1824             // Undoing the tail-call optimazation when the function
1825             // is relocated. Here is an example:
1826             //   before:          --->             after
1827             // ---------------------------------------------------
1828             //   call  %g1                        restore    
1829             //   restore                          st  %i0, [ %fp + 0x44 ]
1830             //                                    mov %o7 %i0
1831             //                                    call %g1 
1832             //                                    nop
1833             //                                    mov %i0,%o7
1834             //                                    st  [ %fp + 0x44 ], %i0
1835             //                              retl
1836             //                                    nop
1837             // Q: Here the assumption that register i1 is available 
1838             //    might be an question, is it?
1839             // A: I think it is appropriate because:
1840             //      (in situation A calls B and B calls C)
1841             //      The procedure C called via tail call is a leaf 
1842             //      procedure, the value arguments and return value between
1843             //      A and C are passed by register (o1...o5, o7)
1844             //      So even If B mess up the value of i0, it won't affect the
1845             //      commnucation between A and C. Also, we saved the value of
1846             //      i0 on stack and when we return from B, the value of i0
1847             //      won't be affected.
1848             //      If C is not a leaf procedure, it should be fine
1849             //      as it is.
1850             //    ( If you could give an counter-example, please
1851             //      let me know.                         --ling )
1852
1853             genSimpleInsn(&newInstr[i++], RESTOREop3, 0, 0, 0);
1854             generateStore(&newInstr[i++], 24, REG_FP, 0x44); 
1855             genImmInsn(&newInstr[i++], ORop3, 15, 0, 24); 
1856             newInstr[i++].raw = owner->get_instruction(adr);
1857             generateNOOP(&newInstr[i++]);
1858             genImmInsn(&newInstr[i++], ORop3, 24, 0, 15);
1859             generateLoad(&newInstr[i++], REG_FP, 0x44, 24);         
1860             generateJmplInsn(&newInstr[i++], 15, 8 ,0);
1861             newAdr += 28;
1862             generateNOOP(&newInstr[i]);
1863             instPoint *point = new instPoint(this, instr, owner, newAdr, false,
1864                                       functionExit, adr);
1865             point-> originalInstruction = newInstr[i-1];
1866             point-> delaySlotInsn = newInstr[i];
1867             point-> isDelayed = true;
1868             point->relocated_ = true;
1869             // if location was this point, change it to new point
1870             if(location == funcReturns[retId]) { 
1871                 location = point;
1872             }
1873             retId++;
1874             reloc_info->addFuncReturn(point);
1875        } else {
1876          // if the second instruction in the function is a call instruction
1877          // then this cannot go in the delay slot of the branch to the
1878          // base tramp, so add a noop between first and second instructions
1879          // in the relocated function (check out write in libc.so.1 for
1880          // and example of this):
1881          //
1882          //     save  %sp, -96, %sp             brach to base tramp
1883          //     call  0x73b70                   nop
1884          //                                     call 0x73b70
1885          if(adr == (getAddress(0)+4)){
1886              newInstr[i+1] = instr;
1887              generateNOOP(&newInstr[i]);
1888              i++;
1889              newAdr += 4;
1890          }
1891
1892          // if this is a call to an address within the same function, then
1893          // we need to set the 07 register to have the same value as it
1894          // would before the function was relocated
1895          // to do this we generate a call instruction back to the original
1896          // function location, and then at this location we generate a call 
1897          // instruction back to the relocated instruction.  In the delay 
1898          // slot of the second instruction the value of 07 is changed by 
1899          // the difference between the origninal call instruction, and 
1900          // the location of the call instruction back to the relocated
1901          // function.  This way the 07 register will contain the address
1902          // of the original call instruction
1903          Address call_target = adr + (instr.call.disp30 << 2);
1904          if((call_target >= getAddress(0)) 
1905                 && (call_target <= (getAddress(0) + size()))){ 
1906             assert((newInstr[i].call.disp30 << 2) == 8);
1907
1908             // generating call instruction to orginal function address
1909             // after the SAVE call RESTORE instr.s that call the relocated
1910             // function 
1911             newInstr[i].call.disp30 = ((call_start_addr -newAdr) >> 2); 
1912
1913             // generate call to relocated function from original function 
1914             // (this will get almost correct value for register 07)
1915             instruction new_inst;
1916             generateCallInsn(&new_inst,call_start_addr,
1917                              newAdr+sizeof(instruction));
1918             callInstrs += new_inst;
1919            
1920             // generate add isntruction to get correct value for 07 register 
1921             // this will go in delay slot of previous call instr.
1922             genImmInsn(&new_inst,ADDop3,REG_O7,
1923                        (adr+baseAddress-call_start_addr),REG_O7);
1924             callInstrs += new_inst;
1925             call_start_addr += 2*sizeof(instruction);
1926          }
1927          else {
1928             // otherwise, this is a call instruction to a location
1929             // outside the function
1930             bool err;
1931             relocateInstruction(&newInstr[i],adr+baseAddress,newAdr,proc);
1932             (void)newCallPoint(newAdr, newInstr[i], owner, err, 
1933                                callsId, adr,reloc_info,location);
1934             if (err) return false;
1935          }
1936        }
1937      }
1938
1939      else if (isInsnType(instr, JMPLmask, JMPLmatch)) {
1940        /* A register indirect jump. Some jumps may exit the function 
1941           (e.g. read/write on SunOS). In general, the only way to 
1942           know if a jump is exiting the function is to instrument
1943           the jump to test if the target is outside the current 
1944           function. Instead of doing this, we just check the 
1945           previous two instructions, to see if they are loading
1946           an address that is out of the current function.
1947           This should catch the most common cases (e.g. read/write).
1948           For other cases, we would miss a return point.
1949
1950           This is the case considered:
1951
1952              sethi addr_hi, r
1953              or addr_lo, r, r
1954              jump r
1955         */
1956
1957          reg jumpreg = instr.rest.rs1;
1958          instruction prev1;
1959          instruction prev2;
1960          
1961          prev1.raw = owner->get_instruction(adr-4);
1962          prev2.raw = owner->get_instruction(adr-8);
1963
1964          unsigned targetAddr;
1965
1966          if (instr.rest.rd == 0 && (instr.rest.i == 1 || instr.rest.rs2 == 0)
1967              && prev2.sethi.op == FMT2op && prev2.sethi.op2 == SETHIop2 
1968              && prev2.sethi.rd == (unsigned)jumpreg
1969              && prev1.rest.op == RESTop 
1970              && prev1.rest.rd == (unsigned)jumpreg && prev1.rest.i == 1
1971              && prev1.rest.op3 == ORop3 && prev1.rest.rs1 == (unsigned)jumpreg){
1972              
1973              targetAddr = (prev2.sethi.imm22 << 10) & 0xfffffc00;
1974              targetAddr |= prev1.resti.simm13;
1975              if ((targetAddr < getAddress(0)) 
1976                  || (targetAddr >= (getAddress(0)+size()))) {
1977                  instPoint *point = new instPoint(this, instr, owner, 
1978                                                   newAdr, false,
1979                                                   functionExit, adr);
1980                  point->relocated_ = true;
1981                  // if location was this point, change it to new point
1982                  if(location == funcReturns[retId]) { 
1983                      location = point;
1984                  }
1985                  retId++;
1986                  reloc_info->addFuncReturn(point);
1987              }
1988          }
1989      }
1990  }
1991    
1992    return true;
1993 }