1b8e80941Smrg/* 2b8e80941Smrg * Copyright (c) 2013 Rob Clark <robdclark@gmail.com> 3b8e80941Smrg * 4b8e80941Smrg * Permission is hereby granted, free of charge, to any person obtaining a 5b8e80941Smrg * copy of this software and associated documentation files (the "Software"), 6b8e80941Smrg * to deal in the Software without restriction, including without limitation 7b8e80941Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8b8e80941Smrg * and/or sell copies of the Software, and to permit persons to whom the 9b8e80941Smrg * Software is furnished to do so, subject to the following conditions: 10b8e80941Smrg * 11b8e80941Smrg * The above copyright notice and this permission notice (including the next 12b8e80941Smrg * paragraph) shall be included in all copies or substantial portions of the 13b8e80941Smrg * Software. 14b8e80941Smrg * 15b8e80941Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16b8e80941Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17b8e80941Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18b8e80941Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19b8e80941Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20b8e80941Smrg * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21b8e80941Smrg * SOFTWARE. 22b8e80941Smrg */ 23b8e80941Smrg 24b8e80941Smrg#ifndef INSTR_A3XX_H_ 25b8e80941Smrg#define INSTR_A3XX_H_ 26b8e80941Smrg 27b8e80941Smrg#define PACKED __attribute__((__packed__)) 28b8e80941Smrg 29b8e80941Smrg#include <stdint.h> 30b8e80941Smrg#include <stdio.h> 31b8e80941Smrg#include <stdbool.h> 32b8e80941Smrg#include <assert.h> 33b8e80941Smrg 34b8e80941Smrg/* size of largest OPC field of all the instruction categories: */ 35b8e80941Smrg#define NOPC_BITS 6 36b8e80941Smrg 37b8e80941Smrg#define _OPC(cat, opc) (((cat) << NOPC_BITS) | opc) 38b8e80941Smrg 39b8e80941Smrgtypedef enum { 40b8e80941Smrg /* category 0: */ 41b8e80941Smrg OPC_NOP = _OPC(0, 0), 42b8e80941Smrg OPC_BR = _OPC(0, 1), 43b8e80941Smrg OPC_JUMP = _OPC(0, 2), 44b8e80941Smrg OPC_CALL = _OPC(0, 3), 45b8e80941Smrg OPC_RET = _OPC(0, 4), 46b8e80941Smrg OPC_KILL = _OPC(0, 5), 47b8e80941Smrg OPC_END = _OPC(0, 6), 48b8e80941Smrg OPC_EMIT = _OPC(0, 7), 49b8e80941Smrg OPC_CUT = _OPC(0, 8), 50b8e80941Smrg OPC_CHMASK = _OPC(0, 9), 51b8e80941Smrg OPC_CHSH = _OPC(0, 10), 52b8e80941Smrg OPC_FLOW_REV = _OPC(0, 11), 53b8e80941Smrg 54b8e80941Smrg /* category 1: */ 55b8e80941Smrg OPC_MOV = _OPC(1, 0), 56b8e80941Smrg 57b8e80941Smrg /* category 2: */ 58b8e80941Smrg OPC_ADD_F = _OPC(2, 0), 59b8e80941Smrg OPC_MIN_F = _OPC(2, 1), 60b8e80941Smrg OPC_MAX_F = _OPC(2, 2), 61b8e80941Smrg OPC_MUL_F = _OPC(2, 3), 62b8e80941Smrg OPC_SIGN_F = _OPC(2, 4), 63b8e80941Smrg OPC_CMPS_F = _OPC(2, 5), 64b8e80941Smrg OPC_ABSNEG_F = _OPC(2, 6), 65b8e80941Smrg OPC_CMPV_F = _OPC(2, 7), 66b8e80941Smrg /* 8 - invalid */ 67b8e80941Smrg OPC_FLOOR_F = _OPC(2, 9), 68b8e80941Smrg OPC_CEIL_F = _OPC(2, 10), 69b8e80941Smrg OPC_RNDNE_F = _OPC(2, 11), 70b8e80941Smrg OPC_RNDAZ_F = _OPC(2, 12), 71b8e80941Smrg OPC_TRUNC_F = _OPC(2, 13), 72b8e80941Smrg /* 14-15 - invalid */ 73b8e80941Smrg OPC_ADD_U = _OPC(2, 16), 74b8e80941Smrg OPC_ADD_S = _OPC(2, 17), 75b8e80941Smrg OPC_SUB_U = _OPC(2, 18), 76b8e80941Smrg OPC_SUB_S = _OPC(2, 19), 77b8e80941Smrg OPC_CMPS_U = _OPC(2, 20), 78b8e80941Smrg OPC_CMPS_S = _OPC(2, 21), 79b8e80941Smrg OPC_MIN_U = _OPC(2, 22), 80b8e80941Smrg OPC_MIN_S = _OPC(2, 23), 81b8e80941Smrg OPC_MAX_U = _OPC(2, 24), 82b8e80941Smrg OPC_MAX_S = _OPC(2, 25), 83b8e80941Smrg OPC_ABSNEG_S = _OPC(2, 26), 84b8e80941Smrg /* 27 - invalid */ 85b8e80941Smrg OPC_AND_B = _OPC(2, 28), 86b8e80941Smrg OPC_OR_B = _OPC(2, 29), 87b8e80941Smrg OPC_NOT_B = _OPC(2, 30), 88b8e80941Smrg OPC_XOR_B = _OPC(2, 31), 89b8e80941Smrg /* 32 - invalid */ 90b8e80941Smrg OPC_CMPV_U = _OPC(2, 33), 91b8e80941Smrg OPC_CMPV_S = _OPC(2, 34), 92b8e80941Smrg /* 35-47 - invalid */ 93b8e80941Smrg OPC_MUL_U = _OPC(2, 48), 94b8e80941Smrg OPC_MUL_S = _OPC(2, 49), 95b8e80941Smrg OPC_MULL_U = _OPC(2, 50), 96b8e80941Smrg OPC_BFREV_B = _OPC(2, 51), 97b8e80941Smrg OPC_CLZ_S = _OPC(2, 52), 98b8e80941Smrg OPC_CLZ_B = _OPC(2, 53), 99b8e80941Smrg OPC_SHL_B = _OPC(2, 54), 100b8e80941Smrg OPC_SHR_B = _OPC(2, 55), 101b8e80941Smrg OPC_ASHR_B = _OPC(2, 56), 102b8e80941Smrg OPC_BARY_F = _OPC(2, 57), 103b8e80941Smrg OPC_MGEN_B = _OPC(2, 58), 104b8e80941Smrg OPC_GETBIT_B = _OPC(2, 59), 105b8e80941Smrg OPC_SETRM = _OPC(2, 60), 106b8e80941Smrg OPC_CBITS_B = _OPC(2, 61), 107b8e80941Smrg OPC_SHB = _OPC(2, 62), 108b8e80941Smrg OPC_MSAD = _OPC(2, 63), 109b8e80941Smrg 110b8e80941Smrg /* category 3: */ 111b8e80941Smrg OPC_MAD_U16 = _OPC(3, 0), 112b8e80941Smrg OPC_MADSH_U16 = _OPC(3, 1), 113b8e80941Smrg OPC_MAD_S16 = _OPC(3, 2), 114b8e80941Smrg OPC_MADSH_M16 = _OPC(3, 3), /* should this be .s16? */ 115b8e80941Smrg OPC_MAD_U24 = _OPC(3, 4), 116b8e80941Smrg OPC_MAD_S24 = _OPC(3, 5), 117b8e80941Smrg OPC_MAD_F16 = _OPC(3, 6), 118b8e80941Smrg OPC_MAD_F32 = _OPC(3, 7), 119b8e80941Smrg OPC_SEL_B16 = _OPC(3, 8), 120b8e80941Smrg OPC_SEL_B32 = _OPC(3, 9), 121b8e80941Smrg OPC_SEL_S16 = _OPC(3, 10), 122b8e80941Smrg OPC_SEL_S32 = _OPC(3, 11), 123b8e80941Smrg OPC_SEL_F16 = _OPC(3, 12), 124b8e80941Smrg OPC_SEL_F32 = _OPC(3, 13), 125b8e80941Smrg OPC_SAD_S16 = _OPC(3, 14), 126b8e80941Smrg OPC_SAD_S32 = _OPC(3, 15), 127b8e80941Smrg 128b8e80941Smrg /* category 4: */ 129b8e80941Smrg OPC_RCP = _OPC(4, 0), 130b8e80941Smrg OPC_RSQ = _OPC(4, 1), 131b8e80941Smrg OPC_LOG2 = _OPC(4, 2), 132b8e80941Smrg OPC_EXP2 = _OPC(4, 3), 133b8e80941Smrg OPC_SIN = _OPC(4, 4), 134b8e80941Smrg OPC_COS = _OPC(4, 5), 135b8e80941Smrg OPC_SQRT = _OPC(4, 6), 136b8e80941Smrg // 7-63 - invalid 137b8e80941Smrg 138b8e80941Smrg /* category 5: */ 139b8e80941Smrg OPC_ISAM = _OPC(5, 0), 140b8e80941Smrg OPC_ISAML = _OPC(5, 1), 141b8e80941Smrg OPC_ISAMM = _OPC(5, 2), 142b8e80941Smrg OPC_SAM = _OPC(5, 3), 143b8e80941Smrg OPC_SAMB = _OPC(5, 4), 144b8e80941Smrg OPC_SAML = _OPC(5, 5), 145b8e80941Smrg OPC_SAMGQ = _OPC(5, 6), 146b8e80941Smrg OPC_GETLOD = _OPC(5, 7), 147b8e80941Smrg OPC_CONV = _OPC(5, 8), 148b8e80941Smrg OPC_CONVM = _OPC(5, 9), 149b8e80941Smrg OPC_GETSIZE = _OPC(5, 10), 150b8e80941Smrg OPC_GETBUF = _OPC(5, 11), 151b8e80941Smrg OPC_GETPOS = _OPC(5, 12), 152b8e80941Smrg OPC_GETINFO = _OPC(5, 13), 153b8e80941Smrg OPC_DSX = _OPC(5, 14), 154b8e80941Smrg OPC_DSY = _OPC(5, 15), 155b8e80941Smrg OPC_GATHER4R = _OPC(5, 16), 156b8e80941Smrg OPC_GATHER4G = _OPC(5, 17), 157b8e80941Smrg OPC_GATHER4B = _OPC(5, 18), 158b8e80941Smrg OPC_GATHER4A = _OPC(5, 19), 159b8e80941Smrg OPC_SAMGP0 = _OPC(5, 20), 160b8e80941Smrg OPC_SAMGP1 = _OPC(5, 21), 161b8e80941Smrg OPC_SAMGP2 = _OPC(5, 22), 162b8e80941Smrg OPC_SAMGP3 = _OPC(5, 23), 163b8e80941Smrg OPC_DSXPP_1 = _OPC(5, 24), 164b8e80941Smrg OPC_DSYPP_1 = _OPC(5, 25), 165b8e80941Smrg OPC_RGETPOS = _OPC(5, 26), 166b8e80941Smrg OPC_RGETINFO = _OPC(5, 27), 167b8e80941Smrg 168b8e80941Smrg /* category 6: */ 169b8e80941Smrg OPC_LDG = _OPC(6, 0), /* load-global */ 170b8e80941Smrg OPC_LDL = _OPC(6, 1), 171b8e80941Smrg OPC_LDP = _OPC(6, 2), 172b8e80941Smrg OPC_STG = _OPC(6, 3), /* store-global */ 173b8e80941Smrg OPC_STL = _OPC(6, 4), 174b8e80941Smrg OPC_STP = _OPC(6, 5), 175b8e80941Smrg OPC_LDIB = _OPC(6, 6), 176b8e80941Smrg OPC_G2L = _OPC(6, 7), 177b8e80941Smrg OPC_L2G = _OPC(6, 8), 178b8e80941Smrg OPC_PREFETCH = _OPC(6, 9), 179b8e80941Smrg OPC_LDLW = _OPC(6, 10), 180b8e80941Smrg OPC_STLW = _OPC(6, 11), 181b8e80941Smrg OPC_RESFMT = _OPC(6, 14), 182b8e80941Smrg OPC_RESINFO = _OPC(6, 15), 183b8e80941Smrg OPC_ATOMIC_ADD = _OPC(6, 16), 184b8e80941Smrg OPC_ATOMIC_SUB = _OPC(6, 17), 185b8e80941Smrg OPC_ATOMIC_XCHG = _OPC(6, 18), 186b8e80941Smrg OPC_ATOMIC_INC = _OPC(6, 19), 187b8e80941Smrg OPC_ATOMIC_DEC = _OPC(6, 20), 188b8e80941Smrg OPC_ATOMIC_CMPXCHG = _OPC(6, 21), 189b8e80941Smrg OPC_ATOMIC_MIN = _OPC(6, 22), 190b8e80941Smrg OPC_ATOMIC_MAX = _OPC(6, 23), 191b8e80941Smrg OPC_ATOMIC_AND = _OPC(6, 24), 192b8e80941Smrg OPC_ATOMIC_OR = _OPC(6, 25), 193b8e80941Smrg OPC_ATOMIC_XOR = _OPC(6, 26), 194b8e80941Smrg OPC_LDGB = _OPC(6, 27), 195b8e80941Smrg OPC_STGB = _OPC(6, 28), 196b8e80941Smrg OPC_STIB = _OPC(6, 29), 197b8e80941Smrg OPC_LDC = _OPC(6, 30), 198b8e80941Smrg OPC_LDLV = _OPC(6, 31), 199b8e80941Smrg 200b8e80941Smrg /* category 7: */ 201b8e80941Smrg OPC_BAR = _OPC(7, 0), 202b8e80941Smrg OPC_FENCE = _OPC(7, 1), 203b8e80941Smrg 204b8e80941Smrg /* meta instructions (category -1): */ 205b8e80941Smrg /* placeholder instr to mark shader inputs: */ 206b8e80941Smrg OPC_META_INPUT = _OPC(-1, 0), 207b8e80941Smrg /* The "fan-in" and "fan-out" instructions are used for keeping 208b8e80941Smrg * track of instructions that write to multiple dst registers 209b8e80941Smrg * (fan-out) like texture sample instructions, or read multiple 210b8e80941Smrg * consecutive scalar registers (fan-in) (bary.f, texture samp) 211b8e80941Smrg */ 212b8e80941Smrg OPC_META_FO = _OPC(-1, 2), 213b8e80941Smrg OPC_META_FI = _OPC(-1, 3), 214b8e80941Smrg 215b8e80941Smrg} opc_t; 216b8e80941Smrg 217b8e80941Smrg#define opc_cat(opc) ((int)((opc) >> NOPC_BITS)) 218b8e80941Smrg#define opc_op(opc) ((unsigned)((opc) & ((1 << NOPC_BITS) - 1))) 219b8e80941Smrg 220b8e80941Smrgtypedef enum { 221b8e80941Smrg TYPE_F16 = 0, 222b8e80941Smrg TYPE_F32 = 1, 223b8e80941Smrg TYPE_U16 = 2, 224b8e80941Smrg TYPE_U32 = 3, 225b8e80941Smrg TYPE_S16 = 4, 226b8e80941Smrg TYPE_S32 = 5, 227b8e80941Smrg TYPE_U8 = 6, 228b8e80941Smrg TYPE_S8 = 7, // XXX I assume? 229b8e80941Smrg} type_t; 230b8e80941Smrg 231b8e80941Smrgstatic inline uint32_t type_size(type_t type) 232b8e80941Smrg{ 233b8e80941Smrg switch (type) { 234b8e80941Smrg case TYPE_F32: 235b8e80941Smrg case TYPE_U32: 236b8e80941Smrg case TYPE_S32: 237b8e80941Smrg return 32; 238b8e80941Smrg case TYPE_F16: 239b8e80941Smrg case TYPE_U16: 240b8e80941Smrg case TYPE_S16: 241b8e80941Smrg return 16; 242b8e80941Smrg case TYPE_U8: 243b8e80941Smrg case TYPE_S8: 244b8e80941Smrg return 8; 245b8e80941Smrg default: 246b8e80941Smrg assert(0); /* invalid type */ 247b8e80941Smrg return 0; 248b8e80941Smrg } 249b8e80941Smrg} 250b8e80941Smrg 251b8e80941Smrgstatic inline int type_float(type_t type) 252b8e80941Smrg{ 253b8e80941Smrg return (type == TYPE_F32) || (type == TYPE_F16); 254b8e80941Smrg} 255b8e80941Smrg 256b8e80941Smrgstatic inline int type_uint(type_t type) 257b8e80941Smrg{ 258b8e80941Smrg return (type == TYPE_U32) || (type == TYPE_U16) || (type == TYPE_U8); 259b8e80941Smrg} 260b8e80941Smrg 261b8e80941Smrgstatic inline int type_sint(type_t type) 262b8e80941Smrg{ 263b8e80941Smrg return (type == TYPE_S32) || (type == TYPE_S16) || (type == TYPE_S8); 264b8e80941Smrg} 265b8e80941Smrg 266b8e80941Smrgtypedef union PACKED { 267b8e80941Smrg /* normal gpr or const src register: */ 268b8e80941Smrg struct PACKED { 269b8e80941Smrg uint32_t comp : 2; 270b8e80941Smrg uint32_t num : 10; 271b8e80941Smrg }; 272b8e80941Smrg /* for immediate val: */ 273b8e80941Smrg int32_t iim_val : 11; 274b8e80941Smrg /* to make compiler happy: */ 275b8e80941Smrg uint32_t dummy32; 276b8e80941Smrg uint32_t dummy10 : 10; 277b8e80941Smrg int32_t idummy10 : 10; 278b8e80941Smrg uint32_t dummy11 : 11; 279b8e80941Smrg uint32_t dummy12 : 12; 280b8e80941Smrg uint32_t dummy13 : 13; 281b8e80941Smrg uint32_t dummy8 : 8; 282b8e80941Smrg} reg_t; 283b8e80941Smrg 284b8e80941Smrg/* special registers: */ 285b8e80941Smrg#define REG_A0 61 /* address register */ 286b8e80941Smrg#define REG_P0 62 /* predicate register */ 287b8e80941Smrg 288b8e80941Smrgstatic inline int reg_special(reg_t reg) 289b8e80941Smrg{ 290b8e80941Smrg return (reg.num == REG_A0) || (reg.num == REG_P0); 291b8e80941Smrg} 292b8e80941Smrg 293b8e80941Smrgtypedef struct PACKED { 294b8e80941Smrg /* dword0: */ 295b8e80941Smrg union PACKED { 296b8e80941Smrg struct PACKED { 297b8e80941Smrg int16_t immed : 16; 298b8e80941Smrg uint32_t dummy1 : 16; 299b8e80941Smrg } a3xx; 300b8e80941Smrg struct PACKED { 301b8e80941Smrg int32_t immed : 20; 302b8e80941Smrg uint32_t dummy1 : 12; 303b8e80941Smrg } a4xx; 304b8e80941Smrg struct PACKED { 305b8e80941Smrg int32_t immed : 32; 306b8e80941Smrg } a5xx; 307b8e80941Smrg }; 308b8e80941Smrg 309b8e80941Smrg /* dword1: */ 310b8e80941Smrg uint32_t dummy2 : 8; 311b8e80941Smrg uint32_t repeat : 3; 312b8e80941Smrg uint32_t dummy3 : 1; 313b8e80941Smrg uint32_t ss : 1; 314b8e80941Smrg uint32_t dummy4 : 7; 315b8e80941Smrg uint32_t inv : 1; 316b8e80941Smrg uint32_t comp : 2; 317b8e80941Smrg uint32_t opc : 4; 318b8e80941Smrg uint32_t jmp_tgt : 1; 319b8e80941Smrg uint32_t sync : 1; 320b8e80941Smrg uint32_t opc_cat : 3; 321b8e80941Smrg} instr_cat0_t; 322b8e80941Smrg 323b8e80941Smrgtypedef struct PACKED { 324b8e80941Smrg /* dword0: */ 325b8e80941Smrg union PACKED { 326b8e80941Smrg /* for normal src register: */ 327b8e80941Smrg struct PACKED { 328b8e80941Smrg uint32_t src : 11; 329b8e80941Smrg /* at least low bit of pad must be zero or it will 330b8e80941Smrg * look like a address relative src 331b8e80941Smrg */ 332b8e80941Smrg uint32_t pad : 21; 333b8e80941Smrg }; 334b8e80941Smrg /* for address relative: */ 335b8e80941Smrg struct PACKED { 336b8e80941Smrg int32_t off : 10; 337b8e80941Smrg uint32_t src_rel_c : 1; 338b8e80941Smrg uint32_t src_rel : 1; 339b8e80941Smrg uint32_t unknown : 20; 340b8e80941Smrg }; 341b8e80941Smrg /* for immediate: */ 342b8e80941Smrg int32_t iim_val; 343b8e80941Smrg uint32_t uim_val; 344b8e80941Smrg float fim_val; 345b8e80941Smrg }; 346b8e80941Smrg 347b8e80941Smrg /* dword1: */ 348b8e80941Smrg uint32_t dst : 8; 349b8e80941Smrg uint32_t repeat : 3; 350b8e80941Smrg uint32_t src_r : 1; 351b8e80941Smrg uint32_t ss : 1; 352b8e80941Smrg uint32_t ul : 1; 353b8e80941Smrg uint32_t dst_type : 3; 354b8e80941Smrg uint32_t dst_rel : 1; 355b8e80941Smrg uint32_t src_type : 3; 356b8e80941Smrg uint32_t src_c : 1; 357b8e80941Smrg uint32_t src_im : 1; 358b8e80941Smrg uint32_t even : 1; 359b8e80941Smrg uint32_t pos_inf : 1; 360b8e80941Smrg uint32_t must_be_0 : 2; 361b8e80941Smrg uint32_t jmp_tgt : 1; 362b8e80941Smrg uint32_t sync : 1; 363b8e80941Smrg uint32_t opc_cat : 3; 364b8e80941Smrg} instr_cat1_t; 365b8e80941Smrg 366b8e80941Smrgtypedef struct PACKED { 367b8e80941Smrg /* dword0: */ 368b8e80941Smrg union PACKED { 369b8e80941Smrg struct PACKED { 370b8e80941Smrg uint32_t src1 : 11; 371b8e80941Smrg uint32_t must_be_zero1: 2; 372b8e80941Smrg uint32_t src1_im : 1; /* immediate */ 373b8e80941Smrg uint32_t src1_neg : 1; /* negate */ 374b8e80941Smrg uint32_t src1_abs : 1; /* absolute value */ 375b8e80941Smrg }; 376b8e80941Smrg struct PACKED { 377b8e80941Smrg uint32_t src1 : 10; 378b8e80941Smrg uint32_t src1_c : 1; /* relative-const */ 379b8e80941Smrg uint32_t src1_rel : 1; /* relative address */ 380b8e80941Smrg uint32_t must_be_zero : 1; 381b8e80941Smrg uint32_t dummy : 3; 382b8e80941Smrg } rel1; 383b8e80941Smrg struct PACKED { 384b8e80941Smrg uint32_t src1 : 12; 385b8e80941Smrg uint32_t src1_c : 1; /* const */ 386b8e80941Smrg uint32_t dummy : 3; 387b8e80941Smrg } c1; 388b8e80941Smrg }; 389b8e80941Smrg 390b8e80941Smrg union PACKED { 391b8e80941Smrg struct PACKED { 392b8e80941Smrg uint32_t src2 : 11; 393b8e80941Smrg uint32_t must_be_zero2: 2; 394b8e80941Smrg uint32_t src2_im : 1; /* immediate */ 395b8e80941Smrg uint32_t src2_neg : 1; /* negate */ 396b8e80941Smrg uint32_t src2_abs : 1; /* absolute value */ 397b8e80941Smrg }; 398b8e80941Smrg struct PACKED { 399b8e80941Smrg uint32_t src2 : 10; 400b8e80941Smrg uint32_t src2_c : 1; /* relative-const */ 401b8e80941Smrg uint32_t src2_rel : 1; /* relative address */ 402b8e80941Smrg uint32_t must_be_zero : 1; 403b8e80941Smrg uint32_t dummy : 3; 404b8e80941Smrg } rel2; 405b8e80941Smrg struct PACKED { 406b8e80941Smrg uint32_t src2 : 12; 407b8e80941Smrg uint32_t src2_c : 1; /* const */ 408b8e80941Smrg uint32_t dummy : 3; 409b8e80941Smrg } c2; 410b8e80941Smrg }; 411b8e80941Smrg 412b8e80941Smrg /* dword1: */ 413b8e80941Smrg uint32_t dst : 8; 414b8e80941Smrg uint32_t repeat : 2; 415b8e80941Smrg uint32_t sat : 1; 416b8e80941Smrg uint32_t src1_r : 1; /* doubles as nop0 if repeat==0 */ 417b8e80941Smrg uint32_t ss : 1; 418b8e80941Smrg uint32_t ul : 1; /* dunno */ 419b8e80941Smrg uint32_t dst_half : 1; /* or widen/narrow.. ie. dst hrN <-> rN */ 420b8e80941Smrg uint32_t ei : 1; 421b8e80941Smrg uint32_t cond : 3; 422b8e80941Smrg uint32_t src2_r : 1; /* doubles as nop1 if repeat==0 */ 423b8e80941Smrg uint32_t full : 1; /* not half */ 424b8e80941Smrg uint32_t opc : 6; 425b8e80941Smrg uint32_t jmp_tgt : 1; 426b8e80941Smrg uint32_t sync : 1; 427b8e80941Smrg uint32_t opc_cat : 3; 428b8e80941Smrg} instr_cat2_t; 429b8e80941Smrg 430b8e80941Smrgtypedef struct PACKED { 431b8e80941Smrg /* dword0: */ 432b8e80941Smrg union PACKED { 433b8e80941Smrg struct PACKED { 434b8e80941Smrg uint32_t src1 : 11; 435b8e80941Smrg uint32_t must_be_zero1: 2; 436b8e80941Smrg uint32_t src2_c : 1; 437b8e80941Smrg uint32_t src1_neg : 1; 438b8e80941Smrg uint32_t src2_r : 1; /* doubles as nop1 if repeat==0 */ 439b8e80941Smrg }; 440b8e80941Smrg struct PACKED { 441b8e80941Smrg uint32_t src1 : 10; 442b8e80941Smrg uint32_t src1_c : 1; 443b8e80941Smrg uint32_t src1_rel : 1; 444b8e80941Smrg uint32_t must_be_zero : 1; 445b8e80941Smrg uint32_t dummy : 3; 446b8e80941Smrg } rel1; 447b8e80941Smrg struct PACKED { 448b8e80941Smrg uint32_t src1 : 12; 449b8e80941Smrg uint32_t src1_c : 1; 450b8e80941Smrg uint32_t dummy : 3; 451b8e80941Smrg } c1; 452b8e80941Smrg }; 453b8e80941Smrg 454b8e80941Smrg union PACKED { 455b8e80941Smrg struct PACKED { 456b8e80941Smrg uint32_t src3 : 11; 457b8e80941Smrg uint32_t must_be_zero2: 2; 458b8e80941Smrg uint32_t src3_r : 1; 459b8e80941Smrg uint32_t src2_neg : 1; 460b8e80941Smrg uint32_t src3_neg : 1; 461b8e80941Smrg }; 462b8e80941Smrg struct PACKED { 463b8e80941Smrg uint32_t src3 : 10; 464b8e80941Smrg uint32_t src3_c : 1; 465b8e80941Smrg uint32_t src3_rel : 1; 466b8e80941Smrg uint32_t must_be_zero : 1; 467b8e80941Smrg uint32_t dummy : 3; 468b8e80941Smrg } rel2; 469b8e80941Smrg struct PACKED { 470b8e80941Smrg uint32_t src3 : 12; 471b8e80941Smrg uint32_t src3_c : 1; 472b8e80941Smrg uint32_t dummy : 3; 473b8e80941Smrg } c2; 474b8e80941Smrg }; 475b8e80941Smrg 476b8e80941Smrg /* dword1: */ 477b8e80941Smrg uint32_t dst : 8; 478b8e80941Smrg uint32_t repeat : 2; 479b8e80941Smrg uint32_t sat : 1; 480b8e80941Smrg uint32_t src1_r : 1; /* doubles as nop0 if repeat==0 */ 481b8e80941Smrg uint32_t ss : 1; 482b8e80941Smrg uint32_t ul : 1; 483b8e80941Smrg uint32_t dst_half : 1; /* or widen/narrow.. ie. dst hrN <-> rN */ 484b8e80941Smrg uint32_t src2 : 8; 485b8e80941Smrg uint32_t opc : 4; 486b8e80941Smrg uint32_t jmp_tgt : 1; 487b8e80941Smrg uint32_t sync : 1; 488b8e80941Smrg uint32_t opc_cat : 3; 489b8e80941Smrg} instr_cat3_t; 490b8e80941Smrg 491b8e80941Smrgstatic inline bool instr_cat3_full(instr_cat3_t *cat3) 492b8e80941Smrg{ 493b8e80941Smrg switch (_OPC(3, cat3->opc)) { 494b8e80941Smrg case OPC_MAD_F16: 495b8e80941Smrg case OPC_MAD_U16: 496b8e80941Smrg case OPC_MAD_S16: 497b8e80941Smrg case OPC_SEL_B16: 498b8e80941Smrg case OPC_SEL_S16: 499b8e80941Smrg case OPC_SEL_F16: 500b8e80941Smrg case OPC_SAD_S16: 501b8e80941Smrg case OPC_SAD_S32: // really?? 502b8e80941Smrg return false; 503b8e80941Smrg default: 504b8e80941Smrg return true; 505b8e80941Smrg } 506b8e80941Smrg} 507b8e80941Smrg 508b8e80941Smrgtypedef struct PACKED { 509b8e80941Smrg /* dword0: */ 510b8e80941Smrg union PACKED { 511b8e80941Smrg struct PACKED { 512b8e80941Smrg uint32_t src : 11; 513b8e80941Smrg uint32_t must_be_zero1: 2; 514b8e80941Smrg uint32_t src_im : 1; /* immediate */ 515b8e80941Smrg uint32_t src_neg : 1; /* negate */ 516b8e80941Smrg uint32_t src_abs : 1; /* absolute value */ 517b8e80941Smrg }; 518b8e80941Smrg struct PACKED { 519b8e80941Smrg uint32_t src : 10; 520b8e80941Smrg uint32_t src_c : 1; /* relative-const */ 521b8e80941Smrg uint32_t src_rel : 1; /* relative address */ 522b8e80941Smrg uint32_t must_be_zero : 1; 523b8e80941Smrg uint32_t dummy : 3; 524b8e80941Smrg } rel; 525b8e80941Smrg struct PACKED { 526b8e80941Smrg uint32_t src : 12; 527b8e80941Smrg uint32_t src_c : 1; /* const */ 528b8e80941Smrg uint32_t dummy : 3; 529b8e80941Smrg } c; 530b8e80941Smrg }; 531b8e80941Smrg uint32_t dummy1 : 16; /* seem to be ignored */ 532b8e80941Smrg 533b8e80941Smrg /* dword1: */ 534b8e80941Smrg uint32_t dst : 8; 535b8e80941Smrg uint32_t repeat : 2; 536b8e80941Smrg uint32_t sat : 1; 537b8e80941Smrg uint32_t src_r : 1; 538b8e80941Smrg uint32_t ss : 1; 539b8e80941Smrg uint32_t ul : 1; 540b8e80941Smrg uint32_t dst_half : 1; /* or widen/narrow.. ie. dst hrN <-> rN */ 541b8e80941Smrg uint32_t dummy2 : 5; /* seem to be ignored */ 542b8e80941Smrg uint32_t full : 1; /* not half */ 543b8e80941Smrg uint32_t opc : 6; 544b8e80941Smrg uint32_t jmp_tgt : 1; 545b8e80941Smrg uint32_t sync : 1; 546b8e80941Smrg uint32_t opc_cat : 3; 547b8e80941Smrg} instr_cat4_t; 548b8e80941Smrg 549b8e80941Smrgtypedef struct PACKED { 550b8e80941Smrg /* dword0: */ 551b8e80941Smrg union PACKED { 552b8e80941Smrg /* normal case: */ 553b8e80941Smrg struct PACKED { 554b8e80941Smrg uint32_t full : 1; /* not half */ 555b8e80941Smrg uint32_t src1 : 8; 556b8e80941Smrg uint32_t src2 : 8; 557b8e80941Smrg uint32_t dummy1 : 4; /* seem to be ignored */ 558b8e80941Smrg uint32_t samp : 4; 559b8e80941Smrg uint32_t tex : 7; 560b8e80941Smrg } norm; 561b8e80941Smrg /* s2en case: */ 562b8e80941Smrg struct PACKED { 563b8e80941Smrg uint32_t full : 1; /* not half */ 564b8e80941Smrg uint32_t src1 : 8; 565b8e80941Smrg uint32_t src2 : 11; 566b8e80941Smrg uint32_t dummy1 : 1; 567b8e80941Smrg uint32_t src3 : 8; 568b8e80941Smrg uint32_t dummy2 : 3; 569b8e80941Smrg } s2en; 570b8e80941Smrg /* same in either case: */ 571b8e80941Smrg // XXX I think, confirm this 572b8e80941Smrg struct PACKED { 573b8e80941Smrg uint32_t full : 1; /* not half */ 574b8e80941Smrg uint32_t src1 : 8; 575b8e80941Smrg uint32_t pad : 23; 576b8e80941Smrg }; 577b8e80941Smrg }; 578b8e80941Smrg 579b8e80941Smrg /* dword1: */ 580b8e80941Smrg uint32_t dst : 8; 581b8e80941Smrg uint32_t wrmask : 4; /* write-mask */ 582b8e80941Smrg uint32_t type : 3; 583b8e80941Smrg uint32_t dummy2 : 1; /* seems to be ignored */ 584b8e80941Smrg uint32_t is_3d : 1; 585b8e80941Smrg 586b8e80941Smrg uint32_t is_a : 1; 587b8e80941Smrg uint32_t is_s : 1; 588b8e80941Smrg uint32_t is_s2en : 1; 589b8e80941Smrg uint32_t is_o : 1; 590b8e80941Smrg uint32_t is_p : 1; 591b8e80941Smrg 592b8e80941Smrg uint32_t opc : 5; 593b8e80941Smrg uint32_t jmp_tgt : 1; 594b8e80941Smrg uint32_t sync : 1; 595b8e80941Smrg uint32_t opc_cat : 3; 596b8e80941Smrg} instr_cat5_t; 597b8e80941Smrg 598b8e80941Smrg/* dword0 encoding for src_off: [src1 + off], src2: */ 599b8e80941Smrgtypedef struct PACKED { 600b8e80941Smrg /* dword0: */ 601b8e80941Smrg uint32_t mustbe1 : 1; 602b8e80941Smrg int32_t off : 13; 603b8e80941Smrg uint32_t src1 : 8; 604b8e80941Smrg uint32_t src1_im : 1; 605b8e80941Smrg uint32_t src2_im : 1; 606b8e80941Smrg uint32_t src2 : 8; 607b8e80941Smrg 608b8e80941Smrg /* dword1: */ 609b8e80941Smrg uint32_t dword1; 610b8e80941Smrg} instr_cat6a_t; 611b8e80941Smrg 612b8e80941Smrg/* dword0 encoding for !src_off: [src1], src2 */ 613b8e80941Smrgtypedef struct PACKED { 614b8e80941Smrg /* dword0: */ 615b8e80941Smrg uint32_t mustbe0 : 1; 616b8e80941Smrg uint32_t src1 : 13; 617b8e80941Smrg uint32_t ignore0 : 8; 618b8e80941Smrg uint32_t src1_im : 1; 619b8e80941Smrg uint32_t src2_im : 1; 620b8e80941Smrg uint32_t src2 : 8; 621b8e80941Smrg 622b8e80941Smrg /* dword1: */ 623b8e80941Smrg uint32_t dword1; 624b8e80941Smrg} instr_cat6b_t; 625b8e80941Smrg 626b8e80941Smrg/* dword1 encoding for dst_off: */ 627b8e80941Smrgtypedef struct PACKED { 628b8e80941Smrg /* dword0: */ 629b8e80941Smrg uint32_t dword0; 630b8e80941Smrg 631b8e80941Smrg /* note: there is some weird stuff going on where sometimes 632b8e80941Smrg * cat6->a.off is involved.. but that seems like a bug in 633b8e80941Smrg * the blob, since it is used even if !cat6->src_off 634b8e80941Smrg * It would make sense for there to be some more bits to 635b8e80941Smrg * bring us to 11 bits worth of offset, but not sure.. 636b8e80941Smrg */ 637b8e80941Smrg int32_t off : 8; 638b8e80941Smrg uint32_t mustbe1 : 1; 639b8e80941Smrg uint32_t dst : 8; 640b8e80941Smrg uint32_t pad1 : 15; 641b8e80941Smrg} instr_cat6c_t; 642b8e80941Smrg 643b8e80941Smrg/* dword1 encoding for !dst_off: */ 644b8e80941Smrgtypedef struct PACKED { 645b8e80941Smrg /* dword0: */ 646b8e80941Smrg uint32_t dword0; 647b8e80941Smrg 648b8e80941Smrg uint32_t dst : 8; 649b8e80941Smrg uint32_t mustbe0 : 1; 650b8e80941Smrg uint32_t idx : 8; 651b8e80941Smrg uint32_t pad0 : 15; 652b8e80941Smrg} instr_cat6d_t; 653b8e80941Smrg 654b8e80941Smrg/* ldgb and atomics.. 655b8e80941Smrg * 656b8e80941Smrg * ldgb: pad0=0, pad3=1 657b8e80941Smrg * atomic .g: pad0=1, pad3=1 658b8e80941Smrg * .l: pad0=1, pad3=0 659b8e80941Smrg */ 660b8e80941Smrgtypedef struct PACKED { 661b8e80941Smrg /* dword0: */ 662b8e80941Smrg uint32_t pad0 : 1; 663b8e80941Smrg uint32_t src3 : 8; 664b8e80941Smrg uint32_t d : 2; 665b8e80941Smrg uint32_t typed : 1; 666b8e80941Smrg uint32_t type_size : 2; 667b8e80941Smrg uint32_t src1 : 8; 668b8e80941Smrg uint32_t src1_im : 1; 669b8e80941Smrg uint32_t src2_im : 1; 670b8e80941Smrg uint32_t src2 : 8; 671b8e80941Smrg 672b8e80941Smrg /* dword1: */ 673b8e80941Smrg uint32_t dst : 8; 674b8e80941Smrg uint32_t mustbe0 : 1; 675b8e80941Smrg uint32_t src_ssbo : 8; 676b8e80941Smrg uint32_t pad2 : 3; // type 677b8e80941Smrg uint32_t g : 1; 678b8e80941Smrg uint32_t pad3 : 1; 679b8e80941Smrg uint32_t pad4 : 10; // opc/jmp_tgt/sync/opc_cat 680b8e80941Smrg} instr_cat6ldgb_t; 681b8e80941Smrg 682b8e80941Smrg/* stgb, pad0=0, pad3=2 683b8e80941Smrg */ 684b8e80941Smrgtypedef struct PACKED { 685b8e80941Smrg /* dword0: */ 686b8e80941Smrg uint32_t mustbe1 : 1; // ??? 687b8e80941Smrg uint32_t src1 : 8; 688b8e80941Smrg uint32_t d : 2; 689b8e80941Smrg uint32_t typed : 1; 690b8e80941Smrg uint32_t type_size : 2; 691b8e80941Smrg uint32_t pad0 : 9; 692b8e80941Smrg uint32_t src2_im : 1; 693b8e80941Smrg uint32_t src2 : 8; 694b8e80941Smrg 695b8e80941Smrg /* dword1: */ 696b8e80941Smrg uint32_t src3 : 8; 697b8e80941Smrg uint32_t src3_im : 1; 698b8e80941Smrg uint32_t dst_ssbo : 8; 699b8e80941Smrg uint32_t pad2 : 3; // type 700b8e80941Smrg uint32_t pad3 : 2; 701b8e80941Smrg uint32_t pad4 : 10; // opc/jmp_tgt/sync/opc_cat 702b8e80941Smrg} instr_cat6stgb_t; 703b8e80941Smrg 704b8e80941Smrgtypedef union PACKED { 705b8e80941Smrg instr_cat6a_t a; 706b8e80941Smrg instr_cat6b_t b; 707b8e80941Smrg instr_cat6c_t c; 708b8e80941Smrg instr_cat6d_t d; 709b8e80941Smrg instr_cat6ldgb_t ldgb; 710b8e80941Smrg instr_cat6stgb_t stgb; 711b8e80941Smrg struct PACKED { 712b8e80941Smrg /* dword0: */ 713b8e80941Smrg uint32_t src_off : 1; 714b8e80941Smrg uint32_t pad1 : 31; 715b8e80941Smrg 716b8e80941Smrg /* dword1: */ 717b8e80941Smrg uint32_t pad2 : 8; 718b8e80941Smrg uint32_t dst_off : 1; 719b8e80941Smrg uint32_t pad3 : 8; 720b8e80941Smrg uint32_t type : 3; 721b8e80941Smrg uint32_t g : 1; /* or in some cases it means dst immed */ 722b8e80941Smrg uint32_t pad4 : 1; 723b8e80941Smrg uint32_t opc : 5; 724b8e80941Smrg uint32_t jmp_tgt : 1; 725b8e80941Smrg uint32_t sync : 1; 726b8e80941Smrg uint32_t opc_cat : 3; 727b8e80941Smrg }; 728b8e80941Smrg} instr_cat6_t; 729b8e80941Smrg 730b8e80941Smrg/** 731b8e80941Smrg * For atomic ops (which return a value): 732b8e80941Smrg * 733b8e80941Smrg * pad1=1, pad2=c, pad3=0, pad4=3 734b8e80941Smrg * src1 - vecN offset/coords 735b8e80941Smrg * src2.x - is actually dest register 736b8e80941Smrg * src2.y - is 'data' except for cmpxchg where src2.y is 'compare' 737b8e80941Smrg * and src2.z is 'data' 738b8e80941Smrg * 739b8e80941Smrg * For stib (which does not return a value): 740b8e80941Smrg * pad1=0, pad2=c, pad3=0, pad4=2 741b8e80941Smrg * src1 - vecN offset/coords 742b8e80941Smrg * src2 - value to store 743b8e80941Smrg * 744b8e80941Smrg * For ldib: 745b8e80941Smrg * pad1=1, pad2=c, pad3=0, pad4=2 746b8e80941Smrg * src1 - vecN offset/coords 747b8e80941Smrg * 748b8e80941Smrg * for ldc (load from UBO using descriptor): 749b8e80941Smrg * pad1=0, pad2=8, pad3=0, pad4=2 750b8e80941Smrg */ 751b8e80941Smrgtypedef struct PACKED { 752b8e80941Smrg /* dword0: */ 753b8e80941Smrg uint32_t pad1 : 9; 754b8e80941Smrg uint32_t d : 2; 755b8e80941Smrg uint32_t typed : 1; 756b8e80941Smrg uint32_t type_size : 2; 757b8e80941Smrg uint32_t opc : 5; 758b8e80941Smrg uint32_t pad2 : 5; 759b8e80941Smrg uint32_t src1 : 8; /* coordinate/offset */ 760b8e80941Smrg 761b8e80941Smrg /* dword1: */ 762b8e80941Smrg uint32_t src2 : 8; /* or the dst for load instructions */ 763b8e80941Smrg uint32_t pad3 : 1; //mustbe0 ?? or zero means imm vs reg for ssbo?? 764b8e80941Smrg uint32_t ssbo : 8; /* ssbo/image binding point */ 765b8e80941Smrg uint32_t type : 3; 766b8e80941Smrg uint32_t pad4 : 7; 767b8e80941Smrg uint32_t jmp_tgt : 1; 768b8e80941Smrg uint32_t sync : 1; 769b8e80941Smrg uint32_t opc_cat : 3; 770b8e80941Smrg} instr_cat6_a6xx_t; 771b8e80941Smrg 772b8e80941Smrgtypedef struct PACKED { 773b8e80941Smrg /* dword0: */ 774b8e80941Smrg uint32_t pad1 : 32; 775b8e80941Smrg 776b8e80941Smrg /* dword1: */ 777b8e80941Smrg uint32_t pad2 : 12; 778b8e80941Smrg uint32_t ss : 1; /* maybe in the encoding, but blob only uses (sy) */ 779b8e80941Smrg uint32_t pad3 : 6; 780b8e80941Smrg uint32_t w : 1; /* write */ 781b8e80941Smrg uint32_t r : 1; /* read */ 782b8e80941Smrg uint32_t l : 1; /* local */ 783b8e80941Smrg uint32_t g : 1; /* global */ 784b8e80941Smrg uint32_t opc : 4; /* presumed, but only a couple known OPCs */ 785b8e80941Smrg uint32_t jmp_tgt : 1; /* (jp) */ 786b8e80941Smrg uint32_t sync : 1; /* (sy) */ 787b8e80941Smrg uint32_t opc_cat : 3; 788b8e80941Smrg} instr_cat7_t; 789b8e80941Smrg 790b8e80941Smrgtypedef union PACKED { 791b8e80941Smrg instr_cat0_t cat0; 792b8e80941Smrg instr_cat1_t cat1; 793b8e80941Smrg instr_cat2_t cat2; 794b8e80941Smrg instr_cat3_t cat3; 795b8e80941Smrg instr_cat4_t cat4; 796b8e80941Smrg instr_cat5_t cat5; 797b8e80941Smrg instr_cat6_t cat6; 798b8e80941Smrg instr_cat6_a6xx_t cat6_a6xx; 799b8e80941Smrg instr_cat7_t cat7; 800b8e80941Smrg struct PACKED { 801b8e80941Smrg /* dword0: */ 802b8e80941Smrg uint32_t pad1 : 32; 803b8e80941Smrg 804b8e80941Smrg /* dword1: */ 805b8e80941Smrg uint32_t pad2 : 12; 806b8e80941Smrg uint32_t ss : 1; /* cat1-cat4 (cat0??) and cat7 (?) */ 807b8e80941Smrg uint32_t ul : 1; /* cat2-cat4 (and cat1 in blob.. which may be bug??) */ 808b8e80941Smrg uint32_t pad3 : 13; 809b8e80941Smrg uint32_t jmp_tgt : 1; 810b8e80941Smrg uint32_t sync : 1; 811b8e80941Smrg uint32_t opc_cat : 3; 812b8e80941Smrg 813b8e80941Smrg }; 814b8e80941Smrg} instr_t; 815b8e80941Smrg 816b8e80941Smrgstatic inline uint32_t instr_repeat(instr_t *instr) 817b8e80941Smrg{ 818b8e80941Smrg switch (instr->opc_cat) { 819b8e80941Smrg case 0: return instr->cat0.repeat; 820b8e80941Smrg case 1: return instr->cat1.repeat; 821b8e80941Smrg case 2: return instr->cat2.repeat; 822b8e80941Smrg case 3: return instr->cat3.repeat; 823b8e80941Smrg case 4: return instr->cat4.repeat; 824b8e80941Smrg default: return 0; 825b8e80941Smrg } 826b8e80941Smrg} 827b8e80941Smrg 828b8e80941Smrgstatic inline bool instr_sat(instr_t *instr) 829b8e80941Smrg{ 830b8e80941Smrg switch (instr->opc_cat) { 831b8e80941Smrg case 2: return instr->cat2.sat; 832b8e80941Smrg case 3: return instr->cat3.sat; 833b8e80941Smrg case 4: return instr->cat4.sat; 834b8e80941Smrg default: return false; 835b8e80941Smrg } 836b8e80941Smrg} 837b8e80941Smrg 838b8e80941Smrg/* We can probably drop the gpu_id arg, but keeping it for now so we can 839b8e80941Smrg * assert if we see something we think should be new encoding on an older 840b8e80941Smrg * gpu. 841b8e80941Smrg */ 842b8e80941Smrgstatic inline bool is_cat6_legacy(instr_t *instr, unsigned gpu_id) 843b8e80941Smrg{ 844b8e80941Smrg instr_cat6_a6xx_t *cat6 = &instr->cat6_a6xx; 845b8e80941Smrg 846b8e80941Smrg /* At least one of these two bits is pad in all the possible 847b8e80941Smrg * "legacy" cat6 encodings, and a analysis of all the pre-a6xx 848b8e80941Smrg * cmdstream traces I have indicates that the pad bit is zero 849b8e80941Smrg * in all cases. So we can use this to detect new encoding: 850b8e80941Smrg */ 851b8e80941Smrg if ((cat6->pad2 & 0x8) && (cat6->pad4 & 0x2)) { 852b8e80941Smrg assert(gpu_id >= 600); 853b8e80941Smrg assert(instr->cat6.opc == 0); 854b8e80941Smrg return false; 855b8e80941Smrg } 856b8e80941Smrg 857b8e80941Smrg return true; 858b8e80941Smrg} 859b8e80941Smrg 860b8e80941Smrgstatic inline uint32_t instr_opc(instr_t *instr, unsigned gpu_id) 861b8e80941Smrg{ 862b8e80941Smrg switch (instr->opc_cat) { 863b8e80941Smrg case 0: return instr->cat0.opc; 864b8e80941Smrg case 1: return 0; 865b8e80941Smrg case 2: return instr->cat2.opc; 866b8e80941Smrg case 3: return instr->cat3.opc; 867b8e80941Smrg case 4: return instr->cat4.opc; 868b8e80941Smrg case 5: return instr->cat5.opc; 869b8e80941Smrg case 6: 870b8e80941Smrg if (!is_cat6_legacy(instr, gpu_id)) 871b8e80941Smrg return instr->cat6_a6xx.opc; 872b8e80941Smrg return instr->cat6.opc; 873b8e80941Smrg case 7: return instr->cat7.opc; 874b8e80941Smrg default: return 0; 875b8e80941Smrg } 876b8e80941Smrg} 877b8e80941Smrg 878b8e80941Smrgstatic inline bool is_mad(opc_t opc) 879b8e80941Smrg{ 880b8e80941Smrg switch (opc) { 881b8e80941Smrg case OPC_MAD_U16: 882b8e80941Smrg case OPC_MAD_S16: 883b8e80941Smrg case OPC_MAD_U24: 884b8e80941Smrg case OPC_MAD_S24: 885b8e80941Smrg case OPC_MAD_F16: 886b8e80941Smrg case OPC_MAD_F32: 887b8e80941Smrg return true; 888b8e80941Smrg default: 889b8e80941Smrg return false; 890b8e80941Smrg } 891b8e80941Smrg} 892b8e80941Smrg 893b8e80941Smrgstatic inline bool is_madsh(opc_t opc) 894b8e80941Smrg{ 895b8e80941Smrg switch (opc) { 896b8e80941Smrg case OPC_MADSH_U16: 897b8e80941Smrg case OPC_MADSH_M16: 898b8e80941Smrg return true; 899b8e80941Smrg default: 900b8e80941Smrg return false; 901b8e80941Smrg } 902b8e80941Smrg} 903b8e80941Smrg 904b8e80941Smrgstatic inline bool is_atomic(opc_t opc) 905b8e80941Smrg{ 906b8e80941Smrg switch (opc) { 907b8e80941Smrg case OPC_ATOMIC_ADD: 908b8e80941Smrg case OPC_ATOMIC_SUB: 909b8e80941Smrg case OPC_ATOMIC_XCHG: 910b8e80941Smrg case OPC_ATOMIC_INC: 911b8e80941Smrg case OPC_ATOMIC_DEC: 912b8e80941Smrg case OPC_ATOMIC_CMPXCHG: 913b8e80941Smrg case OPC_ATOMIC_MIN: 914b8e80941Smrg case OPC_ATOMIC_MAX: 915b8e80941Smrg case OPC_ATOMIC_AND: 916b8e80941Smrg case OPC_ATOMIC_OR: 917b8e80941Smrg case OPC_ATOMIC_XOR: 918b8e80941Smrg return true; 919b8e80941Smrg default: 920b8e80941Smrg return false; 921b8e80941Smrg } 922b8e80941Smrg} 923b8e80941Smrg 924b8e80941Smrgstatic inline bool is_ssbo(opc_t opc) 925b8e80941Smrg{ 926b8e80941Smrg switch (opc) { 927b8e80941Smrg case OPC_RESFMT: 928b8e80941Smrg case OPC_RESINFO: 929b8e80941Smrg case OPC_LDGB: 930b8e80941Smrg case OPC_STGB: 931b8e80941Smrg case OPC_STIB: 932b8e80941Smrg return true; 933b8e80941Smrg default: 934b8e80941Smrg return false; 935b8e80941Smrg } 936b8e80941Smrg} 937b8e80941Smrg 938b8e80941Smrgstatic inline bool is_isam(opc_t opc) 939b8e80941Smrg{ 940b8e80941Smrg switch (opc) { 941b8e80941Smrg case OPC_ISAM: 942b8e80941Smrg case OPC_ISAML: 943b8e80941Smrg case OPC_ISAMM: 944b8e80941Smrg return true; 945b8e80941Smrg default: 946b8e80941Smrg return false; 947b8e80941Smrg } 948b8e80941Smrg} 949b8e80941Smrg 950b8e80941Smrgint disasm_a3xx(uint32_t *dwords, int sizedwords, int level, FILE *out, unsigned gpu_id); 951b8e80941Smrg 952b8e80941Smrg#endif /* INSTR_A3XX_H_ */ 953