1 /*
2 * Copyright © 2012 Intel Corporation
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21 * IN THE SOFTWARE.
22 */
23
24 /** @file gen8_instruction.cpp
25 *
26 * A representation of a Gen8+ EU instruction, with helper methods to get
27 * and set various fields. This is the actual hardware format.
28 */
29
30 #include "brw_defines.h"
31 #include "gen8_instruction.h"
32
33 void
gen8_set_dst(struct gen8_instruction * inst,struct brw_reg reg)34 gen8_set_dst(struct gen8_instruction *inst, struct brw_reg reg)
35 {
36 /* MRFs haven't existed since Gen7, so we better not be using them. */
37 if (reg.file == BRW_MESSAGE_REGISTER_FILE) {
38 reg.file = BRW_GENERAL_REGISTER_FILE;
39 reg.nr += GEN7_MRF_HACK_START;
40 }
41
42 assert(reg.file != BRW_MESSAGE_REGISTER_FILE);
43
44 if (reg.file == BRW_GENERAL_REGISTER_FILE)
45 assert(reg.nr < BRW_MAX_GRF);
46
47 gen8_set_dst_reg_file(inst, reg.file);
48 gen8_set_dst_reg_type(inst, reg.type);
49
50 if (reg.address_mode == BRW_ADDRESS_DIRECT) {
51 gen8_set_dst_da_reg_nr(inst, reg.nr);
52
53 if (gen8_access_mode(inst) == BRW_ALIGN_1) {
54 /* Set Dst.SubRegNum[4:0] */
55 gen8_set_dst_da1_subreg_nr(inst, reg.subnr);
56
57 /* Set Dst.HorzStride */
58 if (reg.hstride == BRW_HORIZONTAL_STRIDE_0)
59 reg.hstride = BRW_HORIZONTAL_STRIDE_1;
60 gen8_set_dst_da1_hstride(inst, reg.hstride);
61 } else {
62 /* Align16 SubRegNum only has a single bit (bit 4; bits 3:0 MBZ). */
63 assert(reg.subnr == 0 || reg.subnr == 16);
64 gen8_set_dst_da16_subreg_nr(inst, reg.subnr >> 4);
65 gen8_set_da16_writemask(inst, reg.dw1.bits.writemask);
66 }
67 } else {
68 /* Indirect mode */
69 assert (gen8_access_mode(inst) == BRW_ALIGN_1);
70
71 gen8_set_dst_addr_mode(inst, BRW_ADDRESS_REGISTER_INDIRECT_REGISTER);
72 /* Set Dst.HorzStride */
73 if (reg.hstride == BRW_HORIZONTAL_STRIDE_0)
74 reg.hstride = BRW_HORIZONTAL_STRIDE_1;
75 gen8_set_dst_da1_hstride(inst, reg.hstride);
76 gen8_set_dst_ida1_sub_nr(inst, reg.subnr);
77 gen8_set_dst_ida1_imm8(inst, (reg.dw1.bits.indirect_offset & IMM8_MASK));
78 if ((reg.dw1.bits.indirect_offset & IMM9_MASK) == IMM9_MASK)
79 gen8_set_dst_ida1_imm9(inst, 1);
80 else
81 gen8_set_dst_ida1_imm9(inst, 0);
82 }
83
84 /* Generators should set a default exec_size of either 8 (SIMD4x2 or SIMD8)
85 * or 16 (SIMD16), as that's normally correct. However, when dealing with
86 * small registers, we automatically reduce it to match the register size.
87 */
88 if (reg.width < BRW_EXECUTE_8)
89 gen8_set_exec_size(inst, reg.width);
90 }
91
92 static void
gen8_validate_reg(struct gen8_instruction * inst,struct brw_reg reg)93 gen8_validate_reg(struct gen8_instruction *inst, struct brw_reg reg)
94 {
95 int hstride_for_reg[] = {0, 1, 2, 4};
96 int vstride_for_reg[] = {0, 1, 2, 4, 8, 16, 32, 64, 128, 256};
97 int width_for_reg[] = {1, 2, 4, 8, 16};
98 int execsize_for_reg[] = {1, 2, 4, 8, 16};
99 int width, hstride, vstride, execsize;
100
101 if (reg.file == BRW_IMMEDIATE_VALUE) {
102 /* TODO: check immediate vectors */
103 return;
104 }
105
106 if (reg.file == BRW_ARCHITECTURE_REGISTER_FILE)
107 return;
108
109 assert(reg.hstride >= 0 && reg.hstride < Elements(hstride_for_reg));
110 hstride = hstride_for_reg[reg.hstride];
111
112 if (reg.vstride == 0xf) {
113 vstride = -1;
114 } else {
115 assert(reg.vstride >= 0 && reg.vstride < Elements(vstride_for_reg));
116 vstride = vstride_for_reg[reg.vstride];
117 }
118
119 assert(reg.width >= 0 && reg.width < Elements(width_for_reg));
120 width = width_for_reg[reg.width];
121
122 assert(gen8_exec_size(inst) >= 0 &&
123 gen8_exec_size(inst) < Elements(execsize_for_reg));
124 execsize = execsize_for_reg[gen8_exec_size(inst)];
125
126 /* Restrictions from 3.3.10: Register Region Restrictions. */
127 /* 3. */
128 assert(execsize >= width);
129
130 /* 4. */
131 if (execsize == width && hstride != 0) {
132 assert(vstride == -1 || vstride == width * hstride);
133 }
134
135 /* 5. */
136 if (execsize == width && hstride == 0) {
137 /* no restriction on vstride. */
138 }
139
140 /* 6. */
141 if (width == 1) {
142 assert(hstride == 0);
143 }
144
145 /* 7. */
146 if (execsize == 1 && width == 1) {
147 assert(hstride == 0);
148 assert(vstride == 0);
149 }
150
151 /* 8. */
152 if (vstride == 0 && hstride == 0) {
153 assert(width == 1);
154 }
155
156 /* 10. Check destination issues. */
157 }
158
159 void
gen8_set_src0(struct gen8_instruction * inst,struct brw_reg reg)160 gen8_set_src0(struct gen8_instruction *inst, struct brw_reg reg)
161 {
162 /* MRFs haven't existed since Gen7, so we better not be using them. */
163 if (reg.file == BRW_MESSAGE_REGISTER_FILE) {
164 reg.file = BRW_GENERAL_REGISTER_FILE;
165 reg.nr += GEN7_MRF_HACK_START;
166 }
167
168 if (reg.file == BRW_GENERAL_REGISTER_FILE)
169 assert(reg.nr < BRW_MAX_GRF);
170
171 gen8_validate_reg(inst, reg);
172
173 gen8_set_src0_reg_file(inst, reg.file);
174 gen8_set_src0_reg_type(inst, reg.type);
175 gen8_set_src0_abs(inst, reg.abs);
176 gen8_set_src0_negate(inst, reg.negate);
177
178
179 if (reg.file == BRW_IMMEDIATE_VALUE) {
180 inst->data[3] = reg.dw1.ud;
181
182 /* Required to set some fields in src1 as well: */
183 gen8_set_src1_reg_file(inst, 0); /* arf */
184 gen8_set_src1_reg_type(inst, reg.type);
185 } else if (reg.address_mode == BRW_ADDRESS_DIRECT) {
186 gen8_set_src0_da_reg_nr(inst, reg.nr);
187
188 if (gen8_access_mode(inst) == BRW_ALIGN_1) {
189 /* Set Src0.SubRegNum[4:0] */
190 gen8_set_src0_da1_subreg_nr(inst, reg.subnr);
191
192 if (reg.width == BRW_WIDTH_1 &&
193 gen8_exec_size(inst) == BRW_EXECUTE_1) {
194 gen8_set_src0_da1_hstride(inst, BRW_HORIZONTAL_STRIDE_0);
195 gen8_set_src0_vert_stride(inst, BRW_VERTICAL_STRIDE_0);
196 } else {
197 gen8_set_src0_da1_hstride(inst, reg.hstride);
198 gen8_set_src0_vert_stride(inst, reg.vstride);
199 }
200 gen8_set_src0_da1_width(inst, reg.width);
201
202 } else {
203 /* Align16 SubRegNum only has a single bit (bit 4; bits 3:0 MBZ). */
204 assert(reg.subnr == 0 || reg.subnr == 16);
205 gen8_set_src0_da16_subreg_nr(inst, reg.subnr >> 4);
206
207 gen8_set_src0_da16_swiz_x(inst,
208 BRW_GET_SWZ(reg.dw1.bits.swizzle,
209 BRW_CHANNEL_X));
210 gen8_set_src0_da16_swiz_y(inst,
211 BRW_GET_SWZ(reg.dw1.bits.swizzle,
212 BRW_CHANNEL_Y));
213 gen8_set_src0_da16_swiz_z(inst,
214 BRW_GET_SWZ(reg.dw1.bits.swizzle,
215 BRW_CHANNEL_Z));
216 gen8_set_src0_da16_swiz_w(inst,
217 BRW_GET_SWZ(reg.dw1.bits.swizzle,
218 BRW_CHANNEL_W));
219
220 /* This is an oddity of the fact that we're using the same
221 * descriptions for registers in both Align16 and Align1 modes.
222 */
223 if (reg.vstride == BRW_VERTICAL_STRIDE_8)
224 gen8_set_src0_vert_stride(inst, BRW_VERTICAL_STRIDE_4);
225 else
226 gen8_set_src0_vert_stride(inst, reg.vstride);
227 }
228 } else if (reg.address_mode == BRW_ADDRESS_REGISTER_INDIRECT_REGISTER) {
229 assert (gen8_access_mode(inst) == BRW_ALIGN_1);
230 if (reg.width == BRW_WIDTH_1 &&
231 gen8_exec_size(inst) == BRW_EXECUTE_1) {
232 gen8_set_src0_da1_hstride(inst, BRW_HORIZONTAL_STRIDE_0);
233 gen8_set_src0_vert_stride(inst, BRW_VERTICAL_STRIDE_0);
234 } else {
235 gen8_set_src0_da1_hstride(inst, reg.hstride);
236 gen8_set_src0_vert_stride(inst, reg.vstride);
237 }
238
239 gen8_set_src0_da1_width(inst, reg.width);
240 gen8_set_src0_ida1_sub_nr(inst, reg.subnr);
241 gen8_set_src0_addr_mode(inst, BRW_ADDRESS_REGISTER_INDIRECT_REGISTER);
242 gen8_set_src0_ida1_imm8(inst, (reg.dw1.bits.indirect_offset & IMM8_MASK));
243 if ((reg.dw1.bits.indirect_offset & IMM9_MASK) == IMM9_MASK)
244 gen8_set_src0_ida1_imm9(inst, 1);
245 else
246 gen8_set_src0_ida1_imm9(inst, 0);
247 }
248 }
249
250 void
gen8_set_src1(struct gen8_instruction * inst,struct brw_reg reg)251 gen8_set_src1(struct gen8_instruction *inst, struct brw_reg reg)
252 {
253 /* MRFs haven't existed since Gen7, so we better not be using them. */
254 if (reg.file == BRW_MESSAGE_REGISTER_FILE) {
255 reg.file = BRW_GENERAL_REGISTER_FILE;
256 reg.nr += GEN7_MRF_HACK_START;
257 }
258
259 if (reg.file == BRW_GENERAL_REGISTER_FILE)
260 assert(reg.nr < BRW_MAX_GRF);
261
262 gen8_validate_reg(inst, reg);
263
264 gen8_set_src1_reg_file(inst, reg.file);
265 gen8_set_src1_reg_type(inst, reg.type);
266 gen8_set_src1_abs(inst, reg.abs);
267 gen8_set_src1_negate(inst, reg.negate);
268
269 /* Only src1 can be an immediate in two-argument instructions. */
270 assert(gen8_src0_reg_file(inst) != BRW_IMMEDIATE_VALUE);
271
272 if (reg.file == BRW_IMMEDIATE_VALUE) {
273 inst->data[3] = reg.dw1.ud;
274 } else if (reg.address_mode == BRW_ADDRESS_DIRECT) {
275 gen8_set_src1_da_reg_nr(inst, reg.nr);
276
277 if (gen8_access_mode(inst) == BRW_ALIGN_1) {
278 /* Set Src0.SubRegNum[4:0] */
279 gen8_set_src1_da1_subreg_nr(inst, reg.subnr);
280
281 if (reg.width == BRW_WIDTH_1 &&
282 gen8_exec_size(inst) == BRW_EXECUTE_1) {
283 gen8_set_src1_da1_hstride(inst, BRW_HORIZONTAL_STRIDE_0);
284 gen8_set_src1_vert_stride(inst, BRW_VERTICAL_STRIDE_0);
285 } else {
286 gen8_set_src1_da1_hstride(inst, reg.hstride);
287 gen8_set_src1_vert_stride(inst, reg.vstride);
288 }
289 gen8_set_src1_da1_width(inst, reg.width);
290 } else {
291 /* Align16 SubRegNum only has a single bit (bit 4; bits 3:0 MBZ). */
292 assert(reg.subnr == 0 || reg.subnr == 16);
293 gen8_set_src1_da16_subreg_nr(inst, reg.subnr >> 4);
294
295 gen8_set_src1_da16_swiz_x(inst,
296 BRW_GET_SWZ(reg.dw1.bits.swizzle,
297 BRW_CHANNEL_X));
298 gen8_set_src1_da16_swiz_y(inst,
299 BRW_GET_SWZ(reg.dw1.bits.swizzle,
300 BRW_CHANNEL_Y));
301 gen8_set_src1_da16_swiz_z(inst,
302 BRW_GET_SWZ(reg.dw1.bits.swizzle,
303 BRW_CHANNEL_Z));
304 gen8_set_src1_da16_swiz_w(inst,
305 BRW_GET_SWZ(reg.dw1.bits.swizzle,
306 BRW_CHANNEL_W));
307
308 /* This is an oddity of the fact that we're using the same
309 * descriptions for registers in both Align16 and Align1 modes.
310 */
311 if (reg.vstride == BRW_VERTICAL_STRIDE_8)
312 gen8_set_src1_vert_stride(inst, BRW_VERTICAL_STRIDE_4);
313 else
314 gen8_set_src1_vert_stride(inst, reg.vstride);
315 }
316 } else if (reg.address_mode == BRW_ADDRESS_REGISTER_INDIRECT_REGISTER) {
317 assert (gen8_access_mode(inst) == BRW_ALIGN_1);
318 if (reg.width == BRW_WIDTH_1 &&
319 gen8_exec_size(inst) == BRW_EXECUTE_1) {
320 gen8_set_src1_da1_hstride(inst, BRW_HORIZONTAL_STRIDE_0);
321 gen8_set_src1_vert_stride(inst, BRW_VERTICAL_STRIDE_0);
322 } else {
323 gen8_set_src1_da1_hstride(inst, reg.hstride);
324 gen8_set_src1_vert_stride(inst, reg.vstride);
325 }
326
327 gen8_set_src1_da1_width(inst, reg.width);
328 gen8_set_src1_ida1_sub_nr(inst, reg.subnr);
329 gen8_set_src1_addr_mode(inst, BRW_ADDRESS_REGISTER_INDIRECT_REGISTER);
330 gen8_set_src1_ida1_imm8(inst, (reg.dw1.bits.indirect_offset & IMM8_MASK));
331 if ((reg.dw1.bits.indirect_offset & IMM9_MASK) == IMM9_MASK)
332 gen8_set_src1_ida1_imm9(inst, 1);
333 else
334 gen8_set_src1_ida1_imm9(inst, 0);
335 }
336 }
337
338 /**
339 * Set the Message Descriptor and Extended Message Descriptor fields
340 * for SEND messages.
341 *
342 * \note This zeroes out the Function Control bits, so it must be called
343 * \b before filling out any message-specific data. Callers can
344 * choose not to fill in irrelevant bits; they will be zero.
345 */
346 static void
gen8_set_message_descriptor(struct gen8_instruction * inst,enum brw_message_target sfid,unsigned msg_length,unsigned response_length,bool header_present,bool end_of_thread)347 gen8_set_message_descriptor(struct gen8_instruction *inst,
348 enum brw_message_target sfid,
349 unsigned msg_length,
350 unsigned response_length,
351 bool header_present,
352 bool end_of_thread)
353 {
354 gen8_set_src1(inst, brw_imm_d(0));
355
356 gen8_set_sfid(inst, sfid);
357 gen8_set_mlen(inst, msg_length);
358 gen8_set_rlen(inst, response_length);
359 gen8_set_header_present(inst, header_present);
360 gen8_set_eot(inst, end_of_thread);
361 }
362
363 void
gen8_set_urb_message(struct gen8_instruction * inst,unsigned opcode,unsigned msg_length,unsigned response_length,bool end_of_thread,unsigned offset,bool interleave)364 gen8_set_urb_message(struct gen8_instruction *inst,
365 unsigned opcode,
366 unsigned msg_length,
367 unsigned response_length,
368 bool end_of_thread,
369 unsigned offset,
370 bool interleave)
371 {
372 gen8_set_message_descriptor(inst, BRW_SFID_URB, msg_length, response_length,
373 true, end_of_thread);
374 gen8_set_src0(inst, brw_vec8_grf(GEN7_MRF_HACK_START + 1, 0));
375 gen8_set_urb_opcode(inst, 0); /* URB_WRITE_HWORD */
376 gen8_set_urb_global_offset(inst, offset);
377 gen8_set_urb_interleave(inst, interleave);
378 /* per_slot_offset = 0 makes it ignore offsets in message header */
379 gen8_set_urb_per_slot_offset(inst, 0);
380 }
381
382 void
gen8_set_sampler_message(struct gen8_instruction * inst,unsigned binding_table_index,unsigned sampler,unsigned msg_type,unsigned response_length,unsigned msg_length,bool header_present,unsigned simd_mode)383 gen8_set_sampler_message(struct gen8_instruction *inst,
384 unsigned binding_table_index,
385 unsigned sampler,
386 unsigned msg_type,
387 unsigned response_length,
388 unsigned msg_length,
389 bool header_present,
390 unsigned simd_mode)
391 {
392 gen8_set_message_descriptor(inst, BRW_SFID_SAMPLER, msg_length,
393 response_length, header_present, false);
394
395 gen8_set_binding_table_index(inst, binding_table_index);
396 gen8_set_sampler(inst, sampler);
397 gen8_set_sampler_msg_type(inst, msg_type);
398 gen8_set_sampler_simd_mode(inst, simd_mode);
399 }
400
401 void
gen8_set_dp_message(struct gen8_instruction * inst,enum brw_message_target sfid,unsigned binding_table_index,unsigned msg_type,unsigned msg_control,unsigned mlen,unsigned rlen,bool header_present,bool end_of_thread)402 gen8_set_dp_message(struct gen8_instruction *inst,
403 enum brw_message_target sfid,
404 unsigned binding_table_index,
405 unsigned msg_type,
406 unsigned msg_control,
407 unsigned mlen,
408 unsigned rlen,
409 bool header_present,
410 bool end_of_thread)
411 {
412 /* Binding table index is from 0..255 */
413 assert((binding_table_index & 0xff) == binding_table_index);
414
415 /* Message Type is only 5 bits */
416 assert((msg_type & 0x1f) == msg_type);
417
418 /* Message Control is only 6 bits */
419 assert((msg_control & 0x3f) == msg_control);
420
421 gen8_set_message_descriptor(inst, sfid, mlen, rlen, header_present,
422 end_of_thread);
423 gen8_set_function_control(inst,
424 binding_table_index | msg_type << 14 | msg_control << 8);
425 }
426
427
428 void
gen9_set_send_extdesc(struct gen8_instruction * inst,unsigned int value)429 gen9_set_send_extdesc(struct gen8_instruction *inst,
430 unsigned int value)
431 {
432 unsigned int extdesc;
433
434 extdesc = (value >> 16) & 0x0f;
435 gen8_set_bits(inst, 67, 64, extdesc);
436
437 extdesc = (value >> 20) & 0x0f;
438 gen8_set_bits(inst, 83, 80, extdesc);
439
440 extdesc = (value >> 24) & 0x0f;
441 gen8_set_bits(inst, 88, 85, extdesc);
442
443 extdesc = (value >> 28) & 0x0f;
444 gen8_set_bits(inst, 94, 91, extdesc);
445 }
446