i965/fs: Move some flags that affect code generation to fs_visitor.
[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 dp_dc1_msg_type[16] = {
226 [HSW_DATAPORT_DC_PORT1_UNTYPED_SURFACE_READ] = "untyped surface read",
227 [HSW_DATAPORT_DC_PORT1_UNTYPED_ATOMIC_OP] = "DC untyped atomic op",
228 [HSW_DATAPORT_DC_PORT1_UNTYPED_ATOMIC_OP_SIMD4X2] = "DC untyped 4x2 atomic op",
229 [HSW_DATAPORT_DC_PORT1_MEDIA_BLOCK_READ] = "DC media block read",
230 [HSW_DATAPORT_DC_PORT1_TYPED_SURFACE_READ] = "DC typed surface read",
231 [HSW_DATAPORT_DC_PORT1_TYPED_ATOMIC_OP] = "DC typed atomic",
232 [HSW_DATAPORT_DC_PORT1_TYPED_ATOMIC_OP_SIMD4X2] = "DC typed 4x2 atomic op",
233 [HSW_DATAPORT_DC_PORT1_UNTYPED_SURFACE_WRITE] = "DC untyped surface write",
234 [HSW_DATAPORT_DC_PORT1_MEDIA_BLOCK_WRITE] = "DC media block write",
235 [HSW_DATAPORT_DC_PORT1_ATOMIC_COUNTER_OP] = "DC atomic counter op",
236 [HSW_DATAPORT_DC_PORT1_ATOMIC_COUNTER_OP_SIMD4X2] = "DC 4x2 atomic counter op",
237 [HSW_DATAPORT_DC_PORT1_TYPED_SURFACE_WRITE] = "DC typed surface write",
238 };
239
240 static const char * const aop[16] = {
241 [BRW_AOP_AND] = "and",
242 [BRW_AOP_OR] = "or",
243 [BRW_AOP_XOR] = "xor",
244 [BRW_AOP_MOV] = "mov",
245 [BRW_AOP_INC] = "inc",
246 [BRW_AOP_DEC] = "dec",
247 [BRW_AOP_ADD] = "add",
248 [BRW_AOP_SUB] = "sub",
249 [BRW_AOP_REVSUB] = "revsub",
250 [BRW_AOP_IMAX] = "imax",
251 [BRW_AOP_IMIN] = "imin",
252 [BRW_AOP_UMAX] = "umax",
253 [BRW_AOP_UMIN] = "umin",
254 [BRW_AOP_CMPWR] = "cmpwr",
255 [BRW_AOP_PREDEC] = "predec",
256 };
257
258 static const char *const m_math_function[16] = {
259 [BRW_MATH_FUNCTION_INV] = "inv",
260 [BRW_MATH_FUNCTION_LOG] = "log",
261 [BRW_MATH_FUNCTION_EXP] = "exp",
262 [BRW_MATH_FUNCTION_SQRT] = "sqrt",
263 [BRW_MATH_FUNCTION_RSQ] = "rsq",
264 [BRW_MATH_FUNCTION_SIN] = "sin",
265 [BRW_MATH_FUNCTION_COS] = "cos",
266 [BRW_MATH_FUNCTION_FDIV] = "fdiv",
267 [BRW_MATH_FUNCTION_POW] = "pow",
268 [BRW_MATH_FUNCTION_INT_DIV_QUOTIENT_AND_REMAINDER] = "intdivmod",
269 [BRW_MATH_FUNCTION_INT_DIV_QUOTIENT] = "intdiv",
270 [BRW_MATH_FUNCTION_INT_DIV_REMAINDER] = "intmod",
271 [GEN8_MATH_FUNCTION_INVM] = "invm",
272 [GEN8_MATH_FUNCTION_RSQRTM] = "rsqrtm",
273 };
274
275 static const char *const m_urb_opcode[16] = {
276 [0] = "write HWord",
277 [1] = "write OWord",
278 [2] = "read HWord",
279 [3] = "read OWord",
280 [4] = "atomic mov",
281 [5] = "atomic inc",
282 [6] = "atomic add",
283 [7] = "SIMD8 write",
284 [8] = "SIMD8 read",
285 /* [9-15] - reserved */
286 };
287
288 static const char *const m_urb_interleave[2] = { "", "interleaved" };
289
290 static const char *const m_rt_opcode[] = {
291 [0] = "SIMD16",
292 [1] = "RepData",
293 [2] = "DualLow",
294 [3] = "DualHigh",
295 [4] = "SIMD8",
296 [5] = "ImageWrite",
297 [6] = "Reserved",
298 [7] = "RepData(7)",
299 };
300
301 static int column;
302
303 static int
304 string(FILE *file, const char *string)
305 {
306 fputs(string, file);
307 column += strlen(string);
308 return 0;
309 }
310
311 static int
312 format(FILE *f, const char *format, ...)
313 {
314 char buf[1024];
315 va_list args;
316 va_start(args, format);
317
318 vsnprintf(buf, sizeof(buf) - 1, format, args);
319 va_end(args);
320 string(f, buf);
321 return 0;
322 }
323
324 static int
325 newline(FILE *f)
326 {
327 putc('\n', f);
328 column = 0;
329 return 0;
330 }
331
332 static int
333 pad(FILE *f, int c)
334 {
335 do
336 string(f, " ");
337 while (column < c);
338 return 0;
339 }
340
341 static int
342 control(FILE *file, const char *name, const char *const ctrl[],
343 unsigned id, int *space)
344 {
345 if (!ctrl[id]) {
346 fprintf(file, "*** invalid %s value %d ", name, id);
347 return 1;
348 }
349 if (ctrl[id][0]) {
350 if (space && *space)
351 string(file, " ");
352 string(file, ctrl[id]);
353 if (space)
354 *space = 1;
355 }
356 return 0;
357 }
358
359 static int
360 print_opcode(FILE *file, int id)
361 {
362 if (!m_opcode[id].name) {
363 format(file, "*** invalid opcode value %d ", id);
364 return 1;
365 }
366 string(file, m_opcode[id].name);
367 return 0;
368 }
369
370 static int
371 reg(FILE *file, unsigned reg_file, unsigned _reg_nr)
372 {
373 int err = 0;
374
375 if (reg_file == BRW_ARCHITECTURE_REGISTER_FILE) {
376 switch (_reg_nr & 0xf0) {
377 case BRW_ARF_NULL:
378 string(file, "null");
379 return -1;
380 case BRW_ARF_ADDRESS:
381 format(file, "a%d", _reg_nr & 0x0f);
382 break;
383 case BRW_ARF_ACCUMULATOR:
384 format(file, "acc%d", _reg_nr & 0x0f);
385 break;
386 case BRW_ARF_FLAG:
387 format(file, "f%d", _reg_nr & 0x0f);
388 break;
389 case BRW_ARF_MASK:
390 format(file, "mask%d", _reg_nr & 0x0f);
391 break;
392 case BRW_ARF_MASK_STACK:
393 format(file, "msd%d", _reg_nr & 0x0f);
394 break;
395 case BRW_ARF_STATE:
396 format(file, "sr%d", _reg_nr & 0x0f);
397 break;
398 case BRW_ARF_CONTROL:
399 format(file, "cr%d", _reg_nr & 0x0f);
400 break;
401 case BRW_ARF_NOTIFICATION_COUNT:
402 format(file, "n%d", _reg_nr & 0x0f);
403 break;
404 case BRW_ARF_IP:
405 string(file, "ip");
406 return -1;
407 break;
408 default:
409 format(file, "ARF%d", _reg_nr);
410 break;
411 }
412 } else {
413 err |= control(file, "src reg file", m_reg_file, reg_file, NULL);
414 format(file, "%d", _reg_nr);
415 }
416 return err;
417 }
418
419 static int
420 dest(FILE *file, struct gen8_instruction *inst)
421 {
422 int err = 0;
423
424 if (gen8_access_mode(inst) == BRW_ALIGN_1) {
425 assert(gen8_dst_address_mode(inst) == BRW_ADDRESS_DIRECT);
426 err |= reg(file, gen8_dst_reg_file(inst), gen8_dst_da_reg_nr(inst));
427 if (err == -1)
428 return 0;
429 if (gen8_dst_da1_subreg_nr(inst))
430 format(file, ".%d", gen8_dst_da1_subreg_nr(inst) /
431 reg_type_size[gen8_dst_reg_type(inst)]);
432 string(file, "<");
433 err |= control(file, "horiz stride", m_horiz_stride, gen8_dst_da1_hstride(inst), NULL);
434 string(file, ">");
435 err |= control(file, "dest reg encoding", m_reg_encoding, gen8_dst_reg_type(inst), NULL);
436 } else {
437 assert(gen8_dst_address_mode(inst) == BRW_ADDRESS_DIRECT);
438 err |= reg(file, gen8_dst_reg_file(inst), gen8_dst_da_reg_nr(inst));
439 if (err == -1)
440 return 0;
441 if (gen8_dst_da16_subreg_nr(inst))
442 format(file, ".%d", gen8_dst_da16_subreg_nr(inst) /
443 reg_type_size[gen8_dst_reg_type(inst)]);
444 string(file, "<1>");
445 err |= control(file, "writemask", m_writemask, gen8_da16_writemask(inst), NULL);
446 err |= control(file, "dest reg encoding", m_reg_encoding, gen8_dst_reg_type(inst), NULL);
447 }
448
449 return 0;
450 }
451
452 static int
453 dest_3src(FILE *file, struct gen8_instruction *inst)
454 {
455 int err = 0;
456
457 err |= reg(file, BRW_GENERAL_REGISTER_FILE, gen8_dst_3src_reg_nr(inst));
458 if (err == -1)
459 return 0;
460 if (gen8_dst_3src_subreg_nr(inst))
461 format(file, ".%d", gen8_dst_3src_subreg_nr(inst));
462 string(file, "<1>");
463 err |= control(file, "writemask", m_writemask, gen8_dst_3src_writemask(inst),
464 NULL);
465 err |= control(file, "dest reg encoding", m_three_source_reg_encoding,
466 gen8_dst_3src_type(inst), NULL);
467
468 return 0;
469 }
470
471 static int
472 src_align1_region(FILE *file, unsigned vert_stride, unsigned _width,
473 unsigned horiz_stride)
474 {
475 int err = 0;
476 string(file, "<");
477 err |= control(file, "vert stride", m_vert_stride, vert_stride, NULL);
478 string(file, ",");
479 err |= control(file, "width", width, _width, NULL);
480 string(file, ",");
481 err |= control(file, "horiz_stride", m_horiz_stride, horiz_stride, NULL);
482 string(file, ">");
483 return err;
484 }
485
486 static int
487 src_swizzle(FILE *file, unsigned x, unsigned y, unsigned z, unsigned w)
488 {
489 int err = 0;
490
491 /* Three kinds of swizzle display:
492 * - identity - nothing printed
493 * - 1->all - print the single channel
494 * - 1->1 - print the mapping
495 */
496 if (x == BRW_CHANNEL_X &&
497 y == BRW_CHANNEL_Y &&
498 z == BRW_CHANNEL_Z &&
499 w == BRW_CHANNEL_W) {
500 ; /* Print nothing */
501 } else if (x == y && x == z && x == w) {
502 string(file, ".");
503 err |= control(file, "channel select", m_chan_sel, x, NULL);
504 } else {
505 string(file, ".");
506 err |= control(file, "channel select", m_chan_sel, x, NULL);
507 err |= control(file, "channel select", m_chan_sel, y, NULL);
508 err |= control(file, "channel select", m_chan_sel, z, NULL);
509 err |= control(file, "channel select", m_chan_sel, w, NULL);
510 }
511 return err;
512 }
513
514 static int
515 src_da1(FILE *file, unsigned type, unsigned reg_file,
516 unsigned vert_stride, unsigned _width, unsigned horiz_stride,
517 unsigned reg_num, unsigned sub_reg_num, unsigned _abs, unsigned negate)
518 {
519 int err = 0;
520 err |= control(file, "negate", m_negate, negate, NULL);
521 err |= control(file, "abs", m_abs, _abs, NULL);
522
523 err |= reg(file, reg_file, reg_num);
524 if (err == -1)
525 return 0;
526 if (sub_reg_num)
527 format(file, ".%d", sub_reg_num / reg_type_size[type]); /* use formal style like spec */
528 src_align1_region(file, vert_stride, _width, horiz_stride);
529 err |= control(file, "src reg encoding", m_reg_encoding, type, NULL);
530 return err;
531 }
532
533 static int
534 src_da16(FILE *file,
535 unsigned _reg_type,
536 unsigned reg_file,
537 unsigned vert_stride,
538 unsigned _reg_nr,
539 unsigned _subreg_nr,
540 unsigned _abs,
541 unsigned negate,
542 unsigned swz_x,
543 unsigned swz_y,
544 unsigned swz_z,
545 unsigned swz_w)
546 {
547 int err = 0;
548 err |= control(file, "negate", m_negate, negate, NULL);
549 err |= control(file, "abs", m_abs, _abs, NULL);
550
551 err |= reg(file, reg_file, _reg_nr);
552 if (err == -1)
553 return 0;
554 if (_subreg_nr)
555 /* bit4 for subreg number byte addressing. Make this same meaning as
556 * in da1 case, so output looks consistent.
557 */
558 format(file, ".%d", 16 / reg_type_size[_reg_type]);
559 string(file, "<");
560 err |= control(file, "vert stride", m_vert_stride, vert_stride, NULL);
561 string(file, ",4,1>");
562 /*
563 * Three kinds of swizzle display:
564 * identity - nothing printed
565 * 1->all - print the single channel
566 * 1->1 - print the mapping
567 */
568 if (swz_x == BRW_CHANNEL_X &&
569 swz_y == BRW_CHANNEL_Y &&
570 swz_z == BRW_CHANNEL_Z &&
571 swz_w == BRW_CHANNEL_W) {
572 ; /* Print nothing */
573 } else if (swz_x == swz_y && swz_x == swz_z && swz_x == swz_w) {
574 string(file, ".");
575 err |= control(file, "channel select", m_chan_sel, swz_x, NULL);
576 } else {
577 string(file, ".");
578 err |= control(file, "channel select", m_chan_sel, swz_x, NULL);
579 err |= control(file, "channel select", m_chan_sel, swz_y, NULL);
580 err |= control(file, "channel select", m_chan_sel, swz_z, NULL);
581 err |= control(file, "channel select", m_chan_sel, swz_w, NULL);
582 }
583 err |= control(file, "src da16 reg type", m_reg_encoding, _reg_type, NULL);
584 return err;
585 }
586
587 static int
588 src0_3src(FILE *file, struct gen8_instruction *inst)
589 {
590 int err = 0;
591 unsigned swiz = gen8_src0_3src_swizzle(inst);
592 unsigned swz_x = (swiz >> 0) & 0x3;
593 unsigned swz_y = (swiz >> 2) & 0x3;
594 unsigned swz_z = (swiz >> 4) & 0x3;
595 unsigned swz_w = (swiz >> 6) & 0x3;
596
597 err |= control(file, "negate", m_negate, gen8_src0_3src_negate(inst), NULL);
598 err |= control(file, "abs", m_abs, gen8_src0_3src_abs(inst), NULL);
599
600 err |= reg(file, BRW_GENERAL_REGISTER_FILE, gen8_src0_3src_reg_nr(inst));
601 if (err == -1)
602 return 0;
603 if (gen8_src0_3src_subreg_nr(inst))
604 format(file, ".%d", gen8_src0_3src_subreg_nr(inst));
605 if (gen8_src0_3src_rep_ctrl(inst))
606 string(file, "<0,1,0>");
607 else
608 string(file, "<4,4,1>");
609 err |= control(file, "src da16 reg type", m_three_source_reg_encoding,
610 gen8_src_3src_type(inst), NULL);
611 err |= src_swizzle(file, swz_x, swz_y, swz_z, swz_w);
612 return err;
613 }
614
615 static int
616 src1_3src(FILE *file, struct gen8_instruction *inst)
617 {
618 int err = 0;
619 unsigned swiz = gen8_src1_3src_swizzle(inst);
620 unsigned swz_x = (swiz >> 0) & 0x3;
621 unsigned swz_y = (swiz >> 2) & 0x3;
622 unsigned swz_z = (swiz >> 4) & 0x3;
623 unsigned swz_w = (swiz >> 6) & 0x3;
624 unsigned src1_subreg_nr = gen8_src1_3src_subreg_nr(inst);
625
626 err |= control(file, "negate", m_negate, gen8_src1_3src_negate(inst), NULL);
627 err |= control(file, "abs", m_abs, gen8_src1_3src_abs(inst), NULL);
628
629 err |= reg(file, BRW_GENERAL_REGISTER_FILE, gen8_src1_3src_reg_nr(inst));
630 if (err == -1)
631 return 0;
632 if (src1_subreg_nr)
633 format(file, ".%d", src1_subreg_nr);
634 if (gen8_src1_3src_rep_ctrl(inst))
635 string(file, "<0,1,0>");
636 else
637 string(file, "<4,4,1>");
638 err |= control(file, "src da16 reg type", m_three_source_reg_encoding,
639 gen8_src_3src_type(inst), NULL);
640 err |= src_swizzle(file, swz_x, swz_y, swz_z, swz_w);
641 return err;
642 }
643
644 static int
645 src2_3src(FILE *file, struct gen8_instruction *inst)
646 {
647 int err = 0;
648 unsigned swiz = gen8_src2_3src_swizzle(inst);
649 unsigned swz_x = (swiz >> 0) & 0x3;
650 unsigned swz_y = (swiz >> 2) & 0x3;
651 unsigned swz_z = (swiz >> 4) & 0x3;
652 unsigned swz_w = (swiz >> 6) & 0x3;
653
654 err |= control(file, "negate", m_negate, gen8_src2_3src_negate(inst), NULL);
655 err |= control(file, "abs", m_abs, gen8_src2_3src_abs(inst), NULL);
656
657 err |= reg(file, BRW_GENERAL_REGISTER_FILE, gen8_src2_3src_reg_nr(inst));
658 if (err == -1)
659 return 0;
660 if (gen8_src2_3src_subreg_nr(inst))
661 format(file, ".%d", gen8_src2_3src_subreg_nr(inst));
662 if (gen8_src2_3src_rep_ctrl(inst))
663 string(file, "<0,1,0>");
664 else
665 string(file, "<4,4,1>");
666 err |= control(file, "src da16 reg type", m_three_source_reg_encoding,
667 gen8_src_3src_type(inst), NULL);
668 err |= src_swizzle(file, swz_x, swz_y, swz_z, swz_w);
669 return err;
670 }
671
672 static int
673 imm(FILE *file, unsigned type, struct gen8_instruction *inst)
674 {
675 switch (type) {
676 case BRW_HW_REG_TYPE_UD:
677 format(file, "0x%08xUD", gen8_src1_imm_ud(inst));
678 break;
679 case BRW_HW_REG_TYPE_D:
680 format(file, "%dD", gen8_src1_imm_d(inst));
681 break;
682 case BRW_HW_REG_TYPE_UW:
683 format(file, "0x%04xUW", (uint16_t) gen8_src1_imm_ud(inst));
684 break;
685 case BRW_HW_REG_TYPE_W:
686 format(file, "%dW", (int16_t) gen8_src1_imm_d(inst));
687 break;
688 case BRW_HW_REG_IMM_TYPE_UV:
689 format(file, "0x%08xUV", gen8_src1_imm_ud(inst));
690 break;
691 case BRW_HW_REG_IMM_TYPE_VF:
692 format(file, "Vector Float");
693 break;
694 case BRW_HW_REG_IMM_TYPE_V:
695 format(file, "0x%08xV", gen8_src1_imm_ud(inst));
696 break;
697 case BRW_HW_REG_TYPE_F:
698 format(file, "%-gF", gen8_src1_imm_f(inst));
699 break;
700 case GEN8_HW_REG_IMM_TYPE_DF:
701 case GEN8_HW_REG_IMM_TYPE_HF:
702 assert(!"Not implemented yet");
703 break;
704 }
705 return 0;
706 }
707
708 static int
709 src0(FILE *file, struct gen8_instruction *inst)
710 {
711 if (gen8_src0_reg_file(inst) == BRW_IMMEDIATE_VALUE)
712 return imm(file, gen8_src0_reg_type(inst), inst);
713
714 if (gen8_access_mode(inst) == BRW_ALIGN_1) {
715 assert(gen8_src0_address_mode(inst) == BRW_ADDRESS_DIRECT);
716 return src_da1(file,
717 gen8_src0_reg_type(inst),
718 gen8_src0_reg_file(inst),
719 gen8_src0_vert_stride(inst),
720 gen8_src0_da1_width(inst),
721 gen8_src0_da1_hstride(inst),
722 gen8_src0_da_reg_nr(inst),
723 gen8_src0_da1_subreg_nr(inst),
724 gen8_src0_abs(inst),
725 gen8_src0_negate(inst));
726 } else {
727 assert(gen8_src0_address_mode(inst) == BRW_ADDRESS_DIRECT);
728 return src_da16(file,
729 gen8_src0_reg_type(inst),
730 gen8_src0_reg_file(inst),
731 gen8_src0_vert_stride(inst),
732 gen8_src0_da_reg_nr(inst),
733 gen8_src0_da16_subreg_nr(inst),
734 gen8_src0_abs(inst),
735 gen8_src0_negate(inst),
736 gen8_src0_da16_swiz_x(inst),
737 gen8_src0_da16_swiz_y(inst),
738 gen8_src0_da16_swiz_z(inst),
739 gen8_src0_da16_swiz_w(inst));
740 }
741 }
742
743 static int
744 src1(FILE *file, struct gen8_instruction *inst)
745 {
746 if (gen8_src1_reg_file(inst) == BRW_IMMEDIATE_VALUE)
747 return imm(file, gen8_src1_reg_type(inst), inst);
748
749 if (gen8_access_mode(inst) == BRW_ALIGN_1) {
750 assert(gen8_src1_address_mode(inst) == BRW_ADDRESS_DIRECT);
751 return src_da1(file,
752 gen8_src1_reg_type(inst),
753 gen8_src1_reg_file(inst),
754 gen8_src1_vert_stride(inst),
755 gen8_src1_da1_width(inst),
756 gen8_src1_da1_hstride(inst),
757 gen8_src1_da_reg_nr(inst),
758 gen8_src1_da1_subreg_nr(inst),
759 gen8_src1_abs(inst),
760 gen8_src1_negate(inst));
761 } else {
762 assert(gen8_src1_address_mode(inst) == BRW_ADDRESS_DIRECT);
763 return src_da16(file,
764 gen8_src1_reg_type(inst),
765 gen8_src1_reg_file(inst),
766 gen8_src1_vert_stride(inst),
767 gen8_src1_da_reg_nr(inst),
768 gen8_src1_da16_subreg_nr(inst),
769 gen8_src1_abs(inst),
770 gen8_src1_negate(inst),
771 gen8_src1_da16_swiz_x(inst),
772 gen8_src1_da16_swiz_y(inst),
773 gen8_src1_da16_swiz_z(inst),
774 gen8_src1_da16_swiz_w(inst));
775 }
776 }
777
778 static int
779 qtr_ctrl(FILE *file, struct gen8_instruction *inst)
780 {
781 int qtr_ctl = gen8_qtr_control(inst);
782 int exec_size = 1 << gen8_exec_size(inst);
783
784 if (exec_size == 8) {
785 switch (qtr_ctl) {
786 case 0:
787 string(file, " 1Q");
788 break;
789 case 1:
790 string(file, " 2Q");
791 break;
792 case 2:
793 string(file, " 3Q");
794 break;
795 case 3:
796 string(file, " 4Q");
797 break;
798 }
799 } else if (exec_size == 16) {
800 if (qtr_ctl < 2)
801 string(file, " 1H");
802 else
803 string(file, " 2H");
804 }
805 return 0;
806 }
807
808 int
809 gen8_disassemble_inst(FILE *file, struct gen8_instruction *inst, int gen)
810 {
811 int err = 0;
812 int space = 0;
813
814 const int opcode = gen8_opcode(inst);
815
816 if (gen8_pred_control(inst)) {
817 string(file, "(");
818 err |= control(file, "predicate inverse", m_pred_inv, gen8_pred_inv(inst), NULL);
819 format(file, "f%d", gen8_flag_reg_nr(inst));
820 if (gen8_flag_subreg_nr(inst))
821 format(file, ".%d", gen8_flag_subreg_nr(inst));
822 if (gen8_access_mode(inst) == BRW_ALIGN_1) {
823 err |= control(file, "predicate control align1", m_pred_ctrl_align1,
824 gen8_pred_control(inst), NULL);
825 } else {
826 err |= control(file, "predicate control align16", m_pred_ctrl_align16,
827 gen8_pred_control(inst), NULL);
828 }
829 string(file, ") ");
830 }
831
832 err |= print_opcode(file, opcode);
833 err |= control(file, "saturate", m_saturate, gen8_saturate(inst), NULL);
834 err |= control(file, "debug control", m_debug_ctrl, gen8_debug_control(inst), NULL);
835
836 if (opcode == BRW_OPCODE_MATH) {
837 string(file, " ");
838 err |= control(file, "function", m_math_function, gen8_math_function(inst),
839 NULL);
840 } else if (opcode != BRW_OPCODE_SEND && opcode != BRW_OPCODE_SENDC) {
841 err |= control(file, "conditional modifier", m_conditional_modifier,
842 gen8_cond_modifier(inst), NULL);
843
844 /* If we're using the conditional modifier, print the flag reg used. */
845 if (gen8_cond_modifier(inst) && opcode != BRW_OPCODE_SEL) {
846 format(file, ".f%d", gen8_flag_reg_nr(inst));
847 if (gen8_flag_subreg_nr(inst))
848 format(file, ".%d", gen8_flag_subreg_nr(inst));
849 }
850 }
851
852 if (opcode != BRW_OPCODE_NOP) {
853 string(file, "(");
854 err |= control(file, "execution size", m_exec_size, gen8_exec_size(inst), NULL);
855 string(file, ")");
856 }
857
858 if (m_opcode[opcode].nsrc == 3) {
859 pad(file, 16);
860 err |= dest_3src(file, inst);
861
862 pad(file, 32);
863 err |= src0_3src(file, inst);
864
865 pad(file, 48);
866 err |= src1_3src(file, inst);
867
868 pad(file, 64);
869 err |= src2_3src(file, inst);
870 } else {
871 if (opcode == BRW_OPCODE_ENDIF || opcode == BRW_OPCODE_WHILE) {
872 pad(file, 16);
873 format(file, "JIP: %d", gen8_jip(inst));
874 } else if (opcode == BRW_OPCODE_IF ||
875 opcode == BRW_OPCODE_ELSE ||
876 opcode == BRW_OPCODE_BREAK ||
877 opcode == BRW_OPCODE_CONTINUE ||
878 opcode == BRW_OPCODE_HALT) {
879 pad(file, 16);
880 format(file, "JIP: %d", gen8_jip(inst));
881 pad(file, 32);
882 format(file, "UIP: %d", gen8_uip(inst));
883 } else {
884 if (m_opcode[opcode].ndst > 0) {
885 pad(file, 16);
886 err |= dest(file, inst);
887 }
888 if (m_opcode[opcode].nsrc > 0) {
889 pad(file, 32);
890 err |= src0(file, inst);
891 }
892 if (m_opcode[opcode].nsrc > 1) {
893 pad(file, 48);
894 err |= src1(file, inst);
895 }
896 }
897 }
898
899 if (opcode == BRW_OPCODE_SEND || opcode == BRW_OPCODE_SENDC) {
900 const int sfid = gen8_sfid(inst);
901
902 newline(file);
903 pad(file, 16);
904 space = 0;
905
906 err |= control(file, "SFID", m_sfid, sfid, &space);
907
908 switch (sfid) {
909 case BRW_SFID_SAMPLER:
910 format(file, " (%d, %d, %d, %d)",
911 gen8_binding_table_index(inst),
912 gen8_sampler(inst),
913 gen8_sampler_msg_type(inst),
914 gen8_sampler_simd_mode(inst));
915 break;
916
917 case BRW_SFID_URB:
918 space = 1;
919 err |= control(file, "urb opcode", m_urb_opcode,
920 gen8_urb_opcode(inst), &space);
921 err |= control(file, "urb interleave", m_urb_interleave,
922 gen8_urb_interleave(inst), &space);
923 format(file, " %d %d",
924 gen8_urb_global_offset(inst), gen8_urb_per_slot_offset(inst));
925 break;
926
927 case GEN6_SFID_DATAPORT_RENDER_CACHE: {
928 err |= control(file, "rt message", m_rt_opcode,
929 gen8_rt_message_type(inst), &space);
930 format(file, " %s%sSurface = %d",
931 gen8_rt_slot_group(inst) ? "Hi " : "",
932 gen8_rt_last(inst) ? "LastRT " : "",
933 gen8_binding_table_index(inst));
934 break;
935 }
936
937 case GEN6_SFID_DATAPORT_SAMPLER_CACHE:
938 case GEN6_SFID_DATAPORT_CONSTANT_CACHE:
939 case GEN7_SFID_DATAPORT_DATA_CACHE:
940 format(file, " (%d, 0x%x)",
941 gen8_binding_table_index(inst),
942 gen8_function_control(inst));
943 break;
944
945 case HSW_SFID_DATAPORT_DATA_CACHE_1:
946 err |= control(file, "DP DC1 message type",
947 dp_dc1_msg_type, gen8_dp_message_type(inst), &space);
948 format(file, ", Surface = %d, ", gen8_binding_table_index(inst));
949 switch (gen8_dp_message_type(inst)) {
950 case HSW_DATAPORT_DC_PORT1_UNTYPED_ATOMIC_OP:
951 case HSW_DATAPORT_DC_PORT1_TYPED_ATOMIC_OP:
952 case HSW_DATAPORT_DC_PORT1_ATOMIC_COUNTER_OP:
953 format(file, "SIMD%d,",
954 (gen8_dp_message_control(inst) & (1 << 4)) ? 8 : 16);
955 /* fallthrough */
956 case HSW_DATAPORT_DC_PORT1_UNTYPED_ATOMIC_OP_SIMD4X2:
957 case HSW_DATAPORT_DC_PORT1_TYPED_ATOMIC_OP_SIMD4X2:
958 case HSW_DATAPORT_DC_PORT1_ATOMIC_COUNTER_OP_SIMD4X2:
959 control(file, "atomic op", aop,
960 gen8_dp_message_control(inst) & 0xf, &space);
961 break;
962 case HSW_DATAPORT_DC_PORT1_UNTYPED_SURFACE_READ:
963 case HSW_DATAPORT_DC_PORT1_UNTYPED_SURFACE_WRITE:
964 case HSW_DATAPORT_DC_PORT1_TYPED_SURFACE_READ:
965 case HSW_DATAPORT_DC_PORT1_TYPED_SURFACE_WRITE: {
966 static const char *simd_modes[] = { "4x2", "16", "8" };
967 unsigned msg_ctrl = gen8_dp_message_control(inst);
968 format(file, "SIMD%s, Mask = 0x%x",
969 simd_modes[msg_ctrl >> 4], msg_ctrl & 0xf);
970 break;
971 }
972 default:
973 format(file, "0x%x", gen8_dp_message_control(inst));
974 }
975 break;
976
977 default:
978 format(file, "unsupported shared function ID (%d)", sfid);
979 break;
980 }
981 if (space)
982 string(file, " ");
983 format(file, "mlen %d", gen8_mlen(inst));
984 format(file, " rlen %d", gen8_rlen(inst));
985 }
986 pad(file, 64);
987 if (opcode != BRW_OPCODE_NOP) {
988 string(file, "{");
989 space = 1;
990 err |= control(file, "access mode", m_access_mode, gen8_access_mode(inst), &space);
991 err |= control(file, "mask control", m_maskctrl, gen8_mask_control(inst), &space);
992 err |= control(file, "DDClr", m_dep_clear, gen8_no_dd_clear(inst), &space);
993 err |= control(file, "DDChk", m_dep_check, gen8_no_dd_check(inst), &space);
994
995 err |= qtr_ctrl(file, inst);
996
997 err |= control(file, "thread control", m_thread_ctrl, gen8_thread_control(inst), &space);
998 err |= control(file, "acc write control", m_accwr, gen8_acc_wr_control(inst), &space);
999 if (opcode == BRW_OPCODE_SEND || opcode == BRW_OPCODE_SENDC)
1000 err |= control(file, "end of thread", m_eot, gen8_eot(inst), &space);
1001 if (space)
1002 string(file, " ");
1003 string(file, "}");
1004 }
1005 string(file, ";");
1006 newline(file);
1007 return err;
1008 }