initial dyninstAPI commit for code coverage
[dyninst.git] / dyninstAPI / src / inst-alpha.C
1 /*
2  * Copyright (c) 1996 Barton P. Miller
3  * 
4  * We provide the Paradyn Parallel Performance Tools (below
5  * described as Paradyn") on an AS IS basis, and do not warrant its
6  * validity or performance.  We reserve the right to update, modify,
7  * or discontinue this software at any time.  We shall have no
8  * obligation to supply such updates or modifications or any other
9  * form of support to you.
10  * 
11  * This license is for research uses.  For such uses, there is no
12  * charge. We define "research use" to mean you may freely use it
13  * inside your organization for whatever purposes you see fit. But you
14  * may not re-distribute Paradyn or parts of Paradyn, in any form
15  * source or binary (including derivatives), electronic or otherwise,
16  * to any other organization or entity without our permission.
17  * 
18  * (for other uses, please contact us at paradyn@cs.wisc.edu)
19  * 
20  * All warranties, including without limitation, any warranty of
21  * merchantability or fitness for a particular purpose, are hereby
22  * excluded.
23  * 
24  * By your use of Paradyn, you understand and agree that we (or any
25  * other person or entity with proprietary rights in Paradyn) are
26  * under no obligation to provide either maintenance services,
27  * update services, notices of latent defects, or correction of
28  * defects for Paradyn.
29  * 
30  * Even if advised of the possibility of such damages, under no
31  * circumstances shall we (or any other person or entity with
32  * proprietary rights in the software licensed hereunder) be liable
33  * to you or any third party for direct, indirect, or consequential
34  * damages of any character regardless of type of action, including,
35  * without limitation, loss of profits, loss of use, loss of good
36  * will, or computer failure or malfunction.  You agree to indemnify
37  * us (and any other person or entity with proprietary rights in the
38  * software licensed hereunder) for any and all liability it may
39  * incur to third parties resulting from your use of Paradyn.
40  */
41
42 // $Id: inst-alpha.C,v 1.39 2001/09/07 21:15:07 tikir Exp $
43
44 #include "common/h/headers.h"
45
46 #ifdef BPATCH_LIBRARY
47 #include "dyninstAPI_RT/h/dyninstAPI_RT.h"
48 #else
49 #include "rtinst/h/rtinst.h"
50 #endif
51 #include "dyninstAPI/src/symtab.h"
52 #include "dyninstAPI/src/process.h"
53 #include "dyninstAPI/src/inst.h"
54 #include "dyninstAPI/src/instP.h"
55 #include "dyninstAPI/src/arch-alpha.h"
56 #include "dyninstAPI/src/ast.h"
57 #include "dyninstAPI/src/util.h"
58 #include "dyninstAPI/src/instPoint.h"
59 #include <sys/procfs.h>
60 #include "dyninstAPI/src/stats.h"
61 #include "dyninstAPI/src/os.h"
62
63 /*
64    This has not been fully tested.
65    The Alpha likes to use jsrs much more than the sparc. 
66    Paradyn assumes jsrs are jumps to library functions -- this is incorrect.
67    It causes timers to be left on for many functions.  These timers are not 
68    supposed to overlap.
69
70    gcc compiles code in an interesting manner for the Alpha.  It creates an 
71    alternate entry point for most functions.  If gcc -S is run, the alternate
72    entry point has ..NG appended to the function name.  The alternate entry 
73    point does not show up in the symbol table.  I don't know the rules for 
74    choosing which entry point to use.  The alternate entry point is usually
75    two instructions after the advertised entry point.  This code will not work
76    with gcc compiled applications.  The runtime must also not be compiled with
77    gcc.
78
79    I have seen generated code that uses a register other than 'ra' for the return
80    address (a temporary register had been used).  I find this disturbing and played
81    it mostly safe when it came to saving registers.  At the base tramp, all registers
82    that a callee can clobber are saved.  This is done before and after the relocated
83    instruction.  One simple optimization is to avoid doing the save and restore
84    unless a slot is used on that side of the relocated instruction.
85
86    I have had to split the DYNINSTdata field into DYNINSTcode and DYNINSTdata.
87    The branch displacement is not large enough to reach DYNINSTdata from text space.
88    Programs compiled using cc should specify '-taso -non_shared -N'
89
90    The 'pv' register must contain the address of the callee when the callee is called.
91    I have not seen any documentation on this.  The API does not mention this.
92
93    'TODO' is used to mark loose ends -- this file does not have too many.
94    
95    Optimizing branch behavior (not implemented)
96    * branch to quadword or octaword aligned addresses
97    * forward conditional branches are predicted not taken, take advantage of this
98
99    Optimizing branch behavior (implemented)
100    * use least significant 16 bits of JSR for branch prediction
101
102  */
103
104
105 // HACK: This allows the bootstrap code for loading the dyninst library to
106 //    skip calling save/restore register code.
107 bool skipSaveCalls = false;
108
109 // The API for Alphas does not appear to be followed in all cases
110 // rather than spend much time and effort disassembling and cursing
111 // registers will be saved and restored in the base trampoline
112 // A save/restore pair will be executed before and after the relocated
113 // instruction.  An obvious optimization is to not do the save/restore
114 // when no code is inserted before or after the relocated instruction.
115 // 
116
117 // static inline Address generate_integer_op(instruction *insn, Address, Address,
118 //                                        Address, unsigned&, opCode);
119 // static inline Address generate_call_code(instruction*, Address, Address,
120 //                                       Address, unsigned&, process *proc);
121 // static inline Address generate_tramp_preamble(instruction*, Address,
122 //                                            Address, unsigned&);
123 static inline void generate_integer_op(instruction *insn, Address, Address,
124                                           Address, unsigned long&, opCode,bool Imm = false);
125 static inline Address generate_call_code(instruction*, Address, Address,
126                                          Address, unsigned long&, process *proc);
127 static inline void generate_tramp_preamble(instruction*, Address,
128                                               Address, unsigned long&);
129
130 // Register usage conventions:
131 //   a0-a5 are saved in the base trampoline
132 //   t0-t10 are scratch and do not have to be saved as long as instrumentation
133 //      is restricted to function entry/exit, and call points
134 //      these will be allocated by paradynd
135 //
136 //   t0-t7 : allocated by paradynd
137 //   t8: stores compare results, scratch for paradynd
138 //   t9,t10 : used as scratch registers by paradynd
139
140 // Return value register
141 #define REG_V0           0
142 // scratch registers -- not saved across procedure calls
143 #define REG_T0           1
144 #define REG_T1           2
145 #define REG_T2           3
146 #define REG_T3           4
147 #define REG_T4           5
148 #define REG_T5           6
149 #define REG_T6           7
150 #define REG_T7           8
151
152 // caller save registers
153 #define REG_S0           9
154 #define REG_S1          10
155 #define REG_S2          11
156 #define REG_S3          12
157 #define REG_S4          13
158 #define REG_S5          14
159
160 // argument registers
161 #define REG_A0          16
162 #define REG_A1          17
163 #define REG_A2          18
164 #define REG_A3          19
165 #define REG_A4          20
166 #define REG_A5          21
167
168 // more scratch registers
169 #define REG_T8          22
170 #define REG_T9          23
171 #define REG_T10         24
172 #define REG_T11         25
173
174 // return address register
175 #define REG_RA          26
176
177 // undocumented pv/t12
178 #define REG_PV          27
179 #define REG_T12         27
180
181 #define REG_GP          29
182 #define REG_SP          30
183 #define REG_ZERO        31
184
185 const unsigned Num_Registers=32;
186
187 typedef enum { dw_long, dw_quad } data_width;
188
189 #define MASK_4(x)     (x & 0xffffffff)
190 #define MASK_2(x)     (x & 0xffff)
191
192 const Address shifted_16 = (Address(1)) << 16;
193 const Address shifted_32 = (Address(1)) << 32;
194 const Address shifted_48 = (Address(1)) << 48;
195 const Address bit_15 =     (Address(1)) << 15;
196 const Address bit_31 =     (Address(1)) << 31;
197 const Address bit_47 =     (Address(1)) << 47;
198
199 const char *registerNames[] = { "ren", "stimpy" };
200 registerSpace *regSpace;
201 Register regList[] = {1, 2, 3, 4, 5, 6, 7, 8};
202
203 trampTemplate baseTemplate;
204
205 string getStrOp(int /* op */) {
206   assert(0);
207 }
208
209 // BIS (or)  R31, R31, R31
210 // unsigned generate_nop(instruction* insn) {
211 unsigned long generate_nop(instruction* insn) {
212   insn->raw = 0;
213   // insn.oper.zero = 0; insn.oper.sbz = 0;
214   insn->oper.opcode = OP_BIS;
215   insn->oper.function = FC_BIS;
216   insn->oper.ra = 31;
217   insn->oper.rb = 31;
218   insn->oper.rc = 31;
219   return 1;
220 }
221
222 inline void generateNOOP(instruction *insn)
223 {
224   insn->raw = 0;
225   // insn.oper.zero = 0; insn.oper.sbz = 0;
226   insn->oper.opcode = OP_BIS;
227   insn->oper.function = FC_BIS;
228   insn->oper.ra = 31;
229   insn->oper.rb = 31;
230   insn->oper.rc = 31;
231 }
232
233 #define FIRST_16(x)       ((x) & 0xffff)
234 #define SECOND_16(x)      ((x) >> 16)
235 #define THIRD_16(x)       ((x) >> 32)
236
237 #define ABS(x)          ((x) > 0 ? (x) : -(x))
238
239 // TODO -- the max branch is (0x1 << 22)
240 // if we limited branches to this distance, dyn. inst. would not work
241 // on a 64 bit architecture
242 #define MAX_BRANCH      (0x1<<22)
243
244 #define MAX_IMM 0x1<<8  // 8 bits
245
246 Address getMaxBranch() { 
247   return ((Address)(1 << 22));
248 }
249
250 bool doNotOverflow(int value)
251 {
252   // we are assuming that we have 8 bits to store the immediate operand.
253   if ( (value >= 0) && (value <= 255) ) return(true);
254   else return(false);
255 }
256
257 void instWaitingList::cleanUp(process * , Address ) {
258     P_abort();
259 }
260
261 // 
262 //
263 // unsigned
264 // generate_operate(instruction *insn, unsigned reg_a, unsigned reg_b, 
265 //               unsigned reg_c, unsigned opcode, unsigned func_code) {
266 unsigned long
267 generate_operate(instruction *insn, Register reg_a, Register reg_b, 
268          Register reg_c, unsigned int opcode, unsigned int func_code) {
269   assert(reg_a < Num_Registers);
270   assert(reg_b < Num_Registers);
271   assert(reg_c < Num_Registers);
272   insn->raw = 0;
273   // insn->oper.zero = 0; insn->oper.sbz = 0;
274   insn->oper.ra = reg_a; insn->oper.rb = reg_b; insn->oper.rc = reg_c;
275   insn->oper.opcode = opcode;
276   insn->oper.function = func_code;
277   return 1;
278 }
279
280 // 
281 //
282 // unsigned
283 // generate_lit_operate(instruction *insn, unsigned reg_a, int literal,
284 //                   unsigned reg_c, unsigned opcode, unsigned func_code) {
285 unsigned long
286 generate_lit_operate(instruction *insn, Register reg_a, int literal,
287              Register reg_c, unsigned int opcode, unsigned int func_code) {
288   assert(reg_a < Num_Registers);
289   // literal is 0 to 255
290   assert((literal >= 0) && (literal < MAX_IMM));
291   assert(reg_c < Num_Registers);
292   insn->raw = 0;
293   insn->oper_lit.one = 1;
294   insn->oper_lit.ra = reg_a;
295   insn->oper_lit.lit = literal;
296   insn->oper_lit.rc = reg_c;
297   insn->oper_lit.opcode = opcode;
298   insn->oper_lit.function = func_code;
299   return 1;
300 }
301
302 // j?? ra, (rb), hint
303 // jump to rb, ra gets return address, displacement field provides 
304 // instruction fetch hint
305 // TODO -- provide a decent hint
306 // unsigned
307 // generate_jump(instruction *insn, unsigned dest_reg, unsigned ext_code,
308 //            unsigned ret_reg, int hint) {
309 unsigned long
310 generate_jump(instruction *insn, Register dest_reg, unsigned long ext_code,
311               Register ret_reg, int hint) {
312   assert(dest_reg < Num_Registers); 
313   assert(ret_reg < Num_Registers); 
314   assert((ext_code == MD_JSR) || (ext_code == MD_JMP));
315
316   // If you want to use this for other ext_code values, then modify the branch
317   // prediction
318
319   insn->raw = 0;
320   insn->mem_jmp.opcode = OP_MEM_BRANCH;
321   insn->mem_jmp.ext = ext_code;
322   insn->mem_jmp.ra = ret_reg;
323   insn->mem_jmp.rb = dest_reg;
324   insn->mem_jmp.disp = hint;
325   return 1;
326 }
327
328
329 // src_reg --> for unconditional branch, gets return address
330 // src_reg --> for conditional branch, is register to test
331 // b??  r31, offset   <-- return address written to r31, which is ignored
332 //
333 // unsigned
334 // generate_branch(instruction *insn, unsigned src_reg, int offset, unsigned opcode) {
335 unsigned long
336 generate_branch(instruction *insn, Register src_reg, int offset,
337                 unsigned int opcode) {
338   if (ABS(offset >> 2) > MAX_BRANCH) 
339         { logLine("a branch too far\n"); assert(0); }
340   assert(src_reg < Num_Registers);
341   insn->raw = 0;
342   insn->branch.opcode = opcode;
343   insn->branch.ra = src_reg;
344   insn->branch.disp = offset >> 2;
345   return 1;
346 }
347
348 void generateBSR(instruction *insn,int offset)
349 {
350   generate_branch(insn,REG_RA,offset,OP_BSR);
351
352 }
353 void generateBranchInsn(instruction *insn, int offset) {
354   generate_branch(insn, REG_ZERO, offset, OP_BR);
355 }
356
357 // 
358 // Set condition flag (a register)
359 // unsigned
360 // genRelOp(instruction *insn, unsigned opcode, unsigned fcode,
361 //       unsigned src1, unsigned src2, unsigned dest, bool do_not=false) {
362 unsigned long
363 genRelOp(instruction *insn, unsigned opcode, unsigned fcode, Register src1,
364          Register src2, Register dest, bool Imm=false, bool do_not=false) {
365   // cmp?? src1, src2, t8      : leave result in t8
366 //  unsigned words = generate_operate(insn, src1, src2, dest, opcode, fcode);
367   unsigned long words;
368   if (Imm)
369     words = generate_lit_operate(insn, src1, src2, dest, opcode, fcode);
370   else
371     words = generate_operate(insn, src1, src2, dest, opcode, fcode);
372
373   if (do_not) {
374     // since there is no cmpne -- cmpeq is used and the result must be inverted
375     // 0 -->  1,  1 ---> 0
376     // negate t8, and add 1  (1 --> -1 + 1 = 0,  0 --> -0 +1 = 1 )
377     words += generate_operate(insn+words, REG_ZERO, dest, dest, OP_SUBL, FC_SUBL);
378     words += generate_lit_operate(insn+words, dest, 1, dest, OP_ADDL, FC_ADDL);
379     // dest now contains a 0 or a 1 
380   }
381   return words;
382 }
383
384 instPoint::instPoint(pd_Function *f, const instruction &instr, 
385                      const image *img, Address &adr,
386                      const bool,instPointType pointType)
387 : addr(adr), originalInstruction(instr), inDelaySlot(false), isDelayed(false),
388   callIndirect(false), callAggregate(false), callee(NULL), func(f),
389   ipType(pointType), image_ptr(img)
390 {
391 }
392
393
394
395 // lda(h) rdest, literal:16(rstart)
396 // put a literal in a register
397 // offset is the value before the shift
398 // unsigned 
399 // generate_lda(instruction *insn, unsigned rdest, unsigned rstart,
400 //           int offset, bool do_low) {
401 unsigned long
402 generate_lda(instruction *insn, Register rdest, Register rstart,
403              long offset, bool do_low) {
404
405   // this is not wuite the correct check, but some calls supply the actual
406   //   signed displacement and others supply the raw 16 bits (i.e. not sign
407   //   extended.  - jkh
408   assert(ABS(offset) < (int) shifted_16);
409   // assert(offset >= (- (long) 0xffffffff));
410   assert(rdest < Num_Registers);
411   assert(rstart < Num_Registers);
412
413   insn->raw = 0;
414   insn->mem.opcode = do_low ? OP_LDA : OP_LDAH;
415   insn->mem.ra = rdest;
416   insn->mem.rb = rstart;
417   insn->mem.disp = offset;
418   return 1;
419 }
420
421 // left == true, shift left
422 // left == false, shift right
423 // unsigned
424 // amount is a literal
425 // generate_sxl(instruction *insn, unsigned rdest, unsigned amount,
426 //           bool left, unsigned rsrc) {
427 unsigned long
428 generate_sxl(instruction *insn, Register rdest, unsigned long amount,
429              bool left, Register rsrc) {
430   assert(rdest < Num_Registers);
431   assert(amount < Num_Registers);
432   assert(rsrc < Num_Registers);
433   insn->raw = 0;
434   // insn->oper.sbz = 0;
435   // insn->oper.zero = 0;
436
437   insn->oper_lit.opcode = left ? OP_SLL : OP_SRL;
438   insn->oper_lit.function = left ? FC_SLL : FC_SRL;
439   insn->oper_lit.one = 1;
440   insn->oper_lit.ra = rsrc;
441   insn->oper_lit.lit = amount;
442   insn->oper_lit.rc = rdest;
443   return 1;
444 }
445
446 #define SEXT_16(x) (((x) & bit_15) ? ((x) | 0xffffffffffff0000) : (x))
447
448 typedef unsigned long int Offset;
449
450 // remainder returns 15 bit offset to be included in load or store
451 // returns number of instruction words
452 // unsigned generate_address(instruction *insn, 
453 //                       unsigned rdest,
454 //                       const Address &addr,
455 //                       int& remainder) {
456 unsigned long generate_address(instruction *insn, 
457                          unsigned long rdest,
458                          const Address &addr,
459                          int& remainder) {
460 //  unsigned words = 0;
461   unsigned long words = 0;
462
463   Offset tempAddr = addr;
464   Offset low = tempAddr & 0xffff;
465   tempAddr -= SEXT_16(low);
466   Offset high = (tempAddr >> 16) & 0xffff;
467   tempAddr -= (SEXT_16(high) << 16);
468   Offset third = (tempAddr >> 32) & 0xffff;
469
470   assert((Address)SEXT_16(low) +
471          ((Address)SEXT_16(high)<<16) +
472          ((Address)SEXT_16(third)<<32) == addr);
473
474   bool primed = false;
475   if (third) {
476     primed = true;
477     assert(third < shifted_16);
478     generate_lda(insn+words, rdest, REG_ZERO, third, false);
479     words++;
480     generate_sxl(insn+words, rdest, 16, true, rdest);  // move (31:15) to (47:32)
481     words++;
482   }
483
484   if (high) {
485     if (primed)
486       generate_lda(insn+words, rdest, rdest, high, false);
487     else
488       generate_lda(insn+words, rdest, REG_ZERO, high, false);
489     words++; 
490     primed = true;
491   }
492   // a better solution is to use register zero as the base
493   // clear the base register
494   if (!primed) 
495     words += generate_operate(insn+words, REG_ZERO, REG_ZERO, rdest, 
496                               OP_BIS, FC_BIS);
497
498   remainder = low;
499   return words;
500 }
501
502 // stx rsrc, [rbase + sign_extend(offset:16)]
503 // unsigned
504 // generate_store(instruction* insn, unsigned rsrc, unsigned rbase, int disp,
505 //             data_width width) {
506 unsigned long
507 generate_store(instruction* insn, Register rsrc, Register rbase, 
508         int disp, data_width width) {
509   assert(ABS(disp) < (int) shifted_16); 
510   assert(rsrc < Num_Registers); 
511   assert(rbase < Num_Registers);
512   insn->raw = 0;
513   insn->mem.disp = FIRST_16(disp);
514   insn->mem.ra = rsrc;
515   insn->mem.rb = rbase;
516   switch (width) {
517   case dw_long: insn->mem.opcode = OP_STL; break;
518   case dw_quad: insn->mem.opcode = OP_STQ; break;
519   default: assert(0);
520   }
521   return 1;
522 }
523
524 // ldx rdest, [rbase + sign_extend(offset:16)]
525 // unsigned
526 // generate_load(instruction *insn, unsigned rdest, unsigned rbase, int disp,
527 //            data_width width) {
528 unsigned long
529 generate_load(instruction *insn, Register rdest, Register rbase, 
530         int disp, data_width width,bool aligned = true) {
531   assert(ABS(disp) < (int) shifted_16); 
532   assert(rdest < Num_Registers);
533   assert(rbase < Num_Registers);
534   insn->raw = 0;
535   insn->mem.disp = disp;
536   insn->mem.ra = rdest;
537   insn->mem.rb = rbase;
538   switch (width) {
539   case dw_long: insn->mem.opcode = OP_LDL; break;
540   case dw_quad: insn->mem.opcode = OP_LDQ; break;
541   default: assert(0);
542   }
543   if (aligned == false)
544     insn->mem.opcode = OP_LDQ_U;
545   return 1;
546 }
547
548
549 // Restore argument registers (a0-a4) or v0
550 void restoreRegister(instruction *&insn, Address &base, int reg, int dest)
551 {
552   assert(reg >= 0);
553   generate_load(insn,dest,REG_SP,(reg<<3),dw_quad);
554   insn++;
555   base += sizeof(instruction);
556 }
557
558 // Determine if the called function is a "library" function or a "user" function
559 // This cannot be done until all of the functions have been seen, verified, and
560 // classified
561 //
562 void pd_Function::checkCallPoints() {
563 //  unsigned i;
564   unsigned long i;
565   instPoint *p;
566   Address loc_addr;
567
568   vector<instPoint*> non_lib;
569
570   for (i=0; i<calls.size(); ++i) {
571     /* check to see where we are calling */
572     p = calls[i];
573     assert(p);
574
575     if (isJsr(p->originalInstruction)) {
576       // assume this is a library function
577       // since it is a jump through a register
578       // TODO -- should this be deleted here ?
579       p->callIndirect = true;
580       non_lib.push_back(p);
581       //      delete p;
582     } else if (isBsr(p->originalInstruction)) {
583       loc_addr = p->addr + (p->originalInstruction.branch.disp << 2)+4;
584       non_lib.push_back(p);
585       pd_Function *pdf = (file_->exec())->findFunction(loc_addr);
586
587       if (pdf == NULL)
588         {
589           /* Try alternate entry point in the symbol table */
590           loc_addr = loc_addr - 8;
591           pdf = (file_->exec())->findFunction(loc_addr);
592         }
593
594       if (pdf && 1 /*!pdf->isLibTag()*/)
595           p->callee = pdf;
596     } else {
597       assert(0);
598     }
599   }
600   calls = non_lib;
601 }
602
603 // TODO we cannot find the called function by address at this point in time
604 // because the called function may not have been seen.
605 //
606 Address pd_Function::newCallPoint(Address, const instruction,
607                                   const image *, bool &) {
608     abort();
609     // This is not used on Alpha
610 }
611
612 //
613 // Given and instruction, relocate it to a new address, patching up
614 // any relative addressing that is present.
615 //
616 // Note - currently - only 
617 //
618 void relocateInstruction(instruction* insn, Address origAddr,
619                          Address targetAddr) {
620   Address newOffset;
621
622   if (isBranchType(*insn)) {
623     newOffset = origAddr - targetAddr + (Address) (insn->branch.disp << 2);
624     insn->branch.disp = newOffset >> 2;
625
626     if (ABS(insn->branch.disp) > MAX_BRANCH) {
627       logLine("a branch too far\n");
628       assert(0);
629     }
630   }
631   // The rest of the instructions should be fine as is 
632 }
633
634 registerSpace *createRegisterSpace()
635 {
636   return new registerSpace(sizeof(regList)/sizeof(Register), regList,
637                                 0, NULL);
638 }
639
640 //
641 // We now generate tramps on demand, so all we do is init the reg space.
642 //
643 void initTramps() {
644   static bool init_done=false;
645
646   if (init_done) return;
647   init_done = true;
648
649   regSpace = new registerSpace(sizeof(regList)/sizeof(Register), regList,
650                                 0, NULL);
651 }
652
653 // Emit a func 64bit address for the call
654 inline void callAbsolute(instruction *code, 
655                          unsigned long &words, 
656                          Address funcAddr)
657 {
658   int remainder;
659   words += generate_address(code+(words), REG_GP, funcAddr, remainder);
660   if (remainder)
661     words += generate_lda(code+(words), REG_GP, REG_GP, remainder, true);
662   words += generate_jump(code+(words), REG_GP, MD_JSR, REG_RA, remainder);
663 }
664
665 /*
666  * Install a base tramp -- fill calls with nop's for now.
667  * An obvious optimization is to turn off the save-restore calls when they 
668  * are not needed.
669  */
670 void installBaseTramp(instPoint *location,
671                       process *proc,
672                       trampTemplate &tramp
673                       ) {
674 //  unsigned words = 0;
675   unsigned long words = 0;
676   const int MAX_BASE_TRAMP = 128;
677
678   // XXX - for now assume base tramp is less than 1K
679   instruction *code = new instruction[MAX_BASE_TRAMP]; assert(code);
680
681   function_base *fun_save;
682   function_base *fun_restore;
683
684   Symbol info;
685   Address baseAddr;
686
687   if (location->ipType == otherPoint) {
688       fun_save = proc->findOneFunction("DYNINSTsave_conservative");
689       fun_restore = proc->findOneFunction("DYNINSTrestore_conservative");
690       proc->getSymbolInfo("DYNINSTsave_conservative", info, baseAddr);
691   } else {
692       fun_save = proc->findOneFunction("DYNINSTsave_temp");
693       fun_restore = proc->findOneFunction("DYNINSTrestore_temp");
694       proc->getSymbolInfo("DYNINSTsave_temp", info, baseAddr);
695   }
696
697   assert(fun_save && fun_restore);
698   Address dyn_save = fun_save->addr() + baseAddr;
699   Address dyn_restore = fun_restore->addr() + baseAddr;
700
701   // Pre branch
702   instruction *skipPreBranch = &code[words];
703   tramp.skipPreInsOffset = words*4;
704   words += generate_nop(code+words);
705
706   // decrement stack by 16
707   tramp.savePreInsOffset = words*4;
708   words += generate_lda(code+words, REG_SP, REG_SP, -16, true);
709
710   // push ra onto the stack
711   words += generate_store(code+words, REG_RA, REG_SP, 0, dw_quad);
712
713   // push GP onto the stack
714   words += generate_store(code+words, REG_GP, REG_SP, 8, dw_quad);
715
716   // Call to DYNINSTsave_temp
717   callAbsolute(code, words, dyn_save);
718
719   // global_pre
720   tramp.globalPreOffset = words * 4;
721   words += generate_nop(code+words);
722
723   // local_pre
724   tramp.localPreOffset = words * 4;
725   words += generate_nop(code+words);
726
727   words += generate_nop(code+words);
728
729   // **** When you change these code also look at emitFuncJump ****
730   // Call to DYNINSTrestore_temp
731   tramp.localPreReturnOffset = words * 4;
732   callAbsolute(code, words, dyn_restore);
733
734   // load ra from the stack
735   words += generate_load(code+words, REG_RA, REG_SP, 0, dw_quad);
736
737   // load GP from the stack
738   words += generate_load(code+words, REG_GP, REG_SP, 8, dw_quad);
739
740   // increment stack by 16
741   tramp.restorePreInsOffset = words*4;
742   words += generate_lda(code+words, REG_SP, REG_SP, 16, true);
743
744   // *** end code cloned in emitFuncJump ****
745
746   // slot for emulate instruction
747   tramp.emulateInsOffset = words*4;
748   instruction *reloc = &code[words]; 
749   *reloc = location->originalInstruction;
750   words += 1;
751   // Do actual relocation once we know the base address of the tramp
752
753   // compute effective address of this location
754   Address pointAddr = location->addr;
755   Address baseAddress;
756   if(proc->getBaseAddress(location->image_ptr, baseAddress)){
757       pointAddr += baseAddress;
758   }
759
760   // Post branch
761   instruction *skipPostBranch = &code[words];
762   tramp.skipPostInsOffset = words*4;
763   words += generate_nop(code+words);
764
765   // decrement stack by 16
766   tramp.savePostInsOffset = words*4;
767   words += generate_lda(code+words, REG_SP, REG_SP, -16, true);
768
769   // push ra onto the stack
770   words += generate_store(code+words, REG_RA, REG_SP, 0, dw_quad);
771
772   // push GP onto the stack
773   words += generate_store(code+words, REG_GP, REG_SP, 8, dw_quad);
774
775   // Call to DYNINSTsave_temp
776   callAbsolute(code, words, dyn_save);
777
778   // global_post
779   tramp.globalPostOffset = words * 4;
780   words += generate_nop(code+words);
781
782   // local_post
783   tramp.localPostOffset = words * 4;
784   words += generate_nop(code+words);
785
786   // Call to DYNINSTrestore_temp
787   tramp.localPostReturnOffset = words * 4;
788   callAbsolute(code, words, dyn_restore);
789
790   // load ra from the stack
791   words += generate_load(code+words, REG_RA, REG_SP, 0, dw_quad);
792
793   // load GP from the stack
794   words += generate_load(code+words, REG_GP, REG_SP, 8, dw_quad);
795
796   // increment stack by 16
797   tramp.restorePostInsOffset = words*4;
798   words += generate_lda(code+words, REG_SP, REG_SP, 16, true);
799
800   // If the relocated insn is a Jsr or Bsr then 
801   // appropriately set Register Ra
802   if (isCallInsn(location->originalInstruction)) {
803       int remainder;
804       words += generate_address(code+words, REG_RA, pointAddr+4,remainder);
805       if (remainder)
806         words += generate_lda(code+words, REG_RA, REG_RA, remainder, true);
807   }
808
809   // slot for return (branch) instruction
810   // actual code after we know its locations
811   // branchFromAddr offset from base until we know base of tramp 
812   tramp.returnInsOffset = (words * 4);          
813   instruction *branchBack = &code[words];
814   words += 1;
815
816   words += generate_nop(code+words);
817
818   assert(words < MAX_BASE_TRAMP);
819
820   tramp.size = words * sizeof(instruction);
821   tramp.baseAddr = inferiorMalloc(proc, tramp.size, textHeap, pointAddr);
822   assert(tramp.baseAddr);
823
824   // pointAddr + 4 is address of instruction after relocated instr
825   // branchFromAddr = address of the branch insn that returns to user code
826   // branchFromAddr + 4 is updated pc when branch instruction executes
827   // we assumed this one was instruction long before
828
829   // update now that we know base
830   Address branchFromAddr = tramp.returnInsOffset + tramp.baseAddr;
831
832   int count = generate_branch(branchBack, REG_ZERO,
833                            (pointAddr+4) - (branchFromAddr+4), OP_BR);
834   assert(count == 1);
835
836   // Do actual relocation once we know the base address of the tramp
837   relocateInstruction(reloc, pointAddr, 
838        tramp.baseAddr + tramp.emulateInsOffset);
839
840   // Generate skip pre and post instruction branches
841   generateBranchInsn(skipPreBranch,
842                      tramp.emulateInsOffset - (tramp.skipPreInsOffset+4));
843   generateBranchInsn(skipPostBranch,
844                      tramp.returnInsOffset - (tramp.skipPostInsOffset+4));
845
846   tramp.prevInstru = false;
847   tramp.postInstru = false;
848
849   proc->writeDataSpace((caddr_t)tramp.baseAddr, tramp.size, (caddr_t) code);
850   delete (code);
851 }
852
853 /*
854  * emitSaveConservative - generate code to save all registers
855  *      used as part of inferrior RPC
856  *      We don't know where this will be located, so generate absolute addr
857  *          for the function call.
858  *
859  */
860 void emitSaveConservative(process *proc, char *code, Address &offset)
861 {
862   unsigned count = 0;
863   function_base *fun_save;
864   instruction *insn = (instruction *) ((void*)&code[offset]);
865
866   Symbol info;
867   Address baseAddr;
868   fun_save = proc->findOneFunction("DYNINSTsave_conservative");
869   proc->getSymbolInfo("DYNINSTsave_temp", info, baseAddr);
870   assert(fun_save);
871
872   Address dyn_save = fun_save->addr() + baseAddr;
873
874   // decrement stack by 16
875   count += generate_lda(&insn[count], REG_SP, REG_SP, -16, true);
876
877   // push T10 onto the stack
878   count += generate_store(&insn[count], REG_T10, REG_SP, 0, dw_quad);
879
880   // push ra onto the stack
881   count += generate_store(&insn[count], REG_RA, REG_SP, 8, dw_quad);
882
883   // Call to DYNINSTsave_conservative
884   int remainder;
885   count += generate_address(&insn[count], REG_T10, dyn_save, remainder);
886   if (remainder)
887     count += generate_lda(&insn[count], REG_T10, REG_T10, remainder, true);
888   count += generate_jump(&insn[count], REG_T10, MD_JSR, REG_RA, remainder);
889
890   offset += count * sizeof(instruction);
891 }
892
893 /*
894  * emitSaveConservative - generate code to restore all registers
895  *      used as part of inferrior RPC
896  *      We don't know where this will be located, so generate absolute addr
897  *          for the function call.
898  *
899  */
900 void emitRestoreConservative(process *proc, char *code, Address &offset)
901 {
902   unsigned count = 0;
903   function_base *fun_restore;
904   instruction *insn = (instruction *) ((void*)&code[offset]);
905
906   Symbol info;
907   Address baseAddr;
908   fun_restore = proc->findOneFunction("DYNINSTrestore_conservative");
909   proc->getSymbolInfo("DYNINSTsave_temp", info, baseAddr);
910   assert(fun_restore);
911
912   Address dyn_restore = fun_restore->addr() + baseAddr;
913
914   // Call to DYNINSTrestore_temp
915   int remainder;
916   count += generate_address(&insn[count], REG_T10, dyn_restore, remainder);
917   if (remainder)
918     count += generate_lda(&insn[count], REG_T10, REG_T10, remainder, true);
919   count += generate_jump(&insn[count], REG_T10, MD_JSR, REG_RA, remainder);
920
921   // load t10 from the stack
922   count += generate_load(&insn[count], REG_T10, REG_SP, 0, dw_quad);
923
924   // load ra from the stack
925   count += generate_load(&insn[count], REG_RA, REG_SP, 8, dw_quad);
926
927   // increment stack by 16
928   count += generate_lda(&insn[count], REG_SP, REG_SP, 16, true);
929
930   offset += count * sizeof(instruction);
931 }
932
933 //
934 // move the passed parameter into the passed register, or if it is already
935 //    in a register return the register number.
936 //
937 Register getParameter(Register, int param) {
938   if (param <= 5) {
939     return(16+param);
940   }
941   assert(0); 
942   return(Null_Register);
943 }
944
945 int getInsnCost(opCode op) {
946
947   if (op == loadConstOp) {
948     return(1);
949   } else if (op ==  loadOp) {
950     // assume two cycles to generate address, one to issue load
951     return(1+2);
952   } else if (op ==  storeOp) {
953     // assume two cycles to generate address, one to issue store
954     return(1+2);
955   } else if (op ==  ifOp) {
956     // beq
957     return(1);
958   } else if (op ==  callOp) {
959     //  3  : load address for jsr to DYNINSTsave_misc
960     // 12  : cost of DYNINSTsave_misc           
961     //  3  : jsr to DYNINSTsave_misc (1 + 2 cycle branch penalty)
962     //  3  : load address into register for jsr to called function
963     //  1  : move argument to argument register (assume 1 arg on average)
964     //  3  : issue jsr to called function (1 + 2 cycle branch penalty)
965     //  3  : load address for jsr to DYNINSTrestore_misc
966     // 12  : cost of DYNINSTrestore_misc           
967     //  3  : jsr to DYNINSTrestore_misc (1 + 2 cycle branch penalty)
968     //
969     // TODO -- what about the cost of the called code ?
970     return 43;
971   } else if (op ==  trampPreamble) {
972     //  2  : load address of observed_cost
973     //  1  : load value of observed_cost
974     //  1  : add to observed cost
975     //  1  : store updated observed_cost
976     return(2+1+1+1);
977   } else if (op ==  trampTrailer) {
978     // ret
979     return(1);
980   } else if (op == noOp) {
981     // noop
982     return(1);
983   } else {
984     switch (op) {
985     case eqOp:
986       return 1;                 // 1  : cmpeq
987     case neOp:
988       return 3;                 // cmpeq, negate result, add 1 to result
989     case lessOp:          
990     case greaterOp:
991     case leOp:
992     case geOp:
993       return 1;                 // cmpXX, arguments may be reversed
994     default:                    // other integer operators
995       return(1);
996       break;
997     }
998   }
999 }
1000
1001 // void generateNoOp(process *proc, int addr) {
1002 void generateNoOp(process *proc, unsigned long addr) {
1003   instruction insn;
1004   generate_nop(&insn);
1005   proc->writeTextWord((caddr_t)addr, insn.raw);
1006 }
1007
1008 /*
1009  * change the insn at fromAddr to be a branch to newAddr.
1010  *   Used to add multiple tramps to a point.
1011  */
1012 void generateBranch(process *proc, Address fromAddr, Address newAddr) {
1013   int disp;
1014   instruction insn;
1015
1016   Address a = ABS((long)((fromAddr+4) - newAddr));
1017   Address b = (Address) MAX_BRANCH;
1018 //  if ((ABS((fromAddr+4) - newAddr)) > (Address) MAX_BRANCH) { 
1019 if (a > b) {
1020     logLine("a branch too far\n"); assert(0);
1021   }
1022
1023   // Note the explicit cast
1024   // +4 to use updated pc
1025   disp = newAddr - (fromAddr+4);
1026   generateBranchInsn(&insn, disp);
1027
1028   proc->writeTextWord((caddr_t)fromAddr, insn.raw);
1029 }
1030
1031 // The Alpha does not have a divide instruction
1032 // The divide is performed in software by calling __divl
1033 int software_divide(int src1,int src2,int dest,char *i,Address &base,bool,Address divl_addr,bool Imm = false)
1034 {
1035   int words;
1036   int remainder;
1037   instruction *insn = (instruction *) ((void*)&i[base]);
1038
1039   assert(!((unsigned long)insn & (unsigned long)3));  
1040   // or src1,src1,a0
1041   generate_operate(insn,src1,src1,REG_A0,OP_BIS,FC_BIS);
1042   insn++;
1043   base+= sizeof(instruction);
1044   if (Imm)
1045     // load constant into register a1
1046     generate_lit_operate(insn,REG_ZERO,src2,REG_A1, OP_ADDL, FC_ADDL);    
1047     else
1048       // or src2,src2,a1
1049       generate_operate(insn,src2,src2,REG_A1,OP_BIS,FC_BIS);
1050   insn++;
1051   base+= sizeof(instruction);
1052
1053   // jsr __divl
1054   words = generate_address(insn, REG_PV,divl_addr, remainder);
1055   if (remainder)
1056       words += generate_lda(insn+words, REG_PV, REG_PV, remainder, true);
1057   words += generate_jump(insn+words, REG_PV, MD_JSR, REG_RA, remainder);
1058   insn += words; base += (words*4);
1059
1060   // or v0,v0,dest
1061   generate_operate(insn,REG_V0,REG_V0,dest,OP_BIS,FC_BIS);
1062   insn++;
1063   base+= sizeof(instruction);  
1064   return 0;
1065 }
1066
1067 static inline void
1068 generate_integer_op(instruction *insn, Address src1, Address src2, 
1069                     Address dest, unsigned long& base, opCode op, bool Imm = FALSE) {
1070 //                  Address dest, unsigned & base, opCode op) {
1071   // integer ops
1072 //  unsigned op_code=0, func_code=0, words = 0;
1073   unsigned op_code=0, func_code=0;
1074   unsigned long words = 0;
1075
1076   switch (op) {
1077
1078   case plusOp:        op_code = OP_ADDQ; func_code = FC_ADDQ; break;
1079   case minusOp:       op_code = OP_SUBQ; func_code = FC_SUBQ; break;
1080   case timesOp:       op_code = OP_MULQ; func_code = FC_MULQ; break;
1081   case divOp:         assert(0); // shouldn't get here. Call software_divide from the ast
1082   case orOp:          op_code = OP_BIS;  func_code = FC_BIS; break;
1083   case andOp:         op_code = OP_AND;  func_code = FC_AND; break;
1084
1085   // The compare instruction leave a one in dest if the compare is true
1086   // beq branch when dest is 0 --> and the compare is false
1087
1088   case eqOp:
1089     words += genRelOp(insn, OP_CMPEQ, FC_CMPEQ, src1, src2, dest,Imm);
1090     base += words * 4; return;
1091
1092   case neOp:
1093     // last arg == true --> inverts value of comparison               
1094     words += genRelOp(insn, OP_CMPEQ, FC_CMPEQ, src1, src2, dest,Imm,true);
1095     base += words * 4; return;
1096
1097   case lessOp:
1098     words += genRelOp(insn, OP_CMPLT, FC_CMPLT, src1, src2, dest,Imm);
1099     base += words * 4; return;
1100                       
1101   case greaterOp:                          
1102     words += genRelOp(insn, OP_CMPLE, FC_CMPLE, src1, src2, dest,Imm,true);
1103     base += words * 4; return;
1104
1105   case leOp:
1106     words += genRelOp(insn, OP_CMPLE, FC_CMPLE, src1, src2, dest,Imm);
1107     base += words * 4; return;
1108
1109   case geOp:                               
1110     words += genRelOp(insn, OP_CMPLE, FC_CMPLT, src1, src2, dest,Imm,true);
1111     base += words * 4; return;
1112
1113   default:
1114     assert(0);
1115     break;
1116   }
1117
1118   if (Imm) {
1119       if ((src2 >= 0) && (src2 < MAX_IMM)) {
1120         words += generate_lit_operate(insn+words, src1, src2, dest, op_code, 
1121             func_code);
1122       } else {
1123         words += generate_operate(insn+words, src1, src2, dest, op_code, func_code);
1124       }
1125   } else {
1126     words += generate_operate(insn+words, src1, src2, dest, op_code, func_code);
1127   }
1128   base += words * 4; return;
1129 }
1130
1131 /*
1132     ra only has to be saved when a procedure call is added using
1133     instrumentation.
1134     the Alpha API.
1135     ra must be saved because it will be clobbered by a procedure call since 
1136     it will get the return address. 
1137  */
1138
1139 /*
1140    It would be nice to be able to do relative branches to DYNINST funcs from
1141    here.  Unfortunately, I do not have the base address of the trampoline.
1142  */
1143 static inline Address
1144 generate_call_code(instruction *insn, Address src1, Address src2, Address dest,
1145                    unsigned long& base, process *proc) {
1146 //                 unsigned& base, process *proc) {
1147   // put parameters in argument registers
1148   // register move is "bis src, src, dest"  (bis is logical or)
1149   // save and restore the values currently in the argument registers
1150 //  unsigned words = 0;
1151   unsigned long words = 0;
1152 //  int decrement = -8;
1153
1154   Symbol info;
1155   Address baseAddr;
1156
1157   proc->getSymbolInfo("DYNINSTsave_misc", info, baseAddr);
1158   function_base *fun_save = proc->findOneFunction("DYNINSTsave_misc");
1159   function_base *fun_restore = proc->findOneFunction("DYNINSTrestore_misc");
1160   assert(fun_save && fun_restore);
1161   Address dyn_save = fun_save->addr() + baseAddr;
1162   Address dyn_restore = fun_restore->addr() + baseAddr;
1163
1164   // save the current values in v0, a0..a5, pv, at, gp
1165   // Call to DYNINSTsave_misc
1166   int remainder;
1167   words += generate_address(insn+words, REG_T10, dyn_save, remainder);
1168   if (remainder)
1169     words += generate_lda(insn+words, REG_T10, REG_T10, remainder, true);
1170   words += generate_jump(insn+words, REG_T10, MD_JSR, REG_RA, remainder);
1171
1172   // move args to argument registers
1173   if (src1 > 0)
1174     words += generate_operate(insn+words, src1, src1, REG_A0, OP_BIS, FC_BIS);
1175   if (src2 > 0) 
1176     words += generate_operate(insn+words, src2, src2, REG_A1, OP_BIS, FC_BIS);
1177
1178   // Set the value of  pv/t12/r27
1179   // I have not found any documentation on this
1180   // But the alpha appears to put the callee's address in this register
1181   // this register must be saved and restored
1182
1183   // Jump to the function
1184   words += generate_address(insn+words, REG_PV, dest, remainder);
1185   if (remainder)
1186     words += generate_lda(insn+words, REG_PV, REG_PV, remainder, true);
1187
1188   // TODO -- clear other argument registers ?
1189   words += generate_jump(insn+words, REG_PV, MD_JSR, REG_RA, remainder);
1190   
1191   // Call to DYNINSTrestore_misc
1192   words += generate_address(insn+words, REG_T10, dyn_restore, remainder);
1193   if (remainder)
1194     words += generate_lda(insn+words, REG_T10, REG_T10, remainder, true);
1195   words += generate_jump(insn+words, REG_T10, MD_JSR, REG_RA, remainder);
1196
1197   base += words * 4; return 0;
1198 }
1199
1200 static inline void
1201 generate_tramp_preamble(instruction *insn, Address src1,
1202                         Address dest, unsigned long& base) {
1203 //                      Address dest, unsigned& base) {
1204   // generate code to update the observed cost
1205   // a4 holds address, a3 gets loaded
1206
1207 //  unsigned words = 0; int obs_rem;
1208   unsigned long words = 0; int obs_rem;
1209   // load the current observed cost
1210   words += generate_address(insn+words, REG_T11, dest, obs_rem);
1211   words += generate_load(insn+words, REG_T10, REG_T11, obs_rem, dw_long);
1212
1213   // update the observed cost
1214   if ((src1 >= 0) && (src1 < MAX_IMM)) {
1215     // addl literal, REG_T10, REG_T10       (t10 += literal)
1216     words += generate_lit_operate(insn+words, REG_T10, src1, REG_T10,
1217                                   OP_ADDL, FC_ADDL);
1218   } else {
1219     // load literal into REG_T9
1220     int remainder;
1221     words += generate_address(insn+words, REG_T9, src1, remainder);
1222     if (remainder)
1223       words += generate_lda(insn+words, REG_T9, REG_T9, remainder, true);
1224
1225     // addl REG_T9, REG_T10, REG_T10       (t10 += t9)
1226     words += generate_operate(insn+words, REG_T10, REG_T9, REG_T10, OP_ADDL, FC_ADDL);
1227   }
1228
1229   // store new observed cost  
1230   // st REG_T10, obs_rem[REG_T11]
1231   words += generate_store(insn+words, REG_T10, REG_T11, obs_rem, dw_long);
1232   base += words * 4; 
1233   return;
1234 }
1235
1236
1237 // The value returned by emitA can be
1238 // 
1239 // ifOp: address to calculate branch
1240 // 
1241 // TODO -- if an offset is returned, it is the offset to the instruction
1242 //         where the branch occurs.  This offset cannot be used to
1243 //         calculate branches, the offset of the next instruction should
1244 //         be used.  The alpha uses the UPDATED pc for branches.
1245 // 
1246
1247 Address emitA(opCode op, Register src1, Register /*src2*/, Register dest,
1248              char *i, Address &base, bool /*noCost*/) {
1249
1250   //fprintf(stderr,"emitA(op=%d,src1=%d,src2=XX,dest=%d)\n",op,src1,dest);
1251
1252   instruction *insn = (instruction *) ((void*)&i[base]);
1253   assert(!((unsigned long)insn & (unsigned long)3));
1254
1255   switch (op) {
1256   case ifOp: {
1257     // beq src1
1258     // return address used to calculate branch offset
1259     assert(src1 < Num_Registers);
1260     // branch calculations use the updated pc
1261     unsigned long words = generate_branch(insn, src1, dest-4, OP_BEQ);
1262     // return offset of branch instruction
1263     base += words * 4; 
1264     return (base-4);
1265     }
1266   case branchOp: {
1267     generateBranchInsn(insn, dest-4);
1268     base += sizeof(instruction);
1269     return(base - sizeof(instruction));
1270     }
1271   case trampTrailer: {
1272     // dest is in words of offset and generateBranchInsn is bytes offset
1273     assert(!dest);
1274 //    unsigned words = generate_branch(insn, REG_ZERO, dest << 2, OP_BR);
1275     unsigned long words = generate_branch(insn, REG_ZERO, dest << 2, OP_BR);
1276     // return the offset of the branch instruction -- not the updated pc
1277     base += words * 4; 
1278     return (base-4);
1279     }
1280   case trampPreamble: {
1281     generate_tramp_preamble(insn, src1, dest, base);
1282     return(0);          // let's hope this is expected!
1283     }
1284   default:
1285     abort();            // unexpected op for this emit!
1286   }
1287 }
1288
1289 Register emitR(opCode op, Register src1, Register /*src2*/, Register dest,
1290              char *i, Address &base, bool /*noCost*/) {
1291
1292   //fprintf(stderr,"emitR(op=%d,src1=%d,src2=XX,dest=%d)\n",op,src1,dest);
1293
1294   instruction *insn = (instruction *) ((void*)&i[base]);
1295   assert(!((unsigned long)insn & (unsigned long)3));
1296
1297   switch (op) {
1298   case getRetValOp:
1299     {
1300       // Return value register v0 is the 12th register saved in the base tramp
1301       restoreRegister(insn,base,12,dest);
1302       return(dest);
1303     }
1304   case getParamOp:
1305     {
1306       if (src1 >5) assert(0);
1307       /*
1308        * We don't save the parameter registers unless we make a function call,
1309        * so we can read the values directly out of the registers.
1310        */
1311       unsigned long words =
1312           generate_operate(insn,REG_A0+src1,REG_A0+src1,dest,OP_BIS, FC_BIS);
1313       base += words * sizeof(instruction);
1314       return(dest);
1315     }
1316   default:
1317     abort();                    // unexpected op for this emit!
1318   }
1319   return(Null_Register);        // should never get here!
1320 }
1321
1322 void emitVload(opCode op, Address src1, Register, Register dest,
1323              char *i, Address &base, bool, int size=4)
1324 {
1325   instruction *insn = (instruction *) ((void*)&i[base]);
1326   assert(!((unsigned long)insn & (unsigned long)3));
1327
1328   if (op == loadConstOp) {
1329     // lda dest, src1 (LITERAL)     --> put the literal value of src1 into dest
1330     // it may take several instructions to do this
1331     assert(dest < Num_Registers);
1332     int remainder;
1333     unsigned long words = 0;
1334     // if the constant is a zero -- or it into place
1335     if (!src1) { 
1336       words = generate_operate(insn+words, REG_ZERO, REG_ZERO, 
1337                                (unsigned long) dest, OP_BIS, FC_BIS);
1338 //                             (unsigned) dest, OP_BIS, FC_BIS);
1339     } else {
1340 //      words = generate_address(insn, (unsigned) dest, src1, remainder);
1341       words = generate_address(insn, (unsigned long) dest, src1, remainder);
1342       if (remainder)
1343         words +=
1344 //        generate_lda(insn+words, (unsigned) dest, (unsigned) dest,
1345           generate_lda(insn+words, (unsigned long) dest, (unsigned long) dest,
1346                        remainder, true);
1347     }
1348     base += words * 4; return;
1349
1350   } else if (op ==  loadOp) {
1351         // ld? dest, [src1]             --> src1 is a literal
1352         // src1 = address to load
1353         // src2 = 
1354         // dest = register to load
1355         int remainder;
1356         unsigned long words = generate_address(insn, (unsigned long) dest, src1, remainder);
1357         if (size == 4) {
1358             words += generate_load(insn+words, (unsigned long) dest, 
1359                  (unsigned long) dest, remainder, dw_long);
1360         } else if (size == 8) {
1361             words += generate_load(insn+words, (unsigned long) dest, 
1362                  (unsigned long) dest, remainder, dw_quad);
1363         } else {
1364             abort();
1365         }
1366         base += words * 4; return;
1367     } else if (op ==  loadFrameRelativeOp) {
1368         unsigned long words = 0;
1369         // frame offset is negative of actual offset.
1370         long offset = (long) src1;
1371
1372         // the saved sp is 16 less than original sp (due to base tramp code)
1373         offset += 16;           
1374
1375         assert(ABS(offset) < 32767);
1376         words += generate_load(insn+words, (unsigned long) dest,  REG_SP,
1377                                112, dw_quad);
1378         assert(ABS(offset) < (1<<30));
1379         if (ABS(offset) > 32767) {
1380             Offset low = offset & 0xffff;
1381             offset -= SEXT_16(low);
1382             Offset high = (offset >> 16) & 0xffff;
1383             assert((Address)SEXT_16(low) +
1384              ((Address)SEXT_16(high)<<16) == src1);
1385
1386             words += generate_lda(insn+words, dest, dest, high, false);
1387             words += generate_load(insn+words, (unsigned long) dest,  dest,
1388                                low, dw_long);
1389         } else {
1390             words += generate_load(insn+words, (unsigned long) dest,  dest,
1391                                offset, dw_long);
1392         }
1393         base += words * 4; 
1394     } else if (op == loadFrameAddr) {
1395         unsigned long words = 0;
1396         // frame offset is signed.
1397         long offset = (long) src1;
1398
1399         // the saved sp is 16 less than original sp (due to base tramp code)
1400         offset += 16;           
1401
1402         // load fp into dest
1403         words += generate_load(insn+words, (unsigned long) dest,  REG_SP,
1404                                112, dw_quad);
1405
1406         assert(ABS(offset) < (1<<30));
1407         if (ABS(offset) > 32767) {
1408             Offset low = offset & 0xffff;
1409             offset -= SEXT_16(low);
1410             Offset high = (offset >> 16) & 0xffff;
1411             assert((Address)SEXT_16(low) +
1412              ((Address)SEXT_16(high)<<16) == src1);
1413
1414             // add high bits of offset
1415             words += generate_lda(insn+words, dest, dest, high, false);
1416             // now addd the low bits of the offset
1417             words += generate_lda(insn+words, dest, dest, low, true);
1418         } else {
1419             // addd the offset
1420             words += generate_lda(insn+words, dest, dest, offset, true);
1421         }
1422         base += words * 4; 
1423     } else {
1424         abort();       // unexpected op for this emit!
1425     }
1426 }
1427
1428 void emitVstore(opCode op, Register src1, Register src2, Address dest,
1429              char *i, Address &base, bool /* noCost */, int size=4)
1430 {
1431   instruction *insn = (instruction *) ((void*)&i[base]);
1432   assert(!((unsigned long)insn & (unsigned long)3));
1433
1434   if (op ==  storeOp) {
1435     // st? dest, [src1]
1436     // src1 = value to store
1437     // src2 = register to hold address
1438     // dest = address
1439     int remainder;
1440 //    unsigned words = generate_address(insn, (unsigned) src2, dest, remainder);
1441     unsigned long words = generate_address(insn, (unsigned long) src2, dest, remainder);
1442 //    words += generate_store(insn+words, (unsigned) src1, (unsigned) src2,
1443     if (size == 8) {
1444         words += generate_store(insn+words, (unsigned long) src1, 
1445             (unsigned long) src2, remainder, dw_quad);
1446     } else if (size == 4) {
1447         words += generate_store(insn+words, (unsigned long) src1, 
1448             (unsigned long) src2, remainder, dw_long);
1449     } else {
1450         abort();
1451     }
1452     base += words * 4; return;
1453   } else if (op ==  storeFrameRelativeOp) {
1454     // frame offset is signed.
1455     long offset = (long) dest;
1456
1457     // the saved sp is 16 less than original sp (due to base tramp code)
1458     offset += 16;               
1459
1460     assert(ABS(offset) < 32767);
1461     unsigned long words = 0;
1462     words += generate_load(insn+words, (unsigned long) src2,  REG_SP,
1463                                112, dw_quad);
1464     if (size == 8) {
1465         words += generate_store(insn+words, (unsigned long) src1, 
1466             (unsigned long) src2, offset, dw_quad);
1467     } else if (size == 4) {
1468         words += generate_store(insn+words, (unsigned long) src1, 
1469             (unsigned long) src2, offset, dw_long);
1470     } else {
1471         abort();
1472     }
1473     base += words * 4; return;
1474   } else {
1475       abort();       // unexpected op for this emit!
1476   }
1477 }
1478
1479 void emitVupdate(opCode op, RegValue /* src1 */, 
1480                             Register /*src2*/, Address /* dest */,
1481                             char *i, Address &base, bool /* noCost */)
1482 {
1483   instruction *insn = (instruction *) ((void*)&i[base]);
1484   assert(!((unsigned long)insn & (unsigned long)3));
1485
1486   if (op == updateCostOp) {
1487       return;
1488   } else {
1489       abort();       // unexpected op for this emit!
1490   }
1491 }
1492
1493 void emitV(opCode op, Register src1, Register src2, Register dest,
1494              char *i, Address &base, bool /*noCost*/, int size = 4)
1495 {
1496   //fprintf(stderr,"emitV(op=%d,src1=%d,src2=%d,dest=%d)\n",op,src1,src2,dest);
1497
1498     assert ((op!=branchOp) && (op!=ifOp) && 
1499             (op!=trampTrailer) && (op!=trampPreamble));         // !emitA
1500     assert ((op!=getRetValOp) && (op!=getParamOp));             // !emitR
1501     assert ((op!=loadOp) && (op!=loadConstOp));                 // !emitVload
1502     assert ((op!=storeOp));                                     // !emitVstore
1503     assert ((op!=updateCostOp));                                // !emitVupdate
1504
1505   instruction *insn = (instruction *) ((void*)&i[base]);
1506   assert(!((unsigned long)insn & (unsigned long)3));
1507
1508   data_width width;
1509   if (size == 4) {
1510       width = dw_long;
1511   } else if (size == 8) {
1512       width = dw_quad;
1513   } else {
1514       // should not happen
1515       abort();
1516   }
1517
1518   if (op == noOp) {
1519     unsigned long words = generate_nop(insn);
1520     base += words * 4; 
1521     return;
1522   } else if (op == loadIndirOp) {
1523     unsigned long words = generate_load(insn, dest, src1, 0, width);
1524     base += words * 4;
1525     return;
1526   } else if (op == storeIndirOp) {
1527     unsigned long words = generate_store(insn, src1, dest, 0, width);
1528     base += words * 4;
1529     return;
1530   } else {
1531     generate_integer_op(insn, src1, src2, dest, base, op);
1532     return;
1533   }
1534 }
1535
1536
1537 /************************************************************************
1538  * void restore_original_instructions(process* p, instPoint* ip)
1539 ************************************************************************/
1540
1541 void
1542 restore_original_instructions(process* p, instPoint* ip) {
1543   Address addr = ip->addr;
1544   p->writeTextWord((caddr_t)addr, ip->originalInstruction.raw);
1545   addr += sizeof(instruction);
1546 }
1547
1548 // The only non read only registers are those that are allocated - t0...t7
1549
1550 bool registerSpace::readOnlyRegister(Register reg_number) {
1551   if ((reg_number >= REG_T0) && (reg_number <= REG_T7))
1552     return false;
1553   else 
1554     return true;
1555 }
1556
1557 //
1558 // return cost in cycles of executing at this point.  This is the cost
1559 //   of the base tramp if it is the first at this point or 0 otherwise.
1560 //
1561 // This was in inst.C, but the base tramp cost is machine dependent
1562 // 
1563 int getPointCost(process *proc, const instPoint *point)
1564 {
1565   if (proc->baseMap.defines(point)) {
1566     return(0);
1567   } else {
1568     //  1 : decrement stack
1569     //  1 : push ra onto the stack
1570     //  3 : bsr to DYNINSTsave_temp (1 for call, 2 cycle branch penalty)
1571     // 14 : cost of DYNINSTsave_temp
1572     //  2 : empty nop slots
1573     //  3 : bsr to DYNINSTrestore_temp (1 for call, 2 cycle branch penalty)
1574     // 14 : cost of DYNINSTrestore_temp
1575     //  1 : load ra from stack
1576     //  1 : increment stack
1577     //  1 : slot for relocated instruction
1578     //  1 : decrement stack
1579     //  1 : push ra onto the stack
1580     //  3 : bsr to DYNINSTsave_temp (1 for call, 2 cycle branch penalty)
1581     // 14 : cost of DYNINSTsave_temp
1582     //  2 : empty nop slots
1583     //  3 : bsr to DYNINSTrestore_temp (1 for call, 2 cycle branch penalty)
1584     // 14 : cost of DYNINSTrestore_temp
1585     //  1 : load ra from stack
1586     //  1 : increment stack
1587     //  1 : return
1588     return(81);
1589   }
1590 }
1591
1592 dictionary_hash<string, unsigned> funcFrequencyTable(string::hash);
1593
1594 void initDefaultPointFrequencyTable()
1595 {
1596     FILE *fp;
1597     float value;
1598     char name[512];
1599
1600     funcFrequencyTable["main"] = 1;
1601     funcFrequencyTable["DYNINSTsampleValues"] = 1;
1602     funcFrequencyTable[EXIT_NAME] = 1;
1603
1604     // try to read file.
1605     fp = fopen("freq.input", "r");
1606     if (!fp) {
1607         return;
1608     } else {
1609         printf("found freq.input file\n");
1610     }
1611     while (!feof(fp)) {
1612         fscanf(fp, "%s %f\n", name, &value);
1613         funcFrequencyTable[name] = (int) value;
1614         printf("adding %s %f\n", name, value);
1615     }
1616     fclose(fp);
1617 }
1618
1619
1620
1621 // unsigned findAndInstallBaseTramp(process *proc, 
1622 trampTemplate *findAndInstallBaseTramp(process *proc, 
1623                                        instPoint *&location,
1624                                        returnInstance *&retInstance, 
1625                                        bool trampRecursiveDesired,
1626                                        bool /* noCost */,
1627                                        bool& /*deferred*/)
1628 {
1629   trampTemplate *ret;
1630   process *globalProc;
1631   retInstance = NULL;
1632
1633 #ifdef notdef
1634     if (nodePseudoProcess && (proc->symbols == nodePseudoProcess->symbols)){
1635         globalProc = nodePseudoProcess;
1636         // logLine("findAndInstallBaseTramp global\n");
1637     } else {
1638         globalProc = proc;
1639     }
1640 #endif
1641     globalProc = proc;
1642
1643     if (!globalProc->baseMap.defines(location)) {
1644         ret = new trampTemplate;
1645         installBaseTramp(location, globalProc, *ret);
1646         instruction *insn = new instruction;
1647
1648         Address pointAddr = location->addr;
1649         Address baseAddress;
1650         if (proc->getBaseAddress(location->image_ptr, baseAddress)) {
1651             pointAddr += baseAddress;
1652         }
1653         generateBranchInsn(insn, ret->baseAddr - (pointAddr+4));
1654         globalProc->baseMap[location] = ret;
1655         retInstance = new returnInstance(1, (instruction *)insn,sizeof(instruction), 
1656             pointAddr, sizeof(instruction)); 
1657     } else {
1658         ret = globalProc->baseMap[location];
1659     }
1660       
1661     return(ret);
1662 }
1663
1664 /*
1665  * Install a single tramp.
1666  *
1667  */
1668 void installTramp(instInstance *inst, char *code, int codeSize)
1669 {
1670     totalMiniTramps++;
1671     insnGenerated += codeSize/sizeof(int);
1672
1673     // TODO cast
1674     (inst->proc)->writeDataSpace((caddr_t)inst->trampBase, codeSize, code);
1675
1676     // overwrite branches for skipping instrumentation
1677     trampTemplate *base = inst->baseInstance;
1678     if (inst->when == callPreInsn && base->prevInstru == false) {
1679         base->cost += base->prevBaseCost;
1680         base->prevInstru = true;
1681         generateNoOp(inst->proc, base->baseAddr + base->skipPreInsOffset);
1682     } else if (inst->when == callPostInsn && base->postInstru == false) {
1683         base->cost += base->postBaseCost;
1684         base->postInstru = true;
1685         generateNoOp(inst->proc, base->baseAddr + base->skipPostInsOffset);
1686     }
1687 }
1688
1689
1690 float getPointFrequency(instPoint *point)
1691 {
1692
1693     pd_Function *func;
1694
1695     if (point->callee)
1696         func = point->callee;
1697     else
1698         func = point->func;
1699
1700     if (!funcFrequencyTable.defines(func->prettyName())) {
1701       if (0 /*func->isLibTag()*/) {
1702         return(100);
1703       } else {
1704         return(250);
1705       }
1706     } else {
1707       return (funcFrequencyTable[func->prettyName()]);
1708     }
1709 }
1710
1711 bool isReturn(const instruction insn) {
1712     return ((insn.mem_jmp.opcode == OP_MEM_BRANCH) &&
1713             (insn.mem_jmp.ext == MD_RET));
1714 }
1715
1716 // Borrowed from the POWER version
1717 bool isReturnInsn(const image *owner, Address adr, bool &lastOne)
1718 {
1719   instruction insn;
1720
1721   insn.raw = owner->get_instruction(adr);
1722   // need to know if this is really the last return.
1723   //    for now assume one return per function - jkh 4/12/96
1724   lastOne = true;
1725   return isReturn(insn);
1726 }
1727
1728 bool isCallInsn(const instruction i) {
1729   return (isBsr(i) || isJsr(i));
1730 }
1731
1732 bool pd_Function::findInstPoints(const image *owner) 
1733 {  
1734   Address adr = addr();
1735   instruction instr;
1736   instruction instr2;
1737   long gpValue; // gp needs signed operations
1738   bool gpKnown = false;
1739
1740   frame_size = 0;
1741   // normal linkage on alphas is that the first two instructions load gp.
1742   //   In this case, many functions jump past these two instructions, so
1743   //   we put the inst point at the third instruction.
1744   //   However, system call libs don't always follow this rule, so we
1745   //   look for a load of gp in the first two instructions.
1746   instr.raw = owner->get_instruction(adr);
1747   instr2.raw = owner->get_instruction(adr+4);
1748   if ((instr.mem.opcode == OP_LDAH) && (instr.mem.ra == REG_GP) &&
1749       (instr2.mem.opcode == OP_LDA) && (instr2.mem.ra == REG_GP)) {
1750       // compute the value of the gp
1751       gpKnown = true;
1752       gpValue = ((long) adr) + (SEXT_16(instr.mem.disp)<<16) + instr2.mem.disp;
1753       adr += 8;
1754   }
1755
1756   instr.raw = owner->get_instruction(adr);
1757   if (!IS_VALID_INSN(instr)) {
1758     return false;
1759   }
1760
1761   funcEntry_ = new instPoint(this, instr, owner, adr, true,functionEntry);
1762   assert(funcEntry_);
1763
1764   // perform simple data flow tracking on t12 within a basic block.
1765   Address t12Value;
1766   bool t12Known = false;
1767   while (true) {
1768     instr.raw = owner->get_instruction(adr);
1769
1770     bool done;
1771
1772     // check for lda $sp,n($sp) to guess frame size
1773     if (!frame_size && ((instr.raw & 0xffff0000) == 0x23de0000)) {
1774         // lda $sp,n($sp)
1775         frame_size = -((short) (instr.raw & 0xffff));
1776         if (frame_size < 0) {
1777             // we missed the setup and found the cleanup
1778             frame_size = 0;
1779         }
1780     }
1781
1782     // check for return insn and as a side affect decide if we are at the
1783     //   end of the function.
1784     if (isReturnInsn(owner, adr, done)) {
1785       // define the return point
1786       // check to see if adr-8 is ldq fp, xx(sp) or ldq sp, xx(sp), if so 
1787       // use it as the
1788       // address since it will ensure the activation record is still active.
1789       // Gcc uses a frame pointer, on others only sp is used.
1790       instruction frameRestInsn;
1791       frameRestInsn.raw = owner->get_instruction(adr-8);
1792       if (((frameRestInsn.raw & 0xffff0000) == 0xa5fe0000) ||
1793           ((frameRestInsn.raw & 0xffff0000) == 0x23de0000)) {
1794           Address tempAddr = adr - 8;
1795           funcReturns.push_back(new instPoint(this,frameRestInsn,
1796                                               owner,tempAddr,false,functionExit));
1797       } else {
1798           funcReturns.push_back(new instPoint(this,instr,owner,adr,false,functionExit));
1799       }
1800
1801       // see if this return is the last one 
1802       if (done) return true;
1803     } else if (isCallInsn(instr)) {
1804       // define a call point
1805       instPoint *point = new instPoint(this, instr, owner, adr, false,callSite);
1806
1807       if (isJsr(instr)) {
1808           Address destAddr = 0;
1809           if ((instr.mem_jmp.rb == REG_T12) && t12Known) {
1810               destAddr = t12Value;
1811           }
1812           point->callIndirect = true;
1813           // this is the indirect address
1814           point->callee = (pd_Function *) destAddr;             
1815       } else {
1816           point->callIndirect = false;
1817           point->callee = NULL;
1818       }
1819       calls.push_back(point);
1820       t12Known = false;
1821     } else if (isJmpType(instr) || isBranchType(instr)) {
1822       // end basic block, kill t12
1823       t12Known = false;
1824     } else if ((instr.mem.opcode == OP_LDQ) && (instr.mem.ra == REG_T12) &&
1825                (instr.mem.rb = REG_GP)) {
1826       // intruction is:  ldq t12, disp(gp)
1827       if (gpKnown) {
1828           t12Value = gpValue + instr.mem.disp;
1829           t12Known = true;
1830       }
1831     }
1832
1833     // now do the next instruction
1834     adr += 4;
1835
1836    }
1837 }
1838
1839 //
1840 // Each processor may have a different heap layout.
1841 //   So we make this processor specific.
1842 //
1843 // find all DYNINST symbols that are data symbols
1844 bool process::heapIsOk(const vector<sym_data> &find_us) {
1845   bool err;
1846   Symbol sym;
1847   string str;
1848   Address addr;
1849   Address instHeapStart;
1850
1851   // find the main function
1852   // first look for main or _main
1853   if (!((mainFunction = findOneFunction("main")) 
1854         || (mainFunction = findOneFunction("_main")))) {
1855      string msg = "Cannot find main. Exiting.";
1856      statusLine(msg.string_of());
1857      showErrorCallback(50, msg);
1858      return false;
1859   }
1860   
1861   for (unsigned long i=0; i<find_us.size(); i++) {
1862     addr = findInternalAddress(find_us[i].name, false, err);
1863     //printf("looking for %s\n", find_us[i].name.string_of());
1864     if (err) {
1865         string msg;
1866         msg = string("Cannot find ") + str + string(". Exiting");
1867         statusLine(msg.string_of());
1868         showErrorCallback(50, msg);
1869         return false;
1870     }
1871   }
1872
1873 #if 0
1874   string ghb = "_DYNINSTtext";
1875   addr = findInternalAddress(ghb, false, err);
1876   if (err) {
1877       string msg;
1878       msg = string("Cannot find _DYNINSTtext") + string(". Exiting");
1879       statusLine(msg.string_of());
1880       showErrorCallback(50, msg);
1881   }
1882   instHeapStart = addr;
1883
1884   string hd = "DYNINSTdata";
1885   addr = findInternalAddress(hd, true, err);
1886   if (err) {
1887       string msg;
1888       msg = string("Cannot find DYNINSTdata") + string(". Exiting");
1889       statusLine(msg.string_of());
1890       showErrorCallback(50, msg);
1891       return false;
1892   }
1893   instHeapStart = addr;
1894 #endif
1895   return true;
1896 }
1897
1898 void emitImm(opCode op, Register src1, RegValue src2imm, Register dest, 
1899              char *i, Address &base, bool /* noCost */)
1900 {
1901   instruction *insn = (instruction *) ((void*)&i[base]);
1902   assert(!((unsigned long)insn & (unsigned long)3));
1903   generate_integer_op(insn, src1, src2imm, dest, base, op, true);
1904   return;
1905 }
1906
1907 Register
1908 emitFuncCall(opCode /* op */, 
1909              registerSpace *rs,
1910              char *i, Address &base, 
1911              const vector<AstNode *> &operands,
1912              const string &callee, process *proc, bool noCost,
1913              const function_base *calleebase)
1914 {
1915   vector <Register> srcs;
1916
1917   // First, generate the parameters
1918   for (unsigned u = 0; u < operands.size(); u++)
1919     srcs.push_back(operands[u]->generateCode(proc, rs, i , base, false, false));
1920
1921   // put parameters in argument registers
1922   // register move is "bis src, src, dest"  (bis is logical or)
1923   // save and restore the values currently in the argument registers
1924   //  unsigned long words = 0;
1925   Address addr;
1926   bool err;
1927   void cleanUpAndExit(int status);
1928
1929   if (calleebase)
1930        addr = calleebase->getEffectiveAddress(proc);
1931   else {
1932        addr = proc->findInternalAddress(callee, false, err);
1933        if (err) {
1934             function_base *func_b = proc->findOneFunction(callee);
1935             if (!func_b) {
1936                  ostrstream os(errorLine, 1024, ios::out);
1937                  os << "Internal error: unable to find addr of " << callee << endl;
1938                  logLine(errorLine);
1939                  showErrorCallback(80, (const char *) errorLine);
1940                  P_abort();
1941             }
1942             addr = func_b->addr();
1943        }
1944   }
1945
1946   int remainder;
1947   instruction *insn = (instruction *) ((void*)&i[base]);
1948   Address dyn_save;
1949   Address dyn_restore;
1950
1951   if (!skipSaveCalls) {
1952       function_base *fun_save = proc->findOneFunction("DYNINSTsave_misc");
1953       function_base *fun_restore = proc->findOneFunction("DYNINSTrestore_misc");
1954       assert(fun_save && fun_restore);
1955       dyn_save = fun_save->addr();
1956       dyn_restore = fun_restore->addr();
1957
1958       Symbol info;
1959       Address baseAddr;
1960       proc->getSymbolInfo("DYNINSTsave_misc", info, baseAddr);
1961
1962       dyn_save += baseAddr;
1963       dyn_restore += baseAddr;
1964
1965       // save the current values in v0, a0..a5, pv, at, gp
1966       // Call to DYNINSTsave_misc
1967       base += (4* generate_address(insn, REG_T10, dyn_save, remainder));
1968       if (remainder) {
1969           insn = (instruction *) ((void*)&i[base]);
1970           base += (4 * generate_lda(insn, REG_T10, REG_T10, remainder, true));
1971       }
1972       insn = (instruction *) ((void*)&i[base]);
1973       base += (4 * generate_jump(insn, REG_T10, MD_JSR, REG_RA, remainder));
1974
1975       //  words += (base - temp_base) / sizeof(insn);
1976       //  base = temp_base;
1977   }
1978
1979   for (unsigned u=0; u<srcs.size(); u++){
1980     if (u >= 5) {
1981          string msg = "Too many arguments to function call in instrumentation code: only 5 arguments can be passed on the sparc architecture.\n";
1982          fprintf(stderr, msg.string_of());
1983          showErrorCallback(94,msg);
1984          cleanUpAndExit(-1);
1985     }
1986     insn = (instruction *) ((void*)&i[base]);
1987     base += (4 * generate_operate(insn, srcs[u], srcs[u], u+REG_A0, 
1988                 OP_BIS, FC_BIS));
1989   }
1990
1991   // Set the value of  pv/t12/r27
1992   // I have not found any documentation on this
1993   // But the alpha appears to put the callee's address in this register
1994   // this register must be saved and restored
1995
1996   // Jump to the function
1997   insn = (instruction *) ((void*)&i[base]);
1998   base += (4 *generate_address(insn, REG_PV, addr, remainder));
1999   if (remainder)
2000     {
2001       insn = (instruction *) ((void*)&i[base]);
2002       base += (4 * generate_lda(insn, REG_PV, REG_PV, remainder, true));
2003     }
2004
2005   // TODO -- clear other argument registers ?
2006   insn = (instruction *) ((void*)&i[base]);
2007   base += (4 * generate_jump(insn, REG_PV, MD_JSR, REG_RA, remainder));
2008   
2009   if (!skipSaveCalls) {
2010       // Call to DYNINSTrestore_misc
2011       insn = (instruction *) ((void*)&i[base]);
2012       base += (4 * generate_address(insn, REG_T10, dyn_restore, remainder));
2013       if (remainder) {
2014           insn = (instruction *) ((void*)&i[base]);
2015           base += (4 * generate_lda(insn, REG_T10, REG_T10, remainder, true));
2016       }
2017       insn = (instruction *) ((void*)&i[base]);
2018       base += ( 4 * generate_jump(insn, REG_T10, MD_JSR, REG_RA, remainder));
2019   }
2020
2021   Register dest = rs->allocateRegister(i, base, noCost);
2022
2023   insn = (instruction *) ((void*)&i[base]);
2024
2025   // or v0,v0,dest
2026   generate_operate(insn,REG_V0,REG_V0,dest,OP_BIS,FC_BIS);
2027   base+= sizeof(instruction);
2028
2029   for (unsigned u=0; u<srcs.size(); u++){
2030     rs->freeRegister(srcs[u]);
2031   }
2032
2033   return dest;
2034 }
2035
2036 bool returnInstance::checkReturnInstance(const vector<Address> & /* adr */, 
2037                                          u_int & /* index */) {
2038     return true;
2039 }
2040  
2041 void returnInstance::installReturnInstance(process *proc) {
2042     proc->writeTextSpace((caddr_t)addr_, instSeqSize, (caddr_t) instructionSeq); 
2043         installed = true;
2044 }
2045
2046 void returnInstance::addToReturnWaitingList(Address /* pc */, 
2047                                             process*  /* proc */) 
2048 {
2049     P_abort();
2050 }
2051
2052 void generateBreakPoint(instruction &insn)
2053 {
2054   insn.raw = BREAK_POINT_INSN;
2055 }
2056
2057 void generateIllegalInsn(instruction &insn) { // instP.h
2058    insn.raw = 0;
2059 }
2060
2061 // findCallee: returns false unless callee is already set in instPoint
2062 // dynamic linking not implemented on this platform
2063 bool process::findCallee(instPoint &instr, function_base *&target){
2064
2065     if((target = (function_base *)instr.iPgetCallee())) {
2066        return true;
2067     }
2068     if (instr.callIndirect && instr.callee) {
2069         // callee contains the address in the mutatee
2070         // read the contents of the address
2071         Address dest;
2072         if (!readDataSpace((caddr_t)(instr.callee), sizeof(Address),
2073             (caddr_t)&(dest),true)) {
2074             return false;
2075         }
2076         // now lookup the funcation
2077         target = findFuncByAddr(dest);
2078         if (target) return true;
2079     }
2080     return false;
2081 }
2082
2083 bool process::replaceFunctionCall(const instPoint *point,
2084                                   const function_base *newFunc) {
2085   // Must be a call site
2086     if (point->ipType != callSite)
2087       return false;
2088     
2089     // Cannot already be instrumented with a base tramp
2090     if (baseMap.defines(point))
2091         return false;
2092     instruction newInsn;
2093     if (newFunc == NULL) {      // Replace with a NOOP
2094       generateNOOP(&newInsn);
2095     } else {                    // Replace with a new call instruction
2096       generateBSR(&newInsn, newFunc->addr()+sizeof(instruction)-point->addr);
2097     }
2098     
2099     writeTextSpace((caddr_t)point->addr, sizeof(instruction), &newInsn);
2100     
2101     return true;
2102 }
2103
2104 static const Address lowest_addr = 0x00400000;
2105 void inferiorMallocConstraints(Address near, Address &lo, Address &hi,
2106                                inferiorHeapType type)
2107 {
2108   if (near)
2109     {
2110       // Avoid wrapping issues
2111       if (near < lowest_addr + MAX_BRANCH)
2112         lo = lowest_addr;
2113       else
2114         lo = near - MAX_BRANCH;
2115       hi = near + MAX_BRANCH;
2116     }
2117   else // near == 0
2118     {
2119       lo = lowest_addr;
2120     }
2121 }
2122
2123 void inferiorMallocAlign(unsigned &size)
2124 {
2125   // quadword-aligned (stack alignment)
2126   unsigned align = 16;
2127   if (size % align) size = ((size/align)+1)*align;
2128 }
2129
2130 // Emit code to jump to function CALLEE without linking.  (I.e., when
2131 // CALLEE returns, it returns to the current caller.)
2132 void emitFuncJump(opCode op, 
2133                   char *i, Address &base, 
2134                   const function_base *callee, process *proc)
2135 {
2136
2137     Address addr;
2138     int remainder;
2139     unsigned long count;
2140
2141     assert(op == funcJumpOp);
2142
2143     addr = callee->getEffectiveAddress(proc);
2144     Address addr2 = ((function_base *)callee)->getAddress(0);
2145     instruction *insn = (instruction *) ((void*)&i[base]);
2146     count = 0;
2147
2148     // Cleanup stack state from tramp preamble
2149
2150     // call DYNINSTrestore_temp
2151     Symbol info;
2152     Address baseAddr;
2153     function_base *fun_restore = proc->findOneFunction("DYNINSTrestore_temp");
2154     proc->getSymbolInfo("DYNINSTrestore_temp", info, baseAddr);
2155     assert(fun_restore);
2156     Address dyn_restore = fun_restore->addr() + baseAddr;
2157
2158     callAbsolute(insn, count, dyn_restore);
2159
2160     // load ra from the stack
2161     count += generate_load(&insn[count], REG_RA, REG_SP, 0, dw_quad);
2162
2163     // load GP from the stack
2164     count += generate_load(&insn[count], REG_GP, REG_SP, 8, dw_quad);
2165
2166     // increment stack by 16
2167     count += generate_lda(&insn[count], REG_SP, REG_SP, 16, true);
2168
2169     // save gp and ra in special location
2170     // **** Warning this fails in the case of replacing a mutually recursive
2171     //    function
2172     Address saveArea = inferiorMalloc(proc, 2*sizeof(long), dataHeap, 0);
2173
2174     count += generate_address(&insn[count], REG_T12, saveArea, remainder);
2175     count += generate_store(&insn[count], REG_GP, REG_T12, remainder, 
2176         dw_quad); 
2177
2178     count += generate_store(&insn[count], REG_RA, REG_T12, 
2179         remainder+sizeof(long), dw_quad);
2180
2181     // calling convention seems to expect t12 to contain the address of the
2182     //    suboutine being called, so we use t12 to build the address
2183     count += generate_address(&insn[count], REG_T12, addr, remainder);
2184     if (remainder)
2185         count += generate_lda(&insn[count], REG_T12, REG_T12, remainder, true);
2186     count += generate_jump(&insn[count], REG_T12, MD_JSR, REG_RA, remainder);
2187
2188     count += generate_nop(&insn[count]);
2189
2190     // back after function, restore everything
2191     count += generate_address(&insn[count], REG_RA, saveArea, remainder);
2192     count += generate_load(&insn[count], REG_GP, REG_RA, remainder, 
2193         dw_quad); 
2194
2195     count += generate_load(&insn[count], REG_RA, REG_RA, 
2196         remainder+sizeof(long), dw_quad);
2197     count += generate_jump(&insn[count], REG_RA, MD_JMP, REG_ZERO, remainder);
2198     count += generate_nop(&insn[count]);
2199
2200     base += count * sizeof(instruction);
2201 }
2202
2203 #ifdef BPATCH_LIBRARY
2204 /*
2205    terminate execution of a process
2206  */
2207 bool process::terminateProc_()
2208 {
2209     long flags = PRFS_KOLC;
2210     if (ioctl (proc_fd, PIOCSSPCACT, &flags) < 0)
2211         return false;
2212
2213     // just to make sure it is dead
2214     kill(getPid(), 9);
2215
2216     Exited();
2217
2218     return true;
2219 }
2220 #endif
2221
2222 void emitLoadPreviousStackFrameRegister(Address, Register,
2223                                         char *, Address &, int, bool){
2224   assert(0);
2225 }
2226  
2227 #ifndef BPATCH_LIBRARY
2228 bool process::isDynamicCallSite(instPoint *callSite){
2229   function_base *temp;
2230   if(!findCallee(*(callSite),temp)){
2231     return true;
2232   }
2233   return false;
2234 }
2235  
2236 bool process::MonitorCallSite(instPoint *callSite){
2237   return false;
2238 }
2239 #endif
2240
2241 bool deleteBaseTramp(process *proc,instPoint* location,
2242                      instInstance* instance)
2243 {
2244         cerr << "WARNING : deleteBaseTramp is unimplemented "
2245              << "(after the last instrumentation deleted)" << endl;
2246         return false;
2247 }
2248
2249 #ifdef BPATCH_LIBRARY
2250 /*
2251  * createInstructionInstPoint
2252  *
2253  * Create a BPatch_point instrumentation point at the given address, which
2254  * is guaranteed not be one of the "standard" inst points.
2255  *
2256  * proc         The process in which to create the inst point.
2257  * address      The address for which to create the point.
2258  */
2259 BPatch_point *createInstructionInstPoint(process *proc, void *address,
2260                                          BPatch_point** alternative)
2261 {
2262     int i;
2263
2264     function_base *func = proc->findFuncByAddr((Address)address);
2265
2266     if (!isAligned((Address)address))
2267         return NULL;
2268
2269     instruction instr;
2270     proc->readTextSpace(address, sizeof(instruction), &instr.raw);
2271
2272     pd_Function* pointFunction = (pd_Function*)func;
2273     Address pointImageBase = 0;
2274     image* pointImage = pointFunction->file()->exec();
2275     proc->getBaseAddress((const image*)pointImage,pointImageBase);
2276     Address pointAddress = (Address)address-pointImageBase;
2277
2278     instPoint *newpt = new instPoint(pointFunction,
2279                                     (const instructUnion &) instr,
2280                                     (const image *) NULL, // image * - ignored
2281                                     (Address &)pointAddress,
2282                                     false, // bool delayOk - ignored
2283                                     otherPoint);
2284
2285     pointFunction->addArbitraryPoint(newpt,NULL);
2286
2287
2288     return proc->findOrCreateBPPoint(NULL, newpt, BPatch_instruction);
2289 }
2290
2291 #include "BPatch_point.h"
2292 #include "BPatch_snippet.h"
2293
2294 int BPatch_point::getDisplacedInstructions(int maxSize, void *insns)
2295 {
2296     if (maxSize >= sizeof(instruction))
2297         memcpy(insns, &point->originalInstruction.raw, sizeof(instruction));
2298
2299     return sizeof(instruction);
2300 }
2301
2302 #endif
2303
2304 // needed in metric.C
2305 bool instPoint::match(instPoint *p)
2306 {
2307   if (this == p)
2308     return true;
2309   
2310   // should we check anything else?
2311   if (addr == p->addr)
2312     return true;
2313   
2314   return false;
2315 }