cc3d8647822c484baef6952e420986c4d26eb3bb
[mesa.git] / src / mesa / drivers / dri / i965 / gen8_disasm.c
1 /*
2 * Copyright © 2008 Keith Packard
3 * Copyright © 2009-2013 Intel Corporation
4 *
5 * Permission to use, copy, modify, distribute, and sell this software and its
6 * documentation for any purpose is hereby granted without fee, provided that
7 * the above copyright notice appear in all copies and that both that copyright
8 * notice and this permission notice appear in supporting documentation, and
9 * that the name of the copyright holders not be used in advertising or
10 * publicity pertaining to distribution of the software without specific,
11 * written prior permission. The copyright holders make no representations
12 * about the suitability of this software for any purpose. It is provided "as
13 * is" without express or implied warranty.
14 *
15 * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
16 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
17 * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
18 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
19 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
20 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
21 * OF THIS SOFTWARE.
22 */
23
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <getopt.h>
28 #include <unistd.h>
29 #include <stdarg.h>
30
31 #include "brw_context.h"
32 #include "brw_defines.h"
33 #include "gen8_instruction.h"
34
35 static const struct opcode_desc *m_opcode = opcode_descs;
36
37 static const char *const m_conditional_modifier[16] = {
38 [BRW_CONDITIONAL_NONE] = "",
39 [BRW_CONDITIONAL_Z] = ".e",
40 [BRW_CONDITIONAL_NZ] = ".ne",
41 [BRW_CONDITIONAL_G] = ".g",
42 [BRW_CONDITIONAL_GE] = ".ge",
43 [BRW_CONDITIONAL_L] = ".l",
44 [BRW_CONDITIONAL_LE] = ".le",
45 [BRW_CONDITIONAL_O] = ".o",
46 [BRW_CONDITIONAL_U] = ".u",
47 };
48
49 static const char *const m_negate[2] = { "", "-" };
50
51 static const char *const m_abs[2] = { "", "(abs)" };
52
53 static const char *const m_vert_stride[16] = {
54 "0",
55 "1",
56 "2",
57 "4",
58 "8",
59 "16",
60 "32",
61 };
62
63 static const char *const width[8] = {
64 "1",
65 "2",
66 "4",
67 "8",
68 "16",
69 };
70
71 static const char *const m_horiz_stride[4] = {
72 "0",
73 "1",
74 "2",
75 "4"
76 };
77
78 static const char *const m_chan_sel[4] = { "x", "y", "z", "w" };
79
80 static const char *const m_debug_ctrl[2] = { "", ".breakpoint" };
81
82 static const char *const m_saturate[2] = { "", ".sat" };
83
84 static const char *const m_accwr[2] = { "", "AccWrEnable" };
85
86 static const char *const m_maskctrl[2] = { "WE_normal", "WE_all" };
87
88 static const char *const m_exec_size[8] = {
89 "1",
90 "2",
91 "4",
92 "8",
93 "16",
94 "32",
95 };
96
97 static const char *const m_pred_inv[2] = { "+", "-" };
98
99 static const char *const m_pred_ctrl_align16[16] = {
100 "",
101 "",
102 ".x",
103 ".y",
104 ".z",
105 ".w",
106 ".any4h",
107 ".all4h",
108 };
109
110 static const char *const m_pred_ctrl_align1[16] = {
111 "",
112 "",
113 ".anyv",
114 ".allv",
115 ".any2h",
116 ".all2h",
117 ".any4h",
118 ".all4h",
119 ".any8h",
120 ".all8h",
121 ".any16h",
122 ".all16h",
123 ".any32h",
124 ".all32h",
125 };
126
127 static const char *const m_thread_ctrl[4] = {
128 "",
129 "atomic",
130 "switch",
131 };
132
133 static const char *const m_dep_clear[4] = {
134 "",
135 "NoDDClr",
136 };
137
138 static const char *const m_dep_check[4] = {
139 "",
140 "NoDDChk",
141 };
142
143 static const char *const m_mask_ctrl[4] = {
144 "",
145 "nomask",
146 };
147
148 static const char *const m_access_mode[2] = { "align1", "align16" };
149
150 static const char *const m_reg_encoding[] = {
151 [BRW_HW_REG_TYPE_UD] = "UD",
152 [BRW_HW_REG_TYPE_D] = "D",
153 [BRW_HW_REG_TYPE_UW] = "UW",
154 [BRW_HW_REG_TYPE_W] = "W",
155 [BRW_HW_REG_NON_IMM_TYPE_UB] = "UB",
156 [BRW_HW_REG_NON_IMM_TYPE_B] = "B",
157 [GEN7_HW_REG_NON_IMM_TYPE_DF] = "DF",
158 [BRW_HW_REG_TYPE_F] = "F",
159 [GEN8_HW_REG_TYPE_UQ] = "UQ",
160 [GEN8_HW_REG_TYPE_Q] = "Q",
161 [GEN8_HW_REG_NON_IMM_TYPE_HF] = "HF",
162 };
163
164 static const char *const m_three_source_reg_encoding[] = {
165 [BRW_3SRC_TYPE_F] = "F",
166 [BRW_3SRC_TYPE_D] = "D",
167 [BRW_3SRC_TYPE_UD] = "UD",
168 };
169
170 static const int reg_type_size[] = {
171 [BRW_HW_REG_TYPE_UD] = 4,
172 [BRW_HW_REG_TYPE_D] = 4,
173 [BRW_HW_REG_TYPE_UW] = 2,
174 [BRW_HW_REG_TYPE_W] = 2,
175 [BRW_HW_REG_NON_IMM_TYPE_UB] = 1,
176 [BRW_HW_REG_NON_IMM_TYPE_B] = 1,
177 [GEN7_HW_REG_NON_IMM_TYPE_DF] = 8,
178 [BRW_HW_REG_TYPE_F] = 4,
179 [GEN8_HW_REG_NON_IMM_TYPE_HF] = 2,
180 };
181
182 static const char *const m_reg_file[4] = {
183 [BRW_ARCHITECTURE_REGISTER_FILE] = "A",
184 [BRW_GENERAL_REGISTER_FILE] = "g",
185 [BRW_IMMEDIATE_VALUE] = "imm",
186 };
187
188 static const char *const m_writemask[16] = {
189 ".(none)",
190 ".x",
191 ".y",
192 ".xy",
193 ".z",
194 ".xz",
195 ".yz",
196 ".xyz",
197 ".w",
198 ".xw",
199 ".yw",
200 ".xyw",
201 ".zw",
202 ".xzw",
203 ".yzw",
204 "",
205 };
206
207 static const char *const m_eot[2] = { "", "EOT" };
208
209 static const char *const m_sfid[16] = {
210 [BRW_SFID_NULL] = "null",
211 [BRW_SFID_SAMPLER] = "sampler",
212 [BRW_SFID_MESSAGE_GATEWAY] = "gateway",
213 [GEN6_SFID_DATAPORT_SAMPLER_CACHE] = "dp/sampler_cache",
214 [GEN6_SFID_DATAPORT_RENDER_CACHE] = "dp/render_cache",
215 [BRW_SFID_URB] = "URB",
216 [BRW_SFID_THREAD_SPAWNER] = "thread_spawner",
217 [BRW_SFID_VME] = "vme",
218 [GEN6_SFID_DATAPORT_CONSTANT_CACHE] = "dp/constant_cache",
219 [GEN7_SFID_DATAPORT_DATA_CACHE] = "dp/data_cache",
220 [GEN7_SFID_PIXEL_INTERPOLATOR] = "pi",
221 [HSW_SFID_DATAPORT_DATA_CACHE_1] = "dp/data_cache:1",
222 [HSW_SFID_CRE] = "cre",
223 };
224
225 static const char *const m_math_function[16] = {
226 [BRW_MATH_FUNCTION_INV] = "inv",
227 [BRW_MATH_FUNCTION_LOG] = "log",
228 [BRW_MATH_FUNCTION_EXP] = "exp",
229 [BRW_MATH_FUNCTION_SQRT] = "sqrt",
230 [BRW_MATH_FUNCTION_RSQ] = "rsq",
231 [BRW_MATH_FUNCTION_SIN] = "sin",
232 [BRW_MATH_FUNCTION_COS] = "cos",
233 [BRW_MATH_FUNCTION_FDIV] = "fdiv",
234 [BRW_MATH_FUNCTION_POW] = "pow",
235 [BRW_MATH_FUNCTION_INT_DIV_QUOTIENT_AND_REMAINDER] = "intdivmod",
236 [BRW_MATH_FUNCTION_INT_DIV_QUOTIENT] = "intdiv",
237 [BRW_MATH_FUNCTION_INT_DIV_REMAINDER] = "intmod",
238 [GEN8_MATH_FUNCTION_INVM] = "invm",
239 [GEN8_MATH_FUNCTION_RSQRTM] = "rsqrtm",
240 };
241
242 static const char *const m_urb_opcode[16] = {
243 [0] = "write HWord",
244 [1] = "write OWord",
245 [2] = "read HWord",
246 [3] = "read OWord",
247 [4] = "atomic mov",
248 [5] = "atomic inc",
249 [6] = "atomic add",
250 [7] = "SIMD8 write",
251 [8] = "SIMD8 read",
252 /* [9-15] - reserved */
253 };
254
255 static const char *const m_urb_interleave[2] = { "", "interleaved" };
256
257 static const char *const m_rt_opcode[] = {
258 [0] = "SIMD16",
259 [1] = "RepData",
260 [2] = "DualLow",
261 [3] = "DualHigh",
262 [4] = "SIMD8",
263 [5] = "ImageWrite",
264 [6] = "Reserved",
265 [7] = "RepData(7)",
266 };
267
268 static int column;
269
270 static int
271 string(FILE *file, const char *string)
272 {
273 fputs(string, file);
274 column += strlen(string);
275 return 0;
276 }
277
278 static int
279 format(FILE *f, const char *format, ...)
280 {
281 char buf[1024];
282 va_list args;
283 va_start(args, format);
284
285 vsnprintf(buf, sizeof(buf) - 1, format, args);
286 va_end(args);
287 string(f, buf);
288 return 0;
289 }
290
291 static int
292 newline(FILE *f)
293 {
294 putc('\n', f);
295 column = 0;
296 return 0;
297 }
298
299 static int
300 pad(FILE *f, int c)
301 {
302 do
303 string(f, " ");
304 while (column < c);
305 return 0;
306 }
307
308 static int
309 control(FILE *file, const char *name, const char *const ctrl[],
310 unsigned id, int *space)
311 {
312 if (!ctrl[id]) {
313 fprintf(file, "*** invalid %s value %d ", name, id);
314 return 1;
315 }
316 if (ctrl[id][0]) {
317 if (space && *space)
318 string(file, " ");
319 string(file, ctrl[id]);
320 if (space)
321 *space = 1;
322 }
323 return 0;
324 }
325
326 static int
327 print_opcode(FILE *file, int id)
328 {
329 if (!m_opcode[id].name) {
330 format(file, "*** invalid opcode value %d ", id);
331 return 1;
332 }
333 string(file, m_opcode[id].name);
334 return 0;
335 }
336
337 static int
338 reg(FILE *file, unsigned reg_file, unsigned _reg_nr)
339 {
340 int err = 0;
341
342 if (reg_file == BRW_ARCHITECTURE_REGISTER_FILE) {
343 switch (_reg_nr & 0xf0) {
344 case BRW_ARF_NULL:
345 string(file, "null");
346 return -1;
347 case BRW_ARF_ADDRESS:
348 format(file, "a%d", _reg_nr & 0x0f);
349 break;
350 case BRW_ARF_ACCUMULATOR:
351 format(file, "acc%d", _reg_nr & 0x0f);
352 break;
353 case BRW_ARF_FLAG:
354 format(file, "f%d", _reg_nr & 0x0f);
355 break;
356 case BRW_ARF_MASK:
357 format(file, "mask%d", _reg_nr & 0x0f);
358 break;
359 case BRW_ARF_MASK_STACK:
360 format(file, "msd%d", _reg_nr & 0x0f);
361 break;
362 case BRW_ARF_STATE:
363 format(file, "sr%d", _reg_nr & 0x0f);
364 break;
365 case BRW_ARF_CONTROL:
366 format(file, "cr%d", _reg_nr & 0x0f);
367 break;
368 case BRW_ARF_NOTIFICATION_COUNT:
369 format(file, "n%d", _reg_nr & 0x0f);
370 break;
371 case BRW_ARF_IP:
372 string(file, "ip");
373 return -1;
374 break;
375 default:
376 format(file, "ARF%d", _reg_nr);
377 break;
378 }
379 } else {
380 err |= control(file, "src reg file", m_reg_file, reg_file, NULL);
381 format(file, "%d", _reg_nr);
382 }
383 return err;
384 }
385
386 static int
387 dest(FILE *file, struct gen8_instruction *inst)
388 {
389 int err = 0;
390
391 if (gen8_access_mode(inst) == BRW_ALIGN_1) {
392 assert(gen8_dst_address_mode(inst) == BRW_ADDRESS_DIRECT);
393 err |= reg(file, gen8_dst_reg_file(inst), gen8_dst_da_reg_nr(inst));
394 if (err == -1)
395 return 0;
396 if (gen8_dst_da1_subreg_nr(inst))
397 format(file, ".%d", gen8_dst_da1_subreg_nr(inst) /
398 reg_type_size[gen8_dst_reg_type(inst)]);
399 string(file, "<");
400 err |= control(file, "horiz stride", m_horiz_stride, gen8_dst_da1_hstride(inst), NULL);
401 string(file, ">");
402 err |= control(file, "dest reg encoding", m_reg_encoding, gen8_dst_reg_type(inst), NULL);
403 } else {
404 assert(gen8_dst_address_mode(inst) == BRW_ADDRESS_DIRECT);
405 err |= reg(file, gen8_dst_reg_file(inst), gen8_dst_da_reg_nr(inst));
406 if (err == -1)
407 return 0;
408 if (gen8_dst_da16_subreg_nr(inst))
409 format(file, ".%d", gen8_dst_da16_subreg_nr(inst) /
410 reg_type_size[gen8_dst_reg_type(inst)]);
411 string(file, "<1>");
412 err |= control(file, "writemask", m_writemask, gen8_da16_writemask(inst), NULL);
413 err |= control(file, "dest reg encoding", m_reg_encoding, gen8_dst_reg_type(inst), NULL);
414 }
415
416 return 0;
417 }
418
419 static int
420 dest_3src(FILE *file, struct gen8_instruction *inst)
421 {
422 int err = 0;
423
424 err |= reg(file, BRW_GENERAL_REGISTER_FILE, gen8_dst_3src_reg_nr(inst));
425 if (err == -1)
426 return 0;
427 if (gen8_dst_3src_subreg_nr(inst))
428 format(file, ".%d", gen8_dst_3src_subreg_nr(inst));
429 string(file, "<1>");
430 err |= control(file, "writemask", m_writemask, gen8_dst_3src_writemask(inst),
431 NULL);
432 err |= control(file, "dest reg encoding", m_three_source_reg_encoding,
433 gen8_dst_3src_type(inst), NULL);
434
435 return 0;
436 }
437
438 static int
439 src_align1_region(FILE *file, unsigned vert_stride, unsigned _width,
440 unsigned horiz_stride)
441 {
442 int err = 0;
443 string(file, "<");
444 err |= control(file, "vert stride", m_vert_stride, vert_stride, NULL);
445 string(file, ",");
446 err |= control(file, "width", width, _width, NULL);
447 string(file, ",");
448 err |= control(file, "horiz_stride", m_horiz_stride, horiz_stride, NULL);
449 string(file, ">");
450 return err;
451 }
452
453 static int
454 src_swizzle(FILE *file, unsigned x, unsigned y, unsigned z, unsigned w)
455 {
456 int err = 0;
457
458 /* Three kinds of swizzle display:
459 * - identity - nothing printed
460 * - 1->all - print the single channel
461 * - 1->1 - print the mapping
462 */
463 if (x == BRW_CHANNEL_X &&
464 y == BRW_CHANNEL_Y &&
465 z == BRW_CHANNEL_Z &&
466 w == BRW_CHANNEL_W) {
467 ; /* Print nothing */
468 } else if (x == y && x == z && x == w) {
469 string(file, ".");
470 err |= control(file, "channel select", m_chan_sel, x, NULL);
471 } else {
472 string(file, ".");
473 err |= control(file, "channel select", m_chan_sel, x, NULL);
474 err |= control(file, "channel select", m_chan_sel, y, NULL);
475 err |= control(file, "channel select", m_chan_sel, z, NULL);
476 err |= control(file, "channel select", m_chan_sel, w, NULL);
477 }
478 return err;
479 }
480
481 static int
482 src_da1(FILE *file, unsigned type, unsigned reg_file,
483 unsigned vert_stride, unsigned _width, unsigned horiz_stride,
484 unsigned reg_num, unsigned sub_reg_num, unsigned _abs, unsigned negate)
485 {
486 int err = 0;
487 err |= control(file, "negate", m_negate, negate, NULL);
488 err |= control(file, "abs", m_abs, _abs, NULL);
489
490 err |= reg(file, reg_file, reg_num);
491 if (err == -1)
492 return 0;
493 if (sub_reg_num)
494 format(file, ".%d", sub_reg_num / reg_type_size[type]); /* use formal style like spec */
495 src_align1_region(file, vert_stride, _width, horiz_stride);
496 err |= control(file, "src reg encoding", m_reg_encoding, type, NULL);
497 return err;
498 }
499
500 static int
501 src_da16(FILE *file,
502 unsigned _reg_type,
503 unsigned reg_file,
504 unsigned vert_stride,
505 unsigned _reg_nr,
506 unsigned _subreg_nr,
507 unsigned _abs,
508 unsigned negate,
509 unsigned swz_x,
510 unsigned swz_y,
511 unsigned swz_z,
512 unsigned swz_w)
513 {
514 int err = 0;
515 err |= control(file, "negate", m_negate, negate, NULL);
516 err |= control(file, "abs", m_abs, _abs, NULL);
517
518 err |= reg(file, reg_file, _reg_nr);
519 if (err == -1)
520 return 0;
521 if (_subreg_nr)
522 /* bit4 for subreg number byte addressing. Make this same meaning as
523 * in da1 case, so output looks consistent.
524 */
525 format(file, ".%d", 16 / reg_type_size[_reg_type]);
526 string(file, "<");
527 err |= control(file, "vert stride", m_vert_stride, vert_stride, NULL);
528 string(file, ",4,1>");
529 /*
530 * Three kinds of swizzle display:
531 * identity - nothing printed
532 * 1->all - print the single channel
533 * 1->1 - print the mapping
534 */
535 if (swz_x == BRW_CHANNEL_X &&
536 swz_y == BRW_CHANNEL_Y &&
537 swz_z == BRW_CHANNEL_Z &&
538 swz_w == BRW_CHANNEL_W) {
539 ; /* Print nothing */
540 } else if (swz_x == swz_y && swz_x == swz_z && swz_x == swz_w) {
541 string(file, ".");
542 err |= control(file, "channel select", m_chan_sel, swz_x, NULL);
543 } else {
544 string(file, ".");
545 err |= control(file, "channel select", m_chan_sel, swz_x, NULL);
546 err |= control(file, "channel select", m_chan_sel, swz_y, NULL);
547 err |= control(file, "channel select", m_chan_sel, swz_z, NULL);
548 err |= control(file, "channel select", m_chan_sel, swz_w, NULL);
549 }
550 err |= control(file, "src da16 reg type", m_reg_encoding, _reg_type, NULL);
551 return err;
552 }
553
554 static int
555 src0_3src(FILE *file, struct gen8_instruction *inst)
556 {
557 int err = 0;
558 unsigned swiz = gen8_src0_3src_swizzle(inst);
559 unsigned swz_x = (swiz >> 0) & 0x3;
560 unsigned swz_y = (swiz >> 2) & 0x3;
561 unsigned swz_z = (swiz >> 4) & 0x3;
562 unsigned swz_w = (swiz >> 6) & 0x3;
563
564 err |= control(file, "negate", m_negate, gen8_src0_3src_negate(inst), NULL);
565 err |= control(file, "abs", m_abs, gen8_src0_3src_abs(inst), NULL);
566
567 err |= reg(file, BRW_GENERAL_REGISTER_FILE, gen8_src0_3src_reg_nr(inst));
568 if (err == -1)
569 return 0;
570 if (gen8_src0_3src_subreg_nr(inst))
571 format(file, ".%d", gen8_src0_3src_subreg_nr(inst));
572 if (gen8_src0_3src_rep_ctrl(inst))
573 string(file, "<0,1,0>");
574 else
575 string(file, "<4,4,1>");
576 err |= control(file, "src da16 reg type", m_three_source_reg_encoding,
577 gen8_src_3src_type(inst), NULL);
578 err |= src_swizzle(file, swz_x, swz_y, swz_z, swz_w);
579 return err;
580 }
581
582 static int
583 src1_3src(FILE *file, struct gen8_instruction *inst)
584 {
585 int err = 0;
586 unsigned swiz = gen8_src1_3src_swizzle(inst);
587 unsigned swz_x = (swiz >> 0) & 0x3;
588 unsigned swz_y = (swiz >> 2) & 0x3;
589 unsigned swz_z = (swiz >> 4) & 0x3;
590 unsigned swz_w = (swiz >> 6) & 0x3;
591 unsigned src1_subreg_nr = gen8_src1_3src_subreg_nr(inst);
592
593 err |= control(file, "negate", m_negate, gen8_src1_3src_negate(inst), NULL);
594 err |= control(file, "abs", m_abs, gen8_src1_3src_abs(inst), NULL);
595
596 err |= reg(file, BRW_GENERAL_REGISTER_FILE, gen8_src1_3src_reg_nr(inst));
597 if (err == -1)
598 return 0;
599 if (src1_subreg_nr)
600 format(file, ".%d", src1_subreg_nr);
601 if (gen8_src1_3src_rep_ctrl(inst))
602 string(file, "<0,1,0>");
603 else
604 string(file, "<4,4,1>");
605 err |= control(file, "src da16 reg type", m_three_source_reg_encoding,
606 gen8_src_3src_type(inst), NULL);
607 err |= src_swizzle(file, swz_x, swz_y, swz_z, swz_w);
608 return err;
609 }
610
611 static int
612 src2_3src(FILE *file, struct gen8_instruction *inst)
613 {
614 int err = 0;
615 unsigned swiz = gen8_src2_3src_swizzle(inst);
616 unsigned swz_x = (swiz >> 0) & 0x3;
617 unsigned swz_y = (swiz >> 2) & 0x3;
618 unsigned swz_z = (swiz >> 4) & 0x3;
619 unsigned swz_w = (swiz >> 6) & 0x3;
620
621 err |= control(file, "negate", m_negate, gen8_src2_3src_negate(inst), NULL);
622 err |= control(file, "abs", m_abs, gen8_src2_3src_abs(inst), NULL);
623
624 err |= reg(file, BRW_GENERAL_REGISTER_FILE, gen8_src2_3src_reg_nr(inst));
625 if (err == -1)
626 return 0;
627 if (gen8_src2_3src_subreg_nr(inst))
628 format(file, ".%d", gen8_src2_3src_subreg_nr(inst));
629 if (gen8_src2_3src_rep_ctrl(inst))
630 string(file, "<0,1,0>");
631 else
632 string(file, "<4,4,1>");
633 err |= control(file, "src da16 reg type", m_three_source_reg_encoding,
634 gen8_src_3src_type(inst), NULL);
635 err |= src_swizzle(file, swz_x, swz_y, swz_z, swz_w);
636 return err;
637 }
638
639 static int
640 imm(FILE *file, unsigned type, struct gen8_instruction *inst)
641 {
642 switch (type) {
643 case BRW_HW_REG_TYPE_UD:
644 format(file, "0x%08xUD", gen8_src1_imm_ud(inst));
645 break;
646 case BRW_HW_REG_TYPE_D:
647 format(file, "%dD", gen8_src1_imm_d(inst));
648 break;
649 case BRW_HW_REG_TYPE_UW:
650 format(file, "0x%04xUW", (uint16_t) gen8_src1_imm_ud(inst));
651 break;
652 case BRW_HW_REG_TYPE_W:
653 format(file, "%dW", (int16_t) gen8_src1_imm_d(inst));
654 break;
655 case BRW_HW_REG_IMM_TYPE_UV:
656 format(file, "0x%08xUV", gen8_src1_imm_ud(inst));
657 break;
658 case BRW_HW_REG_IMM_TYPE_VF:
659 format(file, "Vector Float");
660 break;
661 case BRW_HW_REG_IMM_TYPE_V:
662 format(file, "0x%08xV", gen8_src1_imm_ud(inst));
663 break;
664 case BRW_HW_REG_TYPE_F:
665 format(file, "%-gF", gen8_src1_imm_f(inst));
666 break;
667 case GEN8_HW_REG_IMM_TYPE_DF:
668 case GEN8_HW_REG_IMM_TYPE_HF:
669 assert(!"Not implemented yet");
670 break;
671 }
672 return 0;
673 }
674
675 static int
676 src0(FILE *file, struct gen8_instruction *inst)
677 {
678 if (gen8_src0_reg_file(inst) == BRW_IMMEDIATE_VALUE)
679 return imm(file, gen8_src0_reg_type(inst), inst);
680
681 if (gen8_access_mode(inst) == BRW_ALIGN_1) {
682 assert(gen8_src0_address_mode(inst) == BRW_ADDRESS_DIRECT);
683 return src_da1(file,
684 gen8_src0_reg_type(inst),
685 gen8_src0_reg_file(inst),
686 gen8_src0_vert_stride(inst),
687 gen8_src0_da1_width(inst),
688 gen8_src0_da1_hstride(inst),
689 gen8_src0_da_reg_nr(inst),
690 gen8_src0_da1_subreg_nr(inst),
691 gen8_src0_abs(inst),
692 gen8_src0_negate(inst));
693 } else {
694 assert(gen8_src0_address_mode(inst) == BRW_ADDRESS_DIRECT);
695 return src_da16(file,
696 gen8_src0_reg_type(inst),
697 gen8_src0_reg_file(inst),
698 gen8_src0_vert_stride(inst),
699 gen8_src0_da_reg_nr(inst),
700 gen8_src0_da16_subreg_nr(inst),
701 gen8_src0_abs(inst),
702 gen8_src0_negate(inst),
703 gen8_src0_da16_swiz_x(inst),
704 gen8_src0_da16_swiz_y(inst),
705 gen8_src0_da16_swiz_z(inst),
706 gen8_src0_da16_swiz_w(inst));
707 }
708 }
709
710 static int
711 src1(FILE *file, struct gen8_instruction *inst)
712 {
713 if (gen8_src1_reg_file(inst) == BRW_IMMEDIATE_VALUE)
714 return imm(file, gen8_src1_reg_type(inst), inst);
715
716 if (gen8_access_mode(inst) == BRW_ALIGN_1) {
717 assert(gen8_src1_address_mode(inst) == BRW_ADDRESS_DIRECT);
718 return src_da1(file,
719 gen8_src1_reg_type(inst),
720 gen8_src1_reg_file(inst),
721 gen8_src1_vert_stride(inst),
722 gen8_src1_da1_width(inst),
723 gen8_src1_da1_hstride(inst),
724 gen8_src1_da_reg_nr(inst),
725 gen8_src1_da1_subreg_nr(inst),
726 gen8_src1_abs(inst),
727 gen8_src1_negate(inst));
728 } else {
729 assert(gen8_src1_address_mode(inst) == BRW_ADDRESS_DIRECT);
730 return src_da16(file,
731 gen8_src1_reg_type(inst),
732 gen8_src1_reg_file(inst),
733 gen8_src1_vert_stride(inst),
734 gen8_src1_da_reg_nr(inst),
735 gen8_src1_da16_subreg_nr(inst),
736 gen8_src1_abs(inst),
737 gen8_src1_negate(inst),
738 gen8_src1_da16_swiz_x(inst),
739 gen8_src1_da16_swiz_y(inst),
740 gen8_src1_da16_swiz_z(inst),
741 gen8_src1_da16_swiz_w(inst));
742 }
743 }
744
745 static int esize[6] = { 1, 2, 4, 8, 16, 32 };
746
747 static int
748 qtr_ctrl(FILE *file, struct gen8_instruction *inst)
749 {
750 int qtr_ctl = gen8_qtr_control(inst);
751 int exec_size = esize[gen8_exec_size(inst)];
752
753 if (exec_size == 8) {
754 switch (qtr_ctl) {
755 case 0:
756 string(file, " 1Q");
757 break;
758 case 1:
759 string(file, " 2Q");
760 break;
761 case 2:
762 string(file, " 3Q");
763 break;
764 case 3:
765 string(file, " 4Q");
766 break;
767 }
768 } else if (exec_size == 16) {
769 if (qtr_ctl < 2)
770 string(file, " 1H");
771 else
772 string(file, " 2H");
773 }
774 return 0;
775 }
776
777 int
778 gen8_disassemble(FILE *file, struct gen8_instruction *inst, int gen)
779 {
780 int err = 0;
781 int space = 0;
782
783 const int opcode = gen8_opcode(inst);
784
785 if (gen8_pred_control(inst)) {
786 string(file, "(");
787 err |= control(file, "predicate inverse", m_pred_inv, gen8_pred_inv(inst), NULL);
788 format(file, "f%d", gen8_flag_reg_nr(inst));
789 if (gen8_flag_subreg_nr(inst))
790 format(file, ".%d", gen8_flag_subreg_nr(inst));
791 if (gen8_access_mode(inst) == BRW_ALIGN_1) {
792 err |= control(file, "predicate control align1", m_pred_ctrl_align1,
793 gen8_pred_control(inst), NULL);
794 } else {
795 err |= control(file, "predicate control align16", m_pred_ctrl_align16,
796 gen8_pred_control(inst), NULL);
797 }
798 string(file, ") ");
799 }
800
801 err |= print_opcode(file, opcode);
802 err |= control(file, "saturate", m_saturate, gen8_saturate(inst), NULL);
803 err |= control(file, "debug control", m_debug_ctrl, gen8_debug_control(inst), NULL);
804
805 if (opcode == BRW_OPCODE_MATH) {
806 string(file, " ");
807 err |= control(file, "function", m_math_function, gen8_math_function(inst),
808 NULL);
809 } else if (opcode != BRW_OPCODE_SEND && opcode != BRW_OPCODE_SENDC) {
810 err |= control(file, "conditional modifier", m_conditional_modifier,
811 gen8_cond_modifier(inst), NULL);
812
813 /* If we're using the conditional modifier, print the flag reg used. */
814 if (gen8_cond_modifier(inst) && opcode != BRW_OPCODE_SEL) {
815 format(file, ".f%d", gen8_flag_reg_nr(inst));
816 if (gen8_flag_subreg_nr(inst))
817 format(file, ".%d", gen8_flag_subreg_nr(inst));
818 }
819 }
820
821 if (opcode != BRW_OPCODE_NOP) {
822 string(file, "(");
823 err |= control(file, "execution size", m_exec_size, gen8_exec_size(inst), NULL);
824 string(file, ")");
825 }
826
827 if (m_opcode[opcode].nsrc == 3) {
828 pad(file, 16);
829 err |= dest_3src(file, inst);
830
831 pad(file, 32);
832 err |= src0_3src(file, inst);
833
834 pad(file, 48);
835 err |= src1_3src(file, inst);
836
837 pad(file, 64);
838 err |= src2_3src(file, inst);
839 } else {
840 if (opcode == BRW_OPCODE_ENDIF || opcode == BRW_OPCODE_WHILE) {
841 pad(file, 16);
842 format(file, "JIP: %d", gen8_jip(inst));
843 } else if (opcode == BRW_OPCODE_IF ||
844 opcode == BRW_OPCODE_ELSE ||
845 opcode == BRW_OPCODE_BREAK ||
846 opcode == BRW_OPCODE_CONTINUE ||
847 opcode == BRW_OPCODE_HALT) {
848 pad(file, 16);
849 format(file, "JIP: %d", gen8_jip(inst));
850 pad(file, 32);
851 format(file, "UIP: %d", gen8_uip(inst));
852 } else {
853 if (m_opcode[opcode].ndst > 0) {
854 pad(file, 16);
855 err |= dest(file, inst);
856 }
857 if (m_opcode[opcode].nsrc > 0) {
858 pad(file, 32);
859 err |= src0(file, inst);
860 }
861 if (m_opcode[opcode].nsrc > 1) {
862 pad(file, 48);
863 err |= src1(file, inst);
864 }
865 }
866 }
867
868 if (opcode == BRW_OPCODE_SEND || opcode == BRW_OPCODE_SENDC) {
869 const int sfid = gen8_sfid(inst);
870
871 newline(file);
872 pad(file, 16);
873 space = 0;
874
875 err |= control(file, "SFID", m_sfid, sfid, &space);
876
877 switch (sfid) {
878 case BRW_SFID_SAMPLER:
879 format(file, " (%d, %d, %d, %d)",
880 gen8_binding_table_index(inst),
881 gen8_sampler(inst),
882 gen8_sampler_msg_type(inst),
883 gen8_sampler_simd_mode(inst));
884 break;
885
886 case BRW_SFID_URB:
887 space = 1;
888 err |= control(file, "urb opcode", m_urb_opcode,
889 gen8_urb_opcode(inst), &space);
890 err |= control(file, "urb interleave", m_urb_interleave,
891 gen8_urb_interleave(inst), &space);
892 format(file, " %d %d",
893 gen8_urb_global_offset(inst), gen8_urb_per_slot_offset(inst));
894 break;
895
896 case GEN6_SFID_DATAPORT_RENDER_CACHE: {
897 err |= control(file, "rt message", m_rt_opcode,
898 gen8_rt_message_type(inst), &space);
899 format(file, " %s%sSurface = %d",
900 gen8_rt_slot_group(inst) ? "Hi " : "",
901 gen8_rt_last(inst) ? "LastRT " : "",
902 gen8_binding_table_index(inst));
903 break;
904 }
905
906 case GEN6_SFID_DATAPORT_SAMPLER_CACHE:
907 case GEN6_SFID_DATAPORT_CONSTANT_CACHE:
908 case GEN7_SFID_DATAPORT_DATA_CACHE:
909 format(file, " (%d, 0x%x)",
910 gen8_binding_table_index(inst),
911 gen8_function_control(inst));
912 break;
913
914 default:
915 format(file, "unsupported shared function ID (%d)", sfid);
916 break;
917 }
918 if (space)
919 string(file, " ");
920 format(file, "mlen %d", gen8_mlen(inst));
921 format(file, " rlen %d", gen8_rlen(inst));
922 }
923 pad(file, 64);
924 if (opcode != BRW_OPCODE_NOP) {
925 string(file, "{");
926 space = 1;
927 err |= control(file, "access mode", m_access_mode, gen8_access_mode(inst), &space);
928 err |= control(file, "mask control", m_maskctrl, gen8_mask_control(inst), &space);
929 err |= control(file, "DDClr", m_dep_clear, gen8_no_dd_clear(inst), &space);
930 err |= control(file, "DDChk", m_dep_check, gen8_no_dd_check(inst), &space);
931
932 err |= qtr_ctrl(file, inst);
933
934 err |= control(file, "thread control", m_thread_ctrl, gen8_thread_control(inst), &space);
935 err |= control(file, "acc write control", m_accwr, gen8_acc_wr_control(inst), &space);
936 if (opcode == BRW_OPCODE_SEND || opcode == BRW_OPCODE_SENDC)
937 err |= control(file, "end of thread", m_eot, gen8_eot(inst), &space);
938 if (space)
939 string(file, " ");
940 string(file, "}");
941 }
942 string(file, ";");
943 newline(file);
944 return err;
945 }