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 #define READ(dw, field) (((dw) & field ## __MASK) >> field ## __SHIFT)
37 struct disasm_printer
{
38 char buf
[DISASM_PRINTER_BUFFER_SIZE
];
42 struct disasm_operand
{
49 unsigned addr_subreg
:3;
53 struct disasm_dst_operand
{
54 struct disasm_operand base
;
56 unsigned horz_stride
:2;
60 struct disasm_src_operand
{
61 struct disasm_operand base
;
63 unsigned vert_stride
:4;
65 unsigned horz_stride
:2;
75 const struct ilo_dev_info
*dev
;
81 unsigned access_mode
:1;
85 unsigned thread_ctrl
:2;
90 unsigned cond_modifier
:4;
94 unsigned acc_wr_ctrl
:1;
96 unsigned debug_ctrl
:1;
102 unsigned flag_subreg
:1;
104 struct disasm_dst_operand dst
;
105 struct disasm_src_operand src0
;
106 struct disasm_src_operand src1
;
108 struct disasm_src_operand src2
;
113 static const struct {
116 } disasm_opcode_table
[128] = {
117 [GEN6_OPCODE_ILLEGAL
] = { "illegal", 0 },
118 [GEN6_OPCODE_MOV
] = { "mov", 1 },
119 [GEN6_OPCODE_SEL
] = { "sel", 2 },
120 [GEN6_OPCODE_MOVI
] = { "movi", 1 },
121 [GEN6_OPCODE_NOT
] = { "not", 1 },
122 [GEN6_OPCODE_AND
] = { "and", 2 },
123 [GEN6_OPCODE_OR
] = { "or", 2 },
124 [GEN6_OPCODE_XOR
] = { "xor", 2 },
125 [GEN6_OPCODE_SHR
] = { "shr", 2 },
126 [GEN6_OPCODE_SHL
] = { "shl", 2 },
127 [GEN6_OPCODE_DIM
] = { "dim", 1 },
128 [GEN6_OPCODE_ASR
] = { "asr", 2 },
129 [GEN6_OPCODE_CMP
] = { "cmp", 2 },
130 [GEN6_OPCODE_CMPN
] = { "cmpn", 2 },
131 [GEN7_OPCODE_CSEL
] = { "csel", 3 },
132 [GEN7_OPCODE_F32TO16
] = { "f32to16", 1 },
133 [GEN7_OPCODE_F16TO32
] = { "f16to32", 1 },
134 [GEN7_OPCODE_BFREV
] = { "bfrev", 1 },
135 [GEN7_OPCODE_BFE
] = { "bfe", 3 },
136 [GEN7_OPCODE_BFI1
] = { "bfi1", 2 },
137 [GEN7_OPCODE_BFI2
] = { "bfi2", 3 },
138 [GEN6_OPCODE_JMPI
] = { "jmpi", 1 },
139 [GEN7_OPCODE_BRD
] = { "brd", 1 },
140 [GEN6_OPCODE_IF
] = { "if", 2 },
141 [GEN7_OPCODE_BRC
] = { "brc", 1 },
142 [GEN6_OPCODE_ELSE
] = { "else", 1 },
143 [GEN6_OPCODE_ENDIF
] = { "endif", 0 },
144 [GEN6_OPCODE_CASE
] = { "case", 2 },
145 [GEN6_OPCODE_WHILE
] = { "while", 1 },
146 [GEN6_OPCODE_BREAK
] = { "break", 1 },
147 [GEN6_OPCODE_CONT
] = { "cont", 1 },
148 [GEN6_OPCODE_HALT
] = { "halt", 1 },
149 [GEN75_OPCODE_CALLA
] = { "calla", 1 },
150 [GEN6_OPCODE_CALL
] = { "call", 1 },
151 [GEN6_OPCODE_RETURN
] = { "return", 1 },
152 [GEN6_OPCODE_WAIT
] = { "wait", 1 },
153 [GEN6_OPCODE_SEND
] = { "send", 1 },
154 [GEN6_OPCODE_SENDC
] = { "sendc", 1 },
155 [GEN6_OPCODE_MATH
] = { "math", 2 },
156 [GEN6_OPCODE_ADD
] = { "add", 2 },
157 [GEN6_OPCODE_MUL
] = { "mul", 2 },
158 [GEN6_OPCODE_AVG
] = { "avg", 2 },
159 [GEN6_OPCODE_FRC
] = { "frc", 1 },
160 [GEN6_OPCODE_RNDU
] = { "rndu", 1 },
161 [GEN6_OPCODE_RNDD
] = { "rndd", 1 },
162 [GEN6_OPCODE_RNDE
] = { "rnde", 1 },
163 [GEN6_OPCODE_RNDZ
] = { "rndz", 1 },
164 [GEN6_OPCODE_MAC
] = { "mac", 2 },
165 [GEN6_OPCODE_MACH
] = { "mach", 2 },
166 [GEN6_OPCODE_LZD
] = { "lzd", 1 },
167 [GEN7_OPCODE_FBH
] = { "fbh", 1 },
168 [GEN7_OPCODE_FBL
] = { "fbl", 1 },
169 [GEN7_OPCODE_CBIT
] = { "cbit", 1 },
170 [GEN7_OPCODE_ADDC
] = { "addc", 2 },
171 [GEN7_OPCODE_SUBB
] = { "subb", 2 },
172 [GEN6_OPCODE_SAD2
] = { "sad2", 2 },
173 [GEN6_OPCODE_SADA2
] = { "sada2", 2 },
174 [GEN6_OPCODE_DP4
] = { "dp4", 2 },
175 [GEN6_OPCODE_DPH
] = { "dph", 2 },
176 [GEN6_OPCODE_DP3
] = { "dp3", 2 },
177 [GEN6_OPCODE_DP2
] = { "dp2", 2 },
178 [GEN6_OPCODE_LINE
] = { "line", 2 },
179 [GEN6_OPCODE_PLN
] = { "pln", 2 },
180 [GEN6_OPCODE_MAD
] = { "mad", 3 },
181 [GEN6_OPCODE_LRP
] = { "lrp", 3 },
182 [GEN6_OPCODE_NOP
] = { "nop", 0 },
186 disasm_inst_decode_dw0_gen6(struct disasm_inst
*inst
, uint32_t dw0
)
188 inst
->opcode
= READ(dw0
, GEN6_INST_OPCODE
);
190 switch (inst
->opcode
) {
192 inst
->has_jip
= true;
193 inst
->has_uip
= (inst
->dev
->gen
>= ILO_GEN(7));
195 case GEN6_OPCODE_BREAK
:
196 case GEN6_OPCODE_CONT
:
197 case GEN6_OPCODE_HALT
:
198 inst
->has_uip
= true;
200 case GEN6_OPCODE_JMPI
:
201 case GEN7_OPCODE_BRD
:
202 case GEN7_OPCODE_BRC
:
203 case GEN6_OPCODE_ELSE
:
204 case GEN6_OPCODE_ENDIF
:
205 case GEN6_OPCODE_CASE
:
206 case GEN6_OPCODE_WHILE
:
207 case GEN75_OPCODE_CALLA
:
208 case GEN6_OPCODE_CALL
:
209 case GEN6_OPCODE_RETURN
:
210 inst
->has_jip
= true;
216 inst
->access_mode
= READ(dw0
, GEN6_INST_ACCESSMODE
);
217 inst
->mask_ctrl
= READ(dw0
, GEN6_INST_MASKCTRL
);
218 inst
->dep_ctrl
= READ(dw0
, GEN6_INST_DEPCTRL
);
219 inst
->qtr_ctrl
= READ(dw0
, GEN6_INST_QTRCTRL
);
220 inst
->thread_ctrl
= READ(dw0
, GEN6_INST_THREADCTRL
);
221 inst
->pred_ctrl
= READ(dw0
, GEN6_INST_PREDCTRL
);
223 inst
->pred_inv
= (bool) (dw0
& GEN6_INST_PREDINV
);
225 inst
->exec_size
= READ(dw0
, GEN6_INST_EXECSIZE
);
227 switch (inst
->opcode
) {
228 case GEN6_OPCODE_SEND
:
229 case GEN6_OPCODE_SENDC
:
230 inst
->sfid
= READ(dw0
, GEN6_INST_SFID
);
232 case GEN6_OPCODE_MATH
:
233 inst
->fc
= READ(dw0
, GEN6_INST_FC
);
236 inst
->cond_modifier
= READ(dw0
, GEN6_INST_CONDMODIFIER
);
240 inst
->acc_wr_ctrl
= (bool) (dw0
& GEN6_INST_ACCWRCTRL
);
241 inst
->cmpt_ctrl
= (bool) (dw0
& GEN6_INST_CMPTCTRL
);
242 inst
->debug_ctrl
= (bool) (dw0
& GEN6_INST_DEBUGCTRL
);
243 inst
->saturate
= (bool) (dw0
& GEN6_INST_SATURATE
);
247 disasm_inst_jip_in_dw1_high_gen6(const struct disasm_inst
*inst
)
249 return (inst
->dev
->gen
== ILO_GEN(6) && inst
->has_jip
&& !inst
->has_uip
);
253 disasm_inst_decode_dw1_gen6(struct disasm_inst
*inst
, uint32_t dw1
)
255 inst
->dst
.base
.file
= READ(dw1
, GEN6_INST_DST_FILE
);
256 inst
->dst
.base
.type
= READ(dw1
, GEN6_INST_DST_TYPE
);
257 inst
->src0
.base
.file
= READ(dw1
, GEN6_INST_SRC0_FILE
);
258 inst
->src0
.base
.type
= READ(dw1
, GEN6_INST_SRC0_TYPE
);
259 inst
->src1
.base
.file
= READ(dw1
, GEN6_INST_SRC1_FILE
);
260 inst
->src1
.base
.type
= READ(dw1
, GEN6_INST_SRC1_TYPE
);
262 if (inst
->dev
->gen
>= ILO_GEN(7))
263 inst
->nib_ctrl
= (bool) (dw1
& GEN7_INST_NIBCTRL
);
265 if (disasm_inst_jip_in_dw1_high_gen6(inst
)) {
266 inst
->u
.imm32
= dw1
>> 16;
270 inst
->dst
.base
.addr_mode
= READ(dw1
, GEN6_INST_DST_ADDRMODE
);
272 if (inst
->dst
.base
.addr_mode
== GEN6_ADDRMODE_DIRECT
) {
273 inst
->dst
.base
.reg
= READ(dw1
, GEN6_INST_DST_REG
);
275 if (inst
->access_mode
== GEN6_ALIGN_1
) {
276 inst
->dst
.base
.subreg
= READ(dw1
, GEN6_INST_DST_SUBREG
);
278 inst
->dst
.base
.subreg
= READ(dw1
, GEN6_INST_DST_SUBREG_ALIGN16
) <<
279 GEN6_INST_DST_SUBREG_ALIGN16__SHR
;
282 inst
->dst
.base
.addr_subreg
= READ(dw1
, GEN6_INST_DST_ADDR_SUBREG
);
284 if (inst
->access_mode
== GEN6_ALIGN_1
) {
285 inst
->dst
.base
.addr_imm
= READ(dw1
, GEN6_INST_DST_ADDR_IMM
);
287 inst
->dst
.base
.addr_imm
= READ(dw1
, GEN6_INST_DST_ADDR_IMM_ALIGN16
) <<
288 GEN6_INST_DST_ADDR_IMM_ALIGN16__SHR
;
292 inst
->dst
.horz_stride
= READ(dw1
, GEN6_INST_DST_HORZSTRIDE
);
294 if (inst
->access_mode
== GEN6_ALIGN_1
)
295 inst
->dst
.writemask
= 0xf;
297 inst
->dst
.writemask
= READ(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
= READ(dw2
, GEN7_INST_FLAG_REG
);
309 inst
->flag_subreg
= READ(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
= READ(dw
, GEN6_INST_SRC_ADDRMODE
);
326 if (src
->base
.addr_mode
== GEN6_ADDRMODE_DIRECT
) {
327 src
->base
.reg
= READ(dw
, GEN6_INST_SRC_REG
);
329 if (inst
->access_mode
== GEN6_ALIGN_1
) {
330 src
->base
.subreg
= READ(dw
, GEN6_INST_SRC_SUBREG
);
332 src
->base
.subreg
= READ(dw
, GEN6_INST_SRC_SUBREG_ALIGN16
) <<
333 GEN6_INST_SRC_SUBREG_ALIGN16__SHR
;
336 src
->base
.addr_subreg
= READ(dw
, GEN6_INST_SRC_ADDR_SUBREG
);
338 if (inst
->access_mode
== GEN6_ALIGN_1
) {
339 src
->base
.addr_imm
= READ(dw
, GEN6_INST_SRC_ADDR_IMM
);
341 src
->base
.addr_imm
= READ(dw
, GEN6_INST_SRC_ADDR_IMM_ALIGN16
) <<
342 GEN6_INST_SRC_ADDR_IMM_ALIGN16__SHR
;
346 src
->vert_stride
= READ(dw
, GEN6_INST_SRC_VERTSTRIDE
);
348 if (inst
->access_mode
== GEN6_ALIGN_1
) {
349 src
->width
= READ(dw
, GEN6_INST_SRC_WIDTH
);
350 src
->horz_stride
= READ(dw
, GEN6_INST_SRC_HORZSTRIDE
);
352 src
->swizzle_x
= GEN6_SWIZZLE_X
;
353 src
->swizzle_y
= GEN6_SWIZZLE_Y
;
354 src
->swizzle_z
= GEN6_SWIZZLE_Z
;
355 src
->swizzle_w
= GEN6_SWIZZLE_W
;
357 src
->width
= GEN6_WIDTH_4
;
358 src
->horz_stride
= GEN6_HORZSTRIDE_1
;
360 src
->swizzle_x
= READ(dw
, GEN6_INST_SRC_SWIZZLE_X
);
361 src
->swizzle_y
= READ(dw
, GEN6_INST_SRC_SWIZZLE_Y
);
362 src
->swizzle_z
= READ(dw
, GEN6_INST_SRC_SWIZZLE_Z
);
363 src
->swizzle_w
= READ(dw
, GEN6_INST_SRC_SWIZZLE_W
);
366 src
->negate
= (bool) (dw
& GEN6_INST_SRC_NEGATE
);
367 src
->absolute
= (bool) (dw
& GEN6_INST_SRC_ABSOLUTE
);
372 disasm_inst_decode_3src_dw1_gen6(struct disasm_inst
*inst
, uint32_t dw1
)
374 static unsigned type_mapping
[4] = {
375 [GEN7_TYPE_F_3SRC
] = GEN6_TYPE_F
,
376 [GEN7_TYPE_D_3SRC
] = GEN6_TYPE_D
,
377 [GEN7_TYPE_UD_3SRC
] = GEN6_TYPE_UD
,
378 [GEN7_TYPE_DF_3SRC
] = GEN7_TYPE_DF
,
381 inst
->flag_subreg
= READ(dw1
, GEN6_3SRC_FLAG_SUBREG
);
383 if (inst
->dev
->gen
>= ILO_GEN(7)) {
384 inst
->nib_ctrl
= (bool) (dw1
& GEN7_3SRC_NIBCTRL
);
385 inst
->flag_reg
= READ(dw1
, GEN7_3SRC_FLAG_REG
);
387 inst
->dst
.base
.file
= GEN6_FILE_GRF
;
388 inst
->dst
.base
.type
= READ(dw1
, GEN7_3SRC_DST_TYPE
);
389 inst
->dst
.base
.type
= type_mapping
[inst
->dst
.base
.type
];
391 inst
->src0
.base
.type
= READ(dw1
, GEN7_3SRC_SRC_TYPE
);
392 inst
->src0
.base
.type
= type_mapping
[inst
->src0
.base
.type
];
394 inst
->src1
.base
.type
= inst
->src0
.base
.type
;
395 inst
->u
.src2
.base
.type
= inst
->src0
.base
.type
;
397 inst
->dst
.base
.file
= (dw1
& GEN6_3SRC_DST_FILE_MRF
) ?
398 GEN6_FILE_MRF
: GEN6_FILE_GRF
;
399 inst
->dst
.base
.type
= GEN6_TYPE_F
;
401 inst
->src0
.base
.type
= GEN6_TYPE_F
;
402 inst
->src1
.base
.type
= GEN6_TYPE_F
;
403 inst
->u
.src2
.base
.type
= GEN6_TYPE_F
;
406 inst
->dst
.base
.addr_mode
= GEN6_ADDRMODE_DIRECT
;
407 inst
->dst
.base
.reg
= READ(dw1
, GEN6_3SRC_DST_REG
);
408 inst
->dst
.base
.subreg
= READ(dw1
, GEN6_3SRC_DST_SUBREG
) <<
409 GEN6_3SRC_DST_SUBREG__SHR
;
411 inst
->dst
.horz_stride
= GEN6_HORZSTRIDE_1
;
412 inst
->dst
.writemask
= READ(dw1
, GEN6_3SRC_DST_WRITEMASK
);
414 inst
->src0
.base
.file
= GEN6_FILE_GRF
;
415 inst
->src0
.negate
= (bool) (dw1
& GEN6_3SRC_SRC0_NEGATE
);
416 inst
->src0
.absolute
= (bool) (dw1
& GEN6_3SRC_SRC0_ABSOLUTE
);
417 inst
->src1
.base
.file
= GEN6_FILE_GRF
;
418 inst
->src1
.negate
= (bool) (dw1
& GEN6_3SRC_SRC1_NEGATE
);
419 inst
->src1
.absolute
= (bool) (dw1
& GEN6_3SRC_SRC1_ABSOLUTE
);
420 inst
->u
.src2
.base
.file
= GEN6_FILE_GRF
;
421 inst
->u
.src2
.negate
= (bool) (dw1
& GEN6_3SRC_SRC2_NEGATE
);
422 inst
->u
.src2
.absolute
= (bool) (dw1
& GEN6_3SRC_SRC2_ABSOLUTE
);
426 disasm_inst_decode_3src_dw2_dw3_gen6(struct disasm_inst
*inst
,
427 uint32_t dw2
, uint32_t dw3
)
429 const uint64_t qw
= (uint64_t) dw3
<< 32 | dw2
;
432 for (i
= 0; i
< 3; i
++) {
433 struct disasm_src_operand
*src
= (i
== 0) ? &inst
->src0
:
434 (i
== 1) ? &inst
->src1
:
436 const uint32_t dw
= (i
== 0) ? READ(qw
, GEN6_3SRC_SRC_0
) :
437 (i
== 1) ? READ(qw
, GEN6_3SRC_SRC_1
) :
438 READ(qw
, GEN6_3SRC_SRC_2
);
440 src
->base
.addr_mode
= GEN6_ADDRMODE_DIRECT
;
441 src
->base
.reg
= READ(dw
, GEN6_3SRC_SRC_REG
);
442 src
->base
.subreg
= READ(dw
, GEN6_3SRC_SRC_SUBREG
) <<
443 GEN6_3SRC_SRC_SUBREG__SHR
;
445 if (dw
& GEN6_3SRC_SRC_REPCTRL
) {
446 src
->vert_stride
= GEN6_VERTSTRIDE_0
;
447 src
->width
= GEN6_WIDTH_1
;
448 src
->horz_stride
= GEN6_HORZSTRIDE_0
;
450 src
->vert_stride
= GEN6_VERTSTRIDE_4
;
451 src
->width
= GEN6_WIDTH_4
;
452 src
->horz_stride
= GEN6_HORZSTRIDE_1
;
455 src
->swizzle_x
= READ(dw
, GEN6_3SRC_SRC_SWIZZLE_X
);
456 src
->swizzle_y
= READ(dw
, GEN6_3SRC_SRC_SWIZZLE_Y
);
457 src
->swizzle_z
= READ(dw
, GEN6_3SRC_SRC_SWIZZLE_Z
);
458 src
->swizzle_w
= READ(dw
, GEN6_3SRC_SRC_SWIZZLE_W
);
463 * When GEN6_INST_CMPTCTRL of DW0 is set, the instruction has 64 bits and is
464 * in EU_INSTRUCTION_COMPACT_TWO_SRC form. We should have expanded it to its
467 * Depending on the opcode, the 128-bits instruction is in one of the
470 * - EU_INSTRUCTION_BASIC_ONE_SRC
471 * - EU_INSTRUCTION_BASIC_TWO_SRC
472 * - EU_INSTRUCTION_BASIC_THREE_SRC
473 * - EU_INSTRUCTION_BRANCH_CONDITIONAL
474 * - EU_INSTRUCTION_BRANCH_ONE_SRC
475 * - EU_INSTRUCTION_BRANCH_TWO_SRC
476 * - EU_INSTRUCTION_ILLEGAL
477 * - EU_INSTRUCTION_MATH
478 * - EU_INSTRUCTION_NOP
479 * - EU_INSTRUCTION_SEND
481 * In EU_INSTRUCTION_BASIC_ONE_SRC form,
483 * - DW0 is EU_INSTRUCTION_HEADER
484 * - DW1 is EU_INSTRUCTION_OPERAND_CONTROLS
485 * - DW2 is Source 0 and EU_INSTRUCTION_FLAGS
486 * - DW3 is reserved unless Source 0 is an immediate
488 * All other forms except EU_INSTRUCTION_BASIC_THREE_SRC are quite compatible
489 * with EU_INSTRUCTION_BASIC_ONE_SRC.
492 disasm_inst_decode(struct disasm_inst
*inst
,
495 assert(!(dw
[0] & GEN6_INST_CMPTCTRL
));
497 disasm_inst_decode_dw0_gen6(inst
, dw
[0]);
499 switch (inst
->opcode
) {
500 case GEN7_OPCODE_CSEL
:
501 case GEN7_OPCODE_BFE
:
502 case GEN7_OPCODE_BFI2
:
503 case GEN6_OPCODE_MAD
:
504 case GEN6_OPCODE_LRP
:
505 disasm_inst_decode_3src_dw1_gen6(inst
, dw
[1]);
506 disasm_inst_decode_3src_dw2_dw3_gen6(inst
, dw
[2], dw
[3]);
509 disasm_inst_decode_dw1_gen6(inst
, dw
[1]);
510 disasm_inst_decode_dw2_dw3_gen6(inst
, dw
[2], dw
[3]);
516 disasm_inst_opcode(const struct disasm_inst
*inst
)
518 return (disasm_opcode_table
[inst
->opcode
].name
) ?
519 disasm_opcode_table
[inst
->opcode
].name
: "BAD";
523 disasm_inst_pred_ctrl(const struct disasm_inst
*inst
)
525 if (inst
->access_mode
== GEN6_ALIGN_1
) {
526 switch (inst
->pred_ctrl
) {
527 case GEN6_PREDCTRL_NORMAL
: return "";
528 case GEN6_PREDCTRL_ANYV
: return ".anyv";
529 case GEN6_PREDCTRL_ALLV
: return ".allv";
530 case GEN6_PREDCTRL_ANY2H
: return ".any2h";
531 case GEN6_PREDCTRL_ALL2H
: return ".all2h";
532 case GEN6_PREDCTRL_ANY4H
: return ".any4h";
533 case GEN6_PREDCTRL_ALL4H
: return ".all4h";
534 case GEN6_PREDCTRL_ANY8H
: return ".any8h";
535 case GEN6_PREDCTRL_ALL8H
: return ".all8h";
536 case GEN6_PREDCTRL_ANY16H
: return ".any16h";
537 case GEN6_PREDCTRL_ALL16H
: return ".all16h";
538 case GEN7_PREDCTRL_ANY32H
: return ".any32h";
539 case GEN7_PREDCTRL_ALL32H
: return ".all32h";
540 default: return ".BAD";
543 switch (inst
->pred_ctrl
) {
544 case GEN6_PREDCTRL_NORMAL
: return "";
545 case GEN6_PREDCTRL_X
: return ".x";
546 case GEN6_PREDCTRL_Y
: return ".y";
547 case GEN6_PREDCTRL_Z
: return ".z";
548 case GEN6_PREDCTRL_W
: return ".w";
549 default: return ".BAD";
555 disasm_inst_pred_inv(const struct disasm_inst
*inst
)
557 return (inst
->pred_inv
) ? '-' : '+';
561 disasm_inst_exec_size(const struct disasm_inst
*inst
)
563 switch (inst
->exec_size
) {
564 case GEN6_EXECSIZE_1
: return "1";
565 case GEN6_EXECSIZE_2
: return "2";
566 case GEN6_EXECSIZE_4
: return "4";
567 case GEN6_EXECSIZE_8
: return "8";
568 case GEN6_EXECSIZE_16
: return "16";
569 case GEN6_EXECSIZE_32
: return "32";
570 default: return "BAD";
575 disasm_inst_fc(const struct disasm_inst
*inst
)
577 assert(inst
->opcode
== GEN6_OPCODE_MATH
);
580 case GEN6_MATH_INV
: return "inv";
581 case GEN6_MATH_LOG
: return "log";
582 case GEN6_MATH_EXP
: return "exp";
583 case GEN6_MATH_SQRT
: return "sqrt";
584 case GEN6_MATH_RSQ
: return "rsq";
585 case GEN6_MATH_SIN
: return "sin";
586 case GEN6_MATH_COS
: return "cos";
587 case GEN6_MATH_FDIV
: return "fdiv";
588 case GEN6_MATH_POW
: return "pow";
589 case GEN6_MATH_INT_DIV
: return "int_div";
590 case GEN6_MATH_INT_DIV_QUOTIENT
: return "int_div_quotient";
591 case GEN6_MATH_INT_DIV_REMAINDER
: return "int_div_remainder";
592 default: return "BAD";
597 disasm_inst_sfid(const struct disasm_inst
*inst
)
599 assert(inst
->opcode
== GEN6_OPCODE_SEND
||
600 inst
->opcode
== GEN6_OPCODE_SENDC
);
602 switch (inst
->sfid
) {
603 case GEN6_SFID_NULL
: return "null";
604 case GEN6_SFID_SAMPLER
: return "sampler";
605 case GEN6_SFID_GATEWAY
: return "gateway";
606 case GEN6_SFID_DP_SAMPLER
: return "dp sampler";
607 case GEN6_SFID_DP_RC
: return "dp render";
608 case GEN6_SFID_URB
: return "urb";
609 case GEN6_SFID_SPAWNER
: return "spawner";
610 case GEN6_SFID_VME
: return "vme";
611 case GEN6_SFID_DP_CC
: return "dp const";
612 case GEN7_SFID_DP_DC0
: return "dp data 0";
613 case GEN7_SFID_PI
: return "pixel interp";
614 case GEN75_SFID_DP_DC1
: return "dp data 1";
615 default: return "BAD";
620 disasm_inst_cond_modifier(const struct disasm_inst
*inst
)
622 switch (inst
->cond_modifier
) {
623 case GEN6_COND_NONE
: return "";
624 case GEN6_COND_Z
: return ".z";
625 case GEN6_COND_NZ
: return ".nz";
626 case GEN6_COND_G
: return ".g";
627 case GEN6_COND_GE
: return ".ge";
628 case GEN6_COND_L
: return ".l";
629 case GEN6_COND_LE
: return ".le";
630 case GEN6_COND_O
: return ".o";
631 case GEN6_COND_U
: return ".u";
632 default: return ".BAD";
637 disasm_inst_debug_ctrl(const struct disasm_inst
*inst
)
639 return (inst
->debug_ctrl
) ? ".breakpoint" : "";
643 disasm_inst_saturate(const struct disasm_inst
*inst
)
645 return (inst
->saturate
) ? ".sat" : "";
649 disasm_inst_flag_reg(const struct disasm_inst
*inst
)
651 static const char *flag_names
[2][2] = {
656 return (inst
->flag_reg
<= 1 && inst
->flag_subreg
<= 1) ?
657 flag_names
[inst
->flag_reg
][inst
->flag_subreg
] : "fBAD";
661 disasm_inst_access_mode(const struct disasm_inst
*inst
)
663 switch (inst
->access_mode
) {
664 case GEN6_ALIGN_1
: return " align1";
665 case GEN6_ALIGN_16
: return " align16";
666 default: return " alignBAD";
671 disasm_inst_mask_ctrl(const struct disasm_inst
*inst
)
673 switch (inst
->mask_ctrl
) {
674 case GEN6_MASKCTRL_NORMAL
: return "";
675 case GEN6_MASKCTRL_NOMASK
: return " WE_all";
676 default: return " WE_BAD";
681 disasm_inst_dep_ctrl(const struct disasm_inst
*inst
)
683 switch (inst
->dep_ctrl
) {
684 case GEN6_DEPCTRL_NORMAL
: return "";
685 case GEN6_DEPCTRL_NODDCLR
: return " NoDDClr";
686 case GEN6_DEPCTRL_NODDCHK
: return " NoDDChk";
687 case GEN6_DEPCTRL_NEITHER
: return " NoDDClr,NoDDChk";
688 default: return " NoDDBAD";
693 disasm_inst_qtr_ctrl(const struct disasm_inst
*inst
)
695 switch (inst
->exec_size
) {
696 case GEN6_EXECSIZE_8
:
697 switch (inst
->qtr_ctrl
) {
698 case GEN6_QTRCTRL_1Q
: return " 1Q";
699 case GEN6_QTRCTRL_2Q
: return " 2Q";
700 case GEN6_QTRCTRL_3Q
: return " 3Q";
701 case GEN6_QTRCTRL_4Q
: return " 4Q";
702 default: return " BADQ";
705 case GEN6_EXECSIZE_16
:
706 switch (inst
->qtr_ctrl
) {
707 case GEN6_QTRCTRL_1H
: return " 1H";
708 case GEN6_QTRCTRL_2H
: return " 2H";
709 default: return " BADH";
719 disasm_inst_thread_ctrl(const struct disasm_inst
*inst
)
721 switch (inst
->thread_ctrl
) {
722 case GEN6_THREADCTRL_NORMAL
: return "";
723 case GEN6_THREADCTRL_ATOMIC
: return " atomic";
724 case GEN6_THREADCTRL_SWITCH
: return " switch";
725 default: return " BAD";
730 disasm_inst_acc_wr_ctrl(const struct disasm_inst
*inst
)
732 return (inst
->acc_wr_ctrl
) ? " AccWrEnable" : "";
736 disasm_inst_cmpt_ctrl(const struct disasm_inst
*inst
)
738 return (inst
->cmpt_ctrl
) ? " compacted" : "";
742 disasm_inst_eot(const struct disasm_inst
*inst
)
744 if (inst
->opcode
== GEN6_OPCODE_SEND
||
745 inst
->opcode
== GEN6_OPCODE_SENDC
)
746 return (inst
->u
.imm32
& GEN6_MSG_EOT
) ? " EOT" : "";
752 disasm_inst_file(const struct disasm_inst
*inst
,
753 const struct disasm_operand
*operand
,
756 switch (operand
->file
) {
758 switch (operand
->reg
& 0xf0) {
759 case GEN6_ARF_NULL
: *multi_regs
= false; return "null";
760 case GEN6_ARF_A0
: *multi_regs
= true; return "a";
761 case GEN6_ARF_ACC0
: *multi_regs
= true; return "acc";
762 case GEN6_ARF_F0
: *multi_regs
= true; return "f";
763 case GEN6_ARF_SR0
: *multi_regs
= true; return "sr";
764 case GEN6_ARF_CR0
: *multi_regs
= true; return "cr";
765 case GEN6_ARF_N0
: *multi_regs
= true; return "n";
766 case GEN6_ARF_IP
: *multi_regs
= false; return "ip";
767 case GEN6_ARF_TDR
: *multi_regs
= false; return "tdr";
768 case GEN7_ARF_TM0
: *multi_regs
= true; return "tm";
769 default: *multi_regs
= false; return "BAD";
772 case GEN6_FILE_GRF
: *multi_regs
= true; return "g";
773 case GEN6_FILE_MRF
: *multi_regs
= true; return "m";
774 case GEN6_FILE_IMM
: *multi_regs
= true; return "";
775 default: *multi_regs
= false; return "BAD";
780 disasm_inst_type(const struct disasm_inst
*inst
,
781 const struct disasm_operand
*operand
)
783 if (operand
->file
== GEN6_FILE_IMM
) {
784 switch (operand
->type
) {
785 case GEN6_TYPE_UD
: return "UD";
786 case GEN6_TYPE_D
: return "D";
787 case GEN6_TYPE_UW
: return "UW";
788 case GEN6_TYPE_W
: return "W";
789 case GEN6_TYPE_UV_IMM
: return "UV";
790 case GEN6_TYPE_VF_IMM
: return "VF";
791 case GEN6_TYPE_V_IMM
: return "V";
792 case GEN6_TYPE_F
: return "F";
793 default: return "BAD";
796 switch (operand
->type
) {
797 case GEN6_TYPE_UD
: return "UD";
798 case GEN6_TYPE_D
: return "D";
799 case GEN6_TYPE_UW
: return "UW";
800 case GEN6_TYPE_W
: return "W";
801 case GEN6_TYPE_UB
: return "UB";
802 case GEN6_TYPE_B
: return "B";
803 case GEN7_TYPE_DF
: return "DF";
804 case GEN6_TYPE_F
: return "F";
805 default: return "BAD";
811 disasm_inst_vert_stride(const struct disasm_inst
*inst
, unsigned vert_stride
)
813 switch (vert_stride
) {
814 case GEN6_VERTSTRIDE_0
: return "0";
815 case GEN6_VERTSTRIDE_1
: return "1";
816 case GEN6_VERTSTRIDE_2
: return "2";
817 case GEN6_VERTSTRIDE_4
: return "4";
818 case GEN6_VERTSTRIDE_8
: return "8";
819 case GEN6_VERTSTRIDE_16
: return "16";
820 case GEN6_VERTSTRIDE_32
: return "32";
821 case GEN6_VERTSTRIDE_VXH
: return "VxH";
822 default: return "BAD";
827 disasm_inst_width(const struct disasm_inst
*inst
, unsigned width
)
830 case GEN6_WIDTH_1
: return "1";
831 case GEN6_WIDTH_2
: return "2";
832 case GEN6_WIDTH_4
: return "4";
833 case GEN6_WIDTH_8
: return "8";
834 case GEN6_WIDTH_16
: return "16";
835 default: return "BAD";
840 disasm_inst_horz_stride(const struct disasm_inst
*inst
, unsigned horz_stride
)
842 switch (horz_stride
) {
843 case GEN6_HORZSTRIDE_0
: return "0";
844 case GEN6_HORZSTRIDE_1
: return "1";
845 case GEN6_HORZSTRIDE_2
: return "2";
846 case GEN6_HORZSTRIDE_4
: return "4";
847 default: return "BAD";
852 disasm_inst_writemask(const struct disasm_inst
*inst
, unsigned writemask
)
855 case 0x0: return ".";
856 case 0x1: return ".x";
857 case 0x2: return ".y";
858 case 0x3: return ".xy";
859 case 0x4: return ".z";
860 case 0x5: return ".xz";
861 case 0x6: return ".yz";
862 case 0x7: return ".xyz";
863 case 0x8: return ".w";
864 case 0x9: return ".xw";
865 case 0xa: return ".yw";
866 case 0xb: return ".xyw";
867 case 0xc: return ".zw";
868 case 0xd: return ".xzw";
869 case 0xe: return ".yzw";
871 default: return ".BAD";
876 disasm_inst_negate(const struct disasm_inst
*inst
, bool negate
)
878 return (negate
) ? "-" : "";
882 disasm_inst_absolute(const struct disasm_inst
*inst
, bool absolute
)
884 return (absolute
) ? "(abs)" : "";
888 disasm_inst_is_null(const struct disasm_inst
*inst
,
889 const struct disasm_operand
*operand
)
891 return (operand
->file
== GEN6_FILE_ARF
&& operand
->reg
== GEN6_ARF_NULL
);
895 disasm_inst_type_size(const struct disasm_inst
*inst
,
896 const struct disasm_operand
*operand
)
898 assert(operand
->file
!= GEN6_FILE_IMM
);
900 switch (operand
->type
) {
901 case GEN6_TYPE_UD
: return 4;
902 case GEN6_TYPE_D
: return 4;
903 case GEN6_TYPE_UW
: return 2;
904 case GEN6_TYPE_W
: return 2;
905 case GEN6_TYPE_UB
: return 1;
906 case GEN6_TYPE_B
: return 1;
907 case GEN7_TYPE_DF
: return 8;
908 case GEN6_TYPE_F
: return 4;
914 disasm_printer_reset(struct disasm_printer
*printer
)
916 printer
->buf
[0] = '\0';
921 disasm_printer_get_string(struct disasm_printer
*printer
)
926 static void _util_printf_format(2, 3)
927 disasm_printer_add(struct disasm_printer
*printer
, const char *format
, ...)
929 const size_t avail
= sizeof(printer
->buf
) - printer
->len
;
933 va_start(ap
, format
);
934 written
= vsnprintf(printer
->buf
+ printer
->len
, avail
, format
, ap
);
938 if (written
< 0 || written
>= avail
) {
939 memcpy(printer
->buf
+ sizeof(printer
->buf
) - 4, "...", 4);
940 printer
->len
= sizeof(printer
->buf
) - 1;
942 printer
->len
+= written
;
947 * Pad to the specified column.
950 disasm_printer_column(struct disasm_printer
*printer
, int col
)
952 int len
= DISASM_PRINTER_COLUMN_WIDTH
* col
;
954 if (len
<= printer
->len
) {
958 /* at least one space */
959 len
= printer
->len
+ 1;
962 if (len
>= sizeof(printer
->buf
)) {
963 len
= sizeof(printer
->buf
) - 1;
965 if (len
<= printer
->len
)
969 memset(printer
->buf
+ printer
->len
, ' ', len
- printer
->len
);
971 printer
->buf
[printer
->len
] = '\0';
975 disasm_printer_add_op(struct disasm_printer
*printer
,
976 const struct disasm_inst
*inst
)
978 if (inst
->pred_ctrl
!= GEN6_PREDCTRL_NONE
) {
979 disasm_printer_add(printer
, "(%c%s%s) ",
980 disasm_inst_pred_inv(inst
),
981 disasm_inst_flag_reg(inst
),
982 disasm_inst_pred_ctrl(inst
));
985 disasm_printer_add(printer
, "%s%s%s%s",
986 disasm_inst_opcode(inst
),
987 disasm_inst_saturate(inst
),
988 disasm_inst_debug_ctrl(inst
),
989 disasm_inst_cond_modifier(inst
));
991 if (inst
->cond_modifier
!= GEN6_COND_NONE
) {
992 switch (inst
->opcode
) {
993 case GEN6_OPCODE_SEL
:
995 case GEN6_OPCODE_WHILE
:
996 /* these do not update flag registers */
999 disasm_printer_add(printer
, ".%s", disasm_inst_flag_reg(inst
));
1004 if (inst
->opcode
== GEN6_OPCODE_MATH
)
1005 disasm_printer_add(printer
, " %s", disasm_inst_fc(inst
));
1006 if (inst
->opcode
!= GEN6_OPCODE_NOP
)
1007 disasm_printer_add(printer
, "(%s)", disasm_inst_exec_size(inst
));
1011 disasm_printer_add_operand(struct disasm_printer
*printer
,
1012 const struct disasm_inst
*inst
,
1013 const struct disasm_operand
*operand
)
1018 name
= disasm_inst_file(inst
, operand
, &multi_regs
);
1020 disasm_printer_add(printer
, name
);
1024 if (operand
->file
== GEN6_FILE_IMM
) {
1025 switch (operand
->type
) {
1027 disasm_printer_add(printer
, "0x%08xUD", inst
->u
.imm32
);
1030 disasm_printer_add(printer
, "%dD", inst
->u
.imm32
);
1033 disasm_printer_add(printer
, "0x%04xUW", (uint16_t) inst
->u
.imm32
);
1036 disasm_printer_add(printer
, "%dW", (int16_t) inst
->u
.imm32
);
1038 case GEN6_TYPE_UV_IMM
:
1039 disasm_printer_add(printer
, "0x%08xUV", inst
->u
.imm32
);
1041 case GEN6_TYPE_VF_IMM
:
1042 disasm_printer_add(printer
, "Vector Float");
1044 case GEN6_TYPE_V_IMM
:
1045 disasm_printer_add(printer
, "0x%08xV", inst
->u
.imm32
);
1048 disasm_printer_add(printer
, "%-gF", uif(inst
->u
.imm32
));
1051 disasm_printer_add(printer
, "BAD");
1058 if (operand
->addr_mode
== GEN6_ADDRMODE_DIRECT
) {
1059 unsigned reg
, subreg
;
1062 if (operand
->file
== GEN6_FILE_ARF
)
1065 subreg
= operand
->subreg
/ disasm_inst_type_size(inst
, operand
);
1068 disasm_printer_add(printer
, "%s%d.%d", name
, reg
, subreg
);
1070 disasm_printer_add(printer
, "%s%d", name
, reg
);
1072 disasm_printer_add(printer
, "%s[a0.%d %d]",
1073 name
, operand
->addr_subreg
, operand
->addr_imm
);
1078 disasm_printer_add_dst(struct disasm_printer
*printer
,
1079 const struct disasm_inst
*inst
,
1080 const struct disasm_dst_operand
*dst
)
1082 disasm_printer_add_operand(printer
, inst
, &dst
->base
);
1084 /* dst is an immediate when in EU_INSTRUCTION_BRANCH_CONDITIONAL form */
1085 if (disasm_inst_is_null(inst
, &dst
->base
) ||
1086 dst
->base
.file
== GEN6_FILE_IMM
)
1089 disasm_printer_add(printer
, "<%s>%s%s",
1090 disasm_inst_horz_stride(inst
, dst
->horz_stride
),
1091 disasm_inst_writemask(inst
, dst
->writemask
),
1092 disasm_inst_type(inst
, &dst
->base
));
1096 disasm_printer_add_src(struct disasm_printer
*printer
,
1097 const struct disasm_inst
*inst
,
1098 const struct disasm_src_operand
*src
)
1100 static const char swizzle_chars
[4] = { 'x', 'y', 'z', 'w' };
1103 disasm_printer_add(printer
, "%s%s",
1104 disasm_inst_negate(inst
, src
->negate
),
1105 disasm_inst_absolute(inst
, src
->absolute
));
1107 disasm_printer_add_operand(printer
, inst
, &src
->base
);
1109 if (disasm_inst_is_null(inst
, &src
->base
) ||
1110 src
->base
.file
== GEN6_FILE_IMM
)
1113 if (src
->swizzle_x
== 0 && src
->swizzle_y
== 1 &&
1114 src
->swizzle_z
== 2 && src
->swizzle_w
== 3) {
1116 } else if (src
->swizzle_x
== src
->swizzle_y
&&
1117 src
->swizzle_x
== src
->swizzle_z
&&
1118 src
->swizzle_x
== src
->swizzle_w
) {
1119 swizzle
[0] = swizzle_chars
[src
->swizzle_x
];
1122 swizzle
[0] = swizzle_chars
[src
->swizzle_x
];
1123 swizzle
[1] = swizzle_chars
[src
->swizzle_y
];
1124 swizzle
[2] = swizzle_chars
[src
->swizzle_z
];
1125 swizzle
[3] = swizzle_chars
[src
->swizzle_w
];
1129 disasm_printer_add(printer
, "<%s,%s,%s>%s%s",
1130 disasm_inst_vert_stride(inst
, src
->vert_stride
),
1131 disasm_inst_width(inst
, src
->width
),
1132 disasm_inst_horz_stride(inst
, src
->horz_stride
),
1134 disasm_inst_type(inst
, &src
->base
));
1138 disasm_printer_add_ctrl(struct disasm_printer
*printer
,
1139 const struct disasm_inst
*inst
)
1141 if (inst
->opcode
== GEN6_OPCODE_NOP
) {
1142 disasm_printer_add(printer
, ";");
1146 disasm_printer_add(printer
, "{%s%s%s%s%s%s%s%s };",
1147 disasm_inst_access_mode(inst
),
1148 disasm_inst_mask_ctrl(inst
),
1149 disasm_inst_dep_ctrl(inst
),
1150 disasm_inst_qtr_ctrl(inst
),
1151 disasm_inst_cmpt_ctrl(inst
),
1152 disasm_inst_thread_ctrl(inst
),
1153 disasm_inst_acc_wr_ctrl(inst
),
1154 disasm_inst_eot(inst
));
1158 disasm_printer_add_mdesc_sampler(struct disasm_printer
*printer
,
1159 const struct disasm_inst
*inst
,
1164 if (inst
->dev
->gen
>= ILO_GEN(7)) {
1165 op
= READ(mdesc
, GEN7_MSG_SAMPLER_OP
);
1166 simd
= READ(mdesc
, GEN7_MSG_SAMPLER_SIMD
);
1168 op
= READ(mdesc
, GEN6_MSG_SAMPLER_OP
);
1169 simd
= READ(mdesc
, GEN6_MSG_SAMPLER_SIMD
);
1172 disasm_printer_add(printer
, " (%d, %d, %d, %d)",
1173 READ(mdesc
, GEN6_MSG_SAMPLER_SURFACE
),
1174 READ(mdesc
, GEN6_MSG_SAMPLER_INDEX
),
1179 disasm_printer_add_mdesc_urb(struct disasm_printer
*printer
,
1180 const struct disasm_inst
*inst
,
1185 bool interleaved
, complete
, allocate
, used
;
1187 if (inst
->dev
->gen
>= ILO_GEN(7)) {
1188 switch (READ(mdesc
, GEN7_MSG_URB_OP
)) {
1189 case GEN7_MSG_URB_WRITE_HWORD
: op
= "write HWord"; break;
1190 case GEN7_MSG_URB_WRITE_OWORD
: op
= "write OWord"; break;
1191 case GEN7_MSG_URB_READ_HWORD
: op
= "read HWord"; break;
1192 case GEN7_MSG_URB_READ_OWORD
: op
= "read OWord"; break;
1193 case GEN7_MSG_URB_ATOMIC_MOV
: op
= "atomic mov"; break;
1194 case GEN7_MSG_URB_ATOMIC_INC
: op
= "atomic inc"; break;
1195 default: op
= "BAD"; break;
1198 offset
= READ(mdesc
, GEN7_MSG_URB_GLOBAL_OFFSET
);
1199 interleaved
= mdesc
& GEN7_MSG_URB_INTERLEAVED
;
1200 complete
= mdesc
& GEN7_MSG_URB_COMPLETE
;
1205 switch (READ(mdesc
, GEN6_MSG_URB_OP
)) {
1206 case GEN6_MSG_URB_WRITE
: op
= "urb_write"; break;
1207 case GEN6_MSG_URB_FF_SYNC
: op
= "ff_sync"; break;
1208 default: op
= "BAD"; break;
1211 offset
= READ(mdesc
, GEN6_MSG_URB_OFFSET
);
1212 interleaved
= mdesc
& GEN6_MSG_URB_INTERLEAVED
;
1213 complete
= mdesc
& GEN6_MSG_URB_COMPLETE
;
1215 allocate
= mdesc
& GEN6_MSG_URB_ALLOCATE
;
1216 used
= mdesc
& GEN6_MSG_URB_USED
;
1219 disasm_printer_add(printer
, " %d %s%s%s%s%s", offset
, op
,
1220 (interleaved
) ? " interleave" : "",
1221 (allocate
) ? " allocate" : "",
1222 (used
) ? " used" : "",
1223 (complete
) ? " complete" : "");
1227 disasm_printer_add_mdesc_dp_sampler(struct disasm_printer
*printer
,
1228 const struct disasm_inst
*inst
,
1231 const int op
= (inst
->dev
->gen
>= ILO_GEN(7)) ?
1232 READ(mdesc
, GEN7_MSG_DP_OP
) : READ(mdesc
, GEN6_MSG_DP_OP
);
1233 const bool write_commit
= (inst
->dev
->gen
== ILO_GEN(6)) ?
1234 (mdesc
& GEN6_MSG_DP_SEND_WRITE_COMMIT
) : 0;
1236 disasm_printer_add(printer
, " (%d, %d, %d, %d)",
1237 READ(mdesc
, GEN6_MSG_DP_SURFACE
),
1238 READ(mdesc
, GEN6_MSG_DP_OWORD_BLOCK_SIZE
),
1243 disasm_printer_add_mdesc_dp_rc(struct disasm_printer
*printer
,
1244 const struct disasm_inst
*inst
,
1247 const int op
= (inst
->dev
->gen
>= ILO_GEN(7)) ?
1248 READ(mdesc
, GEN7_MSG_DP_OP
) : READ(mdesc
, GEN6_MSG_DP_OP
);
1252 if (inst
->dev
->gen
>= ILO_GEN(7.5)) {
1254 case GEN75_MSG_DP_RC_MEDIA_BLOCK_READ
: str
= "media block read"; break;
1255 case GEN75_MSG_DP_RC_MEMORY_FENCE
: str
= "memory fence"; break;
1256 case GEN75_MSG_DP_RC_MEDIA_BLOCK_WRITE
: str
= "media block write"; break;
1257 case GEN75_MSG_DP_RC_RT_WRITE
: str
= "RT write"; break;
1258 default: str
= "BAD"; break;
1261 is_rt_write
= (op
== GEN75_MSG_DP_RC_RT_WRITE
);
1262 } else if (inst
->dev
->gen
>= ILO_GEN(7)) {
1264 case GEN7_MSG_DP_RC_MEDIA_BLOCK_READ
: str
= "media block read"; break;
1265 case GEN7_MSG_DP_RC_TYPED_SURFACE_READ
: str
= "typed surface read"; break;
1266 case GEN7_MSG_DP_RC_TYPED_ATOMIC_OP
: str
= "typed atomic op"; break;
1267 case GEN7_MSG_DP_RC_MEMORY_FENCE
: str
= "memory fence"; break;
1268 case GEN7_MSG_DP_RC_MEDIA_BLOCK_WRITE
: str
= "media block write"; break;
1269 case GEN7_MSG_DP_RC_RT_WRITE
: str
= "RT write"; break;
1270 case GEN7_MSG_DP_RC_TYPED_SURFACE_WRITE
: str
= "typed surface write"; break;
1271 default: str
= "BAD"; break;
1274 is_rt_write
= (op
== GEN7_MSG_DP_RC_RT_WRITE
);
1277 case GEN6_MSG_DP_OWORD_BLOCK_READ
: str
= "OWORD block read"; break;
1278 case GEN6_MSG_DP_RT_UNORM_READ
: str
= "RT UNORM read"; break;
1279 case GEN6_MSG_DP_OWORD_DUAL_BLOCK_READ
: str
= "OWORD dual block read"; break;
1280 case GEN6_MSG_DP_MEDIA_BLOCK_READ
: str
= "media block read"; break;
1281 case GEN6_MSG_DP_UNALIGNED_OWORD_BLOCK_READ
: str
= "unaligned OWORD block read"; break;
1282 case GEN6_MSG_DP_DWORD_SCATTERED_READ
: str
= "DWORD scattered read"; break;
1283 case GEN6_MSG_DP_DWORD_ATOMIC_WRITE
: str
= "DWORD atomic write"; break;
1284 case GEN6_MSG_DP_OWORD_BLOCK_WRITE
: str
= "OWORD block write"; break;
1285 case GEN6_MSG_DP_OWORD_DUAL_BLOCK_WRITE
: str
= "OWORD dual block_write"; break;
1286 case GEN6_MSG_DP_MEDIA_BLOCK_WRITE
: str
= "media block write"; break;
1287 case GEN6_MSG_DP_DWORD_SCATTERED_WRITE
: str
= "DWORD scattered write"; break;
1288 case GEN6_MSG_DP_RT_WRITE
: str
= "RT write"; break;
1289 case GEN6_MSG_DP_SVB_WRITE
: str
= "SVB write"; break;
1290 case GEN6_MSG_DP_RT_UNORM_WRITE
: str
= "RT UNORM write"; break;
1291 default: str
= "BAD"; break;
1294 is_rt_write
= (op
== GEN6_MSG_DP_RT_WRITE
);
1297 disasm_printer_add(printer
, " %s", str
);
1300 switch (mdesc
& GEN6_MSG_DP_RT_MODE__MASK
) {
1301 case GEN6_MSG_DP_RT_MODE_SIMD16
: str
= "SIMD16"; break;
1302 case GEN6_MSG_DP_RT_MODE_SIMD16_REPDATA
: str
= "SIMD16/RepData"; break;
1303 case GEN6_MSG_DP_RT_MODE_SIMD8_DUALSRC_LO
: str
= "SIMD8/DualSrcLow"; break;
1304 case GEN6_MSG_DP_RT_MODE_SIMD8_DUALSRC_HI
: str
= "SIMD8/DualSrcHigh"; break;
1305 case GEN6_MSG_DP_RT_MODE_SIMD8_LO
: str
= "SIMD8"; break;
1306 case GEN6_MSG_DP_RT_MODE_SIMD8_IMAGE_WR
: str
= "SIMD8/ImageWrite"; break;
1307 default: str
= "BAD"; break;
1310 disasm_printer_add(printer
, " %s%s%s%s", str
,
1311 (mdesc
& GEN6_MSG_DP_SLOTGRP_HI
) ? " Hi" : "",
1312 (mdesc
& GEN6_MSG_DP_RT_LAST
) ? " LastRT" : "",
1313 (inst
->dev
->gen
== ILO_GEN(6) &&
1314 (mdesc
& GEN6_MSG_DP_SEND_WRITE_COMMIT
)) ? " WriteCommit" : "");
1317 disasm_printer_add(printer
, " Surface = %d",
1318 READ(mdesc
, GEN6_MSG_DP_SURFACE
));
1322 disasm_printer_add_mdesc(struct disasm_printer
*printer
,
1323 const struct disasm_inst
*inst
)
1325 const uint32_t mdesc
= inst
->u
.imm32
;
1327 assert(inst
->opcode
== GEN6_OPCODE_SEND
||
1328 inst
->opcode
== GEN6_OPCODE_SENDC
);
1329 assert(inst
->src1
.base
.file
== GEN6_FILE_IMM
);
1331 disasm_printer_add(printer
, " %s", disasm_inst_sfid(inst
));
1333 switch (inst
->sfid
) {
1334 case GEN6_SFID_SAMPLER
:
1335 disasm_printer_add_mdesc_sampler(printer
, inst
, mdesc
);
1337 case GEN6_SFID_DP_SAMPLER
:
1338 disasm_printer_add_mdesc_dp_sampler(printer
, inst
, mdesc
);
1340 case GEN6_SFID_DP_RC
:
1341 disasm_printer_add_mdesc_dp_rc(printer
, inst
, mdesc
);
1344 disasm_printer_add_mdesc_urb(printer
, inst
, mdesc
);
1346 case GEN6_SFID_DP_CC
:
1347 case GEN7_SFID_DP_DC0
:
1349 case GEN75_SFID_DP_DC1
:
1354 disasm_printer_add(printer
, " mlen %d rlen %d",
1355 READ(mdesc
, GEN6_MSG_MLEN
),
1356 READ(mdesc
, GEN6_MSG_RLEN
));
1360 disasm_printer_print_inst(struct disasm_printer
*printer
,
1361 const struct disasm_inst
*inst
)
1365 disasm_printer_reset(printer
);
1367 disasm_printer_column(printer
, col
++);
1368 disasm_printer_add_op(printer
, inst
);
1370 if (inst
->has_jip
|| inst
->has_uip
) {
1371 if (inst
->has_jip
) {
1372 disasm_printer_column(printer
, col
++);
1373 disasm_printer_add(printer
, "JIP: %d", (int16_t) inst
->u
.imm32
);
1376 if (inst
->has_uip
) {
1377 disasm_printer_column(printer
, col
++);
1378 disasm_printer_add(printer
, "UIP: %d",
1379 (int16_t) (inst
->u
.imm32
>> 16));
1382 const int src_count
= disasm_opcode_table
[inst
->opcode
].src_count
;
1383 const struct disasm_src_operand
*src
[3];
1386 /* get src operands */
1387 switch (src_count
) {
1389 src
[2] = &inst
->u
.src2
;
1391 src
[1] = &inst
->src1
;
1393 src
[0] = &inst
->src0
;
1400 disasm_printer_column(printer
, col
++);
1401 disasm_printer_add_dst(printer
, inst
, &inst
->dst
);
1403 for (i
= 0; i
< src_count
; i
++) {
1404 disasm_printer_column(printer
, col
++);
1405 disasm_printer_add_src(printer
, inst
, src
[i
]);
1410 if (inst
->opcode
== GEN6_OPCODE_SEND
||
1411 inst
->opcode
== GEN6_OPCODE_SENDC
) {
1412 /* start a new line */
1413 ilo_printf("%s\n", disasm_printer_get_string(printer
));
1414 disasm_printer_reset(printer
);
1417 disasm_printer_column(printer
, col
++);
1419 disasm_printer_column(printer
, col
++);
1420 disasm_printer_add_mdesc(printer
, inst
);
1426 disasm_printer_column(printer
, col
++);
1427 disasm_printer_add_ctrl(printer
, inst
);
1429 ilo_printf("%s\n", disasm_printer_get_string(printer
));
1433 toy_compiler_disassemble(const struct ilo_dev_info
*dev
,
1434 const void *kernel
, int size
,
1437 const uint32_t *cur
= (const uint32_t *) kernel
;
1438 const uint32_t *end
= cur
+ size
/ sizeof(*cur
);
1439 struct disasm_printer printer
;
1441 disasm_printer_reset(&printer
);
1444 struct disasm_inst inst
;
1445 const bool compacted
= (cur
[0] & GEN6_INST_CMPTCTRL
);
1446 const uint32_t *dw
= cur
;
1449 cur
+= (compacted
) ? 2 : 4;
1450 /* incomplete instruction */
1455 /* no compaction support yet */
1456 memset(temp
, 0, sizeof(temp
));
1461 ilo_printf("0x%08x 0x%08x 0x%08x 0x%08x ",
1462 dw
[0], dw
[1], dw
[2], dw
[3]);
1465 memset(&inst
, 0, sizeof(inst
));
1467 disasm_inst_decode(&inst
, dw
);
1468 inst
.cmpt_ctrl
= compacted
;
1470 disasm_printer_print_inst(&printer
, &inst
);