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