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