intel/eu/validate/gen12: Add TGL to eu_validate tests.
[mesa.git] / src / intel / compiler / test_eu_validate.cpp
1 /*
2 * Copyright © 2016 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 #include <gtest/gtest.h>
25 #include "brw_eu.h"
26 #include "util/ralloc.h"
27
28 static const struct gen_info {
29 const char *name;
30 } gens[] = {
31 { "brw", },
32 { "g4x", },
33 { "ilk", },
34 { "snb", },
35 { "ivb", },
36 { "byt", },
37 { "hsw", },
38 { "bdw", },
39 { "chv", },
40 { "skl", },
41 { "bxt", },
42 { "kbl", },
43 { "aml", },
44 { "glk", },
45 { "cfl", },
46 { "whl", },
47 { "cnl", },
48 { "icl", },
49 { "tgl", },
50 };
51
52 class validation_test: public ::testing::TestWithParam<struct gen_info> {
53 virtual void SetUp();
54
55 public:
56 validation_test();
57 virtual ~validation_test();
58
59 struct brw_codegen *p;
60 struct gen_device_info devinfo;
61 };
62
63 validation_test::validation_test()
64 {
65 p = rzalloc(NULL, struct brw_codegen);
66 memset(&devinfo, 0, sizeof(devinfo));
67 }
68
69 validation_test::~validation_test()
70 {
71 ralloc_free(p);
72 }
73
74 void validation_test::SetUp()
75 {
76 struct gen_info info = GetParam();
77 int devid = gen_device_name_to_pci_device_id(info.name);
78
79 gen_get_device_info_from_pci_id(devid, &devinfo);
80
81 brw_init_codegen(&devinfo, p, p);
82 }
83
84 struct gen_name {
85 template <class ParamType>
86 std::string
87 operator()(const ::testing::TestParamInfo<ParamType>& info) const {
88 return info.param.name;
89 }
90 };
91
92 INSTANTIATE_TEST_CASE_P(eu_assembly, validation_test,
93 ::testing::ValuesIn(gens),
94 gen_name());
95
96 static bool
97 validate(struct brw_codegen *p)
98 {
99 const bool print = getenv("TEST_DEBUG");
100 struct disasm_info *disasm = disasm_initialize(p->devinfo, NULL);
101
102 if (print) {
103 disasm_new_inst_group(disasm, 0);
104 disasm_new_inst_group(disasm, p->next_insn_offset);
105 }
106
107 bool ret = brw_validate_instructions(p->devinfo, p->store, 0,
108 p->next_insn_offset, disasm);
109
110 if (print) {
111 dump_assembly(p->store, disasm);
112 }
113 ralloc_free(disasm);
114
115 return ret;
116 }
117
118 #define last_inst (&p->store[p->nr_insn - 1])
119 #define g0 brw_vec8_grf(0, 0)
120 #define acc0 brw_acc_reg(8)
121 #define null brw_null_reg()
122 #define zero brw_imm_f(0.0f)
123
124 static void
125 clear_instructions(struct brw_codegen *p)
126 {
127 p->next_insn_offset = 0;
128 p->nr_insn = 0;
129 }
130
131 TEST_P(validation_test, sanity)
132 {
133 brw_ADD(p, g0, g0, g0);
134
135 EXPECT_TRUE(validate(p));
136 }
137
138 TEST_P(validation_test, src0_null_reg)
139 {
140 brw_MOV(p, g0, null);
141
142 EXPECT_FALSE(validate(p));
143 }
144
145 TEST_P(validation_test, src1_null_reg)
146 {
147 brw_ADD(p, g0, g0, null);
148
149 EXPECT_FALSE(validate(p));
150 }
151
152 TEST_P(validation_test, math_src0_null_reg)
153 {
154 if (devinfo.gen >= 6) {
155 gen6_math(p, g0, BRW_MATH_FUNCTION_SIN, null, null);
156 } else {
157 gen4_math(p, g0, BRW_MATH_FUNCTION_SIN, 0, null, BRW_MATH_PRECISION_FULL);
158 }
159
160 EXPECT_FALSE(validate(p));
161 }
162
163 TEST_P(validation_test, math_src1_null_reg)
164 {
165 if (devinfo.gen >= 6) {
166 gen6_math(p, g0, BRW_MATH_FUNCTION_POW, g0, null);
167 EXPECT_FALSE(validate(p));
168 } else {
169 /* Math instructions on Gen4/5 are actually SEND messages with payloads.
170 * src1 is an immediate message descriptor set by gen4_math.
171 */
172 }
173 }
174
175 TEST_P(validation_test, opcode46)
176 {
177 /* opcode 46 is "push" on Gen 4 and 5
178 * "fork" on Gen 6
179 * reserved on Gen 7
180 * "goto" on Gen8+
181 */
182 brw_next_insn(p, brw_opcode_decode(&devinfo, 46));
183
184 if (devinfo.gen == 7) {
185 EXPECT_FALSE(validate(p));
186 } else {
187 EXPECT_TRUE(validate(p));
188 }
189 }
190
191 /* When the Execution Data Type is wider than the destination data type, the
192 * destination must [...] specify a HorzStride equal to the ratio in sizes of
193 * the two data types.
194 */
195 TEST_P(validation_test, dest_stride_must_be_equal_to_the_ratio_of_exec_size_to_dest_size)
196 {
197 brw_ADD(p, g0, g0, g0);
198 brw_inst_set_dst_file_type(&devinfo, last_inst, BRW_GENERAL_REGISTER_FILE, BRW_REGISTER_TYPE_W);
199 brw_inst_set_src0_file_type(&devinfo, last_inst, BRW_GENERAL_REGISTER_FILE, BRW_REGISTER_TYPE_D);
200 brw_inst_set_src1_file_type(&devinfo, last_inst, BRW_GENERAL_REGISTER_FILE, BRW_REGISTER_TYPE_D);
201
202 EXPECT_FALSE(validate(p));
203
204 clear_instructions(p);
205
206 brw_ADD(p, g0, g0, g0);
207 brw_inst_set_dst_file_type(&devinfo, last_inst, BRW_GENERAL_REGISTER_FILE, BRW_REGISTER_TYPE_W);
208 brw_inst_set_dst_hstride(&devinfo, last_inst, BRW_HORIZONTAL_STRIDE_2);
209 brw_inst_set_src0_file_type(&devinfo, last_inst, BRW_GENERAL_REGISTER_FILE, BRW_REGISTER_TYPE_D);
210 brw_inst_set_src1_file_type(&devinfo, last_inst, BRW_GENERAL_REGISTER_FILE, BRW_REGISTER_TYPE_D);
211
212 EXPECT_TRUE(validate(p));
213 }
214
215 /* When the Execution Data Type is wider than the destination data type, the
216 * destination must be aligned as required by the wider execution data type
217 * [...]
218 */
219 TEST_P(validation_test, dst_subreg_must_be_aligned_to_exec_type_size)
220 {
221 brw_ADD(p, g0, g0, g0);
222 brw_inst_set_dst_da1_subreg_nr(&devinfo, last_inst, 2);
223 brw_inst_set_dst_hstride(&devinfo, last_inst, BRW_HORIZONTAL_STRIDE_2);
224 brw_inst_set_dst_file_type(&devinfo, last_inst, BRW_GENERAL_REGISTER_FILE, BRW_REGISTER_TYPE_W);
225 brw_inst_set_src0_file_type(&devinfo, last_inst, BRW_GENERAL_REGISTER_FILE, BRW_REGISTER_TYPE_D);
226 brw_inst_set_src1_file_type(&devinfo, last_inst, BRW_GENERAL_REGISTER_FILE, BRW_REGISTER_TYPE_D);
227
228 EXPECT_FALSE(validate(p));
229
230 clear_instructions(p);
231
232 brw_ADD(p, g0, g0, g0);
233 brw_inst_set_exec_size(&devinfo, last_inst, BRW_EXECUTE_4);
234 brw_inst_set_dst_da1_subreg_nr(&devinfo, last_inst, 8);
235 brw_inst_set_dst_hstride(&devinfo, last_inst, BRW_HORIZONTAL_STRIDE_2);
236 brw_inst_set_dst_file_type(&devinfo, last_inst, BRW_GENERAL_REGISTER_FILE, BRW_REGISTER_TYPE_W);
237 brw_inst_set_src0_file_type(&devinfo, last_inst, BRW_GENERAL_REGISTER_FILE, BRW_REGISTER_TYPE_D);
238 brw_inst_set_src0_vstride(&devinfo, last_inst, BRW_VERTICAL_STRIDE_4);
239 brw_inst_set_src0_width(&devinfo, last_inst, BRW_WIDTH_4);
240 brw_inst_set_src0_hstride(&devinfo, last_inst, BRW_HORIZONTAL_STRIDE_1);
241 brw_inst_set_src1_file_type(&devinfo, last_inst, BRW_GENERAL_REGISTER_FILE, BRW_REGISTER_TYPE_D);
242 brw_inst_set_src1_vstride(&devinfo, last_inst, BRW_VERTICAL_STRIDE_4);
243 brw_inst_set_src1_width(&devinfo, last_inst, BRW_WIDTH_4);
244 brw_inst_set_src1_hstride(&devinfo, last_inst, BRW_HORIZONTAL_STRIDE_1);
245
246 EXPECT_TRUE(validate(p));
247 }
248
249 /* ExecSize must be greater than or equal to Width. */
250 TEST_P(validation_test, exec_size_less_than_width)
251 {
252 brw_ADD(p, g0, g0, g0);
253 brw_inst_set_src0_width(&devinfo, last_inst, BRW_WIDTH_16);
254
255 EXPECT_FALSE(validate(p));
256
257 clear_instructions(p);
258
259 brw_ADD(p, g0, g0, g0);
260 brw_inst_set_src1_width(&devinfo, last_inst, BRW_WIDTH_16);
261
262 EXPECT_FALSE(validate(p));
263 }
264
265 /* If ExecSize = Width and HorzStride ≠ 0,
266 * VertStride must be set to Width * HorzStride.
267 */
268 TEST_P(validation_test, vertical_stride_is_width_by_horizontal_stride)
269 {
270 brw_ADD(p, g0, g0, g0);
271 brw_inst_set_src0_vstride(&devinfo, last_inst, BRW_VERTICAL_STRIDE_4);
272
273 EXPECT_FALSE(validate(p));
274
275 clear_instructions(p);
276
277 brw_ADD(p, g0, g0, g0);
278 brw_inst_set_src1_vstride(&devinfo, last_inst, BRW_VERTICAL_STRIDE_4);
279
280 EXPECT_FALSE(validate(p));
281 }
282
283 /* If Width = 1, HorzStride must be 0 regardless of the values
284 * of ExecSize and VertStride.
285 */
286 TEST_P(validation_test, horizontal_stride_must_be_0_if_width_is_1)
287 {
288 brw_ADD(p, g0, g0, g0);
289 brw_inst_set_src0_vstride(&devinfo, last_inst, BRW_VERTICAL_STRIDE_0);
290 brw_inst_set_src0_width(&devinfo, last_inst, BRW_WIDTH_1);
291 brw_inst_set_src0_hstride(&devinfo, last_inst, BRW_HORIZONTAL_STRIDE_1);
292
293 EXPECT_FALSE(validate(p));
294
295 clear_instructions(p);
296
297 brw_ADD(p, g0, g0, g0);
298 brw_inst_set_src1_vstride(&devinfo, last_inst, BRW_VERTICAL_STRIDE_0);
299 brw_inst_set_src1_width(&devinfo, last_inst, BRW_WIDTH_1);
300 brw_inst_set_src1_hstride(&devinfo, last_inst, BRW_HORIZONTAL_STRIDE_1);
301
302 EXPECT_FALSE(validate(p));
303 }
304
305 /* If ExecSize = Width = 1, both VertStride and HorzStride must be 0. */
306 TEST_P(validation_test, scalar_region_must_be_0_1_0)
307 {
308 struct brw_reg g0_0 = brw_vec1_grf(0, 0);
309
310 brw_ADD(p, g0, g0, g0_0);
311 brw_inst_set_exec_size(&devinfo, last_inst, BRW_EXECUTE_1);
312 brw_inst_set_src0_vstride(&devinfo, last_inst, BRW_VERTICAL_STRIDE_1);
313 brw_inst_set_src0_width(&devinfo, last_inst, BRW_WIDTH_1);
314 brw_inst_set_src0_hstride(&devinfo, last_inst, BRW_HORIZONTAL_STRIDE_0);
315
316 EXPECT_FALSE(validate(p));
317
318 clear_instructions(p);
319
320 brw_ADD(p, g0, g0_0, g0);
321 brw_inst_set_exec_size(&devinfo, last_inst, BRW_EXECUTE_1);
322 brw_inst_set_src1_vstride(&devinfo, last_inst, BRW_VERTICAL_STRIDE_1);
323 brw_inst_set_src1_width(&devinfo, last_inst, BRW_WIDTH_1);
324 brw_inst_set_src1_hstride(&devinfo, last_inst, BRW_HORIZONTAL_STRIDE_0);
325
326 EXPECT_FALSE(validate(p));
327 }
328
329 /* If VertStride = HorzStride = 0, Width must be 1 regardless of the value
330 * of ExecSize.
331 */
332 TEST_P(validation_test, zero_stride_implies_0_1_0)
333 {
334 brw_ADD(p, g0, g0, g0);
335 brw_inst_set_src0_vstride(&devinfo, last_inst, BRW_VERTICAL_STRIDE_0);
336 brw_inst_set_src0_width(&devinfo, last_inst, BRW_WIDTH_2);
337 brw_inst_set_src0_hstride(&devinfo, last_inst, BRW_HORIZONTAL_STRIDE_0);
338
339 EXPECT_FALSE(validate(p));
340
341 clear_instructions(p);
342
343 brw_ADD(p, g0, g0, g0);
344 brw_inst_set_src1_vstride(&devinfo, last_inst, BRW_VERTICAL_STRIDE_0);
345 brw_inst_set_src1_width(&devinfo, last_inst, BRW_WIDTH_2);
346 brw_inst_set_src1_hstride(&devinfo, last_inst, BRW_HORIZONTAL_STRIDE_0);
347
348 EXPECT_FALSE(validate(p));
349 }
350
351 /* Dst.HorzStride must not be 0. */
352 TEST_P(validation_test, dst_horizontal_stride_0)
353 {
354 brw_ADD(p, g0, g0, g0);
355 brw_inst_set_dst_hstride(&devinfo, last_inst, BRW_HORIZONTAL_STRIDE_0);
356
357 EXPECT_FALSE(validate(p));
358
359 clear_instructions(p);
360
361 /* Align16 does not exist on Gen11+ */
362 if (devinfo.gen >= 11)
363 return;
364
365 brw_set_default_access_mode(p, BRW_ALIGN_16);
366
367 brw_ADD(p, g0, g0, g0);
368 brw_inst_set_dst_hstride(&devinfo, last_inst, BRW_HORIZONTAL_STRIDE_0);
369
370 EXPECT_FALSE(validate(p));
371 }
372
373 /* VertStride must be used to cross BRW_GENERAL_REGISTER_FILE register boundaries. This rule implies
374 * that elements within a 'Width' cannot cross BRW_GENERAL_REGISTER_FILE boundaries.
375 */
376 TEST_P(validation_test, must_not_cross_grf_boundary_in_a_width)
377 {
378 brw_ADD(p, g0, g0, g0);
379 brw_inst_set_src0_da1_subreg_nr(&devinfo, last_inst, 4);
380
381 EXPECT_FALSE(validate(p));
382
383 clear_instructions(p);
384
385 brw_ADD(p, g0, g0, g0);
386 brw_inst_set_src1_da1_subreg_nr(&devinfo, last_inst, 4);
387
388 EXPECT_FALSE(validate(p));
389
390 clear_instructions(p);
391
392 brw_ADD(p, g0, g0, g0);
393 brw_inst_set_src0_vstride(&devinfo, last_inst, BRW_VERTICAL_STRIDE_4);
394 brw_inst_set_src0_width(&devinfo, last_inst, BRW_WIDTH_4);
395 brw_inst_set_src0_hstride(&devinfo, last_inst, BRW_HORIZONTAL_STRIDE_2);
396
397 EXPECT_FALSE(validate(p));
398
399 clear_instructions(p);
400
401 brw_ADD(p, g0, g0, g0);
402 brw_inst_set_src1_vstride(&devinfo, last_inst, BRW_VERTICAL_STRIDE_4);
403 brw_inst_set_src1_width(&devinfo, last_inst, BRW_WIDTH_4);
404 brw_inst_set_src1_hstride(&devinfo, last_inst, BRW_HORIZONTAL_STRIDE_2);
405
406 EXPECT_FALSE(validate(p));
407 }
408
409 /* Destination Horizontal must be 1 in Align16 */
410 TEST_P(validation_test, dst_hstride_on_align16_must_be_1)
411 {
412 /* Align16 does not exist on Gen11+ */
413 if (devinfo.gen >= 11)
414 return;
415
416 brw_set_default_access_mode(p, BRW_ALIGN_16);
417
418 brw_ADD(p, g0, g0, g0);
419 brw_inst_set_dst_hstride(&devinfo, last_inst, BRW_HORIZONTAL_STRIDE_2);
420
421 EXPECT_FALSE(validate(p));
422
423 clear_instructions(p);
424
425 brw_ADD(p, g0, g0, g0);
426 brw_inst_set_dst_hstride(&devinfo, last_inst, BRW_HORIZONTAL_STRIDE_1);
427
428 EXPECT_TRUE(validate(p));
429 }
430
431 /* VertStride must be 0 or 4 in Align16 */
432 TEST_P(validation_test, vstride_on_align16_must_be_0_or_4)
433 {
434 /* Align16 does not exist on Gen11+ */
435 if (devinfo.gen >= 11)
436 return;
437
438 const struct {
439 enum brw_vertical_stride vstride;
440 bool expected_result;
441 } vstride[] = {
442 { BRW_VERTICAL_STRIDE_0, true },
443 { BRW_VERTICAL_STRIDE_1, false },
444 { BRW_VERTICAL_STRIDE_2, devinfo.is_haswell || devinfo.gen >= 8 },
445 { BRW_VERTICAL_STRIDE_4, true },
446 { BRW_VERTICAL_STRIDE_8, false },
447 { BRW_VERTICAL_STRIDE_16, false },
448 { BRW_VERTICAL_STRIDE_32, false },
449 { BRW_VERTICAL_STRIDE_ONE_DIMENSIONAL, false },
450 };
451
452 brw_set_default_access_mode(p, BRW_ALIGN_16);
453
454 for (unsigned i = 0; i < sizeof(vstride) / sizeof(vstride[0]); i++) {
455 brw_ADD(p, g0, g0, g0);
456 brw_inst_set_src0_vstride(&devinfo, last_inst, vstride[i].vstride);
457
458 EXPECT_EQ(vstride[i].expected_result, validate(p));
459
460 clear_instructions(p);
461 }
462
463 for (unsigned i = 0; i < sizeof(vstride) / sizeof(vstride[0]); i++) {
464 brw_ADD(p, g0, g0, g0);
465 brw_inst_set_src1_vstride(&devinfo, last_inst, vstride[i].vstride);
466
467 EXPECT_EQ(vstride[i].expected_result, validate(p));
468
469 clear_instructions(p);
470 }
471 }
472
473 /* In Direct Addressing mode, a source cannot span more than 2 adjacent BRW_GENERAL_REGISTER_FILE
474 * registers.
475 */
476 TEST_P(validation_test, source_cannot_span_more_than_2_registers)
477 {
478 brw_ADD(p, g0, g0, g0);
479 brw_inst_set_exec_size(&devinfo, last_inst, BRW_EXECUTE_32);
480 brw_inst_set_dst_file_type(&devinfo, last_inst, BRW_GENERAL_REGISTER_FILE, BRW_REGISTER_TYPE_W);
481 brw_inst_set_src0_file_type(&devinfo, last_inst, BRW_GENERAL_REGISTER_FILE, BRW_REGISTER_TYPE_W);
482 brw_inst_set_src1_file_type(&devinfo, last_inst, BRW_GENERAL_REGISTER_FILE, BRW_REGISTER_TYPE_W);
483 brw_inst_set_src1_vstride(&devinfo, last_inst, BRW_VERTICAL_STRIDE_16);
484 brw_inst_set_src1_width(&devinfo, last_inst, BRW_WIDTH_8);
485 brw_inst_set_src1_hstride(&devinfo, last_inst, BRW_HORIZONTAL_STRIDE_2);
486
487 EXPECT_FALSE(validate(p));
488
489 clear_instructions(p);
490
491 brw_ADD(p, g0, g0, g0);
492 brw_inst_set_exec_size(&devinfo, last_inst, BRW_EXECUTE_16);
493 brw_inst_set_dst_file_type(&devinfo, last_inst, BRW_GENERAL_REGISTER_FILE, BRW_REGISTER_TYPE_W);
494 brw_inst_set_src0_file_type(&devinfo, last_inst, BRW_GENERAL_REGISTER_FILE, BRW_REGISTER_TYPE_W);
495 brw_inst_set_src1_file_type(&devinfo, last_inst, BRW_GENERAL_REGISTER_FILE, BRW_REGISTER_TYPE_W);
496 brw_inst_set_src1_vstride(&devinfo, last_inst, BRW_VERTICAL_STRIDE_16);
497 brw_inst_set_src1_width(&devinfo, last_inst, BRW_WIDTH_8);
498 brw_inst_set_src1_hstride(&devinfo, last_inst, BRW_HORIZONTAL_STRIDE_2);
499 brw_inst_set_src1_da1_subreg_nr(&devinfo, last_inst, 2);
500
501 EXPECT_TRUE(validate(p));
502
503 clear_instructions(p);
504
505 brw_ADD(p, g0, g0, g0);
506 brw_inst_set_exec_size(&devinfo, last_inst, BRW_EXECUTE_16);
507
508 EXPECT_TRUE(validate(p));
509 }
510
511 /* A destination cannot span more than 2 adjacent BRW_GENERAL_REGISTER_FILE registers. */
512 TEST_P(validation_test, destination_cannot_span_more_than_2_registers)
513 {
514 brw_ADD(p, g0, g0, g0);
515 brw_inst_set_exec_size(&devinfo, last_inst, BRW_EXECUTE_32);
516 brw_inst_set_dst_hstride(&devinfo, last_inst, BRW_HORIZONTAL_STRIDE_2);
517 brw_inst_set_dst_file_type(&devinfo, last_inst, BRW_GENERAL_REGISTER_FILE, BRW_REGISTER_TYPE_W);
518 brw_inst_set_src0_file_type(&devinfo, last_inst, BRW_GENERAL_REGISTER_FILE, BRW_REGISTER_TYPE_W);
519 brw_inst_set_src1_file_type(&devinfo, last_inst, BRW_GENERAL_REGISTER_FILE, BRW_REGISTER_TYPE_W);
520
521 EXPECT_FALSE(validate(p));
522
523 clear_instructions(p);
524
525 brw_ADD(p, g0, g0, g0);
526 brw_inst_set_exec_size(&devinfo, last_inst, BRW_EXECUTE_8);
527 brw_inst_set_dst_da1_subreg_nr(&devinfo, last_inst, 6);
528 brw_inst_set_dst_hstride(&devinfo, last_inst, BRW_HORIZONTAL_STRIDE_4);
529 brw_inst_set_dst_file_type(&devinfo, last_inst, BRW_GENERAL_REGISTER_FILE, BRW_REGISTER_TYPE_W);
530 brw_inst_set_src0_file_type(&devinfo, last_inst, BRW_GENERAL_REGISTER_FILE, BRW_REGISTER_TYPE_W);
531 brw_inst_set_src0_vstride(&devinfo, last_inst, BRW_VERTICAL_STRIDE_16);
532 brw_inst_set_src0_width(&devinfo, last_inst, BRW_WIDTH_4);
533 brw_inst_set_src0_hstride(&devinfo, last_inst, BRW_HORIZONTAL_STRIDE_1);
534 brw_inst_set_src1_file_type(&devinfo, last_inst, BRW_GENERAL_REGISTER_FILE, BRW_REGISTER_TYPE_W);
535 brw_inst_set_src1_vstride(&devinfo, last_inst, BRW_VERTICAL_STRIDE_16);
536 brw_inst_set_src1_width(&devinfo, last_inst, BRW_WIDTH_4);
537 brw_inst_set_src1_hstride(&devinfo, last_inst, BRW_HORIZONTAL_STRIDE_1);
538
539 EXPECT_TRUE(validate(p));
540 }
541
542 TEST_P(validation_test, src_region_spans_two_regs_dst_region_spans_one)
543 {
544 /* Writes to dest are to the lower OWord */
545 brw_ADD(p, g0, g0, g0);
546 brw_inst_set_dst_file_type(&devinfo, last_inst, BRW_GENERAL_REGISTER_FILE, BRW_REGISTER_TYPE_W);
547 brw_inst_set_src0_file_type(&devinfo, last_inst, BRW_GENERAL_REGISTER_FILE, BRW_REGISTER_TYPE_W);
548 brw_inst_set_src1_file_type(&devinfo, last_inst, BRW_GENERAL_REGISTER_FILE, BRW_REGISTER_TYPE_W);
549 brw_inst_set_src1_vstride(&devinfo, last_inst, BRW_VERTICAL_STRIDE_16);
550 brw_inst_set_src1_width(&devinfo, last_inst, BRW_WIDTH_4);
551 brw_inst_set_src1_hstride(&devinfo, last_inst, BRW_HORIZONTAL_STRIDE_2);
552
553 EXPECT_TRUE(validate(p));
554
555 clear_instructions(p);
556
557 /* Writes to dest are to the upper OWord */
558 brw_ADD(p, g0, g0, g0);
559 brw_inst_set_dst_da1_subreg_nr(&devinfo, last_inst, 16);
560 brw_inst_set_dst_file_type(&devinfo, last_inst, BRW_GENERAL_REGISTER_FILE, BRW_REGISTER_TYPE_W);
561 brw_inst_set_src0_file_type(&devinfo, last_inst, BRW_GENERAL_REGISTER_FILE, BRW_REGISTER_TYPE_W);
562 brw_inst_set_src1_file_type(&devinfo, last_inst, BRW_GENERAL_REGISTER_FILE, BRW_REGISTER_TYPE_W);
563 brw_inst_set_src1_vstride(&devinfo, last_inst, BRW_VERTICAL_STRIDE_16);
564 brw_inst_set_src1_width(&devinfo, last_inst, BRW_WIDTH_4);
565 brw_inst_set_src1_hstride(&devinfo, last_inst, BRW_HORIZONTAL_STRIDE_2);
566
567 EXPECT_TRUE(validate(p));
568
569 clear_instructions(p);
570
571 /* Writes to dest are evenly split between OWords */
572 brw_ADD(p, g0, g0, g0);
573 brw_inst_set_exec_size(&devinfo, last_inst, BRW_EXECUTE_16);
574 brw_inst_set_dst_file_type(&devinfo, last_inst, BRW_GENERAL_REGISTER_FILE, BRW_REGISTER_TYPE_W);
575 brw_inst_set_src0_file_type(&devinfo, last_inst, BRW_GENERAL_REGISTER_FILE, BRW_REGISTER_TYPE_W);
576 brw_inst_set_src1_file_type(&devinfo, last_inst, BRW_GENERAL_REGISTER_FILE, BRW_REGISTER_TYPE_W);
577 brw_inst_set_src1_vstride(&devinfo, last_inst, BRW_VERTICAL_STRIDE_16);
578 brw_inst_set_src1_width(&devinfo, last_inst, BRW_WIDTH_8);
579 brw_inst_set_src1_hstride(&devinfo, last_inst, BRW_HORIZONTAL_STRIDE_2);
580
581 EXPECT_TRUE(validate(p));
582
583 clear_instructions(p);
584
585 /* Writes to dest are uneven between OWords */
586 brw_ADD(p, g0, g0, g0);
587 brw_inst_set_exec_size(&devinfo, last_inst, BRW_EXECUTE_4);
588 brw_inst_set_dst_da1_subreg_nr(&devinfo, last_inst, 10);
589 brw_inst_set_dst_file_type(&devinfo, last_inst, BRW_GENERAL_REGISTER_FILE, BRW_REGISTER_TYPE_W);
590 brw_inst_set_src0_file_type(&devinfo, last_inst, BRW_GENERAL_REGISTER_FILE, BRW_REGISTER_TYPE_W);
591 brw_inst_set_src0_vstride(&devinfo, last_inst, BRW_VERTICAL_STRIDE_4);
592 brw_inst_set_src0_width(&devinfo, last_inst, BRW_WIDTH_4);
593 brw_inst_set_src0_hstride(&devinfo, last_inst, BRW_HORIZONTAL_STRIDE_1);
594 brw_inst_set_src1_file_type(&devinfo, last_inst, BRW_GENERAL_REGISTER_FILE, BRW_REGISTER_TYPE_W);
595 brw_inst_set_src1_vstride(&devinfo, last_inst, BRW_VERTICAL_STRIDE_16);
596 brw_inst_set_src1_width(&devinfo, last_inst, BRW_WIDTH_2);
597 brw_inst_set_src1_hstride(&devinfo, last_inst, BRW_HORIZONTAL_STRIDE_1);
598
599 if (devinfo.gen >= 9) {
600 EXPECT_TRUE(validate(p));
601 } else {
602 EXPECT_FALSE(validate(p));
603 }
604 }
605
606 TEST_P(validation_test, dst_elements_must_be_evenly_split_between_registers)
607 {
608 brw_ADD(p, g0, g0, g0);
609 brw_inst_set_dst_da1_subreg_nr(&devinfo, last_inst, 4);
610
611 if (devinfo.gen >= 9) {
612 EXPECT_TRUE(validate(p));
613 } else {
614 EXPECT_FALSE(validate(p));
615 }
616
617 clear_instructions(p);
618
619 brw_ADD(p, g0, g0, g0);
620 brw_inst_set_exec_size(&devinfo, last_inst, BRW_EXECUTE_16);
621
622 EXPECT_TRUE(validate(p));
623
624 clear_instructions(p);
625
626 if (devinfo.gen >= 6) {
627 gen6_math(p, g0, BRW_MATH_FUNCTION_SIN, g0, null);
628
629 EXPECT_TRUE(validate(p));
630
631 clear_instructions(p);
632
633 gen6_math(p, g0, BRW_MATH_FUNCTION_SIN, g0, null);
634 brw_inst_set_dst_da1_subreg_nr(&devinfo, last_inst, 4);
635
636 EXPECT_FALSE(validate(p));
637 }
638 }
639
640 TEST_P(validation_test, two_src_two_dst_source_offsets_must_be_same)
641 {
642 brw_ADD(p, g0, g0, g0);
643 brw_inst_set_exec_size(&devinfo, last_inst, BRW_EXECUTE_4);
644 brw_inst_set_dst_hstride(&devinfo, last_inst, BRW_HORIZONTAL_STRIDE_4);
645 brw_inst_set_src0_da1_subreg_nr(&devinfo, last_inst, 16);
646 brw_inst_set_src0_vstride(&devinfo, last_inst, BRW_VERTICAL_STRIDE_2);
647 brw_inst_set_src0_width(&devinfo, last_inst, BRW_WIDTH_1);
648 brw_inst_set_src0_hstride(&devinfo, last_inst, BRW_HORIZONTAL_STRIDE_0);
649 brw_inst_set_src1_vstride(&devinfo, last_inst, BRW_VERTICAL_STRIDE_4);
650 brw_inst_set_src1_width(&devinfo, last_inst, BRW_WIDTH_4);
651 brw_inst_set_src1_hstride(&devinfo, last_inst, BRW_HORIZONTAL_STRIDE_1);
652
653 if (devinfo.gen <= 7) {
654 EXPECT_FALSE(validate(p));
655 } else {
656 EXPECT_TRUE(validate(p));
657 }
658
659 clear_instructions(p);
660
661 brw_ADD(p, g0, g0, g0);
662 brw_inst_set_exec_size(&devinfo, last_inst, BRW_EXECUTE_4);
663 brw_inst_set_dst_hstride(&devinfo, last_inst, BRW_HORIZONTAL_STRIDE_4);
664 brw_inst_set_src0_vstride(&devinfo, last_inst, BRW_VERTICAL_STRIDE_4);
665 brw_inst_set_src0_width(&devinfo, last_inst, BRW_WIDTH_1);
666 brw_inst_set_src0_hstride(&devinfo, last_inst, BRW_HORIZONTAL_STRIDE_0);
667 brw_inst_set_src1_vstride(&devinfo, last_inst, BRW_VERTICAL_STRIDE_8);
668 brw_inst_set_src1_width(&devinfo, last_inst, BRW_WIDTH_2);
669 brw_inst_set_src1_hstride(&devinfo, last_inst, BRW_HORIZONTAL_STRIDE_1);
670
671 EXPECT_TRUE(validate(p));
672 }
673
674 TEST_P(validation_test, two_src_two_dst_each_dst_must_be_derived_from_one_src)
675 {
676 brw_MOV(p, g0, g0);
677 brw_inst_set_exec_size(&devinfo, last_inst, BRW_EXECUTE_16);
678 brw_inst_set_dst_file_type(&devinfo, last_inst, BRW_GENERAL_REGISTER_FILE, BRW_REGISTER_TYPE_W);
679 brw_inst_set_dst_hstride(&devinfo, last_inst, BRW_HORIZONTAL_STRIDE_2);
680 brw_inst_set_src0_file_type(&devinfo, last_inst, BRW_GENERAL_REGISTER_FILE, BRW_REGISTER_TYPE_W);
681 brw_inst_set_src0_da1_subreg_nr(&devinfo, last_inst, 8);
682 brw_inst_set_src0_vstride(&devinfo, last_inst, BRW_VERTICAL_STRIDE_4);
683 brw_inst_set_src0_width(&devinfo, last_inst, BRW_WIDTH_4);
684 brw_inst_set_src0_hstride(&devinfo, last_inst, BRW_HORIZONTAL_STRIDE_1);
685
686 if (devinfo.gen <= 7) {
687 EXPECT_FALSE(validate(p));
688 } else {
689 EXPECT_TRUE(validate(p));
690 }
691
692 clear_instructions(p);
693
694 brw_MOV(p, g0, g0);
695 brw_inst_set_dst_da1_subreg_nr(&devinfo, last_inst, 16);
696 brw_inst_set_src0_da1_subreg_nr(&devinfo, last_inst, 8);
697 brw_inst_set_src0_vstride(&devinfo, last_inst, BRW_VERTICAL_STRIDE_2);
698 brw_inst_set_src0_width(&devinfo, last_inst, BRW_WIDTH_2);
699 brw_inst_set_src0_hstride(&devinfo, last_inst, BRW_HORIZONTAL_STRIDE_1);
700
701 if (devinfo.gen <= 7) {
702 EXPECT_FALSE(validate(p));
703 } else {
704 EXPECT_TRUE(validate(p));
705 }
706 }
707
708 TEST_P(validation_test, one_src_two_dst)
709 {
710 struct brw_reg g0_0 = brw_vec1_grf(0, 0);
711
712 brw_ADD(p, g0, g0_0, g0_0);
713 brw_inst_set_exec_size(&devinfo, last_inst, BRW_EXECUTE_16);
714
715 EXPECT_TRUE(validate(p));
716
717 clear_instructions(p);
718
719 brw_ADD(p, g0, g0, g0);
720 brw_inst_set_exec_size(&devinfo, last_inst, BRW_EXECUTE_16);
721 brw_inst_set_dst_file_type(&devinfo, last_inst, BRW_GENERAL_REGISTER_FILE, BRW_REGISTER_TYPE_D);
722 brw_inst_set_src0_file_type(&devinfo, last_inst, BRW_GENERAL_REGISTER_FILE, BRW_REGISTER_TYPE_W);
723 brw_inst_set_src1_file_type(&devinfo, last_inst, BRW_GENERAL_REGISTER_FILE, BRW_REGISTER_TYPE_W);
724
725 EXPECT_TRUE(validate(p));
726
727 clear_instructions(p);
728
729 brw_ADD(p, g0, g0, g0);
730 brw_inst_set_exec_size(&devinfo, last_inst, BRW_EXECUTE_16);
731 brw_inst_set_dst_hstride(&devinfo, last_inst, BRW_HORIZONTAL_STRIDE_2);
732 brw_inst_set_dst_file_type(&devinfo, last_inst, BRW_GENERAL_REGISTER_FILE, BRW_REGISTER_TYPE_W);
733 brw_inst_set_src0_file_type(&devinfo, last_inst, BRW_GENERAL_REGISTER_FILE, BRW_REGISTER_TYPE_W);
734 brw_inst_set_src1_file_type(&devinfo, last_inst, BRW_GENERAL_REGISTER_FILE, BRW_REGISTER_TYPE_W);
735 brw_inst_set_src1_vstride(&devinfo, last_inst, BRW_VERTICAL_STRIDE_0);
736 brw_inst_set_src1_width(&devinfo, last_inst, BRW_WIDTH_1);
737 brw_inst_set_src1_hstride(&devinfo, last_inst, BRW_HORIZONTAL_STRIDE_0);
738
739 if (devinfo.gen >= 8) {
740 EXPECT_TRUE(validate(p));
741 } else {
742 EXPECT_FALSE(validate(p));
743 }
744
745 clear_instructions(p);
746
747 brw_ADD(p, g0, g0, g0);
748 brw_inst_set_exec_size(&devinfo, last_inst, BRW_EXECUTE_16);
749 brw_inst_set_dst_hstride(&devinfo, last_inst, BRW_HORIZONTAL_STRIDE_2);
750 brw_inst_set_dst_file_type(&devinfo, last_inst, BRW_GENERAL_REGISTER_FILE, BRW_REGISTER_TYPE_W);
751 brw_inst_set_src0_file_type(&devinfo, last_inst, BRW_GENERAL_REGISTER_FILE, BRW_REGISTER_TYPE_W);
752 brw_inst_set_src0_vstride(&devinfo, last_inst, BRW_VERTICAL_STRIDE_0);
753 brw_inst_set_src0_width(&devinfo, last_inst, BRW_WIDTH_1);
754 brw_inst_set_src0_hstride(&devinfo, last_inst, BRW_HORIZONTAL_STRIDE_0);
755 brw_inst_set_src1_file_type(&devinfo, last_inst, BRW_GENERAL_REGISTER_FILE, BRW_REGISTER_TYPE_W);
756
757 if (devinfo.gen >= 8) {
758 EXPECT_TRUE(validate(p));
759 } else {
760 EXPECT_FALSE(validate(p));
761 }
762 }
763
764 TEST_P(validation_test, packed_byte_destination)
765 {
766 static const struct {
767 enum brw_reg_type dst_type;
768 enum brw_reg_type src_type;
769 bool neg, abs, sat;
770 bool expected_result;
771 } move[] = {
772 { BRW_REGISTER_TYPE_UB, BRW_REGISTER_TYPE_UB, 0, 0, 0, true },
773 { BRW_REGISTER_TYPE_B , BRW_REGISTER_TYPE_B , 0, 0, 0, true },
774 { BRW_REGISTER_TYPE_UB, BRW_REGISTER_TYPE_B , 0, 0, 0, true },
775 { BRW_REGISTER_TYPE_B , BRW_REGISTER_TYPE_UB, 0, 0, 0, true },
776
777 { BRW_REGISTER_TYPE_UB, BRW_REGISTER_TYPE_UB, 1, 0, 0, false },
778 { BRW_REGISTER_TYPE_B , BRW_REGISTER_TYPE_B , 1, 0, 0, false },
779 { BRW_REGISTER_TYPE_UB, BRW_REGISTER_TYPE_B , 1, 0, 0, false },
780 { BRW_REGISTER_TYPE_B , BRW_REGISTER_TYPE_UB, 1, 0, 0, false },
781
782 { BRW_REGISTER_TYPE_UB, BRW_REGISTER_TYPE_UB, 0, 1, 0, false },
783 { BRW_REGISTER_TYPE_B , BRW_REGISTER_TYPE_B , 0, 1, 0, false },
784 { BRW_REGISTER_TYPE_UB, BRW_REGISTER_TYPE_B , 0, 1, 0, false },
785 { BRW_REGISTER_TYPE_B , BRW_REGISTER_TYPE_UB, 0, 1, 0, false },
786
787 { BRW_REGISTER_TYPE_UB, BRW_REGISTER_TYPE_UB, 0, 0, 1, false },
788 { BRW_REGISTER_TYPE_B , BRW_REGISTER_TYPE_B , 0, 0, 1, false },
789 { BRW_REGISTER_TYPE_UB, BRW_REGISTER_TYPE_B , 0, 0, 1, false },
790 { BRW_REGISTER_TYPE_B , BRW_REGISTER_TYPE_UB, 0, 0, 1, false },
791
792 { BRW_REGISTER_TYPE_UB, BRW_REGISTER_TYPE_UW, 0, 0, 0, false },
793 { BRW_REGISTER_TYPE_B , BRW_REGISTER_TYPE_W , 0, 0, 0, false },
794 { BRW_REGISTER_TYPE_UB, BRW_REGISTER_TYPE_UD, 0, 0, 0, false },
795 { BRW_REGISTER_TYPE_B , BRW_REGISTER_TYPE_D , 0, 0, 0, false },
796 };
797
798 for (unsigned i = 0; i < sizeof(move) / sizeof(move[0]); i++) {
799 brw_MOV(p, retype(g0, move[i].dst_type), retype(g0, move[i].src_type));
800 brw_inst_set_src0_negate(&devinfo, last_inst, move[i].neg);
801 brw_inst_set_src0_abs(&devinfo, last_inst, move[i].abs);
802 brw_inst_set_saturate(&devinfo, last_inst, move[i].sat);
803
804 EXPECT_EQ(move[i].expected_result, validate(p));
805
806 clear_instructions(p);
807 }
808
809 brw_SEL(p, retype(g0, BRW_REGISTER_TYPE_UB),
810 retype(g0, BRW_REGISTER_TYPE_UB),
811 retype(g0, BRW_REGISTER_TYPE_UB));
812 brw_inst_set_pred_control(&devinfo, last_inst, BRW_PREDICATE_NORMAL);
813
814 EXPECT_FALSE(validate(p));
815
816 clear_instructions(p);
817
818 brw_SEL(p, retype(g0, BRW_REGISTER_TYPE_B),
819 retype(g0, BRW_REGISTER_TYPE_B),
820 retype(g0, BRW_REGISTER_TYPE_B));
821 brw_inst_set_pred_control(&devinfo, last_inst, BRW_PREDICATE_NORMAL);
822
823 EXPECT_FALSE(validate(p));
824 }
825
826 TEST_P(validation_test, byte_destination_relaxed_alignment)
827 {
828 brw_SEL(p, retype(g0, BRW_REGISTER_TYPE_B),
829 retype(g0, BRW_REGISTER_TYPE_W),
830 retype(g0, BRW_REGISTER_TYPE_W));
831 brw_inst_set_pred_control(&devinfo, last_inst, BRW_PREDICATE_NORMAL);
832 brw_inst_set_dst_hstride(&devinfo, last_inst, BRW_HORIZONTAL_STRIDE_2);
833
834 EXPECT_TRUE(validate(p));
835
836 clear_instructions(p);
837
838 brw_SEL(p, retype(g0, BRW_REGISTER_TYPE_B),
839 retype(g0, BRW_REGISTER_TYPE_W),
840 retype(g0, BRW_REGISTER_TYPE_W));
841 brw_inst_set_pred_control(&devinfo, last_inst, BRW_PREDICATE_NORMAL);
842 brw_inst_set_dst_hstride(&devinfo, last_inst, BRW_HORIZONTAL_STRIDE_2);
843 brw_inst_set_dst_da1_subreg_nr(&devinfo, last_inst, 1);
844
845 if (devinfo.gen > 4 || devinfo.is_g4x) {
846 EXPECT_TRUE(validate(p));
847 } else {
848 EXPECT_FALSE(validate(p));
849 }
850 }
851
852 TEST_P(validation_test, byte_64bit_conversion)
853 {
854 static const struct {
855 enum brw_reg_type dst_type;
856 enum brw_reg_type src_type;
857 unsigned dst_stride;
858 bool expected_result;
859 } inst[] = {
860 #define INST(dst_type, src_type, dst_stride, expected_result) \
861 { \
862 BRW_REGISTER_TYPE_##dst_type, \
863 BRW_REGISTER_TYPE_##src_type, \
864 BRW_HORIZONTAL_STRIDE_##dst_stride, \
865 expected_result, \
866 }
867
868 INST(B, Q, 1, false),
869 INST(B, UQ, 1, false),
870 INST(B, DF, 1, false),
871 INST(UB, Q, 1, false),
872 INST(UB, UQ, 1, false),
873 INST(UB, DF, 1, false),
874
875 INST(B, Q, 2, false),
876 INST(B, UQ, 2, false),
877 INST(B , DF, 2, false),
878 INST(UB, Q, 2, false),
879 INST(UB, UQ, 2, false),
880 INST(UB, DF, 2, false),
881
882 INST(B, Q, 4, false),
883 INST(B, UQ, 4, false),
884 INST(B, DF, 4, false),
885 INST(UB, Q, 4, false),
886 INST(UB, UQ, 4, false),
887 INST(UB, DF, 4, false),
888
889 #undef INST
890 };
891
892 if (devinfo.gen < 8)
893 return;
894
895 for (unsigned i = 0; i < sizeof(inst) / sizeof(inst[0]); i++) {
896 if (!devinfo.has_64bit_types && type_sz(inst[i].src_type) == 8)
897 continue;
898
899 brw_MOV(p, retype(g0, inst[i].dst_type), retype(g0, inst[i].src_type));
900 brw_inst_set_dst_hstride(&devinfo, last_inst, inst[i].dst_stride);
901 EXPECT_EQ(inst[i].expected_result, validate(p));
902
903 clear_instructions(p);
904 }
905 }
906
907 TEST_P(validation_test, half_float_conversion)
908 {
909 static const struct {
910 enum brw_reg_type dst_type;
911 enum brw_reg_type src_type;
912 unsigned dst_stride;
913 unsigned dst_subnr;
914 bool expected_result_bdw;
915 bool expected_result_chv_gen9;
916 } inst[] = {
917 #define INST_C(dst_type, src_type, dst_stride, dst_subnr, expected_result) \
918 { \
919 BRW_REGISTER_TYPE_##dst_type, \
920 BRW_REGISTER_TYPE_##src_type, \
921 BRW_HORIZONTAL_STRIDE_##dst_stride, \
922 dst_subnr, \
923 expected_result, \
924 expected_result, \
925 }
926 #define INST_S(dst_type, src_type, dst_stride, dst_subnr, \
927 expected_result_bdw, expected_result_chv_gen9) \
928 { \
929 BRW_REGISTER_TYPE_##dst_type, \
930 BRW_REGISTER_TYPE_##src_type, \
931 BRW_HORIZONTAL_STRIDE_##dst_stride, \
932 dst_subnr, \
933 expected_result_bdw, \
934 expected_result_chv_gen9, \
935 }
936
937 /* MOV to half-float destination */
938 INST_C(HF, B, 1, 0, false),
939 INST_C(HF, W, 1, 0, false),
940 INST_C(HF, HF, 1, 0, true),
941 INST_C(HF, HF, 1, 2, true),
942 INST_C(HF, D, 1, 0, false),
943 INST_S(HF, F, 1, 0, false, true),
944 INST_C(HF, Q, 1, 0, false),
945 INST_C(HF, B, 2, 0, true),
946 INST_C(HF, B, 2, 2, false),
947 INST_C(HF, W, 2, 0, true),
948 INST_C(HF, W, 2, 2, false),
949 INST_C(HF, HF, 2, 0, true),
950 INST_C(HF, HF, 2, 2, true),
951 INST_C(HF, D, 2, 0, true),
952 INST_C(HF, D, 2, 2, false),
953 INST_C(HF, F, 2, 0, true),
954 INST_S(HF, F, 2, 2, false, true),
955 INST_C(HF, Q, 2, 0, false),
956 INST_C(HF, DF, 2, 0, false),
957 INST_C(HF, B, 4, 0, false),
958 INST_C(HF, W, 4, 0, false),
959 INST_C(HF, HF, 4, 0, true),
960 INST_C(HF, HF, 4, 2, true),
961 INST_C(HF, D, 4, 0, false),
962 INST_C(HF, F, 4, 0, false),
963 INST_C(HF, Q, 4, 0, false),
964 INST_C(HF, DF, 4, 0, false),
965
966 /* MOV from half-float source */
967 INST_C( B, HF, 1, 0, false),
968 INST_C( W, HF, 1, 0, false),
969 INST_C( D, HF, 1, 0, true),
970 INST_C( D, HF, 1, 4, true),
971 INST_C( F, HF, 1, 0, true),
972 INST_C( F, HF, 1, 4, true),
973 INST_C( Q, HF, 1, 0, false),
974 INST_C(DF, HF, 1, 0, false),
975 INST_C( B, HF, 2, 0, false),
976 INST_C( W, HF, 2, 0, true),
977 INST_C( W, HF, 2, 2, false),
978 INST_C( D, HF, 2, 0, false),
979 INST_C( F, HF, 2, 0, true),
980 INST_C( B, HF, 4, 0, true),
981 INST_C( B, HF, 4, 1, false),
982 INST_C( W, HF, 4, 0, false),
983
984 #undef INST_C
985 #undef INST_S
986 };
987
988 if (devinfo.gen < 8)
989 return;
990
991 for (unsigned i = 0; i < sizeof(inst) / sizeof(inst[0]); i++) {
992 if (!devinfo.has_64bit_types &&
993 (type_sz(inst[i].src_type) == 8 || type_sz(inst[i].dst_type) == 8)) {
994 continue;
995 }
996
997 brw_MOV(p, retype(g0, inst[i].dst_type), retype(g0, inst[i].src_type));
998
999 brw_inst_set_exec_size(&devinfo, last_inst, BRW_EXECUTE_4);
1000
1001 brw_inst_set_dst_hstride(&devinfo, last_inst, inst[i].dst_stride);
1002 brw_inst_set_dst_da1_subreg_nr(&devinfo, last_inst, inst[i].dst_subnr);
1003
1004 if (inst[i].src_type == BRW_REGISTER_TYPE_B) {
1005 brw_inst_set_src0_vstride(&devinfo, last_inst, BRW_VERTICAL_STRIDE_4);
1006 brw_inst_set_src0_width(&devinfo, last_inst, BRW_WIDTH_2);
1007 brw_inst_set_src0_hstride(&devinfo, last_inst, BRW_HORIZONTAL_STRIDE_2);
1008 } else {
1009 brw_inst_set_src0_vstride(&devinfo, last_inst, BRW_VERTICAL_STRIDE_4);
1010 brw_inst_set_src0_width(&devinfo, last_inst, BRW_WIDTH_4);
1011 brw_inst_set_src0_hstride(&devinfo, last_inst, BRW_HORIZONTAL_STRIDE_1);
1012 }
1013
1014 if (devinfo.is_cherryview || devinfo.gen >= 9)
1015 EXPECT_EQ(inst[i].expected_result_chv_gen9, validate(p));
1016 else
1017 EXPECT_EQ(inst[i].expected_result_bdw, validate(p));
1018
1019 clear_instructions(p);
1020 }
1021 }
1022
1023 TEST_P(validation_test, mixed_float_source_indirect_addressing)
1024 {
1025 static const struct {
1026 enum brw_reg_type dst_type;
1027 enum brw_reg_type src0_type;
1028 enum brw_reg_type src1_type;
1029 unsigned dst_stride;
1030 bool dst_indirect;
1031 bool src0_indirect;
1032 bool expected_result;
1033 } inst[] = {
1034 #define INST(dst_type, src0_type, src1_type, \
1035 dst_stride, dst_indirect, src0_indirect, expected_result) \
1036 { \
1037 BRW_REGISTER_TYPE_##dst_type, \
1038 BRW_REGISTER_TYPE_##src0_type, \
1039 BRW_REGISTER_TYPE_##src1_type, \
1040 BRW_HORIZONTAL_STRIDE_##dst_stride, \
1041 dst_indirect, \
1042 src0_indirect, \
1043 expected_result, \
1044 }
1045
1046 /* Source and dest are mixed float: indirect src addressing not allowed */
1047 INST(HF, F, F, 2, false, false, true),
1048 INST(HF, F, F, 2, true, false, true),
1049 INST(HF, F, F, 2, false, true, false),
1050 INST(HF, F, F, 2, true, true, false),
1051 INST( F, HF, F, 1, false, false, true),
1052 INST( F, HF, F, 1, true, false, true),
1053 INST( F, HF, F, 1, false, true, false),
1054 INST( F, HF, F, 1, true, true, false),
1055
1056 INST(HF, HF, F, 2, false, false, true),
1057 INST(HF, HF, F, 2, true, false, true),
1058 INST(HF, HF, F, 2, false, true, false),
1059 INST(HF, HF, F, 2, true, true, false),
1060 INST( F, F, HF, 1, false, false, true),
1061 INST( F, F, HF, 1, true, false, true),
1062 INST( F, F, HF, 1, false, true, false),
1063 INST( F, F, HF, 1, true, true, false),
1064
1065 #undef INST
1066 };
1067
1068 if (devinfo.gen < 8)
1069 return;
1070
1071 for (unsigned i = 0; i < sizeof(inst) / sizeof(inst[0]); i++) {
1072 brw_ADD(p, retype(g0, inst[i].dst_type),
1073 retype(g0, inst[i].src0_type),
1074 retype(g0, inst[i].src1_type));
1075
1076 brw_inst_set_dst_address_mode(&devinfo, last_inst, inst[i].dst_indirect);
1077 brw_inst_set_dst_hstride(&devinfo, last_inst, inst[i].dst_stride);
1078 brw_inst_set_src0_address_mode(&devinfo, last_inst, inst[i].src0_indirect);
1079
1080 EXPECT_EQ(inst[i].expected_result, validate(p));
1081
1082 clear_instructions(p);
1083 }
1084 }
1085
1086 TEST_P(validation_test, mixed_float_align1_simd16)
1087 {
1088 static const struct {
1089 unsigned exec_size;
1090 enum brw_reg_type dst_type;
1091 enum brw_reg_type src0_type;
1092 enum brw_reg_type src1_type;
1093 unsigned dst_stride;
1094 bool expected_result;
1095 } inst[] = {
1096 #define INST(exec_size, dst_type, src0_type, src1_type, \
1097 dst_stride, expected_result) \
1098 { \
1099 BRW_EXECUTE_##exec_size, \
1100 BRW_REGISTER_TYPE_##dst_type, \
1101 BRW_REGISTER_TYPE_##src0_type, \
1102 BRW_REGISTER_TYPE_##src1_type, \
1103 BRW_HORIZONTAL_STRIDE_##dst_stride, \
1104 expected_result, \
1105 }
1106
1107 /* No SIMD16 in mixed mode when destination is packed f16 */
1108 INST( 8, HF, F, HF, 2, true),
1109 INST(16, HF, HF, F, 2, true),
1110 INST(16, HF, HF, F, 1, false),
1111 INST(16, HF, F, HF, 1, false),
1112
1113 /* No SIMD16 in mixed mode when destination is f32 */
1114 INST( 8, F, HF, F, 1, true),
1115 INST( 8, F, F, HF, 1, true),
1116 INST(16, F, HF, F, 1, false),
1117 INST(16, F, F, HF, 1, false),
1118
1119 #undef INST
1120 };
1121
1122 if (devinfo.gen < 8)
1123 return;
1124
1125 for (unsigned i = 0; i < sizeof(inst) / sizeof(inst[0]); i++) {
1126 brw_ADD(p, retype(g0, inst[i].dst_type),
1127 retype(g0, inst[i].src0_type),
1128 retype(g0, inst[i].src1_type));
1129
1130 brw_inst_set_exec_size(&devinfo, last_inst, inst[i].exec_size);
1131
1132 brw_inst_set_dst_hstride(&devinfo, last_inst, inst[i].dst_stride);
1133
1134 EXPECT_EQ(inst[i].expected_result, validate(p));
1135
1136 clear_instructions(p);
1137 }
1138 }
1139
1140 TEST_P(validation_test, mixed_float_align1_packed_fp16_dst_acc_read_offset_0)
1141 {
1142 static const struct {
1143 enum brw_reg_type dst_type;
1144 enum brw_reg_type src0_type;
1145 enum brw_reg_type src1_type;
1146 unsigned dst_stride;
1147 bool read_acc;
1148 unsigned subnr;
1149 bool expected_result_bdw;
1150 bool expected_result_chv_skl;
1151 } inst[] = {
1152 #define INST(dst_type, src0_type, src1_type, dst_stride, read_acc, subnr, \
1153 expected_result_bdw, expected_result_chv_skl) \
1154 { \
1155 BRW_REGISTER_TYPE_##dst_type, \
1156 BRW_REGISTER_TYPE_##src0_type, \
1157 BRW_REGISTER_TYPE_##src1_type, \
1158 BRW_HORIZONTAL_STRIDE_##dst_stride, \
1159 read_acc, \
1160 subnr, \
1161 expected_result_bdw, \
1162 expected_result_chv_skl, \
1163 }
1164
1165 /* Destination is not packed */
1166 INST(HF, HF, F, 2, true, 0, true, true),
1167 INST(HF, HF, F, 2, true, 2, true, true),
1168 INST(HF, HF, F, 2, true, 4, true, true),
1169 INST(HF, HF, F, 2, true, 8, true, true),
1170 INST(HF, HF, F, 2, true, 16, true, true),
1171
1172 /* Destination is packed, we don't read acc */
1173 INST(HF, HF, F, 1, false, 0, false, true),
1174 INST(HF, HF, F, 1, false, 2, false, true),
1175 INST(HF, HF, F, 1, false, 4, false, true),
1176 INST(HF, HF, F, 1, false, 8, false, true),
1177 INST(HF, HF, F, 1, false, 16, false, true),
1178
1179 /* Destination is packed, we read acc */
1180 INST(HF, HF, F, 1, true, 0, false, false),
1181 INST(HF, HF, F, 1, true, 2, false, false),
1182 INST(HF, HF, F, 1, true, 4, false, false),
1183 INST(HF, HF, F, 1, true, 8, false, false),
1184 INST(HF, HF, F, 1, true, 16, false, false),
1185
1186 #undef INST
1187 };
1188
1189 if (devinfo.gen < 8)
1190 return;
1191
1192 for (unsigned i = 0; i < sizeof(inst) / sizeof(inst[0]); i++) {
1193 brw_ADD(p, retype(g0, inst[i].dst_type),
1194 retype(inst[i].read_acc ? acc0 : g0, inst[i].src0_type),
1195 retype(g0, inst[i].src1_type));
1196
1197 brw_inst_set_dst_hstride(&devinfo, last_inst, inst[i].dst_stride);
1198
1199 brw_inst_set_src0_da1_subreg_nr(&devinfo, last_inst, inst[i].subnr);
1200
1201 if (devinfo.is_cherryview || devinfo.gen >= 9)
1202 EXPECT_EQ(inst[i].expected_result_chv_skl, validate(p));
1203 else
1204 EXPECT_EQ(inst[i].expected_result_bdw, validate(p));
1205
1206 clear_instructions(p);
1207 }
1208 }
1209
1210 TEST_P(validation_test, mixed_float_fp16_dest_with_acc)
1211 {
1212 static const struct {
1213 unsigned exec_size;
1214 unsigned opcode;
1215 enum brw_reg_type dst_type;
1216 enum brw_reg_type src0_type;
1217 enum brw_reg_type src1_type;
1218 unsigned dst_stride;
1219 bool read_acc;
1220 bool expected_result_bdw;
1221 bool expected_result_chv_skl;
1222 } inst[] = {
1223 #define INST(exec_size, opcode, dst_type, src0_type, src1_type, \
1224 dst_stride, read_acc,expected_result_bdw, \
1225 expected_result_chv_skl) \
1226 { \
1227 BRW_EXECUTE_##exec_size, \
1228 BRW_OPCODE_##opcode, \
1229 BRW_REGISTER_TYPE_##dst_type, \
1230 BRW_REGISTER_TYPE_##src0_type, \
1231 BRW_REGISTER_TYPE_##src1_type, \
1232 BRW_HORIZONTAL_STRIDE_##dst_stride, \
1233 read_acc, \
1234 expected_result_bdw, \
1235 expected_result_chv_skl, \
1236 }
1237
1238 /* Packed fp16 dest with implicit acc needs hstride=2 */
1239 INST(8, MAC, HF, HF, F, 1, false, false, false),
1240 INST(8, MAC, HF, HF, F, 2, false, true, true),
1241 INST(8, MAC, HF, F, HF, 1, false, false, false),
1242 INST(8, MAC, HF, F, HF, 2, false, true, true),
1243
1244 /* Packed fp16 dest with explicit acc needs hstride=2 */
1245 INST(8, ADD, HF, HF, F, 1, true, false, false),
1246 INST(8, ADD, HF, HF, F, 2, true, true, true),
1247 INST(8, ADD, HF, F, HF, 1, true, false, false),
1248 INST(8, ADD, HF, F, HF, 2, true, true, true),
1249
1250 /* If destination is not fp16, restriction doesn't apply */
1251 INST(8, MAC, F, HF, F, 1, false, true, true),
1252 INST(8, MAC, F, HF, F, 2, false, true, true),
1253
1254 /* If there is no implicit/explicit acc, restriction doesn't apply */
1255 INST(8, ADD, HF, HF, F, 1, false, false, true),
1256 INST(8, ADD, HF, HF, F, 2, false, true, true),
1257 INST(8, ADD, HF, F, HF, 1, false, false, true),
1258 INST(8, ADD, HF, F, HF, 2, false, true, true),
1259 INST(8, ADD, F, HF, F, 1, false, true, true),
1260 INST(8, ADD, F, HF, F, 2, false, true, true),
1261
1262 #undef INST
1263 };
1264
1265 if (devinfo.gen < 8)
1266 return;
1267
1268 for (unsigned i = 0; i < sizeof(inst) / sizeof(inst[0]); i++) {
1269 if (inst[i].opcode == BRW_OPCODE_MAC) {
1270 brw_MAC(p, retype(g0, inst[i].dst_type),
1271 retype(g0, inst[i].src0_type),
1272 retype(g0, inst[i].src1_type));
1273 } else {
1274 assert(inst[i].opcode == BRW_OPCODE_ADD);
1275 brw_ADD(p, retype(g0, inst[i].dst_type),
1276 retype(inst[i].read_acc ? acc0: g0, inst[i].src0_type),
1277 retype(g0, inst[i].src1_type));
1278 }
1279
1280 brw_inst_set_exec_size(&devinfo, last_inst, inst[i].exec_size);
1281
1282 brw_inst_set_dst_hstride(&devinfo, last_inst, inst[i].dst_stride);
1283
1284 if (devinfo.is_cherryview || devinfo.gen >= 9)
1285 EXPECT_EQ(inst[i].expected_result_chv_skl, validate(p));
1286 else
1287 EXPECT_EQ(inst[i].expected_result_bdw, validate(p));
1288
1289 clear_instructions(p);
1290 }
1291 }
1292
1293 TEST_P(validation_test, mixed_float_align1_math_strided_fp16_inputs)
1294 {
1295 static const struct {
1296 enum brw_reg_type dst_type;
1297 enum brw_reg_type src0_type;
1298 enum brw_reg_type src1_type;
1299 unsigned dst_stride;
1300 unsigned src0_stride;
1301 unsigned src1_stride;
1302 bool expected_result;
1303 } inst[] = {
1304 #define INST(dst_type, src0_type, src1_type, \
1305 dst_stride, src0_stride, src1_stride, expected_result) \
1306 { \
1307 BRW_REGISTER_TYPE_##dst_type, \
1308 BRW_REGISTER_TYPE_##src0_type, \
1309 BRW_REGISTER_TYPE_##src1_type, \
1310 BRW_HORIZONTAL_STRIDE_##dst_stride, \
1311 BRW_HORIZONTAL_STRIDE_##src0_stride, \
1312 BRW_HORIZONTAL_STRIDE_##src1_stride, \
1313 expected_result, \
1314 }
1315
1316 INST(HF, HF, F, 2, 2, 1, true),
1317 INST(HF, F, HF, 2, 1, 2, true),
1318 INST(HF, F, HF, 1, 1, 2, true),
1319 INST(HF, F, HF, 2, 1, 1, false),
1320 INST(HF, HF, F, 2, 1, 1, false),
1321 INST(HF, HF, F, 1, 1, 1, false),
1322 INST(HF, HF, F, 2, 1, 1, false),
1323 INST( F, HF, F, 1, 1, 1, false),
1324 INST( F, F, HF, 1, 1, 2, true),
1325 INST( F, HF, HF, 1, 2, 1, false),
1326 INST( F, HF, HF, 1, 2, 2, true),
1327
1328 #undef INST
1329 };
1330
1331 /* No half-float math in gen8 */
1332 if (devinfo.gen < 9)
1333 return;
1334
1335 for (unsigned i = 0; i < sizeof(inst) / sizeof(inst[0]); i++) {
1336 gen6_math(p, retype(g0, inst[i].dst_type),
1337 BRW_MATH_FUNCTION_POW,
1338 retype(g0, inst[i].src0_type),
1339 retype(g0, inst[i].src1_type));
1340
1341 brw_inst_set_dst_hstride(&devinfo, last_inst, inst[i].dst_stride);
1342
1343 brw_inst_set_src0_vstride(&devinfo, last_inst, BRW_VERTICAL_STRIDE_4);
1344 brw_inst_set_src0_width(&devinfo, last_inst, BRW_WIDTH_4);
1345 brw_inst_set_src0_hstride(&devinfo, last_inst, inst[i].src0_stride);
1346
1347 brw_inst_set_src1_vstride(&devinfo, last_inst, BRW_VERTICAL_STRIDE_4);
1348 brw_inst_set_src1_width(&devinfo, last_inst, BRW_WIDTH_4);
1349 brw_inst_set_src1_hstride(&devinfo, last_inst, inst[i].src1_stride);
1350
1351 EXPECT_EQ(inst[i].expected_result, validate(p));
1352
1353 clear_instructions(p);
1354 }
1355 }
1356
1357 TEST_P(validation_test, mixed_float_align1_packed_fp16_dst)
1358 {
1359 static const struct {
1360 unsigned exec_size;
1361 enum brw_reg_type dst_type;
1362 enum brw_reg_type src0_type;
1363 enum brw_reg_type src1_type;
1364 unsigned dst_stride;
1365 unsigned dst_subnr;
1366 bool expected_result_bdw;
1367 bool expected_result_chv_skl;
1368 } inst[] = {
1369 #define INST(exec_size, dst_type, src0_type, src1_type, dst_stride, dst_subnr, \
1370 expected_result_bdw, expected_result_chv_skl) \
1371 { \
1372 BRW_EXECUTE_##exec_size, \
1373 BRW_REGISTER_TYPE_##dst_type, \
1374 BRW_REGISTER_TYPE_##src0_type, \
1375 BRW_REGISTER_TYPE_##src1_type, \
1376 BRW_HORIZONTAL_STRIDE_##dst_stride, \
1377 dst_subnr, \
1378 expected_result_bdw, \
1379 expected_result_chv_skl \
1380 }
1381
1382 /* SIMD8 packed fp16 dst won't cross oword boundaries if region is
1383 * oword-aligned
1384 */
1385 INST( 8, HF, HF, F, 1, 0, false, true),
1386 INST( 8, HF, HF, F, 1, 2, false, false),
1387 INST( 8, HF, HF, F, 1, 4, false, false),
1388 INST( 8, HF, HF, F, 1, 8, false, false),
1389 INST( 8, HF, HF, F, 1, 16, false, true),
1390
1391 /* SIMD16 packed fp16 always crosses oword boundaries */
1392 INST(16, HF, HF, F, 1, 0, false, false),
1393 INST(16, HF, HF, F, 1, 2, false, false),
1394 INST(16, HF, HF, F, 1, 4, false, false),
1395 INST(16, HF, HF, F, 1, 8, false, false),
1396 INST(16, HF, HF, F, 1, 16, false, false),
1397
1398 /* If destination is not packed (or not fp16) we can cross oword
1399 * boundaries
1400 */
1401 INST( 8, HF, HF, F, 2, 0, true, true),
1402 INST( 8, F, HF, F, 1, 0, true, true),
1403
1404 #undef INST
1405 };
1406
1407 if (devinfo.gen < 8)
1408 return;
1409
1410 for (unsigned i = 0; i < sizeof(inst) / sizeof(inst[0]); i++) {
1411 brw_ADD(p, retype(g0, inst[i].dst_type),
1412 retype(g0, inst[i].src0_type),
1413 retype(g0, inst[i].src1_type));
1414
1415 brw_inst_set_dst_hstride(&devinfo, last_inst, inst[i].dst_stride);
1416 brw_inst_set_dst_da1_subreg_nr(&devinfo, last_inst, inst[i].dst_subnr);
1417
1418 brw_inst_set_src0_vstride(&devinfo, last_inst, BRW_VERTICAL_STRIDE_4);
1419 brw_inst_set_src0_width(&devinfo, last_inst, BRW_WIDTH_4);
1420 brw_inst_set_src0_hstride(&devinfo, last_inst, BRW_HORIZONTAL_STRIDE_1);
1421
1422 brw_inst_set_src1_vstride(&devinfo, last_inst, BRW_VERTICAL_STRIDE_4);
1423 brw_inst_set_src1_width(&devinfo, last_inst, BRW_WIDTH_4);
1424 brw_inst_set_src1_hstride(&devinfo, last_inst, BRW_HORIZONTAL_STRIDE_1);
1425
1426 brw_inst_set_exec_size(&devinfo, last_inst, inst[i].exec_size);
1427
1428 if (devinfo.is_cherryview || devinfo.gen >= 9)
1429 EXPECT_EQ(inst[i].expected_result_chv_skl, validate(p));
1430 else
1431 EXPECT_EQ(inst[i].expected_result_bdw, validate(p));
1432
1433 clear_instructions(p);
1434 }
1435 }
1436
1437 TEST_P(validation_test, mixed_float_align16_packed_data)
1438 {
1439 static const struct {
1440 enum brw_reg_type dst_type;
1441 enum brw_reg_type src0_type;
1442 enum brw_reg_type src1_type;
1443 unsigned src0_vstride;
1444 unsigned src1_vstride;
1445 bool expected_result;
1446 } inst[] = {
1447 #define INST(dst_type, src0_type, src1_type, \
1448 src0_vstride, src1_vstride, expected_result) \
1449 { \
1450 BRW_REGISTER_TYPE_##dst_type, \
1451 BRW_REGISTER_TYPE_##src0_type, \
1452 BRW_REGISTER_TYPE_##src1_type, \
1453 BRW_VERTICAL_STRIDE_##src0_vstride, \
1454 BRW_VERTICAL_STRIDE_##src1_vstride, \
1455 expected_result, \
1456 }
1457
1458 /* We only test with F destination because there is a restriction
1459 * by which F->HF conversions need to be DWord aligned but Align16 also
1460 * requires that destination horizontal stride is 1.
1461 */
1462 INST(F, F, HF, 4, 4, true),
1463 INST(F, F, HF, 2, 4, false),
1464 INST(F, F, HF, 4, 2, false),
1465 INST(F, F, HF, 0, 4, false),
1466 INST(F, F, HF, 4, 0, false),
1467 INST(F, HF, F, 4, 4, true),
1468 INST(F, HF, F, 4, 2, false),
1469 INST(F, HF, F, 2, 4, false),
1470 INST(F, HF, F, 0, 4, false),
1471 INST(F, HF, F, 4, 0, false),
1472
1473 #undef INST
1474 };
1475
1476 if (devinfo.gen < 8 || devinfo.gen >= 11)
1477 return;
1478
1479 brw_set_default_access_mode(p, BRW_ALIGN_16);
1480
1481 for (unsigned i = 0; i < sizeof(inst) / sizeof(inst[0]); i++) {
1482 brw_ADD(p, retype(g0, inst[i].dst_type),
1483 retype(g0, inst[i].src0_type),
1484 retype(g0, inst[i].src1_type));
1485
1486 brw_inst_set_src0_vstride(&devinfo, last_inst, inst[i].src0_vstride);
1487 brw_inst_set_src1_vstride(&devinfo, last_inst, inst[i].src1_vstride);
1488
1489 EXPECT_EQ(inst[i].expected_result, validate(p));
1490
1491 clear_instructions(p);
1492 }
1493 }
1494
1495 TEST_P(validation_test, mixed_float_align16_no_simd16)
1496 {
1497 static const struct {
1498 unsigned exec_size;
1499 enum brw_reg_type dst_type;
1500 enum brw_reg_type src0_type;
1501 enum brw_reg_type src1_type;
1502 bool expected_result;
1503 } inst[] = {
1504 #define INST(exec_size, dst_type, src0_type, src1_type, expected_result) \
1505 { \
1506 BRW_EXECUTE_##exec_size, \
1507 BRW_REGISTER_TYPE_##dst_type, \
1508 BRW_REGISTER_TYPE_##src0_type, \
1509 BRW_REGISTER_TYPE_##src1_type, \
1510 expected_result, \
1511 }
1512
1513 /* We only test with F destination because there is a restriction
1514 * by which F->HF conversions need to be DWord aligned but Align16 also
1515 * requires that destination horizontal stride is 1.
1516 */
1517 INST( 8, F, F, HF, true),
1518 INST( 8, F, HF, F, true),
1519 INST( 8, F, F, HF, true),
1520 INST(16, F, F, HF, false),
1521 INST(16, F, HF, F, false),
1522 INST(16, F, F, HF, false),
1523
1524 #undef INST
1525 };
1526
1527 if (devinfo.gen < 8 || devinfo.gen >= 11)
1528 return;
1529
1530 brw_set_default_access_mode(p, BRW_ALIGN_16);
1531
1532 for (unsigned i = 0; i < sizeof(inst) / sizeof(inst[0]); i++) {
1533 brw_ADD(p, retype(g0, inst[i].dst_type),
1534 retype(g0, inst[i].src0_type),
1535 retype(g0, inst[i].src1_type));
1536
1537 brw_inst_set_exec_size(&devinfo, last_inst, inst[i].exec_size);
1538
1539 brw_inst_set_src0_vstride(&devinfo, last_inst, BRW_VERTICAL_STRIDE_4);
1540 brw_inst_set_src1_vstride(&devinfo, last_inst, BRW_VERTICAL_STRIDE_4);
1541
1542 EXPECT_EQ(inst[i].expected_result, validate(p));
1543
1544 clear_instructions(p);
1545 }
1546 }
1547
1548 TEST_P(validation_test, mixed_float_align16_no_acc_read)
1549 {
1550 static const struct {
1551 enum brw_reg_type dst_type;
1552 enum brw_reg_type src0_type;
1553 enum brw_reg_type src1_type;
1554 bool read_acc;
1555 bool expected_result;
1556 } inst[] = {
1557 #define INST(dst_type, src0_type, src1_type, read_acc, expected_result) \
1558 { \
1559 BRW_REGISTER_TYPE_##dst_type, \
1560 BRW_REGISTER_TYPE_##src0_type, \
1561 BRW_REGISTER_TYPE_##src1_type, \
1562 read_acc, \
1563 expected_result, \
1564 }
1565
1566 /* We only test with F destination because there is a restriction
1567 * by which F->HF conversions need to be DWord aligned but Align16 also
1568 * requires that destination horizontal stride is 1.
1569 */
1570 INST( F, F, HF, false, true),
1571 INST( F, F, HF, true, false),
1572 INST( F, HF, F, false, true),
1573 INST( F, HF, F, true, false),
1574
1575 #undef INST
1576 };
1577
1578 if (devinfo.gen < 8 || devinfo.gen >= 11)
1579 return;
1580
1581 brw_set_default_access_mode(p, BRW_ALIGN_16);
1582
1583 for (unsigned i = 0; i < sizeof(inst) / sizeof(inst[0]); i++) {
1584 brw_ADD(p, retype(g0, inst[i].dst_type),
1585 retype(inst[i].read_acc ? acc0 : g0, inst[i].src0_type),
1586 retype(g0, inst[i].src1_type));
1587
1588 brw_inst_set_src0_vstride(&devinfo, last_inst, BRW_VERTICAL_STRIDE_4);
1589 brw_inst_set_src1_vstride(&devinfo, last_inst, BRW_VERTICAL_STRIDE_4);
1590
1591 EXPECT_EQ(inst[i].expected_result, validate(p));
1592
1593 clear_instructions(p);
1594 }
1595 }
1596
1597 TEST_P(validation_test, mixed_float_align16_math_packed_format)
1598 {
1599 static const struct {
1600 enum brw_reg_type dst_type;
1601 enum brw_reg_type src0_type;
1602 enum brw_reg_type src1_type;
1603 unsigned src0_vstride;
1604 unsigned src1_vstride;
1605 bool expected_result;
1606 } inst[] = {
1607 #define INST(dst_type, src0_type, src1_type, \
1608 src0_vstride, src1_vstride, expected_result) \
1609 { \
1610 BRW_REGISTER_TYPE_##dst_type, \
1611 BRW_REGISTER_TYPE_##src0_type, \
1612 BRW_REGISTER_TYPE_##src1_type, \
1613 BRW_VERTICAL_STRIDE_##src0_vstride, \
1614 BRW_VERTICAL_STRIDE_##src1_vstride, \
1615 expected_result, \
1616 }
1617
1618 /* We only test with F destination because there is a restriction
1619 * by which F->HF conversions need to be DWord aligned but Align16 also
1620 * requires that destination horizontal stride is 1.
1621 */
1622 INST( F, HF, F, 4, 0, false),
1623 INST( F, HF, HF, 4, 4, true),
1624 INST( F, F, HF, 4, 0, false),
1625 INST( F, F, HF, 2, 4, false),
1626 INST( F, F, HF, 4, 2, false),
1627 INST( F, HF, HF, 0, 4, false),
1628
1629 #undef INST
1630 };
1631
1632 /* Align16 Math for mixed float mode is not supported in gen8 */
1633 if (devinfo.gen < 9 || devinfo.gen >= 11)
1634 return;
1635
1636 brw_set_default_access_mode(p, BRW_ALIGN_16);
1637
1638 for (unsigned i = 0; i < sizeof(inst) / sizeof(inst[0]); i++) {
1639 gen6_math(p, retype(g0, inst[i].dst_type),
1640 BRW_MATH_FUNCTION_POW,
1641 retype(g0, inst[i].src0_type),
1642 retype(g0, inst[i].src1_type));
1643
1644 brw_inst_set_src0_vstride(&devinfo, last_inst, inst[i].src0_vstride);
1645 brw_inst_set_src1_vstride(&devinfo, last_inst, inst[i].src1_vstride);
1646
1647 EXPECT_EQ(inst[i].expected_result, validate(p));
1648
1649 clear_instructions(p);
1650 }
1651 }
1652
1653 TEST_P(validation_test, vector_immediate_destination_alignment)
1654 {
1655 static const struct {
1656 enum brw_reg_type dst_type;
1657 enum brw_reg_type src_type;
1658 unsigned subnr;
1659 unsigned exec_size;
1660 bool expected_result;
1661 } move[] = {
1662 { BRW_REGISTER_TYPE_F, BRW_REGISTER_TYPE_VF, 0, BRW_EXECUTE_4, true },
1663 { BRW_REGISTER_TYPE_F, BRW_REGISTER_TYPE_VF, 16, BRW_EXECUTE_4, true },
1664 { BRW_REGISTER_TYPE_F, BRW_REGISTER_TYPE_VF, 1, BRW_EXECUTE_4, false },
1665
1666 { BRW_REGISTER_TYPE_W, BRW_REGISTER_TYPE_V, 0, BRW_EXECUTE_8, true },
1667 { BRW_REGISTER_TYPE_W, BRW_REGISTER_TYPE_V, 16, BRW_EXECUTE_8, true },
1668 { BRW_REGISTER_TYPE_W, BRW_REGISTER_TYPE_V, 1, BRW_EXECUTE_8, false },
1669
1670 { BRW_REGISTER_TYPE_W, BRW_REGISTER_TYPE_UV, 0, BRW_EXECUTE_8, true },
1671 { BRW_REGISTER_TYPE_W, BRW_REGISTER_TYPE_UV, 16, BRW_EXECUTE_8, true },
1672 { BRW_REGISTER_TYPE_W, BRW_REGISTER_TYPE_UV, 1, BRW_EXECUTE_8, false },
1673 };
1674
1675 for (unsigned i = 0; i < sizeof(move) / sizeof(move[0]); i++) {
1676 /* UV type is Gen6+ */
1677 if (devinfo.gen < 6 &&
1678 move[i].src_type == BRW_REGISTER_TYPE_UV)
1679 continue;
1680
1681 brw_MOV(p, retype(g0, move[i].dst_type), retype(zero, move[i].src_type));
1682 brw_inst_set_dst_da1_subreg_nr(&devinfo, last_inst, move[i].subnr);
1683 brw_inst_set_exec_size(&devinfo, last_inst, move[i].exec_size);
1684
1685 EXPECT_EQ(move[i].expected_result, validate(p));
1686
1687 clear_instructions(p);
1688 }
1689 }
1690
1691 TEST_P(validation_test, vector_immediate_destination_stride)
1692 {
1693 static const struct {
1694 enum brw_reg_type dst_type;
1695 enum brw_reg_type src_type;
1696 unsigned stride;
1697 bool expected_result;
1698 } move[] = {
1699 { BRW_REGISTER_TYPE_F, BRW_REGISTER_TYPE_VF, BRW_HORIZONTAL_STRIDE_1, true },
1700 { BRW_REGISTER_TYPE_F, BRW_REGISTER_TYPE_VF, BRW_HORIZONTAL_STRIDE_2, false },
1701 { BRW_REGISTER_TYPE_D, BRW_REGISTER_TYPE_VF, BRW_HORIZONTAL_STRIDE_1, true },
1702 { BRW_REGISTER_TYPE_D, BRW_REGISTER_TYPE_VF, BRW_HORIZONTAL_STRIDE_2, false },
1703 { BRW_REGISTER_TYPE_W, BRW_REGISTER_TYPE_VF, BRW_HORIZONTAL_STRIDE_2, true },
1704 { BRW_REGISTER_TYPE_B, BRW_REGISTER_TYPE_VF, BRW_HORIZONTAL_STRIDE_4, true },
1705
1706 { BRW_REGISTER_TYPE_W, BRW_REGISTER_TYPE_V, BRW_HORIZONTAL_STRIDE_1, true },
1707 { BRW_REGISTER_TYPE_W, BRW_REGISTER_TYPE_V, BRW_HORIZONTAL_STRIDE_2, false },
1708 { BRW_REGISTER_TYPE_W, BRW_REGISTER_TYPE_V, BRW_HORIZONTAL_STRIDE_4, false },
1709 { BRW_REGISTER_TYPE_B, BRW_REGISTER_TYPE_V, BRW_HORIZONTAL_STRIDE_2, true },
1710
1711 { BRW_REGISTER_TYPE_W, BRW_REGISTER_TYPE_UV, BRW_HORIZONTAL_STRIDE_1, true },
1712 { BRW_REGISTER_TYPE_W, BRW_REGISTER_TYPE_UV, BRW_HORIZONTAL_STRIDE_2, false },
1713 { BRW_REGISTER_TYPE_W, BRW_REGISTER_TYPE_UV, BRW_HORIZONTAL_STRIDE_4, false },
1714 { BRW_REGISTER_TYPE_B, BRW_REGISTER_TYPE_UV, BRW_HORIZONTAL_STRIDE_2, true },
1715 };
1716
1717 for (unsigned i = 0; i < sizeof(move) / sizeof(move[0]); i++) {
1718 /* UV type is Gen6+ */
1719 if (devinfo.gen < 6 &&
1720 move[i].src_type == BRW_REGISTER_TYPE_UV)
1721 continue;
1722
1723 brw_MOV(p, retype(g0, move[i].dst_type), retype(zero, move[i].src_type));
1724 brw_inst_set_dst_hstride(&devinfo, last_inst, move[i].stride);
1725
1726 EXPECT_EQ(move[i].expected_result, validate(p));
1727
1728 clear_instructions(p);
1729 }
1730 }
1731
1732 TEST_P(validation_test, qword_low_power_align1_regioning_restrictions)
1733 {
1734 static const struct {
1735 enum opcode opcode;
1736 unsigned exec_size;
1737
1738 enum brw_reg_type dst_type;
1739 unsigned dst_subreg;
1740 unsigned dst_stride;
1741
1742 enum brw_reg_type src_type;
1743 unsigned src_subreg;
1744 unsigned src_vstride;
1745 unsigned src_width;
1746 unsigned src_hstride;
1747
1748 bool expected_result;
1749 } inst[] = {
1750 #define INST(opcode, exec_size, dst_type, dst_subreg, dst_stride, src_type, \
1751 src_subreg, src_vstride, src_width, src_hstride, expected_result) \
1752 { \
1753 BRW_OPCODE_##opcode, \
1754 BRW_EXECUTE_##exec_size, \
1755 BRW_REGISTER_TYPE_##dst_type, \
1756 dst_subreg, \
1757 BRW_HORIZONTAL_STRIDE_##dst_stride, \
1758 BRW_REGISTER_TYPE_##src_type, \
1759 src_subreg, \
1760 BRW_VERTICAL_STRIDE_##src_vstride, \
1761 BRW_WIDTH_##src_width, \
1762 BRW_HORIZONTAL_STRIDE_##src_hstride, \
1763 expected_result, \
1764 }
1765
1766 /* Some instruction that violate no restrictions, as a control */
1767 INST(MOV, 4, DF, 0, 1, DF, 0, 4, 4, 1, true ),
1768 INST(MOV, 4, Q, 0, 1, Q, 0, 4, 4, 1, true ),
1769 INST(MOV, 4, UQ, 0, 1, UQ, 0, 4, 4, 1, true ),
1770
1771 INST(MOV, 4, DF, 0, 1, F, 0, 8, 4, 2, true ),
1772 INST(MOV, 4, Q, 0, 1, D, 0, 8, 4, 2, true ),
1773 INST(MOV, 4, UQ, 0, 1, UD, 0, 8, 4, 2, true ),
1774
1775 INST(MOV, 4, F, 0, 2, DF, 0, 4, 4, 1, true ),
1776 INST(MOV, 4, D, 0, 2, Q, 0, 4, 4, 1, true ),
1777 INST(MOV, 4, UD, 0, 2, UQ, 0, 4, 4, 1, true ),
1778
1779 INST(MUL, 8, D, 0, 2, D, 0, 8, 4, 2, true ),
1780 INST(MUL, 8, UD, 0, 2, UD, 0, 8, 4, 2, true ),
1781
1782 /* Something with subreg nrs */
1783 INST(MOV, 2, DF, 8, 1, DF, 8, 2, 2, 1, true ),
1784 INST(MOV, 2, Q, 8, 1, Q, 8, 2, 2, 1, true ),
1785 INST(MOV, 2, UQ, 8, 1, UQ, 8, 2, 2, 1, true ),
1786
1787 INST(MUL, 2, D, 4, 2, D, 4, 4, 2, 2, true ),
1788 INST(MUL, 2, UD, 4, 2, UD, 4, 4, 2, 2, true ),
1789
1790 /* The PRMs say that for CHV, BXT:
1791 *
1792 * When source or destination datatype is 64b or operation is integer
1793 * DWord multiply, regioning in Align1 must follow these rules:
1794 *
1795 * 1. Source and Destination horizontal stride must be aligned to the
1796 * same qword.
1797 */
1798 INST(MOV, 4, DF, 0, 2, DF, 0, 4, 4, 1, false),
1799 INST(MOV, 4, Q, 0, 2, Q, 0, 4, 4, 1, false),
1800 INST(MOV, 4, UQ, 0, 2, UQ, 0, 4, 4, 1, false),
1801
1802 INST(MOV, 4, DF, 0, 2, F, 0, 8, 4, 2, false),
1803 INST(MOV, 4, Q, 0, 2, D, 0, 8, 4, 2, false),
1804 INST(MOV, 4, UQ, 0, 2, UD, 0, 8, 4, 2, false),
1805
1806 INST(MOV, 4, DF, 0, 2, F, 0, 4, 4, 1, false),
1807 INST(MOV, 4, Q, 0, 2, D, 0, 4, 4, 1, false),
1808 INST(MOV, 4, UQ, 0, 2, UD, 0, 4, 4, 1, false),
1809
1810 INST(MUL, 4, D, 0, 2, D, 0, 4, 4, 1, false),
1811 INST(MUL, 4, UD, 0, 2, UD, 0, 4, 4, 1, false),
1812
1813 INST(MUL, 4, D, 0, 1, D, 0, 8, 4, 2, false),
1814 INST(MUL, 4, UD, 0, 1, UD, 0, 8, 4, 2, false),
1815
1816 /* 2. Regioning must ensure Src.Vstride = Src.Width * Src.Hstride. */
1817 INST(MOV, 4, DF, 0, 1, DF, 0, 0, 2, 1, false),
1818 INST(MOV, 4, Q, 0, 1, Q, 0, 0, 2, 1, false),
1819 INST(MOV, 4, UQ, 0, 1, UQ, 0, 0, 2, 1, false),
1820
1821 INST(MOV, 4, DF, 0, 1, F, 0, 0, 2, 2, false),
1822 INST(MOV, 4, Q, 0, 1, D, 0, 0, 2, 2, false),
1823 INST(MOV, 4, UQ, 0, 1, UD, 0, 0, 2, 2, false),
1824
1825 INST(MOV, 8, F, 0, 2, DF, 0, 0, 2, 1, false),
1826 INST(MOV, 8, D, 0, 2, Q, 0, 0, 2, 1, false),
1827 INST(MOV, 8, UD, 0, 2, UQ, 0, 0, 2, 1, false),
1828
1829 INST(MUL, 8, D, 0, 2, D, 0, 0, 4, 2, false),
1830 INST(MUL, 8, UD, 0, 2, UD, 0, 0, 4, 2, false),
1831
1832 INST(MUL, 8, D, 0, 2, D, 0, 0, 4, 2, false),
1833 INST(MUL, 8, UD, 0, 2, UD, 0, 0, 4, 2, false),
1834
1835 /* 3. Source and Destination offset must be the same, except the case
1836 * of scalar source.
1837 */
1838 INST(MOV, 2, DF, 8, 1, DF, 0, 2, 2, 1, false),
1839 INST(MOV, 2, Q, 8, 1, Q, 0, 2, 2, 1, false),
1840 INST(MOV, 2, UQ, 8, 1, UQ, 0, 2, 2, 1, false),
1841
1842 INST(MOV, 2, DF, 0, 1, DF, 8, 2, 2, 1, false),
1843 INST(MOV, 2, Q, 0, 1, Q, 8, 2, 2, 1, false),
1844 INST(MOV, 2, UQ, 0, 1, UQ, 8, 2, 2, 1, false),
1845
1846 INST(MUL, 4, D, 4, 2, D, 0, 4, 2, 2, false),
1847 INST(MUL, 4, UD, 4, 2, UD, 0, 4, 2, 2, false),
1848
1849 INST(MUL, 4, D, 0, 2, D, 4, 4, 2, 2, false),
1850 INST(MUL, 4, UD, 0, 2, UD, 4, 4, 2, 2, false),
1851
1852 INST(MOV, 2, DF, 8, 1, DF, 0, 0, 1, 0, true ),
1853 INST(MOV, 2, Q, 8, 1, Q, 0, 0, 1, 0, true ),
1854 INST(MOV, 2, UQ, 8, 1, UQ, 0, 0, 1, 0, true ),
1855
1856 INST(MOV, 2, DF, 8, 1, F, 4, 0, 1, 0, true ),
1857 INST(MOV, 2, Q, 8, 1, D, 4, 0, 1, 0, true ),
1858 INST(MOV, 2, UQ, 8, 1, UD, 4, 0, 1, 0, true ),
1859
1860 INST(MUL, 4, D, 4, 1, D, 0, 0, 1, 0, true ),
1861 INST(MUL, 4, UD, 4, 1, UD, 0, 0, 1, 0, true ),
1862
1863 INST(MUL, 4, D, 0, 1, D, 4, 0, 1, 0, true ),
1864 INST(MUL, 4, UD, 0, 1, UD, 4, 0, 1, 0, true ),
1865
1866 #undef INST
1867 };
1868
1869 /* These restrictions only apply to Gen8+ */
1870 if (devinfo.gen < 8)
1871 return;
1872
1873 /* NoDDChk/NoDDClr does not exist on Gen12+ */
1874 if (devinfo.gen >= 12)
1875 return;
1876
1877 for (unsigned i = 0; i < sizeof(inst) / sizeof(inst[0]); i++) {
1878 if (!devinfo.has_64bit_types &&
1879 (type_sz(inst[i].dst_type) == 8 || type_sz(inst[i].src_type) == 8))
1880 continue;
1881
1882 if (inst[i].opcode == BRW_OPCODE_MOV) {
1883 brw_MOV(p, retype(g0, inst[i].dst_type),
1884 retype(g0, inst[i].src_type));
1885 } else {
1886 assert(inst[i].opcode == BRW_OPCODE_MUL);
1887 brw_MUL(p, retype(g0, inst[i].dst_type),
1888 retype(g0, inst[i].src_type),
1889 retype(zero, inst[i].src_type));
1890 }
1891 brw_inst_set_exec_size(&devinfo, last_inst, inst[i].exec_size);
1892
1893 brw_inst_set_dst_da1_subreg_nr(&devinfo, last_inst, inst[i].dst_subreg);
1894 brw_inst_set_src0_da1_subreg_nr(&devinfo, last_inst, inst[i].src_subreg);
1895
1896 brw_inst_set_dst_hstride(&devinfo, last_inst, inst[i].dst_stride);
1897
1898 brw_inst_set_src0_vstride(&devinfo, last_inst, inst[i].src_vstride);
1899 brw_inst_set_src0_width(&devinfo, last_inst, inst[i].src_width);
1900 brw_inst_set_src0_hstride(&devinfo, last_inst, inst[i].src_hstride);
1901
1902 if (devinfo.is_cherryview || gen_device_info_is_9lp(&devinfo)) {
1903 EXPECT_EQ(inst[i].expected_result, validate(p));
1904 } else {
1905 EXPECT_TRUE(validate(p));
1906 }
1907
1908 clear_instructions(p);
1909 }
1910 }
1911
1912 TEST_P(validation_test, qword_low_power_no_indirect_addressing)
1913 {
1914 static const struct {
1915 enum opcode opcode;
1916 unsigned exec_size;
1917
1918 enum brw_reg_type dst_type;
1919 bool dst_is_indirect;
1920 unsigned dst_stride;
1921
1922 enum brw_reg_type src_type;
1923 bool src_is_indirect;
1924 unsigned src_vstride;
1925 unsigned src_width;
1926 unsigned src_hstride;
1927
1928 bool expected_result;
1929 } inst[] = {
1930 #define INST(opcode, exec_size, dst_type, dst_is_indirect, dst_stride, \
1931 src_type, src_is_indirect, src_vstride, src_width, src_hstride, \
1932 expected_result) \
1933 { \
1934 BRW_OPCODE_##opcode, \
1935 BRW_EXECUTE_##exec_size, \
1936 BRW_REGISTER_TYPE_##dst_type, \
1937 dst_is_indirect, \
1938 BRW_HORIZONTAL_STRIDE_##dst_stride, \
1939 BRW_REGISTER_TYPE_##src_type, \
1940 src_is_indirect, \
1941 BRW_VERTICAL_STRIDE_##src_vstride, \
1942 BRW_WIDTH_##src_width, \
1943 BRW_HORIZONTAL_STRIDE_##src_hstride, \
1944 expected_result, \
1945 }
1946
1947 /* Some instruction that violate no restrictions, as a control */
1948 INST(MOV, 4, DF, 0, 1, DF, 0, 4, 4, 1, true ),
1949 INST(MOV, 4, Q, 0, 1, Q, 0, 4, 4, 1, true ),
1950 INST(MOV, 4, UQ, 0, 1, UQ, 0, 4, 4, 1, true ),
1951
1952 INST(MUL, 8, D, 0, 2, D, 0, 8, 4, 2, true ),
1953 INST(MUL, 8, UD, 0, 2, UD, 0, 8, 4, 2, true ),
1954
1955 INST(MOV, 4, F, 1, 1, F, 0, 4, 4, 1, true ),
1956 INST(MOV, 4, F, 0, 1, F, 1, 4, 4, 1, true ),
1957 INST(MOV, 4, F, 1, 1, F, 1, 4, 4, 1, true ),
1958
1959 /* The PRMs say that for CHV, BXT:
1960 *
1961 * When source or destination datatype is 64b or operation is integer
1962 * DWord multiply, indirect addressing must not be used.
1963 */
1964 INST(MOV, 4, DF, 1, 1, DF, 0, 4, 4, 1, false),
1965 INST(MOV, 4, Q, 1, 1, Q, 0, 4, 4, 1, false),
1966 INST(MOV, 4, UQ, 1, 1, UQ, 0, 4, 4, 1, false),
1967
1968 INST(MOV, 4, DF, 0, 1, DF, 1, 4, 4, 1, false),
1969 INST(MOV, 4, Q, 0, 1, Q, 1, 4, 4, 1, false),
1970 INST(MOV, 4, UQ, 0, 1, UQ, 1, 4, 4, 1, false),
1971
1972 INST(MOV, 4, DF, 1, 1, F, 0, 8, 4, 2, false),
1973 INST(MOV, 4, Q, 1, 1, D, 0, 8, 4, 2, false),
1974 INST(MOV, 4, UQ, 1, 1, UD, 0, 8, 4, 2, false),
1975
1976 INST(MOV, 4, DF, 0, 1, F, 1, 8, 4, 2, false),
1977 INST(MOV, 4, Q, 0, 1, D, 1, 8, 4, 2, false),
1978 INST(MOV, 4, UQ, 0, 1, UD, 1, 8, 4, 2, false),
1979
1980 INST(MOV, 4, F, 1, 2, DF, 0, 4, 4, 1, false),
1981 INST(MOV, 4, D, 1, 2, Q, 0, 4, 4, 1, false),
1982 INST(MOV, 4, UD, 1, 2, UQ, 0, 4, 4, 1, false),
1983
1984 INST(MOV, 4, F, 0, 2, DF, 1, 4, 4, 1, false),
1985 INST(MOV, 4, D, 0, 2, Q, 1, 4, 4, 1, false),
1986 INST(MOV, 4, UD, 0, 2, UQ, 1, 4, 4, 1, false),
1987
1988 INST(MUL, 8, D, 1, 2, D, 0, 8, 4, 2, false),
1989 INST(MUL, 8, UD, 1, 2, UD, 0, 8, 4, 2, false),
1990
1991 INST(MUL, 8, D, 0, 2, D, 1, 8, 4, 2, false),
1992 INST(MUL, 8, UD, 0, 2, UD, 1, 8, 4, 2, false),
1993
1994 #undef INST
1995 };
1996
1997 /* These restrictions only apply to Gen8+ */
1998 if (devinfo.gen < 8)
1999 return;
2000
2001 for (unsigned i = 0; i < sizeof(inst) / sizeof(inst[0]); i++) {
2002 if (!devinfo.has_64bit_types &&
2003 (type_sz(inst[i].dst_type) == 8 || type_sz(inst[i].src_type) == 8))
2004 continue;
2005
2006 if (inst[i].opcode == BRW_OPCODE_MOV) {
2007 brw_MOV(p, retype(g0, inst[i].dst_type),
2008 retype(g0, inst[i].src_type));
2009 } else {
2010 assert(inst[i].opcode == BRW_OPCODE_MUL);
2011 brw_MUL(p, retype(g0, inst[i].dst_type),
2012 retype(g0, inst[i].src_type),
2013 retype(zero, inst[i].src_type));
2014 }
2015 brw_inst_set_exec_size(&devinfo, last_inst, inst[i].exec_size);
2016
2017 brw_inst_set_dst_address_mode(&devinfo, last_inst, inst[i].dst_is_indirect);
2018 brw_inst_set_src0_address_mode(&devinfo, last_inst, inst[i].src_is_indirect);
2019
2020 brw_inst_set_dst_hstride(&devinfo, last_inst, inst[i].dst_stride);
2021
2022 brw_inst_set_src0_vstride(&devinfo, last_inst, inst[i].src_vstride);
2023 brw_inst_set_src0_width(&devinfo, last_inst, inst[i].src_width);
2024 brw_inst_set_src0_hstride(&devinfo, last_inst, inst[i].src_hstride);
2025
2026 if (devinfo.is_cherryview || gen_device_info_is_9lp(&devinfo)) {
2027 EXPECT_EQ(inst[i].expected_result, validate(p));
2028 } else {
2029 EXPECT_TRUE(validate(p));
2030 }
2031
2032 clear_instructions(p);
2033 }
2034 }
2035
2036 TEST_P(validation_test, qword_low_power_no_64bit_arf)
2037 {
2038 static const struct {
2039 enum opcode opcode;
2040 unsigned exec_size;
2041
2042 struct brw_reg dst;
2043 enum brw_reg_type dst_type;
2044 unsigned dst_stride;
2045
2046 struct brw_reg src;
2047 enum brw_reg_type src_type;
2048 unsigned src_vstride;
2049 unsigned src_width;
2050 unsigned src_hstride;
2051
2052 bool acc_wr;
2053 bool expected_result;
2054 } inst[] = {
2055 #define INST(opcode, exec_size, dst, dst_type, dst_stride, \
2056 src, src_type, src_vstride, src_width, src_hstride, \
2057 acc_wr, expected_result) \
2058 { \
2059 BRW_OPCODE_##opcode, \
2060 BRW_EXECUTE_##exec_size, \
2061 dst, \
2062 BRW_REGISTER_TYPE_##dst_type, \
2063 BRW_HORIZONTAL_STRIDE_##dst_stride, \
2064 src, \
2065 BRW_REGISTER_TYPE_##src_type, \
2066 BRW_VERTICAL_STRIDE_##src_vstride, \
2067 BRW_WIDTH_##src_width, \
2068 BRW_HORIZONTAL_STRIDE_##src_hstride, \
2069 acc_wr, \
2070 expected_result, \
2071 }
2072
2073 /* Some instruction that violate no restrictions, as a control */
2074 INST(MOV, 4, g0, DF, 1, g0, F, 4, 2, 2, 0, true ),
2075 INST(MOV, 4, g0, F, 2, g0, DF, 4, 4, 1, 0, true ),
2076
2077 INST(MOV, 4, g0, Q, 1, g0, D, 4, 2, 2, 0, true ),
2078 INST(MOV, 4, g0, D, 2, g0, Q, 4, 4, 1, 0, true ),
2079
2080 INST(MOV, 4, g0, UQ, 1, g0, UD, 4, 2, 2, 0, true ),
2081 INST(MOV, 4, g0, UD, 2, g0, UQ, 4, 4, 1, 0, true ),
2082
2083 INST(MOV, 4, null, F, 1, g0, F, 4, 4, 1, 0, true ),
2084 INST(MOV, 4, acc0, F, 1, g0, F, 4, 4, 1, 0, true ),
2085 INST(MOV, 4, g0, F, 1, acc0, F, 4, 4, 1, 0, true ),
2086
2087 INST(MOV, 4, null, D, 1, g0, D, 4, 4, 1, 0, true ),
2088 INST(MOV, 4, acc0, D, 1, g0, D, 4, 4, 1, 0, true ),
2089 INST(MOV, 4, g0, D, 1, acc0, D, 4, 4, 1, 0, true ),
2090
2091 INST(MOV, 4, null, UD, 1, g0, UD, 4, 4, 1, 0, true ),
2092 INST(MOV, 4, acc0, UD, 1, g0, UD, 4, 4, 1, 0, true ),
2093 INST(MOV, 4, g0, UD, 1, acc0, UD, 4, 4, 1, 0, true ),
2094
2095 INST(MUL, 4, g0, D, 2, g0, D, 4, 2, 2, 0, true ),
2096 INST(MUL, 4, g0, UD, 2, g0, UD, 4, 2, 2, 0, true ),
2097
2098 /* The PRMs say that for CHV, BXT:
2099 *
2100 * ARF registers must never be used with 64b datatype or when
2101 * operation is integer DWord multiply.
2102 */
2103 INST(MOV, 4, acc0, DF, 1, g0, F, 4, 2, 2, 0, false),
2104 INST(MOV, 4, g0, DF, 1, acc0, F, 4, 2, 2, 0, false),
2105
2106 INST(MOV, 4, acc0, Q, 1, g0, D, 4, 2, 2, 0, false),
2107 INST(MOV, 4, g0, Q, 1, acc0, D, 4, 2, 2, 0, false),
2108
2109 INST(MOV, 4, acc0, UQ, 1, g0, UD, 4, 2, 2, 0, false),
2110 INST(MOV, 4, g0, UQ, 1, acc0, UD, 4, 2, 2, 0, false),
2111
2112 INST(MOV, 4, acc0, F, 2, g0, DF, 4, 4, 1, 0, false),
2113 INST(MOV, 4, g0, F, 2, acc0, DF, 4, 4, 1, 0, false),
2114
2115 INST(MOV, 4, acc0, D, 2, g0, Q, 4, 4, 1, 0, false),
2116 INST(MOV, 4, g0, D, 2, acc0, Q, 4, 4, 1, 0, false),
2117
2118 INST(MOV, 4, acc0, UD, 2, g0, UQ, 4, 4, 1, 0, false),
2119 INST(MOV, 4, g0, UD, 2, acc0, UQ, 4, 4, 1, 0, false),
2120
2121 INST(MUL, 4, acc0, D, 2, g0, D, 4, 2, 2, 0, false),
2122 INST(MUL, 4, acc0, UD, 2, g0, UD, 4, 2, 2, 0, false),
2123 /* MUL cannot have integer accumulator sources, so don't test that */
2124
2125 /* We assume that the restriction does not apply to the null register */
2126 INST(MOV, 4, null, DF, 1, g0, F, 4, 2, 2, 0, true ),
2127 INST(MOV, 4, null, Q, 1, g0, D, 4, 2, 2, 0, true ),
2128 INST(MOV, 4, null, UQ, 1, g0, UD, 4, 2, 2, 0, true ),
2129
2130 /* Check implicit accumulator write control */
2131 INST(MOV, 4, null, DF, 1, g0, F, 4, 2, 2, 1, false),
2132 INST(MUL, 4, null, DF, 1, g0, F, 4, 2, 2, 1, false),
2133
2134 #undef INST
2135 };
2136
2137 /* These restrictions only apply to Gen8+ */
2138 if (devinfo.gen < 8)
2139 return;
2140
2141 for (unsigned i = 0; i < sizeof(inst) / sizeof(inst[0]); i++) {
2142 if (!devinfo.has_64bit_types &&
2143 (type_sz(inst[i].dst_type) == 8 || type_sz(inst[i].src_type) == 8))
2144 continue;
2145
2146 if (inst[i].opcode == BRW_OPCODE_MOV) {
2147 brw_MOV(p, retype(inst[i].dst, inst[i].dst_type),
2148 retype(inst[i].src, inst[i].src_type));
2149 } else {
2150 assert(inst[i].opcode == BRW_OPCODE_MUL);
2151 brw_MUL(p, retype(inst[i].dst, inst[i].dst_type),
2152 retype(inst[i].src, inst[i].src_type),
2153 retype(zero, inst[i].src_type));
2154 brw_inst_set_opcode(&devinfo, last_inst, inst[i].opcode);
2155 }
2156 brw_inst_set_exec_size(&devinfo, last_inst, inst[i].exec_size);
2157 brw_inst_set_acc_wr_control(&devinfo, last_inst, inst[i].acc_wr);
2158
2159 brw_inst_set_dst_hstride(&devinfo, last_inst, inst[i].dst_stride);
2160
2161 brw_inst_set_src0_vstride(&devinfo, last_inst, inst[i].src_vstride);
2162 brw_inst_set_src0_width(&devinfo, last_inst, inst[i].src_width);
2163 brw_inst_set_src0_hstride(&devinfo, last_inst, inst[i].src_hstride);
2164
2165 if (devinfo.is_cherryview || gen_device_info_is_9lp(&devinfo)) {
2166 EXPECT_EQ(inst[i].expected_result, validate(p));
2167 } else {
2168 EXPECT_TRUE(validate(p));
2169 }
2170
2171 clear_instructions(p);
2172 }
2173
2174 if (!devinfo.has_64bit_types)
2175 return;
2176
2177 /* MAC implicitly reads the accumulator */
2178 brw_MAC(p, retype(g0, BRW_REGISTER_TYPE_DF),
2179 retype(stride(g0, 4, 4, 1), BRW_REGISTER_TYPE_DF),
2180 retype(stride(g0, 4, 4, 1), BRW_REGISTER_TYPE_DF));
2181 if (devinfo.is_cherryview || gen_device_info_is_9lp(&devinfo)) {
2182 EXPECT_FALSE(validate(p));
2183 } else {
2184 EXPECT_TRUE(validate(p));
2185 }
2186 }
2187
2188 TEST_P(validation_test, align16_64_bit_integer)
2189 {
2190 static const struct {
2191 enum opcode opcode;
2192 unsigned exec_size;
2193
2194 enum brw_reg_type dst_type;
2195 enum brw_reg_type src_type;
2196
2197 bool expected_result;
2198 } inst[] = {
2199 #define INST(opcode, exec_size, dst_type, src_type, expected_result) \
2200 { \
2201 BRW_OPCODE_##opcode, \
2202 BRW_EXECUTE_##exec_size, \
2203 BRW_REGISTER_TYPE_##dst_type, \
2204 BRW_REGISTER_TYPE_##src_type, \
2205 expected_result, \
2206 }
2207
2208 /* Some instruction that violate no restrictions, as a control */
2209 INST(MOV, 2, Q, D, true ),
2210 INST(MOV, 2, UQ, UD, true ),
2211 INST(MOV, 2, DF, F, true ),
2212
2213 INST(ADD, 2, Q, D, true ),
2214 INST(ADD, 2, UQ, UD, true ),
2215 INST(ADD, 2, DF, F, true ),
2216
2217 /* The PRMs say that for BDW, SKL:
2218 *
2219 * If Align16 is required for an operation with QW destination and non-QW
2220 * source datatypes, the execution size cannot exceed 2.
2221 */
2222
2223 INST(MOV, 4, Q, D, false),
2224 INST(MOV, 4, UQ, UD, false),
2225 INST(MOV, 4, DF, F, false),
2226
2227 INST(ADD, 4, Q, D, false),
2228 INST(ADD, 4, UQ, UD, false),
2229 INST(ADD, 4, DF, F, false),
2230
2231 #undef INST
2232 };
2233
2234 /* 64-bit integer types exist on Gen8+ */
2235 if (devinfo.gen < 8)
2236 return;
2237
2238 /* Align16 does not exist on Gen11+ */
2239 if (devinfo.gen >= 11)
2240 return;
2241
2242 brw_set_default_access_mode(p, BRW_ALIGN_16);
2243
2244 for (unsigned i = 0; i < sizeof(inst) / sizeof(inst[0]); i++) {
2245 if (inst[i].opcode == BRW_OPCODE_MOV) {
2246 brw_MOV(p, retype(g0, inst[i].dst_type),
2247 retype(g0, inst[i].src_type));
2248 } else {
2249 assert(inst[i].opcode == BRW_OPCODE_ADD);
2250 brw_ADD(p, retype(g0, inst[i].dst_type),
2251 retype(g0, inst[i].src_type),
2252 retype(g0, inst[i].src_type));
2253 }
2254 brw_inst_set_exec_size(&devinfo, last_inst, inst[i].exec_size);
2255
2256 EXPECT_EQ(inst[i].expected_result, validate(p));
2257
2258 clear_instructions(p);
2259 }
2260 }
2261
2262 TEST_P(validation_test, qword_low_power_no_depctrl)
2263 {
2264 static const struct {
2265 enum opcode opcode;
2266 unsigned exec_size;
2267
2268 enum brw_reg_type dst_type;
2269 unsigned dst_stride;
2270
2271 enum brw_reg_type src_type;
2272 unsigned src_vstride;
2273 unsigned src_width;
2274 unsigned src_hstride;
2275
2276 bool no_dd_check;
2277 bool no_dd_clear;
2278
2279 bool expected_result;
2280 } inst[] = {
2281 #define INST(opcode, exec_size, dst_type, dst_stride, \
2282 src_type, src_vstride, src_width, src_hstride, \
2283 no_dd_check, no_dd_clear, expected_result) \
2284 { \
2285 BRW_OPCODE_##opcode, \
2286 BRW_EXECUTE_##exec_size, \
2287 BRW_REGISTER_TYPE_##dst_type, \
2288 BRW_HORIZONTAL_STRIDE_##dst_stride, \
2289 BRW_REGISTER_TYPE_##src_type, \
2290 BRW_VERTICAL_STRIDE_##src_vstride, \
2291 BRW_WIDTH_##src_width, \
2292 BRW_HORIZONTAL_STRIDE_##src_hstride, \
2293 no_dd_check, \
2294 no_dd_clear, \
2295 expected_result, \
2296 }
2297
2298 /* Some instruction that violate no restrictions, as a control */
2299 INST(MOV, 4, DF, 1, F, 8, 4, 2, 0, 0, true ),
2300 INST(MOV, 4, Q, 1, D, 8, 4, 2, 0, 0, true ),
2301 INST(MOV, 4, UQ, 1, UD, 8, 4, 2, 0, 0, true ),
2302
2303 INST(MOV, 4, F, 2, DF, 4, 4, 1, 0, 0, true ),
2304 INST(MOV, 4, D, 2, Q, 4, 4, 1, 0, 0, true ),
2305 INST(MOV, 4, UD, 2, UQ, 4, 4, 1, 0, 0, true ),
2306
2307 INST(MUL, 8, D, 2, D, 8, 4, 2, 0, 0, true ),
2308 INST(MUL, 8, UD, 2, UD, 8, 4, 2, 0, 0, true ),
2309
2310 INST(MOV, 4, F, 1, F, 4, 4, 1, 1, 1, true ),
2311
2312 /* The PRMs say that for CHV, BXT:
2313 *
2314 * When source or destination datatype is 64b or operation is integer
2315 * DWord multiply, DepCtrl must not be used.
2316 */
2317 INST(MOV, 4, DF, 1, F, 8, 4, 2, 1, 0, false),
2318 INST(MOV, 4, Q, 1, D, 8, 4, 2, 1, 0, false),
2319 INST(MOV, 4, UQ, 1, UD, 8, 4, 2, 1, 0, false),
2320
2321 INST(MOV, 4, F, 2, DF, 4, 4, 1, 1, 0, false),
2322 INST(MOV, 4, D, 2, Q, 4, 4, 1, 1, 0, false),
2323 INST(MOV, 4, UD, 2, UQ, 4, 4, 1, 1, 0, false),
2324
2325 INST(MOV, 4, DF, 1, F, 8, 4, 2, 0, 1, false),
2326 INST(MOV, 4, Q, 1, D, 8, 4, 2, 0, 1, false),
2327 INST(MOV, 4, UQ, 1, UD, 8, 4, 2, 0, 1, false),
2328
2329 INST(MOV, 4, F, 2, DF, 4, 4, 1, 0, 1, false),
2330 INST(MOV, 4, D, 2, Q, 4, 4, 1, 0, 1, false),
2331 INST(MOV, 4, UD, 2, UQ, 4, 4, 1, 0, 1, false),
2332
2333 INST(MUL, 8, D, 2, D, 8, 4, 2, 1, 0, false),
2334 INST(MUL, 8, UD, 2, UD, 8, 4, 2, 1, 0, false),
2335
2336 INST(MUL, 8, D, 2, D, 8, 4, 2, 0, 1, false),
2337 INST(MUL, 8, UD, 2, UD, 8, 4, 2, 0, 1, false),
2338
2339 #undef INST
2340 };
2341
2342 /* These restrictions only apply to Gen8+ */
2343 if (devinfo.gen < 8)
2344 return;
2345
2346 /* NoDDChk/NoDDClr does not exist on Gen12+ */
2347 if (devinfo.gen >= 12)
2348 return;
2349
2350 for (unsigned i = 0; i < sizeof(inst) / sizeof(inst[0]); i++) {
2351 if (!devinfo.has_64bit_types &&
2352 (type_sz(inst[i].dst_type) == 8 || type_sz(inst[i].src_type) == 8))
2353 continue;
2354
2355 if (inst[i].opcode == BRW_OPCODE_MOV) {
2356 brw_MOV(p, retype(g0, inst[i].dst_type),
2357 retype(g0, inst[i].src_type));
2358 } else {
2359 assert(inst[i].opcode == BRW_OPCODE_MUL);
2360 brw_MUL(p, retype(g0, inst[i].dst_type),
2361 retype(g0, inst[i].src_type),
2362 retype(zero, inst[i].src_type));
2363 }
2364 brw_inst_set_exec_size(&devinfo, last_inst, inst[i].exec_size);
2365
2366 brw_inst_set_dst_hstride(&devinfo, last_inst, inst[i].dst_stride);
2367
2368 brw_inst_set_src0_vstride(&devinfo, last_inst, inst[i].src_vstride);
2369 brw_inst_set_src0_width(&devinfo, last_inst, inst[i].src_width);
2370 brw_inst_set_src0_hstride(&devinfo, last_inst, inst[i].src_hstride);
2371
2372 brw_inst_set_no_dd_check(&devinfo, last_inst, inst[i].no_dd_check);
2373 brw_inst_set_no_dd_clear(&devinfo, last_inst, inst[i].no_dd_clear);
2374
2375 if (devinfo.is_cherryview || gen_device_info_is_9lp(&devinfo)) {
2376 EXPECT_EQ(inst[i].expected_result, validate(p));
2377 } else {
2378 EXPECT_TRUE(validate(p));
2379 }
2380
2381 clear_instructions(p);
2382 }
2383 }
2384
2385 TEST_P(validation_test, gen11_no_byte_src_1_2)
2386 {
2387 static const struct {
2388 enum opcode opcode;
2389 unsigned access_mode;
2390
2391 enum brw_reg_type dst_type;
2392 struct {
2393 enum brw_reg_type type;
2394 unsigned vstride;
2395 unsigned width;
2396 unsigned hstride;
2397 } srcs[3];
2398
2399 int gen;
2400 bool expected_result;
2401 } inst[] = {
2402 #define INST(opcode, access_mode, dst_type, \
2403 src0_type, src0_vstride, src0_width, src0_hstride, \
2404 src1_type, src1_vstride, src1_width, src1_hstride, \
2405 src2_type, \
2406 gen, expected_result) \
2407 { \
2408 BRW_OPCODE_##opcode, \
2409 BRW_ALIGN_##access_mode, \
2410 BRW_REGISTER_TYPE_##dst_type, \
2411 { \
2412 { \
2413 BRW_REGISTER_TYPE_##src0_type, \
2414 BRW_VERTICAL_STRIDE_##src0_vstride, \
2415 BRW_WIDTH_##src0_width, \
2416 BRW_HORIZONTAL_STRIDE_##src0_hstride, \
2417 }, \
2418 { \
2419 BRW_REGISTER_TYPE_##src1_type, \
2420 BRW_VERTICAL_STRIDE_##src1_vstride, \
2421 BRW_WIDTH_##src1_width, \
2422 BRW_HORIZONTAL_STRIDE_##src1_hstride, \
2423 }, \
2424 { \
2425 BRW_REGISTER_TYPE_##src2_type, \
2426 }, \
2427 }, \
2428 gen, \
2429 expected_result, \
2430 }
2431
2432 /* Passes on < 11 */
2433 INST(MOV, 16, F, B, 2, 4, 0, UD, 0, 4, 0, D, 8, true ),
2434 INST(ADD, 16, UD, F, 0, 4, 0, UB, 0, 1, 0, D, 7, true ),
2435 INST(MAD, 16, D, B, 0, 4, 0, UB, 0, 1, 0, B, 10, true ),
2436
2437 /* Fails on 11+ */
2438 INST(MAD, 1, UB, W, 1, 1, 0, D, 0, 4, 0, B, 11, false ),
2439 INST(MAD, 1, UB, W, 1, 1, 1, UB, 1, 1, 0, W, 11, false ),
2440 INST(ADD, 1, W, W, 1, 4, 1, B, 1, 1, 0, D, 11, false ),
2441
2442 /* Passes on 11+ */
2443 INST(MOV, 1, W, B, 8, 8, 1, D, 8, 8, 1, D, 11, true ),
2444 INST(ADD, 1, UD, B, 8, 8, 1, W, 8, 8, 1, D, 11, true ),
2445 INST(MAD, 1, B, B, 0, 1, 0, D, 0, 4, 0, W, 11, true ),
2446
2447 #undef INST
2448 };
2449
2450
2451 for (unsigned i = 0; i < ARRAY_SIZE(inst); i++) {
2452 /* Skip instruction not meant for this gen. */
2453 if (devinfo.gen != inst[i].gen)
2454 continue;
2455
2456 brw_push_insn_state(p);
2457
2458 brw_set_default_exec_size(p, BRW_EXECUTE_8);
2459 brw_set_default_access_mode(p, inst[i].access_mode);
2460
2461 switch (inst[i].opcode) {
2462 case BRW_OPCODE_MOV:
2463 brw_MOV(p, retype(g0, inst[i].dst_type),
2464 retype(g0, inst[i].srcs[0].type));
2465 brw_inst_set_src0_vstride(&devinfo, last_inst, inst[i].srcs[0].vstride);
2466 brw_inst_set_src0_hstride(&devinfo, last_inst, inst[i].srcs[0].hstride);
2467 break;
2468 case BRW_OPCODE_ADD:
2469 brw_ADD(p, retype(g0, inst[i].dst_type),
2470 retype(g0, inst[i].srcs[0].type),
2471 retype(g0, inst[i].srcs[1].type));
2472 brw_inst_set_src0_vstride(&devinfo, last_inst, inst[i].srcs[0].vstride);
2473 brw_inst_set_src0_width(&devinfo, last_inst, inst[i].srcs[0].width);
2474 brw_inst_set_src0_hstride(&devinfo, last_inst, inst[i].srcs[0].hstride);
2475 brw_inst_set_src1_vstride(&devinfo, last_inst, inst[i].srcs[1].vstride);
2476 brw_inst_set_src1_width(&devinfo, last_inst, inst[i].srcs[1].width);
2477 brw_inst_set_src1_hstride(&devinfo, last_inst, inst[i].srcs[1].hstride);
2478 break;
2479 case BRW_OPCODE_MAD:
2480 brw_MAD(p, retype(g0, inst[i].dst_type),
2481 retype(g0, inst[i].srcs[0].type),
2482 retype(g0, inst[i].srcs[1].type),
2483 retype(g0, inst[i].srcs[2].type));
2484 brw_inst_set_3src_a1_src0_vstride(&devinfo, last_inst, inst[i].srcs[0].vstride);
2485 brw_inst_set_3src_a1_src0_hstride(&devinfo, last_inst, inst[i].srcs[0].hstride);
2486 brw_inst_set_3src_a1_src1_vstride(&devinfo, last_inst, inst[i].srcs[0].vstride);
2487 brw_inst_set_3src_a1_src1_hstride(&devinfo, last_inst, inst[i].srcs[0].hstride);
2488 break;
2489 default:
2490 unreachable("invalid opcode");
2491 }
2492
2493 brw_inst_set_dst_hstride(&devinfo, last_inst, BRW_HORIZONTAL_STRIDE_1);
2494
2495 brw_inst_set_src0_width(&devinfo, last_inst, inst[i].srcs[0].width);
2496 brw_inst_set_src1_width(&devinfo, last_inst, inst[i].srcs[1].width);
2497
2498 brw_pop_insn_state(p);
2499
2500 EXPECT_EQ(inst[i].expected_result, validate(p));
2501
2502 clear_instructions(p);
2503 }
2504 }