Commit | Line | Data |
---|---|---|
920dae64 AT |
1 | /* |
2 | * ========== Copyright Header Begin ========================================== | |
3 | * | |
4 | * OpenSPARC T2 Processor File: rz_insttypes.h | |
5 | * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. | |
6 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES. | |
7 | * | |
8 | * The above named program is free software; you can redistribute it and/or | |
9 | * modify it under the terms of the GNU General Public | |
10 | * License version 2 as published by the Free Software Foundation. | |
11 | * | |
12 | * The above named program is distributed in the hope that it will be | |
13 | * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
15 | * General Public License for more details. | |
16 | * | |
17 | * You should have received a copy of the GNU General Public | |
18 | * License along with this work; if not, write to the Free Software | |
19 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. | |
20 | * | |
21 | * ========== Copyright Header End ============================================ | |
22 | */ | |
23 | /* rz_insttypes.h | |
24 | * lightweight spix-like calls to determine inst types and | |
25 | * extract information like effective addresses from sparcv9 insts | |
26 | * | |
27 | * Copyright (c) 2004 by Sun Microsystems, Inc. | |
28 | * All rights reserved. | |
29 | * | |
30 | */ | |
31 | ||
32 | ||
33 | #ifndef _rz_insttypes_h_ | |
34 | #define _rz_insttypes_h_ | |
35 | ||
36 | ||
37 | /* Notes | |
38 | * | |
39 | * rz_insttypes.h contains a set of macros and functions used to | |
40 | * decode and classify SPARC V9 instructions. It is meant as a | |
41 | * light-weight replacement for SPIX. All functions take the 32-bit | |
42 | * instr word as the sole argument | |
43 | * | |
44 | * Here is a list of the functions available, their spix equivalents, | |
45 | * and crucial differences between spix and this library: | |
46 | * | |
47 | * rz_is_dcti() -- equivalent to spix_sparc_iop_isdcti() | |
48 | * | |
49 | * rz_is_branch() -- equivalent to spix_sparc_iop_isbranch() | |
50 | * | |
51 | * rz_isubranch_always() -- equivalent to spix_sparc_iop_isubranch() | |
52 | * | |
53 | * rz_isubranch_never() -- true for BRANCH NEVER instructions | |
54 | * | |
55 | * rz_isubranch() -- unconditional branches (ALWAYS and NEVER) | |
56 | * NOT equivalent to spix_sparc_iop_isubranch() | |
57 | * | |
58 | * rz_iscbranch() -- conditional branches (does not include BRANCH NEVER) | |
59 | * NOT equivalent to spix_sparc_iop_iscbranch() | |
60 | * | |
61 | * rz_isbpr(), rz_isbpcc(), rz_isbicc(), rz_fbfcc(), rz_isfbpcc(), | |
62 | * rz_iscall(), rz_isreturn(), rz_isdone(), rz_isretry() | |
63 | * | |
64 | * rz_isprefetch() -- equivalent to spix_sparc_iop_isprefetch() | |
65 | * | |
66 | * rz_isload() -- true for loads but not load-store or prefetch insts | |
67 | * NOT equivalent to spix_sparc_iop_isload() | |
68 | * | |
69 | * rz_is_load_store() -- conditional AND unconditional load-store insts | |
70 | * rz_isustore() -- contains unconditional stores and unconditional load-stores | |
71 | * | |
72 | * rz_is_load_store_conditional() -- equivalent to spix_sparc_iop_iscstore() | |
73 | */ | |
74 | ||
75 | ||
76 | ||
77 | #define sign_ext_hi_bit(x, n) (((x) >> ((n)-1)) & 1) | |
78 | #define sign_ext_1(x, n) (sign_ext_hi_bit(x, n) ? (~0ull)<<((n)-1) : 0ull) | |
79 | ||
80 | #define sign_ext_lo_mask(n) ((1ull << (n)) - 1) | |
81 | #define sign_ext_2(x, n) ((x) & sign_ext_lo_mask(n)) | |
82 | ||
83 | //#define sign_ext(x, n) (sign_ext_1((x), (n)) | sign_ext_2((x), (n))) | |
84 | static inline int64_t sign_ext(int64_t imm, int sz) { | |
85 | int64_t rv = (imm << (64 - sz)); | |
86 | rv = (rv >> (64-sz)); | |
87 | return rv; | |
88 | } | |
89 | ||
90 | ||
91 | ||
92 | #define BPcc_OPCODE_MASK 0xc1c00000u | |
93 | #define BPcc_OPCODE_BITS 0x00400000u | |
94 | #define BPcc_DISP(_opc_) (sign_ext((_opc_ & 0x7ffff), 19) << 2) | |
95 | ||
96 | static inline bool rz_is_bpcc(uint32_t instr) | |
97 | { | |
98 | return ((instr & BPcc_OPCODE_MASK) == BPcc_OPCODE_BITS); | |
99 | } // static inline bool rz_is_bpcc(uint32_t instr) | |
100 | ||
101 | ||
102 | #define BPR_OPCODE_MASK 0xd1c00000u | |
103 | #define BPR_OPCODE_BITS 0x00c00000u | |
104 | #define BPR_DISP_d16hi(_opc_) (((_opc_) >> 20) & 0x3) | |
105 | #define BPR_DISP_d16lo(_opc_) ((_opc_) & 0x3fff) | |
106 | #define BPR_DISP_d16(_opc_) ((BPR_DISP_d16hi(_opc_) << 14) | BPR_DISP_d16lo(_opc_)) | |
107 | #define BPR_DISP(_opc_) (sign_ext(BPR_DISP_d16(_opc_), 16) << 2) | |
108 | ||
109 | static inline bool rz_is_bpr(uint32_t instr) { | |
110 | if ((instr & BPR_OPCODE_MASK) == BPR_OPCODE_BITS) { | |
111 | uint32_t rcond = (instr >> 25) & 0x7; | |
112 | return ((rcond & 3) != 0); | |
113 | } else { | |
114 | return false; | |
115 | } | |
116 | } // static inline bool rz_is_bpr(uint32_t instr) { | |
117 | ||
118 | #define FBfcc_OPCODE_MASK 0xc1c00000u | |
119 | #define FBfcc_OPCODE_BITS 0x01800000u | |
120 | #define FBfcc_DISP(_opc_) (sign_ext((_opc_ & 0x3fffff), 22) << 2) | |
121 | ||
122 | static inline bool rz_is_fbfcc(uint32_t instr) | |
123 | { | |
124 | return ((instr & FBfcc_OPCODE_MASK) == FBfcc_OPCODE_BITS); | |
125 | } | |
126 | ||
127 | ||
128 | #define FBPfcc_OPCODE_MASK 0xc1c00000u | |
129 | #define FBPfcc_OPCODE_BITS 0x01400000u | |
130 | #define FBPfcc_DISP(_opc_) (sign_ext((_opc_ & 0x7ffff), 19) << 2) | |
131 | ||
132 | ||
133 | static inline bool rz_is_fbpfcc(uint32_t instr) | |
134 | { | |
135 | return ((instr & FBPfcc_OPCODE_MASK) == FBPfcc_OPCODE_BITS); | |
136 | } // static inline bool rz_is_fbpfcc(uint32_t instr) | |
137 | ||
138 | ||
139 | #define Bicc_OPCODE_MASK 0xc1c00000u | |
140 | #define Bicc_OPCODE_BITS 0x00800000u | |
141 | #define Bicc_DISP(_opc_) (sign_ext((_opc_ & 0x3fffff), 22) << 2) | |
142 | ||
143 | ||
144 | ||
145 | static inline bool rz_is_bicc(uint32_t instr) | |
146 | { | |
147 | return ((instr & Bicc_OPCODE_MASK) == Bicc_OPCODE_BITS); | |
148 | } // static inline bool rz_is_bicc(uint32_t instr) | |
149 | ||
150 | ||
151 | ||
152 | #define CALL_OPCODE_MASK 0xc0000000u | |
153 | #define CALL_OPCODE_BITS 0x40000000u | |
154 | #define CALL_DISP(_opc_) (sign_ext((_opc_ & 0x3fffffff), 30) << 2) | |
155 | ||
156 | ||
157 | ||
158 | static inline bool rz_is_call(uint32_t instr) | |
159 | { | |
160 | return ((instr & CALL_OPCODE_MASK) == CALL_OPCODE_BITS); | |
161 | } // static inline bool rz_is_call(uint32_t instr) | |
162 | ||
163 | ||
164 | ||
165 | #define UBRANCH_OPCODE_MASK 0xdfc00000u | |
166 | ||
167 | #define FBA_OPCODE_BITS 0x11400000u | |
168 | #define FBN_OPCODE_BITS 0x01400000u | |
169 | ||
170 | #define FBPA_OPCODE_BITS 0x11400000u | |
171 | #define FBPN_OPCODE_BITS 0x01400000u | |
172 | ||
173 | #define BA_OPCODE_BITS 0x10400000u | |
174 | #define BN_OPCODE_BITS 0x00400000u | |
175 | ||
176 | #define BPA_OPCODE_BITS 0x10400000u | |
177 | #define BPN_OPCODE_BITS 0x00400000u | |
178 | ||
179 | #define RESTORE_OPCODE_MASK 0xc1f80000 | |
180 | #define RESTORE_OPCODE_BITS 0x81e80000 | |
181 | ||
182 | #define MOV_G1_G7_INSTR 0x9e100001 | |
183 | ||
184 | ||
185 | #define JMPL_OPCODE_MASK 0xc1f80000 | |
186 | #define JMPL_OPCODE_BITS 0x81c00000 | |
187 | static inline bool rz_is_jmpl(uint32_t instr) | |
188 | { | |
189 | return ((instr & JMPL_OPCODE_MASK) == JMPL_OPCODE_BITS); | |
190 | } // static inline bool rz_is_jmpl(uint32_t instr) | |
191 | ||
192 | ||
193 | #define RETURN_OPCODE_MASK 0xc1f80000 | |
194 | #define RETURN_OPCODE_BITS 0x81c80000 | |
195 | static inline bool rz_is_return(uint32_t instr) | |
196 | { | |
197 | return ((instr & RETURN_OPCODE_MASK) == RETURN_OPCODE_BITS); | |
198 | } //static inline bool rz_is_return(uint32_t instr) | |
199 | ||
200 | ||
201 | static inline bool rz_is_branch(uint32_t instr) { | |
202 | return rz_is_bpr(instr) || rz_is_fbfcc(instr) || rz_is_fbpfcc(instr) || rz_is_bicc(instr) || rz_is_bpcc(instr); | |
203 | } | |
204 | ||
205 | static inline bool rz_is_ubranch_always(uint32_t instr) { | |
206 | // op=0, (op2 =~ ?01 or op2 =~ ?10), cond == 8 | |
207 | return ((instr & 0xdec00000) == 0x10800000) || ((instr & 0xdec00000) == 0x10400000); | |
208 | } | |
209 | ||
210 | static inline bool rz_is_ubranch_never(uint32_t instr) { | |
211 | // op=0, (op2 =~ ?01 or op2 =~ ?10), cond == 0 | |
212 | return ((instr & 0xdec00000) == 0x00800000) || ((instr & 0xdec00000) == 0x00400000); | |
213 | } | |
214 | ||
215 | static inline bool rz_is_ubranch(uint32_t instr) { | |
216 | return rz_is_ubranch_always(instr) || rz_is_ubranch_never(instr); | |
217 | } | |
218 | ||
219 | // DIFFERENCE FROM SPIX: spix _iscbranch() includes branch_never. ours does NOT. | |
220 | static inline bool rz_is_cbranch(uint32_t instr) { | |
221 | return (rz_is_branch(instr) && ! rz_is_ubranch(instr)); | |
222 | } | |
223 | ||
224 | static inline bool rz_is_dcti(uint32_t instr) | |
225 | { | |
226 | return rz_is_branch(instr) || rz_is_call(instr) || rz_is_jmpl(instr) || rz_is_return(instr); | |
227 | } // static inline bool rz_is_dcti(uint32_t instr) | |
228 | ||
229 | ||
230 | static inline bool rz_is_pc_relative_cti(uint32_t instr) | |
231 | { | |
232 | return rz_is_branch(instr) || rz_is_call(instr); | |
233 | } | |
234 | ||
235 | #define DONE_RETRY_OPCODE_MASK 0xfff80000 | |
236 | #define DONE_OPCODE_BITS 0x81f00000 | |
237 | #define RETRY_OPCODE_BITS 0x83f00000 | |
238 | static inline bool rz_is_done(uint32_t instr) | |
239 | { | |
240 | return ((instr & DONE_RETRY_OPCODE_MASK) == DONE_OPCODE_BITS); | |
241 | } | |
242 | ||
243 | ||
244 | static inline bool rz_is_retry(uint32_t instr) | |
245 | { | |
246 | return ((instr & DONE_RETRY_OPCODE_MASK) == RETRY_OPCODE_BITS); | |
247 | } // static inline bool rz_is_retry(uint32_t instr) | |
248 | ||
249 | ||
250 | ||
251 | static inline bool rz_is_ldstpf(uint32_t instr) | |
252 | { | |
253 | return ((instr >> 30) == 0x3); | |
254 | } // static inline bool rz_is_ldstpf(uint32_t instr) | |
255 | ||
256 | ||
257 | // does *not* include load-store insts, unlike spix _isload() | |
258 | // also does *not* include prefetches, unlike spix _isload() | |
259 | static inline bool rz_is_load(uint32_t instr) | |
260 | { | |
261 | // op3 =~ ?? ?0?? | |
262 | return ((instr & 0xc0200000) == 0xc0000000); | |
263 | } | |
264 | ||
265 | ||
266 | // does *not* include load-store insts. spix _isstore() includes unconditional ldst insts | |
267 | static inline bool rz_is_store(uint32_t instr) | |
268 | { | |
269 | // op3 =~ ?? 01?? or op3 =~ 0? 1110 | |
270 | return ((instr & 0xc0600000) == 0xc0200000) || ((instr & 0xc1780000) == 0xc0700000); | |
271 | } | |
272 | ||
273 | // load and cond store (CAS/CASA) - same as spix _iscstore() | |
274 | static inline bool rz_is_load_store_conditional(uint32_t instr) | |
275 | { | |
276 | // op=3, op3=11 11?0 | |
277 | return ((instr & 0xc1e80000) == 0xc1e00000); | |
278 | } | |
279 | ||
280 | ||
281 | // ldstub, swap | |
282 | static inline bool rz_is_load_store_unconditional(uint32_t instr) | |
283 | { | |
284 | // op=3 op3=0? 11?1 | |
285 | return ((instr & 0xc1680000) == 0xc0680000); | |
286 | } | |
287 | ||
288 | ||
289 | // include conditional as well as unconditional ldst insts (ldst + cas + swap) | |
290 | static inline bool rz_is_load_store(uint32_t instr) | |
291 | { | |
292 | return rz_is_load_store_conditional(instr) || rz_is_load_store_unconditional(instr); | |
293 | } | |
294 | ||
295 | ||
296 | static inline bool rz_is_prefetch(uint32_t instr) | |
297 | { | |
298 | // op3 =~ 1? 1101 | |
299 | return ((instr & 0xc1780000) == 0xc1680000); | |
300 | } | |
301 | ||
302 | static inline bool rz_is_sethi(uint32_t instr) | |
303 | { | |
304 | // op==0 op2=100 | |
305 | return ( ((instr & 0xc1c00000) == 0x01000000) && (instr & 0x3e000000) ); | |
306 | } | |
307 | ||
308 | #endif // _rz_insttypes_h_ |