Update copyright to LGPL on all files
[dyninst.git] / dyninstAPI / src / inst-sparc.C
1 /*
2  * Copyright (c) 1996-2009 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  * By your use of Paradyn, you understand and agree that we (or any
12  * other person or entity with proprietary rights in Paradyn) are
13  * under no obligation to provide either maintenance services,
14  * update services, notices of latent defects, or correction of
15  * defects for Paradyn.
16  * 
17  * This library is free software; you can redistribute it and/or
18  * modify it under the terms of the GNU Lesser General Public
19  * License as published by the Free Software Foundation; either
20  * version 2.1 of the License, or (at your option) any later version.
21  * 
22  * This library is distributed in the hope that it will be useful,
23  * but WITHOUT ANY WARRANTY; without even the implied warranty of
24  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
25  * Lesser General Public License for more details.
26  * 
27  * You should have received a copy of the GNU Lesser General Public
28  * License along with this library; if not, write to the Free Software
29  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
30  */
31
32 // $Id: inst-sparc.C,v 1.204 2008/05/08 21:52:24 legendre Exp $
33
34 #include "dyninstAPI/src/inst-sparc.h"
35
36 #include "dyninstAPI/src/rpcMgr.h"
37 #include "dyninstAPI/src/instPoint.h"
38 #include "dyninstAPI/src/multiTramp.h"
39 #include "dyninstAPI/src/miniTramp.h"
40 #include "dyninstAPI/src/baseTramp.h"
41 #include "dyninstAPI/src/InstrucIter.h"
42 #include "dyninstAPI/src/registerSpace.h"
43
44 #include "dyninstAPI/src/dyn_thread.h" // get_index
45
46 #include "dyninstAPI/src/ast.h"
47 #include "dyninstAPI/h/BPatch.h"
48
49 #include "dyninstAPI/src/addressSpace.h"
50
51 #include "dyninstAPI/h/BPatch_memoryAccess_NP.h"
52
53 /****************************************************************************/
54 /****************************************************************************/
55 /****************************************************************************/
56
57 static dictionary_hash<std::string, unsigned> funcFrequencyTable(::Dyninst::stringhash);
58
59
60 /****************************************************************************/
61 /****************************************************************************/
62 /****************************************************************************/
63 #if 0
64 Register
65 emitOptReturn(instruction i, Register src, char *insn, Address &base, 
66               bool noCost, const instPoint *location,
67               bool for_multithreaded) {
68     
69     unsigned instr = i.raw;
70     registerSpace *rs = NULL;
71
72     cout << "Handling a special case for optimized return value." << endl;
73
74     assert(((instr&0x3e000000)>>25) <= 16);
75
76     if ((instr&0x02000)>>13)
77         emitImm(plusOp, (instr&0x07c000)>>14, instr&0x01fff,
78                 ((instr&0x3e000000)>>25)+16, insn, base, noCost, rs);
79     else
80         (void) emitV(plusOp, (instr&0x07c000)>>14, instr&0x01fff,
81              ((instr&0x3e000000)>>25)+16, insn, base, noCost);
82     
83     return emitR(getSysRetValOp, 0, 0, src, insn, base, noCost, location,
84                  for_multithreaded);
85 }
86 #endif
87 /****************************************************************************/
88 /****************************************************************************/
89 /****************************************************************************/
90
91 //
92 // initDefaultPointFrequencyTable - define the expected call frequency of
93 //    procedures.  Currently we just define several one shots with a
94 //    frequency of one, and provide a hook to read a file with more accurate
95 //    information.
96 //
97 void initDefaultPointFrequencyTable()
98 {
99     FILE *fp;
100     float value;
101     char name[512];
102
103     funcFrequencyTable["main"] = 1;
104     funcFrequencyTable["DYNINSTsampleValues"] = 1;
105     funcFrequencyTable[EXIT_NAME] = 1;
106
107     // try to read file.
108     fp = fopen("freq.input", "r");
109     if (!fp) {
110         return;
111     } else {
112         bperr("found freq.input file\n");
113     }
114     while (!feof(fp)) {
115         fscanf(fp, "%s %f\n", name, &value);
116         funcFrequencyTable[name] = (int) value;
117         bperr("adding %s %f\n", name, value);
118     }
119     fclose(fp);
120 }
121
122 /****************************************************************************/
123 /****************************************************************************/
124 /****************************************************************************/
125
126 /*
127  * Get an estimate of the frequency for the passed instPoint.  
128  *    This is not (always) the same as the function that contains the point.
129  * 
130  *  The function is selected as follows:
131  *
132  *  If the point is an entry or an exit return the function name.
133  *  If the point is a call and the callee can be determined, return the called
134  *     function.
135  *  else return the funcation containing the point.
136  *
137  *  WARNING: This code contins arbitray values for func frequency (both user 
138  *     and system).  This should be refined over time.
139  *
140  * Using 1000 calls sec to be one SD from the mean for most FPSPEC apps.
141  *      -- jkh 6/24/94
142  *
143  */
144 float getPointFrequency(instPoint *point)
145 {
146
147     int_function *func = point->findCallee();
148     if (!func)
149         func = point->func();
150     
151     if (!funcFrequencyTable.defines(func->prettyName().c_str())) {
152         // Changing this value from 250 to 100 because predictedCost was
153         // too high - naim 07/18/96
154         return(100); 
155         
156     } else {
157         return (funcFrequencyTable[func->prettyName().c_str()]);
158     }
159 }
160
161 /****************************************************************************/
162 /****************************************************************************/
163 /****************************************************************************/
164
165 //
166 // return cost in cycles of executing at this point.  This is the cost
167 //   of the base tramp if it is the first at this point or 0 otherwise.
168 //
169 int instPoint::getPointCost()
170 {
171    unsigned worstCost = 0;
172    for (unsigned i = 0; i < instances.size(); i++) {
173        if (instances[i]->multi()) {
174            if (instances[i]->multi()->usesTrap()) {
175               // Stop right here
176               // Actually, probably don't want this if the "always
177               // delivered" instrumentation happens
178               return 9000; // Estimated trap cost
179           }
180           else {
181               // Base tramp cost if we're first at point, otherwise
182               // free (someone else paid)
183               // Which makes no sense, since we're talking an entire instPoint.
184               // So if there is a multitramp hooked up we use the base tramp cost.
185               worstCost = 70; // Magic constant from before time
186           }
187       }
188       else {
189           // No multiTramp, so still free (we're not instrumenting here).
190       }
191   }
192   return worstCost;
193 }
194
195 unsigned baseTramp::getBTCost() {
196     return 70; // Need to dynamically configure!
197 }
198
199 /****************************************************************************/
200 /****************************************************************************/
201 /****************************************************************************/
202
203 void registerSpace::initialize32() { 
204     static bool done = false;
205     if (done) return;
206     done = true;
207     // registers 8 to 15: out registers 
208     // registers 16 to 22: local registers
209     Register deadList[10] = { 16, 17, 18, 19, 20, 21, 22, 23};
210     unsigned dead_reg_count = 8;
211
212     pdvector<registerSlot *> registers;
213     for (unsigned i = 0; i < dead_reg_count; i++) {
214         char buf[128];
215         sprintf(buf, "r%d", deadList[i]);
216         registers.push_back(new registerSlot(deadList[i],
217                                              buf,
218                                              false,
219                                              registerSlot::deadAlways,
220                                              registerSlot::GPR));
221     }
222     registerSpace::createRegisterSpace(registers);
223 }
224
225 void registerSpace::initialize() {
226     initialize32();
227 }
228
229
230 /****************************************************************************/
231 /****************************************************************************/
232 /****************************************************************************/
233
234 void emitImm(opCode op, Register src1, RegValue src2imm, Register dest, 
235              codeGen &gen, bool noCost, registerSpace *)
236 {
237     RegValue op3 = -1;
238     int result = -1;
239     switch (op) {
240         // integer ops
241     case plusOp:
242         op3 = ADDop3;
243         instruction::generateImm(gen, op3, src1, src2imm, dest);
244         break;
245         
246     case minusOp:
247         op3 = SUBop3;
248         instruction::generateImm(gen, op3, src1, src2imm, dest);
249         break;
250         
251     case timesOp:
252         op3 = SMULop3;
253         if (isPowerOf2(src2imm,result) && (result<32))
254                     instruction::generateLShift(gen, src1, (Register)result, dest);           
255                 else 
256                     instruction::generateImm(gen, op3, src1, src2imm, dest);
257                 break;
258                 
259             case divOp:
260                 op3 = SDIVop3;
261                 if (isPowerOf2(src2imm,result) && (result<32))
262                     instruction::generateRShift(gen, src1, (Register)result, 
263                                                 dest);           
264                 else { // needs to set the Y register to zero first
265                     // Set the Y register to zero: Zhichen
266                     instruction::generateImm(gen, WRYop3, REG_G(0), 0, 0);
267                     instruction::generateImm(gen, op3, src1, src2imm, dest);
268                 }
269                 break;
270
271             // Bool ops
272             case orOp:
273                 op3 = ORop3;
274                 instruction::generateImm(gen, op3, src1, src2imm, dest);
275                 break;
276
277             case andOp:
278                 op3 = ANDop3;
279                 instruction::generateImm(gen, op3, src1, src2imm, dest);
280                 break;
281
282             // rel ops
283             // For a particular condition (e.g. <=) we need to use the
284             // the opposite in order to get the right value (e.g. for >=
285             // we need BLTcond) - naim
286             case eqOp:
287                 instruction::generateImmRelOp(gen, BNEcond, src1, src2imm, dest);
288                 break;
289
290             case neOp:
291                 instruction::generateImmRelOp(gen, BEcond, src1, src2imm, dest);
292                 break;
293
294             case lessOp:
295                 instruction::generateImmRelOp(gen, BGEcond, src1, src2imm, dest);
296                 break;
297
298             case leOp:
299                 instruction::generateImmRelOp(gen, BGTcond, src1, src2imm, dest);
300                 break;
301
302             case greaterOp:
303                 instruction::generateImmRelOp(gen, BLEcond, src1, src2imm, dest);
304                 break;
305
306             case geOp:
307                 instruction::generateImmRelOp(gen, BLTcond, src1, src2imm, dest);
308                 break;
309
310             default:
311                 Register dest2 = gen.rs()->getScratchRegister(gen, noCost);
312                 emitV(loadConstOp, src2imm, dest2, dest2, gen, noCost);
313                 emitV(op, src1, dest2, dest, gen, noCost);
314                 break;
315         }
316         return;
317 }
318
319 /****************************************************************************/
320 /****************************************************************************/
321 /****************************************************************************/
322
323 //
324 // All values based on Cypress0 && Cypress1 implementations as documented in
325 //   SPARC v.8 manual p. 291
326 //
327 int getInsnCost(opCode op)
328 {
329     /* XXX Need to add branchOp */
330     if (op == loadConstOp) {
331         return(1);
332     } else if (op ==  loadOp) {
333         // sethi + load single
334         return(1+1);
335     } else if (op ==  loadIndirOp) {
336         return(1);
337     } else if (op ==  storeOp) {
338         // sethi + store single
339         // return(1+3); 
340         // for SS-5 ?
341         return(1+2); 
342     } else if (op ==  storeIndirOp) {
343         return(2); 
344     } else if (op ==  ifOp) {
345         // subcc
346         // be
347         // nop
348         return(1+1+1);
349     } else if (op ==  callOp) {
350         int count = 0;
351
352         // mov src1, %o0
353         count += 1;
354
355         // mov src2, %o1
356         count += 1;
357
358         // clr i2
359         count += 1;
360
361         // clr i3
362         count += 1;
363
364         // sethi
365         count += 1;
366
367         // jmpl
368         count += 1;
369
370         // noop
371         count += 1;
372
373         return(count);
374     } else if (op ==  updateCostOp) {
375         // sethi %hi(obsCost), %l0
376         // ld [%lo + %lo(obsCost)], %l1
377         // add %l1, <cost>, %l1
378         // st %l1, [%lo + %lo(obsCost)]
379         return(1+2+1+3);
380     } else if (op ==  trampPreamble) {
381         return(0);
382     } else if (op == noOp) {
383         // noop
384         return(1);
385     } else if (op == getParamOp) {
386         return(0);
387     } else {
388         switch (op) {
389             // rel ops
390             case eqOp:
391             case neOp:
392             case lessOp:
393             case leOp:
394             case greaterOp:
395             case geOp:
396                 // bne -- assume taken
397                 return(2);
398                 break;
399             default:
400                 return(1);
401                 break;
402         }
403     }
404 }
405
406 /****************************************************************************/
407 /****************************************************************************/
408 /****************************************************************************/
409
410 bool isReturnInsn(instruction instr, Address addr, std::string name) {
411     if (instr.isInsnType(RETmask, RETmatch) ||
412         instr.isInsnType(RETLmask, RETLmatch)) {
413         //  Why 8 or 12?
414         //  According to the sparc arch manual (289), ret or retl are
415         //   synthetic instructions for jmpl %i7+8, %g0 or jmpl %o7+8, %go.
416         //  Apparently, the +8 is not really a hard limit though, as 
417         //   sometimes some extra space is allocated after the jump 
418         //   instruction for various reasons.
419         //  1 possible reason is to include information on the size of
420         //   returned structure (4 bytes).
421         //  So, 8 or 12 here is a heuristic, but doesn't seem to 
422         //   absolutely have to be true.
423         //  -matt
424         if (((*instr).resti.simm13 != 8) && ((*instr).resti.simm13 != 12) 
425                     && ((*instr).resti.simm13 != 16)) {
426           sprintf(errorLine,"WARNING: unsupported return at address 0x%lx"
427                         " in function %s - appears to be return to PC + %i", 
428                   addr, name.c_str(), (int)(*instr).resti.simm13);
429           showErrorCallback(55, errorLine);
430         } else { 
431           return true;
432         }
433     }
434     return false;
435 }
436
437 /****************************************************************************/
438 /****************************************************************************/
439 /****************************************************************************/
440
441 bool isBranchInsn(instruction instr) {
442     if ((*instr).branch.op == 0 
443                 && ((*instr).branch.op2 == 2 || (*instr).branch.op2 == 6)) 
444           return true;
445     return false;
446 }
447
448 /****************************************************************************/
449 /****************************************************************************/
450 /****************************************************************************/
451
452 bool doNotOverflow(int value)
453 {
454   // we are assuming that we have 13 bits to store the immediate operand.
455   //if ( (value <= 16383) && (value >= -16384) ) return(true);
456   if ( (value <= MAX_IMM13) && (value >= MIN_IMM13) ) return(true);
457   else return(false);
458 }
459
460 /****************************************************************************/
461 /****************************************************************************/
462 /****************************************************************************/
463
464 bool AddressSpace::getDynamicCallSiteArgs(instPoint *callSite,
465                                      pdvector<AstNodePtr> &args) {
466     const instruction &insn = callSite->insn();
467     if (insn.isJmplInsn()) {
468         //this instruction is a jmpl with i == 1, meaning it
469         //calling function register rs1+simm13
470         if((*insn).rest.i == 1){
471             
472             AstNodePtr base =  AstNode::operandNode(AstNode::origRegister,
473                                                   (void *) (*insn).rest.rs1);
474             AstNodePtr offset = AstNode::operandNode(AstNode::Constant,
475                                           (void *) (*insn).resti.simm13);
476             args.push_back( AstNode::operatorNode(plusOp, base, offset));
477         }
478         
479         //This instruction is a jmpl with i == 0, meaning its
480         //two operands are registers
481         else if((*insn).rest.i == 0){
482             //Calculate the byte offset from the contents of the %fp reg
483             //that the registers from the previous stack frame
484             //specified by rs1 and rs2 are stored on the stack
485             args.push_back( AstNode::operatorNode(plusOp, 
486                                                   AstNode::operandNode(AstNode::origRegister,
487                                                                        (void *) (*insn).rest.rs1),
488                                                   AstNode::operandNode(AstNode::origRegister,
489                                                                        (void *) (*insn).rest.rs2)));
490         }
491         else assert(0);
492         
493         args.push_back( AstNode::operandNode(AstNode::Constant,
494                                              (void *) callSite->addr()));
495     }
496     else if(insn.isTrueCallInsn()){
497         //True call destinations are always statically determinable.
498         //return true;
499         fprintf(stderr, "%s[%d]:  dynamic call is statically determinable, FIXME\n",
500                 __FILE__, __LINE__);
501         return false; //  but we don't generate any args here??
502     }
503     else return false;
504     
505     return true;
506 }
507
508
509 /****************************************************************************/
510 /****************************************************************************/
511 /****************************************************************************/
512
513 // Emit code to jump to function CALLEE without linking.  (I.e., when
514 // CALLEE returns, it returns to the current caller.)  On SPARC, we do
515 // this by ensuring that the register context upon entry to CALLEE is
516 // the register context of function we are instrumenting, popped once.
517 void emitFuncJump(opCode op, codeGen &gen, 
518                   int_function *callee, AddressSpace * /*proc*/,
519                   const instPoint *, bool)
520 {
521     assert(op == funcJumpOp);
522     Address addr = callee->getAddress();
523
524     // This must mimic the generateRestores baseTramp method. 
525     // TODO: make this work better :)
526
527     for (unsigned g_iter = 0; g_iter <= 6; g_iter += 2) {
528         // ldd [%fp + -8], %g0
529         // ldd [%fp + -16], %g2
530         // ldd [%fp + -24], %g4
531         // ldd [%fp + -32], %g6
532         
533         instruction::generateLoadD(gen, REG_FPTR, 
534                                    -(8+(g_iter*4)), REG_G(g_iter));
535     }
536
537     // And pop the stack
538     // This is left here so that we don't put it back in accidentally.
539     // The jmpl instruction stores the jump address; we don't want that.
540     // So we "invisi-jump" by making the jump, _then_ executing the
541     // restore.
542     //instruction::generateSimple(i, RESTOREop3, 0, 0, 0);
543     
544     instruction::generateSetHi(gen, addr, 13);
545     // don't want the return address to be used
546     instruction::generateImm(gen, JMPLop3, 13, LOW10(addr), 0);
547     instruction::generateSimple(gen, RESTOREop3, 0, 0, 0);
548 }
549
550 #include <sys/systeminfo.h>
551
552 // VG(4/24/2002) It seems a good idea to cache the result.
553 // This is not thread safe, but should be okay since the 
554 // result shoud be the same for all threads...
555 /*
556  * function which check whether the architecture is 
557  * sparcv8plus or not. For the earlier architectures 
558  * it is not possible to support random instrumentation 
559  */
560 bool isV8plusISA()
561 {
562   static bool result;
563   static bool gotresult = false;
564
565   if(gotresult)
566     return result;
567   else {
568     char isaOptions[256];
569
570     if (sysinfo(SI_ISALIST, isaOptions, 256) < 0)
571       return false;
572     if (strstr(isaOptions, "sparcv8plus"))
573       return true;
574     return false;
575   }
576 }
577
578 /*
579  * function which check whether the architecture is 
580  * sparcv9 or later. For the earlier architectures 
581  * it is not possible to support ajacent arbitrary 
582  * instrumentation points
583  */
584 bool isV9ISA()
585 {
586   static bool result;
587   static bool gotresult = false;
588
589   if(gotresult)
590     return result;
591   else { 
592     char isaOptions[256];
593
594     if (sysinfo(SI_ISALIST, isaOptions, 256) < 0)
595       return false;
596     if (strstr(isaOptions, "sparcv9"))
597       return true;
598     return false;
599   }
600 }
601
602 extern bool relocateFunction(process *proc, instPoint *&location);
603 extern bool branchInsideRange(instruction insn, Address branchAddress, 
604                               Address firstAddress, Address lastAddress); 
605 extern instPoint* find_overlap(pdvector<instPoint*> v, Address targetAddress);
606 extern void sorted_ips_vector(pdvector<instPoint*>&fill_in);
607
608 /****************************************************************************/
609 /****************************************************************************/
610 /****************************************************************************/
611
612 // Determine the maximum amount of space required for relocating
613 // an instruction. Must assume the instruction will be relocated
614 // anywhere in the address space.
615
616 unsigned relocatedInstruction::maxSizeRequired() {
617     return insn->spaceToRelocate();
618 }
619
620
621 /****************************************************************************/
622 /****************************************************************************/
623 /****************************************************************************/
624
625
626 bool baseTramp::generateSaves(codeGen &gen,
627                               registerSpace*, baseTrampInstance *) {
628     if (isConservative()) {
629         // Yadda
630     }
631
632     int frameShift = 0;
633     if (isConservative()) 
634         frameShift = -256;
635     else 
636         frameShift = -120;
637
638     // save %sp, -120, %sp
639     instruction::generateImm(gen, SAVEop3, REG_SPTR, frameShift, REG_SPTR);
640
641     for (unsigned g_iter = 0; g_iter <= 6; g_iter += 2) {
642         // std %g[iter], [ %fp + -(8 + (g_iter*4))]
643         // Otherwise known as:
644         // std %g0, [ %fp + -8]
645         // std %g2, [ %fp + -16]
646         // std %g4, [ %fp + -24]
647         // std %g6, [ %fp + -32]
648
649         instruction::generateStoreD(gen, REG_G(g_iter), REG_FPTR, 
650                                     -(8+(g_iter*4)));
651     }
652
653
654     if (isConservative() && BPatch::bpatch->isSaveFPROn() ) {
655         for (unsigned f_iter = 0; f_iter <= 30; f_iter += 2) {
656             // std %f[iter], [%fp + -(40 + iter*4)]
657             instruction::generateStoreFD(gen, f_iter, REG_FPTR, 
658                                          -(40 + (f_iter*4)));
659         }
660         
661         // I hate constants... anyone know what this pattern means?
662         // save codes to %g1?
663         instruction saveConditionCodes(0x83408000);
664         saveConditionCodes.generate(gen);
665         
666         // And store them.
667         instruction::generateStore(gen, REG_G(1), REG_FPTR,
668                                    -164);
669     }
670     
671     return true;
672 }
673
674 bool baseTramp::generateRestores(codeGen &gen,
675                                  registerSpace *,
676                                  baseTrampInstance *) {
677     if (isConservative() && BPatch::bpatch->isSaveFPROn()) {
678         for (unsigned f_iter = 0; f_iter <= 30; f_iter += 2) {
679             // std %f[iter], [%fp + -(40 + iter*4)]
680             instruction::generateLoadFD(gen, REG_FPTR, 
681                                         -(40+(f_iter*4)), f_iter);
682         }
683         
684         // load them...
685         instruction::generateLoad(gen, REG_FPTR,
686                                   -164, REG_G(1));
687
688         // I hate constants... anyone know what this pattern means?
689         // restore codes from g1?
690         instruction restoreConditionCodes(0x85806000);
691         restoreConditionCodes.generate(gen);
692     }
693
694
695     for (unsigned g_iter = 0; g_iter <= 6; g_iter += 2) {
696         // ldd [%fp + -8], %g0
697         // ldd [%fp + -16], %g2
698         // ldd [%fp + -24], %g4
699         // ldd [%fp + -32], %g6
700         
701         instruction::generateLoadD(gen, REG_FPTR, 
702                                    -(8+(g_iter*4)), REG_G(g_iter));
703     }
704
705     // And pop the stack
706
707     instruction::generateSimple(gen, RESTOREop3, 0, 0, 0);
708
709     return true;
710 }
711
712 /****************************************************************************/
713 /****************************************************************************/
714 /****************************************************************************/
715
716 //This function returns true if the processor on which the daemon is running
717 //is an ultra SPARC, otherwise returns false.
718 bool isUltraSparc(){
719   struct utsname u;
720   if(uname(&u) < 0){
721     cerr <<"Trouble in uname(), inst-sparc-solaris.C\n";
722     return false;
723   }
724   if(!strcmp(u.machine, "sun4u")){
725     return 1;
726   }
727   return false;
728 }
729
730 /****************************************************************************/
731 /****************************************************************************/
732 /****************************************************************************/
733
734 void emitLoadPreviousStackFrameRegister(Address register_num,
735                                         Register dest,
736                                         codeGen &gen,
737                                         int size,
738                                         bool noCost){
739   if(register_num > 31)
740     assert(0);
741   else if(register_num > 15){
742     /*Need to find it on the stack*/
743     unsigned frame_offset = (register_num-16) * 4;
744     /*generate a FLUSHW instruction, in order to make sure that
745       the registers from the caller are on the caller's stack
746       frame*/
747
748     if(isUltraSparc())
749         instruction::generateFlushw(gen);
750     else 
751         instruction::generateTrapRegisterSpill(gen);
752     
753     if(frame_offset == 0){
754         emitV(loadIndirOp, 30, 0, dest, gen,  noCost, NULL, size);
755     }       
756     else {
757         emitImm(plusOp,(Register) 30,(RegValue)frame_offset, 
758                 dest, gen, noCost);
759         emitV(loadIndirOp, dest, 0, dest, gen, noCost, NULL, size);
760     }
761   }       
762   else if(register_num > 7) { 
763       //out registers become in registers, so we add 16 to the register
764       //number to find it's value this stack frame. We move it's value
765       //into the destination register
766       emitV(orOp, (Register) register_num + 16, 0,  dest, gen, false);
767   }
768   else /* if(register_num >= 0) */ {
769       int frame_offset;
770       if(register_num % 2 == 0) 
771           frame_offset = (register_num * -4) - 8;
772       else 
773           frame_offset = (register_num * -4);
774       //read globals from the stack, they were saved in tramp-sparc.S
775       emitImm(plusOp,(Register) 30,(RegValue)frame_offset, 
776               dest, gen, noCost);
777       emitV(loadIndirOp, dest, 0, dest, gen, noCost, NULL, size);
778   }
779   /* else assert(0); */
780   
781 }
782
783 void emitStorePreviousStackFrameRegister(Address,
784                                          Register,
785                                          codeGen &,
786                                          int,
787                                          bool) {
788     assert(0);
789 }
790
791 /****************************************************************************/
792 /****************************************************************************/
793 /****************************************************************************/
794
795 Register emitFuncCall(opCode op, 
796                       codeGen &gen, 
797                       pdvector<AstNodePtr> &operands, 
798                       bool noCost, int_function *callee)
799 {
800    assert(op == callOp);
801    pdvector <Register> srcs;
802    void cleanUpAndExit(int status);
803    
804    // sanity check for NULL address argument
805    if (!callee) {
806      char msg[256];
807      sprintf(msg, "%s[%d]:  internal error:  emitFuncCall called w/out"
808              "callee argument", __FILE__, __LINE__);
809      showErrorCallback(80, msg);
810      assert(0);
811    }
812  
813    for (unsigned u = 0; u < operands.size(); u++) {
814        Register src = REG_NULL;
815        Address unused = ADDR_NULL;
816        if (!operands[u]->generateCode_phase2( gen, false, unused, src)) assert(0);
817        assert(src != REG_NULL);
818        srcs.push_back(src);
819    }
820    
821    for (unsigned u=0; u<srcs.size(); u++){
822       if (u >= 5) {
823          std::string msg = "Too many arguments to function call in instrumentation code: only 5 arguments can be passed on the sparc architecture.\n";
824          bperr( msg.c_str());
825          showErrorCallback(94,msg);
826          cleanUpAndExit(-1);
827       }
828       instruction::generateSimple(gen, ORop3, 0, srcs[u], u+8);
829       gen.rs()->freeRegister(srcs[u]);
830    }
831    
832    // As Ling pointed out to me, the following is rather inefficient.  It does:
833    //   sethi %hi(addr), %o5
834    //   jmpl %o5 + %lo(addr), %o7   ('call' pseudo-instr)
835    //   nop
836    // We can do better:
837    //   call <addr>    (but note that the call true-instr is pc-relative jump)
838    //   nop
839    instruction::generateSetHi(gen, callee->getAddress(), 13);
840    instruction::generateImm(gen, JMPLop3, 13, LOW10(callee->getAddress()), 15); 
841    instruction::generateNOOP(gen);
842    
843    // return value is the register with the return value from the function.
844    // This needs to be %o0 since it is back in the caller's scope.
845
846    Register retReg = gen.rs()->allocateRegister(gen, noCost);
847    
848    // Move tmp to dest
849    emitImm(orOp, REG_O(0), 0, retReg, gen, noCost, gen.rs());
850
851    return retReg;
852 }
853
854 Register emitFuncCall(opCode op, 
855                       codeGen &gen, 
856                       pdvector<AstNodePtr> &operands, 
857                       bool noCost, Address callee_addr_) {
858     // Argh... our dlopen installation uses an address version :/
859     
860     assert(op == callOp);
861     pdvector <Register> srcs;
862     void cleanUpAndExit(int status);
863     
864    // sanity check for NULL address argument
865    if (!callee_addr_) {
866      char msg[256];
867      sprintf(msg, "%s[%d]:  internal error:  emitFuncCall called w/out"
868              "callee address argument", __FILE__, __LINE__);
869      showErrorCallback(80, msg);
870      assert(0);
871    }
872  
873    for (unsigned u = 0; u < operands.size(); u++) {
874        Register src = REG_NULL;
875        Address unused = ADDR_NULL;
876        if (!operands[u]->generateCode_phase2( gen, false, unused, src)) assert(0);
877        assert(src != REG_NULL);
878        srcs.push_back(src);
879    }
880    
881    for (unsigned u=0; u<srcs.size(); u++){
882       if (u >= 5) {
883          std::string msg = "Too many arguments to function call in instrumentation code: only 5 arguments can be passed on the sparc architecture.\n";
884          bperr( msg.c_str());
885          showErrorCallback(94,msg);
886          cleanUpAndExit(-1);
887       }
888       instruction::generateSimple(gen, ORop3, 0, srcs[u], u+8);
889       gen.rs()->freeRegister(srcs[u]);
890    }
891    
892    // As Ling pointed out to me, the following is rather inefficient.  It does:
893    //   sethi %hi(addr), %o5
894    //   jmpl %o5 + %lo(addr), %o7   ('call' pseudo-instr)
895    //   nop
896    // We can do better:
897    //   call <addr>    (but note that the call true-instr is pc-relative jump)
898    //   nop
899    instruction::generateSetHi(gen, callee_addr_, 13);
900    instruction::generateImm(gen, JMPLop3, 13, LOW10(callee_addr_), 15); 
901    instruction::generateNOOP(gen);
902    
903    // return value is the register with the return value from the function.
904    // This needs to be %o0 since it is back in the caller's scope.
905
906    Register retReg = gen.rs()->allocateRegister(gen, noCost);
907    
908    // Move tmp to dest
909    emitImm(orOp, retReg, 0, REG_O(0), gen, noCost, gen.rs());
910
911    return retReg;
912 }
913
914  
915 /****************************************************************************/
916 /****************************************************************************/
917 /****************************************************************************/
918
919
920 codeBufIndex_t emitA(opCode op, Register src1, Register /*src2*/, Register dest, 
921               codeGen &gen, RegControl, bool /*noCost*/)
922 {
923     //bperr("emitA(op=%d,src1=%d,src2=XX,dest=%d)\n",op,src1,dest);
924     codeBufIndex_t retval;
925     switch (op) {
926     case ifOp: 
927         // cmp src1,0
928         instruction::generateImm(gen, SUBop3cc, src1, 0, 0);
929         //genSimpleInsn(gen, SUBop3cc, src1, 0, 0); insn++;
930         retval = gen.getIndex();
931         instruction::generateCondBranch(gen, dest, BEcond, false);
932
933         instruction::generateNOOP(gen);
934         break;
935     case branchOp: 
936         // Unconditional branch
937         retval = gen.getIndex();
938         instruction::generateBranch(gen, dest);
939         instruction::generateNOOP(gen);
940         break;
941     case trampPreamble: {
942         return(0);      // let's hope this is expected!
943         }
944     default:
945         abort();        // unexpected op for this emit!
946     }
947     return retval;
948 }
949
950 /****************************************************************************/
951 /****************************************************************************/
952 /****************************************************************************/
953
954 Register emitR(opCode op, Register src1, Register src2, Register dest, 
955                codeGen &gen, bool /*noCost*/,
956                const instPoint *location, bool for_multithreaded)
957 {
958     //bperr("emitR(op=%d,src1=%d,src2=XX,dest=XX)\n",op,src1);
959
960     // Here is what a "well-named" astFlag seems to mean.
961     // astFlag is true iff the function does not begin with a save
962     // or our instumentation is placed before the save instruction.
963     // Notice that we do emit a save in the basetramp in any case,
964     // so if (astFlag) then arguments are in the previous frame's
965     // O registers (this frame's I registers). If (!astFlag) then
966     // arguments are two frames above us.
967     // For callsite instrumentation, callee's arguments are always
968     // in I registers (remember, we did a save)
969     
970     // From ast.C:
971 #if 0
972     if (astFlag || location->getPointType() == callSite)
973         src = emitR(getSysParamOp, (Register)oValue, Null_Register, 
974                     dest, insn, base, noCost, location,
975                     proc->multithread_capable());
976     else 
977         src = emitR(getParamOp, (Address)oValue, Null_Register,
978                     dest, insn, base, noCost, location,
979                     proc->multithread_capable());
980     
981 #endif
982     
983 #if 0
984     if (loperand) {
985         instruction instr;
986         instr.raw = (unsigned)(loperand->oValue);
987         src = emitOptReturn(instr, dest, insn, base, noCost, location,
988                             proc->multithread_capable());
989     }
990     else if (astFlag)
991         src = emitR(getSysRetValOp, 0, 0, dest, insn, base, noCost, location,
992                     proc->multithread_capable());
993 #endif
994
995     // Suppose we can check the instPoint info; for now assume that registers are
996     // requested at function entry, and return at function exit.
997     
998     opCode opToUse;
999     if (op == getParamOp) {
1000         if (location->getPointType() == functionEntry) {
1001             // Function entry: no save, parameters in input registers.
1002             opToUse = getSysParamOp;
1003         }
1004         else if (location->getPointType() == callSite) {
1005             // Call site parameters: in input registers.
1006             opToUse = getSysParamOp;
1007         }
1008         else {
1009             // Odd... not entry, not call site. We'll assume a save has
1010             // been executed. Really, don't do this.
1011             opToUse = getParamOp;
1012         }
1013     }
1014     else if (op == getRetValOp) {
1015         if (location->getPointType() == functionExit)
1016             opToUse = getRetValOp;
1017         else if (location->getPointType() == callSite)
1018             opToUse = getSysRetValOp;
1019         else {
1020             fprintf(stderr, "%s[%d]: Incorrect use of getRetValOp.\n",
1021                     __FILE__, __LINE__);
1022             assert(0);
1023         }
1024     }
1025     else {
1026         assert(0);
1027         return 0;
1028     }
1029
1030     switch(opToUse) {
1031     case getParamOp: {
1032         if(for_multithreaded) {
1033             // saving CT/vector address on the stack
1034             instruction::generateStore(gen, REG_MT_POS, REG_FPTR, -40);
1035         }
1036         // We have managed to emit two saves since the entry point of
1037         // the function, so the first 6 parameters are in the previous
1038         // frame's I registers, and we need to pick them off the stack
1039         
1040         // generate the FLUSHW instruction to make sure that previous
1041         // windows are written to the register save area on the stack
1042         if (isUltraSparc()) {
1043             instruction::generateFlushw(gen);
1044         }
1045         else {
1046             instruction::generateTrapRegisterSpill(gen);
1047         }
1048
1049         if (src1 < 6) {
1050             // The arg is in a previous frame's I register. Get it from
1051             // the register save area
1052             if (src2 != REG_NULL)
1053                 instruction::generateStore(gen, src2, REG_FPTR, 4*8 + 4*src1);
1054             instruction::generateLoad(gen, REG_FPTR, 4*8 + 4*src1, dest);
1055         }
1056         else {
1057             // The arg is on the stack, two frames above us. Get the previous
1058             // FP (i6) from the register save area
1059             instruction::generateLoad(gen, REG_FPTR, 4*8 + 4*6, dest);
1060             // old fp is in dest now
1061
1062             // Write new value, if any
1063             if (src2 != REG_NULL)
1064                 instruction::generateStore(gen, src2, dest, 92 + 4 * (src1 - 6));
1065
1066             // Finally, load the arg from the stack
1067             instruction::generateLoad(gen, dest, 92 + 4 * (src1 - 6), dest);
1068         }
1069
1070         if(for_multithreaded) {
1071             // restoring CT/vector address back in REG_MT_POS
1072             instruction::generateLoad(gen, REG_FPTR, -40, REG_MT_POS);
1073         }
1074
1075         return dest;
1076     }
1077     case getSysParamOp: {
1078         // We have emitted one save since the entry point of
1079         // the function, so the first 6 parameters are in this
1080         // frame's I registers
1081         if (src1 < 6) {
1082             // Param is in an I register
1083             if (src2 != REG_NULL)
1084                 instruction::generateSimple(gen, ORop3, 0, src2, REG_I(src1));
1085             return(REG_I(src1));
1086         }
1087         else {
1088             // Param is on the stack
1089             if (src2 != REG_NULL)
1090                 instruction::generateStore(gen, src2, REG_FPTR, 92 + 4 * (src1 - 6));
1091             instruction::generateLoad(gen, REG_FPTR, 92 + 4 * (src1 - 6), dest);
1092             return dest;
1093         }
1094     }
1095     case getRetValOp: {
1096         // We have emitted one save since the exit point of
1097         // the function, so the return value is in the previous frame's
1098         // I0, and we need to pick it from the stack
1099
1100         // generate the FLUSHW instruction to make sure that previous
1101         // windows are written to the register save area on the stack
1102         if (isUltraSparc()) {
1103             instruction::generateFlushw(gen);
1104         }
1105         else {
1106             instruction::generateTrapRegisterSpill(gen);
1107         }
1108
1109         if (src2 != REG_NULL)
1110             instruction::generateStore(gen, src2, REG_FPTR, 4*8);
1111         instruction::generateLoad(gen, REG_FPTR, 4*8, dest);
1112         return dest;
1113     }
1114     case getSysRetValOp:
1115         if (src2 != REG_NULL)
1116             instruction::generateSimple(gen, ORop3, 0, src2, REG_I(0));
1117         return(REG_I(0));
1118
1119     default:
1120         abort();        // unexpected op for this emit!
1121     }
1122 }
1123
1124 void emitJmpMC(int /*condition*/, int /*offset*/, codeGen & /*baseInsn*/)
1125 {
1126     // Not needed for memory instrumentation, otherwise TBD
1127 }
1128
1129 // VG(12/02/01): Emit code to add the original value of a register to
1130 // another. The original value may need to be restored somehow...
1131 static inline void emitAddOriginal(Register src, Register acc, 
1132                                    codeGen &gen, bool noCost)
1133 {
1134     // Plan:
1135     // ignore g0 (r0), since we would be adding 0.
1136     // get    g1-g4 (r1-r4) from stack (where the base tramp saved them)
1137     // get    g5-g7 (r5-r7) also from stack, but issue an warning because
1138     // the SPARC psABI cleary states that G5-G7 SHOULD NOT BE EVER WRITTEN
1139     // in userland, as they may be changed arbitrarily by signal handlers!
1140     // So AFAICT it doesn't make much sense to read them...
1141     // get o0-o7 (r8-r15) by "shifting" the window back (i.e. get r24-r31)
1142     // get l0-l7 (r16-23) by flushing the register window to stack
1143     //                    and geeting them from there
1144     // get i0-i7 (r24-31) by --"--
1145     // Note: The last two may seem slow, but they're async. trap safe this way
1146     
1147     // All this is coded as a binary search.
1148     
1149     bool mustFree = false;
1150     Register temp;
1151     
1152     if (src >= 16) {
1153         // VG(12/06/01): Currently saving registers on demand is NOT
1154         // implemented on SPARC (dumps assert), so we can safely ignore it
1155         temp = gen.rs()->getScratchRegister(gen, noCost);
1156         mustFree = true;
1157         
1158         // Cause repeated spills, till all windows but current are clear
1159         instruction::generateFlushw(gen); // only ultraSPARC supported here
1160         
1161         // the spill trap puts these at offset from the previous %sp now %fp (r30)
1162         unsigned offset = (src-16) * sizeof(long); // FIXME for 64bit mutator/32bit mutatee
1163         instruction::generateLoad(gen, 30, offset, temp);
1164     }
1165     else if (src >= 8)
1166         temp = src + 16;
1167     else if (src >= 1) {
1168         // VG(12/06/01): Currently saving registers on demand is NOT
1169         // implemented on SPARC (dumps assert), so we can safely ignore it
1170         temp = gen.rs()->getScratchRegister(gen, noCost);
1171         mustFree = true;
1172         
1173         // the base tramp puts these at offset from %fp (r30)
1174         unsigned offset = ((src%2) ? src : (src+2)) * -sizeof(long); // FIXME too
1175         instruction::generateLoad(gen, 30, offset, temp);
1176         
1177         if (src >= 5)
1178             logLine("SPARC WARNING: Restoring original value of g5-g7 is unreliable!");
1179     }
1180     else // src == 0
1181         return;
1182     
1183     // add temp to dest;
1184     emitV(plusOp, temp, acc, acc, gen, noCost, 0);
1185     
1186 }
1187
1188 // VG(11/30/01): Load in destination the effective address given
1189 // by the address descriptor. Used for memory access stuff.
1190 void emitASload(const BPatch_addrSpec_NP *as, Register dest, codeGen &gen,
1191                 bool noCost)
1192 {
1193     int imm = as->getImm();
1194     int ra  = as->getReg(0);
1195     int rb  = as->getReg(1);
1196     
1197     // TODO: optimize this to generate the minimum number of
1198     // instructions; think about schedule
1199     
1200     // emit code to load the immediate (constant offset) into dest; this
1201     // writes at baseInsn+base and updates base, we must update insn...
1202     emitVload(loadConstOp, (Address)imm, dest, dest, gen, noCost);
1203     
1204     // If ra is used in the address spec, allocate a temp register and
1205     // get the value of ra from stack into it
1206     if(ra > -1)
1207         emitAddOriginal(ra, dest, gen, noCost);
1208     
1209     // If rb is used in the address spec, allocate a temp register and
1210     // get the value of ra from stack into it
1211     if(rb > -1)
1212         emitAddOriginal(rb, dest, gen, noCost);
1213 }
1214
1215 void emitCSload(const BPatch_addrSpec_NP *as, Register dest, codeGen &gen,
1216                 bool noCost)
1217 {
1218   emitASload(as, dest, gen, noCost);
1219 }
1220
1221 /****************************************************************************/
1222 /****************************************************************************/
1223 /****************************************************************************/
1224
1225 //
1226 // load the original FP (before the dyninst saves) into register dest
1227 //
1228 int getFP(codeGen &gen, Register dest)
1229 {
1230     instruction::generateSimple(gen, RESTOREop3, 0, 0, 0);
1231     instruction::generateStore(gen, REG_FPTR, REG_SPTR, 68);
1232           
1233     instruction::generateImm(gen, SAVEop3, REG_SPTR, -112, REG_SPTR);
1234     instruction::generateLoad(gen, REG_SPTR, 112+68, dest); 
1235
1236
1237     return(4*instruction::size());
1238 }
1239
1240 /****************************************************************************/
1241 /****************************************************************************/
1242 /****************************************************************************/
1243
1244 void emitVload(opCode op, Address src1, Register src2, Register dest, 
1245                codeGen &gen, bool /*noCost*/, 
1246                registerSpace * /*rs*/, int size,
1247                const instPoint * /* location */, AddressSpace * /* proc */) 
1248 {
1249     if (op == loadConstOp) {
1250         // dest = src1:imm    TODO
1251         
1252         if ((src1) > ( unsigned )MAX_IMM13 || (src1) < ( unsigned )MIN_IMM13) {
1253             // src1 is out of range of imm13, so we need an extra instruction
1254             instruction::generateSetHi(gen, src1, dest);
1255             
1256             // or regd,imm,regd
1257
1258             // Chance for optimization: we should check for LOW10(src1)==0,
1259             // and if so, don't generate the following bitwise-or instruction,
1260             // since in that case nothing would be done.
1261
1262             instruction::generateImm(gen, ORop3, dest, LOW10(src1), dest);
1263         } else {
1264             // really or %g0,imm,regd
1265             instruction::generateImm(gen, ORop3, 0, src1, dest);
1266         }
1267     } else if (op ==  loadOp) {
1268         // dest = [src1]   TODO
1269         instruction::generateSetHi(gen, src1, dest);
1270
1271         if (size == 1)
1272             instruction::generateLoadB(gen, dest, LOW10(src1), dest);
1273         else if (size == 2)
1274             instruction::generateLoadH(gen, dest, LOW10(src1), dest);
1275         else
1276             instruction::generateLoad(gen, dest, LOW10(src1), dest);
1277     } else if (op ==  loadFrameRelativeOp) {
1278         // return the value that is FP offset from the original fp
1279         //   need to restore old fp and save it on the stack to get at it.
1280         
1281         getFP(gen, dest);
1282         if (((int) src1 < MIN_IMM13) || ((int) src1 > MAX_IMM13)) {
1283             // offsets are signed!
1284             int offset = (int) src1;
1285
1286             // emit sethi src2, offset
1287             instruction::generateSetHi(gen, offset, src2);
1288
1289             // or src2, offset, src2
1290             instruction::generateImm(gen, ORop3, src2, LOW10(offset), src2);
1291
1292             // add dest, src2, dest
1293             instruction::generateSimple(gen, ADDop3, dest, src2, src2);
1294
1295             instruction::generateLoad(gen, src2, 0, dest);
1296         }  else {
1297             instruction::generateLoad(gen, dest, src1, dest);
1298         }
1299     } else if (op == loadFrameAddr) {
1300         // offsets are signed!
1301         int offset = (int) src1;
1302         
1303         getFP(gen, dest);
1304
1305         if (((int) offset < MIN_IMM13) || ((int) offset > MAX_IMM13)) {
1306             // emit sethi src2, offset
1307             instruction::generateSetHi(gen, offset, src2);
1308
1309             // or src2, offset, src2
1310             instruction::generateImm(gen, ORop3, src2, LOW10(offset), src2);
1311
1312             // add dest, src2, dest
1313             instruction::generateSimple(gen, ADDop3, dest, src2, dest);
1314         }  else {
1315             // fp is in dest, just add the offset
1316             instruction::generateImm(gen, ADDop3, dest, offset, dest);
1317         }
1318     } else if(op == loadRegRelativeAddr) {
1319       int offset = (int) src1;
1320       instruction::generateLoad(gen, src2, offset, dest);
1321       
1322     } else {
1323         abort();       // unexpected op for this emit!
1324     }
1325 }
1326
1327 /****************************************************************************/
1328 /****************************************************************************/
1329 /****************************************************************************/
1330
1331 void emitVstore(opCode op, Register src1, Register src2, Address dest, 
1332                 codeGen &gen, bool /*noCost*/, 
1333                 registerSpace * /*rs*/, int /* size */,
1334                 const instPoint * /* location */, AddressSpace * /* proc */)
1335 {
1336     
1337     if (op == storeOp) {
1338         instruction insn;
1339         (*insn).sethi.op = FMT2op;
1340         (*insn).sethi.rd = src2;
1341         (*insn).sethi.op2 = SETHIop2;
1342         (*insn).sethi.imm22 = HIGH22(dest);
1343         insn.generate(gen);
1344
1345         instruction::generateStore(gen, src1, src2, LOW10(dest));
1346     } else if (op == storeFrameRelativeOp) {
1347         // offsets are signed!
1348         int offset = (int) dest;
1349
1350         getFP(gen, src2);
1351
1352         if ((offset < MIN_IMM13) || (offset > MAX_IMM13)) {
1353             // We are really one regsiter short here, so we put the
1354             //   value to store onto the stack for part of the sequence
1355             instruction::generateStore(gen, src1, REG_SPTR, 112+68);
1356
1357             instruction::generateSetHi(gen, offset, src1);
1358
1359             instruction::generateImm(gen, ORop3, src1, LOW10(offset), src1);
1360
1361             instruction::generateSimple(gen, ADDop3, src1, src2, src2);
1362
1363             instruction::generateLoad(gen, REG_SPTR, 112+68, src1); 
1364
1365             instruction::generateStore(gen, src1, src2, 0);
1366         } else {
1367             instruction::generateStore(gen, src1, src2, dest);
1368         }
1369     } else {
1370         abort();       // unexpected op for this emit!
1371     }
1372 }
1373
1374 /****************************************************************************/
1375 /****************************************************************************/
1376 /****************************************************************************/
1377
1378 /****************************************************************************/
1379 /****************************************************************************/
1380 /****************************************************************************/
1381
1382 void emitV(opCode op, Register src1, Register src2, Register dest, 
1383               codeGen &gen, bool /*noCost*/, 
1384            registerSpace * /*rs*/, int /* size */,
1385            const instPoint * /* location */, AddressSpace * /* proc */)
1386            
1387 {
1388     //bperr("emitV(op=%d,src1=%d,src2=%d,dest=%d)\n",op,src1,src2,dest);
1389     
1390     assert ((op!=branchOp) && (op!=ifOp) && 
1391             (op!=trampPreamble));         // !emitA
1392     assert ((op!=getRetValOp) && (op!=getSysRetValOp) &&
1393             (op!=getParamOp) && (op!=getSysParamOp));           // !emitR
1394     assert ((op!=loadOp) && (op!=loadConstOp));                 // !emitVload
1395     assert ((op!=storeOp));                                     // !emitVstore
1396     assert ((op!=updateCostOp));                                // !emitVupdate
1397     
1398     
1399     if (op == loadIndirOp) {
1400         instruction::generateLoad(gen, src1, 0, dest);
1401     } else if (op == storeIndirOp) {
1402         instruction::generateStore(gen, src1, dest, 0);
1403     } else if (op == noOp) {
1404         instruction::generateNOOP(gen);
1405     } else if (op == saveRegOp) {
1406         // should never be called for this platform.
1407         // VG(12/02/01): Unfortunately allocateRegister *may* call this
1408         abort();
1409     } else {
1410         int op3=-1;
1411         switch (op) {
1412             // integer ops
1413         case plusOp:
1414             op3 = ADDop3;
1415             break;
1416             
1417         case minusOp:
1418             op3 = SUBop3;
1419             break;
1420             
1421         case timesOp:
1422             op3 = SMULop3;
1423             break;
1424             
1425         case divOp:
1426             op3 = SDIVop3;
1427             //need to set the Y register to Zero, Zhichen
1428             instruction::generateImm(gen, WRYop3, REG_G(0), 0, 0);
1429             break;
1430             
1431             // Bool ops
1432         case orOp:
1433             op3 = ORop3;
1434             break;
1435             
1436         case andOp:
1437             op3 = ANDop3;
1438             break;
1439             
1440             // rel ops
1441             // For a particular condition (e.g. <=) we need to use the
1442             // the opposite in order to get the right value (e.g. for >=
1443             // we need BLTcond) - naim
1444         case eqOp:
1445             instruction::generateRelOp(gen, BNEcond, src1, src2, dest);
1446             break;
1447             
1448         case neOp:
1449             instruction::generateRelOp(gen, BEcond, src1, src2, dest);
1450             break;
1451             
1452         case lessOp:
1453             instruction::generateRelOp(gen, BGEcond, src1, src2, dest);
1454             break;
1455             
1456         case leOp:
1457             instruction::generateRelOp(gen, BGTcond, src1, src2, dest);
1458             break;
1459             
1460         case greaterOp:
1461             instruction::generateRelOp(gen, BLEcond, src1, src2, dest);
1462             break;
1463
1464         case geOp:
1465             instruction::generateRelOp(gen, BLTcond, src1, src2, dest);
1466             break;
1467             
1468         default:
1469             abort();
1470             break;
1471         }
1472         if (op3 != -1) {
1473             // I.E. was set above...
1474             instruction::generateSimple(gen, op3, src1, src2, dest);
1475         }
1476       }
1477    return;
1478 }
1479
1480
1481
1482 /****************************************************************************/
1483 /****************************************************************************/
1484
1485 int instPoint::liveRegSize()
1486 {
1487   /* Stub function */
1488   return 0;
1489 }
1490
1491 /**
1492  * Fills in an indirect function pointer at 'addr' to point to 'f'.
1493  **/
1494 bool writeFunctionPtr(AddressSpace *p, Address addr, int_function *f)
1495 {
1496    Address val_to_write = f->getAddress();
1497    return p->writeDataSpace((void *) addr, sizeof(Address), &val_to_write);   
1498 }
1499
1500 bool image::isAligned(const Address where) const {
1501    return (!(where & 0x3));
1502 }
1503
1504 Emitter *AddressSpace::getEmitter() {
1505     return NULL;
1506 }