ilo: cleanup ISA DW1 decoding
[mesa.git] / src / gallium / drivers / ilo / shader / toy_compiler_disasm.c
1 /*
2 * Mesa 3-D graphics library
3 *
4 * Copyright (C) 2014 LunarG, Inc.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included
14 * in all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 * DEALINGS IN THE SOFTWARE.
23 *
24 * Authors:
25 * Chia-I Wu <olv@lunarg.com>
26 */
27
28 #include <stdio.h>
29 #include "genhw/genhw.h"
30 #include "toy_compiler.h"
31
32 #define DISASM_PRINTER_BUFFER_SIZE 256
33 #define DISASM_PRINTER_COLUMN_WIDTH 16
34
35 struct disasm_printer {
36 char buf[DISASM_PRINTER_BUFFER_SIZE];
37 int len;
38 };
39
40 struct disasm_operand {
41 unsigned file:2;
42 unsigned type:4;
43
44 unsigned addr_mode:1;
45 unsigned reg:8;
46 unsigned subreg:5;
47 unsigned addr_subreg:3;
48 unsigned addr_imm:10;
49 };
50
51 struct disasm_dst_operand {
52 struct disasm_operand base;
53
54 unsigned horz_stride:2;
55 unsigned writemask:4;
56 };
57
58 struct disasm_src_operand {
59 struct disasm_operand base;
60
61 unsigned vert_stride:4;
62 unsigned width:3;
63 unsigned horz_stride:2;
64 unsigned swizzle_x:2;
65 unsigned swizzle_y:2;
66 unsigned swizzle_z:2;
67 unsigned swizzle_w:2;
68 unsigned negate:1;
69 unsigned absolute:1;
70 };
71
72 struct disasm_inst {
73 const struct ilo_dev_info *dev;
74
75 unsigned has_jip:1;
76 unsigned has_uip:1;
77
78 unsigned opcode:7;
79 unsigned access_mode:1;
80 unsigned mask_ctrl:1;
81 unsigned dep_ctrl:2;
82 unsigned qtr_ctrl:2;
83 unsigned thread_ctrl:2;
84 unsigned pred_ctrl:4;
85 unsigned pred_inv:1;
86 unsigned exec_size:3;
87
88 unsigned cond_modifier:4;
89 unsigned sfid:4;
90 unsigned fc:4;
91
92 unsigned acc_wr_ctrl:1;
93 unsigned branch_ctrl:1;
94
95 unsigned cmpt_ctrl:1;
96 unsigned debug_ctrl:1;
97 unsigned saturate:1;
98
99 unsigned nib_ctrl:1;
100
101 unsigned flag_reg:1;
102 unsigned flag_subreg:1;
103
104 struct disasm_dst_operand dst;
105 struct disasm_src_operand src0;
106 struct disasm_src_operand src1;
107 union {
108 struct disasm_src_operand src2;
109 uint32_t imm32;
110 } u;
111 };
112
113 static const struct {
114 const char *name;
115 int src_count;
116 } disasm_opcode_table[128] = {
117 [GEN6_OPCODE_ILLEGAL] = { "illegal", 0 },
118 [GEN6_OPCODE_MOV] = { "mov", 1 },
119 [GEN6_OPCODE_SEL] = { "sel", 2 },
120 [GEN6_OPCODE_MOVI] = { "movi", 1 },
121 [GEN6_OPCODE_NOT] = { "not", 1 },
122 [GEN6_OPCODE_AND] = { "and", 2 },
123 [GEN6_OPCODE_OR] = { "or", 2 },
124 [GEN6_OPCODE_XOR] = { "xor", 2 },
125 [GEN6_OPCODE_SHR] = { "shr", 2 },
126 [GEN6_OPCODE_SHL] = { "shl", 2 },
127 [GEN6_OPCODE_DIM] = { "dim", 1 },
128 [GEN6_OPCODE_ASR] = { "asr", 2 },
129 [GEN6_OPCODE_CMP] = { "cmp", 2 },
130 [GEN6_OPCODE_CMPN] = { "cmpn", 2 },
131 [GEN7_OPCODE_CSEL] = { "csel", 3 },
132 [GEN7_OPCODE_F32TO16] = { "f32to16", 1 },
133 [GEN7_OPCODE_F16TO32] = { "f16to32", 1 },
134 [GEN7_OPCODE_BFREV] = { "bfrev", 1 },
135 [GEN7_OPCODE_BFE] = { "bfe", 3 },
136 [GEN7_OPCODE_BFI1] = { "bfi1", 2 },
137 [GEN7_OPCODE_BFI2] = { "bfi2", 3 },
138 [GEN6_OPCODE_JMPI] = { "jmpi", 1 },
139 [GEN7_OPCODE_BRD] = { "brd", 1 },
140 [GEN6_OPCODE_IF] = { "if", 2 },
141 [GEN7_OPCODE_BRC] = { "brc", 1 },
142 [GEN6_OPCODE_ELSE] = { "else", 1 },
143 [GEN6_OPCODE_ENDIF] = { "endif", 0 },
144 [GEN6_OPCODE_CASE] = { "case", 2 },
145 [GEN6_OPCODE_WHILE] = { "while", 1 },
146 [GEN6_OPCODE_BREAK] = { "break", 1 },
147 [GEN6_OPCODE_CONT] = { "cont", 1 },
148 [GEN6_OPCODE_HALT] = { "halt", 1 },
149 [GEN75_OPCODE_CALLA] = { "calla", 1 },
150 [GEN6_OPCODE_CALL] = { "call", 1 },
151 [GEN6_OPCODE_RETURN] = { "return", 1 },
152 [GEN8_OPCODE_GOTO] = { "goto", 1 },
153 [GEN6_OPCODE_WAIT] = { "wait", 1 },
154 [GEN6_OPCODE_SEND] = { "send", 1 },
155 [GEN6_OPCODE_SENDC] = { "sendc", 1 },
156 [GEN6_OPCODE_MATH] = { "math", 2 },
157 [GEN6_OPCODE_ADD] = { "add", 2 },
158 [GEN6_OPCODE_MUL] = { "mul", 2 },
159 [GEN6_OPCODE_AVG] = { "avg", 2 },
160 [GEN6_OPCODE_FRC] = { "frc", 1 },
161 [GEN6_OPCODE_RNDU] = { "rndu", 1 },
162 [GEN6_OPCODE_RNDD] = { "rndd", 1 },
163 [GEN6_OPCODE_RNDE] = { "rnde", 1 },
164 [GEN6_OPCODE_RNDZ] = { "rndz", 1 },
165 [GEN6_OPCODE_MAC] = { "mac", 2 },
166 [GEN6_OPCODE_MACH] = { "mach", 2 },
167 [GEN6_OPCODE_LZD] = { "lzd", 1 },
168 [GEN7_OPCODE_FBH] = { "fbh", 1 },
169 [GEN7_OPCODE_FBL] = { "fbl", 1 },
170 [GEN7_OPCODE_CBIT] = { "cbit", 1 },
171 [GEN7_OPCODE_ADDC] = { "addc", 2 },
172 [GEN7_OPCODE_SUBB] = { "subb", 2 },
173 [GEN6_OPCODE_SAD2] = { "sad2", 2 },
174 [GEN6_OPCODE_SADA2] = { "sada2", 2 },
175 [GEN6_OPCODE_DP4] = { "dp4", 2 },
176 [GEN6_OPCODE_DPH] = { "dph", 2 },
177 [GEN6_OPCODE_DP3] = { "dp3", 2 },
178 [GEN6_OPCODE_DP2] = { "dp2", 2 },
179 [GEN6_OPCODE_LINE] = { "line", 2 },
180 [GEN6_OPCODE_PLN] = { "pln", 2 },
181 [GEN6_OPCODE_MAD] = { "mad", 3 },
182 [GEN6_OPCODE_LRP] = { "lrp", 3 },
183 [GEN6_OPCODE_NOP] = { "nop", 0 },
184 };
185
186 static void
187 disasm_inst_decode_dw0_opcode_gen6(struct disasm_inst *inst, uint32_t dw0)
188 {
189 ILO_DEV_ASSERT(inst->dev, 6, 8);
190
191 inst->opcode = GEN_EXTRACT(dw0, GEN6_INST_OPCODE);
192
193 switch (inst->opcode) {
194 case GEN6_OPCODE_IF:
195 inst->has_jip = true;
196 inst->has_uip = (ilo_dev_gen(inst->dev) >= ILO_GEN(7));
197 break;
198 case GEN6_OPCODE_ELSE:
199 inst->has_jip = true;
200 inst->has_uip = (ilo_dev_gen(inst->dev) >= ILO_GEN(8));
201 break;
202 case GEN6_OPCODE_BREAK:
203 case GEN6_OPCODE_CONT:
204 case GEN6_OPCODE_HALT:
205 inst->has_uip = true;
206 /* fall through */
207 case GEN6_OPCODE_JMPI:
208 case GEN7_OPCODE_BRD:
209 case GEN7_OPCODE_BRC:
210 case GEN6_OPCODE_ENDIF:
211 case GEN6_OPCODE_CASE:
212 case GEN6_OPCODE_WHILE:
213 case GEN75_OPCODE_CALLA:
214 case GEN6_OPCODE_CALL:
215 case GEN6_OPCODE_RETURN:
216 inst->has_jip = true;
217 break;
218 default:
219 break;
220 }
221 }
222
223 static void
224 disasm_inst_decode_dw0_gen6(struct disasm_inst *inst, uint32_t dw0)
225 {
226 ILO_DEV_ASSERT(inst->dev, 6, 8);
227
228 disasm_inst_decode_dw0_opcode_gen6(inst, dw0);
229
230 inst->access_mode = GEN_EXTRACT(dw0, GEN6_INST_ACCESSMODE);
231
232 if (ilo_dev_gen(inst->dev) >= ILO_GEN(8)) {
233 inst->dep_ctrl = GEN_EXTRACT(dw0, GEN8_INST_DEPCTRL);
234 inst->nib_ctrl = (bool) (dw0 & GEN8_INST_NIBCTRL);
235 } else {
236 inst->mask_ctrl = GEN_EXTRACT(dw0, GEN6_INST_MASKCTRL);
237 inst->dep_ctrl = GEN_EXTRACT(dw0, GEN6_INST_DEPCTRL);
238 }
239
240 inst->qtr_ctrl = GEN_EXTRACT(dw0, GEN6_INST_QTRCTRL);
241 inst->thread_ctrl = GEN_EXTRACT(dw0, GEN6_INST_THREADCTRL);
242 inst->pred_ctrl = GEN_EXTRACT(dw0, GEN6_INST_PREDCTRL);
243
244 inst->pred_inv = (bool) (dw0 & GEN6_INST_PREDINV);
245
246 inst->exec_size = GEN_EXTRACT(dw0, GEN6_INST_EXECSIZE);
247
248 switch (inst->opcode) {
249 case GEN6_OPCODE_SEND:
250 case GEN6_OPCODE_SENDC:
251 inst->sfid = GEN_EXTRACT(dw0, GEN6_INST_SFID);
252 break;
253 case GEN6_OPCODE_MATH:
254 inst->fc = GEN_EXTRACT(dw0, GEN6_INST_FC);
255 break;
256 default:
257 inst->cond_modifier = GEN_EXTRACT(dw0, GEN6_INST_CONDMODIFIER);
258 break;
259 }
260
261 switch (inst->opcode) {
262 case GEN6_OPCODE_IF:
263 case GEN6_OPCODE_ELSE:
264 case GEN8_OPCODE_GOTO:
265 if (ilo_dev_gen(inst->dev) >= ILO_GEN(8)) {
266 inst->branch_ctrl = (bool) (dw0 & GEN8_INST_BRANCHCTRL);
267 break;
268 }
269 default:
270 inst->acc_wr_ctrl = (bool) (dw0 & GEN6_INST_ACCWRCTRL);
271 break;
272 }
273
274 inst->cmpt_ctrl = (bool) (dw0 & GEN6_INST_CMPTCTRL);
275 inst->debug_ctrl = (bool) (dw0 & GEN6_INST_DEBUGCTRL);
276 inst->saturate = (bool) (dw0 & GEN6_INST_SATURATE);
277 }
278
279 static bool
280 disasm_inst_jip_in_dw1_high_gen6(const struct disasm_inst *inst)
281 {
282 return (ilo_dev_gen(inst->dev) == ILO_GEN(6) &&
283 inst->has_jip && !inst->has_uip);
284 }
285
286 static void
287 disasm_inst_decode_dw1_low_gen6(struct disasm_inst *inst, uint32_t dw1)
288 {
289 ILO_DEV_ASSERT(inst->dev, 6, 7.5);
290
291 inst->dst.base.file = GEN_EXTRACT(dw1, GEN6_INST_DST_FILE);
292 inst->dst.base.type = GEN_EXTRACT(dw1, GEN6_INST_DST_TYPE);
293 inst->src0.base.file = GEN_EXTRACT(dw1, GEN6_INST_SRC0_FILE);
294 inst->src0.base.type = GEN_EXTRACT(dw1, GEN6_INST_SRC0_TYPE);
295 inst->src1.base.file = GEN_EXTRACT(dw1, GEN6_INST_SRC1_FILE);
296 inst->src1.base.type = GEN_EXTRACT(dw1, GEN6_INST_SRC1_TYPE);
297
298 if (ilo_dev_gen(inst->dev) >= ILO_GEN(7))
299 inst->nib_ctrl = (bool) (dw1 & GEN7_INST_NIBCTRL);
300 }
301
302 static void
303 disasm_inst_decode_dw1_low_gen8(struct disasm_inst *inst, uint32_t dw1)
304 {
305 ILO_DEV_ASSERT(inst->dev, 8, 8);
306
307 inst->flag_subreg = GEN_EXTRACT(dw1, GEN8_INST_FLAG_SUBREG);
308 inst->flag_reg = GEN_EXTRACT(dw1, GEN8_INST_FLAG_REG);
309 inst->mask_ctrl = GEN_EXTRACT(dw1, GEN8_INST_MASKCTRL);
310
311 inst->dst.base.file = GEN_EXTRACT(dw1, GEN8_INST_DST_FILE);
312 inst->dst.base.type = GEN_EXTRACT(dw1, GEN8_INST_DST_TYPE);
313 inst->src0.base.file = GEN_EXTRACT(dw1, GEN8_INST_SRC0_FILE);
314 inst->src0.base.type = GEN_EXTRACT(dw1, GEN8_INST_SRC0_TYPE);
315
316 inst->dst.base.addr_imm = GEN_EXTRACT(dw1, GEN8_INST_DST_ADDR_IMM_BIT9) <<
317 GEN8_INST_DST_ADDR_IMM_BIT9__SHR;
318 }
319
320 static void
321 disasm_inst_decode_dw1_high_gen6(struct disasm_inst *inst, uint32_t dw1)
322 {
323 ILO_DEV_ASSERT(inst->dev, 6, 8);
324
325 inst->dst.base.addr_mode = GEN_EXTRACT(dw1, GEN6_INST_DST_ADDRMODE);
326
327 if (inst->dst.base.addr_mode == GEN6_ADDRMODE_DIRECT) {
328 inst->dst.base.reg = GEN_EXTRACT(dw1, GEN6_INST_DST_REG);
329
330 if (inst->access_mode == GEN6_ALIGN_1) {
331 inst->dst.base.subreg = GEN_EXTRACT(dw1, GEN6_INST_DST_SUBREG);
332 } else {
333 inst->dst.base.subreg =
334 GEN_EXTRACT(dw1, GEN6_INST_DST_SUBREG_ALIGN16) <<
335 GEN6_INST_DST_SUBREG_ALIGN16__SHR;
336 }
337 } else {
338 if (ilo_dev_gen(inst->dev) >= ILO_GEN(8)) {
339 inst->dst.base.addr_subreg =
340 GEN_EXTRACT(dw1, GEN8_INST_DST_ADDR_SUBREG);
341
342 /* bit 9 is already set in disasm_inst_decode_dw1_low_gen8() */
343 if (inst->access_mode == GEN6_ALIGN_1) {
344 inst->dst.base.addr_imm |=
345 GEN_EXTRACT(dw1, GEN8_INST_DST_ADDR_IMM);
346 } else {
347 inst->dst.base.addr_imm |=
348 GEN_EXTRACT(dw1, GEN8_INST_DST_ADDR_IMM_ALIGN16) <<
349 GEN8_INST_DST_ADDR_IMM_ALIGN16__SHR;
350 }
351 } else {
352 inst->dst.base.addr_subreg =
353 GEN_EXTRACT(dw1, GEN6_INST_DST_ADDR_SUBREG);
354
355 if (inst->access_mode == GEN6_ALIGN_1) {
356 inst->dst.base.addr_imm =
357 GEN_EXTRACT(dw1, GEN6_INST_DST_ADDR_IMM);
358 } else {
359 inst->dst.base.addr_imm =
360 GEN_EXTRACT(dw1, GEN6_INST_DST_ADDR_IMM_ALIGN16) <<
361 GEN6_INST_DST_ADDR_IMM_ALIGN16__SHR;
362 }
363 }
364 }
365
366 inst->dst.horz_stride = GEN_EXTRACT(dw1, GEN6_INST_DST_HORZSTRIDE);
367
368 if (inst->access_mode == GEN6_ALIGN_1)
369 inst->dst.writemask = 0xf;
370 else
371 inst->dst.writemask = GEN_EXTRACT(dw1, GEN6_INST_DST_WRITEMASK);
372 }
373
374 static void
375 disasm_inst_decode_dw1_gen6(struct disasm_inst *inst, uint32_t dw1)
376 {
377 ILO_DEV_ASSERT(inst->dev, 6, 8);
378
379 if (ilo_dev_gen(inst->dev) >= ILO_GEN(8))
380 disasm_inst_decode_dw1_low_gen8(inst, dw1);
381 else
382 disasm_inst_decode_dw1_low_gen6(inst, dw1);
383
384 if (disasm_inst_jip_in_dw1_high_gen6(inst))
385 inst->u.imm32 = dw1 >> 16;
386 else
387 disasm_inst_decode_dw1_high_gen6(inst, dw1);
388 }
389
390 static void
391 disasm_inst_decode_dw2_dw3_gen6(struct disasm_inst *inst,
392 uint32_t dw2, uint32_t dw3)
393 {
394 int count, i;
395
396 ILO_DEV_ASSERT(inst->dev, 6, 8);
397
398 if (ilo_dev_gen(inst->dev) >= ILO_GEN(8)) {
399 inst->src1.base.file = GEN_EXTRACT(dw2, GEN8_INST_SRC1_FILE);
400 inst->src1.base.type = GEN_EXTRACT(dw2, GEN8_INST_SRC1_TYPE);
401 } else {
402 if (ilo_dev_gen(inst->dev) >= ILO_GEN(7))
403 inst->flag_reg = GEN_EXTRACT(dw2, GEN7_INST_FLAG_REG);
404 inst->flag_subreg = GEN_EXTRACT(dw2, GEN6_INST_FLAG_SUBREG);
405 }
406
407 if (inst->src0.base.file == GEN6_FILE_IMM ||
408 inst->src1.base.file == GEN6_FILE_IMM) {
409 count = 1;
410 if (!disasm_inst_jip_in_dw1_high_gen6(inst))
411 inst->u.imm32 = dw3;
412 } else {
413 count = 2;
414 }
415
416 for (i = 0; i < count; i++) {
417 struct disasm_src_operand *src = (i == 0) ? &inst->src0 : &inst->src1;
418 const uint32_t dw = (i == 0) ? dw2 : dw3;
419
420 src->base.addr_mode = GEN_EXTRACT(dw, GEN6_INST_SRC_ADDRMODE);
421
422 if (src->base.addr_mode == GEN6_ADDRMODE_DIRECT) {
423 src->base.reg = GEN_EXTRACT(dw, GEN6_INST_SRC_REG);
424
425 if (inst->access_mode == GEN6_ALIGN_1) {
426 src->base.subreg = GEN_EXTRACT(dw, GEN6_INST_SRC_SUBREG);
427 } else {
428 src->base.subreg = GEN_EXTRACT(dw, GEN6_INST_SRC_SUBREG_ALIGN16) <<
429 GEN6_INST_SRC_SUBREG_ALIGN16__SHR;
430 }
431 } else {
432 if (ilo_dev_gen(inst->dev) >= ILO_GEN(8)) {
433 src->base.addr_subreg =
434 GEN_EXTRACT(dw, GEN8_INST_SRC_ADDR_SUBREG);
435
436 if (inst->access_mode == GEN6_ALIGN_1) {
437 src->base.addr_imm = GEN_EXTRACT(dw, GEN8_INST_SRC_ADDR_IMM);
438 } else {
439 src->base.addr_imm =
440 GEN_EXTRACT(dw, GEN8_INST_SRC_ADDR_IMM_ALIGN16) <<
441 GEN8_INST_SRC_ADDR_IMM_ALIGN16__SHR;
442 }
443
444 if (i == 0) {
445 inst->dst.base.addr_imm |= GEN_EXTRACT(dw,
446 GEN8_INST_SRC0_ADDR_IMM_BIT9) <<
447 GEN8_INST_SRC0_ADDR_IMM_BIT9__SHR;
448 } else {
449 inst->dst.base.addr_imm |= GEN_EXTRACT(dw,
450 GEN8_INST_SRC1_ADDR_IMM_BIT9) <<
451 GEN8_INST_SRC1_ADDR_IMM_BIT9__SHR;
452 }
453 } else {
454 src->base.addr_subreg =
455 GEN_EXTRACT(dw, GEN6_INST_SRC_ADDR_SUBREG);
456
457 if (inst->access_mode == GEN6_ALIGN_1) {
458 src->base.addr_imm = GEN_EXTRACT(dw, GEN6_INST_SRC_ADDR_IMM);
459 } else {
460 src->base.addr_imm =
461 GEN_EXTRACT(dw, GEN6_INST_SRC_ADDR_IMM_ALIGN16) <<
462 GEN6_INST_SRC_ADDR_IMM_ALIGN16__SHR;
463 }
464 }
465 }
466
467 src->vert_stride = GEN_EXTRACT(dw, GEN6_INST_SRC_VERTSTRIDE);
468
469 if (inst->access_mode == GEN6_ALIGN_1) {
470 src->width = GEN_EXTRACT(dw, GEN6_INST_SRC_WIDTH);
471 src->horz_stride = GEN_EXTRACT(dw, GEN6_INST_SRC_HORZSTRIDE);
472
473 src->swizzle_x = GEN6_SWIZZLE_X;
474 src->swizzle_y = GEN6_SWIZZLE_Y;
475 src->swizzle_z = GEN6_SWIZZLE_Z;
476 src->swizzle_w = GEN6_SWIZZLE_W;
477 } else {
478 src->width = GEN6_WIDTH_4;
479 src->horz_stride = GEN6_HORZSTRIDE_1;
480
481 src->swizzle_x = GEN_EXTRACT(dw, GEN6_INST_SRC_SWIZZLE_X);
482 src->swizzle_y = GEN_EXTRACT(dw, GEN6_INST_SRC_SWIZZLE_Y);
483 src->swizzle_z = GEN_EXTRACT(dw, GEN6_INST_SRC_SWIZZLE_Z);
484 src->swizzle_w = GEN_EXTRACT(dw, GEN6_INST_SRC_SWIZZLE_W);
485 }
486
487 src->negate = (bool) (dw & GEN6_INST_SRC_NEGATE);
488 src->absolute = (bool) (dw & GEN6_INST_SRC_ABSOLUTE);
489 }
490 }
491
492 static void
493 disasm_inst_decode_3src_dw1_gen6(struct disasm_inst *inst, uint32_t dw1)
494 {
495 static const unsigned type_mapping[4] = {
496 [GEN7_TYPE_F_3SRC] = GEN6_TYPE_F,
497 [GEN7_TYPE_D_3SRC] = GEN6_TYPE_D,
498 [GEN7_TYPE_UD_3SRC] = GEN6_TYPE_UD,
499 [GEN7_TYPE_DF_3SRC] = GEN7_TYPE_DF,
500 };
501
502 ILO_DEV_ASSERT(inst->dev, 6, 7.5);
503
504 inst->flag_subreg = GEN_EXTRACT(dw1, GEN6_3SRC_FLAG_SUBREG);
505
506 if (ilo_dev_gen(inst->dev) >= ILO_GEN(7)) {
507 inst->nib_ctrl = (bool) (dw1 & GEN7_3SRC_NIBCTRL);
508 inst->flag_reg = GEN_EXTRACT(dw1, GEN7_3SRC_FLAG_REG);
509
510 inst->dst.base.file = GEN6_FILE_GRF;
511 inst->dst.base.type = GEN_EXTRACT(dw1, GEN7_3SRC_DST_TYPE);
512 inst->dst.base.type = type_mapping[inst->dst.base.type];
513
514 inst->src0.base.type = GEN_EXTRACT(dw1, GEN7_3SRC_SRC_TYPE);
515 inst->src0.base.type = type_mapping[inst->src0.base.type];
516
517 inst->src1.base.type = inst->src0.base.type;
518 inst->u.src2.base.type = inst->src0.base.type;
519 } else {
520 inst->dst.base.file = (dw1 & GEN6_3SRC_DST_FILE_MRF) ?
521 GEN6_FILE_MRF: GEN6_FILE_GRF;
522 inst->dst.base.type = GEN6_TYPE_F;
523
524 inst->src0.base.type = GEN6_TYPE_F;
525 inst->src1.base.type = GEN6_TYPE_F;
526 inst->u.src2.base.type = GEN6_TYPE_F;
527 }
528
529 inst->dst.base.addr_mode = GEN6_ADDRMODE_DIRECT;
530 inst->dst.base.reg = GEN_EXTRACT(dw1, GEN6_3SRC_DST_REG);
531 inst->dst.base.subreg = GEN_EXTRACT(dw1, GEN6_3SRC_DST_SUBREG) <<
532 GEN6_3SRC_DST_SUBREG__SHR;
533
534 inst->dst.horz_stride = GEN6_HORZSTRIDE_1;
535 inst->dst.writemask = GEN_EXTRACT(dw1, GEN6_3SRC_DST_WRITEMASK);
536
537 inst->src0.base.file = GEN6_FILE_GRF;
538 inst->src0.negate = (bool) (dw1 & GEN6_3SRC_SRC0_NEGATE);
539 inst->src0.absolute = (bool) (dw1 & GEN6_3SRC_SRC0_ABSOLUTE);
540 inst->src1.base.file = GEN6_FILE_GRF;
541 inst->src1.negate = (bool) (dw1 & GEN6_3SRC_SRC1_NEGATE);
542 inst->src1.absolute = (bool) (dw1 & GEN6_3SRC_SRC1_ABSOLUTE);
543 inst->u.src2.base.file = GEN6_FILE_GRF;
544 inst->u.src2.negate = (bool) (dw1 & GEN6_3SRC_SRC2_NEGATE);
545 inst->u.src2.absolute = (bool) (dw1 & GEN6_3SRC_SRC2_ABSOLUTE);
546 }
547
548 static void
549 disasm_inst_decode_3src_dw1_gen8(struct disasm_inst *inst, uint32_t dw1)
550 {
551 static const unsigned type_mapping[8] = {
552 [GEN7_TYPE_F_3SRC] = GEN6_TYPE_F,
553 [GEN7_TYPE_D_3SRC] = GEN6_TYPE_D,
554 [GEN7_TYPE_UD_3SRC] = GEN6_TYPE_UD,
555 [GEN7_TYPE_DF_3SRC] = GEN7_TYPE_DF,
556 /* map unknown types to unknown types */
557 [0x4] = 0xf,
558 [0x5] = 0xf,
559 [0x6] = 0xf,
560 [0x7] = 0xf,
561 };
562
563 ILO_DEV_ASSERT(inst->dev, 8, 8);
564
565 inst->flag_subreg = GEN_EXTRACT(dw1, GEN8_3SRC_FLAG_SUBREG);
566 inst->flag_reg = GEN_EXTRACT(dw1, GEN8_3SRC_FLAG_REG);
567 inst->mask_ctrl = GEN_EXTRACT(dw1, GEN8_3SRC_MASKCTRL);
568 inst->src0.absolute = (bool) (dw1 & GEN8_3SRC_SRC0_ABSOLUTE);
569 inst->src0.negate = (bool) (dw1 & GEN8_3SRC_SRC0_NEGATE);
570 inst->src1.negate = (bool) (dw1 & GEN8_3SRC_SRC1_NEGATE);
571 inst->src1.absolute = (bool) (dw1 & GEN8_3SRC_SRC1_ABSOLUTE);
572 inst->u.src2.negate = (bool) (dw1 & GEN8_3SRC_SRC2_NEGATE);
573 inst->u.src2.absolute = (bool) (dw1 & GEN8_3SRC_SRC2_ABSOLUTE);
574
575 inst->src0.base.file = GEN6_FILE_GRF;
576 inst->src0.base.type = GEN_EXTRACT(dw1, GEN8_3SRC_SRC_TYPE);
577 inst->src0.base.type = type_mapping[inst->src0.base.type];
578
579 inst->src1.base.file = GEN6_FILE_GRF;
580 inst->src1.base.type = inst->src0.base.type;
581
582 inst->u.src2.base.file = GEN6_FILE_GRF;
583 inst->u.src2.base.type = inst->src0.base.type;
584
585 inst->dst.base.file = GEN6_FILE_GRF;
586 inst->dst.base.type = GEN_EXTRACT(dw1, GEN8_3SRC_DST_TYPE);
587 inst->dst.base.type = type_mapping[inst->dst.base.type];
588 inst->dst.base.addr_mode = GEN6_ADDRMODE_DIRECT;
589 inst->dst.horz_stride = GEN6_HORZSTRIDE_1;
590
591 inst->dst.writemask = GEN_EXTRACT(dw1, GEN6_3SRC_DST_WRITEMASK);
592 inst->dst.base.subreg = GEN_EXTRACT(dw1, GEN6_3SRC_DST_SUBREG) <<
593 GEN6_3SRC_DST_SUBREG__SHR;
594 inst->dst.base.reg = GEN_EXTRACT(dw1, GEN6_3SRC_DST_REG);
595 }
596
597 static void
598 disasm_inst_decode_3src_dw2_dw3_gen6(struct disasm_inst *inst,
599 uint32_t dw2, uint32_t dw3)
600 {
601 const uint64_t qw = (uint64_t) dw3 << 32 | dw2;
602 int i;
603
604 ILO_DEV_ASSERT(inst->dev, 6, 8);
605
606 for (i = 0; i < 3; i++) {
607 struct disasm_src_operand *src = (i == 0) ? &inst->src0 :
608 (i == 1) ? &inst->src1 :
609 &inst->u.src2;
610 const uint32_t dw = (i == 0) ? GEN_EXTRACT(qw, GEN6_3SRC_SRC_0) :
611 (i == 1) ? GEN_EXTRACT(qw, GEN6_3SRC_SRC_1) :
612 GEN_EXTRACT(qw, GEN6_3SRC_SRC_2);
613
614 src->base.addr_mode = GEN6_ADDRMODE_DIRECT;
615 src->base.reg = GEN_EXTRACT(dw, GEN6_3SRC_SRC_REG);
616 src->base.subreg = GEN_EXTRACT(dw, GEN6_3SRC_SRC_SUBREG) <<
617 GEN6_3SRC_SRC_SUBREG__SHR;
618
619 if (dw & GEN6_3SRC_SRC_REPCTRL) {
620 src->vert_stride = GEN6_VERTSTRIDE_0;
621 src->width = GEN6_WIDTH_1;
622 src->horz_stride = GEN6_HORZSTRIDE_0;
623 } else {
624 src->vert_stride = GEN6_VERTSTRIDE_4;
625 src->width = GEN6_WIDTH_4;
626 src->horz_stride = GEN6_HORZSTRIDE_1;
627 }
628
629 src->swizzle_x = GEN_EXTRACT(dw, GEN6_3SRC_SRC_SWIZZLE_X);
630 src->swizzle_y = GEN_EXTRACT(dw, GEN6_3SRC_SRC_SWIZZLE_Y);
631 src->swizzle_z = GEN_EXTRACT(dw, GEN6_3SRC_SRC_SWIZZLE_Z);
632 src->swizzle_w = GEN_EXTRACT(dw, GEN6_3SRC_SRC_SWIZZLE_W);
633 }
634 }
635
636 /*
637 * When GEN6_INST_CMPTCTRL of DW0 is set, the instruction has 64 bits and is
638 * in EU_INSTRUCTION_COMPACT_TWO_SRC form. We should have expanded it to its
639 * original form.
640 *
641 * Depending on the opcode, the 128-bits instruction is in one of the
642 * following forms
643 *
644 * - EU_INSTRUCTION_BASIC_ONE_SRC
645 * - EU_INSTRUCTION_BASIC_TWO_SRC
646 * - EU_INSTRUCTION_BASIC_THREE_SRC
647 * - EU_INSTRUCTION_BRANCH_CONDITIONAL
648 * - EU_INSTRUCTION_BRANCH_ONE_SRC
649 * - EU_INSTRUCTION_BRANCH_TWO_SRC
650 * - EU_INSTRUCTION_ILLEGAL
651 * - EU_INSTRUCTION_MATH
652 * - EU_INSTRUCTION_NOP
653 * - EU_INSTRUCTION_SEND
654 *
655 * In EU_INSTRUCTION_BASIC_ONE_SRC form,
656 *
657 * - DW0 is EU_INSTRUCTION_HEADER
658 * - DW1 is EU_INSTRUCTION_OPERAND_CONTROLS
659 * - DW2 is Source 0 and EU_INSTRUCTION_FLAGS
660 * - DW3 is reserved unless Source 0 is an immediate
661 *
662 * All other forms except EU_INSTRUCTION_BASIC_THREE_SRC are quite compatible
663 * with EU_INSTRUCTION_BASIC_ONE_SRC.
664 */
665 static void
666 disasm_inst_decode(struct disasm_inst *inst,
667 const uint32_t *dw)
668 {
669 assert(!(dw[0] & GEN6_INST_CMPTCTRL));
670
671 disasm_inst_decode_dw0_gen6(inst, dw[0]);
672
673 if (disasm_opcode_table[inst->opcode].src_count == 3) {
674 if (ilo_dev_gen(inst->dev) >= ILO_GEN(8))
675 disasm_inst_decode_3src_dw1_gen8(inst, dw[1]);
676 else
677 disasm_inst_decode_3src_dw1_gen6(inst, dw[1]);
678 disasm_inst_decode_3src_dw2_dw3_gen6(inst, dw[2], dw[3]);
679 } else {
680 disasm_inst_decode_dw1_gen6(inst, dw[1]);
681 disasm_inst_decode_dw2_dw3_gen6(inst, dw[2], dw[3]);
682 }
683 }
684
685 static const char *
686 disasm_inst_opcode(const struct disasm_inst *inst)
687 {
688 return (disasm_opcode_table[inst->opcode].name) ?
689 disasm_opcode_table[inst->opcode].name : "BAD";
690 }
691
692 static const char *
693 disasm_inst_pred_ctrl(const struct disasm_inst *inst)
694 {
695 if (inst->access_mode == GEN6_ALIGN_1) {
696 switch (inst->pred_ctrl) {
697 case GEN6_PREDCTRL_NORMAL: return "";
698 case GEN6_PREDCTRL_ANYV: return ".anyv";
699 case GEN6_PREDCTRL_ALLV: return ".allv";
700 case GEN6_PREDCTRL_ANY2H: return ".any2h";
701 case GEN6_PREDCTRL_ALL2H: return ".all2h";
702 case GEN6_PREDCTRL_ANY4H: return ".any4h";
703 case GEN6_PREDCTRL_ALL4H: return ".all4h";
704 case GEN6_PREDCTRL_ANY8H: return ".any8h";
705 case GEN6_PREDCTRL_ALL8H: return ".all8h";
706 case GEN6_PREDCTRL_ANY16H: return ".any16h";
707 case GEN6_PREDCTRL_ALL16H: return ".all16h";
708 case GEN7_PREDCTRL_ANY32H: return ".any32h";
709 case GEN7_PREDCTRL_ALL32H: return ".all32h";
710 default: return ".BAD";
711 }
712 } else {
713 switch (inst->pred_ctrl) {
714 case GEN6_PREDCTRL_NORMAL: return "";
715 case GEN6_PREDCTRL_X: return ".x";
716 case GEN6_PREDCTRL_Y: return ".y";
717 case GEN6_PREDCTRL_Z: return ".z";
718 case GEN6_PREDCTRL_W: return ".w";
719 default: return ".BAD";
720 }
721 }
722 }
723
724 static char
725 disasm_inst_pred_inv(const struct disasm_inst *inst)
726 {
727 return (inst->pred_inv) ? '-' : '+';
728 }
729
730 static const char *
731 disasm_inst_exec_size(const struct disasm_inst *inst)
732 {
733 switch (inst->exec_size) {
734 case GEN6_EXECSIZE_1: return "1";
735 case GEN6_EXECSIZE_2: return "2";
736 case GEN6_EXECSIZE_4: return "4";
737 case GEN6_EXECSIZE_8: return "8";
738 case GEN6_EXECSIZE_16: return "16";
739 case GEN6_EXECSIZE_32: return "32";
740 default: return "BAD";
741 }
742 }
743
744 static const char *
745 disasm_inst_fc(const struct disasm_inst *inst)
746 {
747 assert(inst->opcode == GEN6_OPCODE_MATH);
748
749 switch (inst->fc) {
750 case GEN6_MATH_INV: return "inv";
751 case GEN6_MATH_LOG: return "log";
752 case GEN6_MATH_EXP: return "exp";
753 case GEN6_MATH_SQRT: return "sqrt";
754 case GEN6_MATH_RSQ: return "rsq";
755 case GEN6_MATH_SIN: return "sin";
756 case GEN6_MATH_COS: return "cos";
757 case GEN6_MATH_FDIV: return "fdiv";
758 case GEN6_MATH_POW: return "pow";
759 case GEN6_MATH_INT_DIV: return "int_div";
760 case GEN6_MATH_INT_DIV_QUOTIENT: return "int_div_quotient";
761 case GEN6_MATH_INT_DIV_REMAINDER: return "int_div_remainder";
762 case GEN8_MATH_INVM: return "invm";
763 case GEN8_MATH_RSQRTM: return "rsqrtm";
764 default: return "BAD";
765 }
766 }
767
768 static const char *
769 disasm_inst_sfid(const struct disasm_inst *inst)
770 {
771 assert(inst->opcode == GEN6_OPCODE_SEND ||
772 inst->opcode == GEN6_OPCODE_SENDC);
773
774 switch (inst->sfid) {
775 case GEN6_SFID_NULL: return "null";
776 case GEN6_SFID_SAMPLER: return "sampler";
777 case GEN6_SFID_GATEWAY: return "gateway";
778 case GEN6_SFID_DP_SAMPLER: return "dp sampler";
779 case GEN6_SFID_DP_RC: return "dp render";
780 case GEN6_SFID_URB: return "urb";
781 case GEN6_SFID_SPAWNER: return "spawner";
782 case GEN6_SFID_VME: return "vme";
783 case GEN6_SFID_DP_CC: return "dp const";
784 case GEN7_SFID_DP_DC0: return "dp data 0";
785 case GEN7_SFID_PI: return "pixel interp";
786 case GEN75_SFID_DP_DC1: return "dp data 1";
787 default: return "BAD";
788 }
789 }
790
791 static const char *
792 disasm_inst_cond_modifier(const struct disasm_inst *inst)
793 {
794 switch (inst->cond_modifier) {
795 case GEN6_COND_NONE: return "";
796 case GEN6_COND_Z: return ".z";
797 case GEN6_COND_NZ: return ".nz";
798 case GEN6_COND_G: return ".g";
799 case GEN6_COND_GE: return ".ge";
800 case GEN6_COND_L: return ".l";
801 case GEN6_COND_LE: return ".le";
802 case GEN6_COND_O: return ".o";
803 case GEN6_COND_U: return ".u";
804 default: return ".BAD";
805 }
806 }
807
808 static const char *
809 disasm_inst_debug_ctrl(const struct disasm_inst *inst)
810 {
811 return (inst->debug_ctrl) ? ".breakpoint" : "";
812 }
813
814 static const char *
815 disasm_inst_saturate(const struct disasm_inst *inst)
816 {
817 return (inst->saturate) ? ".sat" : "";
818 }
819
820 static const char *
821 disasm_inst_flag_reg(const struct disasm_inst *inst)
822 {
823 static const char *flag_names[2][2] = {
824 { "f0", "f0.1" },
825 { "f1.0", "f1.1" },
826 };
827
828 return (inst->flag_reg <= 1 && inst->flag_subreg <= 1) ?
829 flag_names[inst->flag_reg][inst->flag_subreg] : "fBAD";
830 }
831
832 static const char *
833 disasm_inst_access_mode(const struct disasm_inst *inst)
834 {
835 switch (inst->access_mode) {
836 case GEN6_ALIGN_1: return " align1";
837 case GEN6_ALIGN_16: return " align16";
838 default: return " alignBAD";
839 }
840 }
841
842 static const char *
843 disasm_inst_mask_ctrl(const struct disasm_inst *inst)
844 {
845 switch (inst->mask_ctrl) {
846 case GEN6_MASKCTRL_NORMAL: return "";
847 case GEN6_MASKCTRL_NOMASK: return " WE_all";
848 default: return " WE_BAD";
849 }
850 }
851
852 static const char *
853 disasm_inst_dep_ctrl(const struct disasm_inst *inst)
854 {
855 switch (inst->dep_ctrl) {
856 case GEN6_DEPCTRL_NORMAL: return "";
857 case GEN6_DEPCTRL_NODDCLR: return " NoDDClr";
858 case GEN6_DEPCTRL_NODDCHK: return " NoDDChk";
859 case GEN6_DEPCTRL_NEITHER: return " NoDDClr,NoDDChk";
860 default: return " NoDDBAD";
861 }
862 }
863
864 static const char *
865 disasm_inst_qtr_ctrl(const struct disasm_inst *inst)
866 {
867 switch (inst->exec_size) {
868 case GEN6_EXECSIZE_8:
869 switch (inst->qtr_ctrl) {
870 case GEN6_QTRCTRL_1Q: return " 1Q";
871 case GEN6_QTRCTRL_2Q: return " 2Q";
872 case GEN6_QTRCTRL_3Q: return " 3Q";
873 case GEN6_QTRCTRL_4Q: return " 4Q";
874 default: return " BADQ";
875 }
876 break;
877 case GEN6_EXECSIZE_16:
878 switch (inst->qtr_ctrl) {
879 case GEN6_QTRCTRL_1H: return " 1H";
880 case GEN6_QTRCTRL_2H: return " 2H";
881 default: return " BADH";
882 }
883 break;
884 default:
885 return "";
886 }
887
888 }
889
890 static const char *
891 disasm_inst_thread_ctrl(const struct disasm_inst *inst)
892 {
893 switch (inst->thread_ctrl) {
894 case GEN6_THREADCTRL_NORMAL: return "";
895 case GEN6_THREADCTRL_ATOMIC: return " atomic";
896 case GEN6_THREADCTRL_SWITCH: return " switch";
897 default: return " BAD";
898 }
899 }
900
901 static const char *
902 disasm_inst_acc_wr_ctrl(const struct disasm_inst *inst)
903 {
904 return (inst->acc_wr_ctrl) ? " AccWrEnable" : "";
905 }
906
907 static const char *
908 disasm_inst_cmpt_ctrl(const struct disasm_inst *inst)
909 {
910 return (inst->cmpt_ctrl) ? " compacted" : "";
911 }
912
913 static const char *
914 disasm_inst_eot(const struct disasm_inst *inst)
915 {
916 if (inst->opcode == GEN6_OPCODE_SEND ||
917 inst->opcode == GEN6_OPCODE_SENDC)
918 return (inst->u.imm32 & GEN6_MSG_EOT) ? " EOT" : "";
919 else
920 return "";
921 }
922
923 static const char *
924 disasm_inst_file(const struct disasm_inst *inst,
925 const struct disasm_operand *operand,
926 bool *multi_regs)
927 {
928 switch (operand->file) {
929 case GEN6_FILE_ARF:
930 switch (operand->reg & 0xf0) {
931 case GEN6_ARF_NULL: *multi_regs = false; return "null";
932 case GEN6_ARF_A0: *multi_regs = true; return "a";
933 case GEN6_ARF_ACC0: *multi_regs = true; return "acc";
934 case GEN6_ARF_F0: *multi_regs = true; return "f";
935 case GEN6_ARF_SR0: *multi_regs = true; return "sr";
936 case GEN6_ARF_CR0: *multi_regs = true; return "cr";
937 case GEN6_ARF_N0: *multi_regs = true; return "n";
938 case GEN6_ARF_IP: *multi_regs = false; return "ip";
939 case GEN6_ARF_TDR: *multi_regs = false; return "tdr";
940 case GEN7_ARF_TM0: *multi_regs = true; return "tm";
941 default: *multi_regs = false; return "BAD";
942 }
943 break;
944 case GEN6_FILE_GRF: *multi_regs = true; return "g";
945 case GEN6_FILE_MRF: *multi_regs = true; return "m";
946 case GEN6_FILE_IMM: *multi_regs = true; return "";
947 default: *multi_regs = false; return "BAD";
948 }
949 }
950
951 static const char *
952 disasm_inst_type(const struct disasm_inst *inst,
953 const struct disasm_operand *operand)
954 {
955 if (operand->file == GEN6_FILE_IMM) {
956 switch (operand->type) {
957 case GEN6_TYPE_UD: return "UD";
958 case GEN6_TYPE_D: return "D";
959 case GEN6_TYPE_UW: return "UW";
960 case GEN6_TYPE_W: return "W";
961 case GEN6_TYPE_UV_IMM: return "UV";
962 case GEN6_TYPE_VF_IMM: return "VF";
963 case GEN6_TYPE_V_IMM: return "V";
964 case GEN6_TYPE_F: return "F";
965 case GEN8_TYPE_DF_IMM: return "DF";
966 case GEN8_TYPE_HF_IMM: return "HF";
967 default: return "BAD";
968 }
969 } else {
970 switch (operand->type) {
971 case GEN6_TYPE_UD: return "UD";
972 case GEN6_TYPE_D: return "D";
973 case GEN6_TYPE_UW: return "UW";
974 case GEN6_TYPE_W: return "W";
975 case GEN6_TYPE_UB: return "UB";
976 case GEN6_TYPE_B: return "B";
977 case GEN7_TYPE_DF: return "DF";
978 case GEN6_TYPE_F: return "F";
979 case GEN8_TYPE_UQ: return "UQ";
980 case GEN8_TYPE_Q: return "Q";
981 case GEN8_TYPE_HF: return "HF";
982 default: return "BAD";
983 }
984 }
985 }
986
987 static const char *
988 disasm_inst_vert_stride(const struct disasm_inst *inst, unsigned vert_stride)
989 {
990 switch (vert_stride) {
991 case GEN6_VERTSTRIDE_0: return "0";
992 case GEN6_VERTSTRIDE_1: return "1";
993 case GEN6_VERTSTRIDE_2: return "2";
994 case GEN6_VERTSTRIDE_4: return "4";
995 case GEN6_VERTSTRIDE_8: return "8";
996 case GEN6_VERTSTRIDE_16: return "16";
997 case GEN6_VERTSTRIDE_32: return "32";
998 case GEN6_VERTSTRIDE_VXH: return "VxH";
999 default: return "BAD";
1000 }
1001 }
1002
1003 static const char *
1004 disasm_inst_width(const struct disasm_inst *inst, unsigned width)
1005 {
1006 switch (width) {
1007 case GEN6_WIDTH_1: return "1";
1008 case GEN6_WIDTH_2: return "2";
1009 case GEN6_WIDTH_4: return "4";
1010 case GEN6_WIDTH_8: return "8";
1011 case GEN6_WIDTH_16: return "16";
1012 default: return "BAD";
1013 }
1014 }
1015
1016 static const char *
1017 disasm_inst_horz_stride(const struct disasm_inst *inst, unsigned horz_stride)
1018 {
1019 switch (horz_stride) {
1020 case GEN6_HORZSTRIDE_0: return "0";
1021 case GEN6_HORZSTRIDE_1: return "1";
1022 case GEN6_HORZSTRIDE_2: return "2";
1023 case GEN6_HORZSTRIDE_4: return "4";
1024 default: return "BAD";
1025 }
1026 }
1027
1028 static const char *
1029 disasm_inst_writemask(const struct disasm_inst *inst, unsigned writemask)
1030 {
1031 switch (writemask) {
1032 case 0x0: return ".";
1033 case 0x1: return ".x";
1034 case 0x2: return ".y";
1035 case 0x3: return ".xy";
1036 case 0x4: return ".z";
1037 case 0x5: return ".xz";
1038 case 0x6: return ".yz";
1039 case 0x7: return ".xyz";
1040 case 0x8: return ".w";
1041 case 0x9: return ".xw";
1042 case 0xa: return ".yw";
1043 case 0xb: return ".xyw";
1044 case 0xc: return ".zw";
1045 case 0xd: return ".xzw";
1046 case 0xe: return ".yzw";
1047 case 0xf: return "";
1048 default: return ".BAD";
1049 }
1050 }
1051
1052 static const char *
1053 disasm_inst_negate(const struct disasm_inst *inst, bool negate)
1054 {
1055 if (ilo_dev_gen(inst->dev) >= ILO_GEN(8)) {
1056 switch (inst->opcode) {
1057 case GEN6_OPCODE_AND:
1058 case GEN6_OPCODE_NOT:
1059 case GEN6_OPCODE_OR:
1060 case GEN6_OPCODE_XOR:
1061 return (negate) ? "~" : "";
1062 break;
1063 default:
1064 break;
1065 }
1066 }
1067
1068 return (negate) ? "-" : "";
1069 }
1070
1071 static const char *
1072 disasm_inst_absolute(const struct disasm_inst *inst, bool absolute)
1073 {
1074 return (absolute) ? "(abs)" : "";
1075 }
1076
1077 static const char *
1078 disasm_inst_mdesc_sampler_op(const struct disasm_inst *inst, int op)
1079 {
1080 switch (op) {
1081 case GEN6_MSG_SAMPLER_SAMPLE: return "sample";
1082 case GEN6_MSG_SAMPLER_SAMPLE_B: return "sample_b";
1083 case GEN6_MSG_SAMPLER_SAMPLE_L: return "sample_l";
1084 case GEN6_MSG_SAMPLER_SAMPLE_C: return "sample_c";
1085 case GEN6_MSG_SAMPLER_SAMPLE_D: return "sample_d";
1086 case GEN6_MSG_SAMPLER_SAMPLE_B_C: return "sample_b_c";
1087 case GEN6_MSG_SAMPLER_SAMPLE_L_C: return "sample_l_c";
1088 case GEN6_MSG_SAMPLER_LD: return "ld";
1089 case GEN6_MSG_SAMPLER_GATHER4: return "gather4";
1090 case GEN6_MSG_SAMPLER_LOD: return "lod";
1091 case GEN6_MSG_SAMPLER_RESINFO: return "resinfo";
1092 case GEN6_MSG_SAMPLER_SAMPLEINFO: return "sampleinfo";
1093 case GEN7_MSG_SAMPLER_GATHER4_C: return "gather4_c";
1094 case GEN7_MSG_SAMPLER_GATHER4_PO: return "gather4_po";
1095 case GEN7_MSG_SAMPLER_GATHER4_PO_C: return "gather4_po_c";
1096 case GEN7_MSG_SAMPLER_SAMPLE_D_C: return "sample_d_c";
1097 case GEN7_MSG_SAMPLER_SAMPLE_LZ: return "sample_lz";
1098 case GEN7_MSG_SAMPLER_SAMPLE_C_LC: return "sample_c_lc";
1099 case GEN7_MSG_SAMPLER_LD_LZ: return "ld_lz";
1100 case GEN7_MSG_SAMPLER_LD_MCS: return "ld_mcs";
1101 case GEN7_MSG_SAMPLER_LD2DMS: return "ld2dms";
1102 case GEN7_MSG_SAMPLER_LD2DSS: return "ld2dss";
1103 default: return "BAD";
1104 }
1105 }
1106
1107 static const char *
1108 disasm_inst_mdesc_sampler_simd(const struct disasm_inst *inst, int simd)
1109 {
1110 switch (simd) {
1111 case GEN6_MSG_SAMPLER_SIMD4X2: return "SIMD4x2";
1112 case GEN6_MSG_SAMPLER_SIMD8: return "SIMD8";
1113 case GEN6_MSG_SAMPLER_SIMD16: return "SIMD16";
1114 case GEN6_MSG_SAMPLER_SIMD32_64: return "SIMD32";
1115 default: return "BAD";
1116 }
1117 }
1118
1119 static const char *
1120 disasm_inst_mdesc_urb_op(const struct disasm_inst *inst, int op)
1121 {
1122 if (ilo_dev_gen(inst->dev) >= ILO_GEN(7)) {
1123 switch (op) {
1124 case GEN7_MSG_URB_WRITE_HWORD: return "write HWord";
1125 case GEN7_MSG_URB_WRITE_OWORD: return "write OWord";
1126 case GEN7_MSG_URB_READ_HWORD: return "read HWord";
1127 case GEN7_MSG_URB_READ_OWORD: return "read OWord";
1128 case GEN7_MSG_URB_ATOMIC_MOV: return "atomic mov";
1129 case GEN7_MSG_URB_ATOMIC_INC: return "atomic inc";
1130 default: return "BAD";
1131 }
1132 } else {
1133 switch (op) {
1134 case GEN6_MSG_URB_WRITE: return "urb_write";
1135 case GEN6_MSG_URB_FF_SYNC: return "ff_sync";
1136 default: return "BAD";
1137 }
1138 }
1139 }
1140
1141 static const char *
1142 disasm_inst_mdesc_dp_op_gen6(const struct disasm_inst *inst,
1143 int sfid, int op)
1144 {
1145 ILO_DEV_ASSERT(inst->dev, 6, 6);
1146
1147 switch (op) {
1148 case GEN6_MSG_DP_OWORD_BLOCK_READ: return "OWORD block read";
1149 case GEN6_MSG_DP_RT_UNORM_READ: return "RT UNORM read";
1150 case GEN6_MSG_DP_OWORD_DUAL_BLOCK_READ: return "OWORD dual block read";
1151 case GEN6_MSG_DP_MEDIA_BLOCK_READ: return "media block read";
1152 case GEN6_MSG_DP_UNALIGNED_OWORD_BLOCK_READ: return "unaligned OWORD block read";
1153 case GEN6_MSG_DP_DWORD_SCATTERED_READ: return "DWORD scattered read";
1154 case GEN6_MSG_DP_DWORD_ATOMIC_WRITE: return "DWORD atomic write";
1155 case GEN6_MSG_DP_OWORD_BLOCK_WRITE: return "OWORD block write";
1156 case GEN6_MSG_DP_OWORD_DUAL_BLOCK_WRITE: return "OWORD dual block_write";
1157 case GEN6_MSG_DP_MEDIA_BLOCK_WRITE: return "media block write";
1158 case GEN6_MSG_DP_DWORD_SCATTERED_WRITE: return "DWORD scattered write";
1159 case GEN6_MSG_DP_RT_WRITE: return "RT write";
1160 case GEN6_MSG_DP_SVB_WRITE: return "SVB write";
1161 case GEN6_MSG_DP_RT_UNORM_WRITE: return "RT UNORM write";
1162 default: return "BAD";
1163 }
1164 }
1165
1166 static const char *
1167 disasm_inst_mdesc_dp_op_gen7(const struct disasm_inst *inst,
1168 int sfid, int op)
1169 {
1170 ILO_DEV_ASSERT(inst->dev, 7, 7);
1171
1172 switch (sfid) {
1173 case GEN6_SFID_DP_SAMPLER:
1174 switch (op) {
1175 case GEN7_MSG_DP_SAMPLER_UNALIGNED_OWORD_BLOCK_READ: return "OWORD block read";
1176 case GEN7_MSG_DP_SAMPLER_MEDIA_BLOCK_READ: return "media block read";
1177 default: return "BAD";
1178 }
1179 case GEN6_SFID_DP_RC:
1180 switch (op) {
1181 case GEN7_MSG_DP_RC_MEDIA_BLOCK_READ: return "media block read";
1182 case GEN7_MSG_DP_RC_TYPED_SURFACE_READ: return "typed surface read";
1183 case GEN7_MSG_DP_RC_TYPED_ATOMIC_OP: return "typed atomic op";
1184 case GEN7_MSG_DP_RC_MEMORY_FENCE: return "memory fence";
1185 case GEN7_MSG_DP_RC_MEDIA_BLOCK_WRITE: return "media block write";
1186 case GEN7_MSG_DP_RC_RT_WRITE: return "RT write";
1187 case GEN7_MSG_DP_RC_TYPED_SURFACE_WRITE: return "typed surface write";
1188 default: return "BAD";
1189 }
1190 case GEN6_SFID_DP_CC:
1191 switch (op) {
1192 case GEN7_MSG_DP_CC_OWORD_BLOCK_READ: return "OWROD block read";
1193 case GEN7_MSG_DP_CC_UNALIGNED_OWORD_BLOCK_READ: return "unaligned OWORD block read";
1194 case GEN7_MSG_DP_CC_OWORD_DUAL_BLOCK_READ: return "OWORD dual block read";
1195 case GEN7_MSG_DP_CC_DWORD_SCATTERED_READ: return "DWORD scattered read";
1196 default: return "BAD";
1197 }
1198 case GEN7_SFID_DP_DC0:
1199 switch (op) {
1200 case GEN7_MSG_DP_DC0_OWORD_BLOCK_READ: return "OWORD block read";
1201 case GEN7_MSG_DP_DC0_UNALIGNED_OWORD_BLOCK_READ: return "unaligned OWORD block read";
1202 case GEN7_MSG_DP_DC0_OWORD_DUAL_BLOCK_READ: return "OWORD dual block read";
1203 case GEN7_MSG_DP_DC0_DWORD_SCATTERED_READ: return "DWORD scattered read";
1204 case GEN7_MSG_DP_DC0_BYTE_SCATTERED_READ: return "BYTE scattered read";
1205 case GEN7_MSG_DP_DC0_UNTYPED_SURFACE_READ: return "untyped surface read";
1206 case GEN7_MSG_DP_DC0_UNTYPED_ATOMIC_OP: return "untyped atomic op";
1207 case GEN7_MSG_DP_DC0_MEMORY_FENCE: return "memory fence";
1208 case GEN7_MSG_DP_DC0_OWORD_BLOCK_WRITE: return "OWORD block write";
1209 case GEN7_MSG_DP_DC0_OWORD_DUAL_BLOCK_WRITE: return "OWORD dual block write";
1210 case GEN7_MSG_DP_DC0_DWORD_SCATTERED_WRITE: return "OWORD scattered write";
1211 case GEN7_MSG_DP_DC0_BYTE_SCATTERED_WRITE: return "BYTE scattered write";
1212 case GEN7_MSG_DP_DC0_UNTYPED_SURFACE_WRITE: return "untyped surface write";
1213 default: return "BAD";
1214 }
1215 default: return "BAD";
1216 }
1217 }
1218
1219 static const char *
1220 disasm_inst_mdesc_dp_op_gen75(const struct disasm_inst *inst,
1221 int sfid, int op)
1222 {
1223 ILO_DEV_ASSERT(inst->dev, 7.5, 8);
1224
1225 switch (sfid) {
1226 case GEN6_SFID_DP_SAMPLER:
1227 switch (op) {
1228 case GEN75_MSG_DP_SAMPLER_READ_SURFACE_INFO: return "read surface info";
1229 case GEN75_MSG_DP_SAMPLER_UNALIGNED_OWORD_BLOCK_READ: return "unaligned OWORD block read";
1230 case GEN75_MSG_DP_SAMPLER_MEDIA_BLOCK_READ: return "media block read";
1231 default: return "BAD";
1232 }
1233
1234 case GEN6_SFID_DP_RC:
1235 switch (op) {
1236 case GEN75_MSG_DP_RC_MEDIA_BLOCK_READ: return "media block read";
1237 case GEN75_MSG_DP_RC_MEMORY_FENCE: return "memory fence";
1238 case GEN75_MSG_DP_RC_MEDIA_BLOCK_WRITE: return "media block write";
1239 case GEN75_MSG_DP_RC_RT_WRITE: return "RT write";
1240 default: return "BAD";
1241 }
1242 case GEN6_SFID_DP_CC:
1243 switch (op) {
1244 case GEN75_MSG_DP_CC_OWORD_BLOCK_READ: return "OWROD block read";
1245 case GEN75_MSG_DP_CC_UNALIGNED_OWORD_BLOCK_READ: return "unaligned OWORD block read";
1246 case GEN75_MSG_DP_CC_OWORD_DUAL_BLOCK_READ: return "OWORD dual block read";
1247 case GEN75_MSG_DP_CC_DWORD_SCATTERED_READ: return "DWORD scattered read";
1248 default: return "BAD";
1249 }
1250 case GEN7_SFID_DP_DC0:
1251 switch (op) {
1252 case GEN75_MSG_DP_DC0_OWORD_BLOCK_READ: return "OWORD block read";
1253 case GEN75_MSG_DP_DC0_UNALIGNED_OWORD_BLOCK_READ: return "unaligned OWORD block read";
1254 case GEN75_MSG_DP_DC0_OWORD_DUAL_BLOCK_READ: return "OWORD dual block read";
1255 case GEN75_MSG_DP_DC0_DWORD_SCATTERED_READ: return "DWORD scattered read";
1256 case GEN75_MSG_DP_DC0_BYTE_SCATTERED_READ: return "BYTE scattered read";
1257 case GEN75_MSG_DP_DC0_MEMORY_FENCE: return "memory fence";
1258 case GEN75_MSG_DP_DC0_OWORD_BLOCK_WRITE: return "OWORD block write";
1259 case GEN75_MSG_DP_DC0_OWORD_DUAL_BLOCK_WRITE: return "OWORD dual block write";
1260 case GEN75_MSG_DP_DC0_DWORD_SCATTERED_WRITE: return "OWORD scattered write";
1261 case GEN75_MSG_DP_DC0_BYTE_SCATTERED_WRITE: return "BYTE scattered write";
1262 default: return "BAD";
1263 }
1264 case GEN75_SFID_DP_DC1:
1265 switch (op) {
1266 case GEN75_MSG_DP_DC1_UNTYPED_SURFACE_READ: return "untyped surface read";
1267 case GEN75_MSG_DP_DC1_UNTYPED_ATOMIC_OP: return "DC untyped atomic op";
1268 case GEN75_MSG_DP_DC1_UNTYPED_ATOMIC_OP_SIMD4X2: return "DC untyped 4x2 atomic op";
1269 case GEN75_MSG_DP_DC1_MEDIA_BLOCK_READ: return "DC media block read";
1270 case GEN75_MSG_DP_DC1_TYPED_SURFACE_READ: return "DC typed surface read";
1271 case GEN75_MSG_DP_DC1_TYPED_ATOMIC_OP: return "DC typed atomic";
1272 case GEN75_MSG_DP_DC1_TYPED_ATOMIC_OP_SIMD4X2: return "DC typed 4x2 atomic op";
1273 case GEN75_MSG_DP_DC1_UNTYPED_SURFACE_WRITE: return "DC untyped surface write";
1274 case GEN75_MSG_DP_DC1_MEDIA_BLOCK_WRITE: return "DC media block write";
1275 case GEN75_MSG_DP_DC1_ATOMIC_COUNTER_OP: return "DC atomic counter op";
1276 case GEN75_MSG_DP_DC1_ATOMIC_COUNTER_OP_SIMD4X2: return "DC 4x2 atomic counter op";
1277 case GEN75_MSG_DP_DC1_TYPED_SURFACE_WRITE: return "DC typed surface write";
1278 default: return "BAD";
1279 }
1280 default: return "BAD";
1281 }
1282 }
1283
1284 static const char *
1285 disasm_inst_mdesc_dp_op(const struct disasm_inst *inst, int sfid, int op)
1286 {
1287 switch (ilo_dev_gen(inst->dev)) {
1288 case ILO_GEN(8):
1289 case ILO_GEN(7.5): return disasm_inst_mdesc_dp_op_gen75(inst, sfid, op);
1290 case ILO_GEN(7): return disasm_inst_mdesc_dp_op_gen7(inst, sfid, op);
1291 case ILO_GEN(6): return disasm_inst_mdesc_dp_op_gen6(inst, sfid, op);
1292 default: return "BAD";
1293 }
1294 }
1295
1296 static const char *
1297 disasm_inst_mdesc_dp_untyped_surface_simd_mode(const struct disasm_inst *inst,
1298 uint32_t mdesc)
1299 {
1300 switch (mdesc & GEN7_MSG_DP_UNTYPED_MODE__MASK) {
1301 case GEN7_MSG_DP_UNTYPED_MODE_SIMD4X2: return "SIMD4x2";
1302 case GEN7_MSG_DP_UNTYPED_MODE_SIMD16: return "SIMD16";
1303 case GEN7_MSG_DP_UNTYPED_MODE_SIMD8: return "SIMD8";
1304 default: return "BAD";
1305 }
1306 }
1307
1308 static const char *
1309 disasm_inst_mdesc_dp_rt_write_simd_mode(const struct disasm_inst *inst,
1310 uint32_t mdesc)
1311 {
1312 switch (mdesc & GEN6_MSG_DP_RT_MODE__MASK) {
1313 case GEN6_MSG_DP_RT_MODE_SIMD16: return "SIMD16";
1314 case GEN6_MSG_DP_RT_MODE_SIMD16_REPDATA: return "SIMD16/RepData";
1315 case GEN6_MSG_DP_RT_MODE_SIMD8_DUALSRC_LO: return "SIMD8/DualSrcLow";
1316 case GEN6_MSG_DP_RT_MODE_SIMD8_DUALSRC_HI: return "SIMD8/DualSrcHigh";
1317 case GEN6_MSG_DP_RT_MODE_SIMD8_LO: return "SIMD8";
1318 case GEN6_MSG_DP_RT_MODE_SIMD8_IMAGE_WR: return "SIMD8/ImageWrite";
1319 default: return "BAD";
1320 }
1321 }
1322
1323 static bool
1324 disasm_inst_is_null(const struct disasm_inst *inst,
1325 const struct disasm_operand *operand)
1326 {
1327 return (operand->file == GEN6_FILE_ARF && operand->reg == GEN6_ARF_NULL);
1328 }
1329
1330 static int
1331 disasm_inst_type_size(const struct disasm_inst *inst,
1332 const struct disasm_operand *operand)
1333 {
1334 assert(operand->file != GEN6_FILE_IMM);
1335
1336 switch (operand->type) {
1337 case GEN6_TYPE_UD: return 4;
1338 case GEN6_TYPE_D: return 4;
1339 case GEN6_TYPE_UW: return 2;
1340 case GEN6_TYPE_W: return 2;
1341 case GEN6_TYPE_UB: return 1;
1342 case GEN6_TYPE_B: return 1;
1343 case GEN7_TYPE_DF: return 8;
1344 case GEN6_TYPE_F: return 4;
1345 default: return 1;
1346 }
1347 }
1348
1349 static void
1350 disasm_printer_reset(struct disasm_printer *printer)
1351 {
1352 printer->buf[0] = '\0';
1353 printer->len = 0;
1354 }
1355
1356 static const char *
1357 disasm_printer_get_string(struct disasm_printer *printer)
1358 {
1359 return printer->buf;
1360 }
1361
1362 static void _util_printf_format(2, 3)
1363 disasm_printer_add(struct disasm_printer *printer, const char *format, ...)
1364 {
1365 const size_t avail = sizeof(printer->buf) - printer->len;
1366 va_list ap;
1367 int written;
1368
1369 va_start(ap, format);
1370 written = vsnprintf(printer->buf + printer->len, avail, format, ap);
1371 va_end(ap);
1372
1373 /* truncated */
1374 if (written < 0 || written >= avail) {
1375 memcpy(printer->buf + sizeof(printer->buf) - 4, "...", 4);
1376 printer->len = sizeof(printer->buf) - 1;
1377 } else {
1378 printer->len += written;
1379 }
1380 }
1381
1382 /**
1383 * Pad to the specified column.
1384 */
1385 static void
1386 disasm_printer_column(struct disasm_printer *printer, int col)
1387 {
1388 int len = DISASM_PRINTER_COLUMN_WIDTH * col;
1389
1390 if (len <= printer->len) {
1391 if (!printer->len)
1392 return;
1393
1394 /* at least one space */
1395 len = printer->len + 1;
1396 }
1397
1398 if (len >= sizeof(printer->buf)) {
1399 len = sizeof(printer->buf) - 1;
1400
1401 if (len <= printer->len)
1402 return;
1403 }
1404
1405 memset(printer->buf + printer->len, ' ', len - printer->len);
1406 printer->len = len;
1407 printer->buf[printer->len] = '\0';
1408 }
1409
1410 static void
1411 disasm_printer_add_op(struct disasm_printer *printer,
1412 const struct disasm_inst *inst)
1413 {
1414 if (inst->pred_ctrl != GEN6_PREDCTRL_NONE) {
1415 disasm_printer_add(printer, "(%c%s%s) ",
1416 disasm_inst_pred_inv(inst),
1417 disasm_inst_flag_reg(inst),
1418 disasm_inst_pred_ctrl(inst));
1419 }
1420
1421 disasm_printer_add(printer, "%s%s%s%s",
1422 disasm_inst_opcode(inst),
1423 disasm_inst_saturate(inst),
1424 disasm_inst_debug_ctrl(inst),
1425 disasm_inst_cond_modifier(inst));
1426
1427 if (inst->cond_modifier != GEN6_COND_NONE) {
1428 switch (inst->opcode) {
1429 case GEN6_OPCODE_SEL:
1430 case GEN6_OPCODE_IF:
1431 case GEN6_OPCODE_WHILE:
1432 /* these do not update flag registers */
1433 break;
1434 default:
1435 disasm_printer_add(printer, ".%s", disasm_inst_flag_reg(inst));
1436 break;
1437 }
1438 }
1439
1440 if (inst->opcode == GEN6_OPCODE_MATH)
1441 disasm_printer_add(printer, " %s", disasm_inst_fc(inst));
1442 if (inst->opcode != GEN6_OPCODE_NOP)
1443 disasm_printer_add(printer, "(%s)", disasm_inst_exec_size(inst));
1444 }
1445
1446 static void
1447 disasm_printer_add_operand(struct disasm_printer *printer,
1448 const struct disasm_inst *inst,
1449 const struct disasm_operand *operand)
1450 {
1451 const char *name;
1452 bool multi_regs;
1453
1454 name = disasm_inst_file(inst, operand, &multi_regs);
1455 if (!multi_regs) {
1456 disasm_printer_add(printer, "%s", name);
1457 return;
1458 }
1459
1460 if (operand->file == GEN6_FILE_IMM) {
1461 switch (operand->type) {
1462 case GEN6_TYPE_UD:
1463 disasm_printer_add(printer, "0x%08xUD", inst->u.imm32);
1464 break;
1465 case GEN6_TYPE_D:
1466 disasm_printer_add(printer, "%dD", inst->u.imm32);
1467 break;
1468 case GEN6_TYPE_UW:
1469 disasm_printer_add(printer, "0x%04xUW", (uint16_t) inst->u.imm32);
1470 break;
1471 case GEN6_TYPE_W:
1472 disasm_printer_add(printer, "%dW", (int16_t) inst->u.imm32);
1473 break;
1474 case GEN6_TYPE_UV_IMM:
1475 disasm_printer_add(printer, "0x%08xUV", inst->u.imm32);
1476 break;
1477 case GEN6_TYPE_VF_IMM:
1478 disasm_printer_add(printer, "Vector Float");
1479 break;
1480 case GEN6_TYPE_V_IMM:
1481 disasm_printer_add(printer, "0x%08xV", inst->u.imm32);
1482 break;
1483 case GEN6_TYPE_F:
1484 disasm_printer_add(printer, "%-gF", uif(inst->u.imm32));
1485 break;
1486 default:
1487 disasm_printer_add(printer, "BAD");
1488 break;
1489 }
1490
1491 return;
1492 }
1493
1494 if (operand->addr_mode == GEN6_ADDRMODE_DIRECT) {
1495 unsigned reg, subreg;
1496
1497 reg = operand->reg;
1498 if (operand->file == GEN6_FILE_ARF)
1499 reg &= 0xf;
1500
1501 subreg = operand->subreg / disasm_inst_type_size(inst, operand);
1502
1503 if (subreg)
1504 disasm_printer_add(printer, "%s%d.%d", name, reg, subreg);
1505 else
1506 disasm_printer_add(printer, "%s%d", name, reg);
1507 } else {
1508 disasm_printer_add(printer, "%s[a0.%d %d]",
1509 name, operand->addr_subreg, operand->addr_imm);
1510 }
1511 }
1512
1513 static void
1514 disasm_printer_add_dst(struct disasm_printer *printer,
1515 const struct disasm_inst *inst,
1516 const struct disasm_dst_operand *dst)
1517 {
1518 disasm_printer_add_operand(printer, inst, &dst->base);
1519
1520 /* dst is an immediate when in EU_INSTRUCTION_BRANCH_CONDITIONAL form */
1521 if (disasm_inst_is_null(inst, &dst->base) ||
1522 dst->base.file == GEN6_FILE_IMM)
1523 return;
1524
1525 disasm_printer_add(printer, "<%s>%s%s",
1526 disasm_inst_horz_stride(inst, dst->horz_stride),
1527 disasm_inst_writemask(inst, dst->writemask),
1528 disasm_inst_type(inst, &dst->base));
1529 }
1530
1531 static void
1532 disasm_printer_add_src(struct disasm_printer *printer,
1533 const struct disasm_inst *inst,
1534 const struct disasm_src_operand *src)
1535 {
1536 static const char swizzle_chars[4] = { 'x', 'y', 'z', 'w' };
1537 char swizzle[5];
1538
1539 disasm_printer_add(printer, "%s%s",
1540 disasm_inst_negate(inst, src->negate),
1541 disasm_inst_absolute(inst, src->absolute));
1542
1543 disasm_printer_add_operand(printer, inst, &src->base);
1544
1545 if (disasm_inst_is_null(inst, &src->base) ||
1546 src->base.file == GEN6_FILE_IMM)
1547 return;
1548
1549 if (src->swizzle_x == 0 && src->swizzle_y == 1 &&
1550 src->swizzle_z == 2 && src->swizzle_w == 3) {
1551 swizzle[0] = '\0';
1552 } else if (src->swizzle_x == src->swizzle_y &&
1553 src->swizzle_x == src->swizzle_z &&
1554 src->swizzle_x == src->swizzle_w) {
1555 swizzle[0] = swizzle_chars[src->swizzle_x];
1556 swizzle[1] = '\0';
1557 } else {
1558 swizzle[0] = swizzle_chars[src->swizzle_x];
1559 swizzle[1] = swizzle_chars[src->swizzle_y];
1560 swizzle[2] = swizzle_chars[src->swizzle_z];
1561 swizzle[3] = swizzle_chars[src->swizzle_w];
1562 swizzle[4] = '\0';
1563 }
1564
1565 disasm_printer_add(printer, "<%s,%s,%s>%s%s",
1566 disasm_inst_vert_stride(inst, src->vert_stride),
1567 disasm_inst_width(inst, src->width),
1568 disasm_inst_horz_stride(inst, src->horz_stride),
1569 swizzle,
1570 disasm_inst_type(inst, &src->base));
1571 }
1572
1573 static void
1574 disasm_printer_add_ctrl(struct disasm_printer *printer,
1575 const struct disasm_inst *inst)
1576 {
1577 if (inst->opcode == GEN6_OPCODE_NOP) {
1578 disasm_printer_add(printer, ";");
1579 return;
1580 }
1581
1582 disasm_printer_add(printer, "{%s%s%s%s%s%s%s%s };",
1583 disasm_inst_access_mode(inst),
1584 disasm_inst_mask_ctrl(inst),
1585 disasm_inst_dep_ctrl(inst),
1586 disasm_inst_qtr_ctrl(inst),
1587 disasm_inst_cmpt_ctrl(inst),
1588 disasm_inst_thread_ctrl(inst),
1589 disasm_inst_acc_wr_ctrl(inst),
1590 disasm_inst_eot(inst));
1591 }
1592
1593 static void
1594 disasm_printer_add_mdesc_sampler(struct disasm_printer *printer,
1595 const struct disasm_inst *inst,
1596 uint32_t mdesc)
1597 {
1598 int op, simd;
1599
1600 if (ilo_dev_gen(inst->dev) >= ILO_GEN(7)) {
1601 op = GEN_EXTRACT(mdesc, GEN7_MSG_SAMPLER_OP);
1602 simd = GEN_EXTRACT(mdesc, GEN7_MSG_SAMPLER_SIMD);
1603 } else {
1604 op = GEN_EXTRACT(mdesc, GEN6_MSG_SAMPLER_OP);
1605 simd = GEN_EXTRACT(mdesc, GEN6_MSG_SAMPLER_SIMD);
1606 }
1607
1608 disasm_printer_add(printer,
1609 "%s %s samp %d surf %d",
1610 disasm_inst_mdesc_sampler_op(inst, op),
1611 disasm_inst_mdesc_sampler_simd(inst, simd),
1612 GEN_EXTRACT(mdesc, GEN6_MSG_SAMPLER_INDEX),
1613 GEN_EXTRACT(mdesc, GEN6_MSG_SAMPLER_SURFACE));
1614 }
1615
1616 static void
1617 disasm_printer_add_mdesc_urb(struct disasm_printer *printer,
1618 const struct disasm_inst *inst,
1619 uint32_t mdesc)
1620 {
1621 int op, offset;
1622 bool interleaved, complete, allocate, used;
1623
1624 if (ilo_dev_gen(inst->dev) >= ILO_GEN(7)) {
1625 op = GEN_EXTRACT(mdesc, GEN7_MSG_URB_OP);
1626 offset = GEN_EXTRACT(mdesc, GEN7_MSG_URB_GLOBAL_OFFSET);
1627 interleaved = mdesc & GEN7_MSG_URB_INTERLEAVED;
1628
1629 complete = (ilo_dev_gen(inst->dev) >= ILO_GEN(8)) ?
1630 false : (mdesc & GEN7_MSG_URB_COMPLETE);
1631
1632 allocate = false;
1633 used = false;
1634 } else {
1635 op = GEN_EXTRACT(mdesc, GEN6_MSG_URB_OP);
1636 offset = GEN_EXTRACT(mdesc, GEN6_MSG_URB_OFFSET);
1637 interleaved = mdesc & GEN6_MSG_URB_INTERLEAVED;
1638 complete = mdesc & GEN6_MSG_URB_COMPLETE;
1639
1640 allocate = mdesc & GEN6_MSG_URB_ALLOCATE;
1641 used = mdesc & GEN6_MSG_URB_USED;
1642 }
1643
1644 disasm_printer_add(printer, "%s offset %d%s%s%s%s",
1645 disasm_inst_mdesc_urb_op(inst, op),
1646 offset,
1647 (interleaved) ? " interleave" : "",
1648 (allocate) ? " allocate" : "",
1649 (used) ? " used" : "",
1650 (complete) ? " complete" : "");
1651 }
1652
1653 static void
1654 disasm_printer_add_mdesc_spawner(struct disasm_printer *printer,
1655 const struct disasm_inst *inst,
1656 uint32_t mdesc)
1657 {
1658 const char *requester, *op;
1659
1660 switch (mdesc & GEN6_MSG_TS_REQUESTER_TYPE__MASK) {
1661 case GEN6_MSG_TS_REQUESTER_TYPE_ROOT: requester = "root"; break;
1662 case GEN6_MSG_TS_REQUESTER_TYPE_CHILD: requester = "child"; break;
1663 default: requester = "BAD"; break;
1664 }
1665
1666 switch (mdesc & GEN6_MSG_TS_OPCODE__MASK) {
1667 case GEN6_MSG_TS_OPCODE_DEREF:
1668 op = (mdesc & GEN6_MSG_TS_RESOURCE_SELECT_NO_DEREF) ?
1669 "no deref" : "deref";
1670 break;
1671 case GEN6_MSG_TS_OPCODE_SPAWN:
1672 op = (mdesc & GEN6_MSG_TS_RESOURCE_SELECT_ROOT) ?
1673 "spawn root" : "spawn child";
1674 break;
1675 default:
1676 op = "BAD";
1677 break;
1678 }
1679
1680 disasm_printer_add(printer, "%s thread %s", requester, op);
1681 }
1682
1683 static void
1684 disasm_printer_add_mdesc_dp_sampler(struct disasm_printer *printer,
1685 const struct disasm_inst *inst,
1686 uint32_t mdesc)
1687 {
1688 const int op = (ilo_dev_gen(inst->dev) >= ILO_GEN(7)) ?
1689 GEN_EXTRACT(mdesc, GEN7_MSG_DP_OP) : GEN_EXTRACT(mdesc, GEN6_MSG_DP_OP);
1690 const bool write_commit = (ilo_dev_gen(inst->dev) == ILO_GEN(6)) ?
1691 (mdesc & GEN6_MSG_DP_SEND_WRITE_COMMIT) : 0;
1692
1693 disasm_printer_add(printer, "%s block size %d commit %d surf %d",
1694 disasm_inst_mdesc_dp_op(inst, GEN6_SFID_DP_SAMPLER, op),
1695 GEN_EXTRACT(mdesc, GEN6_MSG_DP_OWORD_BLOCK_SIZE),
1696 write_commit,
1697 GEN_EXTRACT(mdesc, GEN6_MSG_DP_SURFACE));
1698 }
1699
1700 static void
1701 disasm_printer_add_mdesc_dp_dc0(struct disasm_printer *printer,
1702 const struct disasm_inst *inst,
1703 uint32_t mdesc)
1704 {
1705 const int op = GEN_EXTRACT(mdesc, GEN7_MSG_DP_OP);
1706
1707 ILO_DEV_ASSERT(inst->dev, 7, 7.5);
1708
1709 if (ilo_dev_gen(inst->dev) >= ILO_GEN(7.5)) {
1710 disasm_printer_add(printer, "%s ctrl 0x%x surf %d",
1711 disasm_inst_mdesc_dp_op(inst, GEN7_SFID_DP_DC0, op),
1712 GEN_EXTRACT(mdesc, GEN6_MSG_DP_CTRL),
1713 GEN_EXTRACT(mdesc, GEN6_MSG_DP_SURFACE));
1714 } else {
1715 switch (op) {
1716 case GEN7_MSG_DP_DC0_UNTYPED_SURFACE_READ:
1717 case GEN7_MSG_DP_DC0_UNTYPED_SURFACE_WRITE:
1718 disasm_printer_add(printer, "%s %s mask 0x%x surf %d",
1719 disasm_inst_mdesc_dp_op(inst, GEN7_SFID_DP_DC0, op),
1720 disasm_inst_mdesc_dp_untyped_surface_simd_mode(inst, mdesc),
1721 GEN_EXTRACT(mdesc, GEN7_MSG_DP_UNTYPED_MASK),
1722 GEN_EXTRACT(mdesc, GEN6_MSG_DP_SURFACE));
1723 break;
1724 default:
1725 disasm_printer_add(printer, "%s ctrl 0x%x surf %d",
1726 disasm_inst_mdesc_dp_op(inst, GEN7_SFID_DP_DC0, op),
1727 GEN_EXTRACT(mdesc, GEN6_MSG_DP_CTRL),
1728 GEN_EXTRACT(mdesc, GEN6_MSG_DP_SURFACE));
1729 break;
1730 }
1731 }
1732 }
1733
1734 static void
1735 disasm_printer_add_mdesc_dp_dc1(struct disasm_printer *printer,
1736 const struct disasm_inst *inst,
1737 uint32_t mdesc)
1738 {
1739 const int op = GEN_EXTRACT(mdesc, GEN7_MSG_DP_OP);
1740
1741 ILO_DEV_ASSERT(inst->dev, 7.5, 7.5);
1742
1743 switch (op) {
1744 case GEN75_MSG_DP_DC1_UNTYPED_SURFACE_READ:
1745 case GEN75_MSG_DP_DC1_UNTYPED_SURFACE_WRITE:
1746 disasm_printer_add(printer, "%s %s mask 0x%x surf %d",
1747 disasm_inst_mdesc_dp_op(inst, GEN75_SFID_DP_DC1, op),
1748 disasm_inst_mdesc_dp_untyped_surface_simd_mode(inst, mdesc),
1749 GEN_EXTRACT(mdesc, GEN7_MSG_DP_UNTYPED_MASK),
1750 GEN_EXTRACT(mdesc, GEN6_MSG_DP_SURFACE));
1751 break;
1752 default:
1753 disasm_printer_add(printer, "%s ctrl 0x%x surf %d",
1754 disasm_inst_mdesc_dp_op(inst, GEN75_SFID_DP_DC1, op),
1755 GEN_EXTRACT(mdesc, GEN6_MSG_DP_CTRL),
1756 GEN_EXTRACT(mdesc, GEN6_MSG_DP_SURFACE));
1757 break;
1758 }
1759 }
1760
1761 static void
1762 disasm_printer_add_mdesc_dp_rc(struct disasm_printer *printer,
1763 const struct disasm_inst *inst,
1764 uint32_t mdesc)
1765 {
1766 const int op = (ilo_dev_gen(inst->dev) >= ILO_GEN(7)) ?
1767 GEN_EXTRACT(mdesc, GEN7_MSG_DP_OP) : GEN_EXTRACT(mdesc, GEN6_MSG_DP_OP);
1768 bool is_rt_write;
1769
1770 if (ilo_dev_gen(inst->dev) >= ILO_GEN(7.5))
1771 is_rt_write = (op == GEN75_MSG_DP_RC_RT_WRITE);
1772 else if (ilo_dev_gen(inst->dev) >= ILO_GEN(7))
1773 is_rt_write = (op == GEN7_MSG_DP_RC_RT_WRITE);
1774 else
1775 is_rt_write = (op == GEN6_MSG_DP_RT_WRITE);
1776
1777 disasm_printer_add(printer, "%s",
1778 disasm_inst_mdesc_dp_op(inst, GEN6_SFID_DP_RC, op));
1779
1780 if (is_rt_write) {
1781 disasm_printer_add(printer, " %s%s%s%s",
1782 disasm_inst_mdesc_dp_rt_write_simd_mode(inst, mdesc),
1783 (mdesc & GEN6_MSG_DP_RT_SLOTGRP_HI) ? " Hi" : "",
1784 (mdesc & GEN6_MSG_DP_RT_LAST) ? " LastRT" : "",
1785 (ilo_dev_gen(inst->dev) == ILO_GEN(6) &&
1786 (mdesc & GEN6_MSG_DP_SEND_WRITE_COMMIT)) ? " WriteCommit" : "");
1787 }
1788
1789 disasm_printer_add(printer, " surf %d",
1790 GEN_EXTRACT(mdesc, GEN6_MSG_DP_SURFACE));
1791 }
1792
1793 static void
1794 disasm_printer_add_mdesc(struct disasm_printer *printer,
1795 const struct disasm_inst *inst)
1796 {
1797 const uint32_t mdesc = inst->u.imm32;
1798
1799 assert(inst->opcode == GEN6_OPCODE_SEND ||
1800 inst->opcode == GEN6_OPCODE_SENDC);
1801 assert(inst->src1.base.file == GEN6_FILE_IMM);
1802
1803 disasm_printer_add(printer, " %s (", disasm_inst_sfid(inst));
1804
1805 switch (inst->sfid) {
1806 case GEN6_SFID_SAMPLER:
1807 disasm_printer_add_mdesc_sampler(printer, inst, mdesc);
1808 break;
1809 case GEN6_SFID_DP_SAMPLER:
1810 disasm_printer_add_mdesc_dp_sampler(printer, inst, mdesc);
1811 break;
1812 case GEN6_SFID_DP_RC:
1813 disasm_printer_add_mdesc_dp_rc(printer, inst, mdesc);
1814 break;
1815 case GEN6_SFID_URB:
1816 disasm_printer_add_mdesc_urb(printer, inst, mdesc);
1817 break;
1818 case GEN6_SFID_SPAWNER:
1819 disasm_printer_add_mdesc_spawner(printer, inst, mdesc);
1820 break;
1821 case GEN7_SFID_DP_DC0:
1822 disasm_printer_add_mdesc_dp_dc0(printer, inst, mdesc);
1823 break;
1824 case GEN75_SFID_DP_DC1:
1825 disasm_printer_add_mdesc_dp_dc1(printer, inst, mdesc);
1826 break;
1827 case GEN6_SFID_DP_CC:
1828 case GEN7_SFID_PI:
1829 default:
1830 break;
1831 }
1832
1833 disasm_printer_add(printer, ") mlen %d rlen %d",
1834 GEN_EXTRACT(mdesc, GEN6_MSG_MLEN),
1835 GEN_EXTRACT(mdesc, GEN6_MSG_RLEN));
1836 }
1837
1838 static void
1839 disasm_printer_print_inst(struct disasm_printer *printer,
1840 const struct disasm_inst *inst)
1841 {
1842 int col = 0;
1843
1844 disasm_printer_reset(printer);
1845
1846 disasm_printer_column(printer, col++);
1847 disasm_printer_add_op(printer, inst);
1848
1849 if (inst->has_jip || inst->has_uip) {
1850 if (inst->has_jip) {
1851 disasm_printer_column(printer, col++);
1852 disasm_printer_add(printer, "JIP: %d", (int16_t) inst->u.imm32);
1853 }
1854
1855 if (inst->has_uip) {
1856 disasm_printer_column(printer, col++);
1857 disasm_printer_add(printer, "UIP: %d",
1858 (int16_t) (inst->u.imm32 >> 16));
1859 }
1860 } else {
1861 const int src_count = disasm_opcode_table[inst->opcode].src_count;
1862
1863 if (src_count) {
1864 const struct disasm_src_operand *src[3] = {
1865 &inst->src0, &inst->src1, &inst->u.src2
1866 };
1867 int i;
1868
1869 disasm_printer_column(printer, col++);
1870 disasm_printer_add_dst(printer, inst, &inst->dst);
1871
1872 for (i = 0; i < src_count; i++) {
1873 disasm_printer_column(printer, col++);
1874 disasm_printer_add_src(printer, inst, src[i]);
1875 }
1876 }
1877 }
1878
1879 if (inst->opcode == GEN6_OPCODE_SEND ||
1880 inst->opcode == GEN6_OPCODE_SENDC) {
1881 /* start a new line */
1882 ilo_printf("%s\n", disasm_printer_get_string(printer));
1883 disasm_printer_reset(printer);
1884 col = 0;
1885
1886 disasm_printer_column(printer, col++);
1887
1888 disasm_printer_column(printer, col++);
1889 disasm_printer_add_mdesc(printer, inst);
1890 }
1891
1892 if (col < 4)
1893 col = 4;
1894
1895 disasm_printer_column(printer, col++);
1896 disasm_printer_add_ctrl(printer, inst);
1897
1898 ilo_printf("%s\n", disasm_printer_get_string(printer));
1899 }
1900
1901 static void
1902 disasm_uncompact_3src(const struct ilo_dev_info *dev,
1903 uint64_t compact, uint32_t *dw)
1904 {
1905 const struct toy_compaction_table *tbl =
1906 toy_compiler_get_compaction_table(dev);
1907 uint32_t src[3], tmp;
1908 uint64_t tmp64;
1909
1910 ILO_DEV_ASSERT(dev, 8, 8);
1911
1912 tmp = GEN_EXTRACT(compact, GEN8_COMPACT_3SRC_OPCODE);
1913 dw[0] = GEN_SHIFT32(tmp, GEN6_INST_OPCODE);
1914
1915 /* ControlIndex */
1916 tmp = GEN_EXTRACT(compact, GEN8_COMPACT_3SRC_CONTROL_INDEX);
1917 tmp = tbl->control_3src[tmp];
1918
1919 dw[0] |= (tmp & 0x1fffff) << GEN6_INST_ACCESSMODE__SHIFT;
1920 dw[1] = (tmp >> 21) & ((ilo_dev_gen(dev) >= ILO_GEN(9)) ? 0x1f : 0x7);
1921
1922 /* SourceIndex */
1923 tmp = GEN_EXTRACT(compact, GEN8_COMPACT_3SRC_SOURCE_INDEX);
1924 tmp64 = tbl->source_3src[tmp];
1925
1926 dw[1] |= (tmp64 & 0x7ffff) << 5;
1927 src[0] = ((tmp64 >> 19) & 0xff) << 1;
1928 src[1] = ((tmp64 >> 27) & 0xff) << 1;
1929 src[2] = ((tmp64 >> 35) & 0xff) << 1;
1930 if (ilo_dev_gen(dev) >= ILO_GEN(9)) {
1931 src[0] |= ((tmp64 >> 43) & 0x3) << 19;
1932 src[1] |= ((tmp64 >> 45) & 0x3) << 19;
1933 src[2] |= ((tmp64 >> 47) & 0x3) << 19;
1934 } else {
1935 src[0] |= ((tmp64 >> 43) & 0x1) << 19;
1936 src[1] |= ((tmp64 >> 44) & 0x1) << 19;
1937 src[2] |= ((tmp64 >> 45) & 0x1) << 19;
1938 }
1939
1940 tmp = GEN_EXTRACT(compact, GEN8_COMPACT_3SRC_DST_REG);
1941 dw[1] |= GEN_SHIFT32(tmp, GEN6_3SRC_DST_REG);
1942
1943 if (compact & GEN8_COMPACT_3SRC_SRC0_REPCTRL)
1944 src[0] |= GEN6_3SRC_SRC_REPCTRL;
1945
1946 assert(compact & GEN8_COMPACT_3SRC_CMPTCTRL);
1947
1948 if (compact & GEN8_COMPACT_3SRC_DEBUGCTRL)
1949 dw[0] |= GEN6_INST_DEBUGCTRL;
1950 if (compact & GEN8_COMPACT_3SRC_SATURATE)
1951 dw[0] |= GEN6_INST_SATURATE;
1952
1953 if (compact & GEN8_COMPACT_3SRC_SRC1_REPCTRL)
1954 src[1] |= GEN6_3SRC_SRC_REPCTRL;
1955 if (compact & GEN8_COMPACT_3SRC_SRC2_REPCTRL)
1956 src[2] |= GEN6_3SRC_SRC_REPCTRL;
1957
1958 tmp = GEN_EXTRACT(compact, GEN8_COMPACT_3SRC_SRC0_SUBREG);
1959 src[0] |= GEN_SHIFT32(tmp, GEN6_3SRC_SRC_SUBREG);
1960 tmp = GEN_EXTRACT(compact, GEN8_COMPACT_3SRC_SRC1_SUBREG);
1961 src[1] |= GEN_SHIFT32(tmp, GEN6_3SRC_SRC_SUBREG);
1962 tmp = GEN_EXTRACT(compact, GEN8_COMPACT_3SRC_SRC2_SUBREG);
1963 src[2] |= GEN_SHIFT32(tmp, GEN6_3SRC_SRC_SUBREG);
1964
1965 tmp = GEN_EXTRACT(compact, GEN8_COMPACT_3SRC_SRC0_REG);
1966 src[0] |= GEN_SHIFT32(tmp, GEN6_3SRC_SRC_REG);
1967 tmp = GEN_EXTRACT(compact, GEN8_COMPACT_3SRC_SRC1_REG);
1968 src[1] |= GEN_SHIFT32(tmp, GEN6_3SRC_SRC_REG);
1969 tmp = GEN_EXTRACT(compact, GEN8_COMPACT_3SRC_SRC2_REG);
1970 src[2] |= GEN_SHIFT32(tmp, GEN6_3SRC_SRC_REG);
1971
1972 tmp64 = (uint64_t) src[2] << 42 |
1973 (uint64_t) src[1] << 21 |
1974 (uint64_t) src[0];
1975 dw[2] = (uint32_t) tmp64;
1976 dw[3] = (uint32_t) (tmp64 >> 32);
1977 }
1978
1979 static void
1980 disasm_uncompact(const struct ilo_dev_info *dev,
1981 uint64_t compact, uint32_t *dw)
1982 {
1983 const struct toy_compaction_table *tbl =
1984 toy_compiler_get_compaction_table(dev);
1985 bool src_is_imm;
1986 uint32_t tmp;
1987
1988 ILO_DEV_ASSERT(dev, 6, 8);
1989
1990 tmp = GEN_EXTRACT(compact, GEN6_COMPACT_OPCODE);
1991 if (disasm_opcode_table[tmp].src_count == 3) {
1992 disasm_uncompact_3src(dev, compact, dw);
1993 return;
1994 }
1995
1996 memset(dw, 0, sizeof(*dw) * 4);
1997
1998 dw[0] |= GEN_SHIFT32(tmp, GEN6_INST_OPCODE);
1999
2000 if (ilo_dev_gen(dev) >= ILO_GEN(7) && (compact & GEN6_COMPACT_DEBUGCTRL))
2001 dw[0] |= GEN6_INST_DEBUGCTRL;
2002
2003 /* ControlIndex */
2004 tmp = GEN_EXTRACT(compact, GEN6_COMPACT_CONTROL_INDEX);
2005 tmp = tbl->control[tmp];
2006
2007 dw[0] |= (tmp & 0xffff) << GEN6_INST_ACCESSMODE__SHIFT;
2008 if (tmp & 0x10000)
2009 dw[0] |= GEN6_INST_SATURATE;
2010
2011 if (ilo_dev_gen(dev) >= ILO_GEN(7))
2012 dw[2] |= (tmp >> 17) << GEN6_INST_FLAG_SUBREG__SHIFT;
2013
2014 /* DataTypeIndex */
2015 tmp = GEN_EXTRACT(compact, GEN6_COMPACT_DATATYPE_INDEX);
2016 tmp = tbl->datatype[tmp];
2017
2018 dw[1] |= (tmp & 0x7fff) << GEN6_INST_DST_FILE__SHIFT;
2019 dw[1] |= (tmp >> 15) << GEN6_INST_DST_HORZSTRIDE__SHIFT;
2020
2021 /* SubRegIndex */
2022 tmp = GEN_EXTRACT(compact, GEN6_COMPACT_SUBREG_INDEX);
2023 tmp = tbl->subreg[tmp];
2024
2025 dw[1] |= (tmp & 0x1f) << 16;
2026 dw[2] |= ((tmp >> 5) & 0x1f);
2027 dw[3] |= ((tmp >> 10) & 0x1f);
2028
2029 if (compact & GEN6_COMPACT_ACCWRCTRL)
2030 dw[0] |= GEN6_INST_ACCWRCTRL;
2031
2032 tmp = GEN_EXTRACT(compact, GEN6_COMPACT_CONDMODIFIER);
2033 dw[0] |= GEN_SHIFT32(tmp, GEN6_INST_CONDMODIFIER);
2034
2035 if (ilo_dev_gen(dev) == ILO_GEN(6)) {
2036 tmp = GEN_EXTRACT(compact, GEN6_COMPACT_FLAG_SUBREG);
2037 dw[2] |= GEN_SHIFT32(compact, GEN6_INST_FLAG_SUBREG);
2038 }
2039
2040 assert(compact & GEN6_COMPACT_CMPTCTRL);
2041
2042 /* Src0Index */
2043 tmp = GEN_EXTRACT(compact, GEN6_COMPACT_SRC0_INDEX);
2044 tmp = tbl->src[tmp];
2045 dw[2] |= tmp << 13;
2046
2047 src_is_imm = (GEN_EXTRACT(dw[1], GEN6_INST_SRC0_FILE) == GEN6_FILE_IMM) ||
2048 (GEN_EXTRACT(dw[1], GEN6_INST_SRC1_FILE) == GEN6_FILE_IMM);
2049
2050 /* Src1Index */
2051 tmp = GEN_EXTRACT(compact, GEN6_COMPACT_SRC1_INDEX);
2052 if (src_is_imm) {
2053 if (tmp & 0x10)
2054 tmp |= 0xfffff0;
2055 dw[3] |= tmp << 8;
2056 } else {
2057 tmp = tbl->src[tmp];
2058 dw[3] |= tmp << 13;
2059 }
2060
2061 tmp = GEN_EXTRACT(compact, GEN6_COMPACT_DST_REG);
2062 dw[1] |= GEN_SHIFT32(tmp, GEN6_INST_DST_REG);
2063
2064 tmp = GEN_EXTRACT(compact, GEN6_COMPACT_SRC0_REG);
2065 dw[2] |= GEN_SHIFT32(tmp, GEN6_INST_SRC_REG);
2066
2067 tmp = GEN_EXTRACT(compact, GEN6_COMPACT_SRC1_REG);
2068 if (src_is_imm)
2069 dw[3] |= tmp;
2070 else
2071 dw[3] |= GEN_SHIFT32(tmp, GEN6_INST_SRC_REG);
2072 }
2073
2074 void
2075 toy_compiler_disassemble(const struct ilo_dev_info *dev,
2076 const void *kernel, int size,
2077 bool dump_hex)
2078 {
2079 const uint32_t *cur = (const uint32_t *) kernel;
2080 const uint32_t *end = cur + size / sizeof(*cur);
2081 struct disasm_printer printer;
2082
2083 disasm_printer_reset(&printer);
2084
2085 while (cur < end) {
2086 struct disasm_inst inst;
2087 const bool compacted = (cur[0] & GEN6_INST_CMPTCTRL);
2088 const uint32_t *dw = cur;
2089 uint32_t temp[4];
2090
2091 cur += (compacted) ? 2 : 4;
2092 /* incomplete instruction */
2093 if (cur > end)
2094 break;
2095
2096 if (compacted) {
2097 const uint64_t compact = (uint64_t) dw[1] << 32 | dw[0];
2098 disasm_uncompact(dev, compact, temp);
2099 dw = temp;
2100 }
2101
2102 if (dump_hex) {
2103 ilo_printf("0x%08x 0x%08x 0x%08x 0x%08x ",
2104 dw[0], dw[1], dw[2], dw[3]);
2105 }
2106
2107 memset(&inst, 0, sizeof(inst));
2108 inst.dev = dev;
2109 disasm_inst_decode(&inst, dw);
2110 inst.cmpt_ctrl = compacted;
2111
2112 disasm_printer_print_inst(&printer, &inst);
2113 }
2114 }