kgem_debug.c revision 42542f5f
1/* 2 * Copyright © 2007-2011 Intel Corporation 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Software"), 6 * to deal in the Software without restriction, including without limitation 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 * and/or sell copies of the Software, and to permit persons to whom the 9 * Software is furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice (including the next 12 * paragraph) shall be included in all copies or substantial portions of the 13 * Software. 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 * SOFTWARE. 22 * 23 * Authors: 24 * Eric Anholt <eric@anholt.net> 25 * 26 */ 27 28#ifdef HAVE_CONFIG_H 29#include "config.h" 30#endif 31 32#include <sys/mman.h> 33#include <assert.h> 34 35#include "sna.h" 36#include "sna_reg.h" 37 38#include "kgem_debug.h" 39 40struct drm_i915_gem_relocation_entry * 41kgem_debug_get_reloc_entry(struct kgem *kgem, uint32_t offset) 42{ 43 int i; 44 45 offset *= sizeof(uint32_t); 46 47 for (i = 0; i < kgem->nreloc; i++) 48 if (kgem->reloc[i].offset == offset) 49 return kgem->reloc+i; 50 51 assert(!"valid relocation entry, unknown batch offset"); 52 return NULL; 53} 54 55struct kgem_bo * 56kgem_debug_get_bo_for_reloc_entry(struct kgem *kgem, 57 struct drm_i915_gem_relocation_entry *reloc) 58{ 59 struct kgem_bo *bo; 60 61 if (reloc == NULL) 62 return NULL; 63 64 list_for_each_entry(bo, &kgem->next_request->buffers, request) 65 if (bo->target_handle == reloc->target_handle && bo->proxy == NULL) 66 break; 67 68 assert(&bo->request != &kgem->next_request->buffers); 69 70 return bo; 71} 72 73static int kgem_debug_handle_is_fenced(struct kgem *kgem, uint32_t handle) 74{ 75 int i; 76 77 if (kgem->has_handle_lut) 78 return kgem->exec[handle].flags & EXEC_OBJECT_NEEDS_FENCE; 79 80 for (i = 0; i < kgem->nexec; i++) 81 if (kgem->exec[i].handle == handle) 82 return kgem->exec[i].flags & EXEC_OBJECT_NEEDS_FENCE; 83 84 return 0; 85} 86 87static int kgem_debug_handle_tiling(struct kgem *kgem, uint32_t handle) 88{ 89 struct kgem_bo *bo; 90 91 list_for_each_entry(bo, &kgem->next_request->buffers, request) 92 if (bo->target_handle == handle) 93 return bo->tiling; 94 95 return 0; 96} 97 98void 99kgem_debug_print(const uint32_t *data, 100 uint32_t offset, unsigned int index, 101 const char *fmt, ...) 102{ 103 va_list va; 104 char buf[240]; 105 int len; 106 107 len = snprintf(buf, sizeof(buf), 108 "0x%08x: 0x%08x: %s", 109 (offset + index) * 4, 110 data[index], 111 index == 0 ? "" : " "); 112 113 va_start(va, fmt); 114 vsnprintf(buf + len, sizeof(buf) - len, fmt, va); 115 va_end(va); 116 117 ErrorF("%s", buf); 118} 119 120static int 121decode_nop(struct kgem *kgem, uint32_t offset) 122{ 123 uint32_t *data = kgem->batch + offset; 124 kgem_debug_print(data, offset, 0, "UNKNOWN\n"); 125 assert(0); 126 return 1; 127} 128 129static int 130decode_mi(struct kgem *kgem, uint32_t offset) 131{ 132 static const struct { 133 uint32_t opcode; 134 int len_mask; 135 int min_len; 136 int max_len; 137 const char *name; 138 } opcodes[] = { 139 { 0x08, 0, 1, 1, "MI_ARB_ON_OFF" }, 140 { 0x0a, 0, 1, 1, "MI_BATCH_BUFFER_END" }, 141 { 0x30, 0x3f, 3, 3, "MI_BATCH_BUFFER" }, 142 { 0x31, 0x3f, 2, 2, "MI_BATCH_BUFFER_START" }, 143 { 0x14, 0x3f, 3, 3, "MI_DISPLAY_BUFFER_INFO" }, 144 { 0x04, 0, 1, 1, "MI_FLUSH" }, 145 { 0x22, 0x1f, 3, 3, "MI_LOAD_REGISTER_IMM" }, 146 { 0x13, 0x3f, 2, 2, "MI_LOAD_SCAN_LINES_EXCL" }, 147 { 0x12, 0x3f, 2, 2, "MI_LOAD_SCAN_LINES_INCL" }, 148 { 0x00, 0, 1, 1, "MI_NOOP" }, 149 { 0x11, 0x3f, 2, 2, "MI_OVERLAY_FLIP" }, 150 { 0x07, 0, 1, 1, "MI_REPORT_HEAD" }, 151 { 0x18, 0x3f, 2, 2, "MI_SET_CONTEXT" }, 152 { 0x20, 0x3f, 3, 4, "MI_STORE_DATA_IMM" }, 153 { 0x21, 0x3f, 3, 4, "MI_STORE_DATA_INDEX" }, 154 { 0x24, 0x3f, 3, 3, "MI_STORE_REGISTER_MEM" }, 155 { 0x02, 0, 1, 1, "MI_USER_INTERRUPT" }, 156 { 0x03, 0, 1, 1, "MI_WAIT_FOR_EVENT" }, 157 { 0x16, 0x7f, 3, 3, "MI_SEMAPHORE_MBOX" }, 158 { 0x26, 0x1f, 3, 4, "MI_FLUSH_DW" }, 159 { 0x0b, 0, 1, 1, "MI_SUSPEND_FLUSH" }, 160 }; 161 uint32_t *data = kgem->batch + offset; 162 int op; 163 164 for (op = 0; op < ARRAY_SIZE(opcodes); op++) { 165 if ((data[0] & 0x1f800000) >> 23 == opcodes[op].opcode) { 166 unsigned int len = 1, i; 167 168 kgem_debug_print(data, offset, 0, "%s\n", opcodes[op].name); 169 if (opcodes[op].max_len > 1) { 170 len = (data[0] & opcodes[op].len_mask) + 2; 171 if (len < opcodes[op].min_len || 172 len > opcodes[op].max_len) 173 { 174 ErrorF("Bad length (%d) in %s, [%d, %d]\n", 175 len, opcodes[op].name, 176 opcodes[op].min_len, 177 opcodes[op].max_len); 178 assert(0); 179 } 180 } 181 182 for (i = 1; i < len; i++) 183 kgem_debug_print(data, offset, i, "dword %d\n", i); 184 185 return len; 186 } 187 } 188 189 kgem_debug_print(data, offset, 0, "MI UNKNOWN\n"); 190 assert(0); 191 return 1; 192} 193 194static int 195__decode_2d(struct kgem *kgem, uint32_t offset) 196{ 197 static const struct { 198 uint32_t opcode; 199 int min_len; 200 int max_len; 201 const char *name; 202 } opcodes[] = { 203 { 0x40, 5, 5, "COLOR_BLT" }, 204 { 0x43, 6, 6, "SRC_COPY_BLT" }, 205 { 0x01, 8, 8, "XY_SETUP_BLT" }, 206 { 0x11, 9, 9, "XY_SETUP_MONO_PATTERN_SL_BLT" }, 207 { 0x03, 3, 3, "XY_SETUP_CLIP_BLT" }, 208 { 0x24, 2, 2, "XY_PIXEL_BLT" }, 209 { 0x25, 3, 3, "XY_SCANLINES_BLT" }, 210 { 0x26, 4, 4, "Y_TEXT_BLT" }, 211 { 0x31, 5, 134, "XY_TEXT_IMMEDIATE_BLT" }, 212 { 0x50, 6, 6, "XY_COLOR_BLT" }, 213 { 0x51, 6, 6, "XY_PAT_BLT" }, 214 { 0x76, 8, 8, "XY_PAT_CHROMA_BLT" }, 215 { 0x72, 7, 135, "XY_PAT_BLT_IMMEDIATE" }, 216 { 0x77, 9, 137, "XY_PAT_CHROMA_BLT_IMMEDIATE" }, 217 { 0x52, 9, 9, "XY_MONO_PAT_BLT" }, 218 { 0x59, 7, 7, "XY_MONO_PAT_FIXED_BLT" }, 219 { 0x53, 8, 8, "XY_SRC_COPY_BLT" }, 220 { 0x54, 8, 8, "XY_MONO_SRC_COPY_BLT" }, 221 { 0x71, 9, 137, "XY_MONO_SRC_COPY_IMMEDIATE_BLT" }, 222 { 0x55, 9, 9, "XY_FULL_BLT" }, 223 { 0x55, 9, 137, "XY_FULL_IMMEDIATE_PATTERN_BLT" }, 224 { 0x56, 9, 9, "XY_FULL_MONO_SRC_BLT" }, 225 { 0x75, 10, 138, "XY_FULL_MONO_SRC_IMMEDIATE_PATTERN_BLT" }, 226 { 0x57, 12, 12, "XY_FULL_MONO_PATTERN_BLT" }, 227 { 0x58, 12, 12, "XY_FULL_MONO_PATTERN_MONO_SRC_BLT" }, 228 }; 229 230 unsigned int op, len; 231 const char *format = NULL; 232 uint32_t *data = kgem->batch + offset; 233 struct drm_i915_gem_relocation_entry *reloc; 234 235 /* Special case the two most common ops that we detail in full */ 236 switch ((data[0] & 0x1fc00000) >> 22) { 237 case 0x50: 238 kgem_debug_print(data, offset, 0, 239 "XY_COLOR_BLT (rgb %sabled, alpha %sabled, dst tile %d)\n", 240 (data[0] & (1 << 20)) ? "en" : "dis", 241 (data[0] & (1 << 21)) ? "en" : "dis", 242 (data[0] >> 11) & 1); 243 244 len = (data[0] & 0x000000ff) + 2; 245 assert(len == 6); 246 247 switch ((data[1] >> 24) & 0x3) { 248 case 0: 249 format="8"; 250 break; 251 case 1: 252 format="565"; 253 break; 254 case 2: 255 format="1555"; 256 break; 257 case 3: 258 format="8888"; 259 break; 260 } 261 262 kgem_debug_print(data, offset, 1, "format %s, rop %x, pitch %d, " 263 "clipping %sabled\n", format, 264 (data[1] >> 16) & 0xff, 265 (short)(data[1] & 0xffff), 266 data[1] & (1 << 30) ? "en" : "dis"); 267 kgem_debug_print(data, offset, 2, "(%d,%d)\n", 268 data[2] & 0xffff, data[2] >> 16); 269 kgem_debug_print(data, offset, 3, "(%d,%d)\n", 270 data[3] & 0xffff, data[3] >> 16); 271 reloc = kgem_debug_get_reloc_entry(kgem, offset+4); 272 kgem_debug_print(data, offset, 4, "dst offset 0x%08x [handle=%d, delta=%d, read=%x, write=%x (fenced? %d, tiling? %d)]\n", 273 data[4], 274 reloc->target_handle, reloc->delta, 275 reloc->read_domains, reloc->write_domain, 276 kgem_debug_handle_is_fenced(kgem, reloc->target_handle), 277 kgem_debug_handle_tiling(kgem, reloc->target_handle)); 278 kgem_debug_print(data, offset, 5, "color\n"); 279 assert(kgem->gen >= 040 || 280 kgem_debug_handle_is_fenced(kgem, reloc->target_handle)); 281 return len; 282 283 case 0x53: 284 kgem_debug_print(data, offset, 0, 285 "XY_SRC_COPY_BLT (rgb %sabled, alpha %sabled, " 286 "src tile %d, dst tile %d)\n", 287 (data[0] & (1 << 20)) ? "en" : "dis", 288 (data[0] & (1 << 21)) ? "en" : "dis", 289 (data[0] >> 15) & 1, 290 (data[0] >> 11) & 1); 291 292 len = (data[0] & 0x000000ff) + 2; 293 assert(len == 8); 294 295 switch ((data[1] >> 24) & 0x3) { 296 case 0: 297 format="8"; 298 break; 299 case 1: 300 format="565"; 301 break; 302 case 2: 303 format="1555"; 304 break; 305 case 3: 306 format="8888"; 307 break; 308 } 309 310 kgem_debug_print(data, offset, 1, "format %s, rop %x, dst pitch %d, " 311 "clipping %sabled\n", format, 312 (data[1] >> 16) & 0xff, 313 (short)(data[1] & 0xffff), 314 data[1] & (1 << 30) ? "en" : "dis"); 315 kgem_debug_print(data, offset, 2, "dst (%d,%d)\n", 316 data[2] & 0xffff, data[2] >> 16); 317 kgem_debug_print(data, offset, 3, "dst (%d,%d)\n", 318 data[3] & 0xffff, data[3] >> 16); 319 reloc = kgem_debug_get_reloc_entry(kgem, offset+4); 320 assert(reloc); 321 kgem_debug_print(data, offset, 4, "dst offset 0x%08x [handle=%d, delta=%d, read=%x, write=%x, (fenced? %d, tiling? %d)]\n", 322 data[4], 323 reloc->target_handle, reloc->delta, 324 reloc->read_domains, reloc->write_domain, 325 kgem_debug_handle_is_fenced(kgem, reloc->target_handle), 326 kgem_debug_handle_tiling(kgem, reloc->target_handle)); 327 assert(kgem->gen >= 040 || 328 kgem_debug_handle_is_fenced(kgem, reloc->target_handle)); 329 330 kgem_debug_print(data, offset, 5, "src (%d,%d)\n", 331 data[5] & 0xffff, data[5] >> 16); 332 kgem_debug_print(data, offset, 6, "src pitch %d\n", 333 (short)(data[6] & 0xffff)); 334 reloc = kgem_debug_get_reloc_entry(kgem, offset+7); 335 assert(reloc); 336 kgem_debug_print(data, offset, 7, "src offset 0x%08x [handle=%d, delta=%d, read=%x, write=%x (fenced? %d, tiling? %d)]\n", 337 data[7], 338 reloc->target_handle, reloc->delta, 339 reloc->read_domains, reloc->write_domain, 340 kgem_debug_handle_is_fenced(kgem, reloc->target_handle), 341 kgem_debug_handle_tiling(kgem, reloc->target_handle)); 342 assert(kgem->gen >= 040 || 343 kgem_debug_handle_is_fenced(kgem, reloc->target_handle)); 344 345 return len; 346 } 347 348 for (op = 0; op < ARRAY_SIZE(opcodes); op++) { 349 if ((data[0] & 0x1fc00000) >> 22 == opcodes[op].opcode) { 350 unsigned int i; 351 352 len = 1; 353 kgem_debug_print(data, offset, 0, "%s\n", opcodes[op].name); 354 if (opcodes[op].max_len > 1) { 355 len = (data[0] & 0x000000ff) + 2; 356 assert(len >= opcodes[op].min_len && 357 len <= opcodes[op].max_len); 358 } 359 360 for (i = 1; i < len; i++) 361 kgem_debug_print(data, offset, i, "dword %d\n", i); 362 363 return len; 364 } 365 } 366 367 kgem_debug_print(data, offset, 0, "2D UNKNOWN\n"); 368 assert(0); 369 return 1; 370} 371 372static int 373__decode_2d_gen8(struct kgem *kgem, uint32_t offset) 374{ 375 static const struct { 376 uint32_t opcode; 377 int min_len; 378 int max_len; 379 const char *name; 380 } opcodes[] = { 381 { 0x43, 8, 8, "SRC_COPY_BLT" }, 382 { 0x01, 8, 8, "XY_SETUP_BLT" }, 383 { 0x11, 10, 10, "XY_SETUP_MONO_PATTERN_SL_BLT" }, 384 { 0x03, 3, 3, "XY_SETUP_CLIP_BLT" }, 385 { 0x24, 2, 2, "XY_PIXEL_BLT" }, 386 { 0x25, 3, 3, "XY_SCANLINES_BLT" }, 387 { 0x26, 4, 4, "Y_TEXT_BLT" }, 388 { 0x31, 5, 134, "XY_TEXT_IMMEDIATE_BLT" }, 389 { 0x50, 7, 7, "XY_COLOR_BLT" }, 390 { 0x51, 6, 6, "XY_PAT_BLT" }, 391 { 0x76, 8, 8, "XY_PAT_CHROMA_BLT" }, 392 { 0x72, 7, 135, "XY_PAT_BLT_IMMEDIATE" }, 393 { 0x77, 9, 137, "XY_PAT_CHROMA_BLT_IMMEDIATE" }, 394 { 0x52, 9, 9, "XY_MONO_PAT_BLT" }, 395 { 0x59, 7, 7, "XY_MONO_PAT_FIXED_BLT" }, 396 { 0x53, 8, 8, "XY_SRC_COPY_BLT" }, 397 { 0x54, 8, 8, "XY_MONO_SRC_COPY_BLT" }, 398 { 0x71, 9, 137, "XY_MONO_SRC_COPY_IMMEDIATE_BLT" }, 399 { 0x55, 9, 9, "XY_FULL_BLT" }, 400 { 0x55, 9, 137, "XY_FULL_IMMEDIATE_PATTERN_BLT" }, 401 { 0x56, 9, 9, "XY_FULL_MONO_SRC_BLT" }, 402 { 0x75, 10, 138, "XY_FULL_MONO_SRC_IMMEDIATE_PATTERN_BLT" }, 403 { 0x57, 12, 12, "XY_FULL_MONO_PATTERN_BLT" }, 404 { 0x58, 12, 12, "XY_FULL_MONO_PATTERN_MONO_SRC_BLT" }, 405 }; 406 407 unsigned int op, len; 408 const char *format = NULL; 409 uint32_t *data = kgem->batch + offset; 410 struct drm_i915_gem_relocation_entry *reloc; 411 412 /* Special case the two most common ops that we detail in full */ 413 switch ((data[0] & 0x1fc00000) >> 22) { 414 case 0x50: 415 kgem_debug_print(data, offset, 0, 416 "XY_COLOR_BLT (rgb %sabled, alpha %sabled, dst tile %d)\n", 417 (data[0] & (1 << 20)) ? "en" : "dis", 418 (data[0] & (1 << 21)) ? "en" : "dis", 419 (data[0] >> 11) & 1); 420 421 len = (data[0] & 0x000000ff) + 2; 422 assert(len == 7); 423 424 switch ((data[1] >> 24) & 0x3) { 425 case 0: 426 format="8"; 427 break; 428 case 1: 429 format="565"; 430 break; 431 case 2: 432 format="1555"; 433 break; 434 case 3: 435 format="8888"; 436 break; 437 } 438 439 kgem_debug_print(data, offset, 1, "format %s, rop %x, pitch %d, " 440 "clipping %sabled\n", format, 441 (data[1] >> 16) & 0xff, 442 (short)(data[1] & 0xffff), 443 data[1] & (1 << 30) ? "en" : "dis"); 444 kgem_debug_print(data, offset, 2, "(%d,%d)\n", 445 data[2] & 0xffff, data[2] >> 16); 446 kgem_debug_print(data, offset, 3, "(%d,%d)\n", 447 data[3] & 0xffff, data[3] >> 16); 448 reloc = kgem_debug_get_reloc_entry(kgem, offset+4); 449 kgem_debug_print(data, offset, 4, "dst offset 0x%016llx [handle=%d, delta=%d, read=%x, write=%x (fenced? %d, tiling? %d)]\n", 450 (long long)*(uint64_t *)&data[4], 451 reloc->target_handle, reloc->delta, 452 reloc->read_domains, reloc->write_domain, 453 kgem_debug_handle_is_fenced(kgem, reloc->target_handle), 454 kgem_debug_handle_tiling(kgem, reloc->target_handle)); 455 kgem_debug_print(data, offset, 6, "color\n"); 456 return len; 457 458 case 0x53: 459 kgem_debug_print(data, offset, 0, 460 "XY_SRC_COPY_BLT (rgb %sabled, alpha %sabled, " 461 "src tile %d, dst tile %d)\n", 462 (data[0] & (1 << 20)) ? "en" : "dis", 463 (data[0] & (1 << 21)) ? "en" : "dis", 464 (data[0] >> 15) & 1, 465 (data[0] >> 11) & 1); 466 467 len = (data[0] & 0x000000ff) + 2; 468 assert(len == 10); 469 470 switch ((data[1] >> 24) & 0x3) { 471 case 0: 472 format="8"; 473 break; 474 case 1: 475 format="565"; 476 break; 477 case 2: 478 format="1555"; 479 break; 480 case 3: 481 format="8888"; 482 break; 483 } 484 485 kgem_debug_print(data, offset, 1, "format %s, rop %x, dst pitch %d, " 486 "clipping %sabled\n", format, 487 (data[1] >> 16) & 0xff, 488 (short)(data[1] & 0xffff), 489 data[1] & (1 << 30) ? "en" : "dis"); 490 kgem_debug_print(data, offset, 2, "dst (%d,%d)\n", 491 data[2] & 0xffff, data[2] >> 16); 492 kgem_debug_print(data, offset, 3, "dst (%d,%d)\n", 493 data[3] & 0xffff, data[3] >> 16); 494 reloc = kgem_debug_get_reloc_entry(kgem, offset+4); 495 assert(reloc); 496 kgem_debug_print(data, offset, 4, "dst offset 0x%016llx [handle=%d, delta=%d, read=%x, write=%x, (fenced? %d, tiling? %d)]\n", 497 (long long)*(uint64_t *)&data[4], 498 reloc->target_handle, reloc->delta, 499 reloc->read_domains, reloc->write_domain, 500 kgem_debug_handle_is_fenced(kgem, reloc->target_handle), 501 kgem_debug_handle_tiling(kgem, reloc->target_handle)); 502 503 kgem_debug_print(data, offset, 6, "src (%d,%d)\n", 504 data[6] & 0xffff, data[6] >> 16); 505 kgem_debug_print(data, offset, 7, "src pitch %d\n", 506 (short)(data[7] & 0xffff)); 507 reloc = kgem_debug_get_reloc_entry(kgem, offset+8); 508 assert(reloc); 509 kgem_debug_print(data, offset, 8, "src offset 0x%016llx [handle=%d, delta=%d, read=%x, write=%x (fenced? %d, tiling? %d)]\n", 510 (long long)*(uint64_t *)&data[8], 511 reloc->target_handle, reloc->delta, 512 reloc->read_domains, reloc->write_domain, 513 kgem_debug_handle_is_fenced(kgem, reloc->target_handle), 514 kgem_debug_handle_tiling(kgem, reloc->target_handle)); 515 516 return len; 517 } 518 519 for (op = 0; op < ARRAY_SIZE(opcodes); op++) { 520 if ((data[0] & 0x1fc00000) >> 22 == opcodes[op].opcode) { 521 unsigned int i; 522 523 len = 1; 524 kgem_debug_print(data, offset, 0, "%s\n", opcodes[op].name); 525 if (opcodes[op].max_len > 1) { 526 len = (data[0] & 0x000000ff) + 2; 527 assert(len >= opcodes[op].min_len && 528 len <= opcodes[op].max_len); 529 } 530 531 for (i = 1; i < len; i++) 532 kgem_debug_print(data, offset, i, "dword %d\n", i); 533 534 return len; 535 } 536 } 537 538 kgem_debug_print(data, offset, 0, "2D UNKNOWN\n"); 539 assert(0); 540 return 1; 541} 542 543static int (*decode_2d(int gen))(struct kgem*, uint32_t) 544{ 545 if (gen >= 0100) 546 return __decode_2d_gen8; 547 else 548 return __decode_2d; 549} 550 551static int kgem_nop_decode_3d(struct kgem *kgem, uint32_t offset) 552{ 553 uint32_t *data = kgem->batch + offset; 554 return (data[0] & 0xf) + 2; 555} 556 557static void kgem_nop_finish_state(struct kgem *kgem) 558{ 559} 560 561static int (*decode_3d(int gen))(struct kgem*, uint32_t) 562{ 563 if (gen >= 0100) { 564 return kgem_nop_decode_3d; 565 } else if (gen >= 070) { 566 return kgem_gen7_decode_3d; 567 } else if (gen >= 060) { 568 return kgem_gen6_decode_3d; 569 } else if (gen >= 050) { 570 return kgem_gen5_decode_3d; 571 } else if (gen >= 040) { 572 return kgem_gen4_decode_3d; 573 } else if (gen >= 030) { 574 return kgem_gen3_decode_3d; 575 } else if (gen >= 020) { 576 return kgem_gen2_decode_3d; 577 } 578 assert(0); 579} 580 581static void (*finish_state(int gen))(struct kgem*) 582{ 583 if (gen >= 0100) { 584 return kgem_nop_finish_state; 585 } else if (gen >= 070) { 586 return kgem_gen7_finish_state; 587 } else if (gen >= 060) { 588 return kgem_gen6_finish_state; 589 } else if (gen >= 050) { 590 return kgem_gen5_finish_state; 591 } else if (gen >= 040) { 592 return kgem_gen4_finish_state; 593 } else if (gen >= 030) { 594 return kgem_gen3_finish_state; 595 } else if (gen >= 020) { 596 return kgem_gen2_finish_state; 597 } 598 assert(0); 599} 600 601void __kgem_batch_debug(struct kgem *kgem, uint32_t nbatch) 602{ 603 int (*const decode[])(struct kgem *, uint32_t) = { 604 decode_mi, 605 decode_nop, 606 decode_2d(kgem->gen), 607 decode_3d(kgem->gen), 608 }; 609 uint32_t offset = 0; 610 611 while (offset < nbatch) { 612 int class = (kgem->batch[offset] & 0xe0000000) >> 29; 613 assert(class < ARRAY_SIZE(decode)); 614 offset += decode[class](kgem, offset); 615 } 616 617 finish_state(kgem->gen)(kgem); 618} 619