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