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;
93 unsigned branch_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 [GEN8_OPCODE_GOTO
] = { "goto", 1 },
153 [GEN6_OPCODE_WAIT
] = { "wait", 1 },
154 [GEN6_OPCODE_SEND
] = { "send", 1 },
155 [GEN6_OPCODE_SENDC
] = { "sendc", 1 },
156 [GEN6_OPCODE_MATH
] = { "math", 2 },
157 [GEN6_OPCODE_ADD
] = { "add", 2 },
158 [GEN6_OPCODE_MUL
] = { "mul", 2 },
159 [GEN6_OPCODE_AVG
] = { "avg", 2 },
160 [GEN6_OPCODE_FRC
] = { "frc", 1 },
161 [GEN6_OPCODE_RNDU
] = { "rndu", 1 },
162 [GEN6_OPCODE_RNDD
] = { "rndd", 1 },
163 [GEN6_OPCODE_RNDE
] = { "rnde", 1 },
164 [GEN6_OPCODE_RNDZ
] = { "rndz", 1 },
165 [GEN6_OPCODE_MAC
] = { "mac", 2 },
166 [GEN6_OPCODE_MACH
] = { "mach", 2 },
167 [GEN6_OPCODE_LZD
] = { "lzd", 1 },
168 [GEN7_OPCODE_FBH
] = { "fbh", 1 },
169 [GEN7_OPCODE_FBL
] = { "fbl", 1 },
170 [GEN7_OPCODE_CBIT
] = { "cbit", 1 },
171 [GEN7_OPCODE_ADDC
] = { "addc", 2 },
172 [GEN7_OPCODE_SUBB
] = { "subb", 2 },
173 [GEN6_OPCODE_SAD2
] = { "sad2", 2 },
174 [GEN6_OPCODE_SADA2
] = { "sada2", 2 },
175 [GEN6_OPCODE_DP4
] = { "dp4", 2 },
176 [GEN6_OPCODE_DPH
] = { "dph", 2 },
177 [GEN6_OPCODE_DP3
] = { "dp3", 2 },
178 [GEN6_OPCODE_DP2
] = { "dp2", 2 },
179 [GEN6_OPCODE_LINE
] = { "line", 2 },
180 [GEN6_OPCODE_PLN
] = { "pln", 2 },
181 [GEN6_OPCODE_MAD
] = { "mad", 3 },
182 [GEN6_OPCODE_LRP
] = { "lrp", 3 },
183 [GEN6_OPCODE_NOP
] = { "nop", 0 },
187 disasm_inst_decode_dw0_opcode_gen6(struct disasm_inst
*inst
, uint32_t dw0
)
189 ILO_DEV_ASSERT(inst
->dev
, 6, 8);
191 inst
->opcode
= GEN_EXTRACT(dw0
, GEN6_INST_OPCODE
);
193 switch (inst
->opcode
) {
195 inst
->has_jip
= true;
196 inst
->has_uip
= (ilo_dev_gen(inst
->dev
) >= ILO_GEN(7));
198 case GEN6_OPCODE_ELSE
:
199 inst
->has_jip
= true;
200 inst
->has_uip
= (ilo_dev_gen(inst
->dev
) >= ILO_GEN(8));
202 case GEN6_OPCODE_BREAK
:
203 case GEN6_OPCODE_CONT
:
204 case GEN6_OPCODE_HALT
:
205 inst
->has_uip
= true;
207 case GEN6_OPCODE_JMPI
:
208 case GEN7_OPCODE_BRD
:
209 case GEN7_OPCODE_BRC
:
210 case GEN6_OPCODE_ENDIF
:
211 case GEN6_OPCODE_CASE
:
212 case GEN6_OPCODE_WHILE
:
213 case GEN75_OPCODE_CALLA
:
214 case GEN6_OPCODE_CALL
:
215 case GEN6_OPCODE_RETURN
:
216 inst
->has_jip
= true;
224 disasm_inst_decode_dw0_gen6(struct disasm_inst
*inst
, uint32_t dw0
)
226 ILO_DEV_ASSERT(inst
->dev
, 6, 8);
228 disasm_inst_decode_dw0_opcode_gen6(inst
, dw0
);
230 inst
->access_mode
= GEN_EXTRACT(dw0
, GEN6_INST_ACCESSMODE
);
232 if (ilo_dev_gen(inst
->dev
) >= ILO_GEN(8)) {
233 inst
->dep_ctrl
= GEN_EXTRACT(dw0
, GEN8_INST_DEPCTRL
);
234 inst
->nib_ctrl
= (bool) (dw0
& GEN8_INST_NIBCTRL
);
236 inst
->mask_ctrl
= GEN_EXTRACT(dw0
, GEN6_INST_MASKCTRL
);
237 inst
->dep_ctrl
= GEN_EXTRACT(dw0
, GEN6_INST_DEPCTRL
);
240 inst
->qtr_ctrl
= GEN_EXTRACT(dw0
, GEN6_INST_QTRCTRL
);
241 inst
->thread_ctrl
= GEN_EXTRACT(dw0
, GEN6_INST_THREADCTRL
);
242 inst
->pred_ctrl
= GEN_EXTRACT(dw0
, GEN6_INST_PREDCTRL
);
244 inst
->pred_inv
= (bool) (dw0
& GEN6_INST_PREDINV
);
246 inst
->exec_size
= GEN_EXTRACT(dw0
, GEN6_INST_EXECSIZE
);
248 switch (inst
->opcode
) {
249 case GEN6_OPCODE_SEND
:
250 case GEN6_OPCODE_SENDC
:
251 inst
->sfid
= GEN_EXTRACT(dw0
, GEN6_INST_SFID
);
253 case GEN6_OPCODE_MATH
:
254 inst
->fc
= GEN_EXTRACT(dw0
, GEN6_INST_FC
);
257 inst
->cond_modifier
= GEN_EXTRACT(dw0
, GEN6_INST_CONDMODIFIER
);
261 switch (inst
->opcode
) {
263 case GEN6_OPCODE_ELSE
:
264 case GEN8_OPCODE_GOTO
:
265 if (ilo_dev_gen(inst
->dev
) >= ILO_GEN(8)) {
266 inst
->branch_ctrl
= (bool) (dw0
& GEN8_INST_BRANCHCTRL
);
270 inst
->acc_wr_ctrl
= (bool) (dw0
& GEN6_INST_ACCWRCTRL
);
274 inst
->cmpt_ctrl
= (bool) (dw0
& GEN6_INST_CMPTCTRL
);
275 inst
->debug_ctrl
= (bool) (dw0
& GEN6_INST_DEBUGCTRL
);
276 inst
->saturate
= (bool) (dw0
& GEN6_INST_SATURATE
);
280 disasm_inst_jip_in_dw1_high_gen6(const struct disasm_inst
*inst
)
282 return (ilo_dev_gen(inst
->dev
) == ILO_GEN(6) &&
283 inst
->has_jip
&& !inst
->has_uip
);
287 disasm_inst_decode_dw1_low_gen6(struct disasm_inst
*inst
, uint32_t dw1
)
289 ILO_DEV_ASSERT(inst
->dev
, 6, 7.5);
291 inst
->dst
.base
.file
= GEN_EXTRACT(dw1
, GEN6_INST_DST_FILE
);
292 inst
->dst
.base
.type
= GEN_EXTRACT(dw1
, GEN6_INST_DST_TYPE
);
293 inst
->src0
.base
.file
= GEN_EXTRACT(dw1
, GEN6_INST_SRC0_FILE
);
294 inst
->src0
.base
.type
= GEN_EXTRACT(dw1
, GEN6_INST_SRC0_TYPE
);
295 inst
->src1
.base
.file
= GEN_EXTRACT(dw1
, GEN6_INST_SRC1_FILE
);
296 inst
->src1
.base
.type
= GEN_EXTRACT(dw1
, GEN6_INST_SRC1_TYPE
);
298 if (ilo_dev_gen(inst
->dev
) >= ILO_GEN(7))
299 inst
->nib_ctrl
= (bool) (dw1
& GEN7_INST_NIBCTRL
);
303 disasm_inst_decode_dw1_low_gen8(struct disasm_inst
*inst
, uint32_t dw1
)
305 ILO_DEV_ASSERT(inst
->dev
, 8, 8);
307 inst
->flag_subreg
= GEN_EXTRACT(dw1
, GEN8_INST_FLAG_SUBREG
);
308 inst
->flag_reg
= GEN_EXTRACT(dw1
, GEN8_INST_FLAG_REG
);
309 inst
->mask_ctrl
= GEN_EXTRACT(dw1
, GEN8_INST_MASKCTRL
);
311 inst
->dst
.base
.file
= GEN_EXTRACT(dw1
, GEN8_INST_DST_FILE
);
312 inst
->dst
.base
.type
= GEN_EXTRACT(dw1
, GEN8_INST_DST_TYPE
);
313 inst
->src0
.base
.file
= GEN_EXTRACT(dw1
, GEN8_INST_SRC0_FILE
);
314 inst
->src0
.base
.type
= GEN_EXTRACT(dw1
, GEN8_INST_SRC0_TYPE
);
316 inst
->dst
.base
.addr_imm
= GEN_EXTRACT(dw1
, GEN8_INST_DST_ADDR_IMM_BIT9
) <<
317 GEN8_INST_DST_ADDR_IMM_BIT9__SHR
;
321 disasm_inst_decode_dw1_high_gen6(struct disasm_inst
*inst
, uint32_t dw1
)
323 ILO_DEV_ASSERT(inst
->dev
, 6, 8);
325 inst
->dst
.base
.addr_mode
= GEN_EXTRACT(dw1
, GEN6_INST_DST_ADDRMODE
);
327 if (inst
->dst
.base
.addr_mode
== GEN6_ADDRMODE_DIRECT
) {
328 inst
->dst
.base
.reg
= GEN_EXTRACT(dw1
, GEN6_INST_DST_REG
);
330 if (inst
->access_mode
== GEN6_ALIGN_1
) {
331 inst
->dst
.base
.subreg
= GEN_EXTRACT(dw1
, GEN6_INST_DST_SUBREG
);
333 inst
->dst
.base
.subreg
=
334 GEN_EXTRACT(dw1
, GEN6_INST_DST_SUBREG_ALIGN16
) <<
335 GEN6_INST_DST_SUBREG_ALIGN16__SHR
;
338 if (ilo_dev_gen(inst
->dev
) >= ILO_GEN(8)) {
339 inst
->dst
.base
.addr_subreg
=
340 GEN_EXTRACT(dw1
, GEN8_INST_DST_ADDR_SUBREG
);
342 /* bit 9 is already set in disasm_inst_decode_dw1_low_gen8() */
343 if (inst
->access_mode
== GEN6_ALIGN_1
) {
344 inst
->dst
.base
.addr_imm
|=
345 GEN_EXTRACT(dw1
, GEN8_INST_DST_ADDR_IMM
);
347 inst
->dst
.base
.addr_imm
|=
348 GEN_EXTRACT(dw1
, GEN8_INST_DST_ADDR_IMM_ALIGN16
) <<
349 GEN8_INST_DST_ADDR_IMM_ALIGN16__SHR
;
352 inst
->dst
.base
.addr_subreg
=
353 GEN_EXTRACT(dw1
, GEN6_INST_DST_ADDR_SUBREG
);
355 if (inst
->access_mode
== GEN6_ALIGN_1
) {
356 inst
->dst
.base
.addr_imm
=
357 GEN_EXTRACT(dw1
, GEN6_INST_DST_ADDR_IMM
);
359 inst
->dst
.base
.addr_imm
=
360 GEN_EXTRACT(dw1
, GEN6_INST_DST_ADDR_IMM_ALIGN16
) <<
361 GEN6_INST_DST_ADDR_IMM_ALIGN16__SHR
;
366 inst
->dst
.horz_stride
= GEN_EXTRACT(dw1
, GEN6_INST_DST_HORZSTRIDE
);
368 if (inst
->access_mode
== GEN6_ALIGN_1
)
369 inst
->dst
.writemask
= 0xf;
371 inst
->dst
.writemask
= GEN_EXTRACT(dw1
, GEN6_INST_DST_WRITEMASK
);
375 disasm_inst_decode_dw1_gen6(struct disasm_inst
*inst
, uint32_t dw1
)
377 ILO_DEV_ASSERT(inst
->dev
, 6, 8);
379 if (ilo_dev_gen(inst
->dev
) >= ILO_GEN(8))
380 disasm_inst_decode_dw1_low_gen8(inst
, dw1
);
382 disasm_inst_decode_dw1_low_gen6(inst
, dw1
);
384 if (disasm_inst_jip_in_dw1_high_gen6(inst
))
385 inst
->u
.imm32
= dw1
>> 16;
387 disasm_inst_decode_dw1_high_gen6(inst
, dw1
);
391 disasm_inst_decode_dw2_dw3_gen6(struct disasm_inst
*inst
,
392 uint32_t dw2
, uint32_t dw3
)
396 ILO_DEV_ASSERT(inst
->dev
, 6, 8);
398 if (ilo_dev_gen(inst
->dev
) >= ILO_GEN(8)) {
399 inst
->src1
.base
.file
= GEN_EXTRACT(dw2
, GEN8_INST_SRC1_FILE
);
400 inst
->src1
.base
.type
= GEN_EXTRACT(dw2
, GEN8_INST_SRC1_TYPE
);
402 if (ilo_dev_gen(inst
->dev
) >= ILO_GEN(7))
403 inst
->flag_reg
= GEN_EXTRACT(dw2
, GEN7_INST_FLAG_REG
);
404 inst
->flag_subreg
= GEN_EXTRACT(dw2
, GEN6_INST_FLAG_SUBREG
);
407 if (inst
->src0
.base
.file
== GEN6_FILE_IMM
||
408 inst
->src1
.base
.file
== GEN6_FILE_IMM
) {
410 if (!disasm_inst_jip_in_dw1_high_gen6(inst
))
416 for (i
= 0; i
< count
; i
++) {
417 struct disasm_src_operand
*src
= (i
== 0) ? &inst
->src0
: &inst
->src1
;
418 const uint32_t dw
= (i
== 0) ? dw2
: dw3
;
420 src
->base
.addr_mode
= GEN_EXTRACT(dw
, GEN6_INST_SRC_ADDRMODE
);
422 if (src
->base
.addr_mode
== GEN6_ADDRMODE_DIRECT
) {
423 src
->base
.reg
= GEN_EXTRACT(dw
, GEN6_INST_SRC_REG
);
425 if (inst
->access_mode
== GEN6_ALIGN_1
) {
426 src
->base
.subreg
= GEN_EXTRACT(dw
, GEN6_INST_SRC_SUBREG
);
428 src
->base
.subreg
= GEN_EXTRACT(dw
, GEN6_INST_SRC_SUBREG_ALIGN16
) <<
429 GEN6_INST_SRC_SUBREG_ALIGN16__SHR
;
432 if (ilo_dev_gen(inst
->dev
) >= ILO_GEN(8)) {
433 src
->base
.addr_subreg
=
434 GEN_EXTRACT(dw
, GEN8_INST_SRC_ADDR_SUBREG
);
436 if (inst
->access_mode
== GEN6_ALIGN_1
) {
437 src
->base
.addr_imm
= GEN_EXTRACT(dw
, GEN8_INST_SRC_ADDR_IMM
);
440 GEN_EXTRACT(dw
, GEN8_INST_SRC_ADDR_IMM_ALIGN16
) <<
441 GEN8_INST_SRC_ADDR_IMM_ALIGN16__SHR
;
445 inst
->dst
.base
.addr_imm
|= GEN_EXTRACT(dw
,
446 GEN8_INST_SRC0_ADDR_IMM_BIT9
) <<
447 GEN8_INST_SRC0_ADDR_IMM_BIT9__SHR
;
449 inst
->dst
.base
.addr_imm
|= GEN_EXTRACT(dw
,
450 GEN8_INST_SRC1_ADDR_IMM_BIT9
) <<
451 GEN8_INST_SRC1_ADDR_IMM_BIT9__SHR
;
454 src
->base
.addr_subreg
=
455 GEN_EXTRACT(dw
, GEN6_INST_SRC_ADDR_SUBREG
);
457 if (inst
->access_mode
== GEN6_ALIGN_1
) {
458 src
->base
.addr_imm
= GEN_EXTRACT(dw
, GEN6_INST_SRC_ADDR_IMM
);
461 GEN_EXTRACT(dw
, GEN6_INST_SRC_ADDR_IMM_ALIGN16
) <<
462 GEN6_INST_SRC_ADDR_IMM_ALIGN16__SHR
;
467 src
->vert_stride
= GEN_EXTRACT(dw
, GEN6_INST_SRC_VERTSTRIDE
);
469 if (inst
->access_mode
== GEN6_ALIGN_1
) {
470 src
->width
= GEN_EXTRACT(dw
, GEN6_INST_SRC_WIDTH
);
471 src
->horz_stride
= GEN_EXTRACT(dw
, GEN6_INST_SRC_HORZSTRIDE
);
473 src
->swizzle_x
= GEN6_SWIZZLE_X
;
474 src
->swizzle_y
= GEN6_SWIZZLE_Y
;
475 src
->swizzle_z
= GEN6_SWIZZLE_Z
;
476 src
->swizzle_w
= GEN6_SWIZZLE_W
;
478 src
->width
= GEN6_WIDTH_4
;
479 src
->horz_stride
= GEN6_HORZSTRIDE_1
;
481 src
->swizzle_x
= GEN_EXTRACT(dw
, GEN6_INST_SRC_SWIZZLE_X
);
482 src
->swizzle_y
= GEN_EXTRACT(dw
, GEN6_INST_SRC_SWIZZLE_Y
);
483 src
->swizzle_z
= GEN_EXTRACT(dw
, GEN6_INST_SRC_SWIZZLE_Z
);
484 src
->swizzle_w
= GEN_EXTRACT(dw
, GEN6_INST_SRC_SWIZZLE_W
);
487 src
->negate
= (bool) (dw
& GEN6_INST_SRC_NEGATE
);
488 src
->absolute
= (bool) (dw
& GEN6_INST_SRC_ABSOLUTE
);
493 disasm_inst_decode_3src_dw1_gen6(struct disasm_inst
*inst
, uint32_t dw1
)
495 static const unsigned type_mapping
[4] = {
496 [GEN7_TYPE_F_3SRC
] = GEN6_TYPE_F
,
497 [GEN7_TYPE_D_3SRC
] = GEN6_TYPE_D
,
498 [GEN7_TYPE_UD_3SRC
] = GEN6_TYPE_UD
,
499 [GEN7_TYPE_DF_3SRC
] = GEN7_TYPE_DF
,
502 ILO_DEV_ASSERT(inst
->dev
, 6, 7.5);
504 inst
->flag_subreg
= GEN_EXTRACT(dw1
, GEN6_3SRC_FLAG_SUBREG
);
506 if (ilo_dev_gen(inst
->dev
) >= ILO_GEN(7)) {
507 inst
->nib_ctrl
= (bool) (dw1
& GEN7_3SRC_NIBCTRL
);
508 inst
->flag_reg
= GEN_EXTRACT(dw1
, GEN7_3SRC_FLAG_REG
);
510 inst
->dst
.base
.file
= GEN6_FILE_GRF
;
511 inst
->dst
.base
.type
= GEN_EXTRACT(dw1
, GEN7_3SRC_DST_TYPE
);
512 inst
->dst
.base
.type
= type_mapping
[inst
->dst
.base
.type
];
514 inst
->src0
.base
.type
= GEN_EXTRACT(dw1
, GEN7_3SRC_SRC_TYPE
);
515 inst
->src0
.base
.type
= type_mapping
[inst
->src0
.base
.type
];
517 inst
->src1
.base
.type
= inst
->src0
.base
.type
;
518 inst
->u
.src2
.base
.type
= inst
->src0
.base
.type
;
520 inst
->dst
.base
.file
= (dw1
& GEN6_3SRC_DST_FILE_MRF
) ?
521 GEN6_FILE_MRF
: GEN6_FILE_GRF
;
522 inst
->dst
.base
.type
= GEN6_TYPE_F
;
524 inst
->src0
.base
.type
= GEN6_TYPE_F
;
525 inst
->src1
.base
.type
= GEN6_TYPE_F
;
526 inst
->u
.src2
.base
.type
= GEN6_TYPE_F
;
529 inst
->dst
.base
.addr_mode
= GEN6_ADDRMODE_DIRECT
;
530 inst
->dst
.base
.reg
= GEN_EXTRACT(dw1
, GEN6_3SRC_DST_REG
);
531 inst
->dst
.base
.subreg
= GEN_EXTRACT(dw1
, GEN6_3SRC_DST_SUBREG
) <<
532 GEN6_3SRC_DST_SUBREG__SHR
;
534 inst
->dst
.horz_stride
= GEN6_HORZSTRIDE_1
;
535 inst
->dst
.writemask
= GEN_EXTRACT(dw1
, GEN6_3SRC_DST_WRITEMASK
);
537 inst
->src0
.base
.file
= GEN6_FILE_GRF
;
538 inst
->src0
.negate
= (bool) (dw1
& GEN6_3SRC_SRC0_NEGATE
);
539 inst
->src0
.absolute
= (bool) (dw1
& GEN6_3SRC_SRC0_ABSOLUTE
);
540 inst
->src1
.base
.file
= GEN6_FILE_GRF
;
541 inst
->src1
.negate
= (bool) (dw1
& GEN6_3SRC_SRC1_NEGATE
);
542 inst
->src1
.absolute
= (bool) (dw1
& GEN6_3SRC_SRC1_ABSOLUTE
);
543 inst
->u
.src2
.base
.file
= GEN6_FILE_GRF
;
544 inst
->u
.src2
.negate
= (bool) (dw1
& GEN6_3SRC_SRC2_NEGATE
);
545 inst
->u
.src2
.absolute
= (bool) (dw1
& GEN6_3SRC_SRC2_ABSOLUTE
);
549 disasm_inst_decode_3src_dw1_gen8(struct disasm_inst
*inst
, uint32_t dw1
)
551 static const unsigned type_mapping
[8] = {
552 [GEN7_TYPE_F_3SRC
] = GEN6_TYPE_F
,
553 [GEN7_TYPE_D_3SRC
] = GEN6_TYPE_D
,
554 [GEN7_TYPE_UD_3SRC
] = GEN6_TYPE_UD
,
555 [GEN7_TYPE_DF_3SRC
] = GEN7_TYPE_DF
,
556 /* map unknown types to unknown types */
563 ILO_DEV_ASSERT(inst
->dev
, 8, 8);
565 inst
->flag_subreg
= GEN_EXTRACT(dw1
, GEN8_3SRC_FLAG_SUBREG
);
566 inst
->flag_reg
= GEN_EXTRACT(dw1
, GEN8_3SRC_FLAG_REG
);
567 inst
->mask_ctrl
= GEN_EXTRACT(dw1
, GEN8_3SRC_MASKCTRL
);
568 inst
->src0
.absolute
= (bool) (dw1
& GEN8_3SRC_SRC0_ABSOLUTE
);
569 inst
->src0
.negate
= (bool) (dw1
& GEN8_3SRC_SRC0_NEGATE
);
570 inst
->src1
.negate
= (bool) (dw1
& GEN8_3SRC_SRC1_NEGATE
);
571 inst
->src1
.absolute
= (bool) (dw1
& GEN8_3SRC_SRC1_ABSOLUTE
);
572 inst
->u
.src2
.negate
= (bool) (dw1
& GEN8_3SRC_SRC2_NEGATE
);
573 inst
->u
.src2
.absolute
= (bool) (dw1
& GEN8_3SRC_SRC2_ABSOLUTE
);
575 inst
->src0
.base
.file
= GEN6_FILE_GRF
;
576 inst
->src0
.base
.type
= GEN_EXTRACT(dw1
, GEN8_3SRC_SRC_TYPE
);
577 inst
->src0
.base
.type
= type_mapping
[inst
->src0
.base
.type
];
579 inst
->src1
.base
.file
= GEN6_FILE_GRF
;
580 inst
->src1
.base
.type
= inst
->src0
.base
.type
;
582 inst
->u
.src2
.base
.file
= GEN6_FILE_GRF
;
583 inst
->u
.src2
.base
.type
= inst
->src0
.base
.type
;
585 inst
->dst
.base
.file
= GEN6_FILE_GRF
;
586 inst
->dst
.base
.type
= GEN_EXTRACT(dw1
, GEN8_3SRC_DST_TYPE
);
587 inst
->dst
.base
.type
= type_mapping
[inst
->dst
.base
.type
];
588 inst
->dst
.base
.addr_mode
= GEN6_ADDRMODE_DIRECT
;
589 inst
->dst
.horz_stride
= GEN6_HORZSTRIDE_1
;
591 inst
->dst
.writemask
= GEN_EXTRACT(dw1
, GEN6_3SRC_DST_WRITEMASK
);
592 inst
->dst
.base
.subreg
= GEN_EXTRACT(dw1
, GEN6_3SRC_DST_SUBREG
) <<
593 GEN6_3SRC_DST_SUBREG__SHR
;
594 inst
->dst
.base
.reg
= GEN_EXTRACT(dw1
, GEN6_3SRC_DST_REG
);
598 disasm_inst_decode_3src_dw2_dw3_gen6(struct disasm_inst
*inst
,
599 uint32_t dw2
, uint32_t dw3
)
601 const uint64_t qw
= (uint64_t) dw3
<< 32 | dw2
;
604 ILO_DEV_ASSERT(inst
->dev
, 6, 8);
606 for (i
= 0; i
< 3; i
++) {
607 struct disasm_src_operand
*src
= (i
== 0) ? &inst
->src0
:
608 (i
== 1) ? &inst
->src1
:
610 const uint32_t dw
= (i
== 0) ? GEN_EXTRACT(qw
, GEN6_3SRC_SRC_0
) :
611 (i
== 1) ? GEN_EXTRACT(qw
, GEN6_3SRC_SRC_1
) :
612 GEN_EXTRACT(qw
, GEN6_3SRC_SRC_2
);
614 src
->base
.addr_mode
= GEN6_ADDRMODE_DIRECT
;
615 src
->base
.reg
= GEN_EXTRACT(dw
, GEN6_3SRC_SRC_REG
);
616 src
->base
.subreg
= GEN_EXTRACT(dw
, GEN6_3SRC_SRC_SUBREG
) <<
617 GEN6_3SRC_SRC_SUBREG__SHR
;
619 if (dw
& GEN6_3SRC_SRC_REPCTRL
) {
620 src
->vert_stride
= GEN6_VERTSTRIDE_0
;
621 src
->width
= GEN6_WIDTH_1
;
622 src
->horz_stride
= GEN6_HORZSTRIDE_0
;
624 src
->vert_stride
= GEN6_VERTSTRIDE_4
;
625 src
->width
= GEN6_WIDTH_4
;
626 src
->horz_stride
= GEN6_HORZSTRIDE_1
;
629 src
->swizzle_x
= GEN_EXTRACT(dw
, GEN6_3SRC_SRC_SWIZZLE_X
);
630 src
->swizzle_y
= GEN_EXTRACT(dw
, GEN6_3SRC_SRC_SWIZZLE_Y
);
631 src
->swizzle_z
= GEN_EXTRACT(dw
, GEN6_3SRC_SRC_SWIZZLE_Z
);
632 src
->swizzle_w
= GEN_EXTRACT(dw
, GEN6_3SRC_SRC_SWIZZLE_W
);
637 * When GEN6_INST_CMPTCTRL of DW0 is set, the instruction has 64 bits and is
638 * in EU_INSTRUCTION_COMPACT_TWO_SRC form. We should have expanded it to its
641 * Depending on the opcode, the 128-bits instruction is in one of the
644 * - EU_INSTRUCTION_BASIC_ONE_SRC
645 * - EU_INSTRUCTION_BASIC_TWO_SRC
646 * - EU_INSTRUCTION_BASIC_THREE_SRC
647 * - EU_INSTRUCTION_BRANCH_CONDITIONAL
648 * - EU_INSTRUCTION_BRANCH_ONE_SRC
649 * - EU_INSTRUCTION_BRANCH_TWO_SRC
650 * - EU_INSTRUCTION_ILLEGAL
651 * - EU_INSTRUCTION_MATH
652 * - EU_INSTRUCTION_NOP
653 * - EU_INSTRUCTION_SEND
655 * In EU_INSTRUCTION_BASIC_ONE_SRC form,
657 * - DW0 is EU_INSTRUCTION_HEADER
658 * - DW1 is EU_INSTRUCTION_OPERAND_CONTROLS
659 * - DW2 is Source 0 and EU_INSTRUCTION_FLAGS
660 * - DW3 is reserved unless Source 0 is an immediate
662 * All other forms except EU_INSTRUCTION_BASIC_THREE_SRC are quite compatible
663 * with EU_INSTRUCTION_BASIC_ONE_SRC.
666 disasm_inst_decode(struct disasm_inst
*inst
,
669 assert(!(dw
[0] & GEN6_INST_CMPTCTRL
));
671 disasm_inst_decode_dw0_gen6(inst
, dw
[0]);
673 if (disasm_opcode_table
[inst
->opcode
].src_count
== 3) {
674 if (ilo_dev_gen(inst
->dev
) >= ILO_GEN(8))
675 disasm_inst_decode_3src_dw1_gen8(inst
, dw
[1]);
677 disasm_inst_decode_3src_dw1_gen6(inst
, dw
[1]);
678 disasm_inst_decode_3src_dw2_dw3_gen6(inst
, dw
[2], dw
[3]);
680 disasm_inst_decode_dw1_gen6(inst
, dw
[1]);
681 disasm_inst_decode_dw2_dw3_gen6(inst
, dw
[2], dw
[3]);
686 disasm_inst_opcode(const struct disasm_inst
*inst
)
688 return (disasm_opcode_table
[inst
->opcode
].name
) ?
689 disasm_opcode_table
[inst
->opcode
].name
: "BAD";
693 disasm_inst_pred_ctrl(const struct disasm_inst
*inst
)
695 if (inst
->access_mode
== GEN6_ALIGN_1
) {
696 switch (inst
->pred_ctrl
) {
697 case GEN6_PREDCTRL_NORMAL
: return "";
698 case GEN6_PREDCTRL_ANYV
: return ".anyv";
699 case GEN6_PREDCTRL_ALLV
: return ".allv";
700 case GEN6_PREDCTRL_ANY2H
: return ".any2h";
701 case GEN6_PREDCTRL_ALL2H
: return ".all2h";
702 case GEN6_PREDCTRL_ANY4H
: return ".any4h";
703 case GEN6_PREDCTRL_ALL4H
: return ".all4h";
704 case GEN6_PREDCTRL_ANY8H
: return ".any8h";
705 case GEN6_PREDCTRL_ALL8H
: return ".all8h";
706 case GEN6_PREDCTRL_ANY16H
: return ".any16h";
707 case GEN6_PREDCTRL_ALL16H
: return ".all16h";
708 case GEN7_PREDCTRL_ANY32H
: return ".any32h";
709 case GEN7_PREDCTRL_ALL32H
: return ".all32h";
710 default: return ".BAD";
713 switch (inst
->pred_ctrl
) {
714 case GEN6_PREDCTRL_NORMAL
: return "";
715 case GEN6_PREDCTRL_X
: return ".x";
716 case GEN6_PREDCTRL_Y
: return ".y";
717 case GEN6_PREDCTRL_Z
: return ".z";
718 case GEN6_PREDCTRL_W
: return ".w";
719 default: return ".BAD";
725 disasm_inst_pred_inv(const struct disasm_inst
*inst
)
727 return (inst
->pred_inv
) ? '-' : '+';
731 disasm_inst_exec_size(const struct disasm_inst
*inst
)
733 switch (inst
->exec_size
) {
734 case GEN6_EXECSIZE_1
: return "1";
735 case GEN6_EXECSIZE_2
: return "2";
736 case GEN6_EXECSIZE_4
: return "4";
737 case GEN6_EXECSIZE_8
: return "8";
738 case GEN6_EXECSIZE_16
: return "16";
739 case GEN6_EXECSIZE_32
: return "32";
740 default: return "BAD";
745 disasm_inst_fc(const struct disasm_inst
*inst
)
747 assert(inst
->opcode
== GEN6_OPCODE_MATH
);
750 case GEN6_MATH_INV
: return "inv";
751 case GEN6_MATH_LOG
: return "log";
752 case GEN6_MATH_EXP
: return "exp";
753 case GEN6_MATH_SQRT
: return "sqrt";
754 case GEN6_MATH_RSQ
: return "rsq";
755 case GEN6_MATH_SIN
: return "sin";
756 case GEN6_MATH_COS
: return "cos";
757 case GEN6_MATH_FDIV
: return "fdiv";
758 case GEN6_MATH_POW
: return "pow";
759 case GEN6_MATH_INT_DIV
: return "int_div";
760 case GEN6_MATH_INT_DIV_QUOTIENT
: return "int_div_quotient";
761 case GEN6_MATH_INT_DIV_REMAINDER
: return "int_div_remainder";
762 case GEN8_MATH_INVM
: return "invm";
763 case GEN8_MATH_RSQRTM
: return "rsqrtm";
764 default: return "BAD";
769 disasm_inst_sfid(const struct disasm_inst
*inst
)
771 assert(inst
->opcode
== GEN6_OPCODE_SEND
||
772 inst
->opcode
== GEN6_OPCODE_SENDC
);
774 switch (inst
->sfid
) {
775 case GEN6_SFID_NULL
: return "null";
776 case GEN6_SFID_SAMPLER
: return "sampler";
777 case GEN6_SFID_GATEWAY
: return "gateway";
778 case GEN6_SFID_DP_SAMPLER
: return "dp sampler";
779 case GEN6_SFID_DP_RC
: return "dp render";
780 case GEN6_SFID_URB
: return "urb";
781 case GEN6_SFID_SPAWNER
: return "spawner";
782 case GEN6_SFID_VME
: return "vme";
783 case GEN6_SFID_DP_CC
: return "dp const";
784 case GEN7_SFID_DP_DC0
: return "dp data 0";
785 case GEN7_SFID_PI
: return "pixel interp";
786 case GEN75_SFID_DP_DC1
: return "dp data 1";
787 default: return "BAD";
792 disasm_inst_cond_modifier(const struct disasm_inst
*inst
)
794 switch (inst
->cond_modifier
) {
795 case GEN6_COND_NONE
: return "";
796 case GEN6_COND_Z
: return ".z";
797 case GEN6_COND_NZ
: return ".nz";
798 case GEN6_COND_G
: return ".g";
799 case GEN6_COND_GE
: return ".ge";
800 case GEN6_COND_L
: return ".l";
801 case GEN6_COND_LE
: return ".le";
802 case GEN6_COND_O
: return ".o";
803 case GEN6_COND_U
: return ".u";
804 default: return ".BAD";
809 disasm_inst_debug_ctrl(const struct disasm_inst
*inst
)
811 return (inst
->debug_ctrl
) ? ".breakpoint" : "";
815 disasm_inst_saturate(const struct disasm_inst
*inst
)
817 return (inst
->saturate
) ? ".sat" : "";
821 disasm_inst_flag_reg(const struct disasm_inst
*inst
)
823 static const char *flag_names
[2][2] = {
828 return (inst
->flag_reg
<= 1 && inst
->flag_subreg
<= 1) ?
829 flag_names
[inst
->flag_reg
][inst
->flag_subreg
] : "fBAD";
833 disasm_inst_access_mode(const struct disasm_inst
*inst
)
835 switch (inst
->access_mode
) {
836 case GEN6_ALIGN_1
: return " align1";
837 case GEN6_ALIGN_16
: return " align16";
838 default: return " alignBAD";
843 disasm_inst_mask_ctrl(const struct disasm_inst
*inst
)
845 switch (inst
->mask_ctrl
) {
846 case GEN6_MASKCTRL_NORMAL
: return "";
847 case GEN6_MASKCTRL_NOMASK
: return " WE_all";
848 default: return " WE_BAD";
853 disasm_inst_dep_ctrl(const struct disasm_inst
*inst
)
855 switch (inst
->dep_ctrl
) {
856 case GEN6_DEPCTRL_NORMAL
: return "";
857 case GEN6_DEPCTRL_NODDCLR
: return " NoDDClr";
858 case GEN6_DEPCTRL_NODDCHK
: return " NoDDChk";
859 case GEN6_DEPCTRL_NEITHER
: return " NoDDClr,NoDDChk";
860 default: return " NoDDBAD";
865 disasm_inst_qtr_ctrl(const struct disasm_inst
*inst
)
867 switch (inst
->exec_size
) {
868 case GEN6_EXECSIZE_8
:
869 switch (inst
->qtr_ctrl
) {
870 case GEN6_QTRCTRL_1Q
: return " 1Q";
871 case GEN6_QTRCTRL_2Q
: return " 2Q";
872 case GEN6_QTRCTRL_3Q
: return " 3Q";
873 case GEN6_QTRCTRL_4Q
: return " 4Q";
874 default: return " BADQ";
877 case GEN6_EXECSIZE_16
:
878 switch (inst
->qtr_ctrl
) {
879 case GEN6_QTRCTRL_1H
: return " 1H";
880 case GEN6_QTRCTRL_2H
: return " 2H";
881 default: return " BADH";
891 disasm_inst_thread_ctrl(const struct disasm_inst
*inst
)
893 switch (inst
->thread_ctrl
) {
894 case GEN6_THREADCTRL_NORMAL
: return "";
895 case GEN6_THREADCTRL_ATOMIC
: return " atomic";
896 case GEN6_THREADCTRL_SWITCH
: return " switch";
897 default: return " BAD";
902 disasm_inst_acc_wr_ctrl(const struct disasm_inst
*inst
)
904 return (inst
->acc_wr_ctrl
) ? " AccWrEnable" : "";
908 disasm_inst_cmpt_ctrl(const struct disasm_inst
*inst
)
910 return (inst
->cmpt_ctrl
) ? " compacted" : "";
914 disasm_inst_eot(const struct disasm_inst
*inst
)
916 if (inst
->opcode
== GEN6_OPCODE_SEND
||
917 inst
->opcode
== GEN6_OPCODE_SENDC
)
918 return (inst
->u
.imm32
& GEN6_MSG_EOT
) ? " EOT" : "";
924 disasm_inst_file(const struct disasm_inst
*inst
,
925 const struct disasm_operand
*operand
,
928 switch (operand
->file
) {
930 switch (operand
->reg
& 0xf0) {
931 case GEN6_ARF_NULL
: *multi_regs
= false; return "null";
932 case GEN6_ARF_A0
: *multi_regs
= true; return "a";
933 case GEN6_ARF_ACC0
: *multi_regs
= true; return "acc";
934 case GEN6_ARF_F0
: *multi_regs
= true; return "f";
935 case GEN6_ARF_SR0
: *multi_regs
= true; return "sr";
936 case GEN6_ARF_CR0
: *multi_regs
= true; return "cr";
937 case GEN6_ARF_N0
: *multi_regs
= true; return "n";
938 case GEN6_ARF_IP
: *multi_regs
= false; return "ip";
939 case GEN6_ARF_TDR
: *multi_regs
= false; return "tdr";
940 case GEN7_ARF_TM0
: *multi_regs
= true; return "tm";
941 default: *multi_regs
= false; return "BAD";
944 case GEN6_FILE_GRF
: *multi_regs
= true; return "g";
945 case GEN6_FILE_MRF
: *multi_regs
= true; return "m";
946 case GEN6_FILE_IMM
: *multi_regs
= true; return "";
947 default: *multi_regs
= false; return "BAD";
952 disasm_inst_type(const struct disasm_inst
*inst
,
953 const struct disasm_operand
*operand
)
955 if (operand
->file
== GEN6_FILE_IMM
) {
956 switch (operand
->type
) {
957 case GEN6_TYPE_UD
: return "UD";
958 case GEN6_TYPE_D
: return "D";
959 case GEN6_TYPE_UW
: return "UW";
960 case GEN6_TYPE_W
: return "W";
961 case GEN6_TYPE_UV_IMM
: return "UV";
962 case GEN6_TYPE_VF_IMM
: return "VF";
963 case GEN6_TYPE_V_IMM
: return "V";
964 case GEN6_TYPE_F
: return "F";
965 case GEN8_TYPE_DF_IMM
: return "DF";
966 case GEN8_TYPE_HF_IMM
: return "HF";
967 default: return "BAD";
970 switch (operand
->type
) {
971 case GEN6_TYPE_UD
: return "UD";
972 case GEN6_TYPE_D
: return "D";
973 case GEN6_TYPE_UW
: return "UW";
974 case GEN6_TYPE_W
: return "W";
975 case GEN6_TYPE_UB
: return "UB";
976 case GEN6_TYPE_B
: return "B";
977 case GEN7_TYPE_DF
: return "DF";
978 case GEN6_TYPE_F
: return "F";
979 case GEN8_TYPE_UQ
: return "UQ";
980 case GEN8_TYPE_Q
: return "Q";
981 case GEN8_TYPE_HF
: return "HF";
982 default: return "BAD";
988 disasm_inst_vert_stride(const struct disasm_inst
*inst
, unsigned vert_stride
)
990 switch (vert_stride
) {
991 case GEN6_VERTSTRIDE_0
: return "0";
992 case GEN6_VERTSTRIDE_1
: return "1";
993 case GEN6_VERTSTRIDE_2
: return "2";
994 case GEN6_VERTSTRIDE_4
: return "4";
995 case GEN6_VERTSTRIDE_8
: return "8";
996 case GEN6_VERTSTRIDE_16
: return "16";
997 case GEN6_VERTSTRIDE_32
: return "32";
998 case GEN6_VERTSTRIDE_VXH
: return "VxH";
999 default: return "BAD";
1004 disasm_inst_width(const struct disasm_inst
*inst
, unsigned width
)
1007 case GEN6_WIDTH_1
: return "1";
1008 case GEN6_WIDTH_2
: return "2";
1009 case GEN6_WIDTH_4
: return "4";
1010 case GEN6_WIDTH_8
: return "8";
1011 case GEN6_WIDTH_16
: return "16";
1012 default: return "BAD";
1017 disasm_inst_horz_stride(const struct disasm_inst
*inst
, unsigned horz_stride
)
1019 switch (horz_stride
) {
1020 case GEN6_HORZSTRIDE_0
: return "0";
1021 case GEN6_HORZSTRIDE_1
: return "1";
1022 case GEN6_HORZSTRIDE_2
: return "2";
1023 case GEN6_HORZSTRIDE_4
: return "4";
1024 default: return "BAD";
1029 disasm_inst_writemask(const struct disasm_inst
*inst
, unsigned writemask
)
1031 switch (writemask
) {
1032 case 0x0: return ".";
1033 case 0x1: return ".x";
1034 case 0x2: return ".y";
1035 case 0x3: return ".xy";
1036 case 0x4: return ".z";
1037 case 0x5: return ".xz";
1038 case 0x6: return ".yz";
1039 case 0x7: return ".xyz";
1040 case 0x8: return ".w";
1041 case 0x9: return ".xw";
1042 case 0xa: return ".yw";
1043 case 0xb: return ".xyw";
1044 case 0xc: return ".zw";
1045 case 0xd: return ".xzw";
1046 case 0xe: return ".yzw";
1047 case 0xf: return "";
1048 default: return ".BAD";
1053 disasm_inst_negate(const struct disasm_inst
*inst
, bool negate
)
1055 if (ilo_dev_gen(inst
->dev
) >= ILO_GEN(8)) {
1056 switch (inst
->opcode
) {
1057 case GEN6_OPCODE_AND
:
1058 case GEN6_OPCODE_NOT
:
1059 case GEN6_OPCODE_OR
:
1060 case GEN6_OPCODE_XOR
:
1061 return (negate
) ? "~" : "";
1068 return (negate
) ? "-" : "";
1072 disasm_inst_absolute(const struct disasm_inst
*inst
, bool absolute
)
1074 return (absolute
) ? "(abs)" : "";
1078 disasm_inst_mdesc_sampler_op(const struct disasm_inst
*inst
, int op
)
1081 case GEN6_MSG_SAMPLER_SAMPLE
: return "sample";
1082 case GEN6_MSG_SAMPLER_SAMPLE_B
: return "sample_b";
1083 case GEN6_MSG_SAMPLER_SAMPLE_L
: return "sample_l";
1084 case GEN6_MSG_SAMPLER_SAMPLE_C
: return "sample_c";
1085 case GEN6_MSG_SAMPLER_SAMPLE_D
: return "sample_d";
1086 case GEN6_MSG_SAMPLER_SAMPLE_B_C
: return "sample_b_c";
1087 case GEN6_MSG_SAMPLER_SAMPLE_L_C
: return "sample_l_c";
1088 case GEN6_MSG_SAMPLER_LD
: return "ld";
1089 case GEN6_MSG_SAMPLER_GATHER4
: return "gather4";
1090 case GEN6_MSG_SAMPLER_LOD
: return "lod";
1091 case GEN6_MSG_SAMPLER_RESINFO
: return "resinfo";
1092 case GEN6_MSG_SAMPLER_SAMPLEINFO
: return "sampleinfo";
1093 case GEN7_MSG_SAMPLER_GATHER4_C
: return "gather4_c";
1094 case GEN7_MSG_SAMPLER_GATHER4_PO
: return "gather4_po";
1095 case GEN7_MSG_SAMPLER_GATHER4_PO_C
: return "gather4_po_c";
1096 case GEN7_MSG_SAMPLER_SAMPLE_D_C
: return "sample_d_c";
1097 case GEN7_MSG_SAMPLER_SAMPLE_LZ
: return "sample_lz";
1098 case GEN7_MSG_SAMPLER_SAMPLE_C_LC
: return "sample_c_lc";
1099 case GEN7_MSG_SAMPLER_LD_LZ
: return "ld_lz";
1100 case GEN7_MSG_SAMPLER_LD_MCS
: return "ld_mcs";
1101 case GEN7_MSG_SAMPLER_LD2DMS
: return "ld2dms";
1102 case GEN7_MSG_SAMPLER_LD2DSS
: return "ld2dss";
1103 default: return "BAD";
1108 disasm_inst_mdesc_sampler_simd(const struct disasm_inst
*inst
, int simd
)
1111 case GEN6_MSG_SAMPLER_SIMD4X2
: return "SIMD4x2";
1112 case GEN6_MSG_SAMPLER_SIMD8
: return "SIMD8";
1113 case GEN6_MSG_SAMPLER_SIMD16
: return "SIMD16";
1114 case GEN6_MSG_SAMPLER_SIMD32_64
: return "SIMD32";
1115 default: return "BAD";
1120 disasm_inst_mdesc_urb_op(const struct disasm_inst
*inst
, int op
)
1122 if (ilo_dev_gen(inst
->dev
) >= ILO_GEN(7)) {
1124 case GEN7_MSG_URB_WRITE_HWORD
: return "write HWord";
1125 case GEN7_MSG_URB_WRITE_OWORD
: return "write OWord";
1126 case GEN7_MSG_URB_READ_HWORD
: return "read HWord";
1127 case GEN7_MSG_URB_READ_OWORD
: return "read OWord";
1128 case GEN7_MSG_URB_ATOMIC_MOV
: return "atomic mov";
1129 case GEN7_MSG_URB_ATOMIC_INC
: return "atomic inc";
1130 default: return "BAD";
1134 case GEN6_MSG_URB_WRITE
: return "urb_write";
1135 case GEN6_MSG_URB_FF_SYNC
: return "ff_sync";
1136 default: return "BAD";
1142 disasm_inst_mdesc_dp_op_gen6(const struct disasm_inst
*inst
,
1145 ILO_DEV_ASSERT(inst
->dev
, 6, 6);
1148 case GEN6_MSG_DP_OWORD_BLOCK_READ
: return "OWORD block read";
1149 case GEN6_MSG_DP_RT_UNORM_READ
: return "RT UNORM read";
1150 case GEN6_MSG_DP_OWORD_DUAL_BLOCK_READ
: return "OWORD dual block read";
1151 case GEN6_MSG_DP_MEDIA_BLOCK_READ
: return "media block read";
1152 case GEN6_MSG_DP_UNALIGNED_OWORD_BLOCK_READ
: return "unaligned OWORD block read";
1153 case GEN6_MSG_DP_DWORD_SCATTERED_READ
: return "DWORD scattered read";
1154 case GEN6_MSG_DP_DWORD_ATOMIC_WRITE
: return "DWORD atomic write";
1155 case GEN6_MSG_DP_OWORD_BLOCK_WRITE
: return "OWORD block write";
1156 case GEN6_MSG_DP_OWORD_DUAL_BLOCK_WRITE
: return "OWORD dual block_write";
1157 case GEN6_MSG_DP_MEDIA_BLOCK_WRITE
: return "media block write";
1158 case GEN6_MSG_DP_DWORD_SCATTERED_WRITE
: return "DWORD scattered write";
1159 case GEN6_MSG_DP_RT_WRITE
: return "RT write";
1160 case GEN6_MSG_DP_SVB_WRITE
: return "SVB write";
1161 case GEN6_MSG_DP_RT_UNORM_WRITE
: return "RT UNORM write";
1162 default: return "BAD";
1167 disasm_inst_mdesc_dp_op_gen7(const struct disasm_inst
*inst
,
1170 ILO_DEV_ASSERT(inst
->dev
, 7, 7);
1173 case GEN6_SFID_DP_SAMPLER
:
1175 case GEN7_MSG_DP_SAMPLER_UNALIGNED_OWORD_BLOCK_READ
: return "OWORD block read";
1176 case GEN7_MSG_DP_SAMPLER_MEDIA_BLOCK_READ
: return "media block read";
1177 default: return "BAD";
1179 case GEN6_SFID_DP_RC
:
1181 case GEN7_MSG_DP_RC_MEDIA_BLOCK_READ
: return "media block read";
1182 case GEN7_MSG_DP_RC_TYPED_SURFACE_READ
: return "typed surface read";
1183 case GEN7_MSG_DP_RC_TYPED_ATOMIC_OP
: return "typed atomic op";
1184 case GEN7_MSG_DP_RC_MEMORY_FENCE
: return "memory fence";
1185 case GEN7_MSG_DP_RC_MEDIA_BLOCK_WRITE
: return "media block write";
1186 case GEN7_MSG_DP_RC_RT_WRITE
: return "RT write";
1187 case GEN7_MSG_DP_RC_TYPED_SURFACE_WRITE
: return "typed surface write";
1188 default: return "BAD";
1190 case GEN6_SFID_DP_CC
:
1192 case GEN7_MSG_DP_CC_OWORD_BLOCK_READ
: return "OWROD block read";
1193 case GEN7_MSG_DP_CC_UNALIGNED_OWORD_BLOCK_READ
: return "unaligned OWORD block read";
1194 case GEN7_MSG_DP_CC_OWORD_DUAL_BLOCK_READ
: return "OWORD dual block read";
1195 case GEN7_MSG_DP_CC_DWORD_SCATTERED_READ
: return "DWORD scattered read";
1196 default: return "BAD";
1198 case GEN7_SFID_DP_DC0
:
1200 case GEN7_MSG_DP_DC0_OWORD_BLOCK_READ
: return "OWORD block read";
1201 case GEN7_MSG_DP_DC0_UNALIGNED_OWORD_BLOCK_READ
: return "unaligned OWORD block read";
1202 case GEN7_MSG_DP_DC0_OWORD_DUAL_BLOCK_READ
: return "OWORD dual block read";
1203 case GEN7_MSG_DP_DC0_DWORD_SCATTERED_READ
: return "DWORD scattered read";
1204 case GEN7_MSG_DP_DC0_BYTE_SCATTERED_READ
: return "BYTE scattered read";
1205 case GEN7_MSG_DP_DC0_UNTYPED_SURFACE_READ
: return "untyped surface read";
1206 case GEN7_MSG_DP_DC0_UNTYPED_ATOMIC_OP
: return "untyped atomic op";
1207 case GEN7_MSG_DP_DC0_MEMORY_FENCE
: return "memory fence";
1208 case GEN7_MSG_DP_DC0_OWORD_BLOCK_WRITE
: return "OWORD block write";
1209 case GEN7_MSG_DP_DC0_OWORD_DUAL_BLOCK_WRITE
: return "OWORD dual block write";
1210 case GEN7_MSG_DP_DC0_DWORD_SCATTERED_WRITE
: return "OWORD scattered write";
1211 case GEN7_MSG_DP_DC0_BYTE_SCATTERED_WRITE
: return "BYTE scattered write";
1212 case GEN7_MSG_DP_DC0_UNTYPED_SURFACE_WRITE
: return "untyped surface write";
1213 default: return "BAD";
1215 default: return "BAD";
1220 disasm_inst_mdesc_dp_op_gen75(const struct disasm_inst
*inst
,
1223 ILO_DEV_ASSERT(inst
->dev
, 7.5, 8);
1226 case GEN6_SFID_DP_SAMPLER
:
1228 case GEN75_MSG_DP_SAMPLER_READ_SURFACE_INFO
: return "read surface info";
1229 case GEN75_MSG_DP_SAMPLER_UNALIGNED_OWORD_BLOCK_READ
: return "unaligned OWORD block read";
1230 case GEN75_MSG_DP_SAMPLER_MEDIA_BLOCK_READ
: return "media block read";
1231 default: return "BAD";
1234 case GEN6_SFID_DP_RC
:
1236 case GEN75_MSG_DP_RC_MEDIA_BLOCK_READ
: return "media block read";
1237 case GEN75_MSG_DP_RC_MEMORY_FENCE
: return "memory fence";
1238 case GEN75_MSG_DP_RC_MEDIA_BLOCK_WRITE
: return "media block write";
1239 case GEN75_MSG_DP_RC_RT_WRITE
: return "RT write";
1240 default: return "BAD";
1242 case GEN6_SFID_DP_CC
:
1244 case GEN75_MSG_DP_CC_OWORD_BLOCK_READ
: return "OWROD block read";
1245 case GEN75_MSG_DP_CC_UNALIGNED_OWORD_BLOCK_READ
: return "unaligned OWORD block read";
1246 case GEN75_MSG_DP_CC_OWORD_DUAL_BLOCK_READ
: return "OWORD dual block read";
1247 case GEN75_MSG_DP_CC_DWORD_SCATTERED_READ
: return "DWORD scattered read";
1248 default: return "BAD";
1250 case GEN7_SFID_DP_DC0
:
1252 case GEN75_MSG_DP_DC0_OWORD_BLOCK_READ
: return "OWORD block read";
1253 case GEN75_MSG_DP_DC0_UNALIGNED_OWORD_BLOCK_READ
: return "unaligned OWORD block read";
1254 case GEN75_MSG_DP_DC0_OWORD_DUAL_BLOCK_READ
: return "OWORD dual block read";
1255 case GEN75_MSG_DP_DC0_DWORD_SCATTERED_READ
: return "DWORD scattered read";
1256 case GEN75_MSG_DP_DC0_BYTE_SCATTERED_READ
: return "BYTE scattered read";
1257 case GEN75_MSG_DP_DC0_MEMORY_FENCE
: return "memory fence";
1258 case GEN75_MSG_DP_DC0_OWORD_BLOCK_WRITE
: return "OWORD block write";
1259 case GEN75_MSG_DP_DC0_OWORD_DUAL_BLOCK_WRITE
: return "OWORD dual block write";
1260 case GEN75_MSG_DP_DC0_DWORD_SCATTERED_WRITE
: return "OWORD scattered write";
1261 case GEN75_MSG_DP_DC0_BYTE_SCATTERED_WRITE
: return "BYTE scattered write";
1262 default: return "BAD";
1264 case GEN75_SFID_DP_DC1
:
1266 case GEN75_MSG_DP_DC1_UNTYPED_SURFACE_READ
: return "untyped surface read";
1267 case GEN75_MSG_DP_DC1_UNTYPED_ATOMIC_OP
: return "DC untyped atomic op";
1268 case GEN75_MSG_DP_DC1_UNTYPED_ATOMIC_OP_SIMD4X2
: return "DC untyped 4x2 atomic op";
1269 case GEN75_MSG_DP_DC1_MEDIA_BLOCK_READ
: return "DC media block read";
1270 case GEN75_MSG_DP_DC1_TYPED_SURFACE_READ
: return "DC typed surface read";
1271 case GEN75_MSG_DP_DC1_TYPED_ATOMIC_OP
: return "DC typed atomic";
1272 case GEN75_MSG_DP_DC1_TYPED_ATOMIC_OP_SIMD4X2
: return "DC typed 4x2 atomic op";
1273 case GEN75_MSG_DP_DC1_UNTYPED_SURFACE_WRITE
: return "DC untyped surface write";
1274 case GEN75_MSG_DP_DC1_MEDIA_BLOCK_WRITE
: return "DC media block write";
1275 case GEN75_MSG_DP_DC1_ATOMIC_COUNTER_OP
: return "DC atomic counter op";
1276 case GEN75_MSG_DP_DC1_ATOMIC_COUNTER_OP_SIMD4X2
: return "DC 4x2 atomic counter op";
1277 case GEN75_MSG_DP_DC1_TYPED_SURFACE_WRITE
: return "DC typed surface write";
1278 default: return "BAD";
1280 default: return "BAD";
1285 disasm_inst_mdesc_dp_op(const struct disasm_inst
*inst
, int sfid
, int op
)
1287 switch (ilo_dev_gen(inst
->dev
)) {
1289 case ILO_GEN(7.5): return disasm_inst_mdesc_dp_op_gen75(inst
, sfid
, op
);
1290 case ILO_GEN(7): return disasm_inst_mdesc_dp_op_gen7(inst
, sfid
, op
);
1291 case ILO_GEN(6): return disasm_inst_mdesc_dp_op_gen6(inst
, sfid
, op
);
1292 default: return "BAD";
1297 disasm_inst_mdesc_dp_untyped_surface_simd_mode(const struct disasm_inst
*inst
,
1300 switch (mdesc
& GEN7_MSG_DP_UNTYPED_MODE__MASK
) {
1301 case GEN7_MSG_DP_UNTYPED_MODE_SIMD4X2
: return "SIMD4x2";
1302 case GEN7_MSG_DP_UNTYPED_MODE_SIMD16
: return "SIMD16";
1303 case GEN7_MSG_DP_UNTYPED_MODE_SIMD8
: return "SIMD8";
1304 default: return "BAD";
1309 disasm_inst_mdesc_dp_rt_write_simd_mode(const struct disasm_inst
*inst
,
1312 switch (mdesc
& GEN6_MSG_DP_RT_MODE__MASK
) {
1313 case GEN6_MSG_DP_RT_MODE_SIMD16
: return "SIMD16";
1314 case GEN6_MSG_DP_RT_MODE_SIMD16_REPDATA
: return "SIMD16/RepData";
1315 case GEN6_MSG_DP_RT_MODE_SIMD8_DUALSRC_LO
: return "SIMD8/DualSrcLow";
1316 case GEN6_MSG_DP_RT_MODE_SIMD8_DUALSRC_HI
: return "SIMD8/DualSrcHigh";
1317 case GEN6_MSG_DP_RT_MODE_SIMD8_LO
: return "SIMD8";
1318 case GEN6_MSG_DP_RT_MODE_SIMD8_IMAGE_WR
: return "SIMD8/ImageWrite";
1319 default: return "BAD";
1324 disasm_inst_is_null(const struct disasm_inst
*inst
,
1325 const struct disasm_operand
*operand
)
1327 return (operand
->file
== GEN6_FILE_ARF
&& operand
->reg
== GEN6_ARF_NULL
);
1331 disasm_inst_type_size(const struct disasm_inst
*inst
,
1332 const struct disasm_operand
*operand
)
1334 assert(operand
->file
!= GEN6_FILE_IMM
);
1336 switch (operand
->type
) {
1337 case GEN6_TYPE_UD
: return 4;
1338 case GEN6_TYPE_D
: return 4;
1339 case GEN6_TYPE_UW
: return 2;
1340 case GEN6_TYPE_W
: return 2;
1341 case GEN6_TYPE_UB
: return 1;
1342 case GEN6_TYPE_B
: return 1;
1343 case GEN7_TYPE_DF
: return 8;
1344 case GEN6_TYPE_F
: return 4;
1350 disasm_printer_reset(struct disasm_printer
*printer
)
1352 printer
->buf
[0] = '\0';
1357 disasm_printer_get_string(struct disasm_printer
*printer
)
1359 return printer
->buf
;
1362 static void _util_printf_format(2, 3)
1363 disasm_printer_add(struct disasm_printer
*printer
, const char *format
, ...)
1365 const size_t avail
= sizeof(printer
->buf
) - printer
->len
;
1369 va_start(ap
, format
);
1370 written
= vsnprintf(printer
->buf
+ printer
->len
, avail
, format
, ap
);
1374 if (written
< 0 || written
>= avail
) {
1375 memcpy(printer
->buf
+ sizeof(printer
->buf
) - 4, "...", 4);
1376 printer
->len
= sizeof(printer
->buf
) - 1;
1378 printer
->len
+= written
;
1383 * Pad to the specified column.
1386 disasm_printer_column(struct disasm_printer
*printer
, int col
)
1388 int len
= DISASM_PRINTER_COLUMN_WIDTH
* col
;
1390 if (len
<= printer
->len
) {
1394 /* at least one space */
1395 len
= printer
->len
+ 1;
1398 if (len
>= sizeof(printer
->buf
)) {
1399 len
= sizeof(printer
->buf
) - 1;
1401 if (len
<= printer
->len
)
1405 memset(printer
->buf
+ printer
->len
, ' ', len
- printer
->len
);
1407 printer
->buf
[printer
->len
] = '\0';
1411 disasm_printer_add_op(struct disasm_printer
*printer
,
1412 const struct disasm_inst
*inst
)
1414 if (inst
->pred_ctrl
!= GEN6_PREDCTRL_NONE
) {
1415 disasm_printer_add(printer
, "(%c%s%s) ",
1416 disasm_inst_pred_inv(inst
),
1417 disasm_inst_flag_reg(inst
),
1418 disasm_inst_pred_ctrl(inst
));
1421 disasm_printer_add(printer
, "%s%s%s%s",
1422 disasm_inst_opcode(inst
),
1423 disasm_inst_saturate(inst
),
1424 disasm_inst_debug_ctrl(inst
),
1425 disasm_inst_cond_modifier(inst
));
1427 if (inst
->cond_modifier
!= GEN6_COND_NONE
) {
1428 switch (inst
->opcode
) {
1429 case GEN6_OPCODE_SEL
:
1430 case GEN6_OPCODE_IF
:
1431 case GEN6_OPCODE_WHILE
:
1432 /* these do not update flag registers */
1435 disasm_printer_add(printer
, ".%s", disasm_inst_flag_reg(inst
));
1440 if (inst
->opcode
== GEN6_OPCODE_MATH
)
1441 disasm_printer_add(printer
, " %s", disasm_inst_fc(inst
));
1442 if (inst
->opcode
!= GEN6_OPCODE_NOP
)
1443 disasm_printer_add(printer
, "(%s)", disasm_inst_exec_size(inst
));
1447 disasm_printer_add_operand(struct disasm_printer
*printer
,
1448 const struct disasm_inst
*inst
,
1449 const struct disasm_operand
*operand
)
1454 name
= disasm_inst_file(inst
, operand
, &multi_regs
);
1456 disasm_printer_add(printer
, "%s", name
);
1460 if (operand
->file
== GEN6_FILE_IMM
) {
1461 switch (operand
->type
) {
1463 disasm_printer_add(printer
, "0x%08xUD", inst
->u
.imm32
);
1466 disasm_printer_add(printer
, "%dD", inst
->u
.imm32
);
1469 disasm_printer_add(printer
, "0x%04xUW", (uint16_t) inst
->u
.imm32
);
1472 disasm_printer_add(printer
, "%dW", (int16_t) inst
->u
.imm32
);
1474 case GEN6_TYPE_UV_IMM
:
1475 disasm_printer_add(printer
, "0x%08xUV", inst
->u
.imm32
);
1477 case GEN6_TYPE_VF_IMM
:
1478 disasm_printer_add(printer
, "Vector Float");
1480 case GEN6_TYPE_V_IMM
:
1481 disasm_printer_add(printer
, "0x%08xV", inst
->u
.imm32
);
1484 disasm_printer_add(printer
, "%-gF", uif(inst
->u
.imm32
));
1487 disasm_printer_add(printer
, "BAD");
1494 if (operand
->addr_mode
== GEN6_ADDRMODE_DIRECT
) {
1495 unsigned reg
, subreg
;
1498 if (operand
->file
== GEN6_FILE_ARF
)
1501 subreg
= operand
->subreg
/ disasm_inst_type_size(inst
, operand
);
1504 disasm_printer_add(printer
, "%s%d.%d", name
, reg
, subreg
);
1506 disasm_printer_add(printer
, "%s%d", name
, reg
);
1508 disasm_printer_add(printer
, "%s[a0.%d %d]",
1509 name
, operand
->addr_subreg
, operand
->addr_imm
);
1514 disasm_printer_add_dst(struct disasm_printer
*printer
,
1515 const struct disasm_inst
*inst
,
1516 const struct disasm_dst_operand
*dst
)
1518 disasm_printer_add_operand(printer
, inst
, &dst
->base
);
1520 /* dst is an immediate when in EU_INSTRUCTION_BRANCH_CONDITIONAL form */
1521 if (disasm_inst_is_null(inst
, &dst
->base
) ||
1522 dst
->base
.file
== GEN6_FILE_IMM
)
1525 disasm_printer_add(printer
, "<%s>%s%s",
1526 disasm_inst_horz_stride(inst
, dst
->horz_stride
),
1527 disasm_inst_writemask(inst
, dst
->writemask
),
1528 disasm_inst_type(inst
, &dst
->base
));
1532 disasm_printer_add_src(struct disasm_printer
*printer
,
1533 const struct disasm_inst
*inst
,
1534 const struct disasm_src_operand
*src
)
1536 static const char swizzle_chars
[4] = { 'x', 'y', 'z', 'w' };
1539 disasm_printer_add(printer
, "%s%s",
1540 disasm_inst_negate(inst
, src
->negate
),
1541 disasm_inst_absolute(inst
, src
->absolute
));
1543 disasm_printer_add_operand(printer
, inst
, &src
->base
);
1545 if (disasm_inst_is_null(inst
, &src
->base
) ||
1546 src
->base
.file
== GEN6_FILE_IMM
)
1549 if (src
->swizzle_x
== 0 && src
->swizzle_y
== 1 &&
1550 src
->swizzle_z
== 2 && src
->swizzle_w
== 3) {
1552 } else if (src
->swizzle_x
== src
->swizzle_y
&&
1553 src
->swizzle_x
== src
->swizzle_z
&&
1554 src
->swizzle_x
== src
->swizzle_w
) {
1555 swizzle
[0] = swizzle_chars
[src
->swizzle_x
];
1558 swizzle
[0] = swizzle_chars
[src
->swizzle_x
];
1559 swizzle
[1] = swizzle_chars
[src
->swizzle_y
];
1560 swizzle
[2] = swizzle_chars
[src
->swizzle_z
];
1561 swizzle
[3] = swizzle_chars
[src
->swizzle_w
];
1565 disasm_printer_add(printer
, "<%s,%s,%s>%s%s",
1566 disasm_inst_vert_stride(inst
, src
->vert_stride
),
1567 disasm_inst_width(inst
, src
->width
),
1568 disasm_inst_horz_stride(inst
, src
->horz_stride
),
1570 disasm_inst_type(inst
, &src
->base
));
1574 disasm_printer_add_ctrl(struct disasm_printer
*printer
,
1575 const struct disasm_inst
*inst
)
1577 if (inst
->opcode
== GEN6_OPCODE_NOP
) {
1578 disasm_printer_add(printer
, ";");
1582 disasm_printer_add(printer
, "{%s%s%s%s%s%s%s%s };",
1583 disasm_inst_access_mode(inst
),
1584 disasm_inst_mask_ctrl(inst
),
1585 disasm_inst_dep_ctrl(inst
),
1586 disasm_inst_qtr_ctrl(inst
),
1587 disasm_inst_cmpt_ctrl(inst
),
1588 disasm_inst_thread_ctrl(inst
),
1589 disasm_inst_acc_wr_ctrl(inst
),
1590 disasm_inst_eot(inst
));
1594 disasm_printer_add_mdesc_sampler(struct disasm_printer
*printer
,
1595 const struct disasm_inst
*inst
,
1600 if (ilo_dev_gen(inst
->dev
) >= ILO_GEN(7)) {
1601 op
= GEN_EXTRACT(mdesc
, GEN7_MSG_SAMPLER_OP
);
1602 simd
= GEN_EXTRACT(mdesc
, GEN7_MSG_SAMPLER_SIMD
);
1604 op
= GEN_EXTRACT(mdesc
, GEN6_MSG_SAMPLER_OP
);
1605 simd
= GEN_EXTRACT(mdesc
, GEN6_MSG_SAMPLER_SIMD
);
1608 disasm_printer_add(printer
,
1609 "%s %s samp %d surf %d",
1610 disasm_inst_mdesc_sampler_op(inst
, op
),
1611 disasm_inst_mdesc_sampler_simd(inst
, simd
),
1612 GEN_EXTRACT(mdesc
, GEN6_MSG_SAMPLER_INDEX
),
1613 GEN_EXTRACT(mdesc
, GEN6_MSG_SAMPLER_SURFACE
));
1617 disasm_printer_add_mdesc_urb(struct disasm_printer
*printer
,
1618 const struct disasm_inst
*inst
,
1622 bool interleaved
, complete
, allocate
, used
;
1624 if (ilo_dev_gen(inst
->dev
) >= ILO_GEN(7)) {
1625 op
= GEN_EXTRACT(mdesc
, GEN7_MSG_URB_OP
);
1626 offset
= GEN_EXTRACT(mdesc
, GEN7_MSG_URB_GLOBAL_OFFSET
);
1627 interleaved
= mdesc
& GEN7_MSG_URB_INTERLEAVED
;
1629 complete
= (ilo_dev_gen(inst
->dev
) >= ILO_GEN(8)) ?
1630 false : (mdesc
& GEN7_MSG_URB_COMPLETE
);
1635 op
= GEN_EXTRACT(mdesc
, GEN6_MSG_URB_OP
);
1636 offset
= GEN_EXTRACT(mdesc
, GEN6_MSG_URB_OFFSET
);
1637 interleaved
= mdesc
& GEN6_MSG_URB_INTERLEAVED
;
1638 complete
= mdesc
& GEN6_MSG_URB_COMPLETE
;
1640 allocate
= mdesc
& GEN6_MSG_URB_ALLOCATE
;
1641 used
= mdesc
& GEN6_MSG_URB_USED
;
1644 disasm_printer_add(printer
, "%s offset %d%s%s%s%s",
1645 disasm_inst_mdesc_urb_op(inst
, op
),
1647 (interleaved
) ? " interleave" : "",
1648 (allocate
) ? " allocate" : "",
1649 (used
) ? " used" : "",
1650 (complete
) ? " complete" : "");
1654 disasm_printer_add_mdesc_spawner(struct disasm_printer
*printer
,
1655 const struct disasm_inst
*inst
,
1658 const char *requester
, *op
;
1660 switch (mdesc
& GEN6_MSG_TS_REQUESTER_TYPE__MASK
) {
1661 case GEN6_MSG_TS_REQUESTER_TYPE_ROOT
: requester
= "root"; break;
1662 case GEN6_MSG_TS_REQUESTER_TYPE_CHILD
: requester
= "child"; break;
1663 default: requester
= "BAD"; break;
1666 switch (mdesc
& GEN6_MSG_TS_OPCODE__MASK
) {
1667 case GEN6_MSG_TS_OPCODE_DEREF
:
1668 op
= (mdesc
& GEN6_MSG_TS_RESOURCE_SELECT_NO_DEREF
) ?
1669 "no deref" : "deref";
1671 case GEN6_MSG_TS_OPCODE_SPAWN
:
1672 op
= (mdesc
& GEN6_MSG_TS_RESOURCE_SELECT_ROOT
) ?
1673 "spawn root" : "spawn child";
1680 disasm_printer_add(printer
, "%s thread %s", requester
, op
);
1684 disasm_printer_add_mdesc_dp_sampler(struct disasm_printer
*printer
,
1685 const struct disasm_inst
*inst
,
1688 const int op
= (ilo_dev_gen(inst
->dev
) >= ILO_GEN(7)) ?
1689 GEN_EXTRACT(mdesc
, GEN7_MSG_DP_OP
) : GEN_EXTRACT(mdesc
, GEN6_MSG_DP_OP
);
1690 const bool write_commit
= (ilo_dev_gen(inst
->dev
) == ILO_GEN(6)) ?
1691 (mdesc
& GEN6_MSG_DP_SEND_WRITE_COMMIT
) : 0;
1693 disasm_printer_add(printer
, "%s block size %d commit %d surf %d",
1694 disasm_inst_mdesc_dp_op(inst
, GEN6_SFID_DP_SAMPLER
, op
),
1695 GEN_EXTRACT(mdesc
, GEN6_MSG_DP_OWORD_BLOCK_SIZE
),
1697 GEN_EXTRACT(mdesc
, GEN6_MSG_DP_SURFACE
));
1701 disasm_printer_add_mdesc_dp_dc0(struct disasm_printer
*printer
,
1702 const struct disasm_inst
*inst
,
1705 const int op
= GEN_EXTRACT(mdesc
, GEN7_MSG_DP_OP
);
1707 ILO_DEV_ASSERT(inst
->dev
, 7, 7.5);
1709 if (ilo_dev_gen(inst
->dev
) >= ILO_GEN(7.5)) {
1710 disasm_printer_add(printer
, "%s ctrl 0x%x surf %d",
1711 disasm_inst_mdesc_dp_op(inst
, GEN7_SFID_DP_DC0
, op
),
1712 GEN_EXTRACT(mdesc
, GEN6_MSG_DP_CTRL
),
1713 GEN_EXTRACT(mdesc
, GEN6_MSG_DP_SURFACE
));
1716 case GEN7_MSG_DP_DC0_UNTYPED_SURFACE_READ
:
1717 case GEN7_MSG_DP_DC0_UNTYPED_SURFACE_WRITE
:
1718 disasm_printer_add(printer
, "%s %s mask 0x%x surf %d",
1719 disasm_inst_mdesc_dp_op(inst
, GEN7_SFID_DP_DC0
, op
),
1720 disasm_inst_mdesc_dp_untyped_surface_simd_mode(inst
, mdesc
),
1721 GEN_EXTRACT(mdesc
, GEN7_MSG_DP_UNTYPED_MASK
),
1722 GEN_EXTRACT(mdesc
, GEN6_MSG_DP_SURFACE
));
1725 disasm_printer_add(printer
, "%s ctrl 0x%x surf %d",
1726 disasm_inst_mdesc_dp_op(inst
, GEN7_SFID_DP_DC0
, op
),
1727 GEN_EXTRACT(mdesc
, GEN6_MSG_DP_CTRL
),
1728 GEN_EXTRACT(mdesc
, GEN6_MSG_DP_SURFACE
));
1735 disasm_printer_add_mdesc_dp_dc1(struct disasm_printer
*printer
,
1736 const struct disasm_inst
*inst
,
1739 const int op
= GEN_EXTRACT(mdesc
, GEN7_MSG_DP_OP
);
1741 ILO_DEV_ASSERT(inst
->dev
, 7.5, 7.5);
1744 case GEN75_MSG_DP_DC1_UNTYPED_SURFACE_READ
:
1745 case GEN75_MSG_DP_DC1_UNTYPED_SURFACE_WRITE
:
1746 disasm_printer_add(printer
, "%s %s mask 0x%x surf %d",
1747 disasm_inst_mdesc_dp_op(inst
, GEN75_SFID_DP_DC1
, op
),
1748 disasm_inst_mdesc_dp_untyped_surface_simd_mode(inst
, mdesc
),
1749 GEN_EXTRACT(mdesc
, GEN7_MSG_DP_UNTYPED_MASK
),
1750 GEN_EXTRACT(mdesc
, GEN6_MSG_DP_SURFACE
));
1753 disasm_printer_add(printer
, "%s ctrl 0x%x surf %d",
1754 disasm_inst_mdesc_dp_op(inst
, GEN75_SFID_DP_DC1
, op
),
1755 GEN_EXTRACT(mdesc
, GEN6_MSG_DP_CTRL
),
1756 GEN_EXTRACT(mdesc
, GEN6_MSG_DP_SURFACE
));
1762 disasm_printer_add_mdesc_dp_rc(struct disasm_printer
*printer
,
1763 const struct disasm_inst
*inst
,
1766 const int op
= (ilo_dev_gen(inst
->dev
) >= ILO_GEN(7)) ?
1767 GEN_EXTRACT(mdesc
, GEN7_MSG_DP_OP
) : GEN_EXTRACT(mdesc
, GEN6_MSG_DP_OP
);
1770 if (ilo_dev_gen(inst
->dev
) >= ILO_GEN(7.5))
1771 is_rt_write
= (op
== GEN75_MSG_DP_RC_RT_WRITE
);
1772 else if (ilo_dev_gen(inst
->dev
) >= ILO_GEN(7))
1773 is_rt_write
= (op
== GEN7_MSG_DP_RC_RT_WRITE
);
1775 is_rt_write
= (op
== GEN6_MSG_DP_RT_WRITE
);
1777 disasm_printer_add(printer
, "%s",
1778 disasm_inst_mdesc_dp_op(inst
, GEN6_SFID_DP_RC
, op
));
1781 disasm_printer_add(printer
, " %s%s%s%s",
1782 disasm_inst_mdesc_dp_rt_write_simd_mode(inst
, mdesc
),
1783 (mdesc
& GEN6_MSG_DP_RT_SLOTGRP_HI
) ? " Hi" : "",
1784 (mdesc
& GEN6_MSG_DP_RT_LAST
) ? " LastRT" : "",
1785 (ilo_dev_gen(inst
->dev
) == ILO_GEN(6) &&
1786 (mdesc
& GEN6_MSG_DP_SEND_WRITE_COMMIT
)) ? " WriteCommit" : "");
1789 disasm_printer_add(printer
, " surf %d",
1790 GEN_EXTRACT(mdesc
, GEN6_MSG_DP_SURFACE
));
1794 disasm_printer_add_mdesc(struct disasm_printer
*printer
,
1795 const struct disasm_inst
*inst
)
1797 const uint32_t mdesc
= inst
->u
.imm32
;
1799 assert(inst
->opcode
== GEN6_OPCODE_SEND
||
1800 inst
->opcode
== GEN6_OPCODE_SENDC
);
1801 assert(inst
->src1
.base
.file
== GEN6_FILE_IMM
);
1803 disasm_printer_add(printer
, " %s (", disasm_inst_sfid(inst
));
1805 switch (inst
->sfid
) {
1806 case GEN6_SFID_SAMPLER
:
1807 disasm_printer_add_mdesc_sampler(printer
, inst
, mdesc
);
1809 case GEN6_SFID_DP_SAMPLER
:
1810 disasm_printer_add_mdesc_dp_sampler(printer
, inst
, mdesc
);
1812 case GEN6_SFID_DP_RC
:
1813 disasm_printer_add_mdesc_dp_rc(printer
, inst
, mdesc
);
1816 disasm_printer_add_mdesc_urb(printer
, inst
, mdesc
);
1818 case GEN6_SFID_SPAWNER
:
1819 disasm_printer_add_mdesc_spawner(printer
, inst
, mdesc
);
1821 case GEN7_SFID_DP_DC0
:
1822 disasm_printer_add_mdesc_dp_dc0(printer
, inst
, mdesc
);
1824 case GEN75_SFID_DP_DC1
:
1825 disasm_printer_add_mdesc_dp_dc1(printer
, inst
, mdesc
);
1827 case GEN6_SFID_DP_CC
:
1833 disasm_printer_add(printer
, ") mlen %d rlen %d",
1834 GEN_EXTRACT(mdesc
, GEN6_MSG_MLEN
),
1835 GEN_EXTRACT(mdesc
, GEN6_MSG_RLEN
));
1839 disasm_printer_print_inst(struct disasm_printer
*printer
,
1840 const struct disasm_inst
*inst
)
1844 disasm_printer_reset(printer
);
1846 disasm_printer_column(printer
, col
++);
1847 disasm_printer_add_op(printer
, inst
);
1849 if (inst
->has_jip
|| inst
->has_uip
) {
1850 if (inst
->has_jip
) {
1851 disasm_printer_column(printer
, col
++);
1852 disasm_printer_add(printer
, "JIP: %d", (int16_t) inst
->u
.imm32
);
1855 if (inst
->has_uip
) {
1856 disasm_printer_column(printer
, col
++);
1857 disasm_printer_add(printer
, "UIP: %d",
1858 (int16_t) (inst
->u
.imm32
>> 16));
1861 const int src_count
= disasm_opcode_table
[inst
->opcode
].src_count
;
1864 const struct disasm_src_operand
*src
[3] = {
1865 &inst
->src0
, &inst
->src1
, &inst
->u
.src2
1869 disasm_printer_column(printer
, col
++);
1870 disasm_printer_add_dst(printer
, inst
, &inst
->dst
);
1872 for (i
= 0; i
< src_count
; i
++) {
1873 disasm_printer_column(printer
, col
++);
1874 disasm_printer_add_src(printer
, inst
, src
[i
]);
1879 if (inst
->opcode
== GEN6_OPCODE_SEND
||
1880 inst
->opcode
== GEN6_OPCODE_SENDC
) {
1881 /* start a new line */
1882 ilo_printf("%s\n", disasm_printer_get_string(printer
));
1883 disasm_printer_reset(printer
);
1886 disasm_printer_column(printer
, col
++);
1888 disasm_printer_column(printer
, col
++);
1889 disasm_printer_add_mdesc(printer
, inst
);
1895 disasm_printer_column(printer
, col
++);
1896 disasm_printer_add_ctrl(printer
, inst
);
1898 ilo_printf("%s\n", disasm_printer_get_string(printer
));
1902 disasm_uncompact_3src(const struct ilo_dev_info
*dev
,
1903 uint64_t compact
, uint32_t *dw
)
1905 const struct toy_compaction_table
*tbl
=
1906 toy_compiler_get_compaction_table(dev
);
1907 uint32_t src
[3], tmp
;
1910 ILO_DEV_ASSERT(dev
, 8, 8);
1912 tmp
= GEN_EXTRACT(compact
, GEN8_COMPACT_3SRC_OPCODE
);
1913 dw
[0] = GEN_SHIFT32(tmp
, GEN6_INST_OPCODE
);
1916 tmp
= GEN_EXTRACT(compact
, GEN8_COMPACT_3SRC_CONTROL_INDEX
);
1917 tmp
= tbl
->control_3src
[tmp
];
1919 dw
[0] |= (tmp
& 0x1fffff) << GEN6_INST_ACCESSMODE__SHIFT
;
1920 dw
[1] = (tmp
>> 21) & ((ilo_dev_gen(dev
) >= ILO_GEN(9)) ? 0x1f : 0x7);
1923 tmp
= GEN_EXTRACT(compact
, GEN8_COMPACT_3SRC_SOURCE_INDEX
);
1924 tmp64
= tbl
->source_3src
[tmp
];
1926 dw
[1] |= (tmp64
& 0x7ffff) << 5;
1927 src
[0] = ((tmp64
>> 19) & 0xff) << 1;
1928 src
[1] = ((tmp64
>> 27) & 0xff) << 1;
1929 src
[2] = ((tmp64
>> 35) & 0xff) << 1;
1930 if (ilo_dev_gen(dev
) >= ILO_GEN(9)) {
1931 src
[0] |= ((tmp64
>> 43) & 0x3) << 19;
1932 src
[1] |= ((tmp64
>> 45) & 0x3) << 19;
1933 src
[2] |= ((tmp64
>> 47) & 0x3) << 19;
1935 src
[0] |= ((tmp64
>> 43) & 0x1) << 19;
1936 src
[1] |= ((tmp64
>> 44) & 0x1) << 19;
1937 src
[2] |= ((tmp64
>> 45) & 0x1) << 19;
1940 tmp
= GEN_EXTRACT(compact
, GEN8_COMPACT_3SRC_DST_REG
);
1941 dw
[1] |= GEN_SHIFT32(tmp
, GEN6_3SRC_DST_REG
);
1943 if (compact
& GEN8_COMPACT_3SRC_SRC0_REPCTRL
)
1944 src
[0] |= GEN6_3SRC_SRC_REPCTRL
;
1946 assert(compact
& GEN8_COMPACT_3SRC_CMPTCTRL
);
1948 if (compact
& GEN8_COMPACT_3SRC_DEBUGCTRL
)
1949 dw
[0] |= GEN6_INST_DEBUGCTRL
;
1950 if (compact
& GEN8_COMPACT_3SRC_SATURATE
)
1951 dw
[0] |= GEN6_INST_SATURATE
;
1953 if (compact
& GEN8_COMPACT_3SRC_SRC1_REPCTRL
)
1954 src
[1] |= GEN6_3SRC_SRC_REPCTRL
;
1955 if (compact
& GEN8_COMPACT_3SRC_SRC2_REPCTRL
)
1956 src
[2] |= GEN6_3SRC_SRC_REPCTRL
;
1958 tmp
= GEN_EXTRACT(compact
, GEN8_COMPACT_3SRC_SRC0_SUBREG
);
1959 src
[0] |= GEN_SHIFT32(tmp
, GEN6_3SRC_SRC_SUBREG
);
1960 tmp
= GEN_EXTRACT(compact
, GEN8_COMPACT_3SRC_SRC1_SUBREG
);
1961 src
[1] |= GEN_SHIFT32(tmp
, GEN6_3SRC_SRC_SUBREG
);
1962 tmp
= GEN_EXTRACT(compact
, GEN8_COMPACT_3SRC_SRC2_SUBREG
);
1963 src
[2] |= GEN_SHIFT32(tmp
, GEN6_3SRC_SRC_SUBREG
);
1965 tmp
= GEN_EXTRACT(compact
, GEN8_COMPACT_3SRC_SRC0_REG
);
1966 src
[0] |= GEN_SHIFT32(tmp
, GEN6_3SRC_SRC_REG
);
1967 tmp
= GEN_EXTRACT(compact
, GEN8_COMPACT_3SRC_SRC1_REG
);
1968 src
[1] |= GEN_SHIFT32(tmp
, GEN6_3SRC_SRC_REG
);
1969 tmp
= GEN_EXTRACT(compact
, GEN8_COMPACT_3SRC_SRC2_REG
);
1970 src
[2] |= GEN_SHIFT32(tmp
, GEN6_3SRC_SRC_REG
);
1972 tmp64
= (uint64_t) src
[2] << 42 |
1973 (uint64_t) src
[1] << 21 |
1975 dw
[2] = (uint32_t) tmp64
;
1976 dw
[3] = (uint32_t) (tmp64
>> 32);
1980 disasm_uncompact(const struct ilo_dev_info
*dev
,
1981 uint64_t compact
, uint32_t *dw
)
1983 const struct toy_compaction_table
*tbl
=
1984 toy_compiler_get_compaction_table(dev
);
1988 ILO_DEV_ASSERT(dev
, 6, 8);
1990 tmp
= GEN_EXTRACT(compact
, GEN6_COMPACT_OPCODE
);
1991 if (disasm_opcode_table
[tmp
].src_count
== 3) {
1992 disasm_uncompact_3src(dev
, compact
, dw
);
1996 memset(dw
, 0, sizeof(*dw
) * 4);
1998 dw
[0] |= GEN_SHIFT32(tmp
, GEN6_INST_OPCODE
);
2000 if (ilo_dev_gen(dev
) >= ILO_GEN(7) && (compact
& GEN6_COMPACT_DEBUGCTRL
))
2001 dw
[0] |= GEN6_INST_DEBUGCTRL
;
2004 tmp
= GEN_EXTRACT(compact
, GEN6_COMPACT_CONTROL_INDEX
);
2005 tmp
= tbl
->control
[tmp
];
2007 dw
[0] |= (tmp
& 0xffff) << GEN6_INST_ACCESSMODE__SHIFT
;
2009 dw
[0] |= GEN6_INST_SATURATE
;
2011 if (ilo_dev_gen(dev
) >= ILO_GEN(7))
2012 dw
[2] |= (tmp
>> 17) << GEN6_INST_FLAG_SUBREG__SHIFT
;
2015 tmp
= GEN_EXTRACT(compact
, GEN6_COMPACT_DATATYPE_INDEX
);
2016 tmp
= tbl
->datatype
[tmp
];
2018 dw
[1] |= (tmp
& 0x7fff) << GEN6_INST_DST_FILE__SHIFT
;
2019 dw
[1] |= (tmp
>> 15) << GEN6_INST_DST_HORZSTRIDE__SHIFT
;
2022 tmp
= GEN_EXTRACT(compact
, GEN6_COMPACT_SUBREG_INDEX
);
2023 tmp
= tbl
->subreg
[tmp
];
2025 dw
[1] |= (tmp
& 0x1f) << 16;
2026 dw
[2] |= ((tmp
>> 5) & 0x1f);
2027 dw
[3] |= ((tmp
>> 10) & 0x1f);
2029 if (compact
& GEN6_COMPACT_ACCWRCTRL
)
2030 dw
[0] |= GEN6_INST_ACCWRCTRL
;
2032 tmp
= GEN_EXTRACT(compact
, GEN6_COMPACT_CONDMODIFIER
);
2033 dw
[0] |= GEN_SHIFT32(tmp
, GEN6_INST_CONDMODIFIER
);
2035 if (ilo_dev_gen(dev
) == ILO_GEN(6)) {
2036 tmp
= GEN_EXTRACT(compact
, GEN6_COMPACT_FLAG_SUBREG
);
2037 dw
[2] |= GEN_SHIFT32(compact
, GEN6_INST_FLAG_SUBREG
);
2040 assert(compact
& GEN6_COMPACT_CMPTCTRL
);
2043 tmp
= GEN_EXTRACT(compact
, GEN6_COMPACT_SRC0_INDEX
);
2044 tmp
= tbl
->src
[tmp
];
2047 src_is_imm
= (GEN_EXTRACT(dw
[1], GEN6_INST_SRC0_FILE
) == GEN6_FILE_IMM
) ||
2048 (GEN_EXTRACT(dw
[1], GEN6_INST_SRC1_FILE
) == GEN6_FILE_IMM
);
2051 tmp
= GEN_EXTRACT(compact
, GEN6_COMPACT_SRC1_INDEX
);
2057 tmp
= tbl
->src
[tmp
];
2061 tmp
= GEN_EXTRACT(compact
, GEN6_COMPACT_DST_REG
);
2062 dw
[1] |= GEN_SHIFT32(tmp
, GEN6_INST_DST_REG
);
2064 tmp
= GEN_EXTRACT(compact
, GEN6_COMPACT_SRC0_REG
);
2065 dw
[2] |= GEN_SHIFT32(tmp
, GEN6_INST_SRC_REG
);
2067 tmp
= GEN_EXTRACT(compact
, GEN6_COMPACT_SRC1_REG
);
2071 dw
[3] |= GEN_SHIFT32(tmp
, GEN6_INST_SRC_REG
);
2075 toy_compiler_disassemble(const struct ilo_dev_info
*dev
,
2076 const void *kernel
, int size
,
2079 const uint32_t *cur
= (const uint32_t *) kernel
;
2080 const uint32_t *end
= cur
+ size
/ sizeof(*cur
);
2081 struct disasm_printer printer
;
2083 disasm_printer_reset(&printer
);
2086 struct disasm_inst inst
;
2087 const bool compacted
= (cur
[0] & GEN6_INST_CMPTCTRL
);
2088 const uint32_t *dw
= cur
;
2091 cur
+= (compacted
) ? 2 : 4;
2092 /* incomplete instruction */
2097 const uint64_t compact
= (uint64_t) dw
[1] << 32 | dw
[0];
2098 disasm_uncompact(dev
, compact
, temp
);
2103 ilo_printf("0x%08x 0x%08x 0x%08x 0x%08x ",
2104 dw
[0], dw
[1], dw
[2], dw
[3]);
2107 memset(&inst
, 0, sizeof(inst
));
2109 disasm_inst_decode(&inst
, dw
);
2110 inst
.cmpt_ctrl
= compacted
;
2112 disasm_printer_print_inst(&printer
, &inst
);