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