2 * Mesa 3-D graphics library
4 * Copyright (C) 2014 LunarG, Inc.
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:
13 * The above copyright notice and this permission notice shall be included
14 * in all copies or substantial portions of the Software.
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.
25 * Chia-I Wu <olv@lunarg.com>
29 #include "genhw/genhw.h"
30 #include "toy_compiler.h"
32 #define DISASM_PRINTER_BUFFER_SIZE 256
33 #define DISASM_PRINTER_COLUMN_WIDTH 16
35 struct disasm_printer
{
36 char buf
[DISASM_PRINTER_BUFFER_SIZE
];
40 struct disasm_operand
{
47 unsigned addr_subreg
:3;
51 struct disasm_dst_operand
{
52 struct disasm_operand base
;
54 unsigned horz_stride
:2;
58 struct disasm_src_operand
{
59 struct disasm_operand base
;
61 unsigned vert_stride
:4;
63 unsigned horz_stride
:2;
73 const struct ilo_dev_info
*dev
;
79 unsigned access_mode
:1;
83 unsigned thread_ctrl
:2;
88 unsigned cond_modifier
:4;
92 unsigned acc_wr_ctrl
:1;
94 unsigned debug_ctrl
:1;
100 unsigned flag_subreg
:1;
102 struct disasm_dst_operand dst
;
103 struct disasm_src_operand src0
;
104 struct disasm_src_operand src1
;
106 struct disasm_src_operand src2
;
111 static const struct {
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 },
184 disasm_inst_decode_dw0_gen6(struct disasm_inst
*inst
, uint32_t dw0
)
186 inst
->opcode
= GEN_EXTRACT(dw0
, GEN6_INST_OPCODE
);
188 switch (inst
->opcode
) {
190 inst
->has_jip
= true;
191 inst
->has_uip
= (inst
->dev
->gen
>= ILO_GEN(7));
193 case GEN6_OPCODE_BREAK
:
194 case GEN6_OPCODE_CONT
:
195 case GEN6_OPCODE_HALT
:
196 inst
->has_uip
= true;
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;
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
);
221 inst
->pred_inv
= (bool) (dw0
& GEN6_INST_PREDINV
);
223 inst
->exec_size
= GEN_EXTRACT(dw0
, GEN6_INST_EXECSIZE
);
225 switch (inst
->opcode
) {
226 case GEN6_OPCODE_SEND
:
227 case GEN6_OPCODE_SENDC
:
228 inst
->sfid
= GEN_EXTRACT(dw0
, GEN6_INST_SFID
);
230 case GEN6_OPCODE_MATH
:
231 inst
->fc
= GEN_EXTRACT(dw0
, GEN6_INST_FC
);
234 inst
->cond_modifier
= GEN_EXTRACT(dw0
, GEN6_INST_CONDMODIFIER
);
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
);
245 disasm_inst_jip_in_dw1_high_gen6(const struct disasm_inst
*inst
)
247 return (inst
->dev
->gen
== ILO_GEN(6) && inst
->has_jip
&& !inst
->has_uip
);
251 disasm_inst_decode_dw1_gen6(struct disasm_inst
*inst
, uint32_t dw1
)
253 inst
->dst
.base
.file
= GEN_EXTRACT(dw1
, GEN6_INST_DST_FILE
);
254 inst
->dst
.base
.type
= GEN_EXTRACT(dw1
, GEN6_INST_DST_TYPE
);
255 inst
->src0
.base
.file
= GEN_EXTRACT(dw1
, GEN6_INST_SRC0_FILE
);
256 inst
->src0
.base
.type
= GEN_EXTRACT(dw1
, GEN6_INST_SRC0_TYPE
);
257 inst
->src1
.base
.file
= GEN_EXTRACT(dw1
, GEN6_INST_SRC1_FILE
);
258 inst
->src1
.base
.type
= GEN_EXTRACT(dw1
, GEN6_INST_SRC1_TYPE
);
260 if (inst
->dev
->gen
>= ILO_GEN(7))
261 inst
->nib_ctrl
= (bool) (dw1
& GEN7_INST_NIBCTRL
);
263 if (disasm_inst_jip_in_dw1_high_gen6(inst
)) {
264 inst
->u
.imm32
= dw1
>> 16;
268 inst
->dst
.base
.addr_mode
= GEN_EXTRACT(dw1
, GEN6_INST_DST_ADDRMODE
);
270 if (inst
->dst
.base
.addr_mode
== GEN6_ADDRMODE_DIRECT
) {
271 inst
->dst
.base
.reg
= GEN_EXTRACT(dw1
, GEN6_INST_DST_REG
);
273 if (inst
->access_mode
== GEN6_ALIGN_1
) {
274 inst
->dst
.base
.subreg
= GEN_EXTRACT(dw1
, GEN6_INST_DST_SUBREG
);
276 inst
->dst
.base
.subreg
=
277 GEN_EXTRACT(dw1
, GEN6_INST_DST_SUBREG_ALIGN16
) <<
278 GEN6_INST_DST_SUBREG_ALIGN16__SHR
;
281 inst
->dst
.base
.addr_subreg
= GEN_EXTRACT(dw1
, GEN6_INST_DST_ADDR_SUBREG
);
283 if (inst
->access_mode
== GEN6_ALIGN_1
) {
284 inst
->dst
.base
.addr_imm
= GEN_EXTRACT(dw1
, GEN6_INST_DST_ADDR_IMM
);
286 inst
->dst
.base
.addr_imm
= GEN_EXTRACT(dw1
,
287 GEN6_INST_DST_ADDR_IMM_ALIGN16
) <<
288 GEN6_INST_DST_ADDR_IMM_ALIGN16__SHR
;
292 inst
->dst
.horz_stride
= GEN_EXTRACT(dw1
, GEN6_INST_DST_HORZSTRIDE
);
294 if (inst
->access_mode
== GEN6_ALIGN_1
)
295 inst
->dst
.writemask
= 0xf;
297 inst
->dst
.writemask
= GEN_EXTRACT(dw1
, GEN6_INST_DST_WRITEMASK
);
301 disasm_inst_decode_dw2_dw3_gen6(struct disasm_inst
*inst
,
302 uint32_t dw2
, uint32_t dw3
)
306 if (inst
->dev
->gen
>= ILO_GEN(7))
307 inst
->flag_reg
= GEN_EXTRACT(dw2
, GEN7_INST_FLAG_REG
);
309 inst
->flag_subreg
= GEN_EXTRACT(dw2
, GEN6_INST_FLAG_SUBREG
);
311 if (inst
->src0
.base
.file
== GEN6_FILE_IMM
||
312 inst
->src1
.base
.file
== GEN6_FILE_IMM
) {
314 if (!disasm_inst_jip_in_dw1_high_gen6(inst
))
320 for (i
= 0; i
< count
; i
++) {
321 struct disasm_src_operand
*src
= (i
== 0) ? &inst
->src0
: &inst
->src1
;
322 const uint32_t dw
= (i
== 0) ? dw2
: dw3
;
324 src
->base
.addr_mode
= GEN_EXTRACT(dw
, GEN6_INST_SRC_ADDRMODE
);
326 if (src
->base
.addr_mode
== GEN6_ADDRMODE_DIRECT
) {
327 src
->base
.reg
= GEN_EXTRACT(dw
, GEN6_INST_SRC_REG
);
329 if (inst
->access_mode
== GEN6_ALIGN_1
) {
330 src
->base
.subreg
= GEN_EXTRACT(dw
, GEN6_INST_SRC_SUBREG
);
332 src
->base
.subreg
= GEN_EXTRACT(dw
, GEN6_INST_SRC_SUBREG_ALIGN16
) <<
333 GEN6_INST_SRC_SUBREG_ALIGN16__SHR
;
336 src
->base
.addr_subreg
= GEN_EXTRACT(dw
, GEN6_INST_SRC_ADDR_SUBREG
);
338 if (inst
->access_mode
== GEN6_ALIGN_1
) {
339 src
->base
.addr_imm
= GEN_EXTRACT(dw
, GEN6_INST_SRC_ADDR_IMM
);
342 GEN_EXTRACT(dw
, GEN6_INST_SRC_ADDR_IMM_ALIGN16
) <<
343 GEN6_INST_SRC_ADDR_IMM_ALIGN16__SHR
;
347 src
->vert_stride
= GEN_EXTRACT(dw
, GEN6_INST_SRC_VERTSTRIDE
);
349 if (inst
->access_mode
== GEN6_ALIGN_1
) {
350 src
->width
= GEN_EXTRACT(dw
, GEN6_INST_SRC_WIDTH
);
351 src
->horz_stride
= GEN_EXTRACT(dw
, GEN6_INST_SRC_HORZSTRIDE
);
353 src
->swizzle_x
= GEN6_SWIZZLE_X
;
354 src
->swizzle_y
= GEN6_SWIZZLE_Y
;
355 src
->swizzle_z
= GEN6_SWIZZLE_Z
;
356 src
->swizzle_w
= GEN6_SWIZZLE_W
;
358 src
->width
= GEN6_WIDTH_4
;
359 src
->horz_stride
= GEN6_HORZSTRIDE_1
;
361 src
->swizzle_x
= GEN_EXTRACT(dw
, GEN6_INST_SRC_SWIZZLE_X
);
362 src
->swizzle_y
= GEN_EXTRACT(dw
, GEN6_INST_SRC_SWIZZLE_Y
);
363 src
->swizzle_z
= GEN_EXTRACT(dw
, GEN6_INST_SRC_SWIZZLE_Z
);
364 src
->swizzle_w
= GEN_EXTRACT(dw
, GEN6_INST_SRC_SWIZZLE_W
);
367 src
->negate
= (bool) (dw
& GEN6_INST_SRC_NEGATE
);
368 src
->absolute
= (bool) (dw
& GEN6_INST_SRC_ABSOLUTE
);
373 disasm_inst_decode_3src_dw1_gen6(struct disasm_inst
*inst
, uint32_t dw1
)
375 static unsigned type_mapping
[4] = {
376 [GEN7_TYPE_F_3SRC
] = GEN6_TYPE_F
,
377 [GEN7_TYPE_D_3SRC
] = GEN6_TYPE_D
,
378 [GEN7_TYPE_UD_3SRC
] = GEN6_TYPE_UD
,
379 [GEN7_TYPE_DF_3SRC
] = GEN7_TYPE_DF
,
382 inst
->flag_subreg
= GEN_EXTRACT(dw1
, GEN6_3SRC_FLAG_SUBREG
);
384 if (inst
->dev
->gen
>= ILO_GEN(7)) {
385 inst
->nib_ctrl
= (bool) (dw1
& GEN7_3SRC_NIBCTRL
);
386 inst
->flag_reg
= GEN_EXTRACT(dw1
, GEN7_3SRC_FLAG_REG
);
388 inst
->dst
.base
.file
= GEN6_FILE_GRF
;
389 inst
->dst
.base
.type
= GEN_EXTRACT(dw1
, GEN7_3SRC_DST_TYPE
);
390 inst
->dst
.base
.type
= type_mapping
[inst
->dst
.base
.type
];
392 inst
->src0
.base
.type
= GEN_EXTRACT(dw1
, GEN7_3SRC_SRC_TYPE
);
393 inst
->src0
.base
.type
= type_mapping
[inst
->src0
.base
.type
];
395 inst
->src1
.base
.type
= inst
->src0
.base
.type
;
396 inst
->u
.src2
.base
.type
= inst
->src0
.base
.type
;
398 inst
->dst
.base
.file
= (dw1
& GEN6_3SRC_DST_FILE_MRF
) ?
399 GEN6_FILE_MRF
: GEN6_FILE_GRF
;
400 inst
->dst
.base
.type
= GEN6_TYPE_F
;
402 inst
->src0
.base
.type
= GEN6_TYPE_F
;
403 inst
->src1
.base
.type
= GEN6_TYPE_F
;
404 inst
->u
.src2
.base
.type
= GEN6_TYPE_F
;
407 inst
->dst
.base
.addr_mode
= GEN6_ADDRMODE_DIRECT
;
408 inst
->dst
.base
.reg
= GEN_EXTRACT(dw1
, GEN6_3SRC_DST_REG
);
409 inst
->dst
.base
.subreg
= GEN_EXTRACT(dw1
, GEN6_3SRC_DST_SUBREG
) <<
410 GEN6_3SRC_DST_SUBREG__SHR
;
412 inst
->dst
.horz_stride
= GEN6_HORZSTRIDE_1
;
413 inst
->dst
.writemask
= GEN_EXTRACT(dw1
, GEN6_3SRC_DST_WRITEMASK
);
415 inst
->src0
.base
.file
= GEN6_FILE_GRF
;
416 inst
->src0
.negate
= (bool) (dw1
& GEN6_3SRC_SRC0_NEGATE
);
417 inst
->src0
.absolute
= (bool) (dw1
& GEN6_3SRC_SRC0_ABSOLUTE
);
418 inst
->src1
.base
.file
= GEN6_FILE_GRF
;
419 inst
->src1
.negate
= (bool) (dw1
& GEN6_3SRC_SRC1_NEGATE
);
420 inst
->src1
.absolute
= (bool) (dw1
& GEN6_3SRC_SRC1_ABSOLUTE
);
421 inst
->u
.src2
.base
.file
= GEN6_FILE_GRF
;
422 inst
->u
.src2
.negate
= (bool) (dw1
& GEN6_3SRC_SRC2_NEGATE
);
423 inst
->u
.src2
.absolute
= (bool) (dw1
& GEN6_3SRC_SRC2_ABSOLUTE
);
427 disasm_inst_decode_3src_dw2_dw3_gen6(struct disasm_inst
*inst
,
428 uint32_t dw2
, uint32_t dw3
)
430 const uint64_t qw
= (uint64_t) dw3
<< 32 | dw2
;
433 for (i
= 0; i
< 3; i
++) {
434 struct disasm_src_operand
*src
= (i
== 0) ? &inst
->src0
:
435 (i
== 1) ? &inst
->src1
:
437 const uint32_t dw
= (i
== 0) ? GEN_EXTRACT(qw
, GEN6_3SRC_SRC_0
) :
438 (i
== 1) ? GEN_EXTRACT(qw
, GEN6_3SRC_SRC_1
) :
439 GEN_EXTRACT(qw
, GEN6_3SRC_SRC_2
);
441 src
->base
.addr_mode
= GEN6_ADDRMODE_DIRECT
;
442 src
->base
.reg
= GEN_EXTRACT(dw
, GEN6_3SRC_SRC_REG
);
443 src
->base
.subreg
= GEN_EXTRACT(dw
, GEN6_3SRC_SRC_SUBREG
) <<
444 GEN6_3SRC_SRC_SUBREG__SHR
;
446 if (dw
& GEN6_3SRC_SRC_REPCTRL
) {
447 src
->vert_stride
= GEN6_VERTSTRIDE_0
;
448 src
->width
= GEN6_WIDTH_1
;
449 src
->horz_stride
= GEN6_HORZSTRIDE_0
;
451 src
->vert_stride
= GEN6_VERTSTRIDE_4
;
452 src
->width
= GEN6_WIDTH_4
;
453 src
->horz_stride
= GEN6_HORZSTRIDE_1
;
456 src
->swizzle_x
= GEN_EXTRACT(dw
, GEN6_3SRC_SRC_SWIZZLE_X
);
457 src
->swizzle_y
= GEN_EXTRACT(dw
, GEN6_3SRC_SRC_SWIZZLE_Y
);
458 src
->swizzle_z
= GEN_EXTRACT(dw
, GEN6_3SRC_SRC_SWIZZLE_Z
);
459 src
->swizzle_w
= GEN_EXTRACT(dw
, GEN6_3SRC_SRC_SWIZZLE_W
);
464 * When GEN6_INST_CMPTCTRL of DW0 is set, the instruction has 64 bits and is
465 * in EU_INSTRUCTION_COMPACT_TWO_SRC form. We should have expanded it to its
468 * Depending on the opcode, the 128-bits instruction is in one of the
471 * - EU_INSTRUCTION_BASIC_ONE_SRC
472 * - EU_INSTRUCTION_BASIC_TWO_SRC
473 * - EU_INSTRUCTION_BASIC_THREE_SRC
474 * - EU_INSTRUCTION_BRANCH_CONDITIONAL
475 * - EU_INSTRUCTION_BRANCH_ONE_SRC
476 * - EU_INSTRUCTION_BRANCH_TWO_SRC
477 * - EU_INSTRUCTION_ILLEGAL
478 * - EU_INSTRUCTION_MATH
479 * - EU_INSTRUCTION_NOP
480 * - EU_INSTRUCTION_SEND
482 * In EU_INSTRUCTION_BASIC_ONE_SRC form,
484 * - DW0 is EU_INSTRUCTION_HEADER
485 * - DW1 is EU_INSTRUCTION_OPERAND_CONTROLS
486 * - DW2 is Source 0 and EU_INSTRUCTION_FLAGS
487 * - DW3 is reserved unless Source 0 is an immediate
489 * All other forms except EU_INSTRUCTION_BASIC_THREE_SRC are quite compatible
490 * with EU_INSTRUCTION_BASIC_ONE_SRC.
493 disasm_inst_decode(struct disasm_inst
*inst
,
496 assert(!(dw
[0] & GEN6_INST_CMPTCTRL
));
498 disasm_inst_decode_dw0_gen6(inst
, dw
[0]);
500 switch (inst
->opcode
) {
501 case GEN7_OPCODE_CSEL
:
502 case GEN7_OPCODE_BFE
:
503 case GEN7_OPCODE_BFI2
:
504 case GEN6_OPCODE_MAD
:
505 case GEN6_OPCODE_LRP
:
506 disasm_inst_decode_3src_dw1_gen6(inst
, dw
[1]);
507 disasm_inst_decode_3src_dw2_dw3_gen6(inst
, dw
[2], dw
[3]);
510 disasm_inst_decode_dw1_gen6(inst
, dw
[1]);
511 disasm_inst_decode_dw2_dw3_gen6(inst
, dw
[2], dw
[3]);
517 disasm_inst_opcode(const struct disasm_inst
*inst
)
519 return (disasm_opcode_table
[inst
->opcode
].name
) ?
520 disasm_opcode_table
[inst
->opcode
].name
: "BAD";
524 disasm_inst_pred_ctrl(const struct disasm_inst
*inst
)
526 if (inst
->access_mode
== GEN6_ALIGN_1
) {
527 switch (inst
->pred_ctrl
) {
528 case GEN6_PREDCTRL_NORMAL
: return "";
529 case GEN6_PREDCTRL_ANYV
: return ".anyv";
530 case GEN6_PREDCTRL_ALLV
: return ".allv";
531 case GEN6_PREDCTRL_ANY2H
: return ".any2h";
532 case GEN6_PREDCTRL_ALL2H
: return ".all2h";
533 case GEN6_PREDCTRL_ANY4H
: return ".any4h";
534 case GEN6_PREDCTRL_ALL4H
: return ".all4h";
535 case GEN6_PREDCTRL_ANY8H
: return ".any8h";
536 case GEN6_PREDCTRL_ALL8H
: return ".all8h";
537 case GEN6_PREDCTRL_ANY16H
: return ".any16h";
538 case GEN6_PREDCTRL_ALL16H
: return ".all16h";
539 case GEN7_PREDCTRL_ANY32H
: return ".any32h";
540 case GEN7_PREDCTRL_ALL32H
: return ".all32h";
541 default: return ".BAD";
544 switch (inst
->pred_ctrl
) {
545 case GEN6_PREDCTRL_NORMAL
: return "";
546 case GEN6_PREDCTRL_X
: return ".x";
547 case GEN6_PREDCTRL_Y
: return ".y";
548 case GEN6_PREDCTRL_Z
: return ".z";
549 case GEN6_PREDCTRL_W
: return ".w";
550 default: return ".BAD";
556 disasm_inst_pred_inv(const struct disasm_inst
*inst
)
558 return (inst
->pred_inv
) ? '-' : '+';
562 disasm_inst_exec_size(const struct disasm_inst
*inst
)
564 switch (inst
->exec_size
) {
565 case GEN6_EXECSIZE_1
: return "1";
566 case GEN6_EXECSIZE_2
: return "2";
567 case GEN6_EXECSIZE_4
: return "4";
568 case GEN6_EXECSIZE_8
: return "8";
569 case GEN6_EXECSIZE_16
: return "16";
570 case GEN6_EXECSIZE_32
: return "32";
571 default: return "BAD";
576 disasm_inst_fc(const struct disasm_inst
*inst
)
578 assert(inst
->opcode
== GEN6_OPCODE_MATH
);
581 case GEN6_MATH_INV
: return "inv";
582 case GEN6_MATH_LOG
: return "log";
583 case GEN6_MATH_EXP
: return "exp";
584 case GEN6_MATH_SQRT
: return "sqrt";
585 case GEN6_MATH_RSQ
: return "rsq";
586 case GEN6_MATH_SIN
: return "sin";
587 case GEN6_MATH_COS
: return "cos";
588 case GEN6_MATH_FDIV
: return "fdiv";
589 case GEN6_MATH_POW
: return "pow";
590 case GEN6_MATH_INT_DIV
: return "int_div";
591 case GEN6_MATH_INT_DIV_QUOTIENT
: return "int_div_quotient";
592 case GEN6_MATH_INT_DIV_REMAINDER
: return "int_div_remainder";
593 default: return "BAD";
598 disasm_inst_sfid(const struct disasm_inst
*inst
)
600 assert(inst
->opcode
== GEN6_OPCODE_SEND
||
601 inst
->opcode
== GEN6_OPCODE_SENDC
);
603 switch (inst
->sfid
) {
604 case GEN6_SFID_NULL
: return "null";
605 case GEN6_SFID_SAMPLER
: return "sampler";
606 case GEN6_SFID_GATEWAY
: return "gateway";
607 case GEN6_SFID_DP_SAMPLER
: return "dp sampler";
608 case GEN6_SFID_DP_RC
: return "dp render";
609 case GEN6_SFID_URB
: return "urb";
610 case GEN6_SFID_SPAWNER
: return "spawner";
611 case GEN6_SFID_VME
: return "vme";
612 case GEN6_SFID_DP_CC
: return "dp const";
613 case GEN7_SFID_DP_DC0
: return "dp data 0";
614 case GEN7_SFID_PI
: return "pixel interp";
615 case GEN75_SFID_DP_DC1
: return "dp data 1";
616 default: return "BAD";
621 disasm_inst_cond_modifier(const struct disasm_inst
*inst
)
623 switch (inst
->cond_modifier
) {
624 case GEN6_COND_NONE
: return "";
625 case GEN6_COND_Z
: return ".z";
626 case GEN6_COND_NZ
: return ".nz";
627 case GEN6_COND_G
: return ".g";
628 case GEN6_COND_GE
: return ".ge";
629 case GEN6_COND_L
: return ".l";
630 case GEN6_COND_LE
: return ".le";
631 case GEN6_COND_O
: return ".o";
632 case GEN6_COND_U
: return ".u";
633 default: return ".BAD";
638 disasm_inst_debug_ctrl(const struct disasm_inst
*inst
)
640 return (inst
->debug_ctrl
) ? ".breakpoint" : "";
644 disasm_inst_saturate(const struct disasm_inst
*inst
)
646 return (inst
->saturate
) ? ".sat" : "";
650 disasm_inst_flag_reg(const struct disasm_inst
*inst
)
652 static const char *flag_names
[2][2] = {
657 return (inst
->flag_reg
<= 1 && inst
->flag_subreg
<= 1) ?
658 flag_names
[inst
->flag_reg
][inst
->flag_subreg
] : "fBAD";
662 disasm_inst_access_mode(const struct disasm_inst
*inst
)
664 switch (inst
->access_mode
) {
665 case GEN6_ALIGN_1
: return " align1";
666 case GEN6_ALIGN_16
: return " align16";
667 default: return " alignBAD";
672 disasm_inst_mask_ctrl(const struct disasm_inst
*inst
)
674 switch (inst
->mask_ctrl
) {
675 case GEN6_MASKCTRL_NORMAL
: return "";
676 case GEN6_MASKCTRL_NOMASK
: return " WE_all";
677 default: return " WE_BAD";
682 disasm_inst_dep_ctrl(const struct disasm_inst
*inst
)
684 switch (inst
->dep_ctrl
) {
685 case GEN6_DEPCTRL_NORMAL
: return "";
686 case GEN6_DEPCTRL_NODDCLR
: return " NoDDClr";
687 case GEN6_DEPCTRL_NODDCHK
: return " NoDDChk";
688 case GEN6_DEPCTRL_NEITHER
: return " NoDDClr,NoDDChk";
689 default: return " NoDDBAD";
694 disasm_inst_qtr_ctrl(const struct disasm_inst
*inst
)
696 switch (inst
->exec_size
) {
697 case GEN6_EXECSIZE_8
:
698 switch (inst
->qtr_ctrl
) {
699 case GEN6_QTRCTRL_1Q
: return " 1Q";
700 case GEN6_QTRCTRL_2Q
: return " 2Q";
701 case GEN6_QTRCTRL_3Q
: return " 3Q";
702 case GEN6_QTRCTRL_4Q
: return " 4Q";
703 default: return " BADQ";
706 case GEN6_EXECSIZE_16
:
707 switch (inst
->qtr_ctrl
) {
708 case GEN6_QTRCTRL_1H
: return " 1H";
709 case GEN6_QTRCTRL_2H
: return " 2H";
710 default: return " BADH";
720 disasm_inst_thread_ctrl(const struct disasm_inst
*inst
)
722 switch (inst
->thread_ctrl
) {
723 case GEN6_THREADCTRL_NORMAL
: return "";
724 case GEN6_THREADCTRL_ATOMIC
: return " atomic";
725 case GEN6_THREADCTRL_SWITCH
: return " switch";
726 default: return " BAD";
731 disasm_inst_acc_wr_ctrl(const struct disasm_inst
*inst
)
733 return (inst
->acc_wr_ctrl
) ? " AccWrEnable" : "";
737 disasm_inst_cmpt_ctrl(const struct disasm_inst
*inst
)
739 return (inst
->cmpt_ctrl
) ? " compacted" : "";
743 disasm_inst_eot(const struct disasm_inst
*inst
)
745 if (inst
->opcode
== GEN6_OPCODE_SEND
||
746 inst
->opcode
== GEN6_OPCODE_SENDC
)
747 return (inst
->u
.imm32
& GEN6_MSG_EOT
) ? " EOT" : "";
753 disasm_inst_file(const struct disasm_inst
*inst
,
754 const struct disasm_operand
*operand
,
757 switch (operand
->file
) {
759 switch (operand
->reg
& 0xf0) {
760 case GEN6_ARF_NULL
: *multi_regs
= false; return "null";
761 case GEN6_ARF_A0
: *multi_regs
= true; return "a";
762 case GEN6_ARF_ACC0
: *multi_regs
= true; return "acc";
763 case GEN6_ARF_F0
: *multi_regs
= true; return "f";
764 case GEN6_ARF_SR0
: *multi_regs
= true; return "sr";
765 case GEN6_ARF_CR0
: *multi_regs
= true; return "cr";
766 case GEN6_ARF_N0
: *multi_regs
= true; return "n";
767 case GEN6_ARF_IP
: *multi_regs
= false; return "ip";
768 case GEN6_ARF_TDR
: *multi_regs
= false; return "tdr";
769 case GEN7_ARF_TM0
: *multi_regs
= true; return "tm";
770 default: *multi_regs
= false; return "BAD";
773 case GEN6_FILE_GRF
: *multi_regs
= true; return "g";
774 case GEN6_FILE_MRF
: *multi_regs
= true; return "m";
775 case GEN6_FILE_IMM
: *multi_regs
= true; return "";
776 default: *multi_regs
= false; return "BAD";
781 disasm_inst_type(const struct disasm_inst
*inst
,
782 const struct disasm_operand
*operand
)
784 if (operand
->file
== GEN6_FILE_IMM
) {
785 switch (operand
->type
) {
786 case GEN6_TYPE_UD
: return "UD";
787 case GEN6_TYPE_D
: return "D";
788 case GEN6_TYPE_UW
: return "UW";
789 case GEN6_TYPE_W
: return "W";
790 case GEN6_TYPE_UV_IMM
: return "UV";
791 case GEN6_TYPE_VF_IMM
: return "VF";
792 case GEN6_TYPE_V_IMM
: return "V";
793 case GEN6_TYPE_F
: return "F";
794 default: return "BAD";
797 switch (operand
->type
) {
798 case GEN6_TYPE_UD
: return "UD";
799 case GEN6_TYPE_D
: return "D";
800 case GEN6_TYPE_UW
: return "UW";
801 case GEN6_TYPE_W
: return "W";
802 case GEN6_TYPE_UB
: return "UB";
803 case GEN6_TYPE_B
: return "B";
804 case GEN7_TYPE_DF
: return "DF";
805 case GEN6_TYPE_F
: return "F";
806 default: return "BAD";
812 disasm_inst_vert_stride(const struct disasm_inst
*inst
, unsigned vert_stride
)
814 switch (vert_stride
) {
815 case GEN6_VERTSTRIDE_0
: return "0";
816 case GEN6_VERTSTRIDE_1
: return "1";
817 case GEN6_VERTSTRIDE_2
: return "2";
818 case GEN6_VERTSTRIDE_4
: return "4";
819 case GEN6_VERTSTRIDE_8
: return "8";
820 case GEN6_VERTSTRIDE_16
: return "16";
821 case GEN6_VERTSTRIDE_32
: return "32";
822 case GEN6_VERTSTRIDE_VXH
: return "VxH";
823 default: return "BAD";
828 disasm_inst_width(const struct disasm_inst
*inst
, unsigned width
)
831 case GEN6_WIDTH_1
: return "1";
832 case GEN6_WIDTH_2
: return "2";
833 case GEN6_WIDTH_4
: return "4";
834 case GEN6_WIDTH_8
: return "8";
835 case GEN6_WIDTH_16
: return "16";
836 default: return "BAD";
841 disasm_inst_horz_stride(const struct disasm_inst
*inst
, unsigned horz_stride
)
843 switch (horz_stride
) {
844 case GEN6_HORZSTRIDE_0
: return "0";
845 case GEN6_HORZSTRIDE_1
: return "1";
846 case GEN6_HORZSTRIDE_2
: return "2";
847 case GEN6_HORZSTRIDE_4
: return "4";
848 default: return "BAD";
853 disasm_inst_writemask(const struct disasm_inst
*inst
, unsigned writemask
)
856 case 0x0: return ".";
857 case 0x1: return ".x";
858 case 0x2: return ".y";
859 case 0x3: return ".xy";
860 case 0x4: return ".z";
861 case 0x5: return ".xz";
862 case 0x6: return ".yz";
863 case 0x7: return ".xyz";
864 case 0x8: return ".w";
865 case 0x9: return ".xw";
866 case 0xa: return ".yw";
867 case 0xb: return ".xyw";
868 case 0xc: return ".zw";
869 case 0xd: return ".xzw";
870 case 0xe: return ".yzw";
872 default: return ".BAD";
877 disasm_inst_negate(const struct disasm_inst
*inst
, bool negate
)
879 return (negate
) ? "-" : "";
883 disasm_inst_absolute(const struct disasm_inst
*inst
, bool absolute
)
885 return (absolute
) ? "(abs)" : "";
889 disasm_inst_is_null(const struct disasm_inst
*inst
,
890 const struct disasm_operand
*operand
)
892 return (operand
->file
== GEN6_FILE_ARF
&& operand
->reg
== GEN6_ARF_NULL
);
896 disasm_inst_type_size(const struct disasm_inst
*inst
,
897 const struct disasm_operand
*operand
)
899 assert(operand
->file
!= GEN6_FILE_IMM
);
901 switch (operand
->type
) {
902 case GEN6_TYPE_UD
: return 4;
903 case GEN6_TYPE_D
: return 4;
904 case GEN6_TYPE_UW
: return 2;
905 case GEN6_TYPE_W
: return 2;
906 case GEN6_TYPE_UB
: return 1;
907 case GEN6_TYPE_B
: return 1;
908 case GEN7_TYPE_DF
: return 8;
909 case GEN6_TYPE_F
: return 4;
915 disasm_printer_reset(struct disasm_printer
*printer
)
917 printer
->buf
[0] = '\0';
922 disasm_printer_get_string(struct disasm_printer
*printer
)
927 static void _util_printf_format(2, 3)
928 disasm_printer_add(struct disasm_printer
*printer
, const char *format
, ...)
930 const size_t avail
= sizeof(printer
->buf
) - printer
->len
;
934 va_start(ap
, format
);
935 written
= vsnprintf(printer
->buf
+ printer
->len
, avail
, format
, ap
);
939 if (written
< 0 || written
>= avail
) {
940 memcpy(printer
->buf
+ sizeof(printer
->buf
) - 4, "...", 4);
941 printer
->len
= sizeof(printer
->buf
) - 1;
943 printer
->len
+= written
;
948 * Pad to the specified column.
951 disasm_printer_column(struct disasm_printer
*printer
, int col
)
953 int len
= DISASM_PRINTER_COLUMN_WIDTH
* col
;
955 if (len
<= printer
->len
) {
959 /* at least one space */
960 len
= printer
->len
+ 1;
963 if (len
>= sizeof(printer
->buf
)) {
964 len
= sizeof(printer
->buf
) - 1;
966 if (len
<= printer
->len
)
970 memset(printer
->buf
+ printer
->len
, ' ', len
- printer
->len
);
972 printer
->buf
[printer
->len
] = '\0';
976 disasm_printer_add_op(struct disasm_printer
*printer
,
977 const struct disasm_inst
*inst
)
979 if (inst
->pred_ctrl
!= GEN6_PREDCTRL_NONE
) {
980 disasm_printer_add(printer
, "(%c%s%s) ",
981 disasm_inst_pred_inv(inst
),
982 disasm_inst_flag_reg(inst
),
983 disasm_inst_pred_ctrl(inst
));
986 disasm_printer_add(printer
, "%s%s%s%s",
987 disasm_inst_opcode(inst
),
988 disasm_inst_saturate(inst
),
989 disasm_inst_debug_ctrl(inst
),
990 disasm_inst_cond_modifier(inst
));
992 if (inst
->cond_modifier
!= GEN6_COND_NONE
) {
993 switch (inst
->opcode
) {
994 case GEN6_OPCODE_SEL
:
996 case GEN6_OPCODE_WHILE
:
997 /* these do not update flag registers */
1000 disasm_printer_add(printer
, ".%s", disasm_inst_flag_reg(inst
));
1005 if (inst
->opcode
== GEN6_OPCODE_MATH
)
1006 disasm_printer_add(printer
, " %s", disasm_inst_fc(inst
));
1007 if (inst
->opcode
!= GEN6_OPCODE_NOP
)
1008 disasm_printer_add(printer
, "(%s)", disasm_inst_exec_size(inst
));
1012 disasm_printer_add_operand(struct disasm_printer
*printer
,
1013 const struct disasm_inst
*inst
,
1014 const struct disasm_operand
*operand
)
1019 name
= disasm_inst_file(inst
, operand
, &multi_regs
);
1021 disasm_printer_add(printer
, "%s", name
);
1025 if (operand
->file
== GEN6_FILE_IMM
) {
1026 switch (operand
->type
) {
1028 disasm_printer_add(printer
, "0x%08xUD", inst
->u
.imm32
);
1031 disasm_printer_add(printer
, "%dD", inst
->u
.imm32
);
1034 disasm_printer_add(printer
, "0x%04xUW", (uint16_t) inst
->u
.imm32
);
1037 disasm_printer_add(printer
, "%dW", (int16_t) inst
->u
.imm32
);
1039 case GEN6_TYPE_UV_IMM
:
1040 disasm_printer_add(printer
, "0x%08xUV", inst
->u
.imm32
);
1042 case GEN6_TYPE_VF_IMM
:
1043 disasm_printer_add(printer
, "Vector Float");
1045 case GEN6_TYPE_V_IMM
:
1046 disasm_printer_add(printer
, "0x%08xV", inst
->u
.imm32
);
1049 disasm_printer_add(printer
, "%-gF", uif(inst
->u
.imm32
));
1052 disasm_printer_add(printer
, "BAD");
1059 if (operand
->addr_mode
== GEN6_ADDRMODE_DIRECT
) {
1060 unsigned reg
, subreg
;
1063 if (operand
->file
== GEN6_FILE_ARF
)
1066 subreg
= operand
->subreg
/ disasm_inst_type_size(inst
, operand
);
1069 disasm_printer_add(printer
, "%s%d.%d", name
, reg
, subreg
);
1071 disasm_printer_add(printer
, "%s%d", name
, reg
);
1073 disasm_printer_add(printer
, "%s[a0.%d %d]",
1074 name
, operand
->addr_subreg
, operand
->addr_imm
);
1079 disasm_printer_add_dst(struct disasm_printer
*printer
,
1080 const struct disasm_inst
*inst
,
1081 const struct disasm_dst_operand
*dst
)
1083 disasm_printer_add_operand(printer
, inst
, &dst
->base
);
1085 /* dst is an immediate when in EU_INSTRUCTION_BRANCH_CONDITIONAL form */
1086 if (disasm_inst_is_null(inst
, &dst
->base
) ||
1087 dst
->base
.file
== GEN6_FILE_IMM
)
1090 disasm_printer_add(printer
, "<%s>%s%s",
1091 disasm_inst_horz_stride(inst
, dst
->horz_stride
),
1092 disasm_inst_writemask(inst
, dst
->writemask
),
1093 disasm_inst_type(inst
, &dst
->base
));
1097 disasm_printer_add_src(struct disasm_printer
*printer
,
1098 const struct disasm_inst
*inst
,
1099 const struct disasm_src_operand
*src
)
1101 static const char swizzle_chars
[4] = { 'x', 'y', 'z', 'w' };
1104 disasm_printer_add(printer
, "%s%s",
1105 disasm_inst_negate(inst
, src
->negate
),
1106 disasm_inst_absolute(inst
, src
->absolute
));
1108 disasm_printer_add_operand(printer
, inst
, &src
->base
);
1110 if (disasm_inst_is_null(inst
, &src
->base
) ||
1111 src
->base
.file
== GEN6_FILE_IMM
)
1114 if (src
->swizzle_x
== 0 && src
->swizzle_y
== 1 &&
1115 src
->swizzle_z
== 2 && src
->swizzle_w
== 3) {
1117 } else if (src
->swizzle_x
== src
->swizzle_y
&&
1118 src
->swizzle_x
== src
->swizzle_z
&&
1119 src
->swizzle_x
== src
->swizzle_w
) {
1120 swizzle
[0] = swizzle_chars
[src
->swizzle_x
];
1123 swizzle
[0] = swizzle_chars
[src
->swizzle_x
];
1124 swizzle
[1] = swizzle_chars
[src
->swizzle_y
];
1125 swizzle
[2] = swizzle_chars
[src
->swizzle_z
];
1126 swizzle
[3] = swizzle_chars
[src
->swizzle_w
];
1130 disasm_printer_add(printer
, "<%s,%s,%s>%s%s",
1131 disasm_inst_vert_stride(inst
, src
->vert_stride
),
1132 disasm_inst_width(inst
, src
->width
),
1133 disasm_inst_horz_stride(inst
, src
->horz_stride
),
1135 disasm_inst_type(inst
, &src
->base
));
1139 disasm_printer_add_ctrl(struct disasm_printer
*printer
,
1140 const struct disasm_inst
*inst
)
1142 if (inst
->opcode
== GEN6_OPCODE_NOP
) {
1143 disasm_printer_add(printer
, ";");
1147 disasm_printer_add(printer
, "{%s%s%s%s%s%s%s%s };",
1148 disasm_inst_access_mode(inst
),
1149 disasm_inst_mask_ctrl(inst
),
1150 disasm_inst_dep_ctrl(inst
),
1151 disasm_inst_qtr_ctrl(inst
),
1152 disasm_inst_cmpt_ctrl(inst
),
1153 disasm_inst_thread_ctrl(inst
),
1154 disasm_inst_acc_wr_ctrl(inst
),
1155 disasm_inst_eot(inst
));
1159 disasm_printer_add_mdesc_sampler(struct disasm_printer
*printer
,
1160 const struct disasm_inst
*inst
,
1165 if (inst
->dev
->gen
>= ILO_GEN(7)) {
1166 op
= GEN_EXTRACT(mdesc
, GEN7_MSG_SAMPLER_OP
);
1167 simd
= GEN_EXTRACT(mdesc
, GEN7_MSG_SAMPLER_SIMD
);
1169 op
= GEN_EXTRACT(mdesc
, GEN6_MSG_SAMPLER_OP
);
1170 simd
= GEN_EXTRACT(mdesc
, GEN6_MSG_SAMPLER_SIMD
);
1173 disasm_printer_add(printer
, " (%d, %d, %d, %d)",
1174 GEN_EXTRACT(mdesc
, GEN6_MSG_SAMPLER_SURFACE
),
1175 GEN_EXTRACT(mdesc
, GEN6_MSG_SAMPLER_INDEX
),
1180 disasm_printer_add_mdesc_urb(struct disasm_printer
*printer
,
1181 const struct disasm_inst
*inst
,
1186 bool interleaved
, complete
, allocate
, used
;
1188 if (inst
->dev
->gen
>= ILO_GEN(7)) {
1189 switch (GEN_EXTRACT(mdesc
, GEN7_MSG_URB_OP
)) {
1190 case GEN7_MSG_URB_WRITE_HWORD
: op
= "write HWord"; break;
1191 case GEN7_MSG_URB_WRITE_OWORD
: op
= "write OWord"; break;
1192 case GEN7_MSG_URB_READ_HWORD
: op
= "read HWord"; break;
1193 case GEN7_MSG_URB_READ_OWORD
: op
= "read OWord"; break;
1194 case GEN7_MSG_URB_ATOMIC_MOV
: op
= "atomic mov"; break;
1195 case GEN7_MSG_URB_ATOMIC_INC
: op
= "atomic inc"; break;
1196 default: op
= "BAD"; break;
1199 offset
= GEN_EXTRACT(mdesc
, GEN7_MSG_URB_GLOBAL_OFFSET
);
1200 interleaved
= mdesc
& GEN7_MSG_URB_INTERLEAVED
;
1201 complete
= mdesc
& GEN7_MSG_URB_COMPLETE
;
1206 switch (GEN_EXTRACT(mdesc
, GEN6_MSG_URB_OP
)) {
1207 case GEN6_MSG_URB_WRITE
: op
= "urb_write"; break;
1208 case GEN6_MSG_URB_FF_SYNC
: op
= "ff_sync"; break;
1209 default: op
= "BAD"; break;
1212 offset
= GEN_EXTRACT(mdesc
, GEN6_MSG_URB_OFFSET
);
1213 interleaved
= mdesc
& GEN6_MSG_URB_INTERLEAVED
;
1214 complete
= mdesc
& GEN6_MSG_URB_COMPLETE
;
1216 allocate
= mdesc
& GEN6_MSG_URB_ALLOCATE
;
1217 used
= mdesc
& GEN6_MSG_URB_USED
;
1220 disasm_printer_add(printer
, " %d %s%s%s%s%s", offset
, op
,
1221 (interleaved
) ? " interleave" : "",
1222 (allocate
) ? " allocate" : "",
1223 (used
) ? " used" : "",
1224 (complete
) ? " complete" : "");
1228 disasm_printer_add_mdesc_dp_sampler(struct disasm_printer
*printer
,
1229 const struct disasm_inst
*inst
,
1232 const int op
= (inst
->dev
->gen
>= ILO_GEN(7)) ?
1233 GEN_EXTRACT(mdesc
, GEN7_MSG_DP_OP
) : GEN_EXTRACT(mdesc
, GEN6_MSG_DP_OP
);
1234 const bool write_commit
= (inst
->dev
->gen
== ILO_GEN(6)) ?
1235 (mdesc
& GEN6_MSG_DP_SEND_WRITE_COMMIT
) : 0;
1237 disasm_printer_add(printer
, " (%d, %d, %d, %d)",
1238 GEN_EXTRACT(mdesc
, GEN6_MSG_DP_SURFACE
),
1239 GEN_EXTRACT(mdesc
, GEN6_MSG_DP_OWORD_BLOCK_SIZE
),
1244 disasm_printer_add_mdesc_dp_rc(struct disasm_printer
*printer
,
1245 const struct disasm_inst
*inst
,
1248 const int op
= (inst
->dev
->gen
>= ILO_GEN(7)) ?
1249 GEN_EXTRACT(mdesc
, GEN7_MSG_DP_OP
) : GEN_EXTRACT(mdesc
, GEN6_MSG_DP_OP
);
1253 if (inst
->dev
->gen
>= ILO_GEN(7.5)) {
1255 case GEN75_MSG_DP_RC_MEDIA_BLOCK_READ
: str
= "media block read"; break;
1256 case GEN75_MSG_DP_RC_MEMORY_FENCE
: str
= "memory fence"; break;
1257 case GEN75_MSG_DP_RC_MEDIA_BLOCK_WRITE
: str
= "media block write"; break;
1258 case GEN75_MSG_DP_RC_RT_WRITE
: str
= "RT write"; break;
1259 default: str
= "BAD"; break;
1262 is_rt_write
= (op
== GEN75_MSG_DP_RC_RT_WRITE
);
1263 } else if (inst
->dev
->gen
>= ILO_GEN(7)) {
1265 case GEN7_MSG_DP_RC_MEDIA_BLOCK_READ
: str
= "media block read"; break;
1266 case GEN7_MSG_DP_RC_TYPED_SURFACE_READ
: str
= "typed surface read"; break;
1267 case GEN7_MSG_DP_RC_TYPED_ATOMIC_OP
: str
= "typed atomic op"; break;
1268 case GEN7_MSG_DP_RC_MEMORY_FENCE
: str
= "memory fence"; break;
1269 case GEN7_MSG_DP_RC_MEDIA_BLOCK_WRITE
: str
= "media block write"; break;
1270 case GEN7_MSG_DP_RC_RT_WRITE
: str
= "RT write"; break;
1271 case GEN7_MSG_DP_RC_TYPED_SURFACE_WRITE
: str
= "typed surface write"; break;
1272 default: str
= "BAD"; break;
1275 is_rt_write
= (op
== GEN7_MSG_DP_RC_RT_WRITE
);
1278 case GEN6_MSG_DP_OWORD_BLOCK_READ
: str
= "OWORD block read"; break;
1279 case GEN6_MSG_DP_RT_UNORM_READ
: str
= "RT UNORM read"; break;
1280 case GEN6_MSG_DP_OWORD_DUAL_BLOCK_READ
: str
= "OWORD dual block read"; break;
1281 case GEN6_MSG_DP_MEDIA_BLOCK_READ
: str
= "media block read"; break;
1282 case GEN6_MSG_DP_UNALIGNED_OWORD_BLOCK_READ
: str
= "unaligned OWORD block read"; break;
1283 case GEN6_MSG_DP_DWORD_SCATTERED_READ
: str
= "DWORD scattered read"; break;
1284 case GEN6_MSG_DP_DWORD_ATOMIC_WRITE
: str
= "DWORD atomic write"; break;
1285 case GEN6_MSG_DP_OWORD_BLOCK_WRITE
: str
= "OWORD block write"; break;
1286 case GEN6_MSG_DP_OWORD_DUAL_BLOCK_WRITE
: str
= "OWORD dual block_write"; break;
1287 case GEN6_MSG_DP_MEDIA_BLOCK_WRITE
: str
= "media block write"; break;
1288 case GEN6_MSG_DP_DWORD_SCATTERED_WRITE
: str
= "DWORD scattered write"; break;
1289 case GEN6_MSG_DP_RT_WRITE
: str
= "RT write"; break;
1290 case GEN6_MSG_DP_SVB_WRITE
: str
= "SVB write"; break;
1291 case GEN6_MSG_DP_RT_UNORM_WRITE
: str
= "RT UNORM write"; break;
1292 default: str
= "BAD"; break;
1295 is_rt_write
= (op
== GEN6_MSG_DP_RT_WRITE
);
1298 disasm_printer_add(printer
, " %s", str
);
1301 switch (mdesc
& GEN6_MSG_DP_RT_MODE__MASK
) {
1302 case GEN6_MSG_DP_RT_MODE_SIMD16
: str
= "SIMD16"; break;
1303 case GEN6_MSG_DP_RT_MODE_SIMD16_REPDATA
: str
= "SIMD16/RepData"; break;
1304 case GEN6_MSG_DP_RT_MODE_SIMD8_DUALSRC_LO
: str
= "SIMD8/DualSrcLow"; break;
1305 case GEN6_MSG_DP_RT_MODE_SIMD8_DUALSRC_HI
: str
= "SIMD8/DualSrcHigh"; break;
1306 case GEN6_MSG_DP_RT_MODE_SIMD8_LO
: str
= "SIMD8"; break;
1307 case GEN6_MSG_DP_RT_MODE_SIMD8_IMAGE_WR
: str
= "SIMD8/ImageWrite"; break;
1308 default: str
= "BAD"; break;
1311 disasm_printer_add(printer
, " %s%s%s%s", str
,
1312 (mdesc
& GEN6_MSG_DP_SLOTGRP_HI
) ? " Hi" : "",
1313 (mdesc
& GEN6_MSG_DP_RT_LAST
) ? " LastRT" : "",
1314 (inst
->dev
->gen
== ILO_GEN(6) &&
1315 (mdesc
& GEN6_MSG_DP_SEND_WRITE_COMMIT
)) ? " WriteCommit" : "");
1318 disasm_printer_add(printer
, " Surface = %d",
1319 GEN_EXTRACT(mdesc
, GEN6_MSG_DP_SURFACE
));
1323 disasm_printer_add_mdesc(struct disasm_printer
*printer
,
1324 const struct disasm_inst
*inst
)
1326 const uint32_t mdesc
= inst
->u
.imm32
;
1328 assert(inst
->opcode
== GEN6_OPCODE_SEND
||
1329 inst
->opcode
== GEN6_OPCODE_SENDC
);
1330 assert(inst
->src1
.base
.file
== GEN6_FILE_IMM
);
1332 disasm_printer_add(printer
, " %s", disasm_inst_sfid(inst
));
1334 switch (inst
->sfid
) {
1335 case GEN6_SFID_SAMPLER
:
1336 disasm_printer_add_mdesc_sampler(printer
, inst
, mdesc
);
1338 case GEN6_SFID_DP_SAMPLER
:
1339 disasm_printer_add_mdesc_dp_sampler(printer
, inst
, mdesc
);
1341 case GEN6_SFID_DP_RC
:
1342 disasm_printer_add_mdesc_dp_rc(printer
, inst
, mdesc
);
1345 disasm_printer_add_mdesc_urb(printer
, inst
, mdesc
);
1347 case GEN6_SFID_DP_CC
:
1348 case GEN7_SFID_DP_DC0
:
1350 case GEN75_SFID_DP_DC1
:
1355 disasm_printer_add(printer
, " mlen %d rlen %d",
1356 GEN_EXTRACT(mdesc
, GEN6_MSG_MLEN
),
1357 GEN_EXTRACT(mdesc
, GEN6_MSG_RLEN
));
1361 disasm_printer_print_inst(struct disasm_printer
*printer
,
1362 const struct disasm_inst
*inst
)
1366 disasm_printer_reset(printer
);
1368 disasm_printer_column(printer
, col
++);
1369 disasm_printer_add_op(printer
, inst
);
1371 if (inst
->has_jip
|| inst
->has_uip
) {
1372 if (inst
->has_jip
) {
1373 disasm_printer_column(printer
, col
++);
1374 disasm_printer_add(printer
, "JIP: %d", (int16_t) inst
->u
.imm32
);
1377 if (inst
->has_uip
) {
1378 disasm_printer_column(printer
, col
++);
1379 disasm_printer_add(printer
, "UIP: %d",
1380 (int16_t) (inst
->u
.imm32
>> 16));
1383 const int src_count
= disasm_opcode_table
[inst
->opcode
].src_count
;
1384 const struct disasm_src_operand
*src
[3];
1387 /* get src operands */
1388 switch (src_count
) {
1390 src
[2] = &inst
->u
.src2
;
1392 src
[1] = &inst
->src1
;
1394 src
[0] = &inst
->src0
;
1401 disasm_printer_column(printer
, col
++);
1402 disasm_printer_add_dst(printer
, inst
, &inst
->dst
);
1404 for (i
= 0; i
< src_count
; i
++) {
1405 disasm_printer_column(printer
, col
++);
1406 disasm_printer_add_src(printer
, inst
, src
[i
]);
1411 if (inst
->opcode
== GEN6_OPCODE_SEND
||
1412 inst
->opcode
== GEN6_OPCODE_SENDC
) {
1413 /* start a new line */
1414 ilo_printf("%s\n", disasm_printer_get_string(printer
));
1415 disasm_printer_reset(printer
);
1418 disasm_printer_column(printer
, col
++);
1420 disasm_printer_column(printer
, col
++);
1421 disasm_printer_add_mdesc(printer
, inst
);
1427 disasm_printer_column(printer
, col
++);
1428 disasm_printer_add_ctrl(printer
, inst
);
1430 ilo_printf("%s\n", disasm_printer_get_string(printer
));
1434 toy_compiler_disassemble(const struct ilo_dev_info
*dev
,
1435 const void *kernel
, int size
,
1438 const uint32_t *cur
= (const uint32_t *) kernel
;
1439 const uint32_t *end
= cur
+ size
/ sizeof(*cur
);
1440 struct disasm_printer printer
;
1442 disasm_printer_reset(&printer
);
1445 struct disasm_inst inst
;
1446 const bool compacted
= (cur
[0] & GEN6_INST_CMPTCTRL
);
1447 const uint32_t *dw
= cur
;
1450 cur
+= (compacted
) ? 2 : 4;
1451 /* incomplete instruction */
1456 /* no compaction support yet */
1457 memset(temp
, 0, sizeof(temp
));
1462 ilo_printf("0x%08x 0x%08x 0x%08x 0x%08x ",
1463 dw
[0], dw
[1], dw
[2], dw
[3]);
1466 memset(&inst
, 0, sizeof(inst
));
1468 disasm_inst_decode(&inst
, dw
);
1469 inst
.cmpt_ctrl
= compacted
;
1471 disasm_printer_print_inst(&printer
, &inst
);