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