Added functions to differentiate between 'true' call instructions
[dyninst.git] / dyninstAPI / src / arch-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 _ARCH_SPARC_H
47 #define _ARCH_SPARC_H
48
49 /*
50  * $Log: arch-sparc.h,v $
51  * Revision 1.20  1997/12/04 18:49:36  mcheyney
52  * Added functions to differentiate between 'true' call instructions
53  * (CALL - Opcode 01), and 'jmpl' call instructions (show up under
54  * gdb disass as call, but really jmpl instructions, opcode != 01)....
55  *
56  * Revision 1.19  1997/06/23 17:05:44  tamches
57  * instPointType moved to another file
58  *
59  * Revision 1.18  1997/05/20 15:46:15  zhichen
60  * Added WRYop3 & RDYop3 for correctly handle DIVop3
61  *
62  * Revision 1.17  1997/03/14 15:58:36  lzheng
63  * Dealing with complier optimization related to the return value
64  *
65  * Revision 1.16  1997/02/21 20:13:12  naim
66  * Moving files from paradynd to dyninstAPI + moving references to dataReqNode
67  * out of the ast class. The is the first pre-dyninstAPI commit! - naim
68  *
69  * Revision 1.15  1996/10/31 08:35:36  tamches
70  * removed LOW and HIGH; added a few opcodes
71  *
72  * Revision 1.14  1996/10/18 23:51:21  mjrg
73  * Added function to test for alignment
74  *
75  * Revision 1.13  1996/10/04 16:38:31  naim
76  * Changes to use immediate operations on the sparc - naim
77  *
78  * Revision 1.12  1996/09/26 18:58:23  newhall
79  * added support for instrumenting dynamic executables on sparc-solaris
80  * platform
81  *
82  * Revision 1.11  1996/09/05 16:17:00  lzheng
83  * Move the defination of BREAK_POINT_INSN to the machine dependent file
84  *
85  * Revision 1.10  1996/08/20 19:10:02  lzheng
86  * Implementation of moving multiple instructions sequence
87  * Correcting a few opmask here and add some new.
88  *
89  * Revision 1.9  1996/08/16 21:18:07  tamches
90  * updated copyright for release 1.1
91  *
92  * Revision 1.8  1996/04/29 22:08:44  mjrg
93  * added some extra defines
94  *
95  * Revision 1.7  1995/12/11 15:06:41  naim
96  * Implementing >, >=, < and <= operators - naim
97  *
98  * Revision 1.6  1995/07/11  20:57:23  jcargill
99  * Changed sparc-specific ifdefs to include sparc_tmc_cmost7_3
100  *
101  * Revision 1.5  1995/05/30  05:04:49  krisna
102  * upgrade from solaris-2.3 to solaris-2.4.
103  * architecture-os based include protection of header files.
104  * removed architecture-os dependencies in generic sources.
105  * changed ST_* symbol names to PDST_* (to avoid conflict on HPUX)
106  *
107  * Revision 1.4  1994/11/02  10:59:12  markc
108  * Replaced some of the hash-defs with inlines
109  *
110  * Revision 1.3  1994/09/22  01:31:33  markc
111  * Added log message, duplicate include guards
112  *
113  */
114
115
116 /*
117  * Define sparc instruction information.
118  *
119  */
120 struct fmt1 {
121     unsigned op:2;
122     signed disp30:30;
123 };
124
125 struct fmt2 {
126     unsigned op:2;
127     unsigned anneal:1;
128     unsigned cond:4;
129     unsigned op2:3;
130     signed disp22:22;
131 };
132
133 struct fmt2a {
134     unsigned op:2;
135     unsigned rd:5;
136     unsigned op2:3;
137     signed imm22:22;
138 };
139
140 struct fmt3 {
141     unsigned op:2;
142     unsigned rd:5;
143     unsigned op3:6;
144     unsigned rs1:5;
145     unsigned i:1;
146     unsigned unused:8;
147     unsigned rs2:5;
148 };
149
150 struct fmt3ix {
151     unsigned op:2;
152     unsigned rd:5;
153     unsigned op3:6;
154     unsigned rs1:5;
155     unsigned i:1;
156     unsigned x:1;
157     unsigned unused:7;
158     unsigned rs2:5;
159 };
160
161 struct fmt3i {
162     unsigned op:2;
163     unsigned rd:5;
164     unsigned op3:6;
165     unsigned rs1:5;
166     unsigned i:1;
167     signed simm13:13;
168 };
169
170 union instructUnion {
171     struct fmt1 call;
172     struct fmt2 branch;
173     struct fmt2a sethi;
174     struct fmt3 rest;
175     struct fmt3i resti;
176     struct fmt3ix restix;
177     unsigned int raw;
178 };
179
180 typedef union instructUnion instruction;
181
182
183 /*
184  * Define the operation codes
185  *
186  */
187 #define SetCC           16
188 #define ADDop3          0
189 #define ADDop3cc        16
190 #define ANDop3          1
191 #define ANDop3cc        17
192 #define ANDNop3cc       21
193 #define ORop3           2
194 #define SUBop3          4
195 #define SUBop3cc        SetCC|SUBop3
196 #define SMULop3         11
197 #define SDIVop3         15
198 #define WRYop3          48      //SDIV needs to set Y register to 0
199 #define RDYop3          40
200 #define XNORop3         SetCC|7
201 #define SAVEop3         60
202 #define RESTOREop3      61
203 #define JMPLop3         56
204
205 #define SLLop3          37
206 #define SLLop           2
207 #define SRLop3          38
208 #define SRLop           2
209
210 #define FP_OP3_LOW      0x20
211 #define LDFop3          0x20
212 #define LDFSRop3        0x21
213 #define LDDFop3         0x23
214 #define STFop3          0x24
215 #define STFSRop3        0x25
216 #define STDFQop3        0x26
217 #define STDFop3         0x27
218 #define FP_OP3_HIGH     0x27
219
220 #define FP_OP2_FPop1    0x34
221 #define FP_OP2_FPop2    0x35
222
223 /* op = 11 */
224 #define LDSTop  3
225 #define STop    3
226 #define LDop3   0
227 #define STop3   4
228 #define LDDop3  3
229 #define STDop3  7
230 #define SWAPop  3
231 #define SWAPop3 15 
232
233 /* mask bits for various parts of the instruction format */
234 #define OPmask          0xc0000000
235 #define OP2mask         0x01c00000
236 #define OP3mask         0x01f80000
237 #define RDmask          0x3e000000
238
239 #define DISP30mask      0x3fffffff
240
241 /* op = 01 -- mask for and match for call instruction */
242 #define CALLop          1
243 #define CALLmask        OPmask
244 #define CALLmatch       0x40000000
245
246 /* (op==10) && (op3 == 111000) 
247  */
248 #define RESTop          2
249 #define JMPLmask        (OPmask|OP3mask)
250 #define JMPLmatch       0x81c00000
251
252 #define FMT2op          0
253 #define LOADop          3
254
255 /*
256  * added this on 8/18 (jkh) to tell a jmpl from a call indirect.
257  *
258  */
259 #define CALLImask       (OPmask|RDmask|OP3mask)
260 #define CALLImatch      0x9fc00000
261
262 /* (op=10) && (op3==111001) trap instructions */
263 #define TRAPmask        (OPmask|OP3mask)
264 #define TRAPmatch       0x81d00000
265
266 /* (op == 00) && (op2 ^ 2) mask for conditional branching instructions */
267 #define BICCop2         2
268
269 #define BEcond          1
270 #define BLEcond         2
271 #define BLTcond         3
272 #define BGTcond        10
273 #define BGEcond        11
274 #define BAcond          8
275 #define BNEcond         9
276
277 #define BRNCHmask       (OPmask|OP2mask)
278 #define BRNCHmatch      0x1<<23
279
280 #define FBRNCHmask      (OPmask|OP2mask)
281 #define FBRNCHmatch     0x11<<23
282
283 /* really jmpl %i7+8,%g0 */
284 /* changed this to jmpl %i7+??,%g0 since g++ sometimes returns +0xc not +0x8 
285  * jkh - 7/12/93
286  */
287 #define RETmask         0xfffff000
288 #define RETmatch        0x81c7e000
289
290 /* retl - leaf return really jmpl %o7+8,%g0 */
291 /* changed this to jmpl %i7+??,%g0 since g++ sometimes returns +0xc not +0x8
292  * jkh - 7/12/93
293  */
294 #define RETLmask        0xfffff000
295 #define RETLmatch       0x81c3e000
296
297
298 #define SAVEmask        (OPmask|OP3mask)
299 #define SAVEmatch       0x81e00000
300
301 #define RESTOREmask     (OPmask|OP3mask)
302 #define RESTOREmatch    0x81e80000
303
304 /* noop insn */
305 #define NOOPop2         4
306 #define SETHIop2        4
307
308 /* If these bits are non-zero an op2 instruction is a non-annuled branch */
309 #define ANNUL_BIT       0x40000000
310
311 #define BREAK_POINT_INSN 0x91d02001   /* ta 1 */
312
313
314 inline bool isInsnType(const instruction i,
315                        const unsigned mask,
316                        const unsigned match) {
317   return ((i.raw & mask) == match);
318 }
319
320 inline bool isCallInsn(const instruction i) {
321   return (isInsnType(i, CALLmask, CALLmatch) ||
322           isInsnType(i, CALLImask, CALLImatch));
323 }
324
325 //  is instruction i a "true" call?
326 //  2 types of call insn in sparc:
327 //    true call - call to fixed address (really pc rel addr, but disass will show
328 //     fixed addr - for your convenience)....
329 //    jmpl (jump & link) - call to register | register + const |
330 //       register + register, and stick return address in some 
331 //       register.  If dest register is 07, a disassembler should
332 //       show a "call" insn.
333 inline bool isTrueCallInsn(const instruction i) {
334     return (i.call.op == 0x1);
335 }
336
337 inline bool isJmplCallInsn(const instruction i) {
338     // condition for jmpl insn
339     if (i.resti.op == 0x2 && i.resti.op3 == 0x38) {
340         // condition for dest register == 07
341         if (i.resti.rd == 15) {
342             return true;
343         }
344     }
345     return false;
346 }
347
348 inline bool isCondBranch(const instruction i){
349      if (i.branch.op == 0 && (i.branch.op2 == 2 || i.branch.op2 == 6)) {
350          if ((i.branch.cond != 0) && (i.branch.cond != 8))  
351              return true;
352      }
353      return false;
354 }
355
356 inline bool IS_DELAYED_INST(const instruction insn) {
357   return (insn.call.op == CALLop ||
358           isInsnType(insn, JMPLmask, JMPLmatch) ||
359           isInsnType(insn, BRNCHmask, BRNCHmatch));
360 }
361
362 /* catch small ints that are invalid instructions */
363 /*
364  * insn.call.op checks for CALL or Format 3 insns
365  * op2 == {2,4,6,7} checks for valid format 2 instructions.
366  *    See SPARC Arch manual v8 p. 44.
367  *
368  */
369 inline bool IS_VALID_INSN(const instruction insn) {
370   return ((insn.call.op) || ((insn.branch.op2 == 2) ||
371                              (insn.branch.op2 == 4) ||
372                              (insn.branch.op2 == 6) ||
373                              (insn.branch.op2 == 7)));
374 }
375
376 /* addresses on sparc are aligned to word boundaries */
377 inline bool isAligned(const Address addr) { return !(addr & 0x3); }
378
379 #endif