i965: Assert array index on access to vec4_visitor's arrays.
[mesa.git] / src / mesa / drivers / dri / i965 / gen8_generator.cpp
1 /*
2 * Copyright © 2012 Intel Corporation
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21 * IN THE SOFTWARE.
22 */
23
24 /** @file gen8_generator.cpp
25 *
26 * Code generation for Gen8+ hardware, replacing the brw_eu_emit.c layer.
27 */
28
29 extern "C" {
30 #include "main/compiler.h"
31 #include "main/macros.h"
32 #include "brw_context.h"
33 } /* extern "C" */
34
35 #include "glsl/ralloc.h"
36 #include "brw_eu.h"
37 #include "brw_reg.h"
38 #include "gen8_generator.h"
39
40 gen8_generator::gen8_generator(struct brw_context *brw,
41 struct gl_shader_program *shader_prog,
42 struct gl_program *prog,
43 void *mem_ctx)
44 : shader_prog(shader_prog), prog(prog), brw(brw), mem_ctx(mem_ctx)
45 {
46 ctx = &brw->ctx;
47
48 memset(&default_state, 0, sizeof(default_state));
49 default_state.mask_control = BRW_MASK_ENABLE;
50
51 store_size = 1024;
52 store = rzalloc_array(mem_ctx, gen8_instruction, store_size);
53 nr_inst = 0;
54 next_inst_offset = 0;
55
56 /* Set up the control flow stacks. */
57 if_stack_depth = 0;
58 if_stack_array_size = 16;
59 if_stack = rzalloc_array(mem_ctx, int, if_stack_array_size);
60
61 loop_stack_depth = 0;
62 loop_stack_array_size = 16;
63 loop_stack = rzalloc_array(mem_ctx, int, loop_stack_array_size);
64 }
65
66 gen8_generator::~gen8_generator()
67 {
68 }
69
70 gen8_instruction *
71 gen8_generator::next_inst(unsigned opcode)
72 {
73 gen8_instruction *inst;
74
75 if (nr_inst + 1 > unsigned(store_size)) {
76 store_size <<= 1;
77 store = reralloc(mem_ctx, store, gen8_instruction, store_size);
78 assert(store);
79 }
80
81 next_inst_offset += 16;
82 inst = &store[nr_inst++];
83
84 memset(inst, 0, sizeof(gen8_instruction));
85
86 gen8_set_opcode(inst, opcode);
87 gen8_set_exec_size(inst, default_state.exec_size);
88 gen8_set_access_mode(inst, default_state.access_mode);
89 gen8_set_mask_control(inst, default_state.mask_control);
90 gen8_set_cond_modifier(inst, default_state.conditional_mod);
91 gen8_set_pred_control(inst, default_state.predicate);
92 gen8_set_pred_inv(inst, default_state.predicate_inverse);
93 gen8_set_saturate(inst, default_state.saturate);
94 gen8_set_flag_subreg_nr(inst, default_state.flag_subreg_nr);
95 return inst;
96 }
97
98 #define ALU1(OP) \
99 gen8_instruction * \
100 gen8_generator::OP(struct brw_reg dst, struct brw_reg src) \
101 { \
102 gen8_instruction *inst = next_inst(BRW_OPCODE_##OP); \
103 gen8_set_dst(brw, inst, dst); \
104 gen8_set_src0(brw, inst, src); \
105 return inst; \
106 }
107
108 #define ALU2(OP) \
109 gen8_instruction * \
110 gen8_generator::OP(struct brw_reg dst, struct brw_reg s0, struct brw_reg s1) \
111 { \
112 gen8_instruction *inst = next_inst(BRW_OPCODE_##OP); \
113 gen8_set_dst(brw, inst, dst); \
114 gen8_set_src0(brw, inst, s0); \
115 gen8_set_src1(brw, inst, s1); \
116 return inst; \
117 }
118
119 #define ALU2_ACCUMULATE(OP) \
120 gen8_instruction * \
121 gen8_generator::OP(struct brw_reg dst, struct brw_reg s0, struct brw_reg s1) \
122 { \
123 gen8_instruction *inst = next_inst(BRW_OPCODE_##OP); \
124 gen8_set_dst(brw, inst, dst); \
125 gen8_set_src0(brw, inst, s0); \
126 gen8_set_src1(brw, inst, s1); \
127 gen8_set_acc_wr_control(inst, true); \
128 return inst; \
129 }
130
131 #define ALU3(OP) \
132 gen8_instruction * \
133 gen8_generator::OP(struct brw_reg dst, struct brw_reg s0, \
134 struct brw_reg s1, struct brw_reg s2) \
135 { \
136 return alu3(BRW_OPCODE_##OP, dst, s0, s1, s2); \
137 }
138
139 #define ALU3F(OP) \
140 gen8_instruction * \
141 gen8_generator::OP(struct brw_reg dst, struct brw_reg s0, \
142 struct brw_reg s1, struct brw_reg s2) \
143 { \
144 assert(dst.type == BRW_REGISTER_TYPE_F); \
145 assert(s0.type == BRW_REGISTER_TYPE_F); \
146 assert(s1.type == BRW_REGISTER_TYPE_F); \
147 assert(s2.type == BRW_REGISTER_TYPE_F); \
148 return alu3(BRW_OPCODE_##OP, dst, s0, s1, s2); \
149 }
150
151 ALU2(ADD)
152 ALU2(AND)
153 ALU2(ASR)
154 ALU3(BFE)
155 ALU2(BFI1)
156 ALU3(BFI2)
157 ALU1(BFREV)
158 ALU1(CBIT)
159 ALU2_ACCUMULATE(ADDC)
160 ALU2_ACCUMULATE(SUBB)
161 ALU2(DP2)
162 ALU2(DP3)
163 ALU2(DP4)
164 ALU2(DPH)
165 ALU1(FBH)
166 ALU1(FBL)
167 ALU1(FRC)
168 ALU2(LINE)
169 ALU3F(LRP)
170 ALU3F(MAD)
171 ALU2(MUL)
172 ALU1(MOV)
173 ALU1(NOT)
174 ALU2(OR)
175 ALU2(PLN)
176 ALU1(RNDD)
177 ALU1(RNDE)
178 ALU1(RNDZ)
179 ALU2_ACCUMULATE(MAC)
180 ALU2_ACCUMULATE(MACH)
181 ALU2(SEL)
182 ALU2(SHL)
183 ALU2(SHR)
184 ALU2(XOR)
185
186 gen8_instruction *
187 gen8_generator::CMP(struct brw_reg dst, unsigned conditional,
188 struct brw_reg src0, struct brw_reg src1)
189 {
190 gen8_instruction *inst = next_inst(BRW_OPCODE_CMP);
191 gen8_set_cond_modifier(inst, conditional);
192 /* The CMP instruction appears to behave erratically for floating point
193 * sources unless the destination type is also float. Overriding it to
194 * match src0 makes it work in all cases.
195 */
196 dst.type = src0.type;
197 gen8_set_dst(brw, inst, dst);
198 gen8_set_src0(brw, inst, src0);
199 gen8_set_src1(brw, inst, src1);
200 return inst;
201 }
202
203 static int
204 get_3src_subreg_nr(struct brw_reg reg)
205 {
206 if (reg.vstride == BRW_VERTICAL_STRIDE_0) {
207 assert(brw_is_single_value_swizzle(reg.dw1.bits.swizzle));
208 return reg.subnr / 4 + BRW_GET_SWZ(reg.dw1.bits.swizzle, 0);
209 } else {
210 return reg.subnr / 4;
211 }
212 }
213
214 gen8_instruction *
215 gen8_generator::alu3(unsigned opcode,
216 struct brw_reg dst,
217 struct brw_reg src0,
218 struct brw_reg src1,
219 struct brw_reg src2)
220 {
221 /* MRFs haven't existed since Gen7, so we better not be using them. */
222 if (dst.file == BRW_MESSAGE_REGISTER_FILE) {
223 dst.file = BRW_GENERAL_REGISTER_FILE;
224 dst.nr += GEN7_MRF_HACK_START;
225 }
226
227 gen8_instruction *inst = next_inst(opcode);
228 assert(gen8_access_mode(inst) == BRW_ALIGN_16);
229
230 assert(dst.file == BRW_GENERAL_REGISTER_FILE);
231 assert(dst.nr < 128);
232 assert(dst.address_mode == BRW_ADDRESS_DIRECT);
233 assert(dst.type == BRW_REGISTER_TYPE_F ||
234 dst.type == BRW_REGISTER_TYPE_D ||
235 dst.type == BRW_REGISTER_TYPE_UD);
236 gen8_set_dst_3src_reg_nr(inst, dst.nr);
237 gen8_set_dst_3src_subreg_nr(inst, dst.subnr / 16);
238 gen8_set_dst_3src_writemask(inst, dst.dw1.bits.writemask);
239
240 assert(src0.file == BRW_GENERAL_REGISTER_FILE);
241 assert(src0.address_mode == BRW_ADDRESS_DIRECT);
242 assert(src0.nr < 128);
243 gen8_set_src0_3src_swizzle(inst, src0.dw1.bits.swizzle);
244 gen8_set_src0_3src_subreg_nr(inst, get_3src_subreg_nr(src0));
245 gen8_set_src0_3src_rep_ctrl(inst, src0.vstride == BRW_VERTICAL_STRIDE_0);
246 gen8_set_src0_3src_reg_nr(inst, src0.nr);
247 gen8_set_src0_3src_abs(inst, src0.abs);
248 gen8_set_src0_3src_negate(inst, src0.negate);
249
250 assert(src1.file == BRW_GENERAL_REGISTER_FILE);
251 assert(src1.address_mode == BRW_ADDRESS_DIRECT);
252 assert(src1.nr < 128);
253 gen8_set_src1_3src_swizzle(inst, src1.dw1.bits.swizzle);
254 gen8_set_src1_3src_subreg_nr(inst, get_3src_subreg_nr(src1));
255 gen8_set_src1_3src_rep_ctrl(inst, src1.vstride == BRW_VERTICAL_STRIDE_0);
256 gen8_set_src1_3src_reg_nr(inst, src1.nr);
257 gen8_set_src1_3src_abs(inst, src1.abs);
258 gen8_set_src1_3src_negate(inst, src1.negate);
259
260 assert(src2.file == BRW_GENERAL_REGISTER_FILE);
261 assert(src2.address_mode == BRW_ADDRESS_DIRECT);
262 assert(src2.nr < 128);
263 gen8_set_src2_3src_swizzle(inst, src2.dw1.bits.swizzle);
264 gen8_set_src2_3src_subreg_nr(inst, get_3src_subreg_nr(src2));
265 gen8_set_src2_3src_rep_ctrl(inst, src2.vstride == BRW_VERTICAL_STRIDE_0);
266 gen8_set_src2_3src_reg_nr(inst, src2.nr);
267 gen8_set_src2_3src_abs(inst, src2.abs);
268 gen8_set_src2_3src_negate(inst, src2.negate);
269
270 /* Set both the source and destination types based on dst.type, ignoring
271 * the source register types. The MAD and LRP emitters both ensure that
272 * all register types are float. The BFE and BFI2 emitters, however, may
273 * send us mixed D and UD source types and want us to ignore that.
274 */
275 switch (dst.type) {
276 case BRW_REGISTER_TYPE_F:
277 gen8_set_src_3src_type(inst, BRW_3SRC_TYPE_F);
278 gen8_set_dst_3src_type(inst, BRW_3SRC_TYPE_F);
279 break;
280 case BRW_REGISTER_TYPE_D:
281 gen8_set_src_3src_type(inst, BRW_3SRC_TYPE_D);
282 gen8_set_dst_3src_type(inst, BRW_3SRC_TYPE_D);
283 break;
284 case BRW_REGISTER_TYPE_UD:
285 gen8_set_src_3src_type(inst, BRW_3SRC_TYPE_UD);
286 gen8_set_dst_3src_type(inst, BRW_3SRC_TYPE_UD);
287 break;
288 }
289
290 return inst;
291 }
292
293 gen8_instruction *
294 gen8_generator::math(unsigned math_function,
295 struct brw_reg dst,
296 struct brw_reg src0)
297 {
298 gen8_instruction *inst = next_inst(BRW_OPCODE_MATH);
299
300 assert(src0.hstride == 0 || src0.hstride == dst.hstride);
301
302 gen8_set_math_function(inst, math_function);
303 gen8_set_dst(brw, inst, dst);
304 gen8_set_src0(brw, inst, src0);
305 return inst;
306 }
307
308 gen8_instruction *
309 gen8_generator::MATH(unsigned math_function,
310 struct brw_reg dst,
311 struct brw_reg src0)
312 {
313 assert(src0.type == BRW_REGISTER_TYPE_F);
314 gen8_instruction *inst = math(math_function, dst, src0);
315 return inst;
316 }
317
318 gen8_instruction *
319 gen8_generator::MATH(unsigned math_function,
320 struct brw_reg dst,
321 struct brw_reg src0,
322 struct brw_reg src1)
323 {
324 bool int_math =
325 math_function == BRW_MATH_FUNCTION_INT_DIV_QUOTIENT ||
326 math_function == BRW_MATH_FUNCTION_INT_DIV_REMAINDER ||
327 math_function == BRW_MATH_FUNCTION_INT_DIV_QUOTIENT_AND_REMAINDER;
328
329 if (int_math) {
330 assert(src0.type != BRW_REGISTER_TYPE_F);
331 assert(src1.type != BRW_REGISTER_TYPE_F);
332 } else {
333 assert(src0.type == BRW_REGISTER_TYPE_F);
334 }
335
336 gen8_instruction *inst = math(math_function, dst, src0);
337 gen8_set_src1(brw, inst, src1);
338 return inst;
339 }
340
341 gen8_instruction *
342 gen8_generator::MOV_RAW(struct brw_reg dst, struct brw_reg src0)
343 {
344 gen8_instruction *inst = next_inst(BRW_OPCODE_MOV);
345 gen8_set_dst(brw, inst, retype(dst, BRW_REGISTER_TYPE_UD));
346 gen8_set_src0(brw, inst, retype(src0, BRW_REGISTER_TYPE_UD));
347 gen8_set_mask_control(inst, BRW_MASK_DISABLE);
348
349 return inst;
350 }
351
352
353 gen8_instruction *
354 gen8_generator::NOP()
355 {
356 return next_inst(BRW_OPCODE_NOP);
357 }
358
359 void
360 gen8_generator::push_if_stack(gen8_instruction *inst)
361 {
362 if_stack[if_stack_depth] = inst - store;
363
364 ++if_stack_depth;
365 if (if_stack_array_size <= if_stack_depth) {
366 if_stack_array_size *= 2;
367 if_stack = reralloc(mem_ctx, if_stack, int, if_stack_array_size);
368 }
369 }
370
371 gen8_instruction *
372 gen8_generator::pop_if_stack()
373 {
374 --if_stack_depth;
375 return &store[if_stack[if_stack_depth]];
376 }
377
378 /**
379 * Patch the IF and ELSE instructions to set the jump offsets (JIP and UIP.)
380 */
381 void
382 gen8_generator::patch_IF_ELSE(gen8_instruction *if_inst,
383 gen8_instruction *else_inst,
384 gen8_instruction *endif_inst)
385 {
386 assert(if_inst != NULL && gen8_opcode(if_inst) == BRW_OPCODE_IF);
387 assert(else_inst == NULL || gen8_opcode(else_inst) == BRW_OPCODE_ELSE);
388 assert(endif_inst != NULL && gen8_opcode(endif_inst) == BRW_OPCODE_ENDIF);
389
390 gen8_set_exec_size(endif_inst, gen8_exec_size(if_inst));
391
392 if (else_inst == NULL) {
393 /* Patch IF -> ENDIF */
394 gen8_set_jip(if_inst, 16 * (endif_inst - if_inst));
395 gen8_set_uip(if_inst, 16 * (endif_inst - if_inst));
396 } else {
397 gen8_set_exec_size(else_inst, gen8_exec_size(if_inst));
398
399 /* Patch IF -> ELSE and ELSE -> ENDIF:
400 *
401 * The IF's JIP should point at the instruction after the ELSE.
402 * The IF's UIP should point to the ENDIF.
403 *
404 * Both are expressed in bytes, hence the multiply by 16...128-bits.
405 */
406 gen8_set_jip(if_inst, 16 * (else_inst - if_inst + 1));
407 gen8_set_uip(if_inst, 16 * (endif_inst - if_inst));
408
409 /* Patch ELSE -> ENDIF:
410 *
411 * Since we don't set branch_ctrl, both JIP and UIP point to ENDIF.
412 */
413 gen8_set_jip(else_inst, 16 * (endif_inst - else_inst));
414 gen8_set_uip(else_inst, 16 * (endif_inst - else_inst));
415 }
416 gen8_set_jip(endif_inst, 16);
417 }
418
419 gen8_instruction *
420 gen8_generator::IF(unsigned predicate)
421 {
422 gen8_instruction *inst = next_inst(BRW_OPCODE_IF);
423 gen8_set_dst(brw, inst, vec1(retype(brw_null_reg(), BRW_REGISTER_TYPE_D)));
424 gen8_set_exec_size(inst, default_state.exec_size);
425 gen8_set_pred_control(inst, predicate);
426 gen8_set_mask_control(inst, BRW_MASK_ENABLE);
427 push_if_stack(inst);
428
429 return inst;
430 }
431
432 gen8_instruction *
433 gen8_generator::ELSE()
434 {
435 gen8_instruction *inst = next_inst(BRW_OPCODE_ELSE);
436 gen8_set_dst(brw, inst, retype(brw_null_reg(), BRW_REGISTER_TYPE_D));
437 gen8_set_mask_control(inst, BRW_MASK_ENABLE);
438 push_if_stack(inst);
439 return inst;
440 }
441
442 gen8_instruction *
443 gen8_generator::ENDIF()
444 {
445 gen8_instruction *if_inst = NULL;
446 gen8_instruction *else_inst = NULL;
447
448 gen8_instruction *tmp = pop_if_stack();
449 if (gen8_opcode(tmp) == BRW_OPCODE_ELSE) {
450 else_inst = tmp;
451 tmp = pop_if_stack();
452 }
453 assert(gen8_opcode(tmp) == BRW_OPCODE_IF);
454 if_inst = tmp;
455
456 gen8_instruction *endif_inst = next_inst(BRW_OPCODE_ENDIF);
457 gen8_set_mask_control(endif_inst, BRW_MASK_ENABLE);
458 patch_IF_ELSE(if_inst, else_inst, endif_inst);
459
460 return endif_inst;
461 }
462
463 unsigned
464 gen8_generator::next_ip(unsigned ip) const
465 {
466 return ip + 16;
467 }
468
469 unsigned
470 gen8_generator::find_next_block_end(unsigned start) const
471 {
472 for (unsigned ip = next_ip(start); ip < next_inst_offset; ip = next_ip(ip)) {
473 gen8_instruction *inst = &store[ip / 16];
474
475 switch (gen8_opcode(inst)) {
476 case BRW_OPCODE_ENDIF:
477 case BRW_OPCODE_ELSE:
478 case BRW_OPCODE_WHILE:
479 case BRW_OPCODE_HALT:
480 return ip;
481 }
482 }
483
484 return 0;
485 }
486
487 /* There is no DO instruction on Gen6+, so to find the end of the loop
488 * we have to see if the loop is jumping back before our start
489 * instruction.
490 */
491 unsigned
492 gen8_generator::find_loop_end(unsigned start) const
493 {
494 /* Always start after the instruction (such as a WHILE) we're trying to fix
495 * up.
496 */
497 for (unsigned ip = next_ip(start); ip < next_inst_offset; ip = next_ip(ip)) {
498 gen8_instruction *inst = &store[ip / 16];
499
500 if (gen8_opcode(inst) == BRW_OPCODE_WHILE) {
501 if (ip + gen8_jip(inst) <= start)
502 return ip;
503 }
504 }
505 assert(!"not reached");
506 return start;
507 }
508
509 /* After program generation, go back and update the UIP and JIP of
510 * BREAK, CONT, and HALT instructions to their correct locations.
511 */
512 void
513 gen8_generator::patch_jump_targets()
514 {
515 for (unsigned ip = 0; ip < next_inst_offset; ip = next_ip(ip)) {
516 gen8_instruction *inst = &store[ip / 16];
517
518 int block_end_ip = find_next_block_end(ip);
519 switch (gen8_opcode(inst)) {
520 case BRW_OPCODE_BREAK:
521 assert(block_end_ip != 0);
522 gen8_set_jip(inst, block_end_ip - ip);
523 gen8_set_uip(inst, find_loop_end(ip) - ip);
524 assert(gen8_uip(inst) != 0);
525 assert(gen8_jip(inst) != 0);
526 break;
527 case BRW_OPCODE_CONTINUE:
528 assert(block_end_ip != 0);
529 gen8_set_jip(inst, block_end_ip - ip);
530 gen8_set_uip(inst, find_loop_end(ip) - ip);
531 assert(gen8_uip(inst) != 0);
532 assert(gen8_jip(inst) != 0);
533 break;
534 case BRW_OPCODE_ENDIF:
535 if (block_end_ip == 0)
536 gen8_set_jip(inst, 16);
537 else
538 gen8_set_jip(inst, block_end_ip - ip);
539 break;
540 case BRW_OPCODE_HALT:
541 /* From the Sandy Bridge PRM (volume 4, part 2, section 8.3.19):
542 *
543 * "In case of the halt instruction not inside any conditional
544 * code block, the value of <JIP> and <UIP> should be the
545 * same. In case of the halt instruction inside conditional code
546 * block, the <UIP> should be the end of the program, and the
547 * <JIP> should be end of the most inner conditional code block."
548 *
549 * The uip will have already been set by whoever set up the
550 * instruction.
551 */
552 if (block_end_ip == 0) {
553 gen8_set_jip(inst, gen8_uip(inst));
554 } else {
555 gen8_set_jip(inst, block_end_ip - ip);
556 }
557 assert(gen8_uip(inst) != 0);
558 assert(gen8_jip(inst) != 0);
559 break;
560 }
561 }
562 }
563
564 void
565 gen8_generator::DO()
566 {
567 if (loop_stack_array_size < loop_stack_depth) {
568 loop_stack_array_size *= 2;
569 loop_stack = reralloc(mem_ctx, loop_stack, int, loop_stack_array_size);
570 }
571 loop_stack[loop_stack_depth++] = nr_inst;
572 }
573
574 gen8_instruction *
575 gen8_generator::BREAK()
576 {
577 gen8_instruction *inst = next_inst(BRW_OPCODE_BREAK);
578 gen8_set_dst(brw, inst, retype(brw_null_reg(), BRW_REGISTER_TYPE_D));
579 gen8_set_src0(brw, inst, retype(brw_null_reg(), BRW_REGISTER_TYPE_D));
580 gen8_set_src1(brw, inst, brw_imm_d(0));
581 gen8_set_exec_size(inst, default_state.exec_size);
582 return inst;
583 }
584
585 gen8_instruction *
586 gen8_generator::CONTINUE()
587 {
588 gen8_instruction *inst = next_inst(BRW_OPCODE_CONTINUE);
589 gen8_set_dst(brw, inst, brw_ip_reg());
590 gen8_set_src0(brw, inst, brw_ip_reg());
591 gen8_set_src1(brw, inst, brw_imm_d(0));
592 gen8_set_exec_size(inst, default_state.exec_size);
593 return inst;
594 }
595
596 gen8_instruction *
597 gen8_generator::WHILE()
598 {
599 gen8_instruction *do_inst = &store[loop_stack[--loop_stack_depth]];
600 gen8_instruction *while_inst = next_inst(BRW_OPCODE_WHILE);
601
602 gen8_set_dst(brw, while_inst, retype(brw_null_reg(), BRW_REGISTER_TYPE_D));
603 gen8_set_src0(brw, while_inst, retype(brw_null_reg(), BRW_REGISTER_TYPE_D));
604 gen8_set_src1(brw, while_inst, brw_imm_ud(0));
605 gen8_set_jip(while_inst, 16 * (do_inst - while_inst));
606 gen8_set_exec_size(while_inst, default_state.exec_size);
607
608 return while_inst;
609 }
610
611 gen8_instruction *
612 gen8_generator::HALT()
613 {
614 gen8_instruction *inst = next_inst(BRW_OPCODE_HALT);
615 gen8_set_dst(brw, inst, retype(brw_null_reg(), BRW_REGISTER_TYPE_D));
616 gen8_set_src0(brw, inst, retype(brw_null_reg(), BRW_REGISTER_TYPE_D));
617 gen8_set_exec_size(inst, default_state.exec_size);
618 gen8_set_mask_control(inst, BRW_MASK_DISABLE);
619 return inst;
620 }
621
622 void
623 gen8_generator::disassemble(FILE *out, int start, int end)
624 {
625 bool dump_hex = false;
626
627 for (int offset = start; offset < end; offset += 16) {
628 gen8_instruction *inst = &store[offset / 16];
629 fprintf(stderr, "0x%08x: ", offset);
630
631 if (dump_hex) {
632 fprintf(stderr, "0x%08x 0x%08x 0x%08x 0x%08x ",
633 ((uint32_t *) inst)[3],
634 ((uint32_t *) inst)[2],
635 ((uint32_t *) inst)[1],
636 ((uint32_t *) inst)[0]);
637 }
638
639 gen8_disassemble(stderr, inst, brw->gen);
640 }
641 }