2 * Copyright (c) 1996 Barton P. Miller
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.
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.
18 * (for other uses, please contact us at paradyn@cs.wisc.edu)
20 * All warranties, including without limitation, any warranty of
21 * merchantability or fitness for a particular purpose, are hereby
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.
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.
42 #if !defined(sparc_sun_sunos4_1_3) && !defined(sparc_sun_solaris2_4)
43 #error "invalid architecture-os inclusion"
49 #include "util/h/headers.h"
50 #ifndef BPATCH_LIBRARY
51 #include "rtinst/h/rtinst.h"
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"
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. */
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)
79 inline unsigned ABS(int x) {
83 //#define ABS(x) ((x) > 0 ? x : -x)
85 //#define MAX_BRANCH (0x1<<23)
87 #define MAX_IMM13 (4095)
88 #define MIN_IMM13 (-4096)
105 extern "C" void baseTramp();
106 extern trampTemplate baseTemplate;
107 extern registerSpace *regSpace;
108 extern int deadList[];
109 extern instruction newInstr[1024];
113 inline unsigned getMaxBranch3Insn() {
114 // The length we can branch using 3 instructions
120 // probably returning ~0 would be better, since there's no limit
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);
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);
138 // divide by 4. After the divide, the result must fit in 22 bits.
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);
146 if (offset < INT22_MIN)
148 else if (offset > INT22_MAX)
154 inline bool in1BranchInsnRange(unsigned adr1, unsigned adr2)
156 return (abs(adr1-adr2) < (0x1 << 23));
159 inline void generateNOOP(instruction *insn)
163 insn->branch.op2 = NOOPop2;
168 inline void generateBranchInsn(instruction *insn, int offset)
170 if (!offsetWithinRangeOfBranchInsn(offset)) {
172 sprintf(buffer, "a Branch too far; offset=%d\n", offset);
174 //showErrorCallback(52, "");
175 assert(false && "a Branch too far");
181 insn->branch.cond = BAcond;
182 insn->branch.op2 = BICCop2;
183 insn->branch.anneal = true;
184 insn->branch.disp22 = offset >> 2;
186 // logLine("ba,a %x\n", offset);
189 inline void generateCallInsn(instruction *insn, int fromAddr, int toAddr)
191 int offset = toAddr - fromAddr;
193 insn->call.disp30 = offset >> 2;
196 inline void generateJmplInsn(instruction *insn, int rs1, int offset, int rd)
200 insn->resti.op3 = JMPLop3;
201 insn->resti.rs1 = rs1;
203 assert(offset >= MIN_IMM13 && offset <= MAX_IMM13);
204 insn->resti.simm13 = offset;
207 inline void genBranch(instruction *insn, int offset, unsigned condition, bool annul)
209 // if (ABS(offset) > getMaxBranch1Insn()) {
210 if (!offsetWithinRangeOfBranchInsn(offset)) {
212 sprintf(buffer, "a branch too far, offset=%d\n", offset);
214 showErrorCallback(52, "");
220 insn->branch.cond = condition;
221 insn->branch.op2 = BICCop2;
222 insn->branch.anneal = annul;
223 insn->branch.disp22 = offset >> 2;
226 inline void generateAnnulledBranchInsn(instruction *insn, int offset)
228 genBranch(insn, offset, BAcond, true);
232 inline void genSimpleInsn(instruction *insn, int op, reg rs1, reg rs2, reg rd)
235 insn->rest.op = RESTop;
238 insn->rest.rs1 = rs1;
239 insn->rest.rs2 = rs2;
242 inline void genBreakpointTrap(instruction *insn) {
243 insn->raw = BREAK_POINT_INSN; // ta (trap always) 1
246 inline void genUnimplementedInsn(instruction *insn) {
247 insn->raw = 0; // UNIMP 0
250 inline void genImmInsn(instruction *insn, int op, reg rs1, int immd, reg rd)
253 insn->resti.op = RESTop;
255 insn->resti.op3 = op;
256 insn->resti.rs1 = rs1;
258 assert(immd >= MIN_IMM13 && immd <= MAX_IMM13);
259 insn->resti.simm13 = immd;
262 inline void genImmRelOp(instruction *insn, int cond, reg rs1,
263 int immd, reg rd, unsigned &base)
266 genImmInsn(insn, SUBop3cc, rs1, immd, 0); insn++;
268 genImmInsn(insn, ORop3, 0, 1, rd); insn++;
272 insn->branch.cond = cond;
273 insn->branch.op2 = BICCop2;
274 insn->branch.anneal = true;
275 insn->branch.disp22 = 2;
279 genImmInsn(insn, ORop3, 0, 0, rd); insn++;
280 //genSimpleInsn(insn, ORop3, 0, 0, rd); insn++;
281 base += 4 * sizeof(instruction);
284 inline void genRelOp(instruction *insn, int cond, reg rs1,
285 reg rs2, reg rd, unsigned &base)
288 genSimpleInsn(insn, SUBop3cc, rs1, rs2, 0); insn++;
290 genImmInsn(insn, ORop3, 0, 1, rd); insn++;
294 insn->branch.cond = cond;
295 insn->branch.op2 = BICCop2;
296 insn->branch.anneal = true;
297 insn->branch.disp22 = 2;
301 genImmInsn(insn, ORop3, 0, 0, rd); insn++;
302 //genSimpleInsn(insn, ORop3, 0, 0, rd); insn++;
303 base += 4 * sizeof(instruction);
306 inline void generateSetHi(instruction *insn, int src1, int dest)
309 insn->sethi.op = FMT2op;
310 insn->sethi.rd = dest;
311 insn->sethi.op2 = SETHIop2;
312 insn->sethi.imm22 = HIGH22(src1);
315 // st rd, [rs1 + offset]
316 inline void generateStore(instruction *insn, int rd, int rs1, int offset)
318 insn->resti.op = STop;
320 insn->resti.op3 = STop3;
321 insn->resti.rs1 = rs1;
323 assert(offset >= MIN_IMM13 && offset <= MAX_IMM13);
324 insn->resti.simm13 = offset;
328 inline void generateLShift(instruction *insn, int rs1, int offset, int rd)
330 insn->restix.op = SLLop;
331 insn->restix.op3 = SLLop3;
332 insn->restix.rd = rd;
333 insn->restix.rs1 = rs1;
336 insn->restix.rs2 = offset;
340 inline void generateRShift(instruction *insn, int rs1, int offset, int rd)
342 insn->restix.op = SRLop;
343 insn->restix.op3 = SRLop3;
344 insn->restix.rd = rd;
345 insn->restix.rs1 = rs1;
348 insn->restix.rs2 = offset;
351 // load [rs1 + offset], rd
352 inline void generateLoad(instruction *insn, int rs1, int offset, int rd)
354 insn->resti.op = LOADop;
355 insn->resti.op3 = LDop3;
357 insn->resti.rs1 = rs1;
359 assert(offset >= MIN_IMM13 && offset <= MAX_IMM13);
360 insn->resti.simm13 = offset;
363 // swap [rs1 + offset], rd
364 inline void generateSwap(instruction *insn, int rs1, int offset, int rd)
366 insn->resti.op = SWAPop;
368 insn->resti.op3 = SWAPop3;
369 insn->resti.rs1 = rs1;
371 assert(offset >= MIN_IMM13 && offset <= MAX_IMM13);
372 insn->resti.simm13 = offset;
375 // std rd, [rs1 + offset]
376 inline void genStoreD(instruction *insn, int rd, int rs1, int offset)
378 insn->resti.op = STop;
380 insn->resti.op3 = STDop3;
381 insn->resti.rs1 = rs1;
383 assert(offset >= MIN_IMM13 && offset <= MAX_IMM13);
384 insn->resti.simm13 = offset;
387 // ldd [rs1 + offset], rd
388 inline void genLoadD(instruction *insn, int rs1, int offset, int rd)
390 insn->resti.op = LOADop;
391 insn->resti.op3 = LDDop3;
393 insn->resti.rs1 = rs1;
395 assert(offset >= MIN_IMM13 && offset <= MAX_IMM13);
396 insn->resti.simm13 = offset;
399 bool processOptimaRet(instPoint *location, AstNode *&ast);
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);
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,
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);
419 extern unsigned emitImm(opCode op, reg src1, reg src2, reg dest, char *i,
420 unsigned &base, bool noCost);
422 extern unsigned emitOptReturn(unsigned, reg, char *, unsigned &, bool);
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);