Added some more #ifdef BPATCH_LIBRARYs to eliminate some Dyninst API
[dyninst.git] / dyninstAPI / src / inst-sparc.h
1 /*
2  * Copyright (c) 1996 Barton P. Miller
3  * 
4  * We provide the Paradyn Parallel Performance Tools (below
5  * described as Paradyn") on an AS IS basis, and do not warrant its
6  * validity or performance.  We reserve the right to update, modify,
7  * or discontinue this software at any time.  We shall have no
8  * obligation to supply such updates or modifications or any other
9  * form of support to you.
10  * 
11  * This license is for research uses.  For such uses, there is no
12  * charge. We define "research use" to mean you may freely use it
13  * inside your organization for whatever purposes you see fit. But you
14  * may not re-distribute Paradyn or parts of Paradyn, in any form
15  * source or binary (including derivatives), electronic or otherwise,
16  * to any other organization or entity without our permission.
17  * 
18  * (for other uses, please contact us at paradyn@cs.wisc.edu)
19  * 
20  * All warranties, including without limitation, any warranty of
21  * merchantability or fitness for a particular purpose, are hereby
22  * excluded.
23  * 
24  * By your use of Paradyn, you understand and agree that we (or any
25  * other person or entity with proprietary rights in Paradyn) are
26  * under no obligation to provide either maintenance services,
27  * update services, notices of latent defects, or correction of
28  * defects for Paradyn.
29  * 
30  * Even if advised of the possibility of such damages, under no
31  * circumstances shall we (or any other person or entity with
32  * proprietary rights in the software licensed hereunder) be liable
33  * to you or any third party for direct, indirect, or consequential
34  * damages of any character regardless of type of action, including,
35  * without limitation, loss of profits, loss of use, loss of good
36  * will, or computer failure or malfunction.  You agree to indemnify
37  * us (and any other person or entity with proprietary rights in the
38  * software licensed hereunder) for any and all liability it may
39  * incur to third parties resulting from your use of Paradyn.
40  */
41
42 #if !defined(sparc_sun_sunos4_1_3) && !defined(sparc_sun_solaris2_4)
43 #error "invalid architecture-os inclusion"
44 #endif
45
46 #ifndef INST_SPARC_H
47 #define INST_SPARC_H
48
49 #include "util/h/headers.h"
50 #ifndef BPATCH_LIBRARY
51 #include "rtinst/h/rtinst.h"
52 #endif
53 #include "dyninstAPI/src/symtab.h"
54 #include "dyninstAPI/src/process.h"
55 #include "dyninstAPI/src/inst.h"
56 #include "dyninstAPI/src/ast.h"
57 //#include "dyninstAPI/src/inst-sparc.h"
58 #include "dyninstAPI/src/arch-sparc.h"
59 #include "dyninstAPI/src/util.h"
60 #include "dyninstAPI/src/stats.h"
61 #include "dyninstAPI/src/os.h"
62 #include "paradynd/src/showerror.h"
63 #include "dyninstAPI/src/as-sparc.h"
64 #include "dyninstAPI/src/instP.h"
65
66 #define REG_MT               23   /* register saved to keep the address of */
67                                   /* the current vector of counter/timers  */
68                                   /* for each thread.                      */
69 #define NUM_INSN_MT_PREAMBLE  9   /* number of instructions required for   */
70                                   /* the MT preamble.                      */ 
71
72 // NOTE: LOW() and HIGH() can return ugly values if x is negative, because in
73 // that case, 2's complement has really changed the bitwise representation!
74 // Perhaps an assert should be done!
75 #define LOW10(x) ((x) & 0x3ff)
76 #define LOW13(x) ((x) & 0x1fff)
77 #define HIGH22(x) ((x) >> 10)
78
79 inline unsigned ABS(int x) {
80    if (x < 0) return -x;
81    return x;
82 }
83 //#define ABS(x)                ((x) > 0 ? x : -x)
84
85 //#define MAX_BRANCH    (0x1<<23)
86
87 #define MAX_IMM13       (4095)
88 #define MIN_IMM13       (-4096)
89
90
91 #define REG_G0          0
92 #define REG_G5          5
93 #define REG_G6          6
94 #define REG_G7          7
95
96 #define REG_O7          15
97
98 #define REG_L0          16
99 #define REG_L1          17
100 #define REG_L2          18
101
102 #define REG_SP          14
103 #define REG_FP          30
104
105 extern "C" void baseTramp();
106 extern trampTemplate baseTemplate;
107 extern registerSpace *regSpace;
108 extern int deadList[];
109 extern instruction newInstr[1024];
110
111 class instPoint;
112
113 inline unsigned getMaxBranch3Insn() {
114    // The length we can branch using 3 instructions
115    // isn't limited.
116    unsigned result = 1;
117    result <<= 31;
118    return result;
119
120    // probably returning ~0 would be better, since there's no limit
121 }
122
123 //inline unsigned getMaxBranch1Insn() {
124 //   // The length we can branch using just 1 instruction is dictated by the
125 //   // sparc instruction set.
126 //   return (0x1 << 23);
127 //}
128
129 inline bool offsetWithinRangeOfBranchInsn(int offset) {
130    // The pc-relative offset range which we can branch to with a single sparc
131    // branch instruction is dictated by the sparc instruction set.
132    // There are 22 bits available...however, you really get 2 extra bits
133    // because the CPU multiplies the 22-bit signed offset by 4.
134    // The only downside is that the offset must be a multiple of 4, which we check.
135    unsigned abs_offset = ABS(offset);
136    assert(abs_offset % 4 == 0);
137
138    // divide by 4.  After the divide, the result must fit in 22 bits.
139    offset /= 4;
140
141    const int INT22_MAX = 0x1FFFFF; // low 21 bits all 1's, the high bit (#22) is 0
142    const int INT22_MIN = -(INT22_MAX+1); // in 2's comp, negative numbers get 1 extra value
143    assert(INT22_MAX > 0);
144    assert(INT22_MIN < 0);
145
146    if (offset < INT22_MIN)
147       return false;
148    else if (offset > INT22_MAX)
149       return false;
150    else
151       return true;
152 }
153
154 inline bool in1BranchInsnRange(unsigned adr1, unsigned adr2) 
155 {
156     return (abs(adr1-adr2) < (0x1 << 23));
157 }
158
159 inline void generateNOOP(instruction *insn)
160 {
161     insn->raw = 0;
162     insn->branch.op = 0;
163     insn->branch.op2 = NOOPop2;
164
165     // logLine("nop\n");
166 }
167
168 inline void generateBranchInsn(instruction *insn, int offset)
169 {
170     if (!offsetWithinRangeOfBranchInsn(offset)) {
171         char buffer[100];
172         sprintf(buffer, "a Branch too far; offset=%d\n", offset);
173         logLine(buffer);
174         //showErrorCallback(52, "");
175         assert(false && "a Branch too far");
176         return;
177     }
178
179     insn->raw = 0;
180     insn->branch.op = 0;
181     insn->branch.cond = BAcond;
182     insn->branch.op2 = BICCop2;
183     insn->branch.anneal = true;
184     insn->branch.disp22 = offset >> 2;
185
186     // logLine("ba,a %x\n", offset);
187 }
188
189 inline void generateCallInsn(instruction *insn, int fromAddr, int toAddr)
190 {
191     int offset = toAddr - fromAddr;
192     insn->call.op = 01;
193     insn->call.disp30 = offset >> 2;
194 }
195
196 inline void generateJmplInsn(instruction *insn, int rs1, int offset, int rd)
197 {
198     insn->resti.op = 10;
199     insn->resti.rd = rd;
200     insn->resti.op3 = JMPLop3;
201     insn->resti.rs1 = rs1;
202     insn->resti.i = 1;
203     assert(offset >= MIN_IMM13 && offset <= MAX_IMM13);
204     insn->resti.simm13 = offset;
205 }    
206
207 inline void genBranch(instruction *insn, int offset, unsigned condition, bool annul)
208 {
209 //    if (ABS(offset) > getMaxBranch1Insn()) {
210     if (!offsetWithinRangeOfBranchInsn(offset)) {
211         char buffer[80];
212         sprintf(buffer, "a branch too far, offset=%d\n", offset);
213         logLine(buffer);
214         showErrorCallback(52, "");
215         abort();
216     }
217
218     insn->raw = 0;
219     insn->branch.op = 0;
220     insn->branch.cond = condition;
221     insn->branch.op2 = BICCop2;
222     insn->branch.anneal = annul;
223     insn->branch.disp22 = offset >> 2;
224 }
225
226 inline void generateAnnulledBranchInsn(instruction *insn, int offset)
227 {
228     genBranch(insn, offset, BAcond, true);
229 }
230
231
232 inline void genSimpleInsn(instruction *insn, int op, reg rs1, reg rs2, reg rd)
233 {
234     insn->raw = 0;
235     insn->rest.op = RESTop;
236     insn->rest.rd = rd;
237     insn->rest.op3 = op;
238     insn->rest.rs1 = rs1;
239     insn->rest.rs2 = rs2;
240 }
241
242 inline void genBreakpointTrap(instruction *insn) {
243    insn->raw = BREAK_POINT_INSN; // ta (trap always) 1
244 }
245
246 inline void genUnimplementedInsn(instruction *insn) {
247    insn->raw = 0; // UNIMP 0
248 }
249
250 inline void genImmInsn(instruction *insn, int op, reg rs1, int immd, reg rd)
251 {
252     insn->raw = 0;
253     insn->resti.op = RESTop;
254     insn->resti.rd = rd;
255     insn->resti.op3 = op;
256     insn->resti.rs1 = rs1;
257     insn->resti.i = 1;
258     assert(immd >= MIN_IMM13 && immd <= MAX_IMM13);
259     insn->resti.simm13 = immd;
260 }
261
262 inline void genImmRelOp(instruction *insn, int cond, reg rs1,
263                         int immd, reg rd, unsigned &base)
264 {
265     // cmp rs1, rs2
266     genImmInsn(insn, SUBop3cc, rs1, immd, 0); insn++;
267     // mov 1, rd
268     genImmInsn(insn, ORop3, 0, 1, rd); insn++;
269
270     // b??,a +2
271     insn->branch.op = 0;
272     insn->branch.cond = cond;
273     insn->branch.op2 = BICCop2;
274     insn->branch.anneal = true;
275     insn->branch.disp22 = 2;
276     insn++;
277
278     // clr rd
279     genImmInsn(insn, ORop3, 0, 0, rd); insn++; 
280     //genSimpleInsn(insn, ORop3, 0, 0, rd); insn++;
281     base += 4 * sizeof(instruction);
282 }
283
284 inline void genRelOp(instruction *insn, int cond, reg rs1,
285                      reg rs2, reg rd, unsigned &base)
286 {
287     // cmp rs1, rs2
288     genSimpleInsn(insn, SUBop3cc, rs1, rs2, 0); insn++;
289     // mov 1, rd
290     genImmInsn(insn, ORop3, 0, 1, rd); insn++;
291
292     // b??,a +2
293     insn->branch.op = 0;
294     insn->branch.cond = cond;
295     insn->branch.op2 = BICCop2;
296     insn->branch.anneal = true;
297     insn->branch.disp22 = 2;
298     insn++;
299
300     // clr rd
301     genImmInsn(insn, ORop3, 0, 0, rd); insn++;
302     //genSimpleInsn(insn, ORop3, 0, 0, rd); insn++;
303     base += 4 * sizeof(instruction);
304 }
305
306 inline void generateSetHi(instruction *insn, int src1, int dest)
307 {
308     insn->raw = 0;
309     insn->sethi.op = FMT2op;
310     insn->sethi.rd = dest;
311     insn->sethi.op2 = SETHIop2;
312     insn->sethi.imm22 = HIGH22(src1);
313 }
314
315 // st rd, [rs1 + offset]
316 inline void generateStore(instruction *insn, int rd, int rs1, int offset)
317 {
318     insn->resti.op = STop;
319     insn->resti.rd = rd;
320     insn->resti.op3 = STop3;
321     insn->resti.rs1 = rs1;
322     insn->resti.i = 1;
323     assert(offset >= MIN_IMM13 && offset <= MAX_IMM13);
324     insn->resti.simm13 = offset;
325 }
326
327 // sll rs1,rs2,rd
328 inline void generateLShift(instruction *insn, int rs1, int offset, int rd)
329 {
330     insn->restix.op = SLLop;
331     insn->restix.op3 = SLLop3;
332     insn->restix.rd = rd;
333     insn->restix.rs1 = rs1;
334     insn->restix.i = 1;
335     insn->restix.x = 0;
336     insn->restix.rs2 = offset;
337 }
338
339 // sll rs1,rs2,rd
340 inline void generateRShift(instruction *insn, int rs1, int offset, int rd)
341 {
342     insn->restix.op = SRLop;
343     insn->restix.op3 = SRLop3;
344     insn->restix.rd = rd;
345     insn->restix.rs1 = rs1;
346     insn->restix.i = 1;
347     insn->restix.x = 0;
348     insn->restix.rs2 = offset;
349 }
350
351 // load [rs1 + offset], rd
352 inline void generateLoad(instruction *insn, int rs1, int offset, int rd)
353 {
354     insn->resti.op = LOADop;
355     insn->resti.op3 = LDop3;
356     insn->resti.rd = rd;
357     insn->resti.rs1 = rs1;
358     insn->resti.i = 1;
359     assert(offset >= MIN_IMM13 && offset <= MAX_IMM13);
360     insn->resti.simm13 = offset;
361 }
362
363 // swap [rs1 + offset], rd
364 inline void generateSwap(instruction *insn, int rs1, int offset, int rd)
365 {
366     insn->resti.op = SWAPop;
367     insn->resti.rd = rd;
368     insn->resti.op3 = SWAPop3;
369     insn->resti.rs1 = rs1;
370     insn->resti.i = 0;
371     assert(offset >= MIN_IMM13 && offset <= MAX_IMM13);
372     insn->resti.simm13 = offset;
373 }    
374
375 // std rd, [rs1 + offset]
376 inline void genStoreD(instruction *insn, int rd, int rs1, int offset)
377 {
378     insn->resti.op = STop;
379     insn->resti.rd = rd;
380     insn->resti.op3 = STDop3;
381     insn->resti.rs1 = rs1;
382     insn->resti.i = 1;
383     assert(offset >= MIN_IMM13 && offset <= MAX_IMM13);
384     insn->resti.simm13 = offset;
385 }
386
387 // ldd [rs1 + offset], rd
388 inline void genLoadD(instruction *insn, int rs1, int offset, int rd)
389 {
390     insn->resti.op = LOADop;
391     insn->resti.op3 = LDDop3;
392     insn->resti.rd = rd;
393     insn->resti.rs1 = rs1;
394     insn->resti.i = 1;
395     assert(offset >= MIN_IMM13 && offset <= MAX_IMM13);
396     insn->resti.simm13 = offset;
397 }
398
399 bool processOptimaRet(instPoint *location, AstNode *&ast);
400
401 extern bool isPowerOf2(int value, int &result);
402 extern void generateNoOp(process *proc, int addr);
403 extern void changeBranch(process *proc, unsigned fromAddr, unsigned newAddr,
404                   instruction originalBranch);
405 extern trampTemplate *findAndInstallBaseTramp(process *proc,
406                                  instPoint *&location, 
407                                  returnInstance *&retInstance, bool noCost);
408
409 extern void  generateBranch(process *proc, unsigned fromAddr, unsigned newAddr);
410 extern void generateCall(process *proc, unsigned fromAddr,unsigned newAddr);
411 extern void genImm(process *proc, Address fromAddr,int op, reg rs1, 
412                    int immd, reg rd);
413 extern int callsTrackedFuncP(instPoint *point);
414 extern pd_Function *getFunction(instPoint *point);
415 extern unsigned emitFuncCall(opCode op, registerSpace *rs, char *i, 
416                              unsigned &base, const vector<AstNode *> &operands,
417                              const string &callee, process *proc, bool noCost);
418
419 extern unsigned emitImm(opCode op, reg src1, reg src2, reg dest, char *i,
420                         unsigned &base, bool noCost);
421
422 extern unsigned emitOptReturn(unsigned, reg, char *, unsigned &, bool);
423
424 extern int getInsnCost(opCode op);
425 extern bool isReturnInsn(const image *owner, Address adr, bool &lastOne);
426 extern void generateMTpreamble(char *insn, unsigned &base, process *proc);
427
428 #endif