initial dyninstAPI commit for code coverage
[dyninst.git] / dyninstAPI / src / inst-sparc.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 // $Id: inst-sparc.C,v 1.107 2001/09/07 21:15:08 tikir Exp $
43
44 #include "dyninstAPI/src/inst-sparc.h"
45 #include "dyninstAPI/src/instPoint.h"
46
47 #include "dyninstAPI/src/FunctionExpansionRecord.h"
48
49 /****************************************************************************/
50 /****************************************************************************/
51 /****************************************************************************/
52
53 static dictionary_hash<string, unsigned> funcFrequencyTable(string::hash);
54
55 trampTemplate baseTemplate;
56 NonRecursiveTrampTemplate nonRecursiveBaseTemplate;
57
58 //declaration of conservative base trampoline template
59
60 trampTemplate conservativeBaseTemplate;
61 NonRecursiveTrampTemplate nonRecursiveConservativeBaseTemplate;
62
63
64
65 registerSpace *regSpace;
66
67 #if defined(SHM_SAMPLING) && defined(MT_THREAD)
68 // registers 8 to 15: out registers 
69 // registers 16 to 22: local registers
70 Register deadList[] = {16, 17, 18, 19, 20, 21, 22 };
71 #else
72 Register deadList[] = {16, 17, 18, 19, 20, 21, 22, 23 };
73 #endif
74
75 int deadListSize = sizeof(deadList);
76
77 /****************************************************************************/
78 /****************************************************************************/
79 /****************************************************************************/
80
81 // Constructor for the class instPoint. This one defines the 
82 // instPoints for the relocated function. Since the function reloated
83 // to the heap don't need to worry about that jump could be out of
84 // reach, the instructions to be moved are the one instruction at that
85 // point plus others if necessary(i.e. instruction in the delayed
86 // slot and maybe the aggregate instuction ).    
87 //
88 // Unfortunately, this constructor does NOT set several internal fields
89 //  e.g. size, isDelayedInsn, aggregateInsn, delaySlotInsn
90 //
91 // This constructor is for instPoints of functions that will be relocated,
92 // but have not yet been relocated.
93 instPoint::instPoint(pd_Function *f, const instruction &instr, 
94                      const image *owner, Address &adr, bool delayOK, 
95                      instPointType pointType, Address &oldAddr)
96 : insnAddr(adr), addr(adr), originalInstruction(instr), 
97   inDelaySlot(false), isDelayed(false),
98   callIndirect(false), callAggregate(false), callee(NULL), func(f), 
99   ipType(pointType), image_ptr(owner), firstIsConditional(false), 
100   relocated_(false), isLongJump(false)
101 {
102   assert(f->isTrapFunc() == true);  
103
104   isBranchOut = false;
105   delaySlotInsn.raw = owner->get_instruction(oldAddr+4);
106   aggregateInsn.raw = owner->get_instruction(oldAddr+8);
107
108   // If the instruction is a DCTI, the instruction in the delayed 
109   // slot is to be moved.
110   if (IS_DELAYED_INST(instr))
111     isDelayed = true;
112
113   // If this function call another function which return an aggregate
114   // value, move the aggregate instruction, too. 
115   if (ipType == callSite) {
116       if (!IS_VALID_INSN(aggregateInsn) && aggregateInsn.raw != 0) {
117           callAggregate = true;
118           adr += 8;
119           oldAddr += 8;
120       }
121   }
122
123   if (owner->isValidAddress(oldAddr-4)) {
124     instruction iplus1;
125     iplus1.raw = owner->get_instruction(oldAddr-4);
126     if (IS_DELAYED_INST(iplus1) && !delayOK) {
127       // ostrstream os(errorLine, 1024, ios::out);
128       // os << "** inst point " << func->file->fullName << "/"
129       //  << func->prettyName() << " at addr " << addr <<
130       //        " in a delay slot\n";
131       // logLine(errorLine);
132       inDelaySlot = true;
133     }
134   }
135
136   // set size at least....
137   size = 0;
138   if (ipType == functionEntry) {
139       if (hasNoStackFrame()) {
140           size = 4 * sizeof(instruction);
141       } else {
142           size = 5 * sizeof(instruction);
143       }
144   } else if (ipType == callSite) {
145       size = 3 * sizeof(instruction);
146   } else if (ipType == functionExit) {
147       if (hasNoStackFrame()) {
148           size = 5 * sizeof(instruction);
149       } else {
150           size = 2 * sizeof(instruction);
151       }
152   } else if (ipType == otherPoint){
153           size = 2 * sizeof(instruction);
154   } else {
155       assert(false);  
156   }
157 }
158
159 // This constructor is for instPoints of functions that HAVE been relocated,
160 // thus the instPoint is in the new function, not the old function
161 instPoint::instPoint(pd_Function *f, const instruction instr[], 
162                      int arrayOffset, const image *owner, Address &adr, 
163                      bool delayOK, instPointType pointType, Address &oldAddr)
164 : insnAddr(adr), addr(adr), originalInstruction(instr[arrayOffset]), 
165   inDelaySlot(false), isDelayed(false),
166   callIndirect(false), callAggregate(false), callee(NULL), func(f), 
167   ipType(pointType), image_ptr(owner), firstIsConditional(false), 
168   relocated_(true), isLongJump(false)
169 {
170   assert(f->isTrapFunc() == true);  
171
172   isBranchOut = false;
173   delaySlotInsn.raw = instr[arrayOffset+1].raw;
174   aggregateInsn.raw = instr[arrayOffset+2].raw;
175
176   // If the instruction is a DCTI, the instruction in the delayed 
177   // slot is to be moved.
178   if (IS_DELAYED_INST(originalInstruction))
179     isDelayed = true;
180
181   // If this function call another function which return an aggregate
182   // value, move the aggregate instruction, too. 
183   if (ipType == callSite) {
184       if (!IS_VALID_INSN(aggregateInsn) && aggregateInsn.raw != 0) {
185           callAggregate = true;
186           adr += 8;
187           oldAddr += 8;
188       }
189   }
190
191   if (arrayOffset > 0 && owner->isValidAddress(oldAddr-4)) {
192     instruction iplus1;
193     iplus1.raw = instr[arrayOffset-1].raw;
194     if (IS_DELAYED_INST(iplus1) && !delayOK) {
195       // ostrstream os(errorLine, 1024, ios::out);
196       // os << "** inst point " << func->file->fullName << "/"
197       //  << func->prettyName() << " at addr " << addr <<
198       //        " in a delay slot\n";
199       // logLine(errorLine);
200       inDelaySlot = true;
201     }
202   }
203
204   // set size at least....
205   size = 0;
206   if (ipType == functionEntry) {
207       if (hasNoStackFrame()) {
208           size = 4 * sizeof(instruction);
209       } else {
210           size = 5 * sizeof(instruction);
211       }
212   } else if (ipType == callSite) {
213       size = 3 * sizeof(instruction);
214   } else if (ipType == functionExit) {
215       if (hasNoStackFrame()) {
216           size = 5 * sizeof(instruction);
217       } else {
218           size = 2 * sizeof(instruction);
219       }
220   } else if (ipType == otherPoint){
221           size = 2 * sizeof(instruction);
222   } else {
223       assert(false);  
224   }
225 }
226
227 /****************************************************************************/
228 /****************************************************************************/
229 /****************************************************************************/
230
231 // Add the astNode opt to generate one instruction to get the 
232 // return value for the compiler optimazed case
233 void
234 AstNode::optRetVal(AstNode *opt) {
235
236     if (oType == ReturnVal) {
237         cout << "Optimazed Return." << endl;
238         if (loperand == 0) {
239             loperand = opt;
240             return;
241         } else if (opt == 0) {
242             delete loperand;
243             loperand = NULL;
244             return; 
245         }
246     }
247     if (loperand) loperand->optRetVal(opt);
248     if (roperand) roperand->optRetVal(opt);
249     for (unsigned i = 0; i < operands.size(); i++) 
250         operands[i] -> optRetVal(opt);
251 }
252
253 /****************************************************************************/
254 /****************************************************************************/
255 /****************************************************************************/
256
257 bool 
258 processOptimaRet(instPoint *location, AstNode *&ast) {
259
260     // For optimazed return code
261     if (location -> ipType == functionExit) {
262         if ((isInsnType(location -> originalInstruction, RETmask, RETmatch)) ||
263             (isInsnType(location -> originalInstruction, RETLmask, RETLmatch)))
264         {
265             if (isInsnType(location -> delaySlotInsn, 
266                            RESTOREmask, RESTOREmatch)&&
267                 ((location->delaySlotInsn.raw | 0xc1e82000) != 0xc1e82000)) 
268             {
269                 /* cout << "Optimazed Retrun Value:  Addr " << hex << 
270                     location->addr << " in "
271                         << location -> func -> prettyName() << endl; */
272                 AstNode *opt = new AstNode(AstNode::Constant,
273                                            (void *)location->delaySlotInsn.raw);
274                 ast -> optRetVal(opt);
275                 return true;
276             }
277         }
278     }
279     return false;
280 }
281
282 /****************************************************************************/
283 /****************************************************************************/
284 /****************************************************************************/
285
286 Register
287 emitOptReturn(instruction i, Register src, char *insn, Address &base, bool noCost) {
288     
289     unsigned instr = i.raw;
290
291     cout << "Handling a special case for optimized return value." << endl;
292
293     assert(((instr&0x3e000000)>>25) <= 16);
294
295     if ((instr&0x02000)>>13)
296         emitImm(plusOp, (instr&0x07c000)>>14, instr&0x01fff,
297                 ((instr&0x3e000000)>>25)+16, insn, base, noCost);
298     else
299         (void) emitV(plusOp, (instr&0x07c000)>>14, instr&0x01fff,
300              ((instr&0x3e000000)>>25)+16, insn, base, noCost);
301     
302     return emitR(getSysRetValOp, 0, 0, src, insn, base, noCost);
303 }
304
305 /****************************************************************************/
306 /****************************************************************************/
307 /****************************************************************************/
308
309 //
310 // initDefaultPointFrequencyTable - define the expected call frequency of
311 //    procedures.  Currently we just define several one shots with a
312 //    frequency of one, and provide a hook to read a file with more accurate
313 //    information.
314 //
315 void initDefaultPointFrequencyTable()
316 {
317     FILE *fp;
318     float value;
319     char name[512];
320
321     funcFrequencyTable["main"] = 1;
322     funcFrequencyTable["DYNINSTsampleValues"] = 1;
323     funcFrequencyTable[EXIT_NAME] = 1;
324
325     // try to read file.
326     fp = fopen("freq.input", "r");
327     if (!fp) {
328         return;
329     } else {
330         printf("found freq.input file\n");
331     }
332     while (!feof(fp)) {
333         fscanf(fp, "%s %f\n", name, &value);
334         funcFrequencyTable[name] = (int) value;
335         printf("adding %s %f\n", name, value);
336     }
337     fclose(fp);
338 }
339
340 /****************************************************************************/
341 /****************************************************************************/
342 /****************************************************************************/
343
344 /*
345  * Get an estimate of the frequency for the passed instPoint.  
346  *    This is not (always) the same as the function that contains the point.
347  * 
348  *  The function is selected as follows:
349  *
350  *  If the point is an entry or an exit return the function name.
351  *  If the point is a call and the callee can be determined, return the called
352  *     function.
353  *  else return the funcation containing the point.
354  *
355  *  WARNING: This code contins arbitray values for func frequency (both user 
356  *     and system).  This should be refined over time.
357  *
358  * Using 1000 calls sec to be one SD from the mean for most FPSPEC apps.
359  *      -- jkh 6/24/94
360  *
361  */
362 float getPointFrequency(instPoint *point)
363 {
364
365     pd_Function *func;
366
367     if (point->callee)
368         func = point->callee;
369     else
370         func = point->func;
371
372     if (!funcFrequencyTable.defines(func->prettyName())) {
373       // Changing this value from 250 to 100 because predictedCost was
374       // too high - naim 07/18/96
375       return(100); 
376       
377     } else {
378       return (funcFrequencyTable[func->prettyName()]);
379     }
380 }
381
382 /****************************************************************************/
383 /****************************************************************************/
384 /****************************************************************************/
385
386 //
387 // return cost in cycles of executing at this point.  This is the cost
388 //   of the base tramp if it is the first at this point or 0 otherwise.
389 //
390 int getPointCost(process *proc, const instPoint *point)
391 {
392     if (proc->baseMap.defines(point)) {
393         return(0);
394     } else {
395         // 70 cycles for base tramp (worst case)
396         return(70);
397     }
398 }
399
400 /****************************************************************************/
401 /****************************************************************************/
402 /****************************************************************************/
403
404 void initATramp (trampTemplate *thisTemp, Address tramp,
405                  bool isConservative=false)
406 {
407     instruction *temp;
408
409     if(!isConservative){
410
411         thisTemp->savePreInsOffset = 
412                         ((Address)baseTramp_savePreInsn - tramp);
413         thisTemp->restorePreInsOffset = 
414                         ((Address)baseTramp_restorePreInsn - tramp);
415         thisTemp->savePostInsOffset = 
416                         ((Address)baseTramp_savePostInsn - tramp);
417         thisTemp->restorePostInsOffset = 
418                         ((Address)baseTramp_restorePostInsn - tramp);
419     }else{
420         thisTemp->savePreInsOffset =
421                 ((Address)conservativeBaseTramp_savePreInsn - tramp);
422         thisTemp->restorePreInsOffset =
423                 ((Address)conservativeBaseTramp_restorePreInsn - tramp);
424         thisTemp->savePostInsOffset =
425                 ((Address)conservativeBaseTramp_savePostInsn - tramp);
426         thisTemp->restorePostInsOffset =
427                 ((Address)conservativeBaseTramp_restorePostInsn - tramp);
428     }
429
430     // TODO - are these offsets always positive?
431     thisTemp->trampTemp = (void *) tramp;
432     for (temp = (instruction*)tramp; temp->raw != END_TRAMP; temp++) {
433         const Address offset = (Address)temp - tramp;
434         switch (temp->raw) {
435             case LOCAL_PRE_BRANCH:
436                 thisTemp->localPreOffset = offset;
437                 thisTemp->localPreReturnOffset = thisTemp->localPreOffset 
438                                                 + sizeof(temp->raw);
439                 break;
440             case GLOBAL_PRE_BRANCH:
441                 thisTemp->globalPreOffset = offset;
442                 break;
443             case LOCAL_POST_BRANCH:
444                 thisTemp->localPostOffset = offset;
445                 thisTemp->localPostReturnOffset = thisTemp->localPostOffset
446                                                 + sizeof(temp->raw);
447                 break;
448             case GLOBAL_POST_BRANCH:
449                 thisTemp->globalPostOffset = offset;
450                 break;
451             case SKIP_PRE_INSN:
452                 thisTemp->skipPreInsOffset = offset;
453                 break;
454             case UPDATE_COST_INSN:
455                 thisTemp->updateCostOffset = offset;
456                 break;
457             case SKIP_POST_INSN:
458                 thisTemp->skipPostInsOffset = offset;
459                 break;
460             case RETURN_INSN:
461                 thisTemp->returnInsOffset = offset;
462                 break;
463             case EMULATE_INSN:
464                 thisTemp->emulateInsOffset = offset;
465                 break;
466             case CONSERVATIVE_TRAMP_READ_CONDITION:
467                 if(isConservative)
468                         temp->raw = 0x83408000; /*read condition codes to g1*/
469                 break;
470             case CONSERVATIVE_TRAMP_WRITE_CONDITION:
471                 if(isConservative)
472                         temp->raw = 0x85806000; /*write condition codes fromg1*/
473                 break;
474         }       
475     }
476
477     // Cost with the skip branches.
478     thisTemp->cost = 14;  
479     thisTemp->prevBaseCost = 20 +
480       RECURSIVE_GUARD_ON_CODE_SIZE + RECURSIVE_GUARD_OFF_CODE_SIZE;
481     thisTemp->postBaseCost = 22 +
482       RECURSIVE_GUARD_ON_CODE_SIZE + RECURSIVE_GUARD_OFF_CODE_SIZE;
483     thisTemp->prevInstru = thisTemp->postInstru = false;
484     thisTemp->size = (int) temp - (int) tramp;
485 }
486
487 /****************************************************************************/
488 /****************************************************************************/
489 /****************************************************************************/
490
491 void initATramp(NonRecursiveTrampTemplate *thisTemp, Address tramp,
492                 bool isConservative=false)
493 {
494   initATramp((trampTemplate *)thisTemp, tramp,isConservative);
495
496   instruction *temp;
497
498   for (temp = (instruction*)tramp; temp->raw != END_TRAMP; temp++) {
499     const Address offset = (Address)temp - tramp;
500     switch (temp->raw)
501       {
502
503       case RECURSIVE_GUARD_ON_PRE_INSN:
504         thisTemp->guardOnPre_beginOffset = offset;
505         thisTemp->guardOnPre_endOffset = thisTemp->guardOnPre_beginOffset
506                 + RECURSIVE_GUARD_ON_CODE_SIZE * INSN_SIZE;
507         break;
508
509       case RECURSIVE_GUARD_OFF_PRE_INSN:
510         thisTemp->guardOffPre_beginOffset = offset;
511         thisTemp->guardOffPre_endOffset = thisTemp->guardOffPre_beginOffset
512                 + RECURSIVE_GUARD_OFF_CODE_SIZE * INSN_SIZE;
513         break;
514
515       case RECURSIVE_GUARD_ON_POST_INSN:
516         thisTemp->guardOnPost_beginOffset = offset;
517         thisTemp->guardOnPost_endOffset = thisTemp->guardOnPost_beginOffset
518                 + RECURSIVE_GUARD_ON_CODE_SIZE * INSN_SIZE;
519         break;
520
521       case RECURSIVE_GUARD_OFF_POST_INSN:
522         thisTemp->guardOffPost_beginOffset = offset;
523         thisTemp->guardOffPost_endOffset = thisTemp->guardOffPost_beginOffset
524                 + RECURSIVE_GUARD_OFF_CODE_SIZE * INSN_SIZE;
525         break;
526
527       }
528   }
529 }
530
531 /****************************************************************************/
532 /****************************************************************************/
533 /****************************************************************************/
534
535 void initTramps()
536 {
537     static bool inited=false;
538
539     if (inited) return;
540     inited = true;
541
542     initATramp(&baseTemplate, (Address) baseTramp);
543     initATramp(&nonRecursiveBaseTemplate, (Address)baseTramp);
544
545
546     initATramp(&conservativeBaseTemplate,
547                (Address)conservativeBaseTramp,true);
548     initATramp(&nonRecursiveConservativeBaseTemplate,
549                (Address)conservativeBaseTramp,true);
550
551     regSpace = new registerSpace(sizeof(deadList)/sizeof(Register), deadList,
552                                          0, NULL);
553     assert(regSpace);
554 }
555
556 /****************************************************************************/
557 /****************************************************************************/
558 /****************************************************************************/
559
560 #if defined(MT_THREAD)
561 //
562 // For multithreaded applications and shared memory sampling, this routine 
563 // will compute the address where the corresponding counter/timer vector for
564 // level 0 is (by default). In the mini-tramp, if the counter/timer is at a
565 // different level, we will add the corresponding offset - naim 4/18/97
566 //
567 // NUM_INSN_MT_PREAMBLE
568 void generateMTpreamble(char *insn, Address &base, process *proc)
569 {
570   AstNode *t1 ;
571   Address tableAddr;
572   int value; 
573   bool err;
574   unsigned offset = 19*sizeof(instruction);
575   Register src = Null_Register;
576
577   vector<AstNode *> dummy;
578
579   t1 = new AstNode("DYNINSTthreadPos", dummy);
580
581   // t2=DYNINSTthreadPos()*sizeof(unsigned)
582   value = sizeof(unsigned);
583   AstNode* t4 = new AstNode(AstNode::Constant,(void *)value);
584   AstNode* t2 = new AstNode(timesOp, t1, t4);
585   removeAst(t1) ;
586   removeAst(t4) ;
587
588   // t3=DYNINSTthreadTable+t2
589   //
590   tableAddr = proc->findInternalAddress("DYNINSTthreadTable",true,err);
591   assert(!err);
592   AstNode* t5 = new AstNode(AstNode::Constant, (void *)tableAddr);
593   AstNode* t3 = new AstNode(plusOp, t2, t5);
594   removeAst(t2);
595   removeAst(t5);
596
597   AstNode* t7 = new AstNode(AstNode::Constant,(void *)-2);
598   AstNode* t8 = new AstNode(eqOp, t1, t7);
599   removeAst(t7);
600   AstNode* t9 = new AstNode(AstNode::Constant, (void *)(offset));
601   //goto offset
602   AstNode* t10 = new AstNode(branchOp, t9);
603   removeAst(t9);
604   //t11 = "if(t1 ==-2) goto offset"
605   AstNode* t11 = new AstNode(ifOp, t8, t10);
606   removeAst(t8);
607   removeAst(t10) ;
608
609   //t6 = " if (t1 == -2) goto Offset; t3=DYNINSTthreadTable+t2"
610   AstNode *t6= new AstNode(t11, t3);
611   removeAst(t11);
612   removeAst(t3);
613   src = t6->generateCode(proc, regSpace, insn, base, false, true);
614   removeAst(t6);
615   (void) emitV(orOp, src, 0, REG_MT, insn, base, false);
616   regSpace->freeRegister(src);
617 }
618
619 /****************************************************************************/
620 /****************************************************************************/
621 /****************************************************************************/
622
623 void generateRPCpreamble(char *insn, Address &base, process *proc, unsigned offset, int tid, unsigned pos)
624 {
625   AstNode *t1 ;
626   Address tableAddr;
627   int value; 
628   bool err;
629   Register src = Null_Register;
630
631   if (tid != -1)  {
632     vector<AstNode *> param;
633     param += new AstNode(AstNode::Constant,(void *)tid);
634     param += new AstNode(AstNode::Constant,(void *)pos);
635     t1 = new AstNode("DYNINSTthreadPosTID", param);
636     for (unsigned i=0; i<param.size(); i++) 
637       removeAst(param[i]) ;
638
639     value = sizeof(unsigned);
640     AstNode* t4 = new AstNode(AstNode::Constant,(void *)value);
641     AstNode* t2 = new AstNode(timesOp, t1, t4);
642     removeAst(t1) ;
643     removeAst(t4) ;
644
645     // t3=DYNINSTthreadTable[thr_self()]
646     //
647     tableAddr = proc->findInternalAddress("DYNINSTthreadTable",true,err);
648     assert(!err);
649     AstNode* t5 = new AstNode(AstNode::Constant, (void *)tableAddr);
650     AstNode* t3 = new AstNode(plusOp, t2, t5);
651     removeAst(t2);
652     removeAst(t5);
653
654     AstNode* t7 = new AstNode(AstNode::Constant,(void *)-2);
655     AstNode* t8 = new AstNode(eqOp, t1, t7);
656     removeAst(t7);
657     AstNode* t9 = new AstNode(AstNode::Constant, (void *)(offset));
658     AstNode* t10 = new AstNode(branchOp, t9);
659     removeAst(t9);
660     AstNode* t11 = new AstNode(ifOp, t8, t10);
661     removeAst(t8);
662     removeAst(t10);
663
664     AstNode *t6= new AstNode(t11, t3);
665     removeAst(t11);
666     removeAst(t3);
667     src = t6->generateCode(proc, regSpace, insn, base, false, true);
668     removeAst(t6);
669     unsigned first_insn=base;
670     (void) emitV(orOp, src, 0, REG_MT, insn, base, false);
671     regSpace->freeRegister(src);
672   }
673 }
674 #endif
675
676 /****************************************************************************/
677 /****************************************************************************/
678 /****************************************************************************/
679
680 void generateNoOp(process *proc, Address addr)
681 {
682     instruction insn;
683
684     /* fill with no-op */
685     insn.raw = 0;
686     insn.branch.op = 0;
687     insn.branch.op2 = NOOPop2;
688
689     proc->writeTextWord((caddr_t)addr, insn.raw);
690 }
691
692
693 /****************************************************************************/
694 /****************************************************************************/
695 /****************************************************************************/
696
697 /*
698  * change the insn at addr to be a branch to newAddr.
699  *   Used to add multiple tramps to a point.
700  */
701 void generateBranch(process *proc, Address fromAddr, Address newAddr)
702 {
703     int disp;
704     instruction insn;
705
706     disp = newAddr-fromAddr;
707     generateBranchInsn(&insn, disp);
708
709     proc->writeTextWord((caddr_t)fromAddr, insn.raw);
710 }
711
712 /****************************************************************************/
713 /****************************************************************************/
714 /****************************************************************************/
715
716 void generateCall(process *proc, Address fromAddr, Address newAddr)
717 {
718     instruction insn; 
719     generateCallInsn(&insn, fromAddr, newAddr);
720
721     proc->writeTextWord((caddr_t)fromAddr, insn.raw);
722
723 }
724
725 /****************************************************************************/
726 /****************************************************************************/
727 /****************************************************************************/
728
729 void genImm(process *proc, Address fromAddr, int op, 
730                         Register rs1, int immd, Register rd)
731 {
732     instruction insn;
733     genImmInsn(&insn, op, rs1, immd, rd);
734
735     proc->writeTextWord((caddr_t)fromAddr, insn.raw);
736 }
737
738 /****************************************************************************/
739 /****************************************************************************/
740 /****************************************************************************/
741
742 /*
743  *  change the target of the branch at fromAddr, to be newAddr.
744  */
745 void changeBranch(process *proc, Address fromAddr, Address newAddr, 
746                   instruction originalBranch) {
747     int disp = newAddr-fromAddr;
748     instruction insn;
749     insn.raw = originalBranch.raw;
750     insn.branch.disp22 = disp >> 2;
751     proc->writeTextWord((caddr_t)fromAddr, insn.raw);
752 }
753
754 /****************************************************************************/
755 /****************************************************************************/
756 /****************************************************************************/
757
758 int callsTrackedFuncP(instPoint *point)
759 {
760     if (point->callIndirect) {
761         return(true);
762     } else {
763         if (point->callee) {
764             return(true);
765         } else {
766             return(false);
767         }
768     }
769 }
770
771 /****************************************************************************/
772 /****************************************************************************/
773 /****************************************************************************/
774
775 /*
776  * return the function asociated with a point.
777  *
778  *     If the point is a funcation call, and we know the function being called,
779  *          then we use that.  Otherwise it is the function that contains the
780  *          point.
781  *  
782  *   This is done to return a better idea of which function we are using.
783  */
784 pd_Function *getFunction(instPoint *point)
785 {
786     return(point->callee ? point->callee : point->func);
787 }
788
789 /****************************************************************************/
790 /****************************************************************************/
791 /****************************************************************************/
792
793 bool process::emitInferiorRPCheader(void *insnPtr, Address &baseBytes) {
794    instruction *insn = (instruction *)insnPtr;
795    Address baseInstruc = baseBytes / sizeof(instruction);
796
797    genImmInsn(&insn[baseInstruc++], SAVEop3, 14, -112, 14);
798
799    baseBytes = baseInstruc * sizeof(instruction); // convert back
800    return true;
801 }
802
803
804 /****************************************************************************/
805 /****************************************************************************/
806 /****************************************************************************/
807
808 bool process::emitInferiorRPCtrailer(void *insnPtr, Address &baseBytes,
809                                      unsigned &breakOffset,
810                                      bool stopForResult,
811                                      unsigned &stopForResultOffset,
812 #if defined(MT_THREAD)
813                                      unsigned &justAfter_stopForResultOffset,
814                                      bool isSafeRPC) {
815 #else
816                                      unsigned &justAfter_stopForResultOffset) {
817 #endif
818    // Sequence: restore, trap, illegal
819
820    instruction *insn = (instruction *)insnPtr;
821    Address baseInstruc = baseBytes / sizeof(instruction);
822
823    if (stopForResult) {
824       // trap insn:
825       genBreakpointTrap(&insn[baseInstruc]);
826       stopForResultOffset = baseInstruc * sizeof(instruction);
827       baseInstruc++;
828       justAfter_stopForResultOffset = baseInstruc * sizeof(instruction);
829    }
830
831 #if defined(MT_THREAD)
832    if (isSafeRPC) //ret instruction
833      genImmInsn(&insn[baseInstruc++], JMPLop3, REG_I(7), 0x08, REG_G(0)) ;
834 #endif
835    genSimpleInsn(&insn[baseInstruc++], RESTOREop3, 0, 0, 0);
836
837    // Now that the inferior has executed the 'restore' instruction, the %in and
838    // %local registers have been restored.  We mustn't modify them after this point!!
839    // (reminder: the %in and %local registers aren't saved and set with ptrace
840    //  GETREGS/SETREGS call)
841
842 #if defined(MT_THREAD)
843    if (!isSafeRPC) {
844 #endif
845      // Trap instruction:
846      genBreakpointTrap(&insn[baseInstruc]); // ta 1
847      breakOffset = baseInstruc * sizeof(instruction);
848      baseInstruc++;
849
850      // And just to make sure that we don't continue from the trap:
851      genUnimplementedInsn(&insn[baseInstruc++]); // UNIMP 0
852 #if defined(MT_THREAD)
853    }
854 #endif
855    baseBytes = baseInstruc * sizeof(instruction); // convert back
856
857    return true; // success
858 }
859
860 /****************************************************************************/
861 /****************************************************************************/
862 /****************************************************************************/
863
864 void emitImm(opCode op, Register src1, RegValue src2imm, Register dest, 
865              char *i, Address &base, bool noCost)
866 {
867         instruction *insn = (instruction *) ((void*)&i[base]);
868         RegValue op3 = -1;
869         int result = -1;
870         switch (op) {
871             // integer ops
872             case plusOp:
873                 op3 = ADDop3;
874                 genImmInsn(insn, op3, src1, src2imm, dest);
875                 break;
876
877             case minusOp:
878                 op3 = SUBop3;
879                 genImmInsn(insn, op3, src1, src2imm, dest);
880                 break;
881
882             case timesOp:
883                 op3 = SMULop3;
884                 if (isPowerOf2(src2imm,result) && (result<32))
885                   generateLShift(insn, src1, (Register)result, dest);           
886                 else 
887                   genImmInsn(insn, op3, src1, src2imm, dest);
888                 break;
889
890             case divOp:
891                 op3 = SDIVop3;
892                 if (isPowerOf2(src2imm,result) && (result<32))
893                   generateRShift(insn, src1, (Register)result, dest);           
894                 else { // needs to set the Y register to zero first
895                   // Set the Y register to zero: Zhichen
896                   genImmInsn(insn, WRYop3, REG_G(0), 0, 0);
897                   base += sizeof(instruction);
898                   insn = (instruction *) ((void*)&i[base]);
899                   genImmInsn(insn, op3, src1, src2imm, dest);
900                 }
901
902                 break;
903
904             // Bool ops
905             case orOp:
906                 op3 = ORop3;
907                 genImmInsn(insn, op3, src1, src2imm, dest);
908                 break;
909
910             case andOp:
911                 op3 = ANDop3;
912                 genImmInsn(insn, op3, src1, src2imm, dest);
913                 break;
914
915             // rel ops
916             // For a particular condition (e.g. <=) we need to use the
917             // the opposite in order to get the right value (e.g. for >=
918             // we need BLTcond) - naim
919             case eqOp:
920                 genImmRelOp(insn, BNEcond, src1, src2imm, dest, base);
921                 return;
922                 break;
923
924             case neOp:
925                 genImmRelOp(insn, BEcond, src1, src2imm, dest, base);
926                 return;
927                 break;
928
929             case lessOp:
930                 genImmRelOp(insn, BGEcond, src1, src2imm, dest, base);
931                 return;
932                 break;
933
934             case leOp:
935                 genImmRelOp(insn, BGTcond, src1, src2imm, dest, base);
936                 return;
937                 break;
938
939             case greaterOp:
940                 genImmRelOp(insn, BLEcond, src1, src2imm, dest, base);
941                 return;
942                 break;
943
944             case geOp:
945                 genImmRelOp(insn, BLTcond, src1, src2imm, dest, base);
946                 return;
947                 break;
948
949             default:
950                 Register dest2 = regSpace->allocateRegister(i, base, noCost);
951                 (void) emitV(loadConstOp, src2imm, dest2, dest2, i, base, noCost);
952                 (void) emitV(op, src1, dest2, dest, i, base, noCost);
953                 regSpace->freeRegister(dest2);
954                 return;
955                 break;
956         }
957         base += sizeof(instruction);
958         return;
959 }
960
961 /****************************************************************************/
962 /****************************************************************************/
963 /****************************************************************************/
964
965 //
966 // All values based on Cypress0 && Cypress1 implementations as documented in
967 //   SPARC v.8 manual p. 291
968 //
969 int getInsnCost(opCode op)
970 {
971     /* XXX Need to add branchOp */
972     if (op == loadConstOp) {
973         return(1);
974     } else if (op ==  loadOp) {
975         // sethi + load single
976         return(1+1);
977     } else if (op ==  loadIndirOp) {
978         return(1);
979     } else if (op ==  storeOp) {
980         // sethi + store single
981         // return(1+3); 
982         // for SS-5 ?
983         return(1+2); 
984     } else if (op ==  storeIndirOp) {
985         return(2); 
986     } else if (op ==  ifOp) {
987         // subcc
988         // be
989         // nop
990         return(1+1+1);
991     } else if (op ==  callOp) {
992         int count = 0;
993
994         // mov src1, %o0
995         count += 1;
996
997         // mov src2, %o1
998         count += 1;
999
1000         // clr i2
1001         count += 1;
1002
1003         // clr i3
1004         count += 1;
1005
1006         // sethi
1007         count += 1;
1008
1009         // jmpl
1010         count += 1;
1011
1012         // noop
1013         count += 1;
1014
1015         return(count);
1016     } else if (op ==  updateCostOp) {
1017         // sethi %hi(obsCost), %l0
1018         // ld [%lo + %lo(obsCost)], %l1
1019         // add %l1, <cost>, %l1
1020         // st %l1, [%lo + %lo(obsCost)]
1021         return(1+2+1+3);
1022     } else if (op ==  trampPreamble) {
1023         return(0);
1024     } else if (op ==  trampTrailer) {
1025         // retl
1026         return(2);
1027     } else if (op == noOp) {
1028         // noop
1029         return(1);
1030     } else if (op == getParamOp) {
1031         return(0);
1032     } else {
1033         switch (op) {
1034             // rel ops
1035             case eqOp:
1036             case neOp:
1037             case lessOp:
1038             case leOp:
1039             case greaterOp:
1040             case geOp:
1041                 // bne -- assume taken
1042                 return(2);
1043                 break;
1044             default:
1045                 return(1);
1046                 break;
1047         }
1048     }
1049 }
1050
1051 /****************************************************************************/
1052 /****************************************************************************/
1053 /****************************************************************************/
1054
1055 bool isReturnInsn(instruction instr, Address addr, string name) {
1056     if (isInsnType(instr, RETmask, RETmatch) ||
1057         isInsnType(instr, RETLmask, RETLmatch)) {
1058         //  Why 8 or 12?
1059         //  According to the sparc arch manual (289), ret or retl are
1060         //   synthetic instructions for jmpl %i7+8, %g0 or jmpl %o7+8, %go.
1061         //  Apparently, the +8 is not really a hard limit though, as 
1062         //   sometimes some extra space is allocated after the jump 
1063         //   instruction for various reasons.
1064         //  1 possible reason is to include information on the size of
1065         //   returned structure (4 bytes).
1066         //  So, 8 or 12 here is a heuristic, but doesn't seem to 
1067         //   absolutely have to be true.
1068         //  -matt
1069         if ((instr.resti.simm13 != 8) && (instr.resti.simm13 != 12) 
1070                     && (instr.resti.simm13 != 16)) {
1071           sprintf(errorLine,"WARNING: unsupported return at address 0x%lx"
1072                         " in function %s - appears to be return to PC + %i", 
1073                   addr, name.string_of(), (int)instr.resti.simm13);
1074           showErrorCallback(55, errorLine);
1075         } else { 
1076           return true;
1077         }
1078     }
1079     return false;
1080 }
1081
1082 /****************************************************************************/
1083 /****************************************************************************/
1084 /****************************************************************************/
1085
1086 bool isReturnInsn(const image *owner, Address adr, bool &lastOne, string name)
1087 {
1088     instruction instr;
1089
1090     instr.raw = owner->get_instruction(adr);
1091     lastOne = false;
1092
1093     return isReturnInsn(instr, adr, name);
1094 }
1095
1096 /****************************************************************************/
1097 /****************************************************************************/
1098 /****************************************************************************/
1099
1100 bool isBranchInsn(instruction instr) {
1101     if (instr.branch.op == 0 
1102                 && (instr.branch.op2 == 2 || instr.branch.op2 == 6)) 
1103           return true;
1104     return false;
1105 }
1106
1107 /****************************************************************************/
1108 /****************************************************************************/
1109 /****************************************************************************/
1110
1111 // modifyInstPoint: if the function associated with the process was 
1112 // recently relocated, then the instPoint may have the old pre-relocated
1113 // address (this can occur because we are getting instPoints in mdl routines 
1114 // and passing these to routines that do the instrumentation, it would
1115 // be better to let the routines that do the instrumenting find the points)
1116 void pd_Function::modifyInstPoint(const instPoint *&location,process *proc)
1117 {
1118
1119     if(relocatable_ && !(location->relocated_)){
1120         for(u_int i=0; i < relocatedByProcess.size(); i++){
1121             if((relocatedByProcess[i])->getProcess() == proc){
1122                 if(location->ipType == functionEntry){
1123                     const instPoint *new_entry = 
1124                                 (relocatedByProcess[i])->funcEntry();
1125                     location = new_entry;
1126                 } 
1127                 else if(location->ipType == functionExit){
1128                     const vector<instPoint *> new_returns = 
1129                         (relocatedByProcess[i])->funcReturns(); 
1130                     if(funcReturns.size() != new_returns.size()){
1131                         printf("funcReturns = %d new_returns = %d\n",
1132                                 funcReturns.size(),new_returns.size());
1133                         fflush(stdout);
1134                     }
1135                     assert(funcReturns.size() == new_returns.size());
1136                     for(u_int j=0; j < new_returns.size(); j++){
1137                         if(funcReturns[j] == location){
1138                             location = (new_returns[j]);
1139                             break;
1140                         }
1141                     }
1142                 }
1143                 else if(location->ipType == otherPoint) {
1144                     const vector<instPoint *> new_arbitrary = 
1145                         (relocatedByProcess[i])->funcArbitraryPoints(); 
1146
1147                     assert(arbitraryPoints.size() == new_arbitrary.size());
1148                     for(u_int j=0; j < new_arbitrary.size(); j++){
1149                         if(arbitraryPoints[j] == location){
1150                             location = (new_arbitrary[j]);
1151                             break;
1152                         }
1153                     }
1154                 }
1155                 else {
1156                     const vector<instPoint *> new_calls = 
1157                                 (relocatedByProcess[i])->funcCallSites(); 
1158                     assert(calls.size() == new_calls.size());
1159                     for(u_int j=0; j < new_calls.size(); j++){
1160                         if(calls[j] == location){
1161                             location = (new_calls[j]);
1162                             break;
1163                         }
1164                     }
1165
1166                 }
1167                 break;
1168     } } }
1169 }
1170
1171 /****************************************************************************/
1172 /****************************************************************************/
1173 /****************************************************************************/
1174
1175 // The exact semantics of the heap are processor specific.
1176 //
1177 // find all DYNINST symbols that are data symbols
1178 //
1179 bool process::heapIsOk(const vector<sym_data> &find_us) {
1180   Symbol sym;
1181   Address baseAddr;
1182
1183   // find the main function
1184   // first look for main or _main
1185   if (!((mainFunction = findOneFunction("main")) 
1186         || (mainFunction = findOneFunction("_main")))) {
1187      string msg = "Cannot find main. Exiting.";
1188      statusLine(msg.string_of());
1189 #if defined(BPATCH_LIBRARY)
1190      BPatch_reportError(BPatchWarning, 50, msg.string_of());
1191 #else
1192      showErrorCallback(50, msg);
1193 #endif
1194      return false;
1195   }
1196
1197   for (unsigned i=0; i<find_us.size(); i++) {
1198     const string &str = find_us[i].name;
1199     if (!getSymbolInfo(str, sym, baseAddr)) {
1200       string str1 = string("_") + str.string_of();
1201       if (!getSymbolInfo(str1, sym, baseAddr) && find_us[i].must_find) {
1202         string msg;
1203         msg = string("Cannot find ") + str + string(". Exiting");
1204         statusLine(msg.string_of());
1205         showErrorCallback(50, msg);
1206         return false;
1207       }
1208     }
1209   }
1210
1211 //  string ghb = GLOBAL_HEAP_BASE;
1212 //  if (!getSymbolInfo(ghb, sym, baseAddr)) {
1213 //    ghb = U_GLOBAL_HEAP_BASE;
1214 //    if (!linkedFile.get_symbol(ghb, sym)) {
1215 //      string msg;
1216 //      msg = string("Cannot find ") + ghb + string(". Exiting");
1217 //      statusLine(msg.string_of());
1218 //      showErrorCallback(50, msg);
1219 //      return false;
1220 //    }
1221 //  }
1222 //  Address instHeapEnd = sym.addr()+baseAddr;
1223 //  addInternalSymbol(ghb, instHeapEnd);
1224
1225
1226 #ifdef ndef
1227   /* Not needed with the new heap type system */
1228
1229   string ihb = INFERIOR_HEAP_BASE;
1230   if (!getSymbolInfo(ihb, sym, baseAddr)) {
1231     ihb = UINFERIOR_HEAP_BASE;
1232     if (!getSymbolInfo(ihb, sym, baseAddr)) {
1233       string msg;
1234       msg = string("Cannot find ") + ihb + string(". Cannot use this application");
1235       statusLine(msg.string_of());
1236       showErrorCallback(50, msg);
1237       return false;
1238     }
1239   }
1240
1241   Address curr = sym.addr()+baseAddr;
1242   // Check that we can patch up user code to jump to our base trampolines
1243   // (Perhaps this code is no longer needed for sparc platforms, since we use full
1244   // 32-bit jumps)
1245   const Address instHeapStart = curr;
1246   const Address instHeapEnd = instHeapStart + SYN_INST_BUF_SIZE - 1;
1247
1248   if (instHeapEnd > getMaxBranch3Insn()) {
1249     logLine("*** FATAL ERROR: Program text + data too big for dyninst\n");
1250     sprintf(errorLine, "    heap starts at %x and ends at %x; maxbranch=%x\n",
1251             instHeapStart, instHeapEnd, getMaxBranch3Insn());
1252     logLine(errorLine);
1253     return false;
1254   }
1255 #endif
1256
1257   return true;
1258 }
1259
1260 /****************************************************************************/
1261 /****************************************************************************/
1262 /****************************************************************************/
1263
1264 // Certain registers (i0-i7 on a SPARC) may be available to be read
1265 // as an operand, but cannot be written.
1266 bool registerSpace::readOnlyRegister(Register /*reg_number*/) {
1267 // -- this code removed, since it seems incorrect
1268 //if ((reg_number < REG_L(0)) || (reg_number > REG_L(7)))
1269 //    return true;
1270 //else
1271       return false;
1272 }
1273
1274 /****************************************************************************/
1275 /****************************************************************************/
1276 /****************************************************************************/
1277
1278 bool returnInstance::checkReturnInstance(const vector<Address> &stack, u_int &index) {
1279     // If false (unsafe) is returned, then 'index' is set to the first unsafe call stack
1280     // index.
1281
1282   //    cout << "checkReturnInstance: addr_=" << (void*)addr_ << "; size_=" <<
1283   //            (void*)size_ << endl;
1284   //    cout << "instruction sequence is:" << endl;
1285   //    for (unsigned i=0; i < instSeqSize/4; i ++)
1286   //       cout << (void*)instructionSeq[i].raw << endl;
1287   //    cout << endl;
1288   //    
1289   //    for (unsigned i=0; i < stack.size(); i++)
1290   //       cout << (void*)stack[i] << endl;
1291
1292     for (u_int i=0; i < stack.size(); i++) {
1293         index = i;
1294
1295         // Is the following check correct?  Shouldn't the ">" be changed to ">=",
1296         // and the "<=" be changed to "<" ??? --ari 6/11/97
1297         if (stack[i] > addr_ && stack[i] <= addr_+size_)
1298             return false;
1299     }
1300
1301     return true;
1302 }
1303
1304 /****************************************************************************/
1305 /****************************************************************************/
1306 /****************************************************************************/
1307
1308 void returnInstance::installReturnInstance(process *proc) {
1309     proc->writeTextSpace((caddr_t)addr_, instSeqSize, 
1310                          (caddr_t) instructionSeq); 
1311         installed = true;
1312 }
1313
1314 /****************************************************************************/
1315 /****************************************************************************/
1316 /****************************************************************************/
1317
1318 void generateBreakPoint(instruction &insn) {
1319     insn.raw = BREAK_POINT_INSN;
1320 }
1321
1322 /****************************************************************************/
1323 /****************************************************************************/
1324 /****************************************************************************/
1325
1326 void returnInstance::addToReturnWaitingList(Address pc, process *proc) {
1327     // if there already is a TRAP set at this pc for this process don't
1328     // generate a trap instruction again...you will get the wrong original
1329     // instruction if you do a readDataSpace
1330     bool found = false;
1331     instruction insn;
1332     for (u_int i=0; i < instWList.size(); i++) {
1333          if (instWList[i]->pc_ == pc && instWList[i]->which_proc == proc) {
1334              found = true;
1335              insn = instWList[i]->relocatedInstruction;
1336              break;
1337          }
1338     }
1339     if(!found) {
1340         instruction insnTrap;
1341         generateBreakPoint(insnTrap);
1342         proc->readDataSpace((caddr_t)pc, sizeof(insn), (char *)&insn, true);
1343         proc->writeTextSpace((caddr_t)pc, sizeof(insnTrap), (caddr_t)&insnTrap);
1344     }
1345     else {
1346     }
1347
1348     instWaitingList *instW = new instWaitingList(instructionSeq,instSeqSize,
1349                                                  addr_,pc,insn,pc,proc);
1350     instWList.push_back(instW);
1351 }
1352
1353 /****************************************************************************/
1354 /****************************************************************************/
1355 /****************************************************************************/
1356
1357 bool doNotOverflow(int value)
1358 {
1359   // we are assuming that we have 13 bits to store the immediate operand.
1360   //if ( (value <= 16383) && (value >= -16384) ) return(true);
1361   if ( (value <= MAX_IMM13) && (value >= MIN_IMM13) ) return(true);
1362   else return(false);
1363 }
1364
1365 /****************************************************************************/
1366 /****************************************************************************/
1367 /****************************************************************************/
1368
1369 void instWaitingList::cleanUp(process *proc, Address pc) {
1370     proc->writeTextSpace((caddr_t)pc, sizeof(relocatedInstruction),
1371                     (caddr_t)&relocatedInstruction);
1372     proc->writeTextSpace((caddr_t)addr_, instSeqSize, (caddr_t)instructionSeq);
1373 }
1374
1375 /****************************************************************************/
1376 /****************************************************************************/
1377 /****************************************************************************/
1378
1379 // process::replaceFunctionCall
1380 //
1381 // Replace the function call at the given instrumentation point with a call to
1382 // a different function, or with a NOOP.  In order to replace the call with a
1383 // NOOP, pass NULL as the parameter "func."
1384 // Returns true if sucessful, false if not.  Fails if the site is not a call
1385 // site, or if the site has already been instrumented using a base tramp.
1386 bool process::replaceFunctionCall(const instPoint *point,
1387                                   const function_base *func) {
1388     // Must be a call site
1389     if (point->ipType != callSite)
1390         return false;
1391
1392     // Cannot already be instrumented with a base tramp
1393     if (baseMap.defines(point))
1394         return false;
1395
1396     // Replace the call
1397     if (func == NULL)
1398         generateNoOp(this, point->addr);
1399     else
1400         generateCall(this, point->addr,
1401                      func->getEffectiveAddress(this));
1402
1403     return true;
1404 }
1405
1406 /****************************************************************************/
1407 /****************************************************************************/
1408 /****************************************************************************/
1409
1410 #ifndef BPATCH_LIBRARY
1411 bool process::isDynamicCallSite(instPoint *callSite){
1412   function_base *temp;
1413   if(!findCallee(*(callSite),temp)){
1414     //True call instructions are not dynamic on sparc,
1415     //they are always to a pc relative offset
1416     if(!isTrueCallInsn(callSite->originalInstruction))
1417       return true;
1418   }
1419   return false;
1420 }
1421
1422 /****************************************************************************/
1423 /****************************************************************************/
1424 /****************************************************************************/
1425
1426 bool process::MonitorCallSite(instPoint *callSite){
1427  
1428   if(isJmplInsn(callSite->originalInstruction)){
1429     vector<AstNode *> the_args(2);
1430     
1431     //this instruction is a jmpl with i == 1, meaning it
1432     //calling function register rs1+simm13
1433     if(callSite->originalInstruction.rest.i == 1){
1434       
1435       AstNode *base =  new AstNode(AstNode::PreviousStackFrameDataReg,
1436                           (void *) callSite->originalInstruction.rest.rs1);
1437       AstNode *offset = new AstNode(AstNode::Constant, 
1438                         (void *) callSite->originalInstruction.resti.simm13);
1439       the_args[0] = new AstNode(plusOp, base, offset);
1440     } 
1441     
1442     //This instruction is a jmpl with i == 0, meaning its
1443     //two operands are registers
1444     else if(callSite->originalInstruction.rest.i == 0){
1445       //Calculate the byte offset from the contents of the %fp reg
1446       //that the registers from the previous stack frame 
1447       //specified by rs1 and rs2 are stored on the stack
1448       AstNode *callee_addr1 = 
1449         new AstNode(AstNode::PreviousStackFrameDataReg,
1450                     (void *) callSite->originalInstruction.rest.rs1);
1451       AstNode *callee_addr2 = 
1452         new AstNode(AstNode::PreviousStackFrameDataReg, 
1453                     (void *) callSite->originalInstruction.rest.rs2);
1454       the_args[0] = new AstNode(plusOp, callee_addr1, callee_addr2);
1455     }
1456     else assert(0);
1457     
1458     the_args[1] = new AstNode(AstNode::Constant,
1459                               (void *) callSite->iPgetAddress());
1460     AstNode *func = new AstNode("DYNINSTRegisterCallee", 
1461                                 the_args);
1462     addInstFunc(this, callSite, func, callPreInsn,
1463                 orderFirstAtPoint,
1464                 true,
1465                 false);
1466   }
1467   else if(isTrueCallInsn(callSite->originalInstruction)){
1468     //True call destinations are always statically determinable.
1469     return true;
1470   }
1471   else return false;
1472
1473   return true;
1474 }
1475 #endif
1476
1477 /****************************************************************************/
1478 /****************************************************************************/
1479 /****************************************************************************/
1480
1481 // Emit code to jump to function CALLEE without linking.  (I.e., when
1482 // CALLEE returns, it returns to the current caller.)  On SPARC, we do
1483 // this by ensuring that the register context upon entry to CALLEE is
1484 // the register context of function we are instrumenting, popped once.
1485 void emitFuncJump(opCode op, 
1486                   char *i, Address &base, 
1487                   const function_base *callee,
1488                   process *proc)
1489 {
1490         assert(op == funcJumpOp);
1491         Address addr;
1492         void cleanUpAndExit(int status);
1493
1494         addr = callee->getEffectiveAddress(proc);
1495         // TODO cast
1496         instruction *insn = (instruction *) ((void*)&i[base]);
1497
1498         generateSetHi(insn, addr, 13); insn++;
1499         // don't want the return address to be used
1500         genImmInsn(insn, JMPLop3, 13, LOW10(addr), 0); insn++;
1501         genSimpleInsn(insn, RESTOREop3, 0, 0, 0); insn++;
1502         base += 3 * sizeof(instruction);
1503 }
1504
1505 bool deleteBaseTramp(process *proc,instPoint* location,
1506                      instInstance* instance)
1507 {
1508         //check whether ther is a base trampoline installed for this
1509         //instPoint. If there is no base trampoline installed than there
1510         //is nothing to delete. 
1511
1512         trampTemplate* currentBaseTramp;
1513         if(!proc->baseMap.find((const instPoint*)location,currentBaseTramp))
1514                 return false;
1515
1516         assert(currentBaseTramp == instance->baseInstance);
1517
1518         bool needToAdd = false;
1519         if ((location->ipType == functionEntry) &&
1520             isInsnType(location->delaySlotInsn,CALLmask,CALLmatch)) 
1521         {
1522                 Address callOffset = location->addr + (2*sizeof(instruction)) + 
1523                                      (location->delaySlotInsn.call.disp30 <<2 );
1524                 Address functionAddress = location->func->getAddress(0);
1525                 u_int functionSize = location->func->size();
1526                 if ((callOffset > functionAddress) && 
1527                     (callOffset < (functionAddress + functionSize))) 
1528                         needToAdd = true;
1529         }       
1530
1531         //it is time to undo all operations done when installing the base 
1532         //trampoline. 
1533
1534         if(location->func->isTrapFunc())
1535                 proc->writeTextWord((caddr_t)(location->addr),
1536                                     location->originalInstruction.raw);
1537         else if(location->hasNoStackFrame()){
1538                 Address currentAddress = location->addr;
1539                 proc->writeTextWord((caddr_t)currentAddress,
1540                                     location->originalInstruction.raw);
1541                 currentAddress += sizeof(instruction);
1542                 instruction currentInstruction ;
1543                 if(location->ipType == callSite)
1544                         currentInstruction.raw = location->delaySlotInsn.raw;
1545                 else
1546                         currentInstruction.raw = location->otherInstruction.raw;
1547
1548                 proc->writeTextWord((caddr_t)currentAddress,currentInstruction.raw);
1549                 currentAddress += sizeof(instruction);
1550                 if(location->ipType != callSite)
1551                         proc->writeTextWord((caddr_t)currentAddress,
1552                                             location->delaySlotInsn.raw);
1553                 else if(location->callAggregate)
1554                         proc->writeTextWord((caddr_t)currentAddress,
1555                                             location->aggregateInsn.raw);
1556         }
1557         else{
1558                 Address locationAddress = 0;
1559                 if(proc->getBaseAddress(location->image_ptr,locationAddress))
1560                         locationAddress += location->addr;
1561
1562                 Address currentAddress = location->addr;
1563                 if(in1BranchInsnRange(locationAddress,currentBaseTramp->baseAddr)){
1564                         if(location->isLongJump){
1565                                 proc->writeTextWord((caddr_t)currentAddress,
1566                                                     location->originalInstruction.raw);
1567                                 currentAddress += sizeof(instruction);
1568                                 proc->writeTextWord((caddr_t)currentAddress,
1569                                                     location->delaySlotInsn.raw);
1570                         }
1571                         else if(location->ipType == functionEntry){
1572                                 currentAddress -= sizeof(instruction);
1573                                 proc->writeTextWord((caddr_t)currentAddress,
1574                                                     location->saveInsn.raw);
1575                         }       
1576                         else
1577                                 proc->writeTextWord((caddr_t)currentAddress,
1578                                                     location->originalInstruction.raw);
1579                 }
1580                 else{
1581                         proc->writeTextWord((caddr_t)currentAddress,
1582                                             location->originalInstruction.raw);
1583
1584                         currentAddress += sizeof(instruction);
1585                         proc->writeTextWord((caddr_t)currentAddress,
1586                                             location->delaySlotInsn.raw);
1587
1588                         currentAddress += sizeof(instruction);
1589                         if(needToAdd){
1590                                 if((location->ipType == functionEntry) &&
1591                                    location->isDelayed) 
1592                                         proc->writeTextWord((caddr_t)currentAddress,
1593                                                             location->isDelayedInsn.raw);
1594                                         
1595                                 else if((location->ipType == callSite) &&
1596                                         location->callAggregate)
1597                                         proc->writeTextWord((caddr_t)currentAddress,
1598                                                             location->aggregateInsn.raw);
1599                                 else
1600                                         assert(0);
1601                         }
1602                 }
1603         }
1604
1605         vector<Address> pointsToCheck;
1606         pointsToCheck.push_back(currentBaseTramp->baseAddr);
1607         pointsToCheck.push_back(instance->trampBase);
1608
1609         vector< vector<Address> > checkPointHolder;
1610         checkPointHolder.push_back((vector<Address>)pointsToCheck);
1611         inferiorFree(proc,currentBaseTramp->baseAddr,checkPointHolder);
1612
1613         return true;
1614 }
1615
1616 #ifdef BPATCH_LIBRARY
1617
1618 #include "BPatch_flowGraph.h"
1619 #include "BPatch_function.h"
1620
1621 #include <sys/systeminfo.h>
1622
1623 /*
1624  * function which check whether the architecture is 
1625  * sparcv8plus or not. For the earlier architectures 
1626  * it is not possible to support random instrumentation 
1627  */
1628 bool isV8plusISA()
1629 {
1630     char isaOptions[256];
1631
1632     if (sysinfo(SI_ISALIST, isaOptions, 256) < 0)
1633         return false;
1634     if (strstr(isaOptions, "sparcv8plus"))
1635         return true;
1636     return false;
1637 }
1638
1639 /*
1640  * createInstructionInstPoint
1641  *
1642  * Create a BPatch_point instrumentation point at the given address, which
1643  * is guaranteed not be one of the "standard" inst points.
1644  *
1645  * proc         The process in which to create the inst point.
1646  * address      The address for which to create the point.
1647  */
1648
1649 BPatch_point *createInstructionInstPoint(process *proc, void *address,BPatch_point** alternative)
1650 {
1651     unsigned i;
1652     Address begin_addr,end_addr,curr_addr;
1653
1654     //the method to check whether conservative base tramp can be installed
1655     //or not since it contains condition code instructions which is
1656     //available after version8plus of sparc
1657
1658     if(!isV8plusISA()){
1659         cerr << "BPatch_image::createInstPointAtAddr : is not supported for";
1660         cerr << " sparc architecture earlier than v8plus\n";
1661         return NULL;
1662     }
1663
1664     curr_addr = (Address)address;
1665
1666     //if the address is not aligned then there is a problem
1667     if(!isAligned(curr_addr))   
1668         return NULL;
1669
1670     function_base *func = proc->findFuncByAddr(curr_addr);
1671
1672     pd_Function* pointFunction = (pd_Function*)func;
1673     Address pointImageBase = 0;
1674     image* pointImage = pointFunction->file()->exec();
1675     proc->getBaseAddress((const image*)pointImage,pointImageBase);
1676
1677     BPatch_function *bpfunc = proc->PDFuncToBPFuncMap[func];
1678     /* XXX Should create here with correct module, but we don't know it. */
1679     if (bpfunc == NULL) bpfunc = new BPatch_function(proc, func, NULL);
1680
1681     BPatch_flowGraph *cfg = bpfunc->getCFG();
1682     BPatch_Set<BPatch_basicBlock*> allBlocks;
1683     cfg->getAllBasicBlocks(allBlocks);
1684
1685     BPatch_basicBlock** belements =
1686                 new BPatch_basicBlock*[allBlocks.size()];
1687     allBlocks.elements(belements);
1688
1689     for(i=0; i< (unsigned)allBlocks.size(); i++) {
1690         void *bbsa, *bbea;
1691         if (belements[i]->getAddressRange(bbsa,bbea)) {
1692             begin_addr = (Address)bbsa;
1693             if ((begin_addr - INSN_SIZE) == curr_addr) {
1694                 delete[] belements;
1695                 BPatch_reportError(BPatchSerious, 118,
1696                                    "point uninstrumentable");
1697                 return NULL;
1698             }
1699         }
1700     }
1701     delete[] belements;
1702
1703     curr_addr -= pointImageBase;
1704
1705     if (func != NULL) {
1706         instPoint *entry = const_cast<instPoint *>(func->funcEntry(NULL));
1707         assert(entry);
1708
1709         begin_addr = entry->iPgetAddress();
1710         end_addr = begin_addr + entry->Size();
1711
1712         if(((begin_addr - INSN_SIZE) <= curr_addr) && 
1713            (curr_addr < end_addr)){ 
1714             BPatch_reportError(BPatchSerious, 117,
1715                                "instrumentation point conflict");
1716             if(alternative)
1717                 *alternative = proc->findOrCreateBPPoint(bpfunc, entry, BPatch_entry);
1718             return NULL;
1719         }
1720
1721         const vector<instPoint*> &exits = func->funcExits(NULL);
1722         for (i = 0; i < exits.size(); i++) {
1723             assert(exits[i]);
1724
1725             begin_addr = exits[i]->iPgetAddress();
1726             end_addr = begin_addr + exits[i]->Size();
1727
1728             if (((begin_addr - INSN_SIZE) <= curr_addr) &&
1729                 (curr_addr < end_addr)){
1730                 BPatch_reportError(BPatchSerious, 117,
1731                                    "instrumentation point conflict");
1732                 if(alternative)
1733                         *alternative = proc->findOrCreateBPPoint(bpfunc,exits[i],BPatch_exit);
1734                 return NULL;
1735             }
1736         }
1737
1738         const vector<instPoint*> &calls = func->funcCalls(NULL);
1739         for (i = 0; i < calls.size(); i++) {
1740             assert(calls[i]);
1741
1742             begin_addr = calls[i]->iPgetAddress();
1743             end_addr = begin_addr + calls[i]->Size();
1744
1745             if (((begin_addr - INSN_SIZE) <= curr_addr) &&
1746                 (curr_addr < end_addr)){
1747                 BPatch_reportError(BPatchSerious, 117,
1748                                    "instrumentation point conflict");
1749                 if(alternative)
1750                         *alternative = proc->findOrCreateBPPoint(bpfunc,calls[i],BPatch_subroutine);
1751                 return NULL;
1752             }
1753         }
1754     }
1755
1756     curr_addr += pointImageBase;
1757
1758     /* Check for conflict with a previously created inst point. */
1759     if (proc->instPointMap.defines(curr_addr - INSN_SIZE)) {
1760         BPatch_reportError(BPatchSerious,117,"instrumentation point conflict");
1761         if(alternative)
1762                 *alternative = (proc->instPointMap)[curr_addr-INSN_SIZE];
1763         return NULL;
1764     } else if (proc->instPointMap.defines(curr_addr + INSN_SIZE)) {
1765         BPatch_reportError(BPatchSerious,117,"instrumentation point conflict");
1766         if(alternative)
1767                 *alternative = (proc->instPointMap)[curr_addr+INSN_SIZE];
1768         return NULL;
1769     }
1770
1771     /* Check for instrumenting just before or after a branch. */
1772
1773     bool decrement = false;
1774     if ((Address)address > func->getEffectiveAddress(proc)) {
1775         instruction prevInstr;
1776         proc->readTextSpace((char *)address - INSN_SIZE,
1777                             sizeof(instruction),
1778                             &prevInstr.raw);
1779         if (IS_DELAYED_INST(prevInstr)){
1780           if((prevInstr.call.op == CALLop) ||
1781              ((prevInstr.call.op != CALLop) && !prevInstr.branch.anneal))
1782           {
1783               BPatch_reportError(BPatchSerious, 118, "point uninstrumentable");
1784               return NULL;
1785           }
1786           decrement = true;
1787         }
1788     }
1789
1790     if ((Address)address + INSN_SIZE <
1791         func->getEffectiveAddress(proc) + func->size()) {
1792         instruction nextInstr;
1793         proc->readTextSpace((char *)address + INSN_SIZE,
1794                             sizeof(instruction),
1795                             &nextInstr.raw);
1796         if (IS_DELAYED_INST(nextInstr)){
1797           proc->readTextSpace((char *)address + 2*INSN_SIZE,
1798                             sizeof(instruction),
1799                             &nextInstr.raw);
1800           if(!isNopInsn(nextInstr)){
1801               BPatch_reportError(BPatchSerious, 118,
1802                                  "point uninstrumentable");
1803               return NULL;
1804           }
1805         }
1806     }
1807
1808     if(decrement){
1809       address = (void*)((Address)address - INSN_SIZE);
1810       curr_addr -= INSN_SIZE;
1811     }
1812
1813     instruction instr;
1814     proc->readTextSpace(address, sizeof(instruction), &instr.raw);
1815         
1816     curr_addr -= pointImageBase;
1817     //then create the instrumentation point object for the address
1818     instPoint *newpt = new instPoint(pointFunction,
1819                                      (const instructUnion &)instr,
1820                                      (const image*)pointImage,
1821                                      (Address &)curr_addr,
1822                                      false, // bool delayOk - ignored,
1823                                      otherPoint);
1824
1825     pointFunction->addArbitraryPoint(newpt,proc);
1826
1827     return proc->findOrCreateBPPoint(bpfunc, newpt, BPatch_instruction);
1828 }
1829
1830 /*
1831  * BPatch_point::getDisplacedInstructions
1832  *
1833  * Returns the instructions to be relocated when instrumentation is inserted
1834  * at this point.  Returns the number of bytes taken up by these instructions.
1835  *
1836  * maxSize      The maximum number of bytes of instructions to return.
1837  * insns        A pointer to a buffer in which to return the instructions.
1838  */
1839 int BPatch_point::getDisplacedInstructions(int maxSize, void* insns)
1840 {
1841     int count = 0;
1842     instruction copyOut[10];    // I think 7 is the max - jkh 8/3/00
1843
1844     //
1845     // This function is based on what is contained in the instPoint 
1846     //    constructor in the file inst-sparc-solaris.C
1847     //
1848     if (!point->hasNoStackFrame()) {
1849         if (point->ipType == functionEntry) {
1850             copyOut[count++].raw = point->saveInsn.raw;
1851             copyOut[count++].raw = point->originalInstruction.raw;
1852             copyOut[count++].raw = point->delaySlotInsn.raw;
1853             if (point->isDelayed) {
1854                 copyOut[count++].raw = point->isDelayedInsn.raw;
1855                 if (point->callAggregate) {
1856                     copyOut[count++].raw = point->aggregateInsn.raw;
1857                 }
1858             }
1859         } else if (point->ipType == callSite) {
1860             copyOut[count++].raw = point->originalInstruction.raw;
1861             copyOut[count++].raw = point->delaySlotInsn.raw;
1862             if (point->callAggregate) {
1863                 copyOut[count++].raw = point->aggregateInsn.raw;
1864             }
1865         } else {
1866             copyOut[count++].raw = point->originalInstruction.raw;
1867             copyOut[count++].raw = point->delaySlotInsn.raw;
1868         }
1869     } else {
1870         if (point->ipType == functionEntry) {
1871             copyOut[count++].raw = point->originalInstruction.raw;
1872             copyOut[count++].raw = point->otherInstruction.raw;
1873             copyOut[count++].raw = point->delaySlotInsn.raw;
1874             if (point->isDelayed) {
1875                 copyOut[count++].raw = point->isDelayedInsn.raw;
1876             }
1877         } else if (point->ipType == functionExit) {
1878             copyOut[count++].raw = point->originalInstruction.raw;
1879             copyOut[count++].raw = point->otherInstruction.raw;
1880             copyOut[count++].raw = point->delaySlotInsn.raw;
1881             if (point->inDelaySlot) {
1882                 copyOut[count++].raw = point->inDelaySlotInsn.raw;
1883                 if (point->firstIsConditional) {
1884                     copyOut[count++].raw = point->extraInsn.raw;
1885                 }
1886             }
1887         } else if(point->ipType == otherPoint) {
1888            copyOut[count++].raw = point->originalInstruction.raw;
1889            copyOut[count++].raw = point->otherInstruction.raw;
1890         } else {
1891            assert(point->ipType == callSite);
1892            copyOut[count++].raw = point->originalInstruction.raw;
1893            copyOut[count++].raw = point->delaySlotInsn.raw;
1894            if (point->callAggregate) {
1895                copyOut[count++].raw = point->aggregateInsn.raw;
1896            }
1897         }
1898     }
1899
1900     if (count * sizeof(instruction) > (unsigned) maxSize) {
1901         return -1;
1902     } else {
1903         memcpy(insns, copyOut, count * sizeof(instruction));
1904         return count * sizeof(instruction);
1905     }
1906 }
1907
1908 #endif
1909
1910 // needed in metric.C
1911 bool instPoint::match(instPoint *p)
1912 {
1913   if (this == p)
1914     return true;
1915   
1916   // should we check anything else?
1917   if (addr == p->addr)
1918     return true;
1919   
1920   return false;
1921 }