Corrected mistake of reconstructing base trampolines from instInstance's.
[dyninst.git] / dyninstAPI / src / inst-power.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 /*
43  * inst-power.C - Identify instrumentation points for a RS6000/PowerPCs
44  *
45  * inst-power.C,v
46  * Revision 1.16  1996/05/12  05:16:45  tamches
47  * (really Jeff)
48  * Now works with aix 4.1
49  *
50  * Revision 1.15  1996/05/10 05:12:34  tamches
51  * changed vrble addr to dest; can now compile ok
52  *
53  * Revision 1.14  1996/04/29 22:18:44  mjrg
54  * Added size to functions (get size from symbol table)
55  * Use size to define function boundary
56  * Find multiple return points for sparc
57  * Instrument branches and jumps out of a function as return points (sparc)
58  * Recognize tail-call optimizations and instrument them as return points (sparc)
59  * Move instPoint to machine dependent files
60  *
61  * Revision 1.13  1996/04/26 20:53:36  lzheng
62  * Changes to the procedure emitFuncCall. (move all the code dealing with
63  * the function Calls in the miniTrampoline to here)
64  *
65  * Revision 1.12  1996/03/25 22:58:02  hollings
66  * Support functions that have multiple exit points.
67  *
68  * Revision 1.11  1996/03/20  20:40:31  hollings
69  * Fixed bug in register save/restore for function calls and conditionals
70  *
71  */
72
73 #include "util/h/headers.h"
74
75 #include "rtinst/h/rtinst.h"
76 #include "dyninstAPI/src/symtab.h"
77 #include "dyninstAPI/src/process.h"
78 #include "dyninstAPI/src/inst.h"
79 #include "dyninstAPI/src/instP.h"
80 #include "dyninstAPI/src/inst-power.h"
81 #include "dyninstAPI/src/arch-power.h"
82 #include "dyninstAPI/src/aix.h"
83 #include "dyninstAPI/src/ast.h"
84 #include "dyninstAPI/src/util.h"
85 #include "dyninstAPI/src/stats.h"
86 #include "dyninstAPI/src/os.h"
87 #include "dyninstAPI/src/instPoint.h" // class instPoint
88 #include "paradynd/src/showerror.h"
89 #include "util/h/debugOstream.h"
90
91 // The following vrbles were defined in process.C:
92 extern debug_ostream attach_cerr;
93 extern debug_ostream inferiorrpc_cerr;
94 extern debug_ostream shmsample_cerr;
95 extern debug_ostream forkexec_cerr;
96 extern debug_ostream metric_cerr;
97
98 #define perror(a) P_abort();
99
100 extern bool isPowerOf2(int value, int &result);
101
102 #define ABS(x)          ((x) > 0 ? x : -x)
103 #define MAX_BRANCH      0x1<<23
104 #define MAX_CBRANCH     0x1<<13
105
106 #define MAX_IMM         0x1<<15         /* 15 plus sign == 16 bits */
107
108 unsigned getMaxBranch() {
109   return MAX_BRANCH;
110 }
111
112 const char *registerNames[] = { "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
113                         "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
114                         "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
115                         "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31"};
116
117 dictionary_hash<string, unsigned> funcFrequencyTable(string::hash);
118
119 inline void generateBranchInsn(instruction *insn, int offset)
120 {
121     if (ABS(offset) > MAX_BRANCH) {
122         logLine("a branch too far\n");
123         showErrorCallback(52, "Internal error: branch too far");
124         abort();
125     }
126
127     insn->raw = 0;
128     insn->iform.op = Bop;
129     insn->iform.aa = 0;
130     insn->iform.lk = 0;
131     insn->iform.li = offset >> 2;
132
133     // logLine("ba,a %x\n", offset);
134 }
135
136 inline void genImmInsn(instruction *insn, int op, reg rt, reg ra, int immd)
137 {
138   // something should be here to make sure immd is within bounds
139   insn->raw = 0;
140   insn->dform.op = op;
141   insn->dform.rt = rt;
142   insn->dform.ra = ra;
143   if (op==SIop) immd = -immd;
144   insn->dform.d_or_si = immd;
145 }
146
147 // rlwinm ra,rs,n,0,31-n
148 inline void generateLShift(instruction *insn, int rs, int offset, int ra)
149 {
150     assert(offset<32);
151     insn->raw = 0;
152     insn->mform.op = RLINMxop;
153     insn->mform.rs = rs;
154     insn->mform.ra = ra;
155     insn->mform.sh = offset;
156     insn->mform.mb = 0;
157     insn->mform.me = 31-offset;
158     insn->mform.rc = 0;
159 }
160
161 // rlwinm ra,rs,32-n,n,31
162 inline void generateRShift(instruction *insn, int rs, int offset, int ra)
163 {
164     assert(offset<32);
165     insn->raw = 0;
166     insn->mform.op = RLINMxop;
167     insn->mform.rs = rs;
168     insn->mform.ra = ra;
169     insn->mform.sh = 32-offset;
170     insn->mform.mb = offset;
171     insn->mform.me = 31;
172     insn->mform.rc = 0;
173 }
174
175 //
176 // generate an instruction that does nothing and has to side affect except to
177 //   advance the program counter.
178 //
179 inline void generateNOOP(instruction *insn)
180 {
181   insn->raw = NOOPraw;
182 }
183
184 inline void genSimpleInsn(instruction *insn, int op, reg src1, reg src2, 
185                           reg dest, unsigned &base)
186 {
187     int xop=-1;
188     insn->raw = 0;
189     insn->xform.op = op;
190     insn->xform.rt = src1;
191     insn->xform.ra = dest;
192     insn->xform.rb = src2;
193     if (op==ANDop) {
194       xop=ANDxop;
195     } else if (op==ORop) {
196       xop=ORxop;
197     } else {
198       // only AND and OR are currently designed to use genSimpleInsn
199       abort();
200     }
201     insn->xform.xo = xop;
202     base += sizeof(instruction);
203 }
204
205 inline void genRelOp(instruction *insn, int cond, int mode, reg rs1,
206                      reg rs2, reg rd, unsigned &base)
207 {
208     // cmp rs1, rs2
209     insn->raw = 0;
210     insn->xform.op = CMPop;
211     insn->xform.rt = 0;    // really bf & l sub fields of rt we care about
212     insn->xform.ra = rs1;
213     insn->xform.rb = rs2;
214     insn->xform.xo = CMPxop;
215     insn++;
216
217     // li rd, 1
218     genImmInsn(insn, CALop, rd, 0, 1);
219     insn++;
220
221     // b??,a +2
222     insn->bform.op = BCop;
223     insn->bform.bi = cond;
224     insn->bform.bo = mode;
225     insn->bform.bd = 2;         // + two instructions */
226     insn->bform.aa = 0;
227     insn->bform.lk = 0;
228     insn++;
229
230     // clr rd
231     genImmInsn(insn, CALop, rd, 0, 0);
232     base += 4 * sizeof(instruction);
233 }
234
235
236 instPoint::instPoint(pd_Function *f, const instruction &instr, 
237                      const image *, Address adr, bool, ipFuncLoc fLoc) 
238                       : addr(adr), originalInstruction(instr), 
239                         callIndirect(false), callee(NULL), func(f), ipLoc(fLoc)
240 {
241    // inDelaySlot = false;
242    // isDelayed = false;
243    // callAggregate = false;
244 }
245
246 // Determine if the called function is a "library" function or a "user" function
247 // This cannot be done until all of the functions have been seen, verified, and
248 // classified
249 //
250 void pd_Function::checkCallPoints() {
251   unsigned int i;
252   instPoint *p;
253   Address loc_addr;
254
255   vector<instPoint*> non_lib;
256
257   for (i=0; i<calls.size(); ++i) {
258     /* check to see where we are calling */
259     p = calls[i];
260     assert(p);
261
262     if(isCallInsn(p->originalInstruction)) {
263       loc_addr = p->addr + (p->originalInstruction.iform.li << 2);
264       pd_Function *pdf = (file_->exec())->findFunction(loc_addr);
265       if (pdf && !pdf->isLibTag()) {
266         p->callee = pdf;
267         non_lib += p;
268       } else {
269         delete p;
270       }
271     } else {
272       // Indirect call -- be conservative, assume it is a call to
273       // an unnamed user function
274       assert(!p->callee); assert(p->callIndirect);
275       p->callee = NULL;
276       non_lib += p;
277     }
278   }
279   calls = non_lib;
280 }
281
282 // TODO we cannot find the called function by address at this point in time
283 // because the called function may not have been seen.
284 //
285 Address pd_Function::newCallPoint(const Address adr, const instruction instr,
286                                  const image *owner, bool &err)
287 {
288     Address ret=adr;
289     instPoint *point;
290     err = true;
291
292     point = new instPoint(this, instr, owner, adr, false, ipFuncCallPoint);
293
294     if (!isCallInsn(instr)) {
295       point->callIndirect = true;
296       point->callee = NULL;
297     } else
298       point->callIndirect = false;
299
300     // point->callAggregate = false;
301
302     calls += point;
303     err = false;
304     return ret;
305 }
306
307 void initDefaultPointFrequencyTable()
308 {
309     funcFrequencyTable[EXIT_NAME] = 1;
310
311 #ifdef notdef
312     FILE *fp;
313     float value;
314     char name[512];
315
316     funcFrequencyTable["main"] = 1;
317     funcFrequencyTable["DYNINSTsampleValues"] = 1;
318     // try to read file.
319     fp = fopen("freq.input", "r");
320     if (!fp) {
321         printf("no freq.input file\n");
322         return;
323     }
324     while (!feof(fp)) {
325         fscanf(fp, "%s %f\n", name, &value);
326         funcFrequencyTable[name] = (int) value;
327         printf("adding %s %f\n", name, value);
328     }
329     fclose(fp);
330 #endif
331 }
332
333 /*
334  * Get an etimate of the frequency for the passed instPoint.  
335  *    This is not (always) the same as the function that contains the point.
336  * 
337  *  The function is selected as follows:
338  *
339  *  If the point is an entry or an exit return the function name.
340  *  If the point is a call and the callee can be determined, return the called
341  *     function.
342  *  else return the funcation containing the point.
343  *
344  *  WARNING: This code contins arbitray values for func frequency (both user 
345  *     and system).  This should be refined over time.
346  *
347  * Using 1000 calls sec to be one SD from the mean for most FPSPEC apps.
348  *      -- jkh 6/24/94
349  *
350  */
351 float getPointFrequency(instPoint *point)
352 {
353
354     pd_Function *func;
355
356     if (point->callee)
357         func = point->callee;
358     else
359         func = point->func;
360
361     if (!funcFrequencyTable.defines(func->prettyName())) {
362       if (func->isLibTag()) {
363         return(100);
364       } else {
365         // Changing this value from 250 to 100 because predictedCost was
366         // too high - naim 07/18/96
367         return(100);
368       }
369     } else {
370       return (funcFrequencyTable[func->prettyName()]);
371     }
372 }
373
374 //
375 // return cost in cycles of executing at this point.  This is the cost
376 //   of the base tramp if it is the first at this point or 0 otherwise.
377 //
378 int getPointCost(process *proc, const instPoint *point)
379 {
380     if (proc->baseMap.defines(point)) {
381         return(0);
382     } else {
383         // 35 cycles for base tramp
384         // + 70 cyles for MT version (assuming 1 cycle per instruction)
385         return(105);
386     }
387 }
388
389 /*
390  * Given and instruction, relocate it to a new address, patching up
391  *   any relative addressing that is present.
392  *
393  */
394 void relocateInstruction(instruction *insn, int origAddr, int targetAddr)
395 {
396     int newOffset;
397
398     if (isInsnType(*insn, Bmask, Bmatch)) {
399       // unconditional pc relative branch.
400       newOffset = origAddr  - targetAddr + (insn->iform.li << 2);
401       if (ABS(newOffset) > MAX_BRANCH) {
402         logLine("a branch too far\n");
403         abort();
404       } else {
405         insn->iform.li = newOffset >> 2;
406       }
407     } else if (isInsnType(*insn, Bmask, BCmatch)) {
408       // conditional pc relative branch.
409       newOffset = origAddr - targetAddr + (insn->bform.bd << 2);
410       if (ABS(newOffset) > MAX_CBRANCH) {
411         logLine("a branch too far\n");
412         abort();
413       } else {
414         insn->bform.bd = newOffset >> 2;
415       }
416     } else if (insn->iform.op == SVCop) {
417       logLine("attempt to relocate a system call\n");
418       abort();
419     } 
420     /* The rest of the instructions should be fine as is */
421 }
422
423 trampTemplate baseTemplate;
424
425 extern "C" void baseTramp();
426
427 void initATramp(trampTemplate *thisTemp, instruction *tramp)
428 {
429     instruction *temp;
430
431     // TODO - are these offset always positive?
432     thisTemp->trampTemp = (void *) tramp;
433     for (temp = tramp; temp->raw != END_TRAMP; temp++) {
434         switch (temp->raw) {
435             case LOCAL_PRE_BRANCH:
436                 thisTemp->localPreOffset = ((void*)temp - (void*)tramp);
437                 thisTemp->localPreReturnOffset = thisTemp->localPreOffset
438                                                  + 4 * sizeof(temp->raw);
439                 break;
440             case GLOBAL_PRE_BRANCH:
441                 thisTemp->globalPreOffset = ((void*)temp - (void*)tramp);
442                 break;
443             case LOCAL_POST_BRANCH:
444                 thisTemp->localPostOffset = ((void*)temp - (void*)tramp);
445                 thisTemp->localPostReturnOffset = thisTemp->localPostOffset
446                                                   + 4 * sizeof(temp->raw);
447                 break;
448             case GLOBAL_POST_BRANCH:
449                 thisTemp->globalPostOffset = ((void*)temp - (void*)tramp);
450                 break;
451             case SKIP_PRE_INSN:
452                 thisTemp->skipPreInsOffset = ((void*)temp - (void*)tramp);
453                 break;
454             case UPDATE_COST_INSN:
455                 thisTemp->updateCostOffset = ((void*)temp - (void*)tramp);
456                 break;
457             case SKIP_POST_INSN:
458                 thisTemp->skipPostInsOffset = ((void*)temp - (void*)tramp);
459                 break;
460             case RETURN_INSN:
461                 thisTemp->returnInsOffset = ((void*)temp - (void*)tramp);
462                 break;
463             case EMULATE_INSN:
464                 thisTemp->emulateInsOffset = ((void*)temp - (void*)tramp);
465                 break;
466         }       
467     }
468     thisTemp->cost = 8;
469     thisTemp->prevBaseCost = 20;
470     thisTemp->postBaseCost = 30;
471     thisTemp->prevInstru = thisTemp->postInstru = false;
472     thisTemp->size = (int) temp - (int) tramp;
473 }
474
475 registerSpace *regSpace;
476
477 // 11-12 are defined not to have live values at procedure call points.
478 // reg 3-10 are used to pass arguments to functions.
479 //   We must save them before we can use them.
480 #if defined(SHM_SAMPLING) && defined(MT_THREAD)
481 int deadRegList[] = { 11 };
482 #else
483 int deadRegList[] = { 11, 12 };
484 #endif
485
486 // allocate in reverse order since we use them to build arguments.
487 int liveRegList[] = { 10, 9, 8, 7, 6, 5, 4, 3 };
488
489 void initTramps()
490 {
491     static bool inited=false;
492
493     if (inited) return;
494     inited = true;
495
496     initATramp(&baseTemplate, (instruction *) baseTramp);
497
498     regSpace = new registerSpace(sizeof(deadRegList)/sizeof(int), deadRegList, 
499                                  sizeof(liveRegList)/sizeof(int), liveRegList);
500 }
501
502
503            ////////////////////////////////////////////////////////////////////
504            //Generates instructions to save link register onto stack.
505            //  Returns the number of bytes needed to store the generated
506            //    instructions.
507            //  The instruction storage pointer is advanced the number of 
508            //    instructions generated.
509            //
510 static int saveLR(instruction *&insn,       //Instruction storage pointer
511                   reg           scratchReg, //Scratch register
512                   int           stkOffset)  //Offset from stack pointer
513 {
514   insn->raw = 0;                    //mfspr:  mflr scratchReg
515   insn->xform.op = 31;
516   insn->xform.rt = scratchReg;
517   insn->xform.ra = 8;
518   insn->xform.xo = 339;
519   insn++;
520
521   insn->raw = 0;                    //st:     st scratchReg, stkOffset(r1)
522   insn->dform.op      = 36;
523   insn->dform.rt      = scratchReg;
524   insn->dform.ra      = 1;
525   insn->dform.d_or_si = stkOffset;
526   insn++;
527
528   return 2 * sizeof(instruction);
529 }
530
531            ////////////////////////////////////////////////////////////////////
532            //Generates instructions to restore link register from stack.
533            //  Returns the number of bytes needed to store the generated
534            //    instructions.
535            //  The instruction storage pointer is advanced the number of 
536            //    instructions generated.
537            //
538 static int restoreLR(instruction *&insn,       //Instruction storage pointer
539                      reg           scratchReg, //Scratch register
540                      int           stkOffset)  //Offset from stack pointer
541 {
542   insn->raw = 0;                    //l:      l scratchReg, stkOffset(r1)
543   insn->dform.op      = 32;
544   insn->dform.rt      = scratchReg;
545   insn->dform.ra      = 1;
546   insn->dform.d_or_si = stkOffset;
547   insn++;
548
549   insn->raw = 0;                    //mtspr:  mtlr scratchReg
550   insn->xform.op = 31;
551   insn->xform.rt = scratchReg;
552   insn->xform.ra = 8;
553   insn->xform.xo = 467;
554   insn++;
555
556   return 2 * sizeof(instruction);
557 }
558
559
560            ////////////////////////////////////////////////////////////////////
561            //Generates instructions to place a given value into link register.
562            //  The entire instruction sequence consists of the generated
563            //    instructions followed by a given (tail) instruction.
564            //  Returns the number of bytes needed to store the entire
565            //    instruction sequence.
566            //  The instruction storage pointer is advanced the number of 
567            //    instructions in the sequence.
568            //
569 static int setBRL(instruction *&insn,        //Instruction storage pointer
570                   reg           scratchReg,  //Scratch register
571                   unsigned      val,         //Value to set link register to
572                   unsigned      ti)          //Tail instruction
573 {
574   insn->raw =0;                  //cau:  cau scratchReg, 0, HIGH(val)
575   insn->dform.op      = 15;
576   insn->dform.rt      = scratchReg;
577   insn->dform.ra      = 0;
578   insn->dform.d_or_si = ((val >> 16) & 0x0000ffff);
579   insn++;
580
581   insn->raw = 0;                 //oril:  oril scratchReg, scratchReg, LOW(val)
582   insn->dform.op      = 24;
583   insn->dform.rt      = scratchReg;
584   insn->dform.ra      = scratchReg;
585   insn->dform.d_or_si = (val & 0x0000ffff);
586   insn++;
587  
588   insn->raw = 0;                 //mtspr:  mtlr scratchReg
589   insn->xform.op = 31;
590   insn->xform.rt = scratchReg;
591   insn->xform.ra = 8;
592   insn->xform.xo = 467;
593   insn++;
594
595   insn->raw = ti;
596   insn++;
597
598   return 4 * sizeof(instruction);
599 }
600
601
602      //////////////////////////////////////////////////////////////////////////
603      //Writes out instructions to place a value into the link register.
604      //  If val == 0, then the instruction sequence is followed by a `nop'.
605      //  If val != 0, then the instruction sequence is followed by a `brl'.
606      //
607 void resetBRL(process  *p,   //Process to write instructions into
608               unsigned  loc, //Address in process to write into
609               unsigned  val) //Value to set link register
610 {
611   instruction  i[8];                          //8 just to be safe
612   instruction *t        = i;                  //To avoid side-effects on i
613   int          numBytes = val ? setBRL(t, 10, val, BRLraw)
614                               : setBRL(t, 10, val, NOOPraw);
615
616   p->writeTextSpace((void *)loc, numBytes, i);
617 }
618
619      //////////////////////////////////////////////////////////////////////////
620      //Writes out a `br' instruction
621      //
622 void resetBR(process  *p,    //Process to write instruction into
623              unsigned  loc)  //Address in process to write into
624 {
625   instruction i;
626
627   i.raw = BRraw;
628
629   p->writeDataSpace((void *)loc, sizeof(instruction), &i);
630 }
631
632 static void saveRegister(instruction *&insn, unsigned &base, int reg,
633                   int offset)
634 {
635   assert(reg >= 0);
636   genImmInsn(insn, STop, reg, 1, -1*((reg+1)*4 + offset));
637   insn++;
638   base += sizeof(instruction);
639 }
640
641 static void restoreRegister(instruction *&insn, unsigned &base, int reg, int dest,
642                      int offset)
643 {
644   assert(reg >= 0);
645   genImmInsn(insn, Lop, dest, 1, -1*((reg+1)*4 + offset));
646   insn++;
647   base += sizeof(instruction);
648 }
649
650 static void restoreRegister(instruction *&insn, unsigned &base, int reg,
651                      int offset)
652 {
653   restoreRegister(insn, base, reg, reg, offset);
654 }       
655
656 static void saveFPRegister(instruction *&insn, unsigned &base, int reg,
657                     int offset)
658 {
659   assert(reg >= 0);
660   genImmInsn(insn, STFDop, reg, 1, -1*((reg+1)*8 + offset));
661   insn++;
662   base += sizeof(instruction);
663 }
664
665 static void restoreFPRegister(instruction *&insn, unsigned &base, int reg, int dest,
666                        int offset)
667 {
668   assert(reg >= 0);
669   genImmInsn(insn, LFDop, dest, 1, -1*((reg+1)*8 + offset));
670   insn++;
671   base += sizeof(instruction);
672 }
673
674 static void restoreFPRegister(instruction *&insn, unsigned &base, int reg,
675                        int offset)
676 {
677   restoreFPRegister(insn, base, reg, reg, offset);
678 }       
679
680 void saveAllRegistersThatNeedsSaving(instruction *insn, unsigned &base)
681 {
682    unsigned numInsn=0;
683    for (int i = 0; i < regSpace->getRegisterCount(); i++) {
684      registerSlot *reg = regSpace->getRegSlot(i);
685      if (reg->startsLive) {
686        saveRegister(insn,numInsn,reg->number,8);
687      }
688    }
689    base += numInsn/sizeof(instruction);
690 }
691
692 void restoreAllRegistersThatNeededSaving(instruction *insn, unsigned &base)
693 {
694    unsigned numInsn=0;
695    for (int i = 0; i < regSpace->getRegisterCount(); i++) {
696      registerSlot *reg = regSpace->getRegSlot(i);
697      if (reg->startsLive) {
698        restoreRegister(insn,numInsn,reg->number,8);
699      }
700    }
701    base += numInsn/sizeof(instruction);
702 }
703
704 void generateMTpreamble(char *insn, unsigned &base, process *proc)
705 {
706   AstNode *t1,*t2,*t3,*t4,*t5;
707   vector<AstNode *> dummy;
708   unsigned tableAddr;
709   int value; 
710   bool err;
711   reg src = -1;
712
713   // registers cleanup
714   regSpace->resetSpace();
715
716   /* t3=DYNINSTthreadTable[thr_self()] */
717   t1 = new AstNode("DYNINSTthreadPos", dummy);
718   value = sizeof(unsigned);
719   t4 = new AstNode(AstNode::Constant,(void *)value);
720   t2 = new AstNode(timesOp, t1, t4);
721   removeAst(t1);
722   removeAst(t4);
723
724   tableAddr = proc->findInternalAddress("DYNINSTthreadTable",true,err);
725   assert(!err);
726   t5 = new AstNode(AstNode::Constant, (void *)tableAddr);
727   t3 = new AstNode(plusOp, t2, t5);
728   removeAst(t2);
729   removeAst(t5);
730   src = t3->generateCode(proc, regSpace, insn, base, false);
731   removeAst(t3);
732   instruction *tmp_insn = (instruction *) ((void*)&insn[base]);
733   genImmInsn(tmp_insn, ORILop, src, REG_MT, 0);  
734   base += sizeof(instruction);
735   regSpace->freeRegister(src);
736 }
737
738 /*
739  * Install a base tramp -- fill calls with nop's for now.
740  *
741  */
742 trampTemplate *installBaseTramp(instPoint *location, process *proc,
743                                 unsigned exitTrampAddr = 0,
744                                 unsigned baseAddr = 0)
745 {
746     unsigned currAddr;
747     instruction *code;
748     instruction *temp;
749     unsigned     isReinstall = baseAddr; //Reinstalling base trampoline
750
751     if (! isReinstall) 
752       baseAddr = inferiorMalloc(proc, baseTemplate.size, textHeap);
753     code = new instruction[baseTemplate.size / sizeof(instruction)];
754     memcpy((char *) code, (char*) baseTemplate.trampTemp, baseTemplate.size);
755     // bcopy(baseTemplate.trampTemp, code, baseTemplate.size);
756
757     for (temp = code, currAddr = baseAddr; 
758         (int) (currAddr - baseAddr) < baseTemplate.size;
759         temp++, currAddr += sizeof(instruction)) {
760         if(temp->raw == UPDATE_LR) {
761           if(location->ipLoc == ipFuncReturn) {
762             // loading the old LR from the 4th word from the stack, 
763             // in the link-area
764             genImmInsn(&code[0], Lop, 0, 1, 12);
765             code[1].raw = MTLR0raw;
766             // the rest of the instrs are already NOOPs
767           } else if((location->ipLoc == ipFuncEntry) && (exitTrampAddr != 0)) {
768             code[0].raw = MFLR0raw;
769             // storing the old LR in the 4th word from the stack, 
770             // in the link-area
771             genImmInsn(&code[1], STop, 0, 1, 12); 
772             genImmInsn(&code[2], CAUop, 0, 0, HIGH(exitTrampAddr));
773             genImmInsn(&code[3], ORILop, 0, 0, LOW(exitTrampAddr));
774             code[4].raw = MTLR0raw;
775           } else {
776             generateNOOP(temp);
777             // the rest of the instrs are already NOOPs
778           }
779         } else if (temp->raw == EMULATE_INSN) {
780           if(location->ipLoc == ipFuncReturn) {
781             generateNOOP(temp);
782           } else {
783             *temp = location->originalInstruction;
784             relocateInstruction(temp, location->addr, currAddr);
785           }
786         } else if (temp->raw == RETURN_INSN) {
787           if(location->ipLoc == ipFuncReturn) {
788             temp->raw = BRraw;
789           } else {
790             generateBranchInsn(temp, (location->addr + 
791                                       sizeof(instruction) - currAddr));
792           }
793         } else if (temp->raw == SKIP_PRE_INSN) {
794           unsigned offset;
795           //offset = baseAddr+baseTemplate.updateCostOffset-currAddr;
796           offset = baseAddr+baseTemplate.emulateInsOffset-currAddr;
797           generateBranchInsn(temp,offset);
798
799         } else if (temp->raw == SKIP_POST_INSN) {
800             unsigned offset;
801             offset = baseAddr+baseTemplate.returnInsOffset-currAddr;
802             generateBranchInsn(temp,offset);
803
804         } else if (temp->raw == UPDATE_COST_INSN) {
805             baseTemplate.costAddr = currAddr;
806             generateNOOP(temp);
807
808         } else if ((temp->raw == SAVE_PRE_INSN) || 
809                    (temp->raw == SAVE_POST_INSN)) {
810             unsigned numInsn=0;
811             for(int i = 0; i < regSpace->getRegisterCount(); i++) {
812               registerSlot *reg = regSpace->getRegSlot(i);
813               if (reg->startsLive) {
814                 numInsn = 0;
815                 saveRegister(temp,numInsn,reg->number,8);
816                 assert(numInsn > 0);
817                 currAddr += numInsn;
818               }
819             }
820
821             currAddr += saveLR(temp, 10, -56);  //Save link register on stack
822
823             // Also save the floating point registers which could
824             // be modified, f0-r13
825             for(int i=0; i <= 13; i++) {
826               numInsn = 0;
827               saveFPRegister(temp,numInsn,i,8+(32*4));
828               currAddr += numInsn;
829             }
830             
831             // if there is more than one instruction, we need this
832             if (numInsn>0) {
833               temp--;
834               currAddr -= sizeof(instruction);
835             }
836         } else if ((temp->raw == RESTORE_PRE_INSN) || 
837                    (temp->raw == RESTORE_POST_INSN)) {
838
839             currAddr += restoreLR(temp, 10, -56); //Restore link register from
840                                                   //  stack
841             unsigned numInsn=0;
842             for (int i = 0; i < regSpace->getRegisterCount(); i++) {
843               registerSlot *reg = regSpace->getRegSlot(i);
844               if (reg->startsLive) {
845                 numInsn = 0;
846                 restoreRegister(temp,numInsn,reg->number,8);
847                 assert(numInsn > 0);
848                 currAddr += numInsn;
849               }
850             }
851             // Also load the floating point registers which were save
852             // since they could have been modified, f0-r13
853             for(int i=0; i <= 13; i++) {
854               numInsn = 0;
855               restoreFPRegister(temp,numInsn,i,8+(32*4));
856               currAddr += numInsn;
857             }
858
859             // if there is more than one instruction, we need this 
860             if (numInsn>0) {
861               temp--;
862               currAddr -= sizeof(instruction);
863             }
864         } else if ((temp->raw == LOCAL_PRE_BRANCH) ||
865                    (temp->raw == GLOBAL_PRE_BRANCH) ||
866                    (temp->raw == LOCAL_POST_BRANCH) ||
867                    (temp->raw == GLOBAL_POST_BRANCH)) {
868 #if defined(SHM_SAMPLING) && defined(MT_THREAD)
869             if ((temp->raw == LOCAL_PRE_BRANCH) ||
870                 (temp->raw == LOCAL_POST_BRANCH)) {
871                 temp -= NUM_INSN_MT_PREAMBLE;
872                 unsigned numIns=0;
873                 generateMTpreamble((char *)temp, numIns, proc);
874                 numIns = numIns/sizeof(instruction);
875                 if(numIns != NUM_INSN_MT_PREAMBLE) {
876                   cerr << "numIns = " << numIns << endl;
877                   assert(numIns==NUM_INSN_MT_PREAMBLE);
878                 }
879                 // if numIns!=NUM_INSN_MT_PREAMBLE then we should update the
880                 // space reserved for generateMTpreamble in the base-tramp
881                 // template file (tramp-power.S) - naim
882                 temp += NUM_INSN_MT_PREAMBLE;
883             }
884 #endif
885             currAddr += setBRL(temp, 10, 0, NOOPraw); //Basically `nop'
886
887             temp--;                                   //`for' loop compensate
888             currAddr -= sizeof(instruction);          //`for' loop compensate
889         }
890     }
891     // TODO cast
892     proc->writeDataSpace((caddr_t)baseAddr, baseTemplate.size, (caddr_t) code);
893
894     free(code);
895
896     if (isReinstall) return NULL;
897
898     trampTemplate *baseInst = new trampTemplate;
899     *baseInst = baseTemplate;
900     baseInst->baseAddr = baseAddr;
901     return baseInst;
902 }
903
904 void generateNoOp(process *proc, int addr)
905 {
906     instruction insn;
907
908     /* fill with no-op */
909     /* ori 0,0,0 */
910     insn.raw = 0;
911     insn.dform.op = ORILop;
912
913     proc->writeTextWord((caddr_t)addr, insn.raw);
914 }
915
916
917
918      //////////////////////////////////////////////////////////////////////////
919      //Returns `true' if a correct base trampoline exists; `false' otherwise
920      //
921 bool baseTrampExists(process  *p,         //Process to check into
922                      unsigned  baseAddr)  //Address at which to start checking
923 {
924   if ((! p) || (! baseAddr)) return false;
925
926   int data = ptrace(PT_READ_I, p->getPid(), (int *)baseAddr, 0, 0);
927   if ((data == 0) || (data == -1))        //Bad instruction or ptrace error
928     return false;
929   else
930     return true;
931 }
932
933      //////////////////////////////////////////////////////////////////////////
934      //Given a process and a vector of instPoint's, reinstall all the 
935      //  base trampolines that have been damaged by an AIX load.
936      //
937 void findAndReinstallBaseTramps(process                  *p,
938                                 vector<const instPoint*> &allInstPoints)
939 {
940   if (! p) return;
941
942   for (unsigned u = 0; u < allInstPoints.size(); u++) {
943     const instPoint *ip = allInstPoints[u];
944     trampTemplate   *bt = p->baseMap[ip];                       //Base tramp
945     if (baseTrampExists(p, bt->baseAddr)) continue;
946
947     if ((ip->ipLoc == ipFuncEntry) || (ip->ipLoc == ipFuncReturn)) {
948       instPoint     *rp = ip->iPgetFunction()->funcExits(p)[0]; //Return point
949       trampTemplate *rt = p->baseMap[rp];                       //Return tramp
950       installBaseTramp(rp, p, 0, rt->baseAddr);
951       rt->updateTrampCost(p, 0);
952
953       instPoint     *ep = ip->iPgetFunction()->funcEntry(p);    //Entry point
954       trampTemplate *et = p->baseMap[ep];                       //Entry tramp
955       installBaseTramp(ep, p, rt->baseAddr, et->baseAddr);
956       et->updateTrampCost(p, 0);
957       generateBranch(p, ep->iPgetAddress(), et->baseAddr);
958     }
959     else {
960       installBaseTramp(ip, p, 0, bt->baseAddr);
961       bt->updateTrampCost(p, 0);
962       generateBranch(p, ip->iPgetAddress(), bt->baseAddr);
963     }
964   }
965 }
966
967
968
969 trampTemplate *findAndInstallBaseTramp(process *proc, 
970                                        instPoint *&location,
971                                        returnInstance *&retInstance,
972                                        bool) // last bool is noCost
973 {
974     trampTemplate *ret;
975     process *globalProc;
976     retInstance = NULL;
977
978     globalProc = proc;
979     if (!globalProc->baseMap.defines(location)) {      
980         if((location->ipLoc == ipFuncEntry) ||
981            (location->ipLoc == ipFuncReturn)) {
982           instPoint*     newLoc;
983           trampTemplate* exTramp;
984           instruction    code[5];
985           
986           newLoc = location->func->funcExits(globalProc)[0];
987           exTramp = installBaseTramp(newLoc, globalProc);
988           globalProc->baseMap[newLoc] = exTramp;
989
990           newLoc = location->func->funcEntry(globalProc);
991           assert(newLoc->ipLoc == ipFuncEntry);
992           assert(exTramp->baseAddr != 0);
993           ret = installBaseTramp(newLoc, globalProc, exTramp->baseAddr);
994
995           instruction *insn = new instruction;
996           generateBranchInsn(insn, ret->baseAddr - newLoc->addr);
997           globalProc->baseMap[newLoc] = ret;
998           retInstance = new returnInstance((instruction *)insn, 
999                                            sizeof(instruction), newLoc->addr,
1000                                            sizeof(instruction));
1001           
1002           if(location->ipLoc == ipFuncReturn) {
1003             ret = exTramp;
1004           }
1005         } else {
1006           ret = installBaseTramp(location, globalProc);
1007           instruction *insn = new instruction;
1008           generateBranchInsn(insn, ret->baseAddr - location->addr);
1009           globalProc->baseMap[location] = ret;
1010           retInstance = new returnInstance((instruction *)insn, 
1011                                            sizeof(instruction), location->addr,
1012                                            sizeof(instruction));
1013         }
1014     } else {
1015         ret = globalProc->baseMap[location];
1016     }
1017       
1018     return(ret);
1019 }
1020
1021
1022      //////////////////////////////////////////////////////////////////////////
1023      //Given a process and a vector of instInstance's, reconstruct branches 
1024      //  from base trampolines to their mini trampolines
1025      //
1026 void reattachMiniTramps(process               *p,
1027                         vector<instInstance*> &allInstInstances)
1028 {
1029   if (! p) return;
1030
1031   for (unsigned u = 0; u < allInstInstances.size(); u++) {
1032     instInstance *ii = allInstInstances[u];
1033     if (ii->prevAtPoint) continue;              //Not first at inst point
1034
1035     trampTemplate *bt       = ii->baseInstance; //Base trampoline
1036     unsigned       skipAddr = bt->baseAddr;
1037     if (ii->when == callPreInsn)
1038       skipAddr += bt->skipPreInsOffset;
1039     else
1040       skipAddr += bt->skipPostInsOffset;
1041     generateNoOp(p, skipAddr);                  //Clear "skip" branch
1042                                                 //Restore branch from base tramp
1043     extern int getBaseBranchAddr(process *, instInstance *);
1044     resetBRL(p, getBaseBranchAddr(p, ii), ii->trampBase);
1045   }
1046 }
1047
1048
1049
1050 /*
1051  * Install a single tramp.
1052  *
1053  */
1054 void installTramp(instInstance *inst, char *code, int codeSize) 
1055 {
1056     totalMiniTramps++;
1057     insnGenerated += codeSize/sizeof(int);
1058     
1059     // TODO cast
1060     (inst->proc)->writeDataSpace((caddr_t)inst->trampBase, codeSize, code);
1061
1062     unsigned atAddr;
1063     if (inst->when == callPreInsn) {
1064         if (inst->baseInstance->prevInstru == false) {
1065             atAddr = inst->baseInstance->baseAddr+baseTemplate.skipPreInsOffset;
1066             inst->baseInstance->cost += inst->baseInstance->prevBaseCost;
1067             inst->baseInstance->prevInstru = true;
1068             generateNoOp(inst->proc, atAddr);
1069         }
1070     }
1071     else {
1072         if (inst->baseInstance->postInstru == false) {
1073             atAddr = inst->baseInstance->baseAddr+baseTemplate.skipPostInsOffset; 
1074             inst->baseInstance->cost += inst->baseInstance->postBaseCost;
1075             inst->baseInstance->postInstru = true;
1076             generateNoOp(inst->proc, atAddr);
1077         }
1078     }
1079 }
1080
1081 /*
1082  * change the insn at addr to be a branch to newAddr.
1083  *   Used to add multiple tramps to a point.
1084  */
1085 void generateBranch(process *proc, unsigned fromAddr, unsigned newAddr)
1086 {
1087     int disp;
1088     instruction insn;
1089
1090     disp = newAddr-fromAddr;
1091     generateBranchInsn(&insn, disp);
1092
1093     // TODO cast
1094     proc->writeTextWord((caddr_t)fromAddr, insn.raw);
1095 }
1096
1097 int callsTrackedFuncP(instPoint *point)
1098 {
1099     if (point->callIndirect) {
1100 #ifdef notdef
1101         // TODO this won't compile now
1102         // it's rare to call a library function as a parameter.
1103         sprintf(errorLine, "*** Warning call indirect\n from %s %s (addr %d)\n",
1104             point->func->file->fullName, point->func->prettyName, point->addr);
1105         logLine(errorLine);
1106 #endif
1107         return(true);
1108     } else {
1109         if (point->callee && !(point->callee->isLibTag())) {
1110             return(true);
1111         } else {
1112             return(false);
1113         }
1114     }
1115 }
1116
1117 /*
1118  * return the function asociated with a point.
1119  *
1120  *     If the point is a funcation call, and we know the function being called,
1121  *          then we use that.  Otherwise it is the function that contains the
1122  *          point.
1123  *  
1124  *   This is done to return a better idea of which function we are using.
1125  */
1126 pd_Function *getFunction(instPoint *point)
1127 {
1128     return(point->callee ? point->callee : point->func);
1129 }
1130
1131
1132 unsigned emitImm(opCode op, reg src1, reg src2, reg dest, char *i, 
1133                  unsigned &base, bool noCost)
1134 {
1135         instruction *insn = (instruction *) ((void*)&i[base]);
1136         int iop=-1;
1137         int result;
1138         switch (op) {
1139             // integer ops
1140             case plusOp:
1141                 iop = CALop;
1142                 genImmInsn(insn, iop, dest, src1, src2);
1143                 base += sizeof(instruction);
1144                 return(0);
1145                 break;
1146
1147             case minusOp:
1148                 iop = SIop;
1149                 genImmInsn(insn, iop, dest, src1, src2);
1150                 base += sizeof(instruction);
1151                 return(0);
1152                 break;
1153
1154             case timesOp:
1155                if (isPowerOf2(src2,result) && (result<32)) {
1156                   generateLShift(insn, src1, result, dest);           
1157                   base += sizeof(instruction);
1158                   return(0);
1159                 }
1160                 else {
1161                   reg dest2 = regSpace->allocateRegister(i, base, noCost);
1162                   (void) emit(loadConstOp, src2, dest2, dest2, i, base, noCost);
1163                   (void) emit(op, src1, dest2, dest, i, base, noCost);
1164                   regSpace->freeRegister(dest2);
1165                   return(0);
1166                 }
1167                 break;
1168
1169             case divOp:
1170                 if (isPowerOf2(src2,result) && (result<32)) {
1171                   generateRShift(insn, src1, result, dest);           
1172                   base += sizeof(instruction);
1173                   return(0);
1174                 }
1175                 else {
1176                   reg dest2 = regSpace->allocateRegister(i, base, noCost);
1177                   (void) emit(loadConstOp, src2, dest2, dest2, i, base, noCost);
1178                   (void) emit(op, src1, dest2, dest, i, base, noCost);
1179                   regSpace->freeRegister(dest2);
1180                   return(0);
1181                 }
1182                 break;
1183
1184             // Bool ops
1185             case orOp:
1186                 iop = ORILop;
1187                 // For some reason, the destField is 2nd for ORILop and ANDILop
1188                 genImmInsn(insn, iop, src1, dest, src2);
1189                 base += sizeof(instruction);
1190                 return(0);
1191                 break;
1192
1193             case andOp:
1194                 iop = ANDILop;
1195                 // For some reason, the destField is 2nd for ORILop and ANDILop
1196                 genImmInsn(insn, iop, src1, dest, src2);
1197                 base += sizeof(instruction);
1198                 return(0);
1199                 break;
1200
1201             default:
1202                 reg dest2 = regSpace->allocateRegister(i, base, noCost);
1203                 (void) emit(loadConstOp, src2, dest2, dest2, i, base, noCost);
1204                 (void) emit(op, src1, dest2, dest, i, base, noCost);
1205                 regSpace->freeRegister(dest2);
1206                 return(0);
1207                 break;
1208         }
1209 }
1210
1211
1212 //static int dummy[3];
1213 //
1214 //void
1215 //initTocOffset(int toc_offset) {
1216 //    //  st r2,20(r1)  ; 0x90410014 save toc register  
1217 //    dummy[0] = 0x90410014; 
1218 //
1219 //    //  liu r2, 0x0000     ;0x3c40abcd reset the toc value to 0xabcdefgh
1220 //    dummy[1] = (0x3c400000 | (toc_offset >> 16));
1221 //
1222 //    //  oril    r2, r2,0x0000   ;0x6042efgh
1223 //    dummy[2] = (0x60420000 | (toc_offset & 0x0000ffff));
1224 //}
1225
1226
1227 void cleanUpAndExit(int status);
1228
1229 //
1230 // Author: Jeff Hollingsworth (3/26/96)
1231 //
1232 // Emit a function call.
1233 //   It saves registers as needed.
1234 //   copy the passed arguments into the canonical argument registers (r3-r10)
1235 //   generate a branch and link the the destiation
1236 //   restore the saved registers.
1237 //
1238 // Parameters:
1239 //   op - unused parameter (to be compatible with sparc)
1240 //   srcs - vector of ints indicating the registers that contain the parameters
1241 //   dest - the destination address (should be unsigned not reg). 
1242 //   insn - pointer to the code we are generating
1243 //   based - offset into the code generated.
1244 //
1245
1246 unsigned emitFuncCall(opCode /* ocode */, 
1247                       registerSpace *rs,
1248                       char *iPtr, unsigned &base, 
1249                       const vector<AstNode *> &operands, 
1250                       const string &callee, process *proc, bool noCost)
1251 {
1252   unsigned dest;
1253   bool err;
1254   vector <reg> srcs;
1255   int i;
1256   unsigned ui;
1257   
1258   dest = proc->findInternalAddress(callee, false, err);
1259   if (err) {
1260     function_base *func = proc->findOneFunction(callee);
1261     if (!func) {
1262       ostrstream os(errorLine, 1024, ios::out);
1263       os << "Internal error: unable to find addr of " << callee << endl;
1264       logLine(errorLine);
1265       showErrorCallback(80, (const char *) errorLine);
1266       P_abort();
1267     }
1268     dest = func->getAddress(0);
1269   }
1270         
1271   // If this code tries to save registers, it might save them in the
1272   // wrong area; there was a conflict with where the base trampoline saved
1273   // registers and the function, so now the function is saving the registers
1274   // above the location where the base trampoline did
1275   for (unsigned u = 0; u < operands.size(); u++) {
1276     srcs += operands[u]->generateCode(proc, rs, iPtr, base, false);
1277   }
1278   
1279   // TODO cast
1280   instruction *insn = (instruction *) ((void*)&iPtr[base]);
1281   vector<int> savedRegs;
1282   
1283   //     Save the link register.
1284   // mflr r0
1285   insn->raw = MFLR0raw;
1286   insn++;
1287   base += sizeof(instruction);
1288   
1289   // st r0, (r1)
1290   saveRegister(insn,base,0,8+(46*4));
1291   savedRegs += 0;
1292   
1293 #if defined(SHM_SAMPLING) && defined(MT_THREAD)
1294   // save REG_MT
1295   saveRegister(insn,base,REG_MT,8+(46*4));
1296   savedRegs += REG_MT;
1297 #endif
1298   
1299   // see what others we need to save.
1300   for (i = 0; i < regSpace->getRegisterCount(); i++) {
1301     registerSlot *reg = regSpace->getRegSlot(i);
1302     if (reg->needsSaving) {
1303       // needsSaving -> caller saves register
1304       // we MUST save restore this and the end of the function call
1305       //     rather than delay it to the end of the tramp due to:
1306       //        (1) we could be in a conditional & the restores would
1307       //            be unconditional (i.e. restore bad data)
1308       //        (2) $arg[n] code depends on paramters being in registers
1309       //
1310       // MT_AIX: we are not saving registers on demand on the power
1311       // architecture anymore - naim
1312       // saveRegister(insn,base,reg->number,8+(46*4));
1313       // savedRegs += reg->number;
1314     } else if (reg->inUse && !reg->mustRestore) {
1315       // inUse && !mustRestore -> in use scratch register 
1316       //                (i.e. part of an expression being evaluated).
1317
1318       // no reason to save the register if we are going to free it in a bit
1319       // we should keep it free, otherwise we might overwrite the register
1320       // we allocate for the return value -- we can't request that register
1321       // before, since we then might run out of registers
1322       unsigned u;
1323       for(u=0; u < srcs.size(); u++) {
1324         if(reg->number == srcs[u]) break;
1325       }
1326       // since the register should be free
1327       // assert((u == srcs.size()) || (srcs[u] != (int) (u+3)));
1328       if(u == srcs.size()) {
1329         saveRegister(insn,base,reg->number,8+(46*4));
1330         savedRegs += reg->number;
1331       }
1332     } else if (reg->inUse) {
1333       // only inuse registers permitted here are the parameters.
1334       unsigned u;
1335       for (u=0; u<srcs.size(); u++){
1336         if (reg->number == srcs[u]) break;
1337       }
1338       if (u == srcs.size()) {
1339         // XXXX - caller saves register that is in use.  We have no
1340         //    place to save this, but we must save it!!!.  Should
1341         //    find a place to push this on the stack - jkh 7/31/95
1342         string msg = "Too many registers required for MDL expression\n";
1343         fprintf(stderr, msg.string_of());
1344         showErrorCallback(94,msg);
1345         cleanUpAndExit(-1);
1346       }
1347     }
1348   }
1349   
1350   
1351   if(srcs.size() > 8) {
1352     // This is not necessarily true; more then 8 arguments could be passed,
1353     // the first 8 need to be in registers while the others need to be on
1354     // the stack, -- sec 3/1/97
1355     string msg = "Too many arguments to function call in instrumentation code: only 8 arguments can be passed on the power architecture.\n";
1356     fprintf(stderr, msg.string_of());
1357     showErrorCallback(94,msg);
1358     cleanUpAndExit(-1);
1359   }
1360   
1361   // Now load the parameters into registers.
1362   for (unsigned u=0; u<srcs.size(); u++){
1363     // check that is is not already in the register
1364     if (srcs[u] == (int) u+3) {
1365       regSpace->freeRegister(srcs[u]);
1366       continue;
1367     }
1368
1369     assert(regSpace->isFreeRegister(u+3));
1370
1371     // internal error we expect this register to be free here
1372     // if (!regSpace->isFreeRegister(u+3)) abort();
1373     
1374     genImmInsn(insn, ORILop, srcs[u], u+3, 0);
1375     insn++;
1376     base += sizeof(instruction);
1377     
1378     // source register is now free.
1379     regSpace->freeRegister(srcs[u]);
1380   }
1381   
1382   // 
1383   // Update the stack pointer
1384   //   argarea  =  8 words  (8 registers)
1385   //   linkarea =  6 words  (6 registers)
1386   //   nfuncrs  =  32 words (area we use when saving the registers above 
1387   //                         ngprs at the beginning of this function call; 
1388   //                         this area saves the registers already being
1389   //                         used in the mini trampoline, registers which
1390   //                         need to be accessed after this function call;
1391   //                         this area is used in emitFuncCall--not all the
1392   //                         registers are being saved, only the necessary
1393   //                         ones)
1394   //   nfprs    =  14 words (area we use to save the floatpoing registers,
1395   //                         not all the fprs, only the volatile ones 0-13)
1396   //   ngprs    =  32 words (area we use when saving the registers above the
1397   //                         stack pointer, at the beginning of the base
1398   //                         trampoline--not all the gprs are saved, only the
1399   //   ???      =  2  words  (two extra word was added on for extra space, 
1400   //                          and to make sure the floatpings are aligned)
1401   // OLD STACK POINTER
1402   //   szdsa    =  4*(argarea+linkarea+nfuncrs+nfprs+ngprs) = 368 + 8 = 376
1403
1404   //  Decrement stack ptr
1405   genImmInsn(insn, STUop, 1, 1, -376);
1406   insn++;
1407   base += sizeof(instruction);
1408     
1409   // save and reset the value of TOC 
1410   vector<int> toc_info = proc->getTOCoffsetInfo();
1411   assert(toc_info.size()==3);
1412   insn->raw = toc_info[0]; insn++; base += sizeof(instruction);
1413   insn->raw = toc_info[1]; insn++; base += sizeof(instruction);
1414   insn->raw = toc_info[2]; insn++; base += sizeof(instruction);
1415   // 0x90410014 0x3c402000 0x6042fd7c 
1416   // cout << "Dummy" << dummy[0] << "\t" << dummy[1]<< "\t" << dummy[2]<<endl;
1417
1418   // generate a to the subroutine to be called.
1419   // load r0 with address, then move to link reg and branch and link.
1420   
1421   // really addis 0,dest,HIGH(dest) aka lis dest, HIGH(dest)
1422   genImmInsn(insn, CAUop, 0, 0, HIGH(dest));
1423   insn++;
1424   base += sizeof(instruction);
1425   
1426   // ori dest,dest,LOW(src1)
1427   genImmInsn(insn, ORILop, 0, 0, LOW(dest));
1428   insn++;
1429   base += sizeof(instruction);
1430   
1431   // mtlr       0 (aka mtspr 8, rs) = 0x7c0803a6
1432   insn->raw = MTLR0raw;
1433   insn++;
1434   base += sizeof(instruction);
1435   
1436   // brl - branch and link through the link reg.
1437   insn->raw = BRLraw;
1438   insn++;
1439   base += sizeof(instruction);
1440   
1441   // should their be a nop of some sort here?, sec
1442   // insn->raw = 0x4ffffb82;  // nop
1443   // insn++;
1444   // base += sizeof(instruction);
1445   
1446   // now cleanup.
1447   genImmInsn(insn, CALop, 1, 1, 376);
1448   insn++;
1449   base += sizeof(instruction);
1450   
1451   // sec
1452   //  // restore TOC
1453   //  genImmInsn(insn, Lop, 2, 1, 20);
1454   //  insn++;
1455   //  base += sizeof(instruction);
1456
1457   // get a register to keep the return value in.
1458   reg retReg = regSpace->allocateRegister(iPtr, base, noCost);
1459   // This next line is a hack! - jkh 6/27/96
1460   // It is required since allocateRegister can generate code.
1461   insn = (instruction *) ((void*)&iPtr[base]);
1462
1463   // put the return value from register 3 to the newly allocated register.
1464   genImmInsn(insn, ORILop, 3, retReg, 0);
1465   insn++;
1466   base += sizeof(instruction);
1467   
1468   // restore saved registers.
1469   for (ui = 0; ui < savedRegs.size(); ui++) {
1470     restoreRegister(insn,base,savedRegs[ui],8+(46*4));
1471   }
1472   
1473   // mtlr       0 (aka mtspr 8, rs) = 0x7c0803a6
1474   insn->raw = MTLR0raw;
1475   insn++;
1476   base += sizeof(instruction);
1477   
1478   // return value is the register with the return value from the
1479   //   called function.
1480   return(retReg);
1481 }
1482
1483  
1484 unsigned emit(opCode op, reg src1, reg src2, reg dest, char *baseInsn, 
1485               unsigned &base, bool noCost)
1486 {
1487     // TODO cast
1488     instruction *insn = (instruction *) ((void*)&baseInsn[base]);
1489
1490     if (op == loadConstOp) {
1491         if (ABS(src1) > MAX_IMM) {
1492             // really addis dest,0,HIGH(src1) aka lis dest, HIGH(src1)
1493             genImmInsn(insn, CAUop, dest, 0, HIGH(src1));
1494             insn++;
1495
1496             // ori dest,dest,LOW(src1)
1497             genImmInsn(insn, ORILop, dest, dest, LOW(src1));
1498             base += 2 * sizeof(instruction);
1499         } else {
1500             // really add regd,0,imm
1501             genImmInsn(insn, CALop, dest, 0, src1);
1502             base += sizeof(instruction);
1503         }
1504     } else if (op ==  loadOp) {
1505         int high;
1506
1507         // load high half word of address into dest.
1508         // really addis 0,dest,HIGH(src1) aka lis dest, HIGH(src1)
1509         if (LOW(src1) & 0x8000) {
1510             // high bit of low is set so the sign extension of the load
1511             // will cause the wrong effective addr to be computed.
1512             // so we subtract the sign ext value from HIGH.
1513             // sounds odd, but works and saves an instruction - jkh 5/25/95
1514             high = HIGH(src1) - 0xffff;
1515         } else {
1516             high = HIGH(src1);
1517         }
1518         genImmInsn(insn, CAUop, dest, 0, high);
1519         insn++;
1520
1521         // really load dest, (dest)imm
1522         genImmInsn(insn, Lop, dest, dest, LOW(src1));
1523
1524         base += sizeof(instruction)*2;
1525
1526     } else if (op == loadIndirOp) {
1527         // really load dest, (dest)imm
1528         genImmInsn(insn, Lop, dest, src1, 0);
1529
1530         base += sizeof(instruction);
1531
1532     } else if (op ==  storeOp) {
1533         int high;
1534
1535         // load high half word of address into dest.
1536         // really addis 0,dest,HIGH(src1) aka lis dest, HIGH(src1)
1537         if (LOW(dest) & 0x8000) {
1538             // high bit of low is set so the sign extension of the load
1539             // will cause the wrong effective addr to be computed.
1540             // so we subtract the sign ext value from HIGH.
1541             // sounds odd, but works and saves an instruction - jkh 5/25/95
1542             high = HIGH(dest) - 0xffff;
1543         } else {
1544             high = HIGH(dest);
1545         }
1546
1547         // temp register to hold base address for store (added 6/26/96 jkh)
1548         reg temp = regSpace->allocateRegister(baseInsn, base, noCost);
1549
1550         // This next line is a hack! - jkh 6/27/96
1551         //   It is required since allocateRegister can generate code.
1552         insn = (instruction *) ((void*)&baseInsn[base]);
1553
1554         // set upper 16 bits of  temp to be the top high.
1555         genImmInsn(insn, CAUop, temp, 0, high);
1556         base += sizeof(instruction);
1557         insn++;
1558
1559         // low == LOW(dest)
1560         // generate -- st src1, low(temp)
1561         insn->dform.op = STop;
1562         insn->dform.rt = src1;
1563         insn->dform.ra = temp;
1564         insn->dform.d_or_si = LOW(dest);
1565         base += sizeof(instruction);
1566         insn++;
1567
1568         regSpace->freeRegister(temp);
1569
1570     } else if (op ==  storeIndirOp) {
1571
1572         // generate -- st src1, dest
1573         insn->dform.op = STop;
1574         insn->dform.rt = src1;
1575         insn->dform.ra = dest;
1576         insn->dform.d_or_si = 0;
1577         base += sizeof(instruction);
1578
1579     } else if (op ==  ifOp) {
1580         // cmpi 0,0,src1,0
1581         insn->raw = 0;
1582         insn->dform.op = CMPIop;
1583         insn->dform.ra = src1;
1584         insn->dform.d_or_si = 0;
1585         insn++;
1586
1587         // be 0, dest
1588         insn->bform.op = BCop;
1589         insn->bform.bo = BTRUEcond;
1590         insn->bform.bi = EQcond;
1591         insn->bform.bd = dest/4;
1592         insn->bform.aa = 0;
1593         insn->bform.lk = 0;
1594         insn++;
1595
1596         generateNOOP(insn);
1597         base += sizeof(instruction)*3;
1598         return(base - 2*sizeof(instruction));
1599
1600      } else if (op == branchOp) {
1601         generateBranchInsn(insn, dest);
1602         insn++;
1603
1604         generateNOOP(insn);
1605         base += sizeof(instruction)*2;
1606         return(base - 2*sizeof(instruction));
1607
1608      } else if (op == updateCostOp) {
1609         if (!noCost) {
1610
1611            regSpace->resetSpace();
1612
1613            // add in the cost to the passed pointer variable.
1614
1615            // high order bits of the address of the cummlative cost.
1616            reg obsCostAddr = regSpace->allocateRegister(baseInsn, base, noCost);
1617
1618            // actual cost.
1619            reg obsCostValue = regSpace->allocateRegister(baseInsn, base, noCost);
1620
1621            // This next line is a hack! - jkh 6/27/96
1622            //   It is required since allocateRegister can generate code.
1623            insn = (instruction *) ((void*)&baseInsn[base]);
1624
1625            int high;
1626
1627            // load high half word of address into dest.
1628            // really addis 0,dest,HIGH(dest) aka lis dest, HIGH(dest)
1629            if (LOW(dest) & 0x8000) {
1630               // high bit of low is set so the sign extension of the load
1631               // will cause the wrong effective addr to be computed.
1632               // so we subtract the sign ext value from HIGH.
1633               // sounds odd, but works and saves an instruction - jkh 5/25/95
1634               high = HIGH(dest) - 0xffff;
1635            } else {
1636               high = HIGH(dest);
1637            }
1638            genImmInsn(insn, CAUop, obsCostAddr, 0, high);
1639            insn++;
1640
1641            // really load obsCostValue, (obsCostAddr)imm
1642            genImmInsn(insn, Lop, obsCostValue, obsCostAddr, LOW(dest));
1643            insn++;
1644
1645            base += 2 * sizeof(instruction);
1646
1647            //assert(src1 <= MAX_IMM);
1648            if (src1 <= MAX_IMM) {
1649              genImmInsn(insn, CALop, obsCostValue, obsCostValue, LOW(src1));
1650              insn++;
1651              base += sizeof(instruction);
1652            } else {
1653              // If src1>MAX_IMM, we can't generate an instruction using an
1654              // an immediate operator. Therefore, we need to load the 
1655              // value first, which will cost 2 instructions - naim
1656              reg reg = regSpace->allocateRegister(baseInsn, base, noCost);
1657              genImmInsn(insn, CAUop, reg, 0, HIGH(src1));
1658              insn++;
1659              genImmInsn(insn, ORILop, reg, reg, LOW(src1));
1660              insn++;
1661              base += 2 * sizeof(instruction);
1662              (void) emit(plusOp, reg, obsCostValue, obsCostValue, baseInsn, 
1663                          base, noCost);        
1664              regSpace->freeRegister(reg);     
1665              insn++;
1666            }
1667
1668            // now store it back.
1669            // low == LOW(dest)
1670            // generate -- st obsCostValue, obsCostAddr+low(dest)
1671            insn->dform.op = STop;
1672            insn->dform.rt = obsCostValue;
1673            insn->dform.ra = obsCostAddr;
1674            insn->dform.d_or_si = LOW(dest);
1675            insn++;
1676            base += sizeof(instruction);
1677
1678            regSpace->freeRegister(obsCostValue);
1679            regSpace->freeRegister(obsCostAddr);
1680        } // if !noCost
1681     } else if (op ==  trampPreamble) {
1682         // nothing to do in this platform
1683         
1684     } else if (op ==  trampTrailer) {
1685 /*
1686         // restore the registers we have saved
1687         int i;
1688         for (i = 0; i < regSpace->getRegisterCount(); i++) {
1689             registerSlot *reg = regSpace->getRegSlot(i);
1690             if (reg->mustRestore) {
1691                 // cleanup register space for next trampoline.
1692                 reg->needsSaving = true;
1693                 reg->mustRestore = false;
1694                 // actually restore the register.
1695                 restoreRegister(insn,base,reg->number,8);
1696             }
1697         }
1698 */
1699         generateBranchInsn(insn, dest);
1700         insn++;
1701         base += sizeof(instruction);
1702
1703         generateNOOP(insn);
1704         insn++;
1705         base += sizeof(instruction);
1706
1707         // return the relative address of the return statement.
1708         return(base - 2*sizeof(instruction));
1709     } else if (op == noOp) {
1710         generateNOOP(insn);
1711         base += sizeof(instruction);
1712     } else if (op == getRetValOp) {
1713         // return value is in register 3
1714         int i;
1715         int reg = 3;
1716         registerSlot *regSlot;
1717
1718         // find the registerSlot for this register.
1719         for (i = 0; i < regSpace->getRegisterCount(); i++) {
1720             regSlot = regSpace->getRegSlot(i);
1721             if (regSlot->number == reg) {
1722                 break;
1723             }
1724         }
1725
1726         if (regSlot->mustRestore) {
1727           // its on the stack so load it.
1728           restoreRegister(insn, base, reg, dest, 8);
1729           return(dest);
1730         } else {
1731             // its still in a register so return the register it is in.
1732             return(reg);
1733         }
1734     } else if (op == getParamOp) {
1735       // the first 8 parameters (0-7) are stored in registers (r3-r10) upon entering
1736       // the function and then saved above the stack upon entering the trampoline;
1737       // in emit functional call the stack pointer is moved so the saved registers
1738       // are not over-written
1739       // the other parameters > 8 are stored on the caller's stack at an offset.
1740       // 
1741       // src1 is the argument number 0..X, the first 8 are stored in registers
1742       // r3 and 
1743       if(src1 < 8) {
1744         restoreRegister(insn, base, src1+3, dest, 8);
1745         return(dest);
1746       } else {
1747         genImmInsn(insn, Lop, dest, 1, (src1+6)*4);
1748         insn++; 
1749         base += sizeof(instruction);
1750         return(dest);
1751       }
1752     } else if (op == saveRegOp) {
1753         saveRegister(insn,base,src1,8);
1754     } else {
1755         int instXop=-1;
1756         int instOp=-1;
1757         switch (op) {
1758             // integer ops
1759             case plusOp:
1760                 instOp = CAXop;
1761                 instXop = CAXxop;
1762                 break;
1763
1764             case minusOp:
1765                 reg temp;
1766                 // need to flip operands since this computes ra-rb not rb-ra
1767                 temp = src1;
1768                 src1 = src2;
1769                 src2 = temp;
1770                 instOp = SFop;
1771                 instXop = SFxop;
1772                 break;
1773
1774             case timesOp:
1775                 instOp = MULSop;
1776                 instXop = MULSxop;
1777                 break;
1778
1779             case divOp:
1780                 //#if defined(_POWER_PC)
1781                 // xop = DIVWxop; // PowerPC 32 bit divide instruction
1782                 //#else 
1783                 instOp = DIVSop;   // Power divide instruction
1784                 instXop = DIVSxop;
1785                 break;
1786
1787             // Bool ops
1788             case orOp:
1789                 //genSimpleInsn(insn, ORop, src1, src2, dest, base);
1790                 insn->raw = 0;
1791                 insn->xoform.op = ORop;
1792                 // operation is ra <- rs | rb (or rs,ra,rb)
1793                 insn->xoform.ra = dest;
1794                 insn->xoform.rt = src1;
1795                 insn->xoform.rb = src2;
1796                 insn->xoform.xo = ORxop;
1797                 base += sizeof(instruction);
1798                 return(0);
1799                 break;
1800
1801             case andOp:
1802                 //genSimpleInsn(insn, ANDop, src1, src2, dest, base);
1803                 // This is a Boolean and with true == 1 so bitwise is OK
1804                 insn->raw = 0;
1805                 insn->xoform.op = ANDop;
1806                 // operation is ra <- rs & rb (and rs,ra,rb)
1807                 insn->xoform.ra = dest;
1808                 insn->xoform.rt = src1;
1809                 insn->xoform.rb = src2;
1810                 insn->xoform.xo = ANDxop;
1811                 base += sizeof(instruction);
1812                 return(0);
1813                 break;
1814
1815             // rel ops
1816             case eqOp:
1817                 genRelOp(insn, EQcond, BTRUEcond, src1, src2, dest, base);
1818                 return(0);
1819                 break;
1820
1821             case neOp:
1822                 genRelOp(insn, EQcond, BFALSEcond, src1, src2, dest, base);
1823                 return(0);
1824                 break;
1825
1826             case lessOp:
1827                 genRelOp(insn, LTcond, BTRUEcond, src1, src2, dest, base);
1828                 return(0);
1829                 break;
1830
1831             case greaterOp:
1832                 genRelOp(insn, GTcond, BTRUEcond, src1, src2, dest, base);
1833                 return(0);
1834                 break;
1835
1836             case leOp:
1837                 genRelOp(insn, GTcond, BFALSEcond, src1, src2, dest, base);
1838                 return(0);
1839                 break;
1840
1841             case geOp:
1842                 genRelOp(insn, LTcond, BFALSEcond, src1, src2, dest, base);
1843                 return(0);
1844                 break;
1845
1846             default:
1847                 // internal error, invalid op.
1848                 fprintf(stderr, "Invalid op passed to emit, instOp = %d\n", 
1849                         instOp);
1850                 assert(0 && "Invalid op passed to emit");
1851                 abort();
1852                 break;
1853         }
1854         assert((instOp != -1) && (instXop != -1));
1855         insn->raw = 0;
1856         insn->xoform.op = instOp;
1857         insn->xoform.rt = dest;
1858         insn->xoform.ra = src1;
1859         insn->xoform.rb = src2;
1860         insn->xoform.xo = instXop;
1861
1862         base += sizeof(instruction);
1863       }
1864       return(0);
1865     }
1866
1867 //
1868 // I don't know how to compute cycles for POWER instructions due to 
1869 //   multiple functional units.  However, we can computer the number of
1870 //   instructions and hope that is fairly close. - jkh 1/30/96
1871 //
1872 int getInsnCost(opCode op)
1873   {
1874     int cost = 0;
1875
1876     /* XXX Need to add branchOp */
1877     if (op == loadConstOp) {
1878         // worse case is addi followed by ori
1879         cost = 2;
1880     } else if (op ==  loadOp) {
1881         // addis
1882         // l 
1883         cost = 2;
1884     } else if (op ==  loadIndirOp) {
1885         cost = 1;
1886     } else if (op ==  storeOp) {
1887         cost = 2;
1888     } else if (op ==  storeIndirOp) {
1889         cost = 2;
1890     } else if (op ==  ifOp) {
1891         // cmpi 0,0,src1,0
1892         // be 0, dest
1893         // nop
1894         cost = 3;
1895     } else if (op ==  callOp) {
1896         // mflr r0
1897         // st r0, (r1)
1898         cost += 2;
1899
1900         // Should compute the cost to save registers here.  However, we lack 
1901         //   sufficient information to compute this value. We need to be 
1902         //   inside the code generator to know this amount.
1903         //
1904         // We know it is at *least* every live register (i.e. parameter reg)
1905         cost += sizeof(liveRegList)/sizeof(int);
1906
1907         // clr r5
1908         // clr r6
1909         // decrement stack pointer -- STUop
1910         // load r0 with address, then move to link reg and branch and link.
1911         // ori dest,dest,LOW(src1)
1912         // mtlr 0 (aka mtspr 8, rs) = 0x7c0803a6
1913         // brl - branch and link through the link reg.
1914         cost += 7;
1915         
1916         // now cleanup.
1917
1918         // increment stack pointer -- CALop
1919         // restore the saved register 0.
1920         cost += 2;
1921
1922         // Should compute the cost to restore registers here.  However, we lack 
1923         //   sufficient information to compute this value. We need to be 
1924         //   inside the code generator to know this amount.
1925         //
1926         // We know it is at *least* every live register (i.e. parameter reg)
1927         cost += sizeof(liveRegList)/sizeof(int);
1928
1929         // mtlr 0 
1930         cost++;
1931     } else if (op == updateCostOp) {
1932         // In most cases this cost is 4, but if we can't use CALop because
1933         // the value is to large, then we'll need 2 additional operations to
1934         // load that value - naim
1935         cost += 4;
1936
1937     } else if (op ==  trampPreamble) {
1938         // Generate code to update the observed cost.
1939         // generated code moved to the base trampoline.
1940         cost += 0;
1941
1942     } else if (op ==  trampTrailer) {
1943         // Should compute the cost to restore registers here.  However, we lack 
1944         //   sufficient information to compute this value. We need to be 
1945         //   inside the code generator to know this amount.
1946         //
1947
1948         // branch
1949         // nop
1950         cost += 2;
1951     } else if (op == noOp) {
1952         cost = 1;
1953     } else if (op == getParamOp) {
1954         // worse case is it is on the stack and takes one instruction.
1955         cost = 1;
1956     } else if (op == saveRegOp) {
1957         cost = 1;
1958     } else {
1959         switch (op) {
1960             // integer ops
1961             case plusOp:
1962             case minusOp:
1963             case timesOp:
1964             case divOp:
1965                 cost = 1;
1966                 break;
1967
1968             // rel ops
1969             case eqOp:
1970             case neOp:
1971             case lessOp:
1972             case greaterOp:
1973             case leOp:
1974             case geOp:
1975                 cost = 4;
1976                 break;
1977
1978             default:
1979                 cost = 0;
1980                 break;
1981         }
1982       }
1983       return (cost);
1984 }
1985
1986
1987 bool isCallInsn(const instruction i)
1988 {
1989   #define CALLmatch 0x48000001 /* bl */
1990
1991   // Only look for 'bl' instructions for now, although a branch
1992   // could be a call function, and it doesn't need to set the link
1993   // register if it is the last function call
1994   return(isInsnType(i, OPmask | AALKmask, CALLmatch));
1995 }
1996
1997
1998 /* ************************************************************************
1999    --  This function, isReturnInsn, is no longer needed.  -- sec
2000
2001 // Check for a real return instruction.  Unfortunatly, on RS6000 there are
2002 //    several factors that make this difficult:
2003 //
2004 //    br - is the "normal" return instruction
2005 //    b <cleanupRoutine> is sometimes used to restore fp state.
2006 //    bctr - can be used, but it is also the instruction used for jump tables.
2007 //  
2008 //    However, due to the traceback table convention the instruction after 
2009 //    a real return is always all zeros (i.e. the flag for the start of a
2010 //    tracback record).
2011 //    Also, jump tables never seem to have a 0 offset so the sequence:
2012 //              bctr
2013 //              .long 0
2014 //    doesn't ever appear in a case statement.
2015 //
2016 //    We use the following heuristics.  
2017 //        1.) Any br is a return from function
2018 //        2.) bctr or b insn followed by zero insn is a return from a function.
2019 //
2020 // WARNING:  We use the heuristic that any return insns followed by a 0
2021 //   is the last return in the current function.
2022 //
2023 bool isReturnInsn(const image *owner, Address adr)
2024 {
2025   bool        ret;
2026   instruction instr;
2027   instruction nextInstr;
2028
2029 #ifdef ndef
2030   // Currently there is a problem with finding the return insn on AIX,
2031   // which was found once we started using xlc to compile programs
2032   // xlc uses a br branch to branch inside the function, in addition with
2033   // optmize flags, xlc using conditional branch returns; a conditional branch
2034   // which could branch to somewhere inside of the function or leave the
2035   // function we are working on a new way to handle this, but for it has not
2036   // been implemented, tested, etc. as of now, so it is not here.
2037   // if you have any questins, contact sec@cs.wisc.edu
2038
2039   // Finding a return instruction is becomming harder then predicted,
2040   // right now be safe and allow a bctr or br followed by a 
2041   // 0, raw, instruction--won't always work, but will never fail
2042   // this will be fixed soon, being worked on now...  -- sec
2043   instr.raw = owner->get_instruction(adr);
2044   nextInstr.raw = owner->get_instruction(adr+4);
2045   if(isInsnType(instr, FULLmask, BRraw) ||
2046      isInsnType(instr, FULLmask, BCTRraw)) {     // bctr, br, or b
2047     if(nextInstr.raw == 0) {
2048       ret = true;
2049     } else {
2050       ret = false;
2051     }
2052   } else {
2053     ret = false;
2054   }
2055 #else
2056   instr.raw = owner->get_instruction(adr);
2057   nextInstr.raw = owner->get_instruction(adr+4);
2058   
2059   if(isInsnType(instr, FULLmask, BRraw)) {      // br instruction
2060     ret = true;
2061   } else if (isInsnType(instr, FULLmask, BCTRraw) ||
2062              isInsnType(instr, Bmask, Bmatch)) {  // bctr or b 
2063     if (nextInstr.raw == 0) {
2064       ret = true;
2065     } else {
2066       ret = false;
2067     }
2068   } else {
2069     ret = false;
2070   }
2071 #endif
2072
2073   return ret;
2074 }
2075  * ************************************************************************ */
2076
2077 bool pd_Function::findInstPoints(const image *owner) 
2078 {  
2079   Address adr = getAddress(0);
2080   instruction instr;
2081   bool err;
2082
2083   instr.raw = owner->get_instruction(adr);
2084   if (!IS_VALID_INSN(instr)) {
2085     return false;
2086   }
2087
2088   funcEntry_ = new instPoint(this, instr, owner, adr, true, ipFuncEntry);
2089   assert(funcEntry_);
2090
2091   // instead of finding the return instruction, we are creating a 
2092   // return base trampoline which will be called when the function really
2093   // exits.  what will happen is that the link register, which holds the
2094   // pc for the return branch, will be changed to point ot this trampoline,
2095   instruction retInsn;
2096   retInsn.raw = 0;
2097   funcReturns += new instPoint(this, retInsn, owner, 0, false, ipFuncReturn);
2098
2099   instr.raw = owner->get_instruction(adr);
2100   while(instr.raw != 0x0) {
2101     if (isCallInsn(instr)) {
2102       // define a call point
2103       // this may update address - sparc - aggregate return value
2104       // want to skip instructions
2105       adr = newCallPoint(adr, instr, owner, err);
2106       if (err) return false;
2107     }
2108
2109     // now do the next instruction
2110     adr += 4;
2111     instr.raw = owner->get_instruction(adr);
2112   }
2113
2114   return(true);
2115 }
2116
2117
2118
2119 //
2120 // Each processor may have a different heap layout.
2121 //   So we make this processor specific.
2122 //
2123 // find all DYNINST symbols that are data symbols
2124 bool process::heapIsOk(const vector<sym_data> &find_us) {
2125   Address instHeapStart;
2126   Symbol sym;
2127   string str;
2128
2129   // find the main function
2130   // first look for main or _main
2131   if (!((mainFunction = findOneFunction("main")) 
2132         || (mainFunction = findOneFunction("_main")))) {
2133      string msg = "Cannot find main. Exiting.";
2134      statusLine(msg.string_of());
2135      showErrorCallback(50, msg);
2136      return false;
2137   }
2138
2139   for (unsigned i=0; i<find_us.size(); i++) {
2140     str = find_us[i].name;
2141     if (!symbols->symbol_info(str, sym)) {
2142       string str1 = string("_") + str.string_of();
2143       if (!symbols->symbol_info(str1, sym) && find_us[i].must_find) {
2144         string msg;
2145         msg = string("Cannot find ") + str + string(". Exiting");
2146         statusLine(msg.string_of());
2147         showErrorCallback(50, msg);
2148         return false;
2149       }
2150     }
2151   }
2152
2153   //string ghb = "_DYNINSTtext";
2154   //aix.C does not change the leading "." of function names to "_" anymore.
2155   //  Instead, the "." is simply skipped.
2156   string ghb = "DYNINSTtext";
2157   if (!symbols->symbol_info(ghb, sym)) {
2158       string msg;
2159       msg = string("Cannot find ") + ghb + string(". Exiting");
2160       statusLine(msg.string_of());
2161       showErrorCallback(50, msg);
2162       return false;
2163   }
2164   instHeapStart = sym.addr();
2165
2166   // check that we can get to our heap.
2167   if (instHeapStart > getMaxBranch() + symbols->codeOffset()) {
2168     logLine("*** FATAL ERROR: Program text + data too big for dyninst\n");
2169     sprintf(errorLine, "    heap starts at %x\n", instHeapStart);
2170     logLine(errorLine);
2171     sprintf(errorLine, "    max reachable at %x\n", 
2172         getMaxBranch() + symbols->codeOffset());
2173     logLine(errorLine);
2174     showErrorCallback(53,(const char *) errorLine);
2175     return false;
2176   } else if (instHeapStart + SYN_INST_BUF_SIZE > 
2177              getMaxBranch() + symbols->codeOffset()) {
2178     logLine("WARNING: Program text + data could be too big for dyninst\n");
2179     showErrorCallback(54,(const char *) errorLine);
2180     return false;
2181   }
2182
2183   string hd = "DYNINSTdata";
2184   if (!symbols->symbol_info(hd, sym)) {
2185       string msg;
2186       msg = string("Cannot find ") + hd + string(". Exiting");
2187       statusLine(msg.string_of());
2188       showErrorCallback(50, msg);
2189       return false;
2190   }
2191
2192   return true;
2193 }
2194
2195
2196
2197 //
2198 // This is specific to some processors that have info in registers that we
2199 //   can read, but should not write.
2200 //   On power, registers r3-r11 are parameters that must be read only.
2201 //     However, sometimes we have spilled to paramter registers back to the
2202 //     stack to use them as scratch registers.  In this case they are writeable.
2203 //
2204 bool registerSpace::readOnlyRegister(reg reg_number) 
2205 {
2206     registerSlot *regSlot;
2207
2208     // it's not a parameter registers so it is read/write
2209     if ((reg_number > 11) || (reg_number < 3)) return false;
2210
2211     // find the registerSlot for this register.
2212     for (int i = 0; i < regSpace->getRegisterCount(); i++) {
2213         regSlot = regSpace->getRegSlot(i);
2214         if (regSlot->number == reg_number) {
2215             break;
2216         }
2217     }
2218
2219     if (regSlot->mustRestore) {
2220         // we have already wrriten this to the stack so its OK to clobber it.
2221         return(false);
2222     } else {
2223         // its a live parameter register.
2224         return true;
2225     }
2226 }
2227
2228
2229 bool returnInstance::checkReturnInstance(const vector<Address> &adr,
2230                                          u_int &index)
2231 {
2232 #ifdef ndef  
2233 // TODO: implement this.  This stuff is not implemented for this platform 
2234     for(u_int i=0; i < adr.size(); i++){
2235         index = i;
2236         if ((adr[i] > addr_) && ( adr[i] <= addr_+size_)){
2237              return false;
2238         }
2239     }
2240 #endif
2241     return true;
2242 }
2243  
2244 void returnInstance::installReturnInstance(process *proc) {
2245     proc->writeTextSpace((caddr_t)addr_, instSeqSize, (caddr_t) instructionSeq); 
2246 }
2247
2248 void returnInstance::addToReturnWaitingList(Address , process * ) {
2249     int blah = 0;
2250     assert(blah);
2251     P_abort();
2252 }
2253
2254 void generateBreakPoint(instruction &insn) { // instP.h
2255     insn.raw = BREAK_POINT_INSN;
2256 }
2257
2258 void generateIllegalInsn(instruction &insn) { // instP.h
2259    insn.raw = 0; // I think that on power, this is an illegal instruction (someone check this please) --ari
2260 }
2261
2262 bool doNotOverflow(int value)
2263 {
2264   // we are assuming that we have 15 bits to store the immediate operand.
2265   if ( (value <= 32767) && (value >= -32768) ) return(true);
2266   else return(false);
2267 }
2268
2269 void instWaitingList::cleanUp(process * , Address ) {
2270     P_abort();
2271 }
2272
2273 bool completeTheFork(process *parentProc, int childpid) {
2274    // no "process" structure yet exists for the child.
2275    // a fork syscall has just happened.  On AIX, this means that
2276    // the text segment of the child has been reset instead of copied
2277    // from the parent process.  This routine "completes" the fork so that
2278    // it behaves like a normal UNIX fork.
2279
2280    // First, we copy everything from the parent's inferior text heap
2281    // to the child.  To do this, we loop thru every allocated item in
2282
2283    forkexec_cerr << "WELCOME to completeTheFork parent pid is " << parentProc->getPid()
2284                  << ", child pid is " << childpid << endl;
2285
2286    vector<heapItem*> srcAllocatedBlocks = parentProc->heaps[textHeap].heapActive.values();
2287
2288    char buffer[2048];
2289    const unsigned max_read = 1024;
2290
2291    for (unsigned lcv=0; lcv < srcAllocatedBlocks.size(); lcv++) {
2292       const heapItem &srcItem = *srcAllocatedBlocks[lcv];
2293
2294       assert(srcItem.status == HEAPallocated);
2295       unsigned addr = srcItem.addr;
2296       int      len  = srcItem.length;
2297       const unsigned last_addr = addr + len - 1;
2298
2299       unsigned start_addr = addr;
2300       while (start_addr <= last_addr) {
2301          unsigned this_time_len = len;
2302          if (this_time_len > max_read)
2303             this_time_len = max_read;
2304
2305          if (!parentProc->readDataSpace((const void*)addr, this_time_len, buffer, true))
2306             assert(false);
2307
2308          // now write "this_time_len" bytes from "buffer" into the inferior process,
2309          // starting at "addr".
2310          if (-1 == ptrace(PT_WRITE_BLOCK, childpid, (int*)addr, this_time_len,
2311                           (int*)buffer))
2312             assert(false);
2313
2314          start_addr += this_time_len;
2315       }
2316    }
2317
2318    // Okay that completes the first part; the inferior text heap contents have
2319    // been copied.  In other words, the base and mini tramps have been copied.
2320    // But now we need to update parts where the code that jumped to the base
2321    // tramps.
2322
2323    // How do we do this?  We loop thru all instInstance's of the parent process.
2324    // Fields of interest are:
2325    // 1) location (type instPoint*) -- where the code was put
2326    // 2) trampBase (type unsigned)  -- base of code.
2327    // 3) baseInstance (type trampTemplate*) -- base trampoline instance
2328
2329    // We can use "location" as the index into dictionary "baseMap"
2330    // of the parent process to get a "trampTemplate".
2331
2332    vector<instInstance*> allParentInstInstances;
2333    getAllInstInstancesForProcess(parentProc, allParentInstInstances);
2334
2335    for (unsigned lcv=0; lcv < allParentInstInstances.size(); lcv++) {
2336       instInstance *inst = allParentInstInstances[lcv];
2337       assert(inst);
2338
2339       instPoint *theLocation = inst->location;
2340       unsigned addr = theLocation->addr;
2341
2342       // I don't think we need these - naim
2343       //unsigned   theTrampBase = inst->trampBase;
2344       //trampTemplate *theBaseInstance = inst->baseInstance;
2345
2346       // I had to comment out the following line because it was causing 
2347       // problems. Also, I don't understand why do we want to overwrite the
2348       // content of the baseAddr field in the parent - naim
2349       //if (theBaseInstance) theBaseInstance->baseAddr = theTrampBase;
2350
2351       if (theLocation->addr==NULL) {
2352         // This happens when we are only instrumenting the return point of
2353         // a function, so we need to find the address where to insert the
2354         // jump to the base trampoline somewhere else. Actually, if we have
2355         // instrumentation at the entry point, this is not necessary, but
2356         // it looks easier this way - naim
2357         const function_base *base_f = theLocation->iPgetFunction();
2358         assert(base_f);
2359         const instPoint *ip = base_f->funcEntry(parentProc);
2360         assert(ip);
2361         addr = ip->addr;
2362       }
2363       assert(addr);
2364
2365       // Now all we need is a "returnInstance", which contains
2366       // "instructionSeq", a sequence of instructions to be installed,
2367       // and "addr_", an address to write to.
2368
2369       // But for now, since we always relocate exactly ONE
2370       // instruction on AIX, we can hack our way around without
2371       // the returnInstance.
2372
2373       // So, we need to copy one word.  The word to copy can be found
2374       // at address "theLocation->addr" for AIX.  The original instruction
2375       // can be found at "theLocation->originalInstruction", but we don't
2376       // need it.  So, we ptrace-read 1 word @ theLocation->addr from
2377       // the parent process, and then ptrace-write it to the same location
2378       // in the child process.
2379
2380       int data; // big enough to hold 1 instr
2381
2382       errno = 0;
2383       data = ptrace(PT_READ_I, parentProc->getPid(), 
2384                     (int*)addr, 0, 0);
2385       if (data == -1 && errno != 0)
2386          assert(false);
2387
2388       errno = 0;
2389       if (-1 == ptrace(PT_WRITE_I, childpid, (int*)addr, data, 0) &&
2390           errno != 0)
2391          assert(false);
2392    }
2393
2394    return true;
2395 }
2396
2397
2398 // hasBeenBound: returns false
2399 // dynamic linking not implemented on this platform
2400 bool process::hasBeenBound(const relocationEntry ,pd_Function *&, Address ) {
2401     return false;
2402 }
2403
2404 // findCallee: returns false unless callee is already set in instPoint
2405 // dynamic linking not implemented on this platform
2406 bool process::findCallee(instPoint &instr, function_base *&target){
2407
2408     if((target = (function_base *)instr.iPgetCallee())) {
2409        return true;
2410     }
2411     return false;
2412 }
2413
2414
2415 // process::replaceFunctionCall
2416 //
2417 // Replace the function call at the given instrumentation point with a call to
2418 // a different function, or with a NOOP.  In order to replace the call with a
2419 // NOOP, pass NULL as the parameter "func."
2420 // Returns true if sucessful, false if not.  Fails if the site is not a call
2421 // site, or if the site has already been instrumented using a base tramp.
2422 bool process::replaceFunctionCall(const instPoint *point,
2423                                   const function_base *newFunc) {
2424
2425     // Must be a call site
2426     if (point->ipLoc != ipFuncCallPoint)
2427         return false;
2428
2429     // Cannot already be instrumented with a base tramp
2430     if (baseMap.defines(point))
2431         return false;
2432
2433     instruction newInsn;
2434     if (newFunc == NULL) {      // Replace with a NOOP
2435         generateNOOP(&newInsn);
2436     } else {                    // Replace with a new call instruction
2437         generateBranchInsn(&newInsn,
2438                            newFunc->addr()+sizeof(instruction)-point->addr);
2439         newInsn.iform.lk = 1;
2440     }
2441
2442     writeTextSpace((caddr_t)point->addr, sizeof(instruction), &newInsn);
2443
2444     return true;
2445 }