i965/disasm: Disassemble the compaction control bit.
[mesa.git] / src / mesa / drivers / dri / i965 / test_eu_compact.c
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 #include <stdlib.h>
25 #include <stdio.h>
26 #include <stdbool.h>
27 #include "glsl/ralloc.h"
28 #include "brw_context.h"
29 #include "brw_eu.h"
30
31 static bool
32 test_compact_instruction(struct brw_compile *p, struct brw_instruction src)
33 {
34 struct brw_context *brw = p->brw;
35
36 struct brw_compact_instruction dst;
37 memset(&dst, 0xd0, sizeof(dst));
38
39 if (brw_try_compact_instruction(p, &dst, &src)) {
40 struct brw_instruction uncompacted;
41
42 brw_uncompact_instruction(brw, &uncompacted, &dst);
43 if (memcmp(&uncompacted, &src, sizeof(src))) {
44 brw_debug_compact_uncompact(brw, &src, &uncompacted);
45 return false;
46 }
47 } else {
48 struct brw_compact_instruction unchanged;
49 memset(&unchanged, 0xd0, sizeof(unchanged));
50 /* It's not supposed to change dst unless it compacted. */
51 if (memcmp(&unchanged, &dst, sizeof(dst))) {
52 fprintf(stderr, "Failed to compact, but dst changed\n");
53 fprintf(stderr, " Instruction: ");
54 brw_disasm(stderr, &src, brw->gen, false);
55 return false;
56 }
57 }
58
59 return true;
60 }
61
62 /**
63 * When doing fuzz testing, pad bits won't round-trip.
64 *
65 * This sort of a superset of skip_bit, which is testing for changing bits that
66 * aren't worth testing for fuzzing. We also just want to clear bits that
67 * become meaningless once fuzzing twiddles a related bit.
68 */
69 static void
70 clear_pad_bits(struct brw_instruction *inst)
71 {
72 if (inst->header.opcode != BRW_OPCODE_SEND &&
73 inst->header.opcode != BRW_OPCODE_SENDC &&
74 inst->header.opcode != BRW_OPCODE_BREAK &&
75 inst->header.opcode != BRW_OPCODE_CONTINUE &&
76 inst->bits1.da1.src0_reg_file != BRW_IMMEDIATE_VALUE &&
77 inst->bits1.da1.src1_reg_file != BRW_IMMEDIATE_VALUE) {
78 if (inst->bits3.da1.src1_address_mode)
79 inst->bits3.ia1.pad1 = 0;
80 else
81 inst->bits3.da1.pad0 = 0;
82 }
83 }
84
85 static bool
86 skip_bit(struct brw_instruction *src, int bit)
87 {
88 /* pad bit */
89 if (bit == 7)
90 return true;
91
92 /* The compact bit -- uncompacted can't have it set. */
93 if (bit == 29)
94 return true;
95
96 /* pad bit */
97 if (bit == 47)
98 return true;
99
100 /* pad bits */
101 if (bit >= 90 && bit <= 95)
102 return true;
103
104 /* sometimes these are pad bits. */
105 if (src->header.opcode != BRW_OPCODE_SEND &&
106 src->header.opcode != BRW_OPCODE_SENDC &&
107 src->header.opcode != BRW_OPCODE_BREAK &&
108 src->header.opcode != BRW_OPCODE_CONTINUE &&
109 src->bits1.da1.src0_reg_file != BRW_IMMEDIATE_VALUE &&
110 src->bits1.da1.src1_reg_file != BRW_IMMEDIATE_VALUE &&
111 bit >= 121) {
112 return true;
113 }
114
115 return false;
116 }
117
118 static bool
119 test_fuzz_compact_instruction(struct brw_compile *p,
120 struct brw_instruction src)
121 {
122 for (int bit0 = 0; bit0 < 128; bit0++) {
123 if (skip_bit(&src, bit0))
124 continue;
125
126 for (int bit1 = 0; bit1 < 128; bit1++) {
127 struct brw_instruction instr = src;
128 uint32_t *bits = (uint32_t *)&instr;
129
130 if (skip_bit(&src, bit1))
131 continue;
132
133 bits[bit0 / 32] ^= (1 << (bit0 & 31));
134 bits[bit1 / 32] ^= (1 << (bit1 & 31));
135
136 clear_pad_bits(&instr);
137
138 if (!test_compact_instruction(p, instr)) {
139 printf(" twiddled bits for fuzzing %d, %d\n", bit0, bit1);
140 return false;
141 }
142 }
143 }
144
145 return true;
146 }
147
148 static void
149 gen_ADD_GRF_GRF_GRF(struct brw_compile *p)
150 {
151 struct brw_reg g0 = brw_vec8_grf(0, 0);
152 struct brw_reg g2 = brw_vec8_grf(2, 0);
153 struct brw_reg g4 = brw_vec8_grf(4, 0);
154
155 brw_ADD(p, g0, g2, g4);
156 }
157
158 static void
159 gen_ADD_GRF_GRF_IMM(struct brw_compile *p)
160 {
161 struct brw_reg g0 = brw_vec8_grf(0, 0);
162 struct brw_reg g2 = brw_vec8_grf(2, 0);
163
164 brw_ADD(p, g0, g2, brw_imm_f(1.0));
165 }
166
167 static void
168 gen_ADD_GRF_GRF_IMM_d(struct brw_compile *p)
169 {
170 struct brw_reg g0 = retype(brw_vec8_grf(0, 0), BRW_REGISTER_TYPE_D);
171 struct brw_reg g2 = retype(brw_vec8_grf(2, 0), BRW_REGISTER_TYPE_D);
172
173 brw_ADD(p, g0, g2, brw_imm_d(1));
174 }
175
176 static void
177 gen_MOV_GRF_GRF(struct brw_compile *p)
178 {
179 struct brw_reg g0 = brw_vec8_grf(0, 0);
180 struct brw_reg g2 = brw_vec8_grf(2, 0);
181
182 brw_MOV(p, g0, g2);
183 }
184
185 static void
186 gen_ADD_MRF_GRF_GRF(struct brw_compile *p)
187 {
188 struct brw_reg m6 = brw_vec8_reg(BRW_MESSAGE_REGISTER_FILE, 6, 0);
189 struct brw_reg g2 = brw_vec8_grf(2, 0);
190 struct brw_reg g4 = brw_vec8_grf(4, 0);
191
192 brw_ADD(p, m6, g2, g4);
193 }
194
195 static void
196 gen_ADD_vec1_GRF_GRF_GRF(struct brw_compile *p)
197 {
198 struct brw_reg g0 = brw_vec1_grf(0, 0);
199 struct brw_reg g2 = brw_vec1_grf(2, 0);
200 struct brw_reg g4 = brw_vec1_grf(4, 0);
201
202 brw_ADD(p, g0, g2, g4);
203 }
204
205 static void
206 gen_PLN_MRF_GRF_GRF(struct brw_compile *p)
207 {
208 struct brw_reg m6 = brw_vec8_reg(BRW_MESSAGE_REGISTER_FILE, 6, 0);
209 struct brw_reg interp = brw_vec1_grf(2, 0);
210 struct brw_reg g4 = brw_vec8_grf(4, 0);
211
212 brw_PLN(p, m6, interp, g4);
213 }
214
215 static void
216 gen_f0_0_MOV_GRF_GRF(struct brw_compile *p)
217 {
218 struct brw_reg g0 = brw_vec8_grf(0, 0);
219 struct brw_reg g2 = brw_vec8_grf(2, 0);
220
221 brw_push_insn_state(p);
222 brw_set_predicate_control(p, true);
223 brw_MOV(p, g0, g2);
224 brw_pop_insn_state(p);
225 }
226
227 /* The handling of f0.1 vs f0.0 changes between gen6 and gen7. Explicitly test
228 * it, so that we run the fuzzing can run over all the other bits that might
229 * interact with it.
230 */
231 static void
232 gen_f0_1_MOV_GRF_GRF(struct brw_compile *p)
233 {
234 struct brw_reg g0 = brw_vec8_grf(0, 0);
235 struct brw_reg g2 = brw_vec8_grf(2, 0);
236
237 brw_push_insn_state(p);
238 brw_set_predicate_control(p, true);
239 struct brw_instruction *mov = brw_MOV(p, g0, g2);
240 mov->bits2.da1.flag_subreg_nr = 1;
241 brw_pop_insn_state(p);
242 }
243
244 struct {
245 void (*func)(struct brw_compile *p);
246 } tests[] = {
247 { gen_MOV_GRF_GRF },
248 { gen_ADD_GRF_GRF_GRF },
249 { gen_ADD_GRF_GRF_IMM },
250 { gen_ADD_GRF_GRF_IMM_d },
251 { gen_ADD_MRF_GRF_GRF },
252 { gen_ADD_vec1_GRF_GRF_GRF },
253 { gen_PLN_MRF_GRF_GRF },
254 { gen_f0_0_MOV_GRF_GRF },
255 { gen_f0_1_MOV_GRF_GRF },
256 };
257
258 static bool
259 run_tests(struct brw_context *brw)
260 {
261 bool fail = false;
262
263 for (int i = 0; i < ARRAY_SIZE(tests); i++) {
264 for (int align_16 = 0; align_16 <= 1; align_16++) {
265 struct brw_compile *p = rzalloc(NULL, struct brw_compile);
266 brw_init_compile(brw, p, p);
267
268 brw_set_predicate_control(p, BRW_PREDICATE_NONE);
269 if (align_16)
270 brw_set_access_mode(p, BRW_ALIGN_16);
271 else
272 brw_set_access_mode(p, BRW_ALIGN_1);
273
274 tests[i].func(p);
275 assert(p->nr_insn == 1);
276
277 if (!test_compact_instruction(p, p->store[0])) {
278 fail = true;
279 continue;
280 }
281
282 if (!test_fuzz_compact_instruction(p, p->store[0])) {
283 fail = true;
284 continue;
285 }
286
287 ralloc_free(p);
288 }
289 }
290
291 return fail;
292 }
293
294 int
295 main(int argc, char **argv)
296 {
297 struct brw_context *brw = calloc(1, sizeof(*brw));
298 brw->gen = 6;
299 bool fail = false;
300
301 for (brw->gen = 6; brw->gen <= 7; brw->gen++) {
302 fail |= run_tests(brw);
303 }
304
305 return fail;
306 }