Update copyright to LGPL on all files
[dyninst.git] / dyninstAPI / src / arch-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 /*
33  * inst-power.C - Identify instrumentation points for a RS6000/PowerPCs
34  * $Id: arch-sparc.C,v 1.34 2008/11/03 15:19:24 jaw Exp $
35  */
36
37 #include "common/h/Types.h"
38 #include "dynutil/h/Annotatable.h"
39 #include "arch.h"
40 #include "inst-sparc.h"
41 #include "util.h"
42 #include "debug.h"
43 #include "InstrucIter.h"
44 #include "addressSpace.h"
45
46 AnnotationClass<std::vector<InsnRegister> > RegisterReadSetAnno("RegisterReadSetAnno");
47 AnnotationClass<std::vector<InsnRegister> > RegisterWriteSetAnno("RegisterWriteSetAnno");
48
49 //inline unsigned getMaxBranch1Insn() {
50 //   // The length we can branch using just 1 instruction is dictated by the
51 //   // sparc instruction set.
52 //   return (0x1 << 23);
53 //}
54
55 /****************************************************************************/
56 /****************************************************************************/
57
58 instruction *instruction::copy() const {
59     return new instruction(*this);
60 }
61
62 void instruction::generateTrap(codeGen &gen) {
63     instruction insn(BREAK_POINT_INSN);
64     insn.generate(gen);
65 }
66
67 void instruction::generateIllegal(codeGen &gen) {
68     instruction insn;
69     insn.generate(gen);
70 }
71
72 bool instruction::offsetWithinRangeOfBranchInsn(long offset) {
73     // The pc-relative offset range which we can branch to with a single sparc
74     // branch instruction is dictated by the sparc instruction set.
75     // There are 22 bits available...however, you really get 2 extra bits
76     // because the CPU multiplies the 22-bit signed offset by 4.
77     // The only downside is that the offset must be a multiple of 4, which we 
78     // check.
79     
80     unsigned abs_offset = ABS(offset);
81     assert(abs_offset % 4 == 0);
82     
83     // divide by 4.  After the divide, the result must fit in 22 bits.
84     offset /= 4;
85     
86     // low 21 bits all 1's, the high bit (#22) is 0
87     const int INT22_MAX = 0x1FFFFF; 
88     
89     // in 2's comp, negative numbers get 1 extra value
90     const int INT22_MIN = -(INT22_MAX+1);
91     
92     assert(INT22_MAX > 0);
93     assert(INT22_MIN < 0);
94     
95     if (offset < INT22_MIN) {
96         return false;
97     } else if (offset > INT22_MAX) {
98         return false;
99     } else {
100         return true;
101     }
102 }
103
104 void instruction::generateNOOP(codeGen &gen,
105                                unsigned size)
106 {
107     assert((size % instruction::size()) == 0);
108     instruction insn;
109
110     (*insn).raw = 0;
111     (*insn).branch.op = 0;
112     (*insn).branch.op2 = NOOPop2;
113     // logLine("nop\n");
114     while (size > 0) {
115         insn.generate(gen);
116         size -= instruction::size();
117     }
118 }
119
120 void instruction::generateTrapRegisterSpill(codeGen &gen) {
121     instruction insn;
122     (*insn).raw = SPILL_REGISTERS_INSN;
123     insn.generate(gen);
124 }
125
126 void instruction::generateFlushw(codeGen &gen) {
127     instruction insn;
128     
129     (*insn).raw = 0;
130     (*insn).rest.op = RESTop;
131     (*insn).rest.op3 = FLUSHWop3;
132     (*insn).rest.i = 0;
133     insn.generate(gen);
134 }
135
136 void instruction::generateBranch(codeGen &gen, int jump_off)
137 {
138     instruction insn;
139     
140     if (offsetWithinRangeOfBranchInsn(jump_off)) {
141         (*insn).raw = 0;
142         (*insn).branch.op = 0;
143         (*insn).branch.cond = BAcond;
144         (*insn).branch.op2 = BICCop2;
145         (*insn).branch.anneal = true;
146         (*insn).branch.disp22 = jump_off >> 2;
147         // logLine("ba,a %x\n", offset);
148         insn.generate(gen);
149     }
150     else {
151         instruction::generateImm(gen, SAVEop3, 14, -112, 14);
152         jump_off -= instruction::size(); // To compensate for the saveOp
153         // Copied from generateCall...
154         (*insn).raw = 0;
155         (*insn).call.op = 01;
156         (*insn).call.disp30 = jump_off >> 2;
157         insn.generate(gen);
158         instruction::generateSimple(gen, RESTOREop3, 0, 0, 0);
159     }
160 }
161
162 void instruction::generateBranch(codeGen &gen, Address from, Address to)
163 {
164     int disp = to - from;
165     generateBranch(gen, disp);
166 }
167
168 void instruction::generateCall(codeGen &gen, 
169                                Address fromAddr, 
170                                Address toAddr)
171 {
172     instruction insn;
173     int dist = toAddr - fromAddr;
174     (*insn).call.op = 01;
175     (*insn).call.disp30 = dist >> 2;
176     insn.generate(gen);
177 }
178
179 void instruction::generateJmpl(codeGen &gen, int rs1, int jump_off, 
180                                    int rd)
181 {
182     instruction insn;
183
184     (*insn).resti.op = 10;
185     (*insn).resti.rd = rd;
186     (*insn).resti.op3 = JMPLop3;
187     (*insn).resti.rs1 = rs1;
188     (*insn).resti.i = 1;
189     assert(jump_off >= MIN_IMM13 && jump_off <= MAX_IMM13);
190     (*insn).resti.simm13 = jump_off;
191     insn.generate(gen);
192 }    
193
194 void instruction::generateCondBranch(codeGen &gen, int jump_off, 
195                                      unsigned condition, bool annul) 
196 {
197     instruction insn;
198     
199     if (!offsetWithinRangeOfBranchInsn(jump_off)) {
200         char buffer[80];
201         sprintf(buffer, "a branch too far, jump_off=%d\n", jump_off);
202         logLine(buffer);
203         showErrorCallback(52, buffer);
204         abort();
205     }
206
207     (*insn).raw = 0;
208     (*insn).branch.op = 0;
209     (*insn).branch.cond = condition;
210     (*insn).branch.op2 = BICCop2;
211     (*insn).branch.anneal = annul;
212     (*insn).branch.disp22 = jump_off >> 2;
213     insn.generate(gen);
214 }
215
216 void instruction::generateAnnulledBranch(codeGen &gen, int 
217                                          jump_off)
218 {
219     generateCondBranch(gen, jump_off, BAcond, true);
220 }
221
222
223 void instruction::generateSimple(codeGen &gen, int op,
224         Register rs1, Register rs2, Register rd)
225 {
226     instruction insn;
227
228     (*insn).raw = 0;
229     (*insn).rest.op = RESTop;
230     (*insn).rest.rd = rd;
231     (*insn).rest.op3 = op;
232     (*insn).rest.rs1 = rs1;
233     (*insn).rest.rs2 = rs2;
234     insn.generate(gen);
235 }
236
237 void instruction::generateImm(codeGen &gen, int op,
238         Register rs1, int immd, Register rd)
239 {
240     instruction insn;
241
242     (*insn).raw = 0;
243     (*insn).resti.op = RESTop;
244     (*insn).resti.rd = rd;
245     (*insn).resti.op3 = op;
246     (*insn).resti.rs1 = rs1;
247     (*insn).resti.i = 1;
248     assert(immd >= MIN_IMM13 && immd <= MAX_IMM13);
249     (*insn).resti.simm13 = immd;
250     insn.generate(gen);
251 }
252
253 void instruction::generateImmRelOp(codeGen &gen, int cond, Register rs1,
254                         int immd, Register rd)
255 {
256     // cmp rs1, rs2
257     generateImm(gen, SUBop3cc, rs1, immd, 0);
258     // mov 1, rd
259     generateImm(gen, ORop3, 0, 1, rd);
260
261     // b??,a +2
262
263     generateCondBranch(gen, 2*instruction::size(), cond, true);
264
265     // clr rd
266     generateImm(gen, ORop3, 0, 0, rd);
267 }
268
269 void instruction::generateRelOp(codeGen &gen, int cond, Register rs1,
270                                 Register rs2, Register rd)
271 {
272     // cmp rs1, rs2
273     generateSimple(gen, SUBop3cc, rs1, rs2, 0);
274     // mov 1, rd
275     generateImm(gen, ORop3, 0, 1, rd);
276
277     // b??,a +2
278     generateCondBranch(gen, 2*instruction::size(), cond, true);
279
280     // clr rd
281     generateImm(gen, ORop3, 0, 0, rd);
282 }
283
284 void instruction::generateSetHi(codeGen &gen, int src1, int dest)
285 {
286     instruction insn;
287
288     (*insn).raw = 0;
289     (*insn).sethi.op = FMT2op;
290     (*insn).sethi.rd = dest;
291     (*insn).sethi.op2 = SETHIop2;
292     (*insn).sethi.imm22 = HIGH22(src1);
293     insn.generate(gen);
294 }
295
296 // st rd, [rs1 + jump_off]
297 void instruction::generateStore(codeGen &gen, int rd, int rs1, 
298                                 int store_off)
299 {
300     instruction insn;
301
302     (*insn).resti.op = STop;
303     (*insn).resti.rd = rd;
304     (*insn).resti.op3 = STop3;
305     (*insn).resti.rs1 = rs1;
306     (*insn).resti.i = 1;
307     assert(store_off >= MIN_IMM13 && store_off <= MAX_IMM13);
308     (*insn).resti.simm13 = store_off;
309     insn.generate(gen);
310 }
311
312 // sll rs1,rs2,rd
313 void instruction::generateLShift(codeGen &gen, int rs1, int shift, 
314                                  int rd)
315 {
316     instruction insn;
317
318     (*insn).restix.op = SLLop;
319     (*insn).restix.op3 = SLLop3;
320     (*insn).restix.rd = rd;
321     (*insn).restix.rs1 = rs1;
322     (*insn).restix.i = 1;
323     (*insn).restix.x = 0;
324     (*insn).restix.rs2 = shift;
325     insn.generate(gen);
326 }
327
328 // sll rs1,rs2,rd
329 void instruction::generateRShift(codeGen &gen, int rs1, int shift, 
330                                  int rd)
331 {
332     instruction insn;
333
334     (*insn).restix.op = SRLop;
335     (*insn).restix.op3 = SRLop3;
336     (*insn).restix.rd = rd;
337     (*insn).restix.rs1 = rs1;
338     (*insn).restix.i = 1;
339     (*insn).restix.x = 0;
340     (*insn).restix.rs2 = shift;
341     insn.generate(gen);
342 }
343
344 // load [rs1 + jump_off], rd
345 void instruction::generateLoad(codeGen &gen, int rs1, int load_off, 
346                                int rd)
347 {
348     instruction insn;
349
350     (*insn).resti.op = LOADop;
351     (*insn).resti.op3 = LDop3;
352     (*insn).resti.rd = rd;
353     (*insn).resti.rs1 = rs1;
354     (*insn).resti.i = 1;
355     assert(load_off >= MIN_IMM13 && load_off <= MAX_IMM13);
356     (*insn).resti.simm13 = load_off;
357     insn.generate(gen);
358 }
359
360 #if 0
361 // Unused
362 // swap [rs1 + jump_off], rd
363 void instruction::generateSwap(codeGen &gen, int rs1, int jump_off, 
364                                int rd)
365 {
366     instruction insn;
367
368     (*insn).resti.op = SWAPop;
369     (*insn).resti.rd = rd;
370     (*insn).resti.op3 = SWAPop3;
371     (*insn).resti.rs1 = rs1;
372     (*insn).resti.i = 0;
373     assert(jump_off >= MIN_IMM13 && jump_off <= MAX_IMM13);
374     (*insn).resti.simm13 = jump_off;
375 }    
376 #endif
377
378 // std rd, [rs1 + jump_off]
379 void instruction::generateStoreD(codeGen &gen, int rd, int rs1, 
380                             int store_off)
381 {
382     instruction insn;
383
384     (*insn).resti.op = STop;
385     (*insn).resti.rd = rd;
386     (*insn).resti.op3 = STDop3;
387     (*insn).resti.rs1 = rs1;
388     (*insn).resti.i = 1;
389     assert(store_off >= MIN_IMM13 && store_off <= MAX_IMM13);
390     (*insn).resti.simm13 = store_off;
391     insn.generate(gen);
392 }
393
394 // ldd [rs1 + jump_off], rd
395 void instruction::generateLoadD(codeGen &gen, int rs1, int load_off, 
396                            int rd)
397 {
398     instruction insn;
399
400     (*insn).resti.op = LOADop;
401     (*insn).resti.op3 = LDDop3;
402     (*insn).resti.rd = rd;
403     (*insn).resti.rs1 = rs1;
404     (*insn).resti.i = 1;
405     assert(load_off >= MIN_IMM13 && load_off <= MAX_IMM13);
406     (*insn).resti.simm13 = load_off;
407     insn.generate(gen);
408 }
409
410 // ldub [rs1 + jump_off], rd
411 void instruction::generateLoadB(codeGen &gen, int rs1, int load_off, 
412                            int rd)
413 {
414     instruction insn;
415
416     (*insn).resti.op = LOADop;
417     (*insn).resti.op3 = LDSBop3;
418     (*insn).resti.rd = rd;
419     (*insn).resti.rs1 = rs1;
420     (*insn).resti.i = 1;
421     assert(load_off >= MIN_IMM13 && load_off <= MAX_IMM13);
422     (*insn).resti.simm13 = load_off;
423     insn.generate(gen);
424 }
425
426 // lduh [rs1 + jump_off], rd
427 void instruction::generateLoadH(codeGen &gen, int rs1, int load_off, 
428                            int rd)
429 {
430     instruction insn;
431
432     (*insn).resti.op = LOADop;
433     (*insn).resti.op3 = LDSHop3;
434     (*insn).resti.rd = rd;
435     (*insn).resti.rs1 = rs1;
436     (*insn).resti.i = 1;
437     assert(load_off >= MIN_IMM13 && load_off <= MAX_IMM13);
438     (*insn).resti.simm13 = load_off;
439     insn.generate(gen);
440 }
441
442 // std rd, [rs1 + jump_off]
443 void instruction::generateStoreFD(codeGen &gen, int rd, int rs1, 
444                              int store_off)
445 {
446     instruction insn;
447
448     (*insn).resti.op = STop;
449     (*insn).resti.rd = rd;
450     (*insn).resti.op3 = STDFop3;
451     (*insn).resti.rs1 = rs1;
452     (*insn).resti.i = 1;
453     assert(store_off >= MIN_IMM13 && store_off <= MAX_IMM13);
454     (*insn).resti.simm13 = store_off;
455     insn.generate(gen);
456 }
457
458 // ldd [rs1 + jump_off], rd
459 void instruction::generateLoadFD(codeGen &gen, int rs1, int load_off, 
460                                  int rd)
461 {
462     instruction insn;
463     
464     (*insn).resti.op = LOADop;
465     (*insn).resti.op3 = LDDFop3;
466     (*insn).resti.rd = rd;
467     (*insn).resti.rs1 = rs1;
468     (*insn).resti.i = 1;
469     assert(load_off >= MIN_IMM13 && load_off <= MAX_IMM13);
470     (*insn).resti.simm13 = load_off;
471     insn.generate(gen);
472 }
473
474 /*
475  * Return the displacement of the relative call or branch instruction.
476  * 
477  */
478 int instruction::get_disp()
479 {
480
481   int disp = 0;
482   
483   // If the instruction is a CALL instruction
484   if (isInsnType(CALLmask, CALLmatch)) {
485       disp = (insn_.call.disp30 << 2);
486   } 
487   else {
488
489     // If the instruction is a Branch instruction
490       if (isInsnType(BRNCHmask, BRNCHmatch)||
491           isInsnType(FBRNCHmask, FBRNCHmatch)) {
492           disp = (insn_.branch.disp22 << 2);
493       }
494   }
495   return disp;
496 }
497
498
499 unsigned instruction::jumpSize(Address from, Address to, unsigned addr_width) {
500     int disp = (to - from);
501     return jumpSize(disp, addr_width);
502 }
503
504 unsigned instruction::jumpSize(int disp, unsigned /* addr_width */) {
505     if (offsetWithinRangeOfBranchInsn(disp)) {
506         return instruction::size();
507     }
508     else {
509         // Save/call/restore triplet
510         return 3*instruction::size();
511     }
512 }
513
514 unsigned instruction::maxJumpSize(unsigned /* addr_width */) {
515     // Save/call/restore triplet
516     return 3*instruction::size();
517 }
518
519 unsigned instruction::maxInterFunctionJumpSize(unsigned addr_width) {
520     return maxJumpSize(addr_width);
521 }
522
523 /****************************************************************************/
524
525 /****************************************************************************/
526
527 /*
528  * Upon setDisp being true, set the target of a relative jump or call insn.
529  * Otherwise, return 0
530  * 
531  */
532 void instruction::set_disp(bool setDisp, 
533                            int newOffset, bool /* outOfFunc */ ) 
534 {
535     if (!setDisp)
536         return;
537
538     // If the instruction is a CALL instruction
539     if (isInsnType(CALLmask, CALLmatch)) {
540         insn_.call.disp30 = newOffset >> 2;
541     }
542     else {
543         
544         // If the instruction is a Branch instruction
545         if (isInsnType(BRNCHmask, BRNCHmatch)||
546             isInsnType(FBRNCHmask, FBRNCHmatch)) {
547             insn_.branch.disp22 = newOffset >> 2;
548         }
549     }
550 }
551
552 bool instruction::generate(codeGen &gen,
553                            AddressSpace *proc,
554                            Address origAddr,
555                            Address relocAddr,
556                            patchTarget *fallthroughOverride,
557                            patchTarget *targetOverride) {
558     assert(fallthroughOverride == NULL);
559
560    Address targetAddr = targetOverride ? targetOverride->get_address() : 0;
561    long newLongOffset = 0;
562    
563    instruction newInsn(insn_);
564    
565    // TODO: check the function relocation for any PC-calculation tricks.
566    
567    // If the instruction is a CALL instruction, calculate the new
568    // offset
569    if (isInsnType(CALLmask, CALLmatch)) {
570       // Check to see if we're a "get-my-pc" combo.
571       // Two forms exist: call +8|+12, and call to a retl/nop 
572       // pair. This is very similar to x86, amusingly enough.
573       // If this is the case, we replace with an immediate load of 
574       // the PC.
575       
576       // FIXME The target offset heuristic is rough may not capture all
577       // cases. We should do a better job of detecting these false calls
578       // during parsing and use that information (instead of inspection of
579       // the individual call instruction) to determine whether this
580       // is a real call or a "get-my-pc" combo.
581       Address target = getTarget(origAddr);
582       if (target == origAddr + (2*instruction::size()))
583       {
584          inst_printf("Relocating get PC combo\n");
585          instruction::generateSetHi(gen, origAddr, REG_O(7));
586          instruction::generateImm(gen, ORop3, REG_O(7),
587                                   LOW10(origAddr), REG_O(7));
588       }
589       else if(target == origAddr + (3*instruction::size())) {
590          inst_printf("Relocating get PC combo (long form)\n");
591          // for this case, we want to make sure the intervening
592          // instructions are skipped, thereby preserving the
593          // semantics of the original binary
594          
595          // load the PC into o7
596          instruction::generateSetHi(gen, origAddr, REG_O(7));
597          instruction::generateImm(gen, ORop3, REG_O(7),
598                                   LOW10(origAddr), REG_O(7));
599          
600          // We've generated two instructions; update the offset accordingly
601          newLongOffset = (long)target - (relocAddr + 2*instruction::size());
602          //inst_printf("storing PC (0x%lx) into o7, adding branch to target 0x%lx (offset 0x%lx)\n",origAddr,target,newLongOffset);
603          instruction::generateBranch(gen,newLongOffset);
604       }
605       else if (proc->isValidAddress(target)) {
606          // Need to check the destination. Grab it with an InstrucIter
607          InstrucIter callTarget(target, proc);
608          instruction callInsn = callTarget.getInstruction();
609          
610          if (callInsn.isInsnType(RETLmask, RETLmatch)) {
611             inst_printf("%s[%d]: Call to immediate return\n", FILE__, __LINE__);
612             // The old version (in LocalAlteration-Sparc.C)
613             // is _incredibly_ confusing. This should work, 
614             // assuming an iterator-unwound delay slot.
615             // We had a call to a retl/delay pair. 
616             // Build O7, then copy over the delay slot.
617             instruction::generateSetHi(gen, origAddr, REG_O(7));
618             instruction::generateImm(gen, ORop3, REG_O(7),
619                                      LOW10(origAddr), REG_O(7));
620             callTarget++;
621             instruction nextInsn = callTarget.getInstruction();
622             if (nextInsn.valid()) {
623                nextInsn.generate(gen);
624             }
625          }
626          else {
627             if (!targetAddr) {
628                newLongOffset = origAddr;
629                newLongOffset -= relocAddr;
630                newLongOffset += (insn_.call.disp30 << 2);
631             }
632             else {
633                newLongOffset = targetAddr - relocAddr;
634             }
635             
636             (*newInsn).call.disp30 = (int)(newLongOffset >> 2);
637             
638             newInsn.generate(gen);
639             inst_printf("%s[%d]: Relocating call, displacement 0x%x, "
640                         "relocAddr = 0x%x\n", FILE__, __LINE__, 
641                         newLongOffset, relocAddr);
642          }
643       }
644    } else if (isInsnType(BRNCHmask, BRNCHmatch)||
645               isInsnType(FBRNCHmask, FBRNCHmatch)) {
646       
647       // If the instruction is a Branch instruction, calculate the 
648       // new offset. If the new offset is out of reach after the 
649       // instruction is moved to the base Trampoline, we would do
650       // the following:
651       //    b  address  ......    address: save
652       //                                   call new_offset             
653       //                                   restore 
654       if (!targetAddr)
655          newLongOffset = (long long)getTarget(origAddr) - relocAddr;
656       else
657          newLongOffset = targetAddr - relocAddr;
658       inst_printf("Orig 0x%x, target 0x%x (offset 0x%x), relocated 0x%x, "
659                   "new dist 0x%lx\n", origAddr, getTarget(origAddr), 
660                   getOffset(), relocAddr, newLongOffset);
661       // if the branch is too far, then allocate more space in inferior
662       // heap for a call instruction to branch target.  The base tramp 
663       // will branch to this new inferior heap code, which will call the
664       // target of the branch
665       
666       // XXX doesn't instruction::generateBranch take care of this for you?
667       
668       if (!instruction::offsetWithinRangeOfBranchInsn((int)newLongOffset)){
669          inst_printf("Relocating branch (orig 0x%lx to 0x%lx, now 0x%lx to "
670                      "0x%lx); new offset 0x%lx farther than branch range; " 
671                      "replacing with call\n", origAddr, getTarget(origAddr), 
672                      relocAddr, targetAddr ? targetAddr : getTarget(origAddr), 
673                      newLongOffset);
674          // Replace with a multi-branch series
675          instruction::generateImm(gen,
676                                   SAVEop3,
677                                   REG_SPTR,
678                                   -112,
679                                   REG_SPTR);
680          // Don't use relocAddr here, since we've moved the IP since then.
681          instruction::generateCall(gen,
682                                    relocAddr + instruction::size(),
683                                    targetAddr ? targetAddr : getTarget(origAddr));
684          instruction::generateSimple(gen,
685                                      RESTOREop3,
686                                      0, 0, 0);
687       } else {
688          (*newInsn).branch.disp22 = (int)(newLongOffset >> 2);
689          newInsn.generate(gen);
690       }
691    } else if (isInsnType(TRAPmask, TRAPmatch)) {
692       // There should be no probelm for moving trap instruction
693       // logLine("attempt to relocate trap\n");
694       generate(gen);
695    } 
696    else {
697       /* The rest of the instructions should be fine as is */
698       generate(gen);
699    }
700    return true;
701 }
702
703 /****************************************************************************/
704 /****************************************************************************/
705 /****************************************************************************/
706
707 InsnRegister::InsnRegister() 
708         : wordCount(0),
709           regType(InsnRegister::NoneReg),
710           regNumber(-1) {};
711
712 InsnRegister::InsnRegister(char isD,InsnRegister::RegisterType rt,
713                            short rn)
714         : wordCount(isD),
715           regType(rt),
716           regNumber(rn) {};
717
718 void InsnRegister::setWordCount(char isD) { wordCount = isD; }
719
720 void InsnRegister::setType(InsnRegister::RegisterType rt) { regType = rt ; }
721
722 void InsnRegister::setNumber(short rn) { regNumber = rn ; }
723
724 int InsnRegister::getWordCount() { return wordCount; }
725
726 InsnRegister::RegisterType InsnRegister::getType() { return regType; }
727
728 int InsnRegister::getNumber() { return regNumber; }
729
730 bool InsnRegister::is_o7(){
731         if(regType == InsnRegister::GlobalIntReg)
732                 for(int i=0;i<wordCount;i++)
733                         if((regNumber+i) == 0xf)
734                                 return true;
735         return false;
736 }
737
738 #define DEBUG
739 #ifdef DEBUG
740 void InsnRegister::print(){
741         switch(regType){
742                 case InsnRegister::GlobalIntReg: 
743                         cerr << "R[ "; break;
744                 case InsnRegister::FloatReg    : 
745                         cerr << "F[ "; break;
746                 case InsnRegister::CoProcReg   : 
747                         cerr << "C[ "; break;
748                 case InsnRegister::SpecialReg  : 
749                         cerr << "S[ "; break;
750                 default : 
751                         cerr << "NONE[ "; break;
752         }
753
754         if((regType != InsnRegister::SpecialReg) &&
755            (regType != InsnRegister::NoneReg))
756                 for(int i=0;i<wordCount;i++)
757                         cerr << regNumber+i;
758         cerr << "] ";
759 }
760 #endif
761
762
763 inline unsigned getMaxBranch3() {
764    // The length we can branch using 3 instructions
765    // isn't limited.
766    unsigned result = 1;
767    result <<= 31;
768    return result;
769
770    // probably returning ~0 would be better, since there's no limit
771 }
772
773 // "Casting" methods. We use a "base + offset" model, but often need to 
774 // turn that into "current instruction pointer".
775 instructUnion *instruction::insnPtr(codeGen &gen) {
776     return (instructUnion *)gen.cur_ptr();
777 }
778
779 // Same as above, but increment offset to point at the next insn.
780 instructUnion *instruction::ptrAndInc(codeGen &gen) {
781     instructUnion *ret = insnPtr(gen);
782     gen.moveIndex(instruction::size());
783     return ret;
784 }
785
786 void instruction::setInstruction(codeBuf_t *ptr, Address) {
787     instructUnion *insnPtr = (instructUnion *)ptr;
788     insn_ = *insnPtr;
789 }
790
791 void instruction::generate(codeGen &gen) {
792     instructUnion *ptr = ptrAndInc(gen);
793     *ptr = insn_;
794 }
795
796 void instruction::write(codeGen &gen) {
797     instructUnion *ptr = insnPtr(gen);
798     *ptr = insn_;
799 }
800
801 Address instruction::getOffset() const {
802     Address ret = 0;
803     if(insn_.branch.op == 0)
804         ret = insn_.branch.disp22;
805     else if(insn_.call.op == 0x1)
806         ret = insn_.call.disp30;
807     ret <<= 2;
808     return (Address)ret;
809 }
810
811 Address instruction::getTarget(Address addr) const {
812     return addr + getOffset();
813 }
814
815 unsigned instruction::size() {
816     return 4;
817 }
818
819 bool instruction::isCall() const {
820     return isTrueCallInsn() || isJmplCallInsn();
821 }
822
823 int registerNumberDecoding(unsigned reg, int word_size) {
824   if(word_size == SINGLE)
825     return reg;
826   if(word_size == DOUBLE) {
827     return ((reg & 1) << 5) + (reg & 30);
828   }
829   if(word_size == QUAD) {
830     return ((reg & 1) << 5) + (reg & 28);
831   }
832   fprintf(stderr,"Should have never reached here!\n");
833   return -1;
834 }
835
836 //void instruction::get_register_operands(InsnRegister* reads,InsnRegister* writes)
837 void instruction::get_register_operands()
838 {
839 #if 0
840   unsigned i;
841
842   for(i=0; i<7; i++)
843     reads[i] = InsnRegister();
844
845   for(i=0; i<5; i++)
846     writes[i] = InsnRegister();
847 #endif
848
849   if(!valid())
850      return;
851
852   // mark the annotations
853 #if 0
854   Annotatable<InsnRegister, register_read_set_a> &read_regs = *this;
855   Annotatable<InsnRegister, register_write_set_a> &write_regs = *this;
856 #endif
857   std::vector<InsnRegister> *read_regs_p = NULL;
858   std::vector<InsnRegister> *write_regs_p = NULL;
859
860   bool read_regs_exists = getAnnotation(read_regs_p, RegisterReadSetAnno);
861   bool write_regs_exists = getAnnotation(write_regs_p, RegisterWriteSetAnno);
862
863
864   //  check to see if we already have made these register sets
865   if (read_regs_exists || write_regs_exists) 
866   {
867      //  yep, ...  just return
868      return;
869   }
870
871   read_regs_p = new std::vector<InsnRegister>();
872   write_regs_p = new std::vector<InsnRegister>();
873
874   read_regs_exists = addAnnotation(read_regs_p, RegisterReadSetAnno);
875   write_regs_exists = addAnnotation(write_regs_p, RegisterWriteSetAnno);
876
877   if (!read_regs_exists)
878   {
879      fprintf(stderr, "%s[%d]:  addAnnotation failed here\n", FILE__, __LINE__);
880      return;
881   }
882
883   if (!write_regs_exists)
884   {
885      fprintf(stderr, "%s[%d]:  addAnnotation failed here\n", FILE__, __LINE__);
886      return;
887   }
888 #if 0
889   //  check to see if we already have made these register sets
890   if (read_regs.size() || write_regs.size()) {
891      //  yep, ...  just return
892      return;
893   }
894 #endif
895
896 #if 0
897   //  check to see if we already have made these register sets
898   if (read_regs.size() || write_regs.size()) {
899      //  yep, ...  just return them
900      for (unsigned int i = 0; i < 7; ++i) {
901         reads[i] = read_regs[i];
902      }
903      for (unsigned int i = 0; i < 5; ++i) {
904         writes[i] = write_regs[i];
905      }
906      return;
907   }
908 #endif
909
910 #if 0
911   int read = createAnnotationType("ReadSet");
912   int write = createAnnotationType("WriteSet");
913
914   InsnRegister* read1 = (InsnRegister*)getAnnotation(read);
915   InsnRegister* write1 = (InsnRegister*)getAnnotation(write);
916   if(0)
917      if(read1 != NULL || write1 != NULL) {
918         for(i=0; i<7; i++) {
919            Annotation* r = getAnnotation(read,i);
920            if(r != NULL) {
921               reads[i] = *((InsnRegister*)r->getItem());
922            }
923            else
924               break;
925         }
926         for(i=0; i<5; i++) {
927            Annotation* w = getAnnotation(write,i);
928            if(w != NULL) {
929               writes[i] = *((InsnRegister*)w->getItem());
930            }
931            else
932               break;
933         }
934         return;
935      }
936 #endif
937
938
939   std::vector<InsnRegister> reads;
940   std::vector<InsnRegister> writes;
941   reads.resize(8);
942   writes.resize(6);
943
944   switch(insn_.call.op){
945      case 0x0:
946         {
947            if((insn_.sethi.op2 == 0x4) &&
948                  (insn_.sethi.rd || insn_.sethi.imm22))
949               writes[0] = InsnRegister(1,
950                     InsnRegister::GlobalIntReg,
951                     (short)(insn_.sethi.rd));
952            else if(insn_.branch.op2 == BProp2)
953               reads[0] = InsnRegister(1,
954                     InsnRegister::GlobalIntReg,
955                     (short)(insn_.rest.rs1));
956            else if(insn_.branch.cond & 7) { // if not bpa or bpn
957               unsigned firstTag = (((unsigned)(insn_.branch.disp22)) >> 20) & 0x03;
958               if((insn_.sethi.op2 == Bop2icc) ||
959                     (insn_.sethi.op2 == BPop2cc && (!firstTag)))
960                  reads[0] = InsnRegister(1,InsnRegister::SpecialReg,ICC);
961               else if(insn_.sethi.op2 == BPop2cc && firstTag == 0x2)
962                  reads[0] = InsnRegister(1,InsnRegister::SpecialReg,XCC);
963               else if(insn_.sethi.op2 == FBop2fcc)
964                  reads[0] = InsnRegister(1,InsnRegister::SpecialReg,FCC0);
965               else if(insn_.sethi.op2 == FBPop2fcc)
966                  reads[0] = InsnRegister(1,InsnRegister::SpecialReg,FCC0 + firstTag); // Assuming FCC0, FCC1, FCC2 and FCC3 are adjacent
967            }
968            break;
969         }
970      case 0x1:
971         {
972            // call instruction writes to reg 15
973            writes[0] = InsnRegister(1,InsnRegister::GlobalIntReg,15);
974            break;             
975         }
976      case 0x2:
977         {
978            unsigned firstTag = insn_.rest.op3 & 0x30;
979            unsigned secondTag = insn_.rest.op3 & 0xf;
980
981            if((firstTag == 0x00) ||
982                  (firstTag == 0x10) ||
983                  ((firstTag == 0x20) && (secondTag < 0x8)) ||
984                  ((firstTag == 0x20) && (secondTag == 0xD)) || // TUGRUL: SDIVX
985                  ((firstTag == 0x30) && (secondTag >= 0x8)) ||
986                  ((firstTag == 0x30) && (secondTag < 0x4)))
987            {
988               reads[0] = InsnRegister(1, InsnRegister::GlobalIntReg,
989                     (short)(insn_.rest.rs1));
990               if(!insn_.rest.i)
991                  reads[1] = InsnRegister(1, InsnRegister::GlobalIntReg,
992                        (short)(insn_.rest.rs2));
993
994               if((firstTag == 0x30) && (secondTag == 0x0)) {
995                  switch(insn_.rest.rd) {
996                     case WRY: writes[0] = InsnRegister(1, InsnRegister::SpecialReg,REG_Y_reg); break; // WRY = 0
997                     case WRCCR: writes[0] = InsnRegister(1, InsnRegister::SpecialReg,REG_CCR); break; // WRCCR 2
998                     case WRASI: writes[0] = InsnRegister(1, InsnRegister::SpecialReg,REG_ASI); break; // WRASI 3
999                     case WRFPRS: writes[0] = InsnRegister(1, InsnRegister::SpecialReg,REG_FPRS); // WRFPRS 6
1000                  }
1001               }
1002               else if((firstTag == 0x30) && (secondTag == 0x2)) {
1003                  unsigned num = 0;
1004                  switch(insn_.rest.rd) {
1005                     case TPC: num = REG_TPC; break;
1006                     case TNPC: num = REG_TNPC; break;
1007                     case TSTATE: num = REG_TSTATE; break;
1008                     case TT: num = REG_TT; break;
1009                     case TICK_reg: num = REG_TICK; break;
1010                           case TBA: num = REG_TBA; break;
1011                           case PSTATE: num = REG_PSTATE; break;
1012                           case TL: num = REG_TL; break;
1013                           case PIL: num = REG_PIL; break;
1014                           case CWP: num = REG_CWP; break;
1015                           case CANSAVE: num = REG_CANSAVE; break;
1016                           case CANRESTORE: num = REG_CANRESTORE; break;
1017                           case CLEANWIN: num = REG_CLEANWIN; break;
1018                           case OTHERWIN: num = REG_OTHERWIN; break;
1019                           case WSTATE: num = REG_WSTATE; break;
1020                           }
1021                           if(num != 0)
1022                             writes[0] = InsnRegister(1, InsnRegister::SpecialReg, num);
1023                         }
1024                         else if((firstTag == 0x30) && ((secondTag == 0xC) ||secondTag == 0xD)) { // SAVE, RESTORE
1025                           reads[2] = InsnRegister(1, InsnRegister::SpecialReg,REG_CANSAVE);
1026                           if(!insn_.rest.i)
1027                             reads[3] = InsnRegister(1, InsnRegister::SpecialReg,REG_CANRESTORE);
1028                           else
1029                             reads[1] = InsnRegister(1, InsnRegister::SpecialReg,REG_CANRESTORE);
1030                           writes[0] = InsnRegister(1, InsnRegister::GlobalIntReg,(short)(insn_.rest.rd));                         
1031                           writes[1] = InsnRegister(1, InsnRegister::SpecialReg,REG_CANSAVE);
1032                           writes[2] = InsnRegister(1, InsnRegister::SpecialReg,REG_CANRESTORE);
1033                         }
1034                         else if((firstTag == 0x30) && (secondTag == 0xA)) { // Tcc
1035                           unsigned code = ((insn_.rest.unused >> 6) & 3)==0 ? ICC : XCC;
1036                           if(!insn_.rest.i)
1037                             reads[2] = InsnRegister(1, InsnRegister::SpecialReg,code);
1038                           else
1039                             reads[1] = InsnRegister(1, InsnRegister::SpecialReg,code);
1040                           writes[0] = InsnRegister(1, InsnRegister::GlobalIntReg,(short)(insn_.rest.rd));
1041                         }
1042                         // else if((firstTag == 0x30) && (secondTag < 0x4))
1043                         //  *rd = InsnRegister(1, InsnRegister::SpecialReg, -1);// XXX
1044                         else if((firstTag != 0x30) || 
1045                                 (secondTag <= 0x8) || 
1046                                 (secondTag >= 0xc))
1047                           writes[0] = InsnRegister(1, InsnRegister::GlobalIntReg,(short)(insn_.rest.rd));
1048                     }
1049                 else if((firstTag == 0x20) )//&& (secondTag >= 0x8))
1050                     {
1051                       if(secondTag == 0x8) {
1052                         switch(insn_.rest.rs1) {
1053                         case 0: reads[0] = InsnRegister(1, InsnRegister::SpecialReg,REG_Y_reg); break;
1054                         case 2: reads[0] = InsnRegister(1, InsnRegister::SpecialReg,REG_CCR); break;
1055                         case 3: reads[0] = InsnRegister(1, InsnRegister::SpecialReg,REG_ASI); break;
1056                         case 4: reads[0] = InsnRegister(1, InsnRegister::SpecialReg,REG_TICK); break;
1057                         case 5: reads[0] = InsnRegister(1, InsnRegister::SpecialReg,REG_PC_reg); break;
1058                         case 6: reads[0] = InsnRegister(1, InsnRegister::SpecialReg,REG_FPRS); break;
1059                         case 15: break; // STBAR or MEMBAR
1060                         }
1061                         writes[0] = InsnRegister(1, InsnRegister::GlobalIntReg,
1062                                            (short)(insn_.restix.rd));
1063                       }
1064                       else if(secondTag == 0xA) { // RDPR
1065                         switch(insn_.rest.rs1) {
1066                         case 0: reads[0] = InsnRegister(1, InsnRegister::SpecialReg,REG_TPC); break;
1067                         case 1: reads[0] = InsnRegister(1, InsnRegister::SpecialReg,REG_TNPC); break;
1068                         case 2: reads[0] = InsnRegister(1, InsnRegister::SpecialReg,REG_TSTATE); break;
1069                         case 3: reads[0] = InsnRegister(1, InsnRegister::SpecialReg,REG_TT); break;
1070                         case 4: reads[0] = InsnRegister(1, InsnRegister::SpecialReg,REG_TICK); break;
1071                         case 5: reads[0] = InsnRegister(1, InsnRegister::SpecialReg,REG_TBA); break;
1072                         case 6: reads[0] = InsnRegister(1, InsnRegister::SpecialReg,REG_PSTATE); break;
1073                         case 7: reads[0] = InsnRegister(1, InsnRegister::SpecialReg,REG_TL); break;
1074                         case 8: reads[0] = InsnRegister(1, InsnRegister::SpecialReg,REG_PIL); break;
1075                         case 9: reads[0] = InsnRegister(1, InsnRegister::SpecialReg,REG_CWP); break;
1076                         case 10: reads[0] = InsnRegister(1, InsnRegister::SpecialReg,REG_CANSAVE); break;
1077                         case 11: reads[0] = InsnRegister(1, InsnRegister::SpecialReg,REG_CANRESTORE); break;
1078                         case 12: reads[0] = InsnRegister(1, InsnRegister::SpecialReg,REG_CLEANWIN); break;
1079                         case 13: reads[0] = InsnRegister(1, InsnRegister::SpecialReg,REG_OTHERWIN); break;
1080                         case 14: reads[0] = InsnRegister(1, InsnRegister::SpecialReg,REG_WSTATE); break;
1081                         case 15: reads[0] = InsnRegister(1, InsnRegister::SpecialReg,REG_FQ); break;
1082                         case 31: reads[0] = InsnRegister(1, InsnRegister::SpecialReg,REG_VER); break;
1083                         }
1084                         writes[0] = InsnRegister(1, InsnRegister::GlobalIntReg,
1085                                            (short)(insn_.restix.rd));
1086                       }
1087                       else if(secondTag == 0xC) { // MOVcc
1088                         //                      int counter=0;
1089                         unsigned cc1_cc0 = (insn_.rest.unused >> 11) & 0x03;
1090                         unsigned all = ((insn_.rest.rs1 >> 2 ) & 0x04) + cc1_cc0;
1091                         short cc = FCC0;
1092                         switch(all) {
1093                         case 0:
1094                         case 1:
1095                         case 2:
1096                         case 3: cc += all; break;
1097                         case 4: cc = ICC; break;
1098                         case 6: cc = XCC;
1099                         }
1100                         if(insn_.resti.i == 0) {
1101                           reads[0] = InsnRegister(1,InsnRegister::GlobalIntReg,
1102                                               (short)(insn_.rest.rs2));
1103                           if((insn_.rest.rs1 & 0x07) != 0) { // if the cond field (last 4 bits of rs1:5) is 1000 or 0000 (meaning if last 3 bits of rs1 is 000), then move never or move always
1104                             reads[1] = InsnRegister(1,InsnRegister::SpecialReg,cc);
1105                           }
1106                         }
1107                         else{
1108                           if((insn_.rest.rs1 & 0x07) != 0) { // if the cond field (last 4 bits of rs1:5) is 1000 or 0000 (meaning if last 3 bits of rs1 is 000), then move never or move always
1109                             reads[0] = InsnRegister(1,InsnRegister::SpecialReg,cc);
1110                           }
1111                         }
1112                         writes[0] = InsnRegister(1, InsnRegister::GlobalIntReg,
1113                                            (short)(insn_.restix.rd));
1114                       }
1115                       else if(secondTag == 0xE) { // POPC = 0x2E = 46
1116                         if(insn_.resti.rs1 == 0) {
1117                           if(insn_.resti.i == 0) {
1118                             reads[0] = InsnRegister(1, InsnRegister::GlobalIntReg,insn_.rest.rs2);
1119                           }
1120                           writes[0] = InsnRegister(1, InsnRegister::GlobalIntReg,(short)(insn_.restix.rd));
1121                         }
1122                       }
1123                       else if(secondTag == 0xF) { // MOVr = 0x2F = 47
1124                         // unsigned rcond = ((*i).rest.unused >> 5) & 0x07; // this is rcond:3, I need only the last 2 bits
1125                         if(((insn_.rest.unused >> 5) & 0x03) != 0) {
1126                           reads[0] = InsnRegister(1, InsnRegister::GlobalIntReg,insn_.rest.rs1);
1127                           if(insn_.rest.i == 0)
1128                             reads[1] = InsnRegister(1, InsnRegister::GlobalIntReg,insn_.rest.rs2);
1129                           writes[0] = InsnRegister(1, InsnRegister::GlobalIntReg,(short)(insn_.rest.rd));
1130                         }
1131                       }
1132                       
1133                       reads[0] = InsnRegister(1, InsnRegister::SpecialReg, -1);
1134                       writes[0] = InsnRegister(1, InsnRegister::GlobalIntReg,
1135                                          (short)(insn_.restix.rd));
1136                     }
1137                 else if((secondTag == 0x6) || (secondTag == 0x7)) // firstTag=0x30
1138                     {
1139                         reads[0] = InsnRegister(1, InsnRegister::CoProcReg,
1140                                             (short)(insn_.restix.rs1));
1141                         reads[1] = InsnRegister(1, InsnRegister::CoProcReg,
1142                                             (short)(insn_.restix.rs2));
1143                         writes[0] = InsnRegister(1, InsnRegister::CoProcReg,
1144                                            (short)(insn_.restix.rd));
1145                     }
1146                 else if((secondTag == 0x4) || (secondTag == 0x5)) // firstTag=0x30
1147                     {
1148                         char wC = 0;
1149                         firstTag = insn_.rest.unused & 0xf0;
1150                         unsigned thirdTag = insn_.rest.unused & 0xf;
1151                         switch(insn_.rest.unused & 0x03){
1152                         case 0x0:
1153                           if(firstTag==0xC0) // FiTO(s,d,q)
1154                             wC=1;
1155                           else // FxTO(s,d,q)
1156                             wC=2;
1157                           break;
1158                         case 0x1: wC = 1; break;
1159                         case 0x2: wC = 2; break;
1160                         case 0x3: wC = 4; break;
1161                         default: break; 
1162                         }
1163                         
1164                         reads[1] = InsnRegister(wC, InsnRegister::FloatReg,
1165                                             (short)(insn_.rest.rs2));
1166                         
1167                         if((firstTag == 0x40) || (firstTag == 0x60) || /*TUGRUL: for FCMP instruction family*/ (firstTag == 0x50)) {
1168                             reads[0] = reads[1];
1169                             reads[0].setNumber((short)(insn_.rest.rs1));
1170                         }
1171                         
1172                         if(firstTag < 0x50 || (secondTag == 0x5 && firstTag != 0x50)){
1173                             writes[0] = reads[1];
1174                             writes[0].setNumber((short)(insn_.rest.rd));
1175                         }
1176                         else if(firstTag != 0x50) { // FCMP family is excluded
1177                           if(firstTag == 0x80 && thirdTag < 0x4) // FsTOx, FdTOx, FqTOx
1178                             wC = 2;
1179                           else if(thirdTag < 0x8)
1180                             wC = 1;
1181                           else if(thirdTag < 0xc)
1182                             wC = 2;
1183                           else
1184                             wC = 4;
1185                           
1186                           writes[0] = InsnRegister(wC, InsnRegister::FloatReg,
1187                                              (short)(insn_.rest.rd));
1188                         }
1189
1190                         // floating point condition codes
1191                         if(secondTag == 0x5 && thirdTag < 0x4) {
1192                           unsigned opf = ((insn_.rest.i << 8) | insn_.rest.unused) & 0x1FF;
1193                           switch(opf) {
1194                           case 0x000: reads[2] = InsnRegister(1, InsnRegister::SpecialReg,FCC0); break;
1195                           case 0x040: reads[2] = InsnRegister(1, InsnRegister::SpecialReg,FCC1); break;
1196                           case 0x050: writes[0] = InsnRegister(1, InsnRegister::SpecialReg,FCC0 + (insn_.rest.rd & 3)); break;
1197                           case 0x080: reads[2] = InsnRegister(1, InsnRegister::SpecialReg,FCC2); break;
1198                           case 0x0C0: reads[2] = InsnRegister(1, InsnRegister::SpecialReg,FCC3); break;
1199                           case 0x100: reads[2] = InsnRegister(1, InsnRegister::SpecialReg,ICC); break;
1200                           case 0x180: reads[2] = InsnRegister(1, InsnRegister::SpecialReg,XCC); break;
1201                           }
1202                         }
1203                     }
1204
1205
1206                 // Handle Condition Codes
1207                 firstTag = insn_.rest.op3 & 0x30;
1208                 secondTag = insn_.rest.op3 & 0x3C;
1209                 if((firstTag == 0x10) || (secondTag == 0x20)) {
1210                   writes[1] = InsnRegister(1, InsnRegister::SpecialReg, ICC);
1211                   writes[2] = InsnRegister(1, InsnRegister::SpecialReg, XCC);
1212                 }
1213
1214                 firstTag = insn_.rest.op3 & 0x2B;
1215                 if(firstTag == 0x08) { // ADDC, ADDCcc, SUBC and SUBCcc
1216                   reads[2] = InsnRegister(1, InsnRegister::SpecialReg, ICC);
1217                 }
1218                 break;
1219             }
1220         case 0x3:
1221             {
1222                 char wC = 1;
1223                 InsnRegister::RegisterType rt = InsnRegister::NoneReg;
1224                 short rn = -1;
1225                 
1226                 unsigned firstTag = insn_.rest.op3 & 0x30;
1227                 unsigned secondTag = insn_.rest.op3 & 0xf;
1228                 
1229                 if(firstTag >= 0x20 && (secondTag == 0x2 || secondTag == 0x6)) { // LDQF, LDQFA, STQF, STQFA
1230                   wC = 4;
1231                 }
1232                 else if((secondTag == 0x3) ||
1233                    (secondTag == 0x7))
1234                     wC = 2;
1235
1236                 reads[0] = InsnRegister(1, InsnRegister::GlobalIntReg,
1237                                     (short)(insn_.rest.rs1));
1238                 if(!insn_.rest.i)
1239                     reads[1] = InsnRegister(1, InsnRegister::GlobalIntReg,
1240                                         (short)(insn_.rest.rs2));
1241
1242                 switch(firstTag){
1243                 case 0x00:
1244                 case 0x10:
1245                     rt = InsnRegister::GlobalIntReg;
1246                     rn = (short)(insn_.rest.rd);
1247                     break;
1248                 case 0x20:
1249                 case 0x30:
1250                     if((secondTag == 0x1) ||
1251                        (secondTag == 0x5) ||
1252                        (secondTag == 0x6))
1253                         rt = InsnRegister::SpecialReg;
1254                     else{
1255                       if(firstTag == 0x20 /*|| (firstTag == 0x30 && secondTag <= 0xB)*/)
1256                         rt = InsnRegister::FloatReg;
1257                       else if(firstTag == 0x30)
1258                         rt = InsnRegister::CoProcReg;
1259                       rn = (short)(insn_.rest.rd);
1260                     }
1261                     break;
1262                 default: break;
1263                 }
1264
1265                 if(firstTag >= 0x20) {
1266                   if(secondTag == 0x2 || secondTag == 0x6) {
1267                     rn = registerNumberDecoding(insn_.rest.rd,QUAD);
1268                   }
1269                   else if(secondTag == 0x3 || secondTag == 0x7) {
1270                     rn = registerNumberDecoding(insn_.rest.rd,DOUBLE);
1271                   }
1272                 }
1273                 // if store instruction, reads all three registers.
1274                 if((firstTag <= 0x10 && ((secondTag >= 0x4 && secondTag <= 0x7) || secondTag == 0xE))
1275                   || (firstTag >= 0x20 && (secondTag == 0x6 || secondTag == 0x7 || secondTag == 0x4))) {
1276                   if(!insn_.rest.i)
1277                     reads[2] = InsnRegister(wC, rt,rn);
1278                   else
1279                     reads[1] = InsnRegister(wC, rt,rn);
1280                 }
1281                 else if(firstTag == 0x20 && secondTag == 0x1) { // LDFSR
1282                   writes[0] = InsnRegister(1, InsnRegister::SpecialReg,FSR);
1283                   writes[1] = InsnRegister(1, InsnRegister::SpecialReg,FCC0);
1284                   writes[2] = InsnRegister(1, InsnRegister::SpecialReg,FCC1);
1285                   writes[3] = InsnRegister(1, InsnRegister::SpecialReg,FCC2);
1286                   writes[4] = InsnRegister(1, InsnRegister::SpecialReg,FCC3);
1287                 }
1288                 else if(firstTag == 0x20 && secondTag == 0x5) { // STFSR
1289                   if(!insn_.rest.i)
1290                     reads[6] = InsnRegister(1, InsnRegister::SpecialReg,FSR);
1291                   else
1292                     reads[1] = InsnRegister(1, InsnRegister::SpecialReg,FSR);
1293                   reads[2] = InsnRegister(1, InsnRegister::SpecialReg,FCC0);
1294                   reads[3] = InsnRegister(1, InsnRegister::SpecialReg,FCC1);
1295                   reads[4] = InsnRegister(1, InsnRegister::SpecialReg,FCC2);
1296                   reads[5] = InsnRegister(1, InsnRegister::SpecialReg,FCC3);
1297                 }
1298                 else if(firstTag < 0x20 || secondTag != 0xD) { // all but PREFETCH and PREFETCHA
1299                   writes[0] = InsnRegister(wC,rt,rn);
1300                   if(firstTag == 0x30 && (secondTag == 0xC || secondTag == 0xE)) { // CASA, CASXA
1301                     if(!insn_.rest.i)
1302                       reads[2] = InsnRegister(1, InsnRegister::GlobalIntReg, (short)(insn_.rest.rd));
1303                     else
1304                       reads[1] = InsnRegister(1, InsnRegister::GlobalIntReg, (short)(insn_.rest.rd));
1305                   }
1306                 }
1307                 break;
1308             }
1309         default:
1310             break;
1311         }
1312
1313   if (reads.size() > 8)
1314      fprintf(stderr, "%s[%d]:  WARNING:  unexpected size for read registers\n", FILE__, __LINE__, reads.size());
1315
1316   for (unsigned int i = 0; i < reads.size(); ++i) {
1317      if (reads[i].getNumber() == -1)
1318         break;
1319      read_regs_p->push_back(reads[i]);
1320 #if 0
1321      read_regs.addAnnotation(reads[i]);
1322 #endif
1323   }
1324
1325
1326
1327   if (writes.size() > 6)
1328      fprintf(stderr, "%s[%d]:  WARNING:  unexpected size for write registers\n", FILE__, __LINE__, writes.size());
1329
1330   for (unsigned int i = 0; i < writes.size(); ++i) {
1331      if (writes[i].getNumber() == -1)
1332         break;
1333      write_regs_p->push_back(writes[i]);
1334 #if 0
1335      write_regs.addAnnotation(writes[i]);
1336 #endif
1337   }
1338
1339 #if 0
1340 #if 0
1341   // mark the annotations
1342         read = createAnnotationType("ReadSet");
1343         write = createAnnotationType("WriteSet");
1344 #endif
1345
1346         for(i=0; i<7; i++) {
1347       read_regs.addAnnotation(reads[i]);
1348 #if 0
1349           if(reads[i].getNumber() != -1) {
1350             setAnnotation(read,new Annotation(&(reads[i])));
1351           }
1352           else
1353             break;
1354 #endif
1355         }
1356         for(i=0; i<5; i++) {
1357         write_regs.addAnnotation(writes[i]);
1358 #if 0
1359           if(writes[i].getNumber() != -1) {
1360             setAnnotation(write,new Annotation(&(writes[i])));
1361           }
1362           else
1363             break;
1364 #endif
1365         }
1366 #endif  
1367         return;
1368 }
1369
1370
1371 unsigned instruction::spaceToRelocate() const {
1372     
1373     unsigned size_required = 0;
1374
1375     if (isInsnType(CALLmask, CALLmatch)) {
1376         // We can use the same format.
1377       // We may need 3 more words if it's a getPC jump.
1378         size_required += 4*instruction::size();
1379     } else if (isInsnType(BRNCHmask, BRNCHmatch) ||
1380                isInsnType(FBRNCHmask, FBRNCHmatch)) {
1381         // Worst case: 3 insns (save, call, restore)
1382         size_required += 3*instruction::size();
1383     }
1384     else {
1385         // Relocate "in place"
1386         size_required += instruction::size();
1387     }
1388     
1389     if (isDCTI()) {
1390         size_required += 2*instruction::size();
1391     }
1392
1393     return size_required;
1394 }
1395
1396 bool instruction::generateMem(codeGen &,
1397                               Address, 
1398                               Address,
1399                               Register,
1400                   Register) {return false; }
1401
1402 bool instruction::getUsedRegs(pdvector<int> &) {
1403         return false;
1404
1405 }