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