1/* 2 * Copyright © 2008 Keith Packard 3 * 4 * Permission to use, copy, modify, distribute, and sell this software and its 5 * documentation for any purpose is hereby granted without fee, provided that 6 * the above copyright notice appear in all copies and that both that copyright 7 * notice and this permission notice appear in supporting documentation, and 8 * that the name of the copyright holders not be used in advertising or 9 * publicity pertaining to distribution of the software without specific, 10 * written prior permission. The copyright holders make no representations 11 * about the suitability of this software for any purpose. It is provided "as 12 * is" without express or implied warranty. 13 * 14 * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 15 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO 16 * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR 17 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 18 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 19 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 20 * OF THIS SOFTWARE. 21 */ 22 23#include <stdio.h> 24#include <stdlib.h> 25#include <string.h> 26#include <getopt.h> 27#include <unistd.h> 28#include <stdarg.h> 29 30#include "brw_eu.h" 31 32static const struct { 33 const char *name; 34 int nsrc; 35 int ndst; 36} opcode[128] = { 37 [BRW_OPCODE_MOV] = { .name = "mov", .nsrc = 1, .ndst = 1 }, 38 [BRW_OPCODE_FRC] = { .name = "frc", .nsrc = 1, .ndst = 1 }, 39 [BRW_OPCODE_RNDU] = { .name = "rndu", .nsrc = 1, .ndst = 1 }, 40 [BRW_OPCODE_RNDD] = { .name = "rndd", .nsrc = 1, .ndst = 1 }, 41 [BRW_OPCODE_RNDE] = { .name = "rnde", .nsrc = 1, .ndst = 1 }, 42 [BRW_OPCODE_RNDZ] = { .name = "rndz", .nsrc = 1, .ndst = 1 }, 43 [BRW_OPCODE_NOT] = { .name = "not", .nsrc = 1, .ndst = 1 }, 44 [BRW_OPCODE_LZD] = { .name = "lzd", .nsrc = 1, .ndst = 1 }, 45 46 [BRW_OPCODE_MUL] = { .name = "mul", .nsrc = 2, .ndst = 1 }, 47 [BRW_OPCODE_MAC] = { .name = "mac", .nsrc = 2, .ndst = 1 }, 48 [BRW_OPCODE_MACH] = { .name = "mach", .nsrc = 2, .ndst = 1 }, 49 [BRW_OPCODE_LINE] = { .name = "line", .nsrc = 2, .ndst = 1 }, 50 [BRW_OPCODE_PLN] = { .name = "pln", .nsrc = 2, .ndst = 1 }, 51 [BRW_OPCODE_SAD2] = { .name = "sad2", .nsrc = 2, .ndst = 1 }, 52 [BRW_OPCODE_SADA2] = { .name = "sada2", .nsrc = 2, .ndst = 1 }, 53 [BRW_OPCODE_DP4] = { .name = "dp4", .nsrc = 2, .ndst = 1 }, 54 [BRW_OPCODE_DPH] = { .name = "dph", .nsrc = 2, .ndst = 1 }, 55 [BRW_OPCODE_DP3] = { .name = "dp3", .nsrc = 2, .ndst = 1 }, 56 [BRW_OPCODE_DP2] = { .name = "dp2", .nsrc = 2, .ndst = 1 }, 57 [BRW_OPCODE_MATH] = { .name = "math", .nsrc = 2, .ndst = 1 }, 58 59 [BRW_OPCODE_AVG] = { .name = "avg", .nsrc = 2, .ndst = 1 }, 60 [BRW_OPCODE_ADD] = { .name = "add", .nsrc = 2, .ndst = 1 }, 61 [BRW_OPCODE_SEL] = { .name = "sel", .nsrc = 2, .ndst = 1 }, 62 [BRW_OPCODE_AND] = { .name = "and", .nsrc = 2, .ndst = 1 }, 63 [BRW_OPCODE_OR] = { .name = "or", .nsrc = 2, .ndst = 1 }, 64 [BRW_OPCODE_XOR] = { .name = "xor", .nsrc = 2, .ndst = 1 }, 65 [BRW_OPCODE_SHR] = { .name = "shr", .nsrc = 2, .ndst = 1 }, 66 [BRW_OPCODE_SHL] = { .name = "shl", .nsrc = 2, .ndst = 1 }, 67 [BRW_OPCODE_ASR] = { .name = "asr", .nsrc = 2, .ndst = 1 }, 68 [BRW_OPCODE_CMP] = { .name = "cmp", .nsrc = 2, .ndst = 1 }, 69 [BRW_OPCODE_CMPN] = { .name = "cmpn", .nsrc = 2, .ndst = 1 }, 70 71 [BRW_OPCODE_SEND] = { .name = "send", .nsrc = 1, .ndst = 1 }, 72 [BRW_OPCODE_SENDC] = { .name = "sendc", .nsrc = 1, .ndst = 1 }, 73 [BRW_OPCODE_NOP] = { .name = "nop", .nsrc = 0, .ndst = 0 }, 74 [BRW_OPCODE_JMPI] = { .name = "jmpi", .nsrc = 1, .ndst = 0 }, 75 [BRW_OPCODE_IF] = { .name = "if", .nsrc = 2, .ndst = 0 }, 76 [BRW_OPCODE_IFF] = { .name = "iff", .nsrc = 2, .ndst = 1 }, 77 [BRW_OPCODE_WHILE] = { .name = "while", .nsrc = 2, .ndst = 0 }, 78 [BRW_OPCODE_ELSE] = { .name = "else", .nsrc = 2, .ndst = 0 }, 79 [BRW_OPCODE_BREAK] = { .name = "break", .nsrc = 2, .ndst = 0 }, 80 [BRW_OPCODE_CONTINUE] = { .name = "cont", .nsrc = 1, .ndst = 0 }, 81 [BRW_OPCODE_HALT] = { .name = "halt", .nsrc = 1, .ndst = 0 }, 82 [BRW_OPCODE_MSAVE] = { .name = "msave", .nsrc = 1, .ndst = 1 }, 83 [BRW_OPCODE_PUSH] = { .name = "push", .nsrc = 1, .ndst = 1 }, 84 [BRW_OPCODE_MRESTORE] = { .name = "mrest", .nsrc = 1, .ndst = 1 }, 85 [BRW_OPCODE_POP] = { .name = "pop", .nsrc = 2, .ndst = 0 }, 86 [BRW_OPCODE_WAIT] = { .name = "wait", .nsrc = 1, .ndst = 0 }, 87 [BRW_OPCODE_DO] = { .name = "do", .nsrc = 0, .ndst = 0 }, 88 [BRW_OPCODE_ENDIF] = { .name = "endif", .nsrc = 2, .ndst = 0 }, 89}; 90 91static const char *conditional_modifier[16] = { 92 [BRW_CONDITIONAL_NONE] = "", 93 [BRW_CONDITIONAL_Z] = ".e", 94 [BRW_CONDITIONAL_NZ] = ".ne", 95 [BRW_CONDITIONAL_G] = ".g", 96 [BRW_CONDITIONAL_GE] = ".ge", 97 [BRW_CONDITIONAL_L] = ".l", 98 [BRW_CONDITIONAL_LE] = ".le", 99 [BRW_CONDITIONAL_R] = ".r", 100 [BRW_CONDITIONAL_O] = ".o", 101 [BRW_CONDITIONAL_U] = ".u", 102}; 103 104static const char *negate[2] = { 105 [0] = "", 106 [1] = "-", 107}; 108 109static const char *_abs[2] = { 110 [0] = "", 111 [1] = "(abs)", 112}; 113 114static const char *vert_stride[16] = { 115 [0] = "0", 116 [1] = "1", 117 [2] = "2", 118 [3] = "4", 119 [4] = "8", 120 [5] = "16", 121 [6] = "32", 122 [15] = "VxH", 123}; 124 125static const char *width[8] = { 126 [0] = "1", 127 [1] = "2", 128 [2] = "4", 129 [3] = "8", 130 [4] = "16", 131}; 132 133static const char *horiz_stride[4] = { 134 [0] = "0", 135 [1] = "1", 136 [2] = "2", 137 [3] = "4" 138}; 139 140static const char *chan_sel[4] = { 141 [0] = "x", 142 [1] = "y", 143 [2] = "z", 144 [3] = "w", 145}; 146 147#if 0 148static const char *dest_condmod[16] = { 149}; 150 151static const char *imm_encoding[8] = { 152 [0] = "UD", 153 [1] = "D", 154 [2] = "UW", 155 [3] = "W", 156 [5] = "VF", 157 [6] = "V", 158 [7] = "F" 159}; 160#endif 161 162static const char *debug_ctrl[2] = { 163 [0] = "", 164 [1] = ".breakpoint" 165}; 166 167static const char *saturate[2] = { 168 [0] = "", 169 [1] = ".sat" 170}; 171 172static const char *accwr[2] = { 173 [0] = "", 174 [1] = "AccWrEnable" 175}; 176 177static const char *wectrl[2] = { 178 [0] = "WE_normal", 179 [1] = "WE_all" 180}; 181 182static const char *exec_size[8] = { 183 [0] = "1", 184 [1] = "2", 185 [2] = "4", 186 [3] = "8", 187 [4] = "16", 188 [5] = "32" 189}; 190 191static const char *pred_inv[2] = { 192 [0] = "+", 193 [1] = "-" 194}; 195 196static const char *pred_ctrl_align16[16] = { 197 [1] = "", 198 [2] = ".x", 199 [3] = ".y", 200 [4] = ".z", 201 [5] = ".w", 202 [6] = ".any4h", 203 [7] = ".all4h", 204}; 205 206static const char *pred_ctrl_align1[16] = { 207 [1] = "", 208 [2] = ".anyv", 209 [3] = ".allv", 210 [4] = ".any2h", 211 [5] = ".all2h", 212 [6] = ".any4h", 213 [7] = ".all4h", 214 [8] = ".any8h", 215 [9] = ".all8h", 216 [10] = ".any16h", 217 [11] = ".all16h", 218}; 219 220static const char *thread_ctrl[4] = { 221 [0] = "", 222 [2] = "switch" 223}; 224 225static const char *compr_ctrl[4] = { 226 [0] = "", 227 [1] = "sechalf", 228 [2] = "compr", 229 [3] = "compr4", 230}; 231 232static const char *dep_ctrl[4] = { 233 [0] = "", 234 [1] = "NoDDClr", 235 [2] = "NoDDChk", 236 [3] = "NoDDClr,NoDDChk", 237}; 238 239static const char *mask_ctrl[4] = { 240 [0] = "", 241 [1] = "nomask", 242}; 243 244static const char *access_mode[2] = { 245 [0] = "align1", 246 [1] = "align16", 247}; 248 249static const char *reg_encoding[8] = { 250 [0] = "UD", 251 [1] = "D", 252 [2] = "UW", 253 [3] = "W", 254 [4] = "UB", 255 [5] = "B", 256 [7] = "F" 257}; 258 259static const int reg_type_size[8] = { 260 [0] = 4, 261 [1] = 4, 262 [2] = 2, 263 [3] = 2, 264 [4] = 1, 265 [5] = 1, 266 [7] = 4 267}; 268 269static const char *reg_file[4] = { 270 [0] = "A", 271 [1] = "g", 272 [2] = "m", 273 [3] = "imm", 274}; 275 276static const char *writemask[16] = { 277 [0x0] = ".", 278 [0x1] = ".x", 279 [0x2] = ".y", 280 [0x3] = ".xy", 281 [0x4] = ".z", 282 [0x5] = ".xz", 283 [0x6] = ".yz", 284 [0x7] = ".xyz", 285 [0x8] = ".w", 286 [0x9] = ".xw", 287 [0xa] = ".yw", 288 [0xb] = ".xyw", 289 [0xc] = ".zw", 290 [0xd] = ".xzw", 291 [0xe] = ".yzw", 292 [0xf] = "", 293}; 294 295static const char *end_of_thread[2] = { 296 [0] = "", 297 [1] = "EOT" 298}; 299 300static const char *target_function[16] = { 301 [BRW_SFID_NULL] = "null", 302 [BRW_SFID_MATH] = "math", 303 [BRW_SFID_SAMPLER] = "sampler", 304 [BRW_SFID_MESSAGE_GATEWAY] = "gateway", 305 [BRW_SFID_DATAPORT_READ] = "read", 306 [BRW_SFID_DATAPORT_WRITE] = "write", 307 [BRW_SFID_URB] = "urb", 308 [BRW_SFID_THREAD_SPAWNER] = "thread_spawner" 309}; 310 311static const char *target_function_gen6[16] = { 312 [BRW_SFID_NULL] = "null", 313 [BRW_SFID_MATH] = "math", 314 [BRW_SFID_SAMPLER] = "sampler", 315 [BRW_SFID_MESSAGE_GATEWAY] = "gateway", 316 [BRW_SFID_URB] = "urb", 317 [BRW_SFID_THREAD_SPAWNER] = "thread_spawner", 318 [GEN6_SFID_DATAPORT_SAMPLER_CACHE] = "sampler", 319 [GEN6_SFID_DATAPORT_RENDER_CACHE] = "render", 320 [GEN6_SFID_DATAPORT_CONSTANT_CACHE] = "const", 321 [GEN7_SFID_DATAPORT_DATA_CACHE] = "data" 322}; 323 324static const char *dp_rc_msg_type_gen6[16] = { 325 [BRW_DATAPORT_READ_MESSAGE_OWORD_BLOCK_READ] = "OWORD block read", 326 [GEN6_DATAPORT_READ_MESSAGE_RENDER_UNORM_READ] = "RT UNORM read", 327 [GEN6_DATAPORT_READ_MESSAGE_OWORD_DUAL_BLOCK_READ] = "OWORD dual block read", 328 [GEN6_DATAPORT_READ_MESSAGE_MEDIA_BLOCK_READ] = "media block read", 329 [GEN6_DATAPORT_READ_MESSAGE_OWORD_UNALIGN_BLOCK_READ] = "OWORD unaligned block read", 330 [GEN6_DATAPORT_READ_MESSAGE_DWORD_SCATTERED_READ] = "DWORD scattered read", 331 [GEN6_DATAPORT_WRITE_MESSAGE_DWORD_ATOMIC_WRITE] = "DWORD atomic write", 332 [GEN6_DATAPORT_WRITE_MESSAGE_OWORD_BLOCK_WRITE] = "OWORD block write", 333 [GEN6_DATAPORT_WRITE_MESSAGE_OWORD_DUAL_BLOCK_WRITE] = "OWORD dual block write", 334 [GEN6_DATAPORT_WRITE_MESSAGE_MEDIA_BLOCK_WRITE] = "media block write", 335 [GEN6_DATAPORT_WRITE_MESSAGE_DWORD_SCATTERED_WRITE] = "DWORD scattered write", 336 [GEN6_DATAPORT_WRITE_MESSAGE_RENDER_TARGET_WRITE] = "RT write", 337 [GEN6_DATAPORT_WRITE_MESSAGE_STREAMED_VB_WRITE] = "streamed VB write", 338 [GEN6_DATAPORT_WRITE_MESSAGE_RENDER_TARGET_UNORM_WRITE] = "RT UNORMc write", 339}; 340 341static const char *math_function[16] = { 342 [BRW_MATH_FUNCTION_INV] = "inv", 343 [BRW_MATH_FUNCTION_LOG] = "log", 344 [BRW_MATH_FUNCTION_EXP] = "exp", 345 [BRW_MATH_FUNCTION_SQRT] = "sqrt", 346 [BRW_MATH_FUNCTION_RSQ] = "rsq", 347 [BRW_MATH_FUNCTION_SIN] = "sin", 348 [BRW_MATH_FUNCTION_COS] = "cos", 349 [BRW_MATH_FUNCTION_SINCOS] = "sincos", 350 [BRW_MATH_FUNCTION_TAN] = "tan", 351 [BRW_MATH_FUNCTION_POW] = "pow", 352 [BRW_MATH_FUNCTION_INT_DIV_QUOTIENT_AND_REMAINDER] = "intdivmod", 353 [BRW_MATH_FUNCTION_INT_DIV_QUOTIENT] = "intdiv", 354 [BRW_MATH_FUNCTION_INT_DIV_REMAINDER] = "intmod", 355}; 356 357static const char *math_saturate[2] = { 358 [0] = "", 359 [1] = "sat" 360}; 361 362static const char *math_signed[2] = { 363 [0] = "", 364 [1] = "signed" 365}; 366 367static const char *math_scalar[2] = { 368 [0] = "", 369 [1] = "scalar" 370}; 371 372static const char *math_precision[2] = { 373 [0] = "", 374 [1] = "partial_precision" 375}; 376 377static const char *urb_opcode[2] = { 378 [0] = "urb_write", 379 [1] = "ff_sync", 380}; 381 382static const char *urb_swizzle[4] = { 383 [BRW_URB_SWIZZLE_NONE] = "", 384 [BRW_URB_SWIZZLE_INTERLEAVE] = "interleave", 385 [BRW_URB_SWIZZLE_TRANSPOSE] = "transpose", 386}; 387 388static const char *urb_allocate[2] = { 389 [0] = "", 390 [1] = "allocate" 391}; 392 393static const char *urb_used[2] = { 394 [0] = "", 395 [1] = "used" 396}; 397 398static const char *urb_complete[2] = { 399 [0] = "", 400 [1] = "complete" 401}; 402 403static const char *sampler_target_format[4] = { 404 [0] = "F", 405 [2] = "UD", 406 [3] = "D" 407}; 408 409static int column; 410 411static int string(FILE *file, const char *str) 412{ 413 fputs(str, file); 414 column += strlen(str); 415 return 0; 416} 417 418#if defined(__GNUC__) && (__GNUC__ > 2) 419__attribute__((format(printf, 2, 3))) 420#endif 421static int format(FILE *f, const char *fmt, ...) 422{ 423 char buf[1024]; 424 va_list args; 425 426 va_start(args, fmt); 427 vsnprintf(buf, sizeof(buf) - 1, fmt, args); 428 va_end(args); 429 430 string(f, buf); 431 return 0; 432} 433 434static void newline(FILE *f) 435{ 436 putc('\n', f); 437 column = 0; 438} 439 440static void pad(FILE *f, int c) 441{ 442 do 443 string(f, " "); 444 while (column < c); 445} 446 447static void control(FILE *file, const char *name, const char *ctrl[], unsigned id, int *space) 448{ 449 if (!ctrl[id]) { 450 fprintf(file, "*** invalid %s value %d ", 451 name, id); 452 assert(0); 453 } 454 if (ctrl[id][0]) { 455 if (space && *space) 456 string(file, " "); 457 string(file, ctrl[id]); 458 if (space) 459 *space = 1; 460 } 461} 462 463static void print_opcode(FILE *file, int id) 464{ 465 if (!opcode[id].name) { 466 format(file, "*** invalid opcode value %d ", id); 467 assert(0); 468 } 469 string(file, opcode[id].name); 470} 471 472static int reg(FILE *file, unsigned _reg_file, unsigned _reg_nr) 473{ 474 /* Clear the Compr4 instruction compression bit. */ 475 if (_reg_file == BRW_MESSAGE_REGISTER_FILE) 476 _reg_nr &= ~(1 << 7); 477 478 if (_reg_file == BRW_ARCHITECTURE_REGISTER_FILE) { 479 switch (_reg_nr & 0xf0) { 480 case BRW_ARF_NULL: 481 string(file, "null"); 482 return -1; 483 case BRW_ARF_ADDRESS: 484 format(file, "a%d", _reg_nr & 0x0f); 485 break; 486 case BRW_ARF_ACCUMULATOR: 487 format(file, "acc%d", _reg_nr & 0x0f); 488 break; 489 case BRW_ARF_FLAG: 490 format(file, "f%d", _reg_nr & 0x0f); 491 break; 492 case BRW_ARF_MASK: 493 format(file, "mask%d", _reg_nr & 0x0f); 494 break; 495 case BRW_ARF_MASK_STACK: 496 format(file, "msd%d", _reg_nr & 0x0f); 497 break; 498 case BRW_ARF_STATE: 499 format(file, "sr%d", _reg_nr & 0x0f); 500 break; 501 case BRW_ARF_CONTROL: 502 format(file, "cr%d", _reg_nr & 0x0f); 503 break; 504 case BRW_ARF_NOTIFICATION_COUNT: 505 format(file, "n%d", _reg_nr & 0x0f); 506 break; 507 case BRW_ARF_IP: 508 string(file, "ip"); 509 return -1; 510 default: 511 format(file, "ARF%d", _reg_nr); 512 break; 513 } 514 } else { 515 control(file, "src reg file", reg_file, _reg_file, NULL); 516 format(file, "%d", _reg_nr); 517 } 518 return 0; 519} 520 521static void dest(FILE *file, const struct brw_instruction *inst) 522{ 523 if (inst->header.access_mode == BRW_ALIGN_1) { 524 if (inst->bits1.da1.dest_address_mode == BRW_ADDRESS_DIRECT) { 525 if (reg(file, inst->bits1.da1.dest_reg_file, inst->bits1.da1.dest_reg_nr)) 526 return; 527 528 if (inst->bits1.da1.dest_subreg_nr) 529 format(file, ".%d", inst->bits1.da1.dest_subreg_nr / 530 reg_type_size[inst->bits1.da1.dest_reg_type]); 531 format(file, "<%d>", inst->bits1.da1.dest_horiz_stride); 532 control(file, "dest reg encoding", reg_encoding, inst->bits1.da1.dest_reg_type, NULL); 533 } else { 534 string(file, "g[a0"); 535 if (inst->bits1.ia1.dest_subreg_nr) 536 format(file, ".%d", inst->bits1.ia1.dest_subreg_nr / 537 reg_type_size[inst->bits1.ia1.dest_reg_type]); 538 if (inst->bits1.ia1.dest_indirect_offset) 539 format(file, " %d", inst->bits1.ia1.dest_indirect_offset); 540 string(file, "]"); 541 format(file, "<%d>", inst->bits1.ia1.dest_horiz_stride); 542 control(file, "dest reg encoding", reg_encoding, inst->bits1.ia1.dest_reg_type, NULL); 543 } 544 } else { 545 if (inst->bits1.da16.dest_address_mode == BRW_ADDRESS_DIRECT) { 546 if (reg(file, inst->bits1.da16.dest_reg_file, inst->bits1.da16.dest_reg_nr)) 547 return; 548 549 if (inst->bits1.da16.dest_subreg_nr) 550 format(file, ".%d", inst->bits1.da16.dest_subreg_nr / 551 reg_type_size[inst->bits1.da16.dest_reg_type]); 552 string(file, "<1>"); 553 control(file, "writemask", writemask, inst->bits1.da16.dest_writemask, NULL); 554 control(file, "dest reg encoding", reg_encoding, inst->bits1.da16.dest_reg_type, NULL); 555 } else { 556 string(file, "Indirect align16 address mode not supported"); 557 } 558 } 559} 560 561static void src_align1_region(FILE *file, 562 unsigned _vert_stride, unsigned _width, unsigned _horiz_stride) 563{ 564 string(file, "<"); 565 control(file, "vert stride", vert_stride, _vert_stride, NULL); 566 string(file, ","); 567 control(file, "width", width, _width, NULL); 568 string(file, ","); 569 control(file, "horiz_stride", horiz_stride, _horiz_stride, NULL); 570 string(file, ">"); 571} 572 573static void src_da1(FILE *file, unsigned type, unsigned _reg_file, 574 unsigned _vert_stride, unsigned _width, unsigned _horiz_stride, 575 unsigned reg_num, unsigned sub_reg_num, unsigned __abs, unsigned _negate) 576{ 577 control(file, "negate", negate, _negate, NULL); 578 control(file, "abs", _abs, __abs, NULL); 579 580 if (reg(file, _reg_file, reg_num)) 581 return; 582 583 if (sub_reg_num) 584 format(file, ".%d", sub_reg_num / reg_type_size[type]); /* use formal style like spec */ 585 src_align1_region(file, _vert_stride, _width, _horiz_stride); 586 control(file, "src reg encoding", reg_encoding, type, NULL); 587} 588 589static void src_ia1(FILE *file, 590 unsigned type, 591 unsigned _reg_file, 592 int _addr_imm, 593 unsigned _addr_subreg_nr, 594 unsigned _negate, 595 unsigned __abs, 596 unsigned _addr_mode, 597 unsigned _horiz_stride, 598 unsigned _width, 599 unsigned _vert_stride) 600{ 601 control(file, "negate", negate, _negate, NULL); 602 control(file, "abs", _abs, __abs, NULL); 603 604 string(file, "g[a0"); 605 if (_addr_subreg_nr) 606 format(file, ".%d", _addr_subreg_nr); 607 if (_addr_imm) 608 format(file, " %d", _addr_imm); 609 string(file, "]"); 610 src_align1_region(file, _vert_stride, _width, _horiz_stride); 611 control(file, "src reg encoding", reg_encoding, type, NULL); 612} 613 614static void src_da16(FILE *file, 615 unsigned _reg_type, 616 unsigned _reg_file, 617 unsigned _vert_stride, 618 unsigned _reg_nr, 619 unsigned _subreg_nr, 620 unsigned __abs, 621 unsigned _negate, 622 unsigned swz_x, 623 unsigned swz_y, 624 unsigned swz_z, 625 unsigned swz_w) 626{ 627 control(file, "negate", negate, _negate, NULL); 628 control(file, "abs", _abs, __abs, NULL); 629 630 if (reg(file, _reg_file, _reg_nr)) 631 return; 632 633 if (_subreg_nr) 634 /* bit4 for subreg number byte addressing. Make this same meaning as 635 in da1 case, so output looks consistent. */ 636 format(file, ".%d", 16 / reg_type_size[_reg_type]); 637 string(file, "<"); 638 control(file, "vert stride", vert_stride, _vert_stride, NULL); 639 string(file, ",4,1>"); 640 /* 641 * Three kinds of swizzle display: 642 * identity - nothing printed 643 * 1->all - print the single channel 644 * 1->1 - print the mapping 645 */ 646 if (swz_x == BRW_CHANNEL_X && 647 swz_y == BRW_CHANNEL_Y && 648 swz_z == BRW_CHANNEL_Z && 649 swz_w == BRW_CHANNEL_W) 650 { 651 ; 652 } 653 else if (swz_x == swz_y && swz_x == swz_z && swz_x == swz_w) 654 { 655 string(file, "."); 656 control(file, "channel select", chan_sel, swz_x, NULL); 657 } 658 else 659 { 660 string(file, "."); 661 control(file, "channel select", chan_sel, swz_x, NULL); 662 control(file, "channel select", chan_sel, swz_y, NULL); 663 control(file, "channel select", chan_sel, swz_z, NULL); 664 control(file, "channel select", chan_sel, swz_w, NULL); 665 } 666 control(file, "src da16 reg type", reg_encoding, _reg_type, NULL); 667} 668 669static void imm(FILE *file, unsigned type, const struct brw_instruction *inst) 670{ 671 switch (type) { 672 case BRW_REGISTER_TYPE_UD: 673 format(file, "0x%08xUD", inst->bits3.ud); 674 break; 675 case BRW_REGISTER_TYPE_D: 676 format(file, "%dD", inst->bits3.d); 677 break; 678 case BRW_REGISTER_TYPE_UW: 679 format(file, "0x%04xUW", (uint16_t) inst->bits3.ud); 680 break; 681 case BRW_REGISTER_TYPE_W: 682 format(file, "%dW", (int16_t) inst->bits3.d); 683 break; 684 case BRW_REGISTER_TYPE_UB: 685 format(file, "0x%02xUB", (int8_t) inst->bits3.ud); 686 break; 687 case BRW_REGISTER_TYPE_VF: 688 format(file, "Vector Float"); 689 break; 690 case BRW_REGISTER_TYPE_V: 691 format(file, "0x%08xV", inst->bits3.ud); 692 break; 693 case BRW_REGISTER_TYPE_F: 694 format(file, "%-gF", inst->bits3.f); 695 } 696} 697 698static void src0(FILE *file, const struct brw_instruction *inst) 699{ 700 if (inst->bits1.da1.src0_reg_file == BRW_IMMEDIATE_VALUE) 701 imm(file, inst->bits1.da1.src0_reg_type, inst); 702 else if (inst->header.access_mode == BRW_ALIGN_1) { 703 if (inst->bits2.da1.src0_address_mode == BRW_ADDRESS_DIRECT) { 704 src_da1(file, 705 inst->bits1.da1.src0_reg_type, 706 inst->bits1.da1.src0_reg_file, 707 inst->bits2.da1.src0_vert_stride, 708 inst->bits2.da1.src0_width, 709 inst->bits2.da1.src0_horiz_stride, 710 inst->bits2.da1.src0_reg_nr, 711 inst->bits2.da1.src0_subreg_nr, 712 inst->bits2.da1.src0_abs, 713 inst->bits2.da1.src0_negate); 714 } else { 715 src_ia1(file, 716 inst->bits1.ia1.src0_reg_type, 717 inst->bits1.ia1.src0_reg_file, 718 inst->bits2.ia1.src0_indirect_offset, 719 inst->bits2.ia1.src0_subreg_nr, 720 inst->bits2.ia1.src0_negate, 721 inst->bits2.ia1.src0_abs, 722 inst->bits2.ia1.src0_address_mode, 723 inst->bits2.ia1.src0_horiz_stride, 724 inst->bits2.ia1.src0_width, 725 inst->bits2.ia1.src0_vert_stride); 726 } 727 } else { 728 if (inst->bits2.da16.src0_address_mode == BRW_ADDRESS_DIRECT) { 729 src_da16(file, 730 inst->bits1.da16.src0_reg_type, 731 inst->bits1.da16.src0_reg_file, 732 inst->bits2.da16.src0_vert_stride, 733 inst->bits2.da16.src0_reg_nr, 734 inst->bits2.da16.src0_subreg_nr, 735 inst->bits2.da16.src0_abs, 736 inst->bits2.da16.src0_negate, 737 inst->bits2.da16.src0_swz_x, 738 inst->bits2.da16.src0_swz_y, 739 inst->bits2.da16.src0_swz_z, 740 inst->bits2.da16.src0_swz_w); 741 } else { 742 string(file, "Indirect align16 address mode not supported"); 743 } 744 } 745} 746 747static void src1(FILE *file, const struct brw_instruction *inst) 748{ 749 if (inst->bits1.da1.src1_reg_file == BRW_IMMEDIATE_VALUE) 750 imm(file, inst->bits1.da1.src1_reg_type, inst); 751 else if (inst->header.access_mode == BRW_ALIGN_1) { 752 if (inst->bits3.da1.src1_address_mode == BRW_ADDRESS_DIRECT) { 753 src_da1(file, 754 inst->bits1.da1.src1_reg_type, 755 inst->bits1.da1.src1_reg_file, 756 inst->bits3.da1.src1_vert_stride, 757 inst->bits3.da1.src1_width, 758 inst->bits3.da1.src1_horiz_stride, 759 inst->bits3.da1.src1_reg_nr, 760 inst->bits3.da1.src1_subreg_nr, 761 inst->bits3.da1.src1_abs, 762 inst->bits3.da1.src1_negate); 763 } else { 764 src_ia1(file, 765 inst->bits1.ia1.src1_reg_type, 766 inst->bits1.ia1.src1_reg_file, 767 inst->bits3.ia1.src1_indirect_offset, 768 inst->bits3.ia1.src1_subreg_nr, 769 inst->bits3.ia1.src1_negate, 770 inst->bits3.ia1.src1_abs, 771 inst->bits3.ia1.src1_address_mode, 772 inst->bits3.ia1.src1_horiz_stride, 773 inst->bits3.ia1.src1_width, 774 inst->bits3.ia1.src1_vert_stride); 775 } 776 } else { 777 if (inst->bits3.da16.src1_address_mode == BRW_ADDRESS_DIRECT) { 778 src_da16(file, 779 inst->bits1.da16.src1_reg_type, 780 inst->bits1.da16.src1_reg_file, 781 inst->bits3.da16.src1_vert_stride, 782 inst->bits3.da16.src1_reg_nr, 783 inst->bits3.da16.src1_subreg_nr, 784 inst->bits3.da16.src1_abs, 785 inst->bits3.da16.src1_negate, 786 inst->bits3.da16.src1_swz_x, 787 inst->bits3.da16.src1_swz_y, 788 inst->bits3.da16.src1_swz_z, 789 inst->bits3.da16.src1_swz_w); 790 } else { 791 string(file, "Indirect align16 address mode not supported"); 792 } 793 } 794} 795 796static const int esize[6] = { 797 [0] = 1, 798 [1] = 2, 799 [2] = 4, 800 [3] = 8, 801 [4] = 16, 802 [5] = 32, 803}; 804 805static int qtr_ctrl(FILE *file, const struct brw_instruction *inst) 806{ 807 int qtr_ctl = inst->header.compression_control; 808 int size = esize[inst->header.execution_size]; 809 810 if (size == 8) { 811 switch (qtr_ctl) { 812 case 0: 813 string(file, " 1Q"); 814 break; 815 case 1: 816 string(file, " 2Q"); 817 break; 818 case 2: 819 string(file, " 3Q"); 820 break; 821 case 3: 822 string(file, " 4Q"); 823 break; 824 } 825 } else if (size == 16){ 826 if (qtr_ctl < 2) 827 string(file, " 1H"); 828 else 829 string(file, " 2H"); 830 } 831 return 0; 832} 833 834void brw_disasm(FILE *file, const struct brw_instruction *inst, int gen) 835{ 836 int space = 0; 837 838 format(file, "%08x %08x %08x %08x\n", 839 ((const uint32_t*)inst)[0], 840 ((const uint32_t*)inst)[1], 841 ((const uint32_t*)inst)[2], 842 ((const uint32_t*)inst)[3]); 843 844 if (inst->header.predicate_control) { 845 string(file, "("); 846 control(file, "predicate inverse", pred_inv, inst->header.predicate_inverse, NULL); 847 string(file, "f0"); 848 if (inst->bits2.da1.flag_subreg_nr) 849 format(file, ".%d", inst->bits2.da1.flag_subreg_nr); 850 if (inst->header.access_mode == BRW_ALIGN_1) 851 control(file, "predicate control align1", pred_ctrl_align1, 852 inst->header.predicate_control, NULL); 853 else 854 control(file, "predicate control align16", pred_ctrl_align16, 855 inst->header.predicate_control, NULL); 856 string(file, ") "); 857 } 858 859 print_opcode(file, inst->header.opcode); 860 control(file, "saturate", saturate, inst->header.saturate, NULL); 861 control(file, "debug control", debug_ctrl, inst->header.debug_control, NULL); 862 863 if (inst->header.opcode == BRW_OPCODE_MATH) { 864 string(file, " "); 865 control(file, "function", math_function, 866 inst->header.destreg__conditionalmod, NULL); 867 } else if (inst->header.opcode != BRW_OPCODE_SEND && 868 inst->header.opcode != BRW_OPCODE_SENDC) 869 control(file, "conditional modifier", conditional_modifier, 870 inst->header.destreg__conditionalmod, NULL); 871 872 if (inst->header.opcode != BRW_OPCODE_NOP) { 873 string(file, "("); 874 control(file, "execution size", exec_size, inst->header.execution_size, NULL); 875 string(file, ")"); 876 } 877 878 if (inst->header.opcode == BRW_OPCODE_SEND && gen < 060) 879 format(file, " %d", inst->header.destreg__conditionalmod); 880 881 if (opcode[inst->header.opcode].ndst > 0) { 882 pad(file, 16); 883 dest(file, inst); 884 } else if (gen >= 060 && 885 (inst->header.opcode == BRW_OPCODE_IF || 886 inst->header.opcode == BRW_OPCODE_ELSE || 887 inst->header.opcode == BRW_OPCODE_ENDIF || 888 inst->header.opcode == BRW_OPCODE_WHILE)) { 889 format(file, " %d", inst->bits1.branch_gen6.jump_count); 890 } 891 892 if (opcode[inst->header.opcode].nsrc > 0) { 893 pad(file, 32); 894 src0(file, inst); 895 } 896 if (opcode[inst->header.opcode].nsrc > 1) { 897 pad(file, 48); 898 src1(file, inst); 899 } 900 901 if (inst->header.opcode == BRW_OPCODE_SEND || 902 inst->header.opcode == BRW_OPCODE_SENDC) { 903 enum brw_message_target target; 904 905 if (gen >= 060) 906 target = inst->header.destreg__conditionalmod; 907 else if (gen >= 050) 908 target = inst->bits2.send_gen5.sfid; 909 else 910 target = inst->bits3.generic.msg_target; 911 912 newline (file); 913 pad (file, 16); 914 space = 0; 915 916 if (gen >= 060) { 917 control (file, "target function", target_function_gen6, 918 target, &space); 919 } else { 920 control (file, "target function", target_function, 921 target, &space); 922 } 923 924 switch (target) { 925 case BRW_SFID_MATH: 926 control (file, "math function", math_function, 927 inst->bits3.math.function, &space); 928 control (file, "math saturate", math_saturate, 929 inst->bits3.math.saturate, &space); 930 control (file, "math signed", math_signed, 931 inst->bits3.math.int_type, &space); 932 control (file, "math scalar", math_scalar, 933 inst->bits3.math.data_type, &space); 934 control (file, "math precision", math_precision, 935 inst->bits3.math.precision, &space); 936 break; 937 case BRW_SFID_SAMPLER: 938 if (gen >= 070) { 939 format (file, " (%d, %d, %d, %d)", 940 inst->bits3.sampler_gen7.binding_table_index, 941 inst->bits3.sampler_gen7.sampler, 942 inst->bits3.sampler_gen7.msg_type, 943 inst->bits3.sampler_gen7.simd_mode); 944 } else if (gen >= 050) { 945 format (file, " (%d, %d, %d, %d)", 946 inst->bits3.sampler_gen5.binding_table_index, 947 inst->bits3.sampler_gen5.sampler, 948 inst->bits3.sampler_gen5.msg_type, 949 inst->bits3.sampler_gen5.simd_mode); 950 } else if (gen >= 045) { 951 format (file, " (%d, %d)", 952 inst->bits3.sampler_g4x.binding_table_index, 953 inst->bits3.sampler_g4x.sampler); 954 } else { 955 format (file, " (%d, %d, ", 956 inst->bits3.sampler.binding_table_index, 957 inst->bits3.sampler.sampler); 958 control (file, "sampler target format", 959 sampler_target_format, 960 inst->bits3.sampler.return_format, NULL); 961 string (file, ")"); 962 } 963 break; 964 case BRW_SFID_DATAPORT_READ: 965 if (gen >= 060) { 966 format (file, " (%d, %d, %d, %d)", 967 inst->bits3.gen6_dp.binding_table_index, 968 inst->bits3.gen6_dp.msg_control, 969 inst->bits3.gen6_dp.msg_type, 970 inst->bits3.gen6_dp.send_commit_msg); 971 } else if (gen >= 045) { 972 format (file, " (%d, %d, %d)", 973 inst->bits3.dp_read_gen5.binding_table_index, 974 inst->bits3.dp_read_gen5.msg_control, 975 inst->bits3.dp_read_gen5.msg_type); 976 } else { 977 format (file, " (%d, %d, %d)", 978 inst->bits3.dp_read.binding_table_index, 979 inst->bits3.dp_read.msg_control, 980 inst->bits3.dp_read.msg_type); 981 } 982 break; 983 984 case BRW_SFID_DATAPORT_WRITE: 985 if (gen >= 070) { 986 format (file, " ("); 987 988 control (file, "DP rc message type", 989 dp_rc_msg_type_gen6, 990 inst->bits3.gen7_dp.msg_type, &space); 991 992 format (file, ", %d, %d, %d)", 993 inst->bits3.gen7_dp.binding_table_index, 994 inst->bits3.gen7_dp.msg_control, 995 inst->bits3.gen7_dp.msg_type); 996 } else if (gen >= 060) { 997 format (file, " ("); 998 999 control (file, "DP rc message type", 1000 dp_rc_msg_type_gen6, 1001 inst->bits3.gen6_dp.msg_type, &space); 1002 1003 format (file, ", %d, %d, %d, %d)", 1004 inst->bits3.gen6_dp.binding_table_index, 1005 inst->bits3.gen6_dp.msg_control, 1006 inst->bits3.gen6_dp.msg_type, 1007 inst->bits3.gen6_dp.send_commit_msg); 1008 } else { 1009 format (file, " (%d, %d, %d, %d)", 1010 inst->bits3.dp_write.binding_table_index, 1011 (inst->bits3.dp_write.last_render_target << 3) | 1012 inst->bits3.dp_write.msg_control, 1013 inst->bits3.dp_write.msg_type, 1014 inst->bits3.dp_write.send_commit_msg); 1015 } 1016 break; 1017 1018 case BRW_SFID_URB: 1019 if (gen >= 050) { 1020 format (file, " %d", inst->bits3.urb_gen5.offset); 1021 } else { 1022 format (file, " %d", inst->bits3.urb.offset); 1023 } 1024 1025 space = 1; 1026 if (gen >= 050) { 1027 control (file, "urb opcode", urb_opcode, 1028 inst->bits3.urb_gen5.opcode, &space); 1029 } 1030 control (file, "urb swizzle", urb_swizzle, 1031 inst->bits3.urb.swizzle_control, &space); 1032 control (file, "urb allocate", urb_allocate, 1033 inst->bits3.urb.allocate, &space); 1034 control (file, "urb used", urb_used, 1035 inst->bits3.urb.used, &space); 1036 control (file, "urb complete", urb_complete, 1037 inst->bits3.urb.complete, &space); 1038 break; 1039 case BRW_SFID_THREAD_SPAWNER: 1040 break; 1041 case GEN7_SFID_DATAPORT_DATA_CACHE: 1042 format (file, " (%d, %d, %d)", 1043 inst->bits3.gen7_dp.binding_table_index, 1044 inst->bits3.gen7_dp.msg_control, 1045 inst->bits3.gen7_dp.msg_type); 1046 break; 1047 1048 1049 default: 1050 format (file, "unsupported target %d", target); 1051 break; 1052 } 1053 if (space) 1054 string (file, " "); 1055 if (gen >= 050) { 1056 format (file, "mlen %d", 1057 inst->bits3.generic_gen5.msg_length); 1058 format (file, " rlen %d", 1059 inst->bits3.generic_gen5.response_length); 1060 } else { 1061 format (file, "mlen %d", 1062 inst->bits3.generic.msg_length); 1063 format (file, " rlen %d", 1064 inst->bits3.generic.response_length); 1065 } 1066 } 1067 pad(file, 64); 1068 if (inst->header.opcode != BRW_OPCODE_NOP) { 1069 string(file, "{"); 1070 space = 1; 1071 control(file, "access mode", access_mode, inst->header.access_mode, &space); 1072 if (gen >= 060) 1073 control(file, "write enable control", wectrl, inst->header.mask_control, &space); 1074 else 1075 control(file, "mask control", mask_ctrl, inst->header.mask_control, &space); 1076 control(file, "dependency control", dep_ctrl, inst->header.dependency_control, &space); 1077 1078 if (gen >= 060) 1079 qtr_ctrl(file, inst); 1080 else { 1081 if (inst->header.compression_control == BRW_COMPRESSION_COMPRESSED && 1082 opcode[inst->header.opcode].ndst > 0 && 1083 inst->bits1.da1.dest_reg_file == BRW_MESSAGE_REGISTER_FILE && 1084 inst->bits1.da1.dest_reg_nr & (1 << 7)) { 1085 format(file, " compr4"); 1086 } else { 1087 control(file, "compression control", compr_ctrl, 1088 inst->header.compression_control, &space); 1089 } 1090 } 1091 1092 control(file, "thread control", thread_ctrl, inst->header.thread_control, &space); 1093 if (gen >= 060) 1094 control(file, "acc write control", accwr, inst->header.acc_wr_control, &space); 1095 if (inst->header.opcode == BRW_OPCODE_SEND || 1096 inst->header.opcode == BRW_OPCODE_SENDC) 1097 control(file, "end of thread", end_of_thread, 1098 inst->bits3.generic.end_of_thread, &space); 1099 if (space) 1100 string(file, " "); 1101 string(file, "}"); 1102 } 1103 string(file, ";"); 1104 newline(file); 1105} 1106