| 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_ |