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