1b8e80941Smrg/*
2b8e80941Smrg Copyright (C) Intel Corp.  2006.  All Rights Reserved.
3b8e80941Smrg Intel funded Tungsten Graphics to
4b8e80941Smrg develop this 3D driver.
5b8e80941Smrg
6b8e80941Smrg Permission is hereby granted, free of charge, to any person obtaining
7b8e80941Smrg a copy of this software and associated documentation files (the
8b8e80941Smrg "Software"), to deal in the Software without restriction, including
9b8e80941Smrg without limitation the rights to use, copy, modify, merge, publish,
10b8e80941Smrg distribute, sublicense, and/or sell copies of the Software, and to
11b8e80941Smrg permit persons to whom the Software is furnished to do so, subject to
12b8e80941Smrg the following conditions:
13b8e80941Smrg
14b8e80941Smrg The above copyright notice and this permission notice (including the
15b8e80941Smrg next paragraph) shall be included in all copies or substantial
16b8e80941Smrg portions of the Software.
17b8e80941Smrg
18b8e80941Smrg THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19b8e80941Smrg EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20b8e80941Smrg MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
21b8e80941Smrg IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
22b8e80941Smrg LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
23b8e80941Smrg OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
24b8e80941Smrg WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25b8e80941Smrg
26b8e80941Smrg **********************************************************************/
27b8e80941Smrg /*
28b8e80941Smrg  * Authors:
29b8e80941Smrg  *   Keith Whitwell <keithw@vmware.com>
30b8e80941Smrg  */
31b8e80941Smrg
32b8e80941Smrg
33b8e80941Smrg#include "brw_eu_defines.h"
34b8e80941Smrg#include "brw_eu.h"
35b8e80941Smrg#include "brw_shader.h"
36b8e80941Smrg#include "dev/gen_debug.h"
37b8e80941Smrg
38b8e80941Smrg#include "util/ralloc.h"
39b8e80941Smrg
40b8e80941Smrg/* Returns a conditional modifier that negates the condition. */
41b8e80941Smrgenum brw_conditional_mod
42b8e80941Smrgbrw_negate_cmod(uint32_t cmod)
43b8e80941Smrg{
44b8e80941Smrg   switch (cmod) {
45b8e80941Smrg   case BRW_CONDITIONAL_Z:
46b8e80941Smrg      return BRW_CONDITIONAL_NZ;
47b8e80941Smrg   case BRW_CONDITIONAL_NZ:
48b8e80941Smrg      return BRW_CONDITIONAL_Z;
49b8e80941Smrg   case BRW_CONDITIONAL_G:
50b8e80941Smrg      return BRW_CONDITIONAL_LE;
51b8e80941Smrg   case BRW_CONDITIONAL_GE:
52b8e80941Smrg      return BRW_CONDITIONAL_L;
53b8e80941Smrg   case BRW_CONDITIONAL_L:
54b8e80941Smrg      return BRW_CONDITIONAL_GE;
55b8e80941Smrg   case BRW_CONDITIONAL_LE:
56b8e80941Smrg      return BRW_CONDITIONAL_G;
57b8e80941Smrg   default:
58b8e80941Smrg      return ~0;
59b8e80941Smrg   }
60b8e80941Smrg}
61b8e80941Smrg
62b8e80941Smrg/* Returns the corresponding conditional mod for swapping src0 and
63b8e80941Smrg * src1 in e.g. CMP.
64b8e80941Smrg */
65b8e80941Smrgenum brw_conditional_mod
66b8e80941Smrgbrw_swap_cmod(uint32_t cmod)
67b8e80941Smrg{
68b8e80941Smrg   switch (cmod) {
69b8e80941Smrg   case BRW_CONDITIONAL_Z:
70b8e80941Smrg   case BRW_CONDITIONAL_NZ:
71b8e80941Smrg      return cmod;
72b8e80941Smrg   case BRW_CONDITIONAL_G:
73b8e80941Smrg      return BRW_CONDITIONAL_L;
74b8e80941Smrg   case BRW_CONDITIONAL_GE:
75b8e80941Smrg      return BRW_CONDITIONAL_LE;
76b8e80941Smrg   case BRW_CONDITIONAL_L:
77b8e80941Smrg      return BRW_CONDITIONAL_G;
78b8e80941Smrg   case BRW_CONDITIONAL_LE:
79b8e80941Smrg      return BRW_CONDITIONAL_GE;
80b8e80941Smrg   default:
81b8e80941Smrg      return BRW_CONDITIONAL_NONE;
82b8e80941Smrg   }
83b8e80941Smrg}
84b8e80941Smrg
85b8e80941Smrg/**
86b8e80941Smrg * Get the least significant bit offset of the i+1-th component of immediate
87b8e80941Smrg * type \p type.  For \p i equal to the two's complement of j, return the
88b8e80941Smrg * offset of the j-th component starting from the end of the vector.  For
89b8e80941Smrg * scalar register types return zero.
90b8e80941Smrg */
91b8e80941Smrgstatic unsigned
92b8e80941Smrgimm_shift(enum brw_reg_type type, unsigned i)
93b8e80941Smrg{
94b8e80941Smrg   assert(type != BRW_REGISTER_TYPE_UV && type != BRW_REGISTER_TYPE_V &&
95b8e80941Smrg          "Not implemented.");
96b8e80941Smrg
97b8e80941Smrg   if (type == BRW_REGISTER_TYPE_VF)
98b8e80941Smrg      return 8 * (i & 3);
99b8e80941Smrg   else
100b8e80941Smrg      return 0;
101b8e80941Smrg}
102b8e80941Smrg
103b8e80941Smrg/**
104b8e80941Smrg * Swizzle an arbitrary immediate \p x of the given type according to the
105b8e80941Smrg * permutation specified as \p swz.
106b8e80941Smrg */
107b8e80941Smrguint32_t
108b8e80941Smrgbrw_swizzle_immediate(enum brw_reg_type type, uint32_t x, unsigned swz)
109b8e80941Smrg{
110b8e80941Smrg   if (imm_shift(type, 1)) {
111b8e80941Smrg      const unsigned n = 32 / imm_shift(type, 1);
112b8e80941Smrg      uint32_t y = 0;
113b8e80941Smrg
114b8e80941Smrg      for (unsigned i = 0; i < n; i++) {
115b8e80941Smrg         /* Shift the specified component all the way to the right and left to
116b8e80941Smrg          * discard any undesired L/MSBs, then shift it right into component i.
117b8e80941Smrg          */
118b8e80941Smrg         y |= x >> imm_shift(type, (i & ~3) + BRW_GET_SWZ(swz, i & 3))
119b8e80941Smrg                << imm_shift(type, ~0u)
120b8e80941Smrg                >> imm_shift(type, ~0u - i);
121b8e80941Smrg      }
122b8e80941Smrg
123b8e80941Smrg      return y;
124b8e80941Smrg   } else {
125b8e80941Smrg      return x;
126b8e80941Smrg   }
127b8e80941Smrg}
128b8e80941Smrg
129b8e80941Smrgunsigned
130b8e80941Smrgbrw_get_default_exec_size(struct brw_codegen *p)
131b8e80941Smrg{
132b8e80941Smrg   return p->current->exec_size;
133b8e80941Smrg}
134b8e80941Smrg
135b8e80941Smrgunsigned
136b8e80941Smrgbrw_get_default_group(struct brw_codegen *p)
137b8e80941Smrg{
138b8e80941Smrg   return p->current->group;
139b8e80941Smrg}
140b8e80941Smrg
141b8e80941Smrgunsigned
142b8e80941Smrgbrw_get_default_access_mode(struct brw_codegen *p)
143b8e80941Smrg{
144b8e80941Smrg   return p->current->access_mode;
145b8e80941Smrg}
146b8e80941Smrg
147b8e80941Smrgvoid
148b8e80941Smrgbrw_set_default_exec_size(struct brw_codegen *p, unsigned value)
149b8e80941Smrg{
150b8e80941Smrg   p->current->exec_size = value;
151b8e80941Smrg}
152b8e80941Smrg
153b8e80941Smrgvoid brw_set_default_predicate_control( struct brw_codegen *p, unsigned pc )
154b8e80941Smrg{
155b8e80941Smrg   p->current->predicate = pc;
156b8e80941Smrg}
157b8e80941Smrg
158b8e80941Smrgvoid brw_set_default_predicate_inverse(struct brw_codegen *p, bool predicate_inverse)
159b8e80941Smrg{
160b8e80941Smrg   p->current->pred_inv = predicate_inverse;
161b8e80941Smrg}
162b8e80941Smrg
163b8e80941Smrgvoid brw_set_default_flag_reg(struct brw_codegen *p, int reg, int subreg)
164b8e80941Smrg{
165b8e80941Smrg   assert(subreg < 2);
166b8e80941Smrg   p->current->flag_subreg = reg * 2 + subreg;
167b8e80941Smrg}
168b8e80941Smrg
169b8e80941Smrgvoid brw_set_default_access_mode( struct brw_codegen *p, unsigned access_mode )
170b8e80941Smrg{
171b8e80941Smrg   p->current->access_mode = access_mode;
172b8e80941Smrg}
173b8e80941Smrg
174b8e80941Smrgvoid
175b8e80941Smrgbrw_set_default_compression_control(struct brw_codegen *p,
176b8e80941Smrg			    enum brw_compression compression_control)
177b8e80941Smrg{
178b8e80941Smrg   switch (compression_control) {
179b8e80941Smrg   case BRW_COMPRESSION_NONE:
180b8e80941Smrg      /* This is the "use the first set of bits of dmask/vmask/arf
181b8e80941Smrg       * according to execsize" option.
182b8e80941Smrg       */
183b8e80941Smrg      p->current->group = 0;
184b8e80941Smrg      break;
185b8e80941Smrg   case BRW_COMPRESSION_2NDHALF:
186b8e80941Smrg      /* For SIMD8, this is "use the second set of 8 bits." */
187b8e80941Smrg      p->current->group = 8;
188b8e80941Smrg      break;
189b8e80941Smrg   case BRW_COMPRESSION_COMPRESSED:
190b8e80941Smrg      /* For SIMD16 instruction compression, use the first set of 16 bits
191b8e80941Smrg       * since we don't do SIMD32 dispatch.
192b8e80941Smrg       */
193b8e80941Smrg      p->current->group = 0;
194b8e80941Smrg      break;
195b8e80941Smrg   default:
196b8e80941Smrg      unreachable("not reached");
197b8e80941Smrg   }
198b8e80941Smrg
199b8e80941Smrg   if (p->devinfo->gen <= 6) {
200b8e80941Smrg      p->current->compressed =
201b8e80941Smrg         (compression_control == BRW_COMPRESSION_COMPRESSED);
202b8e80941Smrg   }
203b8e80941Smrg}
204b8e80941Smrg
205b8e80941Smrg/**
206b8e80941Smrg * Enable or disable instruction compression on the given instruction leaving
207b8e80941Smrg * the currently selected channel enable group untouched.
208b8e80941Smrg */
209b8e80941Smrgvoid
210b8e80941Smrgbrw_inst_set_compression(const struct gen_device_info *devinfo,
211b8e80941Smrg                         brw_inst *inst, bool on)
212b8e80941Smrg{
213b8e80941Smrg   if (devinfo->gen >= 6) {
214b8e80941Smrg      /* No-op, the EU will figure out for us whether the instruction needs to
215b8e80941Smrg       * be compressed.
216b8e80941Smrg       */
217b8e80941Smrg   } else {
218b8e80941Smrg      /* The channel group and compression controls are non-orthogonal, there
219b8e80941Smrg       * are two possible representations for uncompressed instructions and we
220b8e80941Smrg       * may need to preserve the current one to avoid changing the selected
221b8e80941Smrg       * channel group inadvertently.
222b8e80941Smrg       */
223b8e80941Smrg      if (on)
224b8e80941Smrg         brw_inst_set_qtr_control(devinfo, inst, BRW_COMPRESSION_COMPRESSED);
225b8e80941Smrg      else if (brw_inst_qtr_control(devinfo, inst)
226b8e80941Smrg               == BRW_COMPRESSION_COMPRESSED)
227b8e80941Smrg         brw_inst_set_qtr_control(devinfo, inst, BRW_COMPRESSION_NONE);
228b8e80941Smrg   }
229b8e80941Smrg}
230b8e80941Smrg
231b8e80941Smrgvoid
232b8e80941Smrgbrw_set_default_compression(struct brw_codegen *p, bool on)
233b8e80941Smrg{
234b8e80941Smrg   p->current->compressed = on;
235b8e80941Smrg}
236b8e80941Smrg
237b8e80941Smrg/**
238b8e80941Smrg * Apply the range of channel enable signals given by
239b8e80941Smrg * [group, group + exec_size) to the instruction passed as argument.
240b8e80941Smrg */
241b8e80941Smrgvoid
242b8e80941Smrgbrw_inst_set_group(const struct gen_device_info *devinfo,
243b8e80941Smrg                   brw_inst *inst, unsigned group)
244b8e80941Smrg{
245b8e80941Smrg   if (devinfo->gen >= 7) {
246b8e80941Smrg      assert(group % 4 == 0 && group < 32);
247b8e80941Smrg      brw_inst_set_qtr_control(devinfo, inst, group / 8);
248b8e80941Smrg      brw_inst_set_nib_control(devinfo, inst, (group / 4) % 2);
249b8e80941Smrg
250b8e80941Smrg   } else if (devinfo->gen == 6) {
251b8e80941Smrg      assert(group % 8 == 0 && group < 32);
252b8e80941Smrg      brw_inst_set_qtr_control(devinfo, inst, group / 8);
253b8e80941Smrg
254b8e80941Smrg   } else {
255b8e80941Smrg      assert(group % 8 == 0 && group < 16);
256b8e80941Smrg      /* The channel group and compression controls are non-orthogonal, there
257b8e80941Smrg       * are two possible representations for group zero and we may need to
258b8e80941Smrg       * preserve the current one to avoid changing the selected compression
259b8e80941Smrg       * enable inadvertently.
260b8e80941Smrg       */
261b8e80941Smrg      if (group == 8)
262b8e80941Smrg         brw_inst_set_qtr_control(devinfo, inst, BRW_COMPRESSION_2NDHALF);
263b8e80941Smrg      else if (brw_inst_qtr_control(devinfo, inst) == BRW_COMPRESSION_2NDHALF)
264b8e80941Smrg         brw_inst_set_qtr_control(devinfo, inst, BRW_COMPRESSION_NONE);
265b8e80941Smrg   }
266b8e80941Smrg}
267b8e80941Smrg
268b8e80941Smrgvoid
269b8e80941Smrgbrw_set_default_group(struct brw_codegen *p, unsigned group)
270b8e80941Smrg{
271b8e80941Smrg   p->current->group = group;
272b8e80941Smrg}
273b8e80941Smrg
274b8e80941Smrgvoid brw_set_default_mask_control( struct brw_codegen *p, unsigned value )
275b8e80941Smrg{
276b8e80941Smrg   p->current->mask_control = value;
277b8e80941Smrg}
278b8e80941Smrg
279b8e80941Smrgvoid brw_set_default_saturate( struct brw_codegen *p, bool enable )
280b8e80941Smrg{
281b8e80941Smrg   p->current->saturate = enable;
282b8e80941Smrg}
283b8e80941Smrg
284b8e80941Smrgvoid brw_set_default_acc_write_control(struct brw_codegen *p, unsigned value)
285b8e80941Smrg{
286b8e80941Smrg   p->current->acc_wr_control = value;
287b8e80941Smrg}
288b8e80941Smrg
289b8e80941Smrgvoid brw_push_insn_state( struct brw_codegen *p )
290b8e80941Smrg{
291b8e80941Smrg   assert(p->current != &p->stack[BRW_EU_MAX_INSN_STACK-1]);
292b8e80941Smrg   *(p->current + 1) = *p->current;
293b8e80941Smrg   p->current++;
294b8e80941Smrg}
295b8e80941Smrg
296b8e80941Smrgvoid brw_pop_insn_state( struct brw_codegen *p )
297b8e80941Smrg{
298b8e80941Smrg   assert(p->current != p->stack);
299b8e80941Smrg   p->current--;
300b8e80941Smrg}
301b8e80941Smrg
302b8e80941Smrg
303b8e80941Smrg/***********************************************************************
304b8e80941Smrg */
305b8e80941Smrgvoid
306b8e80941Smrgbrw_init_codegen(const struct gen_device_info *devinfo,
307b8e80941Smrg                 struct brw_codegen *p, void *mem_ctx)
308b8e80941Smrg{
309b8e80941Smrg   memset(p, 0, sizeof(*p));
310b8e80941Smrg
311b8e80941Smrg   p->devinfo = devinfo;
312b8e80941Smrg   p->automatic_exec_sizes = true;
313b8e80941Smrg   /*
314b8e80941Smrg    * Set the initial instruction store array size to 1024, if found that
315b8e80941Smrg    * isn't enough, then it will double the store size at brw_next_insn()
316b8e80941Smrg    * until out of memory.
317b8e80941Smrg    */
318b8e80941Smrg   p->store_size = 1024;
319b8e80941Smrg   p->store = rzalloc_array(mem_ctx, brw_inst, p->store_size);
320b8e80941Smrg   p->nr_insn = 0;
321b8e80941Smrg   p->current = p->stack;
322b8e80941Smrg   memset(p->current, 0, sizeof(p->current[0]));
323b8e80941Smrg
324b8e80941Smrg   p->mem_ctx = mem_ctx;
325b8e80941Smrg
326b8e80941Smrg   /* Some defaults?
327b8e80941Smrg    */
328b8e80941Smrg   brw_set_default_exec_size(p, BRW_EXECUTE_8);
329b8e80941Smrg   brw_set_default_mask_control(p, BRW_MASK_ENABLE); /* what does this do? */
330b8e80941Smrg   brw_set_default_saturate(p, 0);
331b8e80941Smrg   brw_set_default_compression_control(p, BRW_COMPRESSION_NONE);
332b8e80941Smrg
333b8e80941Smrg   /* Set up control flow stack */
334b8e80941Smrg   p->if_stack_depth = 0;
335b8e80941Smrg   p->if_stack_array_size = 16;
336b8e80941Smrg   p->if_stack = rzalloc_array(mem_ctx, int, p->if_stack_array_size);
337b8e80941Smrg
338b8e80941Smrg   p->loop_stack_depth = 0;
339b8e80941Smrg   p->loop_stack_array_size = 16;
340b8e80941Smrg   p->loop_stack = rzalloc_array(mem_ctx, int, p->loop_stack_array_size);
341b8e80941Smrg   p->if_depth_in_loop = rzalloc_array(mem_ctx, int, p->loop_stack_array_size);
342b8e80941Smrg}
343b8e80941Smrg
344b8e80941Smrg
345b8e80941Smrgconst unsigned *brw_get_program( struct brw_codegen *p,
346b8e80941Smrg			       unsigned *sz )
347b8e80941Smrg{
348b8e80941Smrg   *sz = p->next_insn_offset;
349b8e80941Smrg   return (const unsigned *)p->store;
350b8e80941Smrg}
351b8e80941Smrg
352b8e80941Smrgvoid
353b8e80941Smrgbrw_disassemble(const struct gen_device_info *devinfo,
354b8e80941Smrg                const void *assembly, int start, int end, FILE *out)
355b8e80941Smrg{
356b8e80941Smrg   bool dump_hex = (INTEL_DEBUG & DEBUG_HEX) != 0;
357b8e80941Smrg
358b8e80941Smrg   for (int offset = start; offset < end;) {
359b8e80941Smrg      const brw_inst *insn = assembly + offset;
360b8e80941Smrg      brw_inst uncompacted;
361b8e80941Smrg      bool compacted = brw_inst_cmpt_control(devinfo, insn);
362b8e80941Smrg      if (0)
363b8e80941Smrg         fprintf(out, "0x%08x: ", offset);
364b8e80941Smrg
365b8e80941Smrg      if (compacted) {
366b8e80941Smrg         brw_compact_inst *compacted = (void *)insn;
367b8e80941Smrg         if (dump_hex) {
368b8e80941Smrg            unsigned char * insn_ptr = ((unsigned char *)&insn[0]);
369b8e80941Smrg            const unsigned int blank_spaces = 24;
370b8e80941Smrg            for (int i = 0 ; i < 8; i = i + 4) {
371b8e80941Smrg               fprintf(out, "%02x %02x %02x %02x ",
372b8e80941Smrg                       insn_ptr[i],
373b8e80941Smrg                       insn_ptr[i + 1],
374b8e80941Smrg                       insn_ptr[i + 2],
375b8e80941Smrg                       insn_ptr[i + 3]);
376b8e80941Smrg            }
377b8e80941Smrg            /* Make compacted instructions hex value output vertically aligned
378b8e80941Smrg             * with uncompacted instructions hex value
379b8e80941Smrg             */
380b8e80941Smrg            fprintf(out, "%*c", blank_spaces, ' ');
381b8e80941Smrg         }
382b8e80941Smrg
383b8e80941Smrg         brw_uncompact_instruction(devinfo, &uncompacted, compacted);
384b8e80941Smrg         insn = &uncompacted;
385b8e80941Smrg         offset += 8;
386b8e80941Smrg      } else {
387b8e80941Smrg         if (dump_hex) {
388b8e80941Smrg            unsigned char * insn_ptr = ((unsigned char *)&insn[0]);
389b8e80941Smrg            for (int i = 0 ; i < 16; i = i + 4) {
390b8e80941Smrg               fprintf(out, "%02x %02x %02x %02x ",
391b8e80941Smrg                       insn_ptr[i],
392b8e80941Smrg                       insn_ptr[i + 1],
393b8e80941Smrg                       insn_ptr[i + 2],
394b8e80941Smrg                       insn_ptr[i + 3]);
395b8e80941Smrg            }
396b8e80941Smrg         }
397b8e80941Smrg         offset += 16;
398b8e80941Smrg      }
399b8e80941Smrg
400b8e80941Smrg      brw_disassemble_inst(out, devinfo, insn, compacted);
401b8e80941Smrg   }
402b8e80941Smrg}
403b8e80941Smrg
404b8e80941Smrgenum gen {
405b8e80941Smrg   GEN4  = (1 << 0),
406b8e80941Smrg   GEN45 = (1 << 1),
407b8e80941Smrg   GEN5  = (1 << 2),
408b8e80941Smrg   GEN6  = (1 << 3),
409b8e80941Smrg   GEN7  = (1 << 4),
410b8e80941Smrg   GEN75 = (1 << 5),
411b8e80941Smrg   GEN8  = (1 << 6),
412b8e80941Smrg   GEN9  = (1 << 7),
413b8e80941Smrg   GEN10 = (1 << 8),
414b8e80941Smrg   GEN11 = (1 << 9),
415b8e80941Smrg   GEN_ALL = ~0
416b8e80941Smrg};
417b8e80941Smrg
418b8e80941Smrg#define GEN_LT(gen) ((gen) - 1)
419b8e80941Smrg#define GEN_GE(gen) (~GEN_LT(gen))
420b8e80941Smrg#define GEN_LE(gen) (GEN_LT(gen) | (gen))
421b8e80941Smrg
422b8e80941Smrgstatic const struct opcode_desc opcode_10_descs[] = {
423b8e80941Smrg   { .name = "dim",   .nsrc = 1, .ndst = 1, .gens = GEN75 },
424b8e80941Smrg   { .name = "smov",  .nsrc = 0, .ndst = 0, .gens = GEN_GE(GEN8) },
425b8e80941Smrg};
426b8e80941Smrg
427b8e80941Smrgstatic const struct opcode_desc opcode_35_descs[] = {
428b8e80941Smrg   { .name = "iff",   .nsrc = 0, .ndst = 0, .gens = GEN_LE(GEN5) },
429b8e80941Smrg   { .name = "brc",   .nsrc = 0, .ndst = 0, .gens = GEN_GE(GEN7) },
430b8e80941Smrg};
431b8e80941Smrg
432b8e80941Smrgstatic const struct opcode_desc opcode_38_descs[] = {
433b8e80941Smrg   { .name = "do",    .nsrc = 0, .ndst = 0, .gens = GEN_LE(GEN5) },
434b8e80941Smrg   { .name = "case",  .nsrc = 0, .ndst = 0, .gens = GEN6 },
435b8e80941Smrg};
436b8e80941Smrg
437b8e80941Smrgstatic const struct opcode_desc opcode_44_descs[] = {
438b8e80941Smrg   { .name = "msave", .nsrc = 0, .ndst = 0, .gens = GEN_LE(GEN5) },
439b8e80941Smrg   { .name = "call",  .nsrc = 0, .ndst = 0, .gens = GEN_GE(GEN6) },
440b8e80941Smrg};
441b8e80941Smrg
442b8e80941Smrgstatic const struct opcode_desc opcode_45_descs[] = {
443b8e80941Smrg   { .name = "mrest", .nsrc = 0, .ndst = 0, .gens = GEN_LE(GEN5) },
444b8e80941Smrg   { .name = "ret",   .nsrc = 0, .ndst = 0, .gens = GEN_GE(GEN6) },
445b8e80941Smrg};
446b8e80941Smrg
447b8e80941Smrgstatic const struct opcode_desc opcode_46_descs[] = {
448b8e80941Smrg   { .name = "push",  .nsrc = 0, .ndst = 0, .gens = GEN_LE(GEN5) },
449b8e80941Smrg   { .name = "fork",  .nsrc = 0, .ndst = 0, .gens = GEN6 },
450b8e80941Smrg   { .name = "goto",  .nsrc = 0, .ndst = 0, .gens = GEN_GE(GEN8) },
451b8e80941Smrg};
452b8e80941Smrg
453b8e80941Smrgstatic const struct opcode_desc opcode_descs[128] = {
454b8e80941Smrg   [BRW_OPCODE_ILLEGAL] = {
455b8e80941Smrg      .name = "illegal", .nsrc = 0, .ndst = 0, .gens = GEN_ALL,
456b8e80941Smrg   },
457b8e80941Smrg   [BRW_OPCODE_MOV] = {
458b8e80941Smrg      .name = "mov",     .nsrc = 1, .ndst = 1, .gens = GEN_ALL,
459b8e80941Smrg   },
460b8e80941Smrg   [BRW_OPCODE_SEL] = {
461b8e80941Smrg      .name = "sel",     .nsrc = 2, .ndst = 1, .gens = GEN_ALL,
462b8e80941Smrg   },
463b8e80941Smrg   [BRW_OPCODE_MOVI] = {
464b8e80941Smrg      .name = "movi",    .nsrc = 2, .ndst = 1, .gens = GEN_GE(GEN45),
465b8e80941Smrg   },
466b8e80941Smrg   [BRW_OPCODE_NOT] = {
467b8e80941Smrg      .name = "not",     .nsrc = 1, .ndst = 1, .gens = GEN_ALL,
468b8e80941Smrg   },
469b8e80941Smrg   [BRW_OPCODE_AND] = {
470b8e80941Smrg      .name = "and",     .nsrc = 2, .ndst = 1, .gens = GEN_ALL,
471b8e80941Smrg   },
472b8e80941Smrg   [BRW_OPCODE_OR] = {
473b8e80941Smrg      .name = "or",      .nsrc = 2, .ndst = 1, .gens = GEN_ALL,
474b8e80941Smrg   },
475b8e80941Smrg   [BRW_OPCODE_XOR] = {
476b8e80941Smrg      .name = "xor",     .nsrc = 2, .ndst = 1, .gens = GEN_ALL,
477b8e80941Smrg   },
478b8e80941Smrg   [BRW_OPCODE_SHR] = {
479b8e80941Smrg      .name = "shr",     .nsrc = 2, .ndst = 1, .gens = GEN_ALL,
480b8e80941Smrg   },
481b8e80941Smrg   [BRW_OPCODE_SHL] = {
482b8e80941Smrg      .name = "shl",     .nsrc = 2, .ndst = 1, .gens = GEN_ALL,
483b8e80941Smrg   },
484b8e80941Smrg   [10] = {
485b8e80941Smrg      .table = opcode_10_descs, .size = ARRAY_SIZE(opcode_10_descs),
486b8e80941Smrg   },
487b8e80941Smrg   /* Reserved - 11 */
488b8e80941Smrg   [BRW_OPCODE_ASR] = {
489b8e80941Smrg      .name = "asr",     .nsrc = 2, .ndst = 1, .gens = GEN_ALL,
490b8e80941Smrg   },
491b8e80941Smrg   /* Reserved - 13-15 */
492b8e80941Smrg   [BRW_OPCODE_CMP] = {
493b8e80941Smrg      .name = "cmp",     .nsrc = 2, .ndst = 1, .gens = GEN_ALL,
494b8e80941Smrg   },
495b8e80941Smrg   [BRW_OPCODE_CMPN] = {
496b8e80941Smrg      .name = "cmpn",    .nsrc = 2, .ndst = 1, .gens = GEN_ALL,
497b8e80941Smrg   },
498b8e80941Smrg   [BRW_OPCODE_CSEL] = {
499b8e80941Smrg      .name = "csel",    .nsrc = 3, .ndst = 1, .gens = GEN_GE(GEN8),
500b8e80941Smrg   },
501b8e80941Smrg   [BRW_OPCODE_F32TO16] = {
502b8e80941Smrg      .name = "f32to16", .nsrc = 1, .ndst = 1, .gens = GEN7 | GEN75,
503b8e80941Smrg   },
504b8e80941Smrg   [BRW_OPCODE_F16TO32] = {
505b8e80941Smrg      .name = "f16to32", .nsrc = 1, .ndst = 1, .gens = GEN7 | GEN75,
506b8e80941Smrg   },
507b8e80941Smrg   /* Reserved - 21-22 */
508b8e80941Smrg   [BRW_OPCODE_BFREV] = {
509b8e80941Smrg      .name = "bfrev",   .nsrc = 1, .ndst = 1, .gens = GEN_GE(GEN7),
510b8e80941Smrg   },
511b8e80941Smrg   [BRW_OPCODE_BFE] = {
512b8e80941Smrg      .name = "bfe",     .nsrc = 3, .ndst = 1, .gens = GEN_GE(GEN7),
513b8e80941Smrg   },
514b8e80941Smrg   [BRW_OPCODE_BFI1] = {
515b8e80941Smrg      .name = "bfi1",    .nsrc = 2, .ndst = 1, .gens = GEN_GE(GEN7),
516b8e80941Smrg   },
517b8e80941Smrg   [BRW_OPCODE_BFI2] = {
518b8e80941Smrg      .name = "bfi2",    .nsrc = 3, .ndst = 1, .gens = GEN_GE(GEN7),
519b8e80941Smrg   },
520b8e80941Smrg   /* Reserved - 27-31 */
521b8e80941Smrg   [BRW_OPCODE_JMPI] = {
522b8e80941Smrg      .name = "jmpi",    .nsrc = 0, .ndst = 0, .gens = GEN_ALL,
523b8e80941Smrg   },
524b8e80941Smrg   [33] = {
525b8e80941Smrg      .name = "brd",     .nsrc = 0, .ndst = 0, .gens = GEN_GE(GEN7),
526b8e80941Smrg   },
527b8e80941Smrg   [BRW_OPCODE_IF] = {
528b8e80941Smrg      .name = "if",      .nsrc = 0, .ndst = 0, .gens = GEN_ALL,
529b8e80941Smrg   },
530b8e80941Smrg   [35] = {
531b8e80941Smrg      .table = opcode_35_descs, .size = ARRAY_SIZE(opcode_35_descs),
532b8e80941Smrg   },
533b8e80941Smrg   [BRW_OPCODE_ELSE] = {
534b8e80941Smrg      .name = "else",    .nsrc = 0, .ndst = 0, .gens = GEN_ALL,
535b8e80941Smrg   },
536b8e80941Smrg   [BRW_OPCODE_ENDIF] = {
537b8e80941Smrg      .name = "endif",   .nsrc = 0, .ndst = 0, .gens = GEN_ALL,
538b8e80941Smrg   },
539b8e80941Smrg   [38] = {
540b8e80941Smrg      .table = opcode_38_descs, .size = ARRAY_SIZE(opcode_38_descs),
541b8e80941Smrg   },
542b8e80941Smrg   [BRW_OPCODE_WHILE] = {
543b8e80941Smrg      .name = "while",   .nsrc = 0, .ndst = 0, .gens = GEN_ALL,
544b8e80941Smrg   },
545b8e80941Smrg   [BRW_OPCODE_BREAK] = {
546b8e80941Smrg      .name = "break",   .nsrc = 0, .ndst = 0, .gens = GEN_ALL,
547b8e80941Smrg   },
548b8e80941Smrg   [BRW_OPCODE_CONTINUE] = {
549b8e80941Smrg      .name = "cont",    .nsrc = 0, .ndst = 0, .gens = GEN_ALL,
550b8e80941Smrg   },
551b8e80941Smrg   [BRW_OPCODE_HALT] = {
552b8e80941Smrg      .name = "halt",    .nsrc = 0, .ndst = 0, .gens = GEN_ALL,
553b8e80941Smrg   },
554b8e80941Smrg   [43] = {
555b8e80941Smrg      .name = "calla",   .nsrc = 0, .ndst = 0, .gens = GEN_GE(GEN75),
556b8e80941Smrg   },
557b8e80941Smrg   [44] = {
558b8e80941Smrg      .table = opcode_44_descs, .size = ARRAY_SIZE(opcode_44_descs),
559b8e80941Smrg   },
560b8e80941Smrg   [45] = {
561b8e80941Smrg      .table = opcode_45_descs, .size = ARRAY_SIZE(opcode_45_descs),
562b8e80941Smrg   },
563b8e80941Smrg   [46] = {
564b8e80941Smrg      .table = opcode_46_descs, .size = ARRAY_SIZE(opcode_46_descs),
565b8e80941Smrg   },
566b8e80941Smrg   [47] = {
567b8e80941Smrg      .name = "pop",     .nsrc = 2, .ndst = 0, .gens = GEN_LE(GEN5),
568b8e80941Smrg   },
569b8e80941Smrg   [BRW_OPCODE_WAIT] = {
570b8e80941Smrg      .name = "wait",    .nsrc = 1, .ndst = 0, .gens = GEN_ALL,
571b8e80941Smrg   },
572b8e80941Smrg   [BRW_OPCODE_SEND] = {
573b8e80941Smrg      .name = "send",    .nsrc = 1, .ndst = 1, .gens = GEN_ALL,
574b8e80941Smrg   },
575b8e80941Smrg   [BRW_OPCODE_SENDC] = {
576b8e80941Smrg      .name = "sendc",   .nsrc = 1, .ndst = 1, .gens = GEN_ALL,
577b8e80941Smrg   },
578b8e80941Smrg   [BRW_OPCODE_SENDS] = {
579b8e80941Smrg      .name = "sends",   .nsrc = 2, .ndst = 1, .gens = GEN_GE(GEN9),
580b8e80941Smrg   },
581b8e80941Smrg   [BRW_OPCODE_SENDSC] = {
582b8e80941Smrg      .name = "sendsc",  .nsrc = 2, .ndst = 1, .gens = GEN_GE(GEN9),
583b8e80941Smrg   },
584b8e80941Smrg   /* Reserved 53-55 */
585b8e80941Smrg   [BRW_OPCODE_MATH] = {
586b8e80941Smrg      .name = "math",    .nsrc = 2, .ndst = 1, .gens = GEN_GE(GEN6),
587b8e80941Smrg   },
588b8e80941Smrg   /* Reserved 57-63 */
589b8e80941Smrg   [BRW_OPCODE_ADD] = {
590b8e80941Smrg      .name = "add",     .nsrc = 2, .ndst = 1, .gens = GEN_ALL,
591b8e80941Smrg   },
592b8e80941Smrg   [BRW_OPCODE_MUL] = {
593b8e80941Smrg      .name = "mul",     .nsrc = 2, .ndst = 1, .gens = GEN_ALL,
594b8e80941Smrg   },
595b8e80941Smrg   [BRW_OPCODE_AVG] = {
596b8e80941Smrg      .name = "avg",     .nsrc = 2, .ndst = 1, .gens = GEN_ALL,
597b8e80941Smrg   },
598b8e80941Smrg   [BRW_OPCODE_FRC] = {
599b8e80941Smrg      .name = "frc",     .nsrc = 1, .ndst = 1, .gens = GEN_ALL,
600b8e80941Smrg   },
601b8e80941Smrg   [BRW_OPCODE_RNDU] = {
602b8e80941Smrg      .name = "rndu",    .nsrc = 1, .ndst = 1, .gens = GEN_ALL,
603b8e80941Smrg   },
604b8e80941Smrg   [BRW_OPCODE_RNDD] = {
605b8e80941Smrg      .name = "rndd",    .nsrc = 1, .ndst = 1, .gens = GEN_ALL,
606b8e80941Smrg   },
607b8e80941Smrg   [BRW_OPCODE_RNDE] = {
608b8e80941Smrg      .name = "rnde",    .nsrc = 1, .ndst = 1, .gens = GEN_ALL,
609b8e80941Smrg   },
610b8e80941Smrg   [BRW_OPCODE_RNDZ] = {
611b8e80941Smrg      .name = "rndz",    .nsrc = 1, .ndst = 1, .gens = GEN_ALL,
612b8e80941Smrg   },
613b8e80941Smrg   [BRW_OPCODE_MAC] = {
614b8e80941Smrg      .name = "mac",     .nsrc = 2, .ndst = 1, .gens = GEN_ALL,
615b8e80941Smrg   },
616b8e80941Smrg   [BRW_OPCODE_MACH] = {
617b8e80941Smrg      .name = "mach",    .nsrc = 2, .ndst = 1, .gens = GEN_ALL,
618b8e80941Smrg   },
619b8e80941Smrg   [BRW_OPCODE_LZD] = {
620b8e80941Smrg      .name = "lzd",     .nsrc = 1, .ndst = 1, .gens = GEN_ALL,
621b8e80941Smrg   },
622b8e80941Smrg   [BRW_OPCODE_FBH] = {
623b8e80941Smrg      .name = "fbh",     .nsrc = 1, .ndst = 1, .gens = GEN_GE(GEN7),
624b8e80941Smrg   },
625b8e80941Smrg   [BRW_OPCODE_FBL] = {
626b8e80941Smrg      .name = "fbl",     .nsrc = 1, .ndst = 1, .gens = GEN_GE(GEN7),
627b8e80941Smrg   },
628b8e80941Smrg   [BRW_OPCODE_CBIT] = {
629b8e80941Smrg      .name = "cbit",    .nsrc = 1, .ndst = 1, .gens = GEN_GE(GEN7),
630b8e80941Smrg   },
631b8e80941Smrg   [BRW_OPCODE_ADDC] = {
632b8e80941Smrg      .name = "addc",    .nsrc = 2, .ndst = 1, .gens = GEN_GE(GEN7),
633b8e80941Smrg   },
634b8e80941Smrg   [BRW_OPCODE_SUBB] = {
635b8e80941Smrg      .name = "subb",    .nsrc = 2, .ndst = 1, .gens = GEN_GE(GEN7),
636b8e80941Smrg   },
637b8e80941Smrg   [BRW_OPCODE_SAD2] = {
638b8e80941Smrg      .name = "sad2",    .nsrc = 2, .ndst = 1, .gens = GEN_ALL,
639b8e80941Smrg   },
640b8e80941Smrg   [BRW_OPCODE_SADA2] = {
641b8e80941Smrg      .name = "sada2",   .nsrc = 2, .ndst = 1, .gens = GEN_ALL,
642b8e80941Smrg   },
643b8e80941Smrg   /* Reserved 82-83 */
644b8e80941Smrg   [BRW_OPCODE_DP4] = {
645b8e80941Smrg      .name = "dp4",     .nsrc = 2, .ndst = 1, .gens = GEN_ALL,
646b8e80941Smrg   },
647b8e80941Smrg   [BRW_OPCODE_DPH] = {
648b8e80941Smrg      .name = "dph",     .nsrc = 2, .ndst = 1, .gens = GEN_ALL,
649b8e80941Smrg   },
650b8e80941Smrg   [BRW_OPCODE_DP3] = {
651b8e80941Smrg      .name = "dp3",     .nsrc = 2, .ndst = 1, .gens = GEN_ALL,
652b8e80941Smrg   },
653b8e80941Smrg   [BRW_OPCODE_DP2] = {
654b8e80941Smrg      .name = "dp2",     .nsrc = 2, .ndst = 1, .gens = GEN_ALL,
655b8e80941Smrg   },
656b8e80941Smrg   /* Reserved 88 */
657b8e80941Smrg   [BRW_OPCODE_LINE] = {
658b8e80941Smrg      .name = "line",    .nsrc = 2, .ndst = 1, .gens = GEN_LE(GEN10),
659b8e80941Smrg   },
660b8e80941Smrg   [BRW_OPCODE_PLN] = {
661b8e80941Smrg      .name = "pln",     .nsrc = 2, .ndst = 1, .gens = GEN_GE(GEN45) & GEN_LE(GEN10),
662b8e80941Smrg   },
663b8e80941Smrg   [BRW_OPCODE_MAD] = {
664b8e80941Smrg      .name = "mad",     .nsrc = 3, .ndst = 1, .gens = GEN_GE(GEN6),
665b8e80941Smrg   },
666b8e80941Smrg   [BRW_OPCODE_LRP] = {
667b8e80941Smrg      .name = "lrp",     .nsrc = 3, .ndst = 1, .gens = GEN_GE(GEN6) & GEN_LE(GEN10),
668b8e80941Smrg   },
669b8e80941Smrg   [93] = {
670b8e80941Smrg      .name = "madm",    .nsrc = 3, .ndst = 1, .gens = GEN_GE(GEN8),
671b8e80941Smrg   },
672b8e80941Smrg   /* Reserved 94-124 */
673b8e80941Smrg   [BRW_OPCODE_NENOP] = {
674b8e80941Smrg      .name = "nenop",   .nsrc = 0, .ndst = 0, .gens = GEN45,
675b8e80941Smrg   },
676b8e80941Smrg   [BRW_OPCODE_NOP] = {
677b8e80941Smrg      .name = "nop",     .nsrc = 0, .ndst = 0, .gens = GEN_ALL,
678b8e80941Smrg   },
679b8e80941Smrg};
680b8e80941Smrg
681b8e80941Smrgstatic enum gen
682b8e80941Smrggen_from_devinfo(const struct gen_device_info *devinfo)
683b8e80941Smrg{
684b8e80941Smrg   switch (devinfo->gen) {
685b8e80941Smrg   case 4: return devinfo->is_g4x ? GEN45 : GEN4;
686b8e80941Smrg   case 5: return GEN5;
687b8e80941Smrg   case 6: return GEN6;
688b8e80941Smrg   case 7: return devinfo->is_haswell ? GEN75 : GEN7;
689b8e80941Smrg   case 8: return GEN8;
690b8e80941Smrg   case 9: return GEN9;
691b8e80941Smrg   case 10: return GEN10;
692b8e80941Smrg   case 11: return GEN11;
693b8e80941Smrg   default:
694b8e80941Smrg      unreachable("not reached");
695b8e80941Smrg   }
696b8e80941Smrg}
697b8e80941Smrg
698b8e80941Smrg/* Return the matching opcode_desc for the specified opcode number and
699b8e80941Smrg * hardware generation, or NULL if the opcode is not supported by the device.
700b8e80941Smrg */
701b8e80941Smrgconst struct opcode_desc *
702b8e80941Smrgbrw_opcode_desc(const struct gen_device_info *devinfo, enum opcode opcode)
703b8e80941Smrg{
704b8e80941Smrg   if (opcode >= ARRAY_SIZE(opcode_descs))
705b8e80941Smrg      return NULL;
706b8e80941Smrg
707b8e80941Smrg   enum gen gen = gen_from_devinfo(devinfo);
708b8e80941Smrg   if (opcode_descs[opcode].gens != 0) {
709b8e80941Smrg      if ((opcode_descs[opcode].gens & gen) != 0) {
710b8e80941Smrg         return &opcode_descs[opcode];
711b8e80941Smrg      }
712b8e80941Smrg   } else if (opcode_descs[opcode].table != NULL) {
713b8e80941Smrg      const struct opcode_desc *table = opcode_descs[opcode].table;
714b8e80941Smrg      for (unsigned i = 0; i < opcode_descs[opcode].size; i++) {
715b8e80941Smrg         if ((table[i].gens & gen) != 0) {
716b8e80941Smrg            return &table[i];
717b8e80941Smrg         }
718b8e80941Smrg      }
719b8e80941Smrg   }
720b8e80941Smrg   return NULL;
721b8e80941Smrg}
722