1 /* 2 * Mesa 3-D graphics library 3 * 4 * Copyright (C) 2014 LunarG, Inc. 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining a 7 * copy of this software and associated documentation files (the "Software"), 8 * to deal in the Software without restriction, including without limitation 9 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 10 * and/or sell copies of the Software, and to permit persons to whom the 11 * Software is furnished to do so, subject to the following conditions: 12 * 13 * The above copyright notice and this permission notice shall be included 14 * in all copies or substantial portions of the Software. 15 * 16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 22 * DEALINGS IN THE SOFTWARE. 23 * 24 * Authors: 25 * Chia-I Wu <olv (at) lunarg.com> 26 */ 27 28 #include <stdio.h> 29 #include "genhw/genhw.h" 30 #include "toy_compiler.h" 31 32 #define DISASM_PRINTER_BUFFER_SIZE 256 33 #define DISASM_PRINTER_COLUMN_WIDTH 16 34 35 struct disasm_printer { 36 char buf[DISASM_PRINTER_BUFFER_SIZE]; 37 int len; 38 }; 39 40 struct disasm_operand { 41 unsigned file:2; 42 unsigned type:4; 43 44 unsigned addr_mode:1; 45 unsigned reg:8; 46 unsigned subreg:5; 47 unsigned addr_subreg:3; 48 unsigned addr_imm:10; 49 }; 50 51 struct disasm_dst_operand { 52 struct disasm_operand base; 53 54 unsigned horz_stride:2; 55 unsigned writemask:4; 56 }; 57 58 struct disasm_src_operand { 59 struct disasm_operand base; 60 61 unsigned vert_stride:4; 62 unsigned width:3; 63 unsigned horz_stride:2; 64 unsigned swizzle_x:2; 65 unsigned swizzle_y:2; 66 unsigned swizzle_z:2; 67 unsigned swizzle_w:2; 68 unsigned negate:1; 69 unsigned absolute:1; 70 }; 71 72 struct disasm_inst { 73 const struct ilo_dev *dev; 74 75 unsigned has_jip:1; 76 unsigned has_uip:1; 77 78 unsigned opcode:7; 79 unsigned access_mode:1; 80 unsigned mask_ctrl:1; 81 unsigned dep_ctrl:2; 82 unsigned qtr_ctrl:2; 83 unsigned thread_ctrl:2; 84 unsigned pred_ctrl:4; 85 unsigned pred_inv:1; 86 unsigned exec_size:3; 87 88 unsigned cond_modifier:4; 89 unsigned sfid:4; 90 unsigned fc:4; 91 92 unsigned acc_wr_ctrl:1; 93 unsigned branch_ctrl:1; 94 95 unsigned cmpt_ctrl:1; 96 unsigned debug_ctrl:1; 97 unsigned saturate:1; 98 99 unsigned nib_ctrl:1; 100 101 unsigned flag_reg:1; 102 unsigned flag_subreg:1; 103 104 struct disasm_dst_operand dst; 105 struct disasm_src_operand src0; 106 struct disasm_src_operand src1; 107 union { 108 struct disasm_src_operand src2; 109 uint64_t imm64; 110 111 uint32_t ud; 112 int32_t d; 113 uint16_t uw; 114 int16_t w; 115 float f; 116 117 struct { 118 int16_t jip; 119 int16_t uip; 120 } ip16; 121 122 struct { 123 int32_t jip; 124 int32_t uip; 125 } ip32; 126 } u; 127 }; 128 129 static const struct { 130 const char *name; 131 int src_count; 132 } disasm_opcode_table[128] = { 133 [GEN6_OPCODE_ILLEGAL] = { "illegal", 0 }, 134 [GEN6_OPCODE_MOV] = { "mov", 1 }, 135 [GEN6_OPCODE_SEL] = { "sel", 2 }, 136 [GEN6_OPCODE_MOVI] = { "movi", 1 }, 137 [GEN6_OPCODE_NOT] = { "not", 1 }, 138 [GEN6_OPCODE_AND] = { "and", 2 }, 139 [GEN6_OPCODE_OR] = { "or", 2 }, 140 [GEN6_OPCODE_XOR] = { "xor", 2 }, 141 [GEN6_OPCODE_SHR] = { "shr", 2 }, 142 [GEN6_OPCODE_SHL] = { "shl", 2 }, 143 [GEN6_OPCODE_DIM] = { "dim", 1 }, 144 [GEN6_OPCODE_ASR] = { "asr", 2 }, 145 [GEN6_OPCODE_CMP] = { "cmp", 2 }, 146 [GEN6_OPCODE_CMPN] = { "cmpn", 2 }, 147 [GEN7_OPCODE_CSEL] = { "csel", 3 }, 148 [GEN7_OPCODE_F32TO16] = { "f32to16", 1 }, 149 [GEN7_OPCODE_F16TO32] = { "f16to32", 1 }, 150 [GEN7_OPCODE_BFREV] = { "bfrev", 1 }, 151 [GEN7_OPCODE_BFE] = { "bfe", 3 }, 152 [GEN7_OPCODE_BFI1] = { "bfi1", 2 }, 153 [GEN7_OPCODE_BFI2] = { "bfi2", 3 }, 154 [GEN6_OPCODE_JMPI] = { "jmpi", 1 }, 155 [GEN7_OPCODE_BRD] = { "brd", 1 }, 156 [GEN6_OPCODE_IF] = { "if", 2 }, 157 [GEN7_OPCODE_BRC] = { "brc", 1 }, 158 [GEN6_OPCODE_ELSE] = { "else", 1 }, 159 [GEN6_OPCODE_ENDIF] = { "endif", 0 }, 160 [GEN6_OPCODE_CASE] = { "case", 2 }, 161 [GEN6_OPCODE_WHILE] = { "while", 1 }, 162 [GEN6_OPCODE_BREAK] = { "break", 1 }, 163 [GEN6_OPCODE_CONT] = { "cont", 1 }, 164 [GEN6_OPCODE_HALT] = { "halt", 1 }, 165 [GEN75_OPCODE_CALLA] = { "calla", 1 }, 166 [GEN6_OPCODE_CALL] = { "call", 1 }, 167 [GEN6_OPCODE_RETURN] = { "return", 1 }, 168 [GEN8_OPCODE_GOTO] = { "goto", 1 }, 169 [GEN6_OPCODE_WAIT] = { "wait", 1 }, 170 [GEN6_OPCODE_SEND] = { "send", 1 }, 171 [GEN6_OPCODE_SENDC] = { "sendc", 1 }, 172 [GEN6_OPCODE_MATH] = { "math", 2 }, 173 [GEN6_OPCODE_ADD] = { "add", 2 }, 174 [GEN6_OPCODE_MUL] = { "mul", 2 }, 175 [GEN6_OPCODE_AVG] = { "avg", 2 }, 176 [GEN6_OPCODE_FRC] = { "frc", 1 }, 177 [GEN6_OPCODE_RNDU] = { "rndu", 1 }, 178 [GEN6_OPCODE_RNDD] = { "rndd", 1 }, 179 [GEN6_OPCODE_RNDE] = { "rnde", 1 }, 180 [GEN6_OPCODE_RNDZ] = { "rndz", 1 }, 181 [GEN6_OPCODE_MAC] = { "mac", 2 }, 182 [GEN6_OPCODE_MACH] = { "mach", 2 }, 183 [GEN6_OPCODE_LZD] = { "lzd", 1 }, 184 [GEN7_OPCODE_FBH] = { "fbh", 1 }, 185 [GEN7_OPCODE_FBL] = { "fbl", 1 }, 186 [GEN7_OPCODE_CBIT] = { "cbit", 1 }, 187 [GEN7_OPCODE_ADDC] = { "addc", 2 }, 188 [GEN7_OPCODE_SUBB] = { "subb", 2 }, 189 [GEN6_OPCODE_SAD2] = { "sad2", 2 }, 190 [GEN6_OPCODE_SADA2] = { "sada2", 2 }, 191 [GEN6_OPCODE_DP4] = { "dp4", 2 }, 192 [GEN6_OPCODE_DPH] = { "dph", 2 }, 193 [GEN6_OPCODE_DP3] = { "dp3", 2 }, 194 [GEN6_OPCODE_DP2] = { "dp2", 2 }, 195 [GEN6_OPCODE_LINE] = { "line", 2 }, 196 [GEN6_OPCODE_PLN] = { "pln", 2 }, 197 [GEN6_OPCODE_MAD] = { "mad", 3 }, 198 [GEN6_OPCODE_LRP] = { "lrp", 3 }, 199 [GEN6_OPCODE_NOP] = { "nop", 0 }, 200 }; 201 202 static void 203 disasm_inst_decode_dw0_opcode_gen6(struct disasm_inst *inst, uint32_t dw0) 204 { 205 ILO_DEV_ASSERT(inst->dev, 6, 8); 206 207 inst->opcode = GEN_EXTRACT(dw0, GEN6_INST_OPCODE); 208 209 switch (inst->opcode) { 210 case GEN6_OPCODE_IF: 211 inst->has_jip = true; 212 inst->has_uip = (ilo_dev_gen(inst->dev) >= ILO_GEN(7)); 213 break; 214 case GEN6_OPCODE_ELSE: 215 inst->has_jip = true; 216 inst->has_uip = (ilo_dev_gen(inst->dev) >= ILO_GEN(8)); 217 break; 218 case GEN6_OPCODE_BREAK: 219 case GEN6_OPCODE_CONT: 220 case GEN6_OPCODE_HALT: 221 inst->has_uip = true; 222 /* fall through */ 223 case GEN6_OPCODE_JMPI: 224 case GEN7_OPCODE_BRD: 225 case GEN7_OPCODE_BRC: 226 case GEN6_OPCODE_ENDIF: 227 case GEN6_OPCODE_CASE: 228 case GEN6_OPCODE_WHILE: 229 case GEN75_OPCODE_CALLA: 230 case GEN6_OPCODE_CALL: 231 case GEN6_OPCODE_RETURN: 232 inst->has_jip = true; 233 break; 234 default: 235 break; 236 } 237 } 238 239 static void 240 disasm_inst_decode_dw0_gen6(struct disasm_inst *inst, uint32_t dw0) 241 { 242 ILO_DEV_ASSERT(inst->dev, 6, 8); 243 244 disasm_inst_decode_dw0_opcode_gen6(inst, dw0); 245 246 inst->access_mode = GEN_EXTRACT(dw0, GEN6_INST_ACCESSMODE); 247 248 if (ilo_dev_gen(inst->dev) >= ILO_GEN(8)) { 249 inst->dep_ctrl = GEN_EXTRACT(dw0, GEN8_INST_DEPCTRL); 250 inst->nib_ctrl = (bool) (dw0 & GEN8_INST_NIBCTRL); 251 } else { 252 inst->mask_ctrl = GEN_EXTRACT(dw0, GEN6_INST_MASKCTRL); 253 inst->dep_ctrl = GEN_EXTRACT(dw0, GEN6_INST_DEPCTRL); 254 } 255 256 inst->qtr_ctrl = GEN_EXTRACT(dw0, GEN6_INST_QTRCTRL); 257 inst->thread_ctrl = GEN_EXTRACT(dw0, GEN6_INST_THREADCTRL); 258 inst->pred_ctrl = GEN_EXTRACT(dw0, GEN6_INST_PREDCTRL); 259 260 inst->pred_inv = (bool) (dw0 & GEN6_INST_PREDINV); 261 262 inst->exec_size = GEN_EXTRACT(dw0, GEN6_INST_EXECSIZE); 263 264 switch (inst->opcode) { 265 case GEN6_OPCODE_SEND: 266 case GEN6_OPCODE_SENDC: 267 inst->sfid = GEN_EXTRACT(dw0, GEN6_INST_SFID); 268 break; 269 case GEN6_OPCODE_MATH: 270 inst->fc = GEN_EXTRACT(dw0, GEN6_INST_FC); 271 break; 272 default: 273 inst->cond_modifier = GEN_EXTRACT(dw0, GEN6_INST_CONDMODIFIER); 274 break; 275 } 276 277 switch (inst->opcode) { 278 case GEN6_OPCODE_IF: 279 case GEN6_OPCODE_ELSE: 280 case GEN8_OPCODE_GOTO: 281 if (ilo_dev_gen(inst->dev) >= ILO_GEN(8)) { 282 inst->branch_ctrl = (bool) (dw0 & GEN8_INST_BRANCHCTRL); 283 break; 284 } 285 default: 286 inst->acc_wr_ctrl = (bool) (dw0 & GEN6_INST_ACCWRCTRL); 287 break; 288 } 289 290 inst->cmpt_ctrl = (bool) (dw0 & GEN6_INST_CMPTCTRL); 291 inst->debug_ctrl = (bool) (dw0 & GEN6_INST_DEBUGCTRL); 292 inst->saturate = (bool) (dw0 & GEN6_INST_SATURATE); 293 } 294 295 static void 296 disasm_inst_decode_dw1_low_gen6(struct disasm_inst *inst, uint32_t dw1) 297 { 298 ILO_DEV_ASSERT(inst->dev, 6, 7.5); 299 300 inst->dst.base.file = GEN_EXTRACT(dw1, GEN6_INST_DST_FILE); 301 inst->dst.base.type = GEN_EXTRACT(dw1, GEN6_INST_DST_TYPE); 302 inst->src0.base.file = GEN_EXTRACT(dw1, GEN6_INST_SRC0_FILE); 303 inst->src0.base.type = GEN_EXTRACT(dw1, GEN6_INST_SRC0_TYPE); 304 inst->src1.base.file = GEN_EXTRACT(dw1, GEN6_INST_SRC1_FILE); 305 inst->src1.base.type = GEN_EXTRACT(dw1, GEN6_INST_SRC1_TYPE); 306 307 if (ilo_dev_gen(inst->dev) >= ILO_GEN(7)) 308 inst->nib_ctrl = (bool) (dw1 & GEN7_INST_NIBCTRL); 309 } 310 311 static void 312 disasm_inst_decode_dw1_low_gen8(struct disasm_inst *inst, uint32_t dw1) 313 { 314 ILO_DEV_ASSERT(inst->dev, 8, 8); 315 316 inst->flag_subreg = GEN_EXTRACT(dw1, GEN8_INST_FLAG_SUBREG); 317 inst->flag_reg = GEN_EXTRACT(dw1, GEN8_INST_FLAG_REG); 318 inst->mask_ctrl = GEN_EXTRACT(dw1, GEN8_INST_MASKCTRL); 319 320 inst->dst.base.file = GEN_EXTRACT(dw1, GEN8_INST_DST_FILE); 321 inst->dst.base.type = GEN_EXTRACT(dw1, GEN8_INST_DST_TYPE); 322 inst->src0.base.file = GEN_EXTRACT(dw1, GEN8_INST_SRC0_FILE); 323 inst->src0.base.type = GEN_EXTRACT(dw1, GEN8_INST_SRC0_TYPE); 324 325 inst->dst.base.addr_imm = GEN_EXTRACT(dw1, GEN8_INST_DST_ADDR_IMM_BIT9) << 326 GEN8_INST_DST_ADDR_IMM_BIT9__SHR; 327 } 328 329 static void 330 disasm_inst_decode_dw1_high_gen6(struct disasm_inst *inst, uint32_t dw1) 331 { 332 ILO_DEV_ASSERT(inst->dev, 6, 8); 333 334 inst->dst.base.addr_mode = GEN_EXTRACT(dw1, GEN6_INST_DST_ADDRMODE); 335 336 if (inst->dst.base.addr_mode == GEN6_ADDRMODE_DIRECT) { 337 inst->dst.base.reg = GEN_EXTRACT(dw1, GEN6_INST_DST_REG); 338 339 if (inst->access_mode == GEN6_ALIGN_1) { 340 inst->dst.base.subreg = GEN_EXTRACT(dw1, GEN6_INST_DST_SUBREG); 341 } else { 342 inst->dst.base.subreg = 343 GEN_EXTRACT(dw1, GEN6_INST_DST_SUBREG_ALIGN16) << 344 GEN6_INST_DST_SUBREG_ALIGN16__SHR; 345 } 346 } else { 347 if (ilo_dev_gen(inst->dev) >= ILO_GEN(8)) { 348 inst->dst.base.addr_subreg = 349 GEN_EXTRACT(dw1, GEN8_INST_DST_ADDR_SUBREG); 350 351 /* bit 9 is already set in disasm_inst_decode_dw1_low_gen8() */ 352 if (inst->access_mode == GEN6_ALIGN_1) { 353 inst->dst.base.addr_imm |= 354 GEN_EXTRACT(dw1, GEN8_INST_DST_ADDR_IMM); 355 } else { 356 inst->dst.base.addr_imm |= 357 GEN_EXTRACT(dw1, GEN8_INST_DST_ADDR_IMM_ALIGN16) << 358 GEN8_INST_DST_ADDR_IMM_ALIGN16__SHR; 359 } 360 } else { 361 inst->dst.base.addr_subreg = 362 GEN_EXTRACT(dw1, GEN6_INST_DST_ADDR_SUBREG); 363 364 if (inst->access_mode == GEN6_ALIGN_1) { 365 inst->dst.base.addr_imm = 366 GEN_EXTRACT(dw1, GEN6_INST_DST_ADDR_IMM); 367 } else { 368 inst->dst.base.addr_imm = 369 GEN_EXTRACT(dw1, GEN6_INST_DST_ADDR_IMM_ALIGN16) << 370 GEN6_INST_DST_ADDR_IMM_ALIGN16__SHR; 371 } 372 } 373 } 374 375 inst->dst.horz_stride = GEN_EXTRACT(dw1, GEN6_INST_DST_HORZSTRIDE); 376 377 if (inst->access_mode == GEN6_ALIGN_1) 378 inst->dst.writemask = 0xf; 379 else 380 inst->dst.writemask = GEN_EXTRACT(dw1, GEN6_INST_DST_WRITEMASK); 381 } 382 383 static void 384 disasm_inst_decode_dw1_gen6(struct disasm_inst *inst, uint32_t dw1) 385 { 386 ILO_DEV_ASSERT(inst->dev, 6, 8); 387 388 if (ilo_dev_gen(inst->dev) >= ILO_GEN(8)) 389 disasm_inst_decode_dw1_low_gen8(inst, dw1); 390 else 391 disasm_inst_decode_dw1_low_gen6(inst, dw1); 392 393 if (ilo_dev_gen(inst->dev) == ILO_GEN(6) && 394 inst->has_jip && !inst->has_uip) 395 inst->u.imm64 = dw1 >> 16; 396 else 397 disasm_inst_decode_dw1_high_gen6(inst, dw1); 398 } 399 400 static void 401 disasm_inst_decode_dw2_dw3_gen6(struct disasm_inst *inst, 402 uint32_t dw2, uint32_t dw3) 403 { 404 int imm_bits = 0, count, i; 405 406 ILO_DEV_ASSERT(inst->dev, 6, 8); 407 408 if (ilo_dev_gen(inst->dev) >= ILO_GEN(8)) { 409 /* how about real 64-bit immediates? */ 410 if (inst->has_uip) { 411 imm_bits = 64; 412 inst->src1.base.file = GEN6_FILE_IMM; 413 inst->src1.base.type = GEN6_TYPE_D; 414 } else { 415 inst->src1.base.file = GEN_EXTRACT(dw2, GEN8_INST_SRC1_FILE); 416 inst->src1.base.type = GEN_EXTRACT(dw2, GEN8_INST_SRC1_TYPE); 417 418 if (inst->src0.base.file == GEN6_FILE_IMM || 419 inst->src1.base.file == GEN6_FILE_IMM) 420 imm_bits = 32; 421 } 422 } else { 423 if (ilo_dev_gen(inst->dev) >= ILO_GEN(7)) 424 inst->flag_reg = GEN_EXTRACT(dw2, GEN7_INST_FLAG_REG); 425 inst->flag_subreg = GEN_EXTRACT(dw2, GEN6_INST_FLAG_SUBREG); 426 427 if (inst->src0.base.file == GEN6_FILE_IMM || 428 inst->src1.base.file == GEN6_FILE_IMM) 429 imm_bits = 32; 430 } 431 432 switch (imm_bits) { 433 case 32: 434 inst->u.imm64 = dw3; 435 count = 1; 436 break; 437 case 64: 438 inst->u.imm64 = (uint64_t) dw2 << 32 | dw3; 439 count = 0; 440 break; 441 default: 442 count = 2; 443 break; 444 } 445 446 for (i = 0; i < count; i++) { 447 struct disasm_src_operand *src = (i == 0) ? &inst->src0 : &inst->src1; 448 const uint32_t dw = (i == 0) ? dw2 : dw3; 449 450 src->base.addr_mode = GEN_EXTRACT(dw, GEN6_INST_SRC_ADDRMODE); 451 452 if (src->base.addr_mode == GEN6_ADDRMODE_DIRECT) { 453 src->base.reg = GEN_EXTRACT(dw, GEN6_INST_SRC_REG); 454 455 if (inst->access_mode == GEN6_ALIGN_1) { 456 src->base.subreg = GEN_EXTRACT(dw, GEN6_INST_SRC_SUBREG); 457 } else { 458 src->base.subreg = GEN_EXTRACT(dw, GEN6_INST_SRC_SUBREG_ALIGN16) << 459 GEN6_INST_SRC_SUBREG_ALIGN16__SHR; 460 } 461 } else { 462 if (ilo_dev_gen(inst->dev) >= ILO_GEN(8)) { 463 src->base.addr_subreg = 464 GEN_EXTRACT(dw, GEN8_INST_SRC_ADDR_SUBREG); 465 466 if (inst->access_mode == GEN6_ALIGN_1) { 467 src->base.addr_imm = GEN_EXTRACT(dw, GEN8_INST_SRC_ADDR_IMM); 468 } else { 469 src->base.addr_imm = 470 GEN_EXTRACT(dw, GEN8_INST_SRC_ADDR_IMM_ALIGN16) << 471 GEN8_INST_SRC_ADDR_IMM_ALIGN16__SHR; 472 } 473 474 if (i == 0) { 475 inst->dst.base.addr_imm |= GEN_EXTRACT(dw, 476 GEN8_INST_SRC0_ADDR_IMM_BIT9) << 477 GEN8_INST_SRC0_ADDR_IMM_BIT9__SHR; 478 } else { 479 inst->dst.base.addr_imm |= GEN_EXTRACT(dw, 480 GEN8_INST_SRC1_ADDR_IMM_BIT9) << 481 GEN8_INST_SRC1_ADDR_IMM_BIT9__SHR; 482 } 483 } else { 484 src->base.addr_subreg = 485 GEN_EXTRACT(dw, GEN6_INST_SRC_ADDR_SUBREG); 486 487 if (inst->access_mode == GEN6_ALIGN_1) { 488 src->base.addr_imm = GEN_EXTRACT(dw, GEN6_INST_SRC_ADDR_IMM); 489 } else { 490 src->base.addr_imm = 491 GEN_EXTRACT(dw, GEN6_INST_SRC_ADDR_IMM_ALIGN16) << 492 GEN6_INST_SRC_ADDR_IMM_ALIGN16__SHR; 493 } 494 } 495 } 496 497 src->vert_stride = GEN_EXTRACT(dw, GEN6_INST_SRC_VERTSTRIDE); 498 499 if (inst->access_mode == GEN6_ALIGN_1) { 500 src->width = GEN_EXTRACT(dw, GEN6_INST_SRC_WIDTH); 501 src->horz_stride = GEN_EXTRACT(dw, GEN6_INST_SRC_HORZSTRIDE); 502 503 src->swizzle_x = GEN6_SWIZZLE_X; 504 src->swizzle_y = GEN6_SWIZZLE_Y; 505 src->swizzle_z = GEN6_SWIZZLE_Z; 506 src->swizzle_w = GEN6_SWIZZLE_W; 507 } else { 508 src->width = GEN6_WIDTH_4; 509 src->horz_stride = GEN6_HORZSTRIDE_1; 510 511 src->swizzle_x = GEN_EXTRACT(dw, GEN6_INST_SRC_SWIZZLE_X); 512 src->swizzle_y = GEN_EXTRACT(dw, GEN6_INST_SRC_SWIZZLE_Y); 513 src->swizzle_z = GEN_EXTRACT(dw, GEN6_INST_SRC_SWIZZLE_Z); 514 src->swizzle_w = GEN_EXTRACT(dw, GEN6_INST_SRC_SWIZZLE_W); 515 } 516 517 src->negate = (bool) (dw & GEN6_INST_SRC_NEGATE); 518 src->absolute = (bool) (dw & GEN6_INST_SRC_ABSOLUTE); 519 } 520 } 521 522 static void 523 disasm_inst_decode_3src_dw1_gen6(struct disasm_inst *inst, uint32_t dw1) 524 { 525 static const unsigned type_mapping[4] = { 526 [GEN7_TYPE_F_3SRC] = GEN6_TYPE_F, 527 [GEN7_TYPE_D_3SRC] = GEN6_TYPE_D, 528 [GEN7_TYPE_UD_3SRC] = GEN6_TYPE_UD, 529 [GEN7_TYPE_DF_3SRC] = GEN7_TYPE_DF, 530 }; 531 532 ILO_DEV_ASSERT(inst->dev, 6, 7.5); 533 534 inst->flag_subreg = GEN_EXTRACT(dw1, GEN6_3SRC_FLAG_SUBREG); 535 536 if (ilo_dev_gen(inst->dev) >= ILO_GEN(7)) { 537 inst->nib_ctrl = (bool) (dw1 & GEN7_3SRC_NIBCTRL); 538 inst->flag_reg = GEN_EXTRACT(dw1, GEN7_3SRC_FLAG_REG); 539 540 inst->dst.base.file = GEN6_FILE_GRF; 541 inst->dst.base.type = GEN_EXTRACT(dw1, GEN7_3SRC_DST_TYPE); 542 inst->dst.base.type = type_mapping[inst->dst.base.type]; 543 544 inst->src0.base.type = GEN_EXTRACT(dw1, GEN7_3SRC_SRC_TYPE); 545 inst->src0.base.type = type_mapping[inst->src0.base.type]; 546 547 inst->src1.base.type = inst->src0.base.type; 548 inst->u.src2.base.type = inst->src0.base.type; 549 } else { 550 inst->dst.base.file = (dw1 & GEN6_3SRC_DST_FILE_MRF) ? 551 GEN6_FILE_MRF: GEN6_FILE_GRF; 552 inst->dst.base.type = GEN6_TYPE_F; 553 554 inst->src0.base.type = GEN6_TYPE_F; 555 inst->src1.base.type = GEN6_TYPE_F; 556 inst->u.src2.base.type = GEN6_TYPE_F; 557 } 558 559 inst->dst.base.addr_mode = GEN6_ADDRMODE_DIRECT; 560 inst->dst.base.reg = GEN_EXTRACT(dw1, GEN6_3SRC_DST_REG); 561 inst->dst.base.subreg = GEN_EXTRACT(dw1, GEN6_3SRC_DST_SUBREG) << 562 GEN6_3SRC_DST_SUBREG__SHR; 563 564 inst->dst.horz_stride = GEN6_HORZSTRIDE_1; 565 inst->dst.writemask = GEN_EXTRACT(dw1, GEN6_3SRC_DST_WRITEMASK); 566 567 inst->src0.base.file = GEN6_FILE_GRF; 568 inst->src0.negate = (bool) (dw1 & GEN6_3SRC_SRC0_NEGATE); 569 inst->src0.absolute = (bool) (dw1 & GEN6_3SRC_SRC0_ABSOLUTE); 570 inst->src1.base.file = GEN6_FILE_GRF; 571 inst->src1.negate = (bool) (dw1 & GEN6_3SRC_SRC1_NEGATE); 572 inst->src1.absolute = (bool) (dw1 & GEN6_3SRC_SRC1_ABSOLUTE); 573 inst->u.src2.base.file = GEN6_FILE_GRF; 574 inst->u.src2.negate = (bool) (dw1 & GEN6_3SRC_SRC2_NEGATE); 575 inst->u.src2.absolute = (bool) (dw1 & GEN6_3SRC_SRC2_ABSOLUTE); 576 } 577 578 static void 579 disasm_inst_decode_3src_dw1_gen8(struct disasm_inst *inst, uint32_t dw1) 580 { 581 static const unsigned type_mapping[8] = { 582 [GEN7_TYPE_F_3SRC] = GEN6_TYPE_F, 583 [GEN7_TYPE_D_3SRC] = GEN6_TYPE_D, 584 [GEN7_TYPE_UD_3SRC] = GEN6_TYPE_UD, 585 [GEN7_TYPE_DF_3SRC] = GEN7_TYPE_DF, 586 /* map unknown types to unknown types */ 587 [0x4] = 0xf, 588 [0x5] = 0xf, 589 [0x6] = 0xf, 590 [0x7] = 0xf, 591 }; 592 593 ILO_DEV_ASSERT(inst->dev, 8, 8); 594 595 inst->flag_subreg = GEN_EXTRACT(dw1, GEN8_3SRC_FLAG_SUBREG); 596 inst->flag_reg = GEN_EXTRACT(dw1, GEN8_3SRC_FLAG_REG); 597 inst->mask_ctrl = GEN_EXTRACT(dw1, GEN8_3SRC_MASKCTRL); 598 inst->src0.absolute = (bool) (dw1 & GEN8_3SRC_SRC0_ABSOLUTE); 599 inst->src0.negate = (bool) (dw1 & GEN8_3SRC_SRC0_NEGATE); 600 inst->src1.negate = (bool) (dw1 & GEN8_3SRC_SRC1_NEGATE); 601 inst->src1.absolute = (bool) (dw1 & GEN8_3SRC_SRC1_ABSOLUTE); 602 inst->u.src2.negate = (bool) (dw1 & GEN8_3SRC_SRC2_NEGATE); 603 inst->u.src2.absolute = (bool) (dw1 & GEN8_3SRC_SRC2_ABSOLUTE); 604 605 inst->src0.base.file = GEN6_FILE_GRF; 606 inst->src0.base.type = GEN_EXTRACT(dw1, GEN8_3SRC_SRC_TYPE); 607 inst->src0.base.type = type_mapping[inst->src0.base.type]; 608 609 inst->src1.base.file = GEN6_FILE_GRF; 610 inst->src1.base.type = inst->src0.base.type; 611 612 inst->u.src2.base.file = GEN6_FILE_GRF; 613 inst->u.src2.base.type = inst->src0.base.type; 614 615 inst->dst.base.file = GEN6_FILE_GRF; 616 inst->dst.base.type = GEN_EXTRACT(dw1, GEN8_3SRC_DST_TYPE); 617 inst->dst.base.type = type_mapping[inst->dst.base.type]; 618 inst->dst.base.addr_mode = GEN6_ADDRMODE_DIRECT; 619 inst->dst.horz_stride = GEN6_HORZSTRIDE_1; 620 621 inst->dst.writemask = GEN_EXTRACT(dw1, GEN6_3SRC_DST_WRITEMASK); 622 inst->dst.base.subreg = GEN_EXTRACT(dw1, GEN6_3SRC_DST_SUBREG) << 623 GEN6_3SRC_DST_SUBREG__SHR; 624 inst->dst.base.reg = GEN_EXTRACT(dw1, GEN6_3SRC_DST_REG); 625 } 626 627 static void 628 disasm_inst_decode_3src_dw2_dw3_gen6(struct disasm_inst *inst, 629 uint32_t dw2, uint32_t dw3) 630 { 631 const uint64_t qw = (uint64_t) dw3 << 32 | dw2; 632 int i; 633 634 ILO_DEV_ASSERT(inst->dev, 6, 8); 635 636 for (i = 0; i < 3; i++) { 637 struct disasm_src_operand *src = (i == 0) ? &inst->src0 : 638 (i == 1) ? &inst->src1 : 639 &inst->u.src2; 640 const uint32_t dw = (i == 0) ? GEN_EXTRACT(qw, GEN6_3SRC_SRC_0) : 641 (i == 1) ? GEN_EXTRACT(qw, GEN6_3SRC_SRC_1) : 642 GEN_EXTRACT(qw, GEN6_3SRC_SRC_2); 643 644 src->base.addr_mode = GEN6_ADDRMODE_DIRECT; 645 src->base.reg = GEN_EXTRACT(dw, GEN6_3SRC_SRC_REG); 646 src->base.subreg = GEN_EXTRACT(dw, GEN6_3SRC_SRC_SUBREG) << 647 GEN6_3SRC_SRC_SUBREG__SHR; 648 649 if (dw & GEN6_3SRC_SRC_REPCTRL) { 650 src->vert_stride = GEN6_VERTSTRIDE_0; 651 src->width = GEN6_WIDTH_1; 652 src->horz_stride = GEN6_HORZSTRIDE_0; 653 } else { 654 src->vert_stride = GEN6_VERTSTRIDE_4; 655 src->width = GEN6_WIDTH_4; 656 src->horz_stride = GEN6_HORZSTRIDE_1; 657 } 658 659 src->swizzle_x = GEN_EXTRACT(dw, GEN6_3SRC_SRC_SWIZZLE_X); 660 src->swizzle_y = GEN_EXTRACT(dw, GEN6_3SRC_SRC_SWIZZLE_Y); 661 src->swizzle_z = GEN_EXTRACT(dw, GEN6_3SRC_SRC_SWIZZLE_Z); 662 src->swizzle_w = GEN_EXTRACT(dw, GEN6_3SRC_SRC_SWIZZLE_W); 663 } 664 } 665 666 /* 667 * When GEN6_INST_CMPTCTRL of DW0 is set, the instruction has 64 bits and is 668 * in EU_INSTRUCTION_COMPACT_TWO_SRC form. We should have expanded it to its 669 * original form. 670 * 671 * Depending on the opcode, the 128-bits instruction is in one of the 672 * following forms 673 * 674 * - EU_INSTRUCTION_BASIC_ONE_SRC 675 * - EU_INSTRUCTION_BASIC_TWO_SRC 676 * - EU_INSTRUCTION_BASIC_THREE_SRC 677 * - EU_INSTRUCTION_BRANCH_CONDITIONAL 678 * - EU_INSTRUCTION_BRANCH_ONE_SRC 679 * - EU_INSTRUCTION_BRANCH_TWO_SRC 680 * - EU_INSTRUCTION_ILLEGAL 681 * - EU_INSTRUCTION_MATH 682 * - EU_INSTRUCTION_NOP 683 * - EU_INSTRUCTION_SEND 684 * 685 * In EU_INSTRUCTION_BASIC_ONE_SRC form, 686 * 687 * - DW0 is EU_INSTRUCTION_HEADER 688 * - DW1 is EU_INSTRUCTION_OPERAND_CONTROLS 689 * - DW2 is Source 0 and EU_INSTRUCTION_FLAGS 690 * - DW3 is reserved unless Source 0 is an immediate 691 * 692 * All other forms except EU_INSTRUCTION_BASIC_THREE_SRC are quite compatible 693 * with EU_INSTRUCTION_BASIC_ONE_SRC. 694 */ 695 static void 696 disasm_inst_decode(struct disasm_inst *inst, 697 const uint32_t *dw) 698 { 699 assert(!(dw[0] & GEN6_INST_CMPTCTRL)); 700 701 disasm_inst_decode_dw0_gen6(inst, dw[0]); 702 703 if (disasm_opcode_table[inst->opcode].src_count == 3) { 704 if (ilo_dev_gen(inst->dev) >= ILO_GEN(8)) 705 disasm_inst_decode_3src_dw1_gen8(inst, dw[1]); 706 else 707 disasm_inst_decode_3src_dw1_gen6(inst, dw[1]); 708 disasm_inst_decode_3src_dw2_dw3_gen6(inst, dw[2], dw[3]); 709 } else { 710 disasm_inst_decode_dw1_gen6(inst, dw[1]); 711 disasm_inst_decode_dw2_dw3_gen6(inst, dw[2], dw[3]); 712 } 713 } 714 715 static const char * 716 disasm_inst_opcode(const struct disasm_inst *inst) 717 { 718 return (disasm_opcode_table[inst->opcode].name) ? 719 disasm_opcode_table[inst->opcode].name : "BAD"; 720 } 721 722 static const char * 723 disasm_inst_pred_ctrl(const struct disasm_inst *inst) 724 { 725 if (inst->access_mode == GEN6_ALIGN_1) { 726 switch (inst->pred_ctrl) { 727 case GEN6_PREDCTRL_NORMAL: return ""; 728 case GEN6_PREDCTRL_ANYV: return ".anyv"; 729 case GEN6_PREDCTRL_ALLV: return ".allv"; 730 case GEN6_PREDCTRL_ANY2H: return ".any2h"; 731 case GEN6_PREDCTRL_ALL2H: return ".all2h"; 732 case GEN6_PREDCTRL_ANY4H: return ".any4h"; 733 case GEN6_PREDCTRL_ALL4H: return ".all4h"; 734 case GEN6_PREDCTRL_ANY8H: return ".any8h"; 735 case GEN6_PREDCTRL_ALL8H: return ".all8h"; 736 case GEN6_PREDCTRL_ANY16H: return ".any16h"; 737 case GEN6_PREDCTRL_ALL16H: return ".all16h"; 738 case GEN7_PREDCTRL_ANY32H: return ".any32h"; 739 case GEN7_PREDCTRL_ALL32H: return ".all32h"; 740 default: return ".BAD"; 741 } 742 } else { 743 switch (inst->pred_ctrl) { 744 case GEN6_PREDCTRL_NORMAL: return ""; 745 case GEN6_PREDCTRL_X: return ".x"; 746 case GEN6_PREDCTRL_Y: return ".y"; 747 case GEN6_PREDCTRL_Z: return ".z"; 748 case GEN6_PREDCTRL_W: return ".w"; 749 default: return ".BAD"; 750 } 751 } 752 } 753 754 static char 755 disasm_inst_pred_inv(const struct disasm_inst *inst) 756 { 757 return (inst->pred_inv) ? '-' : '+'; 758 } 759 760 static const char * 761 disasm_inst_exec_size(const struct disasm_inst *inst) 762 { 763 switch (inst->exec_size) { 764 case GEN6_EXECSIZE_1: return "1"; 765 case GEN6_EXECSIZE_2: return "2"; 766 case GEN6_EXECSIZE_4: return "4"; 767 case GEN6_EXECSIZE_8: return "8"; 768 case GEN6_EXECSIZE_16: return "16"; 769 case GEN6_EXECSIZE_32: return "32"; 770 default: return "BAD"; 771 } 772 } 773 774 static const char * 775 disasm_inst_fc(const struct disasm_inst *inst) 776 { 777 assert(inst->opcode == GEN6_OPCODE_MATH); 778 779 switch (inst->fc) { 780 case GEN6_MATH_INV: return "inv"; 781 case GEN6_MATH_LOG: return "log"; 782 case GEN6_MATH_EXP: return "exp"; 783 case GEN6_MATH_SQRT: return "sqrt"; 784 case GEN6_MATH_RSQ: return "rsq"; 785 case GEN6_MATH_SIN: return "sin"; 786 case GEN6_MATH_COS: return "cos"; 787 case GEN6_MATH_FDIV: return "fdiv"; 788 case GEN6_MATH_POW: return "pow"; 789 case GEN6_MATH_INT_DIV: return "int_div"; 790 case GEN6_MATH_INT_DIV_QUOTIENT: return "int_div_quotient"; 791 case GEN6_MATH_INT_DIV_REMAINDER: return "int_div_remainder"; 792 case GEN8_MATH_INVM: return "invm"; 793 case GEN8_MATH_RSQRTM: return "rsqrtm"; 794 default: return "BAD"; 795 } 796 } 797 798 static const char * 799 disasm_inst_sfid(const struct disasm_inst *inst) 800 { 801 assert(inst->opcode == GEN6_OPCODE_SEND || 802 inst->opcode == GEN6_OPCODE_SENDC); 803 804 switch (inst->sfid) { 805 case GEN6_SFID_NULL: return "null"; 806 case GEN6_SFID_SAMPLER: return "sampler"; 807 case GEN6_SFID_GATEWAY: return "gateway"; 808 case GEN6_SFID_DP_SAMPLER: return "dp sampler"; 809 case GEN6_SFID_DP_RC: return "dp render"; 810 case GEN6_SFID_URB: return "urb"; 811 case GEN6_SFID_SPAWNER: return "spawner"; 812 case GEN6_SFID_VME: return "vme"; 813 case GEN6_SFID_DP_CC: return "dp const"; 814 case GEN7_SFID_DP_DC0: return "dp data 0"; 815 case GEN7_SFID_PI: return "pixel interp"; 816 case GEN75_SFID_DP_DC1: return "dp data 1"; 817 default: return "BAD"; 818 } 819 } 820 821 static const char * 822 disasm_inst_cond_modifier(const struct disasm_inst *inst) 823 { 824 switch (inst->cond_modifier) { 825 case GEN6_COND_NONE: return ""; 826 case GEN6_COND_Z: return ".z"; 827 case GEN6_COND_NZ: return ".nz"; 828 case GEN6_COND_G: return ".g"; 829 case GEN6_COND_GE: return ".ge"; 830 case GEN6_COND_L: return ".l"; 831 case GEN6_COND_LE: return ".le"; 832 case GEN6_COND_O: return ".o"; 833 case GEN6_COND_U: return ".u"; 834 default: return ".BAD"; 835 } 836 } 837 838 static const char * 839 disasm_inst_debug_ctrl(const struct disasm_inst *inst) 840 { 841 return (inst->debug_ctrl) ? ".breakpoint" : ""; 842 } 843 844 static const char * 845 disasm_inst_saturate(const struct disasm_inst *inst) 846 { 847 return (inst->saturate) ? ".sat" : ""; 848 } 849 850 static const char * 851 disasm_inst_flag_reg(const struct disasm_inst *inst) 852 { 853 static const char *flag_names[2][2] = { 854 { "f0", "f0.1" }, 855 { "f1.0", "f1.1" }, 856 }; 857 858 return (inst->flag_reg <= 1 && inst->flag_subreg <= 1) ? 859 flag_names[inst->flag_reg][inst->flag_subreg] : "fBAD"; 860 } 861 862 static const char * 863 disasm_inst_access_mode(const struct disasm_inst *inst) 864 { 865 switch (inst->access_mode) { 866 case GEN6_ALIGN_1: return " align1"; 867 case GEN6_ALIGN_16: return " align16"; 868 default: return " alignBAD"; 869 } 870 } 871 872 static const char * 873 disasm_inst_mask_ctrl(const struct disasm_inst *inst) 874 { 875 switch (inst->mask_ctrl) { 876 case GEN6_MASKCTRL_NORMAL: return ""; 877 case GEN6_MASKCTRL_NOMASK: return " WE_all"; 878 default: return " WE_BAD"; 879 } 880 } 881 882 static const char * 883 disasm_inst_dep_ctrl(const struct disasm_inst *inst) 884 { 885 switch (inst->dep_ctrl) { 886 case GEN6_DEPCTRL_NORMAL: return ""; 887 case GEN6_DEPCTRL_NODDCLR: return " NoDDClr"; 888 case GEN6_DEPCTRL_NODDCHK: return " NoDDChk"; 889 case GEN6_DEPCTRL_NEITHER: return " NoDDClr,NoDDChk"; 890 default: return " NoDDBAD"; 891 } 892 } 893 894 static const char * 895 disasm_inst_qtr_ctrl(const struct disasm_inst *inst) 896 { 897 switch (inst->exec_size) { 898 case GEN6_EXECSIZE_8: 899 switch (inst->qtr_ctrl) { 900 case GEN6_QTRCTRL_1Q: return " 1Q"; 901 case GEN6_QTRCTRL_2Q: return " 2Q"; 902 case GEN6_QTRCTRL_3Q: return " 3Q"; 903 case GEN6_QTRCTRL_4Q: return " 4Q"; 904 default: return " BADQ"; 905 } 906 break; 907 case GEN6_EXECSIZE_16: 908 switch (inst->qtr_ctrl) { 909 case GEN6_QTRCTRL_1H: return " 1H"; 910 case GEN6_QTRCTRL_2H: return " 2H"; 911 default: return " BADH"; 912 } 913 break; 914 default: 915 return ""; 916 } 917 918 } 919 920 static const char * 921 disasm_inst_thread_ctrl(const struct disasm_inst *inst) 922 { 923 switch (inst->thread_ctrl) { 924 case GEN6_THREADCTRL_NORMAL: return ""; 925 case GEN6_THREADCTRL_ATOMIC: return " atomic"; 926 case GEN6_THREADCTRL_SWITCH: return " switch"; 927 default: return " BAD"; 928 } 929 } 930 931 static const char * 932 disasm_inst_acc_wr_ctrl(const struct disasm_inst *inst) 933 { 934 return (inst->acc_wr_ctrl) ? " AccWrEnable" : ""; 935 } 936 937 static const char * 938 disasm_inst_cmpt_ctrl(const struct disasm_inst *inst) 939 { 940 return (inst->cmpt_ctrl) ? " compacted" : ""; 941 } 942 943 static const char * 944 disasm_inst_eot(const struct disasm_inst *inst) 945 { 946 const uint32_t mdesc = inst->u.ud; 947 948 if (inst->opcode == GEN6_OPCODE_SEND || 949 inst->opcode == GEN6_OPCODE_SENDC) 950 return (mdesc & GEN6_MSG_EOT) ? " EOT" : ""; 951 else 952 return ""; 953 } 954 955 static const char * 956 disasm_inst_file(const struct disasm_inst *inst, 957 const struct disasm_operand *operand, 958 bool *multi_regs) 959 { 960 switch (operand->file) { 961 case GEN6_FILE_ARF: 962 switch (operand->reg & 0xf0) { 963 case GEN6_ARF_NULL: *multi_regs = false; return "null"; 964 case GEN6_ARF_A0: *multi_regs = true; return "a"; 965 case GEN6_ARF_ACC0: *multi_regs = true; return "acc"; 966 case GEN6_ARF_F0: *multi_regs = true; return "f"; 967 case GEN6_ARF_SR0: *multi_regs = true; return "sr"; 968 case GEN6_ARF_CR0: *multi_regs = true; return "cr"; 969 case GEN6_ARF_N0: *multi_regs = true; return "n"; 970 case GEN6_ARF_IP: *multi_regs = false; return "ip"; 971 case GEN6_ARF_TDR: *multi_regs = false; return "tdr"; 972 case GEN7_ARF_TM0: *multi_regs = true; return "tm"; 973 default: *multi_regs = false; return "BAD"; 974 } 975 break; 976 case GEN6_FILE_GRF: *multi_regs = true; return "g"; 977 case GEN6_FILE_MRF: *multi_regs = true; return "m"; 978 case GEN6_FILE_IMM: *multi_regs = true; return ""; 979 default: *multi_regs = false; return "BAD"; 980 } 981 } 982 983 static const char * 984 disasm_inst_type(const struct disasm_inst *inst, 985 const struct disasm_operand *operand) 986 { 987 if (operand->file == GEN6_FILE_IMM) { 988 switch (operand->type) { 989 case GEN6_TYPE_UD: return "UD"; 990 case GEN6_TYPE_D: return "D"; 991 case GEN6_TYPE_UW: return "UW"; 992 case GEN6_TYPE_W: return "W"; 993 case GEN6_TYPE_UV_IMM: return "UV"; 994 case GEN6_TYPE_VF_IMM: return "VF"; 995 case GEN6_TYPE_V_IMM: return "V"; 996 case GEN6_TYPE_F: return "F"; 997 case GEN8_TYPE_DF_IMM: return "DF"; 998 case GEN8_TYPE_HF_IMM: return "HF"; 999 default: return "BAD"; 1000 } 1001 } else { 1002 switch (operand->type) { 1003 case GEN6_TYPE_UD: return "UD"; 1004 case GEN6_TYPE_D: return "D"; 1005 case GEN6_TYPE_UW: return "UW"; 1006 case GEN6_TYPE_W: return "W"; 1007 case GEN6_TYPE_UB: return "UB"; 1008 case GEN6_TYPE_B: return "B"; 1009 case GEN7_TYPE_DF: return "DF"; 1010 case GEN6_TYPE_F: return "F"; 1011 case GEN8_TYPE_UQ: return "UQ"; 1012 case GEN8_TYPE_Q: return "Q"; 1013 case GEN8_TYPE_HF: return "HF"; 1014 default: return "BAD"; 1015 } 1016 } 1017 } 1018 1019 static const char * 1020 disasm_inst_vert_stride(const struct disasm_inst *inst, unsigned vert_stride) 1021 { 1022 switch (vert_stride) { 1023 case GEN6_VERTSTRIDE_0: return "0"; 1024 case GEN6_VERTSTRIDE_1: return "1"; 1025 case GEN6_VERTSTRIDE_2: return "2"; 1026 case GEN6_VERTSTRIDE_4: return "4"; 1027 case GEN6_VERTSTRIDE_8: return "8"; 1028 case GEN6_VERTSTRIDE_16: return "16"; 1029 case GEN6_VERTSTRIDE_32: return "32"; 1030 case GEN6_VERTSTRIDE_VXH: return "VxH"; 1031 default: return "BAD"; 1032 } 1033 } 1034 1035 static const char * 1036 disasm_inst_width(const struct disasm_inst *inst, unsigned width) 1037 { 1038 switch (width) { 1039 case GEN6_WIDTH_1: return "1"; 1040 case GEN6_WIDTH_2: return "2"; 1041 case GEN6_WIDTH_4: return "4"; 1042 case GEN6_WIDTH_8: return "8"; 1043 case GEN6_WIDTH_16: return "16"; 1044 default: return "BAD"; 1045 } 1046 } 1047 1048 static const char * 1049 disasm_inst_horz_stride(const struct disasm_inst *inst, unsigned horz_stride) 1050 { 1051 switch (horz_stride) { 1052 case GEN6_HORZSTRIDE_0: return "0"; 1053 case GEN6_HORZSTRIDE_1: return "1"; 1054 case GEN6_HORZSTRIDE_2: return "2"; 1055 case GEN6_HORZSTRIDE_4: return "4"; 1056 default: return "BAD"; 1057 } 1058 } 1059 1060 static const char * 1061 disasm_inst_writemask(const struct disasm_inst *inst, unsigned writemask) 1062 { 1063 switch (writemask) { 1064 case 0x0: return "."; 1065 case 0x1: return ".x"; 1066 case 0x2: return ".y"; 1067 case 0x3: return ".xy"; 1068 case 0x4: return ".z"; 1069 case 0x5: return ".xz"; 1070 case 0x6: return ".yz"; 1071 case 0x7: return ".xyz"; 1072 case 0x8: return ".w"; 1073 case 0x9: return ".xw"; 1074 case 0xa: return ".yw"; 1075 case 0xb: return ".xyw"; 1076 case 0xc: return ".zw"; 1077 case 0xd: return ".xzw"; 1078 case 0xe: return ".yzw"; 1079 case 0xf: return ""; 1080 default: return ".BAD"; 1081 } 1082 } 1083 1084 static const char * 1085 disasm_inst_negate(const struct disasm_inst *inst, bool negate) 1086 { 1087 if (ilo_dev_gen(inst->dev) >= ILO_GEN(8)) { 1088 switch (inst->opcode) { 1089 case GEN6_OPCODE_AND: 1090 case GEN6_OPCODE_NOT: 1091 case GEN6_OPCODE_OR: 1092 case GEN6_OPCODE_XOR: 1093 return (negate) ? "~" : ""; 1094 break; 1095 default: 1096 break; 1097 } 1098 } 1099 1100 return (negate) ? "-" : ""; 1101 } 1102 1103 static const char * 1104 disasm_inst_absolute(const struct disasm_inst *inst, bool absolute) 1105 { 1106 return (absolute) ? "(abs)" : ""; 1107 } 1108 1109 static const char * 1110 disasm_inst_mdesc_sampler_op(const struct disasm_inst *inst, int op) 1111 { 1112 switch (op) { 1113 case GEN6_MSG_SAMPLER_SAMPLE: return "sample"; 1114 case GEN6_MSG_SAMPLER_SAMPLE_B: return "sample_b"; 1115 case GEN6_MSG_SAMPLER_SAMPLE_L: return "sample_l"; 1116 case GEN6_MSG_SAMPLER_SAMPLE_C: return "sample_c"; 1117 case GEN6_MSG_SAMPLER_SAMPLE_D: return "sample_d"; 1118 case GEN6_MSG_SAMPLER_SAMPLE_B_C: return "sample_b_c"; 1119 case GEN6_MSG_SAMPLER_SAMPLE_L_C: return "sample_l_c"; 1120 case GEN6_MSG_SAMPLER_LD: return "ld"; 1121 case GEN6_MSG_SAMPLER_GATHER4: return "gather4"; 1122 case GEN6_MSG_SAMPLER_LOD: return "lod"; 1123 case GEN6_MSG_SAMPLER_RESINFO: return "resinfo"; 1124 case GEN6_MSG_SAMPLER_SAMPLEINFO: return "sampleinfo"; 1125 case GEN7_MSG_SAMPLER_GATHER4_C: return "gather4_c"; 1126 case GEN7_MSG_SAMPLER_GATHER4_PO: return "gather4_po"; 1127 case GEN7_MSG_SAMPLER_GATHER4_PO_C: return "gather4_po_c"; 1128 case GEN7_MSG_SAMPLER_SAMPLE_D_C: return "sample_d_c"; 1129 case GEN7_MSG_SAMPLER_SAMPLE_LZ: return "sample_lz"; 1130 case GEN7_MSG_SAMPLER_SAMPLE_C_LC: return "sample_c_lc"; 1131 case GEN7_MSG_SAMPLER_LD_LZ: return "ld_lz"; 1132 case GEN7_MSG_SAMPLER_LD_MCS: return "ld_mcs"; 1133 case GEN7_MSG_SAMPLER_LD2DMS: return "ld2dms"; 1134 case GEN7_MSG_SAMPLER_LD2DSS: return "ld2dss"; 1135 default: return "BAD"; 1136 } 1137 } 1138 1139 static const char * 1140 disasm_inst_mdesc_sampler_simd(const struct disasm_inst *inst, int simd) 1141 { 1142 switch (simd) { 1143 case GEN6_MSG_SAMPLER_SIMD4X2: return "SIMD4x2"; 1144 case GEN6_MSG_SAMPLER_SIMD8: return "SIMD8"; 1145 case GEN6_MSG_SAMPLER_SIMD16: return "SIMD16"; 1146 case GEN6_MSG_SAMPLER_SIMD32_64: return "SIMD32"; 1147 default: return "BAD"; 1148 } 1149 } 1150 1151 static const char * 1152 disasm_inst_mdesc_urb_op(const struct disasm_inst *inst, int op) 1153 { 1154 if (ilo_dev_gen(inst->dev) >= ILO_GEN(7)) { 1155 switch (op) { 1156 case GEN7_MSG_URB_WRITE_HWORD: return "write HWord"; 1157 case GEN7_MSG_URB_WRITE_OWORD: return "write OWord"; 1158 case GEN7_MSG_URB_READ_HWORD: return "read HWord"; 1159 case GEN7_MSG_URB_READ_OWORD: return "read OWord"; 1160 case GEN7_MSG_URB_ATOMIC_MOV: return "atomic mov"; 1161 case GEN7_MSG_URB_ATOMIC_INC: return "atomic inc"; 1162 default: return "BAD"; 1163 } 1164 } else { 1165 switch (op) { 1166 case GEN6_MSG_URB_WRITE: return "urb_write"; 1167 case GEN6_MSG_URB_FF_SYNC: return "ff_sync"; 1168 default: return "BAD"; 1169 } 1170 } 1171 } 1172 1173 static const char * 1174 disasm_inst_mdesc_dp_op_gen6(const struct disasm_inst *inst, 1175 int sfid, int op) 1176 { 1177 ILO_DEV_ASSERT(inst->dev, 6, 6); 1178 1179 switch (op) { 1180 case GEN6_MSG_DP_OWORD_BLOCK_READ: return "OWORD block read"; 1181 case GEN6_MSG_DP_RT_UNORM_READ: return "RT UNORM read"; 1182 case GEN6_MSG_DP_OWORD_DUAL_BLOCK_READ: return "OWORD dual block read"; 1183 case GEN6_MSG_DP_MEDIA_BLOCK_READ: return "media block read"; 1184 case GEN6_MSG_DP_UNALIGNED_OWORD_BLOCK_READ: return "unaligned OWORD block read"; 1185 case GEN6_MSG_DP_DWORD_SCATTERED_READ: return "DWORD scattered read"; 1186 case GEN6_MSG_DP_DWORD_ATOMIC_WRITE: return "DWORD atomic write"; 1187 case GEN6_MSG_DP_OWORD_BLOCK_WRITE: return "OWORD block write"; 1188 case GEN6_MSG_DP_OWORD_DUAL_BLOCK_WRITE: return "OWORD dual block_write"; 1189 case GEN6_MSG_DP_MEDIA_BLOCK_WRITE: return "media block write"; 1190 case GEN6_MSG_DP_DWORD_SCATTERED_WRITE: return "DWORD scattered write"; 1191 case GEN6_MSG_DP_RT_WRITE: return "RT write"; 1192 case GEN6_MSG_DP_SVB_WRITE: return "SVB write"; 1193 case GEN6_MSG_DP_RT_UNORM_WRITE: return "RT UNORM write"; 1194 default: return "BAD"; 1195 } 1196 } 1197 1198 static const char * 1199 disasm_inst_mdesc_dp_op_gen7(const struct disasm_inst *inst, 1200 int sfid, int op) 1201 { 1202 ILO_DEV_ASSERT(inst->dev, 7, 7); 1203 1204 switch (sfid) { 1205 case GEN6_SFID_DP_SAMPLER: 1206 switch (op) { 1207 case GEN7_MSG_DP_SAMPLER_UNALIGNED_OWORD_BLOCK_READ: return "OWORD block read"; 1208 case GEN7_MSG_DP_SAMPLER_MEDIA_BLOCK_READ: return "media block read"; 1209 default: return "BAD"; 1210 } 1211 case GEN6_SFID_DP_RC: 1212 switch (op) { 1213 case GEN7_MSG_DP_RC_MEDIA_BLOCK_READ: return "media block read"; 1214 case GEN7_MSG_DP_RC_TYPED_SURFACE_READ: return "typed surface read"; 1215 case GEN7_MSG_DP_RC_TYPED_ATOMIC_OP: return "typed atomic op"; 1216 case GEN7_MSG_DP_RC_MEMORY_FENCE: return "memory fence"; 1217 case GEN7_MSG_DP_RC_MEDIA_BLOCK_WRITE: return "media block write"; 1218 case GEN7_MSG_DP_RC_RT_WRITE: return "RT write"; 1219 case GEN7_MSG_DP_RC_TYPED_SURFACE_WRITE: return "typed surface write"; 1220 default: return "BAD"; 1221 } 1222 case GEN6_SFID_DP_CC: 1223 switch (op) { 1224 case GEN7_MSG_DP_CC_OWORD_BLOCK_READ: return "OWROD block read"; 1225 case GEN7_MSG_DP_CC_UNALIGNED_OWORD_BLOCK_READ: return "unaligned OWORD block read"; 1226 case GEN7_MSG_DP_CC_OWORD_DUAL_BLOCK_READ: return "OWORD dual block read"; 1227 case GEN7_MSG_DP_CC_DWORD_SCATTERED_READ: return "DWORD scattered read"; 1228 default: return "BAD"; 1229 } 1230 case GEN7_SFID_DP_DC0: 1231 switch (op) { 1232 case GEN7_MSG_DP_DC0_OWORD_BLOCK_READ: return "OWORD block read"; 1233 case GEN7_MSG_DP_DC0_UNALIGNED_OWORD_BLOCK_READ: return "unaligned OWORD block read"; 1234 case GEN7_MSG_DP_DC0_OWORD_DUAL_BLOCK_READ: return "OWORD dual block read"; 1235 case GEN7_MSG_DP_DC0_DWORD_SCATTERED_READ: return "DWORD scattered read"; 1236 case GEN7_MSG_DP_DC0_BYTE_SCATTERED_READ: return "BYTE scattered read"; 1237 case GEN7_MSG_DP_DC0_UNTYPED_SURFACE_READ: return "untyped surface read"; 1238 case GEN7_MSG_DP_DC0_UNTYPED_ATOMIC_OP: return "untyped atomic op"; 1239 case GEN7_MSG_DP_DC0_MEMORY_FENCE: return "memory fence"; 1240 case GEN7_MSG_DP_DC0_OWORD_BLOCK_WRITE: return "OWORD block write"; 1241 case GEN7_MSG_DP_DC0_OWORD_DUAL_BLOCK_WRITE: return "OWORD dual block write"; 1242 case GEN7_MSG_DP_DC0_DWORD_SCATTERED_WRITE: return "OWORD scattered write"; 1243 case GEN7_MSG_DP_DC0_BYTE_SCATTERED_WRITE: return "BYTE scattered write"; 1244 case GEN7_MSG_DP_DC0_UNTYPED_SURFACE_WRITE: return "untyped surface write"; 1245 default: return "BAD"; 1246 } 1247 default: return "BAD"; 1248 } 1249 } 1250 1251 static const char * 1252 disasm_inst_mdesc_dp_op_gen75(const struct disasm_inst *inst, 1253 int sfid, int op) 1254 { 1255 ILO_DEV_ASSERT(inst->dev, 7.5, 8); 1256 1257 switch (sfid) { 1258 case GEN6_SFID_DP_SAMPLER: 1259 switch (op) { 1260 case GEN75_MSG_DP_SAMPLER_READ_SURFACE_INFO: return "read surface info"; 1261 case GEN75_MSG_DP_SAMPLER_UNALIGNED_OWORD_BLOCK_READ: return "unaligned OWORD block read"; 1262 case GEN75_MSG_DP_SAMPLER_MEDIA_BLOCK_READ: return "media block read"; 1263 default: return "BAD"; 1264 } 1265 1266 case GEN6_SFID_DP_RC: 1267 switch (op) { 1268 case GEN75_MSG_DP_RC_MEDIA_BLOCK_READ: return "media block read"; 1269 case GEN75_MSG_DP_RC_MEMORY_FENCE: return "memory fence"; 1270 case GEN75_MSG_DP_RC_MEDIA_BLOCK_WRITE: return "media block write"; 1271 case GEN75_MSG_DP_RC_RT_WRITE: return "RT write"; 1272 default: return "BAD"; 1273 } 1274 case GEN6_SFID_DP_CC: 1275 switch (op) { 1276 case GEN75_MSG_DP_CC_OWORD_BLOCK_READ: return "OWROD block read"; 1277 case GEN75_MSG_DP_CC_UNALIGNED_OWORD_BLOCK_READ: return "unaligned OWORD block read"; 1278 case GEN75_MSG_DP_CC_OWORD_DUAL_BLOCK_READ: return "OWORD dual block read"; 1279 case GEN75_MSG_DP_CC_DWORD_SCATTERED_READ: return "DWORD scattered read"; 1280 default: return "BAD"; 1281 } 1282 case GEN7_SFID_DP_DC0: 1283 switch (op) { 1284 case GEN75_MSG_DP_DC0_OWORD_BLOCK_READ: return "OWORD block read"; 1285 case GEN75_MSG_DP_DC0_UNALIGNED_OWORD_BLOCK_READ: return "unaligned OWORD block read"; 1286 case GEN75_MSG_DP_DC0_OWORD_DUAL_BLOCK_READ: return "OWORD dual block read"; 1287 case GEN75_MSG_DP_DC0_DWORD_SCATTERED_READ: return "DWORD scattered read"; 1288 case GEN75_MSG_DP_DC0_BYTE_SCATTERED_READ: return "BYTE scattered read"; 1289 case GEN75_MSG_DP_DC0_MEMORY_FENCE: return "memory fence"; 1290 case GEN75_MSG_DP_DC0_OWORD_BLOCK_WRITE: return "OWORD block write"; 1291 case GEN75_MSG_DP_DC0_OWORD_DUAL_BLOCK_WRITE: return "OWORD dual block write"; 1292 case GEN75_MSG_DP_DC0_DWORD_SCATTERED_WRITE: return "OWORD scattered write"; 1293 case GEN75_MSG_DP_DC0_BYTE_SCATTERED_WRITE: return "BYTE scattered write"; 1294 default: return "BAD"; 1295 } 1296 case GEN75_SFID_DP_DC1: 1297 switch (op) { 1298 case GEN75_MSG_DP_DC1_UNTYPED_SURFACE_READ: return "untyped surface read"; 1299 case GEN75_MSG_DP_DC1_UNTYPED_ATOMIC_OP: return "DC untyped atomic op"; 1300 case GEN75_MSG_DP_DC1_UNTYPED_ATOMIC_OP_SIMD4X2: return "DC untyped 4x2 atomic op"; 1301 case GEN75_MSG_DP_DC1_MEDIA_BLOCK_READ: return "DC media block read"; 1302 case GEN75_MSG_DP_DC1_TYPED_SURFACE_READ: return "DC typed surface read"; 1303 case GEN75_MSG_DP_DC1_TYPED_ATOMIC_OP: return "DC typed atomic"; 1304 case GEN75_MSG_DP_DC1_TYPED_ATOMIC_OP_SIMD4X2: return "DC typed 4x2 atomic op"; 1305 case GEN75_MSG_DP_DC1_UNTYPED_SURFACE_WRITE: return "DC untyped surface write"; 1306 case GEN75_MSG_DP_DC1_MEDIA_BLOCK_WRITE: return "DC media block write"; 1307 case GEN75_MSG_DP_DC1_ATOMIC_COUNTER_OP: return "DC atomic counter op"; 1308 case GEN75_MSG_DP_DC1_ATOMIC_COUNTER_OP_SIMD4X2: return "DC 4x2 atomic counter op"; 1309 case GEN75_MSG_DP_DC1_TYPED_SURFACE_WRITE: return "DC typed surface write"; 1310 default: return "BAD"; 1311 } 1312 default: return "BAD"; 1313 } 1314 } 1315 1316 static const char * 1317 disasm_inst_mdesc_dp_op(const struct disasm_inst *inst, int sfid, int op) 1318 { 1319 switch (ilo_dev_gen(inst->dev)) { 1320 case ILO_GEN(8): 1321 case ILO_GEN(7.5): return disasm_inst_mdesc_dp_op_gen75(inst, sfid, op); 1322 case ILO_GEN(7): return disasm_inst_mdesc_dp_op_gen7(inst, sfid, op); 1323 case ILO_GEN(6): return disasm_inst_mdesc_dp_op_gen6(inst, sfid, op); 1324 default: return "BAD"; 1325 } 1326 } 1327 1328 static const char * 1329 disasm_inst_mdesc_dp_untyped_surface_simd_mode(const struct disasm_inst *inst, 1330 uint32_t mdesc) 1331 { 1332 switch (mdesc & GEN7_MSG_DP_UNTYPED_MODE__MASK) { 1333 case GEN7_MSG_DP_UNTYPED_MODE_SIMD4X2: return "SIMD4x2"; 1334 case GEN7_MSG_DP_UNTYPED_MODE_SIMD16: return "SIMD16"; 1335 case GEN7_MSG_DP_UNTYPED_MODE_SIMD8: return "SIMD8"; 1336 default: return "BAD"; 1337 } 1338 } 1339 1340 static const char * 1341 disasm_inst_mdesc_dp_rt_write_simd_mode(const struct disasm_inst *inst, 1342 uint32_t mdesc) 1343 { 1344 switch (mdesc & GEN6_MSG_DP_RT_MODE__MASK) { 1345 case GEN6_MSG_DP_RT_MODE_SIMD16: return "SIMD16"; 1346 case GEN6_MSG_DP_RT_MODE_SIMD16_REPDATA: return "SIMD16/RepData"; 1347 case GEN6_MSG_DP_RT_MODE_SIMD8_DUALSRC_LO: return "SIMD8/DualSrcLow"; 1348 case GEN6_MSG_DP_RT_MODE_SIMD8_DUALSRC_HI: return "SIMD8/DualSrcHigh"; 1349 case GEN6_MSG_DP_RT_MODE_SIMD8_LO: return "SIMD8"; 1350 case GEN6_MSG_DP_RT_MODE_SIMD8_IMAGE_WR: return "SIMD8/ImageWrite"; 1351 default: return "BAD"; 1352 } 1353 } 1354 1355 static bool 1356 disasm_inst_is_null(const struct disasm_inst *inst, 1357 const struct disasm_operand *operand) 1358 { 1359 return (operand->file == GEN6_FILE_ARF && operand->reg == GEN6_ARF_NULL); 1360 } 1361 1362 static int 1363 disasm_inst_type_size(const struct disasm_inst *inst, 1364 const struct disasm_operand *operand) 1365 { 1366 assert(operand->file != GEN6_FILE_IMM); 1367 1368 switch (operand->type) { 1369 case GEN6_TYPE_UD: return 4; 1370 case GEN6_TYPE_D: return 4; 1371 case GEN6_TYPE_UW: return 2; 1372 case GEN6_TYPE_W: return 2; 1373 case GEN6_TYPE_UB: return 1; 1374 case GEN6_TYPE_B: return 1; 1375 case GEN7_TYPE_DF: return 8; 1376 case GEN6_TYPE_F: return 4; 1377 default: return 1; 1378 } 1379 } 1380 1381 static void 1382 disasm_printer_reset(struct disasm_printer *printer) 1383 { 1384 printer->buf[0] = '\0'; 1385 printer->len = 0; 1386 } 1387 1388 static const char * 1389 disasm_printer_get_string(struct disasm_printer *printer) 1390 { 1391 return printer->buf; 1392 } 1393 1394 static void _util_printf_format(2, 3) 1395 disasm_printer_add(struct disasm_printer *printer, const char *format, ...) 1396 { 1397 const size_t avail = sizeof(printer->buf) - printer->len; 1398 va_list ap; 1399 int written; 1400 1401 va_start(ap, format); 1402 written = vsnprintf(printer->buf + printer->len, avail, format, ap); 1403 va_end(ap); 1404 1405 /* truncated */ 1406 if (written < 0 || written >= avail) { 1407 memcpy(printer->buf + sizeof(printer->buf) - 4, "...", 4); 1408 printer->len = sizeof(printer->buf) - 1; 1409 } else { 1410 printer->len += written; 1411 } 1412 } 1413 1414 /** 1415 * Pad to the specified column. 1416 */ 1417 static void 1418 disasm_printer_column(struct disasm_printer *printer, int col) 1419 { 1420 int len = DISASM_PRINTER_COLUMN_WIDTH * col; 1421 1422 if (len <= printer->len) { 1423 if (!printer->len) 1424 return; 1425 1426 /* at least one space */ 1427 len = printer->len + 1; 1428 } 1429 1430 if (len >= sizeof(printer->buf)) { 1431 len = sizeof(printer->buf) - 1; 1432 1433 if (len <= printer->len) 1434 return; 1435 } 1436 1437 memset(printer->buf + printer->len, ' ', len - printer->len); 1438 printer->len = len; 1439 printer->buf[printer->len] = '\0'; 1440 } 1441 1442 static void 1443 disasm_printer_add_op(struct disasm_printer *printer, 1444 const struct disasm_inst *inst) 1445 { 1446 if (inst->pred_ctrl != GEN6_PREDCTRL_NONE) { 1447 disasm_printer_add(printer, "(%c%s%s) ", 1448 disasm_inst_pred_inv(inst), 1449 disasm_inst_flag_reg(inst), 1450 disasm_inst_pred_ctrl(inst)); 1451 } 1452 1453 disasm_printer_add(printer, "%s%s%s%s", 1454 disasm_inst_opcode(inst), 1455 disasm_inst_saturate(inst), 1456 disasm_inst_debug_ctrl(inst), 1457 disasm_inst_cond_modifier(inst)); 1458 1459 if (inst->cond_modifier != GEN6_COND_NONE) { 1460 switch (inst->opcode) { 1461 case GEN6_OPCODE_SEL: 1462 case GEN6_OPCODE_IF: 1463 case GEN6_OPCODE_WHILE: 1464 /* these do not update flag registers */ 1465 break; 1466 default: 1467 disasm_printer_add(printer, ".%s", disasm_inst_flag_reg(inst)); 1468 break; 1469 } 1470 } 1471 1472 if (inst->opcode == GEN6_OPCODE_MATH) 1473 disasm_printer_add(printer, " %s", disasm_inst_fc(inst)); 1474 if (inst->opcode != GEN6_OPCODE_NOP) 1475 disasm_printer_add(printer, "(%s)", disasm_inst_exec_size(inst)); 1476 } 1477 1478 static void 1479 disasm_printer_add_operand(struct disasm_printer *printer, 1480 const struct disasm_inst *inst, 1481 const struct disasm_operand *operand) 1482 { 1483 const char *name; 1484 bool multi_regs; 1485 1486 name = disasm_inst_file(inst, operand, &multi_regs); 1487 if (!multi_regs) { 1488 disasm_printer_add(printer, "%s", name); 1489 return; 1490 } 1491 1492 if (operand->file == GEN6_FILE_IMM) { 1493 switch (operand->type) { 1494 case GEN6_TYPE_UD: 1495 disasm_printer_add(printer, "0x%08xUD", inst->u.ud); 1496 break; 1497 case GEN6_TYPE_D: 1498 disasm_printer_add(printer, "%dD", inst->u.d); 1499 break; 1500 case GEN6_TYPE_UW: 1501 disasm_printer_add(printer, "0x%04xUW", inst->u.uw); 1502 break; 1503 case GEN6_TYPE_W: 1504 disasm_printer_add(printer, "%dW", inst->u.w); 1505 break; 1506 case GEN6_TYPE_UV_IMM: 1507 disasm_printer_add(printer, "0x%08xUV", inst->u.ud); 1508 break; 1509 case GEN6_TYPE_VF_IMM: 1510 disasm_printer_add(printer, "Vector Float"); 1511 break; 1512 case GEN6_TYPE_V_IMM: 1513 disasm_printer_add(printer, "0x%08xV", inst->u.ud); 1514 break; 1515 case GEN6_TYPE_F: 1516 disasm_printer_add(printer, "%-gF", uif(inst->u.f)); 1517 break; 1518 default: 1519 disasm_printer_add(printer, "BAD"); 1520 break; 1521 } 1522 1523 return; 1524 } 1525 1526 if (operand->addr_mode == GEN6_ADDRMODE_DIRECT) { 1527 unsigned reg, subreg; 1528 1529 reg = operand->reg; 1530 if (operand->file == GEN6_FILE_ARF) 1531 reg &= 0xf; 1532 1533 subreg = operand->subreg / disasm_inst_type_size(inst, operand); 1534 1535 if (subreg) 1536 disasm_printer_add(printer, "%s%d.%d", name, reg, subreg); 1537 else 1538 disasm_printer_add(printer, "%s%d", name, reg); 1539 } else { 1540 disasm_printer_add(printer, "%s[a0.%d %d]", 1541 name, operand->addr_subreg, operand->addr_imm); 1542 } 1543 } 1544 1545 static void 1546 disasm_printer_add_dst(struct disasm_printer *printer, 1547 const struct disasm_inst *inst, 1548 const struct disasm_dst_operand *dst) 1549 { 1550 disasm_printer_add_operand(printer, inst, &dst->base); 1551 1552 /* dst is an immediate when in EU_INSTRUCTION_BRANCH_CONDITIONAL form */ 1553 if (disasm_inst_is_null(inst, &dst->base) || 1554 dst->base.file == GEN6_FILE_IMM) 1555 return; 1556 1557 disasm_printer_add(printer, "<%s>%s%s", 1558 disasm_inst_horz_stride(inst, dst->horz_stride), 1559 disasm_inst_writemask(inst, dst->writemask), 1560 disasm_inst_type(inst, &dst->base)); 1561 } 1562 1563 static void 1564 disasm_printer_add_src(struct disasm_printer *printer, 1565 const struct disasm_inst *inst, 1566 const struct disasm_src_operand *src) 1567 { 1568 static const char swizzle_chars[4] = { 'x', 'y', 'z', 'w' }; 1569 char swizzle[5]; 1570 1571 disasm_printer_add(printer, "%s%s", 1572 disasm_inst_negate(inst, src->negate), 1573 disasm_inst_absolute(inst, src->absolute)); 1574 1575 disasm_printer_add_operand(printer, inst, &src->base); 1576 1577 if (disasm_inst_is_null(inst, &src->base) || 1578 src->base.file == GEN6_FILE_IMM) 1579 return; 1580 1581 if (src->swizzle_x == 0 && src->swizzle_y == 1 && 1582 src->swizzle_z == 2 && src->swizzle_w == 3) { 1583 swizzle[0] = '\0'; 1584 } else if (src->swizzle_x == src->swizzle_y && 1585 src->swizzle_x == src->swizzle_z && 1586 src->swizzle_x == src->swizzle_w) { 1587 swizzle[0] = swizzle_chars[src->swizzle_x]; 1588 swizzle[1] = '\0'; 1589 } else { 1590 swizzle[0] = swizzle_chars[src->swizzle_x]; 1591 swizzle[1] = swizzle_chars[src->swizzle_y]; 1592 swizzle[2] = swizzle_chars[src->swizzle_z]; 1593 swizzle[3] = swizzle_chars[src->swizzle_w]; 1594 swizzle[4] = '\0'; 1595 } 1596 1597 disasm_printer_add(printer, "<%s,%s,%s>%s%s", 1598 disasm_inst_vert_stride(inst, src->vert_stride), 1599 disasm_inst_width(inst, src->width), 1600 disasm_inst_horz_stride(inst, src->horz_stride), 1601 swizzle, 1602 disasm_inst_type(inst, &src->base)); 1603 } 1604 1605 static void 1606 disasm_printer_add_ctrl(struct disasm_printer *printer, 1607 const struct disasm_inst *inst) 1608 { 1609 if (inst->opcode == GEN6_OPCODE_NOP) { 1610 disasm_printer_add(printer, ";"); 1611 return; 1612 } 1613 1614 disasm_printer_add(printer, "{%s%s%s%s%s%s%s%s };", 1615 disasm_inst_access_mode(inst), 1616 disasm_inst_mask_ctrl(inst), 1617 disasm_inst_dep_ctrl(inst), 1618 disasm_inst_qtr_ctrl(inst), 1619 disasm_inst_cmpt_ctrl(inst), 1620 disasm_inst_thread_ctrl(inst), 1621 disasm_inst_acc_wr_ctrl(inst), 1622 disasm_inst_eot(inst)); 1623 } 1624 1625 static void 1626 disasm_printer_add_mdesc_sampler(struct disasm_printer *printer, 1627 const struct disasm_inst *inst, 1628 uint32_t mdesc) 1629 { 1630 int op, simd; 1631 1632 if (ilo_dev_gen(inst->dev) >= ILO_GEN(7)) { 1633 op = GEN_EXTRACT(mdesc, GEN7_MSG_SAMPLER_OP); 1634 simd = GEN_EXTRACT(mdesc, GEN7_MSG_SAMPLER_SIMD); 1635 } else { 1636 op = GEN_EXTRACT(mdesc, GEN6_MSG_SAMPLER_OP); 1637 simd = GEN_EXTRACT(mdesc, GEN6_MSG_SAMPLER_SIMD); 1638 } 1639 1640 disasm_printer_add(printer, 1641 "%s %s samp %d surf %d", 1642 disasm_inst_mdesc_sampler_op(inst, op), 1643 disasm_inst_mdesc_sampler_simd(inst, simd), 1644 GEN_EXTRACT(mdesc, GEN6_MSG_SAMPLER_INDEX), 1645 GEN_EXTRACT(mdesc, GEN6_MSG_SAMPLER_SURFACE)); 1646 } 1647 1648 static void 1649 disasm_printer_add_mdesc_urb(struct disasm_printer *printer, 1650 const struct disasm_inst *inst, 1651 uint32_t mdesc) 1652 { 1653 int op, offset; 1654 bool interleaved, complete, allocate, used; 1655 1656 if (ilo_dev_gen(inst->dev) >= ILO_GEN(7)) { 1657 op = GEN_EXTRACT(mdesc, GEN7_MSG_URB_OP); 1658 offset = GEN_EXTRACT(mdesc, GEN7_MSG_URB_GLOBAL_OFFSET); 1659 interleaved = mdesc & GEN7_MSG_URB_INTERLEAVED; 1660 1661 complete = (ilo_dev_gen(inst->dev) >= ILO_GEN(8)) ? 1662 false : (mdesc & GEN7_MSG_URB_COMPLETE); 1663 1664 allocate = false; 1665 used = false; 1666 } else { 1667 op = GEN_EXTRACT(mdesc, GEN6_MSG_URB_OP); 1668 offset = GEN_EXTRACT(mdesc, GEN6_MSG_URB_OFFSET); 1669 interleaved = mdesc & GEN6_MSG_URB_INTERLEAVED; 1670 complete = mdesc & GEN6_MSG_URB_COMPLETE; 1671 1672 allocate = mdesc & GEN6_MSG_URB_ALLOCATE; 1673 used = mdesc & GEN6_MSG_URB_USED; 1674 } 1675 1676 disasm_printer_add(printer, "%s offset %d%s%s%s%s", 1677 disasm_inst_mdesc_urb_op(inst, op), 1678 offset, 1679 (interleaved) ? " interleave" : "", 1680 (allocate) ? " allocate" : "", 1681 (used) ? " used" : "", 1682 (complete) ? " complete" : ""); 1683 } 1684 1685 static void 1686 disasm_printer_add_mdesc_spawner(struct disasm_printer *printer, 1687 const struct disasm_inst *inst, 1688 uint32_t mdesc) 1689 { 1690 const char *requester, *op; 1691 1692 switch (mdesc & GEN6_MSG_TS_REQUESTER_TYPE__MASK) { 1693 case GEN6_MSG_TS_REQUESTER_TYPE_ROOT: requester = "root"; break; 1694 case GEN6_MSG_TS_REQUESTER_TYPE_CHILD: requester = "child"; break; 1695 default: requester = "BAD"; break; 1696 } 1697 1698 switch (mdesc & GEN6_MSG_TS_OPCODE__MASK) { 1699 case GEN6_MSG_TS_OPCODE_DEREF: 1700 op = (mdesc & GEN6_MSG_TS_RESOURCE_SELECT_NO_DEREF) ? 1701 "no deref" : "deref"; 1702 break; 1703 case GEN6_MSG_TS_OPCODE_SPAWN: 1704 op = (mdesc & GEN6_MSG_TS_RESOURCE_SELECT_ROOT) ? 1705 "spawn root" : "spawn child"; 1706 break; 1707 default: 1708 op = "BAD"; 1709 break; 1710 } 1711 1712 disasm_printer_add(printer, "%s thread %s", requester, op); 1713 } 1714 1715 static void 1716 disasm_printer_add_mdesc_dp_sampler(struct disasm_printer *printer, 1717 const struct disasm_inst *inst, 1718 uint32_t mdesc) 1719 { 1720 const int op = (ilo_dev_gen(inst->dev) >= ILO_GEN(7)) ? 1721 GEN_EXTRACT(mdesc, GEN7_MSG_DP_OP) : GEN_EXTRACT(mdesc, GEN6_MSG_DP_OP); 1722 const bool write_commit = (ilo_dev_gen(inst->dev) == ILO_GEN(6)) ? 1723 (mdesc & GEN6_MSG_DP_SEND_WRITE_COMMIT) : 0; 1724 1725 disasm_printer_add(printer, "%s block size %d commit %d surf %d", 1726 disasm_inst_mdesc_dp_op(inst, GEN6_SFID_DP_SAMPLER, op), 1727 GEN_EXTRACT(mdesc, GEN6_MSG_DP_OWORD_BLOCK_SIZE), 1728 write_commit, 1729 GEN_EXTRACT(mdesc, GEN6_MSG_DP_SURFACE)); 1730 } 1731 1732 static void 1733 disasm_printer_add_mdesc_dp_dc0(struct disasm_printer *printer, 1734 const struct disasm_inst *inst, 1735 uint32_t mdesc) 1736 { 1737 const int op = GEN_EXTRACT(mdesc, GEN7_MSG_DP_OP); 1738 1739 ILO_DEV_ASSERT(inst->dev, 7, 7.5); 1740 1741 if (ilo_dev_gen(inst->dev) >= ILO_GEN(7.5)) { 1742 disasm_printer_add(printer, "%s ctrl 0x%x surf %d", 1743 disasm_inst_mdesc_dp_op(inst, GEN7_SFID_DP_DC0, op), 1744 GEN_EXTRACT(mdesc, GEN6_MSG_DP_CTRL), 1745 GEN_EXTRACT(mdesc, GEN6_MSG_DP_SURFACE)); 1746 } else { 1747 switch (op) { 1748 case GEN7_MSG_DP_DC0_UNTYPED_SURFACE_READ: 1749 case GEN7_MSG_DP_DC0_UNTYPED_SURFACE_WRITE: 1750 disasm_printer_add(printer, "%s %s mask 0x%x surf %d", 1751 disasm_inst_mdesc_dp_op(inst, GEN7_SFID_DP_DC0, op), 1752 disasm_inst_mdesc_dp_untyped_surface_simd_mode(inst, mdesc), 1753 GEN_EXTRACT(mdesc, GEN7_MSG_DP_UNTYPED_MASK), 1754 GEN_EXTRACT(mdesc, GEN6_MSG_DP_SURFACE)); 1755 break; 1756 default: 1757 disasm_printer_add(printer, "%s ctrl 0x%x surf %d", 1758 disasm_inst_mdesc_dp_op(inst, GEN7_SFID_DP_DC0, op), 1759 GEN_EXTRACT(mdesc, GEN6_MSG_DP_CTRL), 1760 GEN_EXTRACT(mdesc, GEN6_MSG_DP_SURFACE)); 1761 break; 1762 } 1763 } 1764 } 1765 1766 static void 1767 disasm_printer_add_mdesc_dp_dc1(struct disasm_printer *printer, 1768 const struct disasm_inst *inst, 1769 uint32_t mdesc) 1770 { 1771 const int op = GEN_EXTRACT(mdesc, GEN7_MSG_DP_OP); 1772 1773 ILO_DEV_ASSERT(inst->dev, 7.5, 7.5); 1774 1775 switch (op) { 1776 case GEN75_MSG_DP_DC1_UNTYPED_SURFACE_READ: 1777 case GEN75_MSG_DP_DC1_UNTYPED_SURFACE_WRITE: 1778 disasm_printer_add(printer, "%s %s mask 0x%x surf %d", 1779 disasm_inst_mdesc_dp_op(inst, GEN75_SFID_DP_DC1, op), 1780 disasm_inst_mdesc_dp_untyped_surface_simd_mode(inst, mdesc), 1781 GEN_EXTRACT(mdesc, GEN7_MSG_DP_UNTYPED_MASK), 1782 GEN_EXTRACT(mdesc, GEN6_MSG_DP_SURFACE)); 1783 break; 1784 default: 1785 disasm_printer_add(printer, "%s ctrl 0x%x surf %d", 1786 disasm_inst_mdesc_dp_op(inst, GEN75_SFID_DP_DC1, op), 1787 GEN_EXTRACT(mdesc, GEN6_MSG_DP_CTRL), 1788 GEN_EXTRACT(mdesc, GEN6_MSG_DP_SURFACE)); 1789 break; 1790 } 1791 } 1792 1793 static void 1794 disasm_printer_add_mdesc_dp_rc(struct disasm_printer *printer, 1795 const struct disasm_inst *inst, 1796 uint32_t mdesc) 1797 { 1798 const int op = (ilo_dev_gen(inst->dev) >= ILO_GEN(7)) ? 1799 GEN_EXTRACT(mdesc, GEN7_MSG_DP_OP) : GEN_EXTRACT(mdesc, GEN6_MSG_DP_OP); 1800 bool is_rt_write; 1801 1802 if (ilo_dev_gen(inst->dev) >= ILO_GEN(7.5)) 1803 is_rt_write = (op == GEN75_MSG_DP_RC_RT_WRITE); 1804 else if (ilo_dev_gen(inst->dev) >= ILO_GEN(7)) 1805 is_rt_write = (op == GEN7_MSG_DP_RC_RT_WRITE); 1806 else 1807 is_rt_write = (op == GEN6_MSG_DP_RT_WRITE); 1808 1809 disasm_printer_add(printer, "%s", 1810 disasm_inst_mdesc_dp_op(inst, GEN6_SFID_DP_RC, op)); 1811 1812 if (is_rt_write) { 1813 disasm_printer_add(printer, " %s%s%s%s", 1814 disasm_inst_mdesc_dp_rt_write_simd_mode(inst, mdesc), 1815 (mdesc & GEN6_MSG_DP_RT_SLOTGRP_HI) ? " Hi" : "", 1816 (mdesc & GEN6_MSG_DP_RT_LAST) ? " LastRT" : "", 1817 (ilo_dev_gen(inst->dev) == ILO_GEN(6) && 1818 (mdesc & GEN6_MSG_DP_SEND_WRITE_COMMIT)) ? " WriteCommit" : ""); 1819 } 1820 1821 disasm_printer_add(printer, " surf %d", 1822 GEN_EXTRACT(mdesc, GEN6_MSG_DP_SURFACE)); 1823 } 1824 1825 static void 1826 disasm_printer_add_mdesc(struct disasm_printer *printer, 1827 const struct disasm_inst *inst) 1828 { 1829 const uint32_t mdesc = inst->u.ud; 1830 1831 assert(inst->opcode == GEN6_OPCODE_SEND || 1832 inst->opcode == GEN6_OPCODE_SENDC); 1833 assert(inst->src1.base.file == GEN6_FILE_IMM); 1834 1835 disasm_printer_add(printer, " %s (", disasm_inst_sfid(inst)); 1836 1837 switch (inst->sfid) { 1838 case GEN6_SFID_SAMPLER: 1839 disasm_printer_add_mdesc_sampler(printer, inst, mdesc); 1840 break; 1841 case GEN6_SFID_DP_SAMPLER: 1842 disasm_printer_add_mdesc_dp_sampler(printer, inst, mdesc); 1843 break; 1844 case GEN6_SFID_DP_RC: 1845 disasm_printer_add_mdesc_dp_rc(printer, inst, mdesc); 1846 break; 1847 case GEN6_SFID_URB: 1848 disasm_printer_add_mdesc_urb(printer, inst, mdesc); 1849 break; 1850 case GEN6_SFID_SPAWNER: 1851 disasm_printer_add_mdesc_spawner(printer, inst, mdesc); 1852 break; 1853 case GEN7_SFID_DP_DC0: 1854 disasm_printer_add_mdesc_dp_dc0(printer, inst, mdesc); 1855 break; 1856 case GEN75_SFID_DP_DC1: 1857 disasm_printer_add_mdesc_dp_dc1(printer, inst, mdesc); 1858 break; 1859 case GEN6_SFID_DP_CC: 1860 case GEN7_SFID_PI: 1861 default: 1862 break; 1863 } 1864 1865 disasm_printer_add(printer, ") mlen %d rlen %d", 1866 GEN_EXTRACT(mdesc, GEN6_MSG_MLEN), 1867 GEN_EXTRACT(mdesc, GEN6_MSG_RLEN)); 1868 } 1869 1870 static void 1871 disasm_printer_print_inst(struct disasm_printer *printer, 1872 const struct disasm_inst *inst) 1873 { 1874 int col = 0; 1875 1876 disasm_printer_reset(printer); 1877 1878 disasm_printer_column(printer, col++); 1879 disasm_printer_add_op(printer, inst); 1880 1881 if (inst->has_jip || inst->has_uip) { 1882 if (inst->has_jip) { 1883 const int32_t jip = (ilo_dev_gen(inst->dev) >= ILO_GEN(8)) ? 1884 inst->u.ip32.jip : inst->u.ip16.jip; 1885 1886 disasm_printer_column(printer, col++); 1887 disasm_printer_add(printer, "JIP: %d", jip); 1888 } 1889 1890 if (inst->has_uip) { 1891 const int32_t uip = (ilo_dev_gen(inst->dev) >= ILO_GEN(8)) ? 1892 inst->u.ip32.uip : inst->u.ip16.uip; 1893 1894 disasm_printer_column(printer, col++); 1895 disasm_printer_add(printer, "UIP: %d", uip); 1896 } 1897 } else { 1898 const int src_count = disasm_opcode_table[inst->opcode].src_count; 1899 1900 if (src_count) { 1901 const struct disasm_src_operand *src[3] = { 1902 &inst->src0, &inst->src1, &inst->u.src2 1903 }; 1904 int i; 1905 1906 disasm_printer_column(printer, col++); 1907 disasm_printer_add_dst(printer, inst, &inst->dst); 1908 1909 for (i = 0; i < src_count; i++) { 1910 disasm_printer_column(printer, col++); 1911 disasm_printer_add_src(printer, inst, src[i]); 1912 } 1913 } 1914 } 1915 1916 if (inst->opcode == GEN6_OPCODE_SEND || 1917 inst->opcode == GEN6_OPCODE_SENDC) { 1918 /* start a new line */ 1919 ilo_printf("%s\n", disasm_printer_get_string(printer)); 1920 disasm_printer_reset(printer); 1921 col = 0; 1922 1923 disasm_printer_column(printer, col++); 1924 1925 disasm_printer_column(printer, col++); 1926 disasm_printer_add_mdesc(printer, inst); 1927 } 1928 1929 if (col < 4) 1930 col = 4; 1931 1932 disasm_printer_column(printer, col++); 1933 disasm_printer_add_ctrl(printer, inst); 1934 1935 ilo_printf("%s\n", disasm_printer_get_string(printer)); 1936 } 1937 1938 static void 1939 disasm_uncompact_3src(const struct ilo_dev *dev, 1940 uint64_t compact, uint32_t *dw) 1941 { 1942 const struct toy_compaction_table *tbl = 1943 toy_compiler_get_compaction_table(dev); 1944 uint32_t src[3], tmp; 1945 uint64_t tmp64; 1946 1947 ILO_DEV_ASSERT(dev, 8, 8); 1948 1949 tmp = GEN_EXTRACT(compact, GEN8_COMPACT_3SRC_OPCODE); 1950 dw[0] = GEN_SHIFT32(tmp, GEN6_INST_OPCODE); 1951 1952 /* ControlIndex */ 1953 tmp = GEN_EXTRACT(compact, GEN8_COMPACT_3SRC_CONTROL_INDEX); 1954 tmp = tbl->control_3src[tmp]; 1955 1956 dw[0] |= (tmp & 0x1fffff) << GEN6_INST_ACCESSMODE__SHIFT; 1957 dw[1] = (tmp >> 21) & ((ilo_dev_gen(dev) >= ILO_GEN(9)) ? 0x1f : 0x7); 1958 1959 /* SourceIndex */ 1960 tmp = GEN_EXTRACT(compact, GEN8_COMPACT_3SRC_SOURCE_INDEX); 1961 tmp64 = tbl->source_3src[tmp]; 1962 1963 dw[1] |= (tmp64 & 0x7ffff) << 5; 1964 src[0] = ((tmp64 >> 19) & 0xff) << 1; 1965 src[1] = ((tmp64 >> 27) & 0xff) << 1; 1966 src[2] = ((tmp64 >> 35) & 0xff) << 1; 1967 if (ilo_dev_gen(dev) >= ILO_GEN(9)) { 1968 src[0] |= ((tmp64 >> 43) & 0x3) << 19; 1969 src[1] |= ((tmp64 >> 45) & 0x3) << 19; 1970 src[2] |= ((tmp64 >> 47) & 0x3) << 19; 1971 } else { 1972 src[0] |= ((tmp64 >> 43) & 0x1) << 19; 1973 src[1] |= ((tmp64 >> 44) & 0x1) << 19; 1974 src[2] |= ((tmp64 >> 45) & 0x1) << 19; 1975 } 1976 1977 tmp = GEN_EXTRACT(compact, GEN8_COMPACT_3SRC_DST_REG); 1978 dw[1] |= GEN_SHIFT32(tmp, GEN6_3SRC_DST_REG); 1979 1980 if (compact & GEN8_COMPACT_3SRC_SRC0_REPCTRL) 1981 src[0] |= GEN6_3SRC_SRC_REPCTRL; 1982 1983 assert(compact & GEN8_COMPACT_3SRC_CMPTCTRL); 1984 1985 if (compact & GEN8_COMPACT_3SRC_DEBUGCTRL) 1986 dw[0] |= GEN6_INST_DEBUGCTRL; 1987 if (compact & GEN8_COMPACT_3SRC_SATURATE) 1988 dw[0] |= GEN6_INST_SATURATE; 1989 1990 if (compact & GEN8_COMPACT_3SRC_SRC1_REPCTRL) 1991 src[1] |= GEN6_3SRC_SRC_REPCTRL; 1992 if (compact & GEN8_COMPACT_3SRC_SRC2_REPCTRL) 1993 src[2] |= GEN6_3SRC_SRC_REPCTRL; 1994 1995 tmp = GEN_EXTRACT(compact, GEN8_COMPACT_3SRC_SRC0_SUBREG); 1996 src[0] |= GEN_SHIFT32(tmp, GEN6_3SRC_SRC_SUBREG); 1997 tmp = GEN_EXTRACT(compact, GEN8_COMPACT_3SRC_SRC1_SUBREG); 1998 src[1] |= GEN_SHIFT32(tmp, GEN6_3SRC_SRC_SUBREG); 1999 tmp = GEN_EXTRACT(compact, GEN8_COMPACT_3SRC_SRC2_SUBREG); 2000 src[2] |= GEN_SHIFT32(tmp, GEN6_3SRC_SRC_SUBREG); 2001 2002 tmp = GEN_EXTRACT(compact, GEN8_COMPACT_3SRC_SRC0_REG); 2003 src[0] |= GEN_SHIFT32(tmp, GEN6_3SRC_SRC_REG); 2004 tmp = GEN_EXTRACT(compact, GEN8_COMPACT_3SRC_SRC1_REG); 2005 src[1] |= GEN_SHIFT32(tmp, GEN6_3SRC_SRC_REG); 2006 tmp = GEN_EXTRACT(compact, GEN8_COMPACT_3SRC_SRC2_REG); 2007 src[2] |= GEN_SHIFT32(tmp, GEN6_3SRC_SRC_REG); 2008 2009 tmp64 = (uint64_t) src[2] << 42 | 2010 (uint64_t) src[1] << 21 | 2011 (uint64_t) src[0]; 2012 dw[2] = (uint32_t) tmp64; 2013 dw[3] = (uint32_t) (tmp64 >> 32); 2014 } 2015 2016 static void 2017 disasm_uncompact(const struct ilo_dev *dev, 2018 uint64_t compact, uint32_t *dw) 2019 { 2020 const struct toy_compaction_table *tbl = 2021 toy_compiler_get_compaction_table(dev); 2022 bool src_is_imm; 2023 uint32_t tmp; 2024 2025 ILO_DEV_ASSERT(dev, 6, 8); 2026 2027 tmp = GEN_EXTRACT(compact, GEN6_COMPACT_OPCODE); 2028 if (disasm_opcode_table[tmp].src_count == 3) { 2029 disasm_uncompact_3src(dev, compact, dw); 2030 return; 2031 } 2032 2033 memset(dw, 0, sizeof(*dw) * 4); 2034 2035 dw[0] |= GEN_SHIFT32(tmp, GEN6_INST_OPCODE); 2036 2037 if (ilo_dev_gen(dev) >= ILO_GEN(7) && (compact & GEN6_COMPACT_DEBUGCTRL)) 2038 dw[0] |= GEN6_INST_DEBUGCTRL; 2039 2040 /* ControlIndex */ 2041 tmp = GEN_EXTRACT(compact, GEN6_COMPACT_CONTROL_INDEX); 2042 tmp = tbl->control[tmp]; 2043 2044 dw[0] |= (tmp & 0xffff) << GEN6_INST_ACCESSMODE__SHIFT; 2045 if (tmp & 0x10000) 2046 dw[0] |= GEN6_INST_SATURATE; 2047 2048 if (ilo_dev_gen(dev) >= ILO_GEN(7)) 2049 dw[2] |= (tmp >> 17) << GEN6_INST_FLAG_SUBREG__SHIFT; 2050 2051 /* DataTypeIndex */ 2052 tmp = GEN_EXTRACT(compact, GEN6_COMPACT_DATATYPE_INDEX); 2053 tmp = tbl->datatype[tmp]; 2054 2055 dw[1] |= (tmp & 0x7fff) << GEN6_INST_DST_FILE__SHIFT; 2056 dw[1] |= (tmp >> 15) << GEN6_INST_DST_HORZSTRIDE__SHIFT; 2057 2058 /* SubRegIndex */ 2059 tmp = GEN_EXTRACT(compact, GEN6_COMPACT_SUBREG_INDEX); 2060 tmp = tbl->subreg[tmp]; 2061 2062 dw[1] |= (tmp & 0x1f) << 16; 2063 dw[2] |= ((tmp >> 5) & 0x1f); 2064 dw[3] |= ((tmp >> 10) & 0x1f); 2065 2066 if (compact & GEN6_COMPACT_ACCWRCTRL) 2067 dw[0] |= GEN6_INST_ACCWRCTRL; 2068 2069 tmp = GEN_EXTRACT(compact, GEN6_COMPACT_CONDMODIFIER); 2070 dw[0] |= GEN_SHIFT32(tmp, GEN6_INST_CONDMODIFIER); 2071 2072 if (ilo_dev_gen(dev) == ILO_GEN(6)) { 2073 tmp = GEN_EXTRACT(compact, GEN6_COMPACT_FLAG_SUBREG); 2074 dw[2] |= GEN_SHIFT32(compact, GEN6_INST_FLAG_SUBREG); 2075 } 2076 2077 assert(compact & GEN6_COMPACT_CMPTCTRL); 2078 2079 /* Src0Index */ 2080 tmp = GEN_EXTRACT(compact, GEN6_COMPACT_SRC0_INDEX); 2081 tmp = tbl->src[tmp]; 2082 dw[2] |= tmp << 13; 2083 2084 src_is_imm = (GEN_EXTRACT(dw[1], GEN6_INST_SRC0_FILE) == GEN6_FILE_IMM) || 2085 (GEN_EXTRACT(dw[1], GEN6_INST_SRC1_FILE) == GEN6_FILE_IMM); 2086 2087 /* Src1Index */ 2088 tmp = GEN_EXTRACT(compact, GEN6_COMPACT_SRC1_INDEX); 2089 if (src_is_imm) { 2090 if (tmp & 0x10) 2091 tmp |= 0xfffff0; 2092 dw[3] |= tmp << 8; 2093 } else { 2094 tmp = tbl->src[tmp]; 2095 dw[3] |= tmp << 13; 2096 } 2097 2098 tmp = GEN_EXTRACT(compact, GEN6_COMPACT_DST_REG); 2099 dw[1] |= GEN_SHIFT32(tmp, GEN6_INST_DST_REG); 2100 2101 tmp = GEN_EXTRACT(compact, GEN6_COMPACT_SRC0_REG); 2102 dw[2] |= GEN_SHIFT32(tmp, GEN6_INST_SRC_REG); 2103 2104 tmp = GEN_EXTRACT(compact, GEN6_COMPACT_SRC1_REG); 2105 if (src_is_imm) 2106 dw[3] |= tmp; 2107 else 2108 dw[3] |= GEN_SHIFT32(tmp, GEN6_INST_SRC_REG); 2109 } 2110 2111 void 2112 toy_compiler_disassemble(const struct ilo_dev *dev, 2113 const void *kernel, int size, 2114 bool dump_hex) 2115 { 2116 const uint32_t *cur = (const uint32_t *) kernel; 2117 const uint32_t *end = cur + size / sizeof(*cur); 2118 struct disasm_printer printer; 2119 2120 disasm_printer_reset(&printer); 2121 2122 while (cur < end) { 2123 struct disasm_inst inst; 2124 const bool compacted = (cur[0] & GEN6_INST_CMPTCTRL); 2125 const uint32_t *dw = cur; 2126 uint32_t temp[4]; 2127 2128 cur += (compacted) ? 2 : 4; 2129 /* incomplete instruction */ 2130 if (cur > end) 2131 break; 2132 2133 if (compacted) { 2134 const uint64_t compact = (uint64_t) dw[1] << 32 | dw[0]; 2135 disasm_uncompact(dev, compact, temp); 2136 dw = temp; 2137 } 2138 2139 if (dump_hex) { 2140 ilo_printf("0x%08x 0x%08x 0x%08x 0x%08x ", 2141 dw[0], dw[1], dw[2], dw[3]); 2142 } 2143 2144 memset(&inst, 0, sizeof(inst)); 2145 inst.dev = dev; 2146 disasm_inst_decode(&inst, dw); 2147 inst.cmpt_ctrl = compacted; 2148 2149 disasm_printer_print_inst(&printer, &inst); 2150 } 2151 } 2152