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/** @file brw_reg.h
33b8e80941Smrg *
34b8e80941Smrg * This file defines struct brw_reg, which is our representation for EU
35b8e80941Smrg * registers.  They're not a hardware specific format, just an abstraction
36b8e80941Smrg * that intends to capture the full flexibility of the hardware registers.
37b8e80941Smrg *
38b8e80941Smrg * The brw_eu_emit.c layer's brw_set_dest/brw_set_src[01] functions encode
39b8e80941Smrg * the abstract brw_reg type into the actual hardware instruction encoding.
40b8e80941Smrg */
41b8e80941Smrg
42b8e80941Smrg#ifndef BRW_REG_H
43b8e80941Smrg#define BRW_REG_H
44b8e80941Smrg
45b8e80941Smrg#include <stdbool.h>
46b8e80941Smrg#include "main/compiler.h"
47b8e80941Smrg#include "main/macros.h"
48b8e80941Smrg#include "program/prog_instruction.h"
49b8e80941Smrg#include "brw_eu_defines.h"
50b8e80941Smrg#include "brw_reg_type.h"
51b8e80941Smrg
52b8e80941Smrg#ifdef __cplusplus
53b8e80941Smrgextern "C" {
54b8e80941Smrg#endif
55b8e80941Smrg
56b8e80941Smrgstruct gen_device_info;
57b8e80941Smrg
58b8e80941Smrg/** Number of general purpose registers (VS, WM, etc) */
59b8e80941Smrg#define BRW_MAX_GRF 128
60b8e80941Smrg
61b8e80941Smrg/**
62b8e80941Smrg * First GRF used for the MRF hack.
63b8e80941Smrg *
64b8e80941Smrg * On gen7, MRFs are no longer used, and contiguous GRFs are used instead.  We
65b8e80941Smrg * haven't converted our compiler to be aware of this, so it asks for MRFs and
66b8e80941Smrg * brw_eu_emit.c quietly converts them to be accesses of the top GRFs.  The
67b8e80941Smrg * register allocators have to be careful of this to avoid corrupting the "MRF"s
68b8e80941Smrg * with actual GRF allocations.
69b8e80941Smrg */
70b8e80941Smrg#define GEN7_MRF_HACK_START 112
71b8e80941Smrg
72b8e80941Smrg/** Number of message register file registers */
73b8e80941Smrg#define BRW_MAX_MRF(gen) (gen == 6 ? 24 : 16)
74b8e80941Smrg
75b8e80941Smrg#define BRW_SWIZZLE4(a,b,c,d) (((a)<<0) | ((b)<<2) | ((c)<<4) | ((d)<<6))
76b8e80941Smrg#define BRW_GET_SWZ(swz, idx) (((swz) >> ((idx)*2)) & 0x3)
77b8e80941Smrg
78b8e80941Smrg#define BRW_SWIZZLE_NOOP      BRW_SWIZZLE4(0,1,2,3)
79b8e80941Smrg#define BRW_SWIZZLE_XYZW      BRW_SWIZZLE4(0,1,2,3)
80b8e80941Smrg#define BRW_SWIZZLE_XXXX      BRW_SWIZZLE4(0,0,0,0)
81b8e80941Smrg#define BRW_SWIZZLE_YYYY      BRW_SWIZZLE4(1,1,1,1)
82b8e80941Smrg#define BRW_SWIZZLE_ZZZZ      BRW_SWIZZLE4(2,2,2,2)
83b8e80941Smrg#define BRW_SWIZZLE_WWWW      BRW_SWIZZLE4(3,3,3,3)
84b8e80941Smrg#define BRW_SWIZZLE_XYXY      BRW_SWIZZLE4(0,1,0,1)
85b8e80941Smrg#define BRW_SWIZZLE_YXYX      BRW_SWIZZLE4(1,0,1,0)
86b8e80941Smrg#define BRW_SWIZZLE_XZXZ      BRW_SWIZZLE4(0,2,0,2)
87b8e80941Smrg#define BRW_SWIZZLE_YZXW      BRW_SWIZZLE4(1,2,0,3)
88b8e80941Smrg#define BRW_SWIZZLE_YWYW      BRW_SWIZZLE4(1,3,1,3)
89b8e80941Smrg#define BRW_SWIZZLE_ZXYW      BRW_SWIZZLE4(2,0,1,3)
90b8e80941Smrg#define BRW_SWIZZLE_ZWZW      BRW_SWIZZLE4(2,3,2,3)
91b8e80941Smrg#define BRW_SWIZZLE_WZWZ      BRW_SWIZZLE4(3,2,3,2)
92b8e80941Smrg#define BRW_SWIZZLE_WZYX      BRW_SWIZZLE4(3,2,1,0)
93b8e80941Smrg#define BRW_SWIZZLE_XXZZ      BRW_SWIZZLE4(0,0,2,2)
94b8e80941Smrg#define BRW_SWIZZLE_YYWW      BRW_SWIZZLE4(1,1,3,3)
95b8e80941Smrg#define BRW_SWIZZLE_YXWZ      BRW_SWIZZLE4(1,0,3,2)
96b8e80941Smrg
97b8e80941Smrg#define BRW_SWZ_COMP_INPUT(comp) (BRW_SWIZZLE_XYZW >> ((comp)*2))
98b8e80941Smrg#define BRW_SWZ_COMP_OUTPUT(comp) (BRW_SWIZZLE_XYZW << ((comp)*2))
99b8e80941Smrg
100b8e80941Smrgstatic inline bool
101b8e80941Smrgbrw_is_single_value_swizzle(unsigned swiz)
102b8e80941Smrg{
103b8e80941Smrg   return (swiz == BRW_SWIZZLE_XXXX ||
104b8e80941Smrg           swiz == BRW_SWIZZLE_YYYY ||
105b8e80941Smrg           swiz == BRW_SWIZZLE_ZZZZ ||
106b8e80941Smrg           swiz == BRW_SWIZZLE_WWWW);
107b8e80941Smrg}
108b8e80941Smrg
109b8e80941Smrg/**
110b8e80941Smrg * Compute the swizzle obtained from the application of \p swz0 on the result
111b8e80941Smrg * of \p swz1.  The argument ordering is expected to match function
112b8e80941Smrg * composition.
113b8e80941Smrg */
114b8e80941Smrgstatic inline unsigned
115b8e80941Smrgbrw_compose_swizzle(unsigned swz0, unsigned swz1)
116b8e80941Smrg{
117b8e80941Smrg   return BRW_SWIZZLE4(
118b8e80941Smrg      BRW_GET_SWZ(swz1, BRW_GET_SWZ(swz0, 0)),
119b8e80941Smrg      BRW_GET_SWZ(swz1, BRW_GET_SWZ(swz0, 1)),
120b8e80941Smrg      BRW_GET_SWZ(swz1, BRW_GET_SWZ(swz0, 2)),
121b8e80941Smrg      BRW_GET_SWZ(swz1, BRW_GET_SWZ(swz0, 3)));
122b8e80941Smrg}
123b8e80941Smrg
124b8e80941Smrg/**
125b8e80941Smrg * Return the result of applying swizzle \p swz to shuffle the bits of \p mask
126b8e80941Smrg * (AKA image).
127b8e80941Smrg */
128b8e80941Smrgstatic inline unsigned
129b8e80941Smrgbrw_apply_swizzle_to_mask(unsigned swz, unsigned mask)
130b8e80941Smrg{
131b8e80941Smrg   unsigned result = 0;
132b8e80941Smrg
133b8e80941Smrg   for (unsigned i = 0; i < 4; i++) {
134b8e80941Smrg      if (mask & (1 << BRW_GET_SWZ(swz, i)))
135b8e80941Smrg         result |= 1 << i;
136b8e80941Smrg   }
137b8e80941Smrg
138b8e80941Smrg   return result;
139b8e80941Smrg}
140b8e80941Smrg
141b8e80941Smrg/**
142b8e80941Smrg * Return the result of applying the inverse of swizzle \p swz to shuffle the
143b8e80941Smrg * bits of \p mask (AKA preimage).  Useful to find out which components are
144b8e80941Smrg * read from a swizzled source given the instruction writemask.
145b8e80941Smrg */
146b8e80941Smrgstatic inline unsigned
147b8e80941Smrgbrw_apply_inv_swizzle_to_mask(unsigned swz, unsigned mask)
148b8e80941Smrg{
149b8e80941Smrg   unsigned result = 0;
150b8e80941Smrg
151b8e80941Smrg   for (unsigned i = 0; i < 4; i++) {
152b8e80941Smrg      if (mask & (1 << i))
153b8e80941Smrg         result |= 1 << BRW_GET_SWZ(swz, i);
154b8e80941Smrg   }
155b8e80941Smrg
156b8e80941Smrg   return result;
157b8e80941Smrg}
158b8e80941Smrg
159b8e80941Smrg/**
160b8e80941Smrg * Construct an identity swizzle for the set of enabled channels given by \p
161b8e80941Smrg * mask.  The result will only reference channels enabled in the provided \p
162b8e80941Smrg * mask, assuming that \p mask is non-zero.  The constructed swizzle will
163b8e80941Smrg * satisfy the property that for any instruction OP and any mask:
164b8e80941Smrg *
165b8e80941Smrg *    brw_OP(p, brw_writemask(dst, mask),
166b8e80941Smrg *           brw_swizzle(src, brw_swizzle_for_mask(mask)));
167b8e80941Smrg *
168b8e80941Smrg * will be equivalent to the same instruction without swizzle:
169b8e80941Smrg *
170b8e80941Smrg *    brw_OP(p, brw_writemask(dst, mask), src);
171b8e80941Smrg */
172b8e80941Smrgstatic inline unsigned
173b8e80941Smrgbrw_swizzle_for_mask(unsigned mask)
174b8e80941Smrg{
175b8e80941Smrg   unsigned last = (mask ? ffs(mask) - 1 : 0);
176b8e80941Smrg   unsigned swz[4];
177b8e80941Smrg
178b8e80941Smrg   for (unsigned i = 0; i < 4; i++)
179b8e80941Smrg      last = swz[i] = (mask & (1 << i) ? i : last);
180b8e80941Smrg
181b8e80941Smrg   return BRW_SWIZZLE4(swz[0], swz[1], swz[2], swz[3]);
182b8e80941Smrg}
183b8e80941Smrg
184b8e80941Smrg/**
185b8e80941Smrg * Construct an identity swizzle for the first \p n components of a vector.
186b8e80941Smrg * When only a subset of channels of a vec4 are used we don't want to
187b8e80941Smrg * reference the other channels, as that will tell optimization passes that
188b8e80941Smrg * those other channels are used.
189b8e80941Smrg */
190b8e80941Smrgstatic inline unsigned
191b8e80941Smrgbrw_swizzle_for_size(unsigned n)
192b8e80941Smrg{
193b8e80941Smrg   return brw_swizzle_for_mask((1 << n) - 1);
194b8e80941Smrg}
195b8e80941Smrg
196b8e80941Smrg/**
197b8e80941Smrg * Converse of brw_swizzle_for_mask().  Returns the mask of components
198b8e80941Smrg * accessed by the specified swizzle \p swz.
199b8e80941Smrg */
200b8e80941Smrgstatic inline unsigned
201b8e80941Smrgbrw_mask_for_swizzle(unsigned swz)
202b8e80941Smrg{
203b8e80941Smrg   return brw_apply_inv_swizzle_to_mask(swz, ~0);
204b8e80941Smrg}
205b8e80941Smrg
206b8e80941Smrguint32_t brw_swizzle_immediate(enum brw_reg_type type, uint32_t x, unsigned swz);
207b8e80941Smrg
208b8e80941Smrg#define REG_SIZE (8*4)
209b8e80941Smrg
210b8e80941Smrg/* These aren't hardware structs, just something useful for us to pass around:
211b8e80941Smrg *
212b8e80941Smrg * Align1 operation has a lot of control over input ranges.  Used in
213b8e80941Smrg * WM programs to implement shaders decomposed into "channel serial"
214b8e80941Smrg * or "structure of array" form:
215b8e80941Smrg */
216b8e80941Smrgstruct brw_reg {
217b8e80941Smrg   union {
218b8e80941Smrg      struct {
219b8e80941Smrg         enum brw_reg_type type:4;
220b8e80941Smrg         enum brw_reg_file file:3;      /* :2 hardware format */
221b8e80941Smrg         unsigned negate:1;             /* source only */
222b8e80941Smrg         unsigned abs:1;                /* source only */
223b8e80941Smrg         unsigned address_mode:1;       /* relative addressing, hopefully! */
224b8e80941Smrg         unsigned pad0:17;
225b8e80941Smrg         unsigned subnr:5;              /* :1 in align16 */
226b8e80941Smrg      };
227b8e80941Smrg      uint32_t bits;
228b8e80941Smrg   };
229b8e80941Smrg
230b8e80941Smrg   union {
231b8e80941Smrg      struct {
232b8e80941Smrg         unsigned nr;
233b8e80941Smrg         unsigned swizzle:8;      /* src only, align16 only */
234b8e80941Smrg         unsigned writemask:4;    /* dest only, align16 only */
235b8e80941Smrg         int  indirect_offset:10; /* relative addressing offset */
236b8e80941Smrg         unsigned vstride:4;      /* source only */
237b8e80941Smrg         unsigned width:3;        /* src only, align1 only */
238b8e80941Smrg         unsigned hstride:2;      /* align1 only */
239b8e80941Smrg         unsigned pad1:1;
240b8e80941Smrg      };
241b8e80941Smrg
242b8e80941Smrg      double df;
243b8e80941Smrg      uint64_t u64;
244b8e80941Smrg      int64_t d64;
245b8e80941Smrg      float f;
246b8e80941Smrg      int   d;
247b8e80941Smrg      unsigned ud;
248b8e80941Smrg   };
249b8e80941Smrg};
250b8e80941Smrg
251b8e80941Smrgstatic inline bool
252b8e80941Smrgbrw_regs_equal(const struct brw_reg *a, const struct brw_reg *b)
253b8e80941Smrg{
254b8e80941Smrg   return a->bits == b->bits && a->u64 == b->u64;
255b8e80941Smrg}
256b8e80941Smrg
257b8e80941Smrgstatic inline bool
258b8e80941Smrgbrw_regs_negative_equal(const struct brw_reg *a, const struct brw_reg *b)
259b8e80941Smrg{
260b8e80941Smrg   if (a->file == IMM) {
261b8e80941Smrg      if (a->bits != b->bits)
262b8e80941Smrg         return false;
263b8e80941Smrg
264b8e80941Smrg      switch ((enum brw_reg_type) a->type) {
265b8e80941Smrg      case BRW_REGISTER_TYPE_UQ:
266b8e80941Smrg      case BRW_REGISTER_TYPE_Q:
267b8e80941Smrg         return a->d64 == -b->d64;
268b8e80941Smrg      case BRW_REGISTER_TYPE_DF:
269b8e80941Smrg         return a->df == -b->df;
270b8e80941Smrg      case BRW_REGISTER_TYPE_UD:
271b8e80941Smrg      case BRW_REGISTER_TYPE_D:
272b8e80941Smrg         return a->d == -b->d;
273b8e80941Smrg      case BRW_REGISTER_TYPE_F:
274b8e80941Smrg         return a->f == -b->f;
275b8e80941Smrg      case BRW_REGISTER_TYPE_VF:
276b8e80941Smrg         /* It is tempting to treat 0 as a negation of 0 (and -0 as a negation
277b8e80941Smrg          * of -0).  There are occasions where 0 or -0 is used and the exact
278b8e80941Smrg          * bit pattern is desired.  At the very least, changing this to allow
279b8e80941Smrg          * 0 as a negation of 0 causes some fp64 tests to fail on IVB.
280b8e80941Smrg          */
281b8e80941Smrg         return a->ud == (b->ud ^ 0x80808080);
282b8e80941Smrg      case BRW_REGISTER_TYPE_UW:
283b8e80941Smrg      case BRW_REGISTER_TYPE_W:
284b8e80941Smrg      case BRW_REGISTER_TYPE_UV:
285b8e80941Smrg      case BRW_REGISTER_TYPE_V:
286b8e80941Smrg      case BRW_REGISTER_TYPE_HF:
287b8e80941Smrg         /* FINISHME: Implement support for these types once there is
288b8e80941Smrg          * something in the compiler that can generate them.  Until then,
289b8e80941Smrg          * they cannot be tested.
290b8e80941Smrg          */
291b8e80941Smrg         return false;
292b8e80941Smrg      case BRW_REGISTER_TYPE_UB:
293b8e80941Smrg      case BRW_REGISTER_TYPE_B:
294b8e80941Smrg      case BRW_REGISTER_TYPE_NF:
295b8e80941Smrg      default:
296b8e80941Smrg         unreachable("not reached");
297b8e80941Smrg      }
298b8e80941Smrg   } else {
299b8e80941Smrg      struct brw_reg tmp = *a;
300b8e80941Smrg
301b8e80941Smrg      tmp.negate = !tmp.negate;
302b8e80941Smrg
303b8e80941Smrg      return brw_regs_equal(&tmp, b);
304b8e80941Smrg   }
305b8e80941Smrg}
306b8e80941Smrg
307b8e80941Smrgstruct brw_indirect {
308b8e80941Smrg   unsigned addr_subnr:4;
309b8e80941Smrg   int addr_offset:10;
310b8e80941Smrg   unsigned pad:18;
311b8e80941Smrg};
312b8e80941Smrg
313b8e80941Smrg
314b8e80941Smrgstatic inline unsigned
315b8e80941Smrgtype_sz(unsigned type)
316b8e80941Smrg{
317b8e80941Smrg   switch(type) {
318b8e80941Smrg   case BRW_REGISTER_TYPE_UQ:
319b8e80941Smrg   case BRW_REGISTER_TYPE_Q:
320b8e80941Smrg   case BRW_REGISTER_TYPE_DF:
321b8e80941Smrg      return 8;
322b8e80941Smrg   case BRW_REGISTER_TYPE_UD:
323b8e80941Smrg   case BRW_REGISTER_TYPE_D:
324b8e80941Smrg   case BRW_REGISTER_TYPE_F:
325b8e80941Smrg   case BRW_REGISTER_TYPE_VF:
326b8e80941Smrg      return 4;
327b8e80941Smrg   case BRW_REGISTER_TYPE_UW:
328b8e80941Smrg   case BRW_REGISTER_TYPE_W:
329b8e80941Smrg   case BRW_REGISTER_TYPE_UV:
330b8e80941Smrg   case BRW_REGISTER_TYPE_V:
331b8e80941Smrg   case BRW_REGISTER_TYPE_HF:
332b8e80941Smrg      return 2;
333b8e80941Smrg   case BRW_REGISTER_TYPE_UB:
334b8e80941Smrg   case BRW_REGISTER_TYPE_B:
335b8e80941Smrg      return 1;
336b8e80941Smrg   default:
337b8e80941Smrg      unreachable("not reached");
338b8e80941Smrg   }
339b8e80941Smrg}
340b8e80941Smrg
341b8e80941Smrgstatic inline enum brw_reg_type
342b8e80941Smrgget_exec_type(const enum brw_reg_type type)
343b8e80941Smrg{
344b8e80941Smrg   switch (type) {
345b8e80941Smrg   case BRW_REGISTER_TYPE_B:
346b8e80941Smrg   case BRW_REGISTER_TYPE_V:
347b8e80941Smrg      return BRW_REGISTER_TYPE_W;
348b8e80941Smrg   case BRW_REGISTER_TYPE_UB:
349b8e80941Smrg   case BRW_REGISTER_TYPE_UV:
350b8e80941Smrg      return BRW_REGISTER_TYPE_UW;
351b8e80941Smrg   case BRW_REGISTER_TYPE_VF:
352b8e80941Smrg      return BRW_REGISTER_TYPE_F;
353b8e80941Smrg   default:
354b8e80941Smrg      return type;
355b8e80941Smrg   }
356b8e80941Smrg}
357b8e80941Smrg
358b8e80941Smrg/**
359b8e80941Smrg * Return an integer type of the requested size and signedness.
360b8e80941Smrg */
361b8e80941Smrgstatic inline enum brw_reg_type
362b8e80941Smrgbrw_int_type(unsigned sz, bool is_signed)
363b8e80941Smrg{
364b8e80941Smrg   switch (sz) {
365b8e80941Smrg   case 1:
366b8e80941Smrg      return (is_signed ? BRW_REGISTER_TYPE_B : BRW_REGISTER_TYPE_UB);
367b8e80941Smrg   case 2:
368b8e80941Smrg      return (is_signed ? BRW_REGISTER_TYPE_W : BRW_REGISTER_TYPE_UW);
369b8e80941Smrg   case 4:
370b8e80941Smrg      return (is_signed ? BRW_REGISTER_TYPE_D : BRW_REGISTER_TYPE_UD);
371b8e80941Smrg   case 8:
372b8e80941Smrg      return (is_signed ? BRW_REGISTER_TYPE_Q : BRW_REGISTER_TYPE_UQ);
373b8e80941Smrg   default:
374b8e80941Smrg      unreachable("Not reached.");
375b8e80941Smrg   }
376b8e80941Smrg}
377b8e80941Smrg
378b8e80941Smrgstatic inline bool
379b8e80941Smrgtype_is_unsigned_int(enum brw_reg_type tp)
380b8e80941Smrg{
381b8e80941Smrg   return tp == BRW_REGISTER_TYPE_UB ||
382b8e80941Smrg          tp == BRW_REGISTER_TYPE_UW ||
383b8e80941Smrg          tp == BRW_REGISTER_TYPE_UD ||
384b8e80941Smrg          tp == BRW_REGISTER_TYPE_UQ;
385b8e80941Smrg}
386b8e80941Smrg
387b8e80941Smrg/**
388b8e80941Smrg * Construct a brw_reg.
389b8e80941Smrg * \param file      one of the BRW_x_REGISTER_FILE values
390b8e80941Smrg * \param nr        register number/index
391b8e80941Smrg * \param subnr     register sub number
392b8e80941Smrg * \param negate    register negate modifier
393b8e80941Smrg * \param abs       register abs modifier
394b8e80941Smrg * \param type      one of BRW_REGISTER_TYPE_x
395b8e80941Smrg * \param vstride   one of BRW_VERTICAL_STRIDE_x
396b8e80941Smrg * \param width     one of BRW_WIDTH_x
397b8e80941Smrg * \param hstride   one of BRW_HORIZONTAL_STRIDE_x
398b8e80941Smrg * \param swizzle   one of BRW_SWIZZLE_x
399b8e80941Smrg * \param writemask WRITEMASK_X/Y/Z/W bitfield
400b8e80941Smrg */
401b8e80941Smrgstatic inline struct brw_reg
402b8e80941Smrgbrw_reg(enum brw_reg_file file,
403b8e80941Smrg        unsigned nr,
404b8e80941Smrg        unsigned subnr,
405b8e80941Smrg        unsigned negate,
406b8e80941Smrg        unsigned abs,
407b8e80941Smrg        enum brw_reg_type type,
408b8e80941Smrg        unsigned vstride,
409b8e80941Smrg        unsigned width,
410b8e80941Smrg        unsigned hstride,
411b8e80941Smrg        unsigned swizzle,
412b8e80941Smrg        unsigned writemask)
413b8e80941Smrg{
414b8e80941Smrg   struct brw_reg reg;
415b8e80941Smrg   if (file == BRW_GENERAL_REGISTER_FILE)
416b8e80941Smrg      assert(nr < BRW_MAX_GRF);
417b8e80941Smrg   else if (file == BRW_ARCHITECTURE_REGISTER_FILE)
418b8e80941Smrg      assert(nr <= BRW_ARF_TIMESTAMP);
419b8e80941Smrg   /* Asserting on the MRF register number requires to know the hardware gen
420b8e80941Smrg    * (gen6 has 24 MRF registers), which we don't know here, so we assert
421b8e80941Smrg    * for that in the generators and in brw_eu_emit.c
422b8e80941Smrg    */
423b8e80941Smrg
424b8e80941Smrg   reg.type = type;
425b8e80941Smrg   reg.file = file;
426b8e80941Smrg   reg.negate = negate;
427b8e80941Smrg   reg.abs = abs;
428b8e80941Smrg   reg.address_mode = BRW_ADDRESS_DIRECT;
429b8e80941Smrg   reg.pad0 = 0;
430b8e80941Smrg   reg.subnr = subnr * type_sz(type);
431b8e80941Smrg   reg.nr = nr;
432b8e80941Smrg
433b8e80941Smrg   /* Could do better: If the reg is r5.3<0;1,0>, we probably want to
434b8e80941Smrg    * set swizzle and writemask to W, as the lower bits of subnr will
435b8e80941Smrg    * be lost when converted to align16.  This is probably too much to
436b8e80941Smrg    * keep track of as you'd want it adjusted by suboffset(), etc.
437b8e80941Smrg    * Perhaps fix up when converting to align16?
438b8e80941Smrg    */
439b8e80941Smrg   reg.swizzle = swizzle;
440b8e80941Smrg   reg.writemask = writemask;
441b8e80941Smrg   reg.indirect_offset = 0;
442b8e80941Smrg   reg.vstride = vstride;
443b8e80941Smrg   reg.width = width;
444b8e80941Smrg   reg.hstride = hstride;
445b8e80941Smrg   reg.pad1 = 0;
446b8e80941Smrg   return reg;
447b8e80941Smrg}
448b8e80941Smrg
449b8e80941Smrg/** Construct float[16] register */
450b8e80941Smrgstatic inline struct brw_reg
451b8e80941Smrgbrw_vec16_reg(enum brw_reg_file file, unsigned nr, unsigned subnr)
452b8e80941Smrg{
453b8e80941Smrg   return brw_reg(file,
454b8e80941Smrg                  nr,
455b8e80941Smrg                  subnr,
456b8e80941Smrg                  0,
457b8e80941Smrg                  0,
458b8e80941Smrg                  BRW_REGISTER_TYPE_F,
459b8e80941Smrg                  BRW_VERTICAL_STRIDE_16,
460b8e80941Smrg                  BRW_WIDTH_16,
461b8e80941Smrg                  BRW_HORIZONTAL_STRIDE_1,
462b8e80941Smrg                  BRW_SWIZZLE_XYZW,
463b8e80941Smrg                  WRITEMASK_XYZW);
464b8e80941Smrg}
465b8e80941Smrg
466b8e80941Smrg/** Construct float[8] register */
467b8e80941Smrgstatic inline struct brw_reg
468b8e80941Smrgbrw_vec8_reg(enum brw_reg_file file, unsigned nr, unsigned subnr)
469b8e80941Smrg{
470b8e80941Smrg   return brw_reg(file,
471b8e80941Smrg                  nr,
472b8e80941Smrg                  subnr,
473b8e80941Smrg                  0,
474b8e80941Smrg                  0,
475b8e80941Smrg                  BRW_REGISTER_TYPE_F,
476b8e80941Smrg                  BRW_VERTICAL_STRIDE_8,
477b8e80941Smrg                  BRW_WIDTH_8,
478b8e80941Smrg                  BRW_HORIZONTAL_STRIDE_1,
479b8e80941Smrg                  BRW_SWIZZLE_XYZW,
480b8e80941Smrg                  WRITEMASK_XYZW);
481b8e80941Smrg}
482b8e80941Smrg
483b8e80941Smrg/** Construct float[4] register */
484b8e80941Smrgstatic inline struct brw_reg
485b8e80941Smrgbrw_vec4_reg(enum brw_reg_file file, unsigned nr, unsigned subnr)
486b8e80941Smrg{
487b8e80941Smrg   return brw_reg(file,
488b8e80941Smrg                  nr,
489b8e80941Smrg                  subnr,
490b8e80941Smrg                  0,
491b8e80941Smrg                  0,
492b8e80941Smrg                  BRW_REGISTER_TYPE_F,
493b8e80941Smrg                  BRW_VERTICAL_STRIDE_4,
494b8e80941Smrg                  BRW_WIDTH_4,
495b8e80941Smrg                  BRW_HORIZONTAL_STRIDE_1,
496b8e80941Smrg                  BRW_SWIZZLE_XYZW,
497b8e80941Smrg                  WRITEMASK_XYZW);
498b8e80941Smrg}
499b8e80941Smrg
500b8e80941Smrg/** Construct float[2] register */
501b8e80941Smrgstatic inline struct brw_reg
502b8e80941Smrgbrw_vec2_reg(enum brw_reg_file file, unsigned nr, unsigned subnr)
503b8e80941Smrg{
504b8e80941Smrg   return brw_reg(file,
505b8e80941Smrg                  nr,
506b8e80941Smrg                  subnr,
507b8e80941Smrg                  0,
508b8e80941Smrg                  0,
509b8e80941Smrg                  BRW_REGISTER_TYPE_F,
510b8e80941Smrg                  BRW_VERTICAL_STRIDE_2,
511b8e80941Smrg                  BRW_WIDTH_2,
512b8e80941Smrg                  BRW_HORIZONTAL_STRIDE_1,
513b8e80941Smrg                  BRW_SWIZZLE_XYXY,
514b8e80941Smrg                  WRITEMASK_XY);
515b8e80941Smrg}
516b8e80941Smrg
517b8e80941Smrg/** Construct float[1] register */
518b8e80941Smrgstatic inline struct brw_reg
519b8e80941Smrgbrw_vec1_reg(enum brw_reg_file file, unsigned nr, unsigned subnr)
520b8e80941Smrg{
521b8e80941Smrg   return brw_reg(file,
522b8e80941Smrg                  nr,
523b8e80941Smrg                  subnr,
524b8e80941Smrg                  0,
525b8e80941Smrg                  0,
526b8e80941Smrg                  BRW_REGISTER_TYPE_F,
527b8e80941Smrg                  BRW_VERTICAL_STRIDE_0,
528b8e80941Smrg                  BRW_WIDTH_1,
529b8e80941Smrg                  BRW_HORIZONTAL_STRIDE_0,
530b8e80941Smrg                  BRW_SWIZZLE_XXXX,
531b8e80941Smrg                  WRITEMASK_X);
532b8e80941Smrg}
533b8e80941Smrg
534b8e80941Smrgstatic inline struct brw_reg
535b8e80941Smrgbrw_vecn_reg(unsigned width, enum brw_reg_file file,
536b8e80941Smrg             unsigned nr, unsigned subnr)
537b8e80941Smrg{
538b8e80941Smrg   switch (width) {
539b8e80941Smrg   case 1:
540b8e80941Smrg      return brw_vec1_reg(file, nr, subnr);
541b8e80941Smrg   case 2:
542b8e80941Smrg      return brw_vec2_reg(file, nr, subnr);
543b8e80941Smrg   case 4:
544b8e80941Smrg      return brw_vec4_reg(file, nr, subnr);
545b8e80941Smrg   case 8:
546b8e80941Smrg      return brw_vec8_reg(file, nr, subnr);
547b8e80941Smrg   case 16:
548b8e80941Smrg      return brw_vec16_reg(file, nr, subnr);
549b8e80941Smrg   default:
550b8e80941Smrg      unreachable("Invalid register width");
551b8e80941Smrg   }
552b8e80941Smrg}
553b8e80941Smrg
554b8e80941Smrgstatic inline struct brw_reg
555b8e80941Smrgretype(struct brw_reg reg, enum brw_reg_type type)
556b8e80941Smrg{
557b8e80941Smrg   reg.type = type;
558b8e80941Smrg   return reg;
559b8e80941Smrg}
560b8e80941Smrg
561b8e80941Smrgstatic inline struct brw_reg
562b8e80941Smrgfirsthalf(struct brw_reg reg)
563b8e80941Smrg{
564b8e80941Smrg   return reg;
565b8e80941Smrg}
566b8e80941Smrg
567b8e80941Smrgstatic inline struct brw_reg
568b8e80941Smrgsechalf(struct brw_reg reg)
569b8e80941Smrg{
570b8e80941Smrg   if (reg.vstride)
571b8e80941Smrg      reg.nr++;
572b8e80941Smrg   return reg;
573b8e80941Smrg}
574b8e80941Smrg
575b8e80941Smrgstatic inline struct brw_reg
576b8e80941Smrgoffset(struct brw_reg reg, unsigned delta)
577b8e80941Smrg{
578b8e80941Smrg   reg.nr += delta;
579b8e80941Smrg   return reg;
580b8e80941Smrg}
581b8e80941Smrg
582b8e80941Smrg
583b8e80941Smrgstatic inline struct brw_reg
584b8e80941Smrgbyte_offset(struct brw_reg reg, unsigned bytes)
585b8e80941Smrg{
586b8e80941Smrg   unsigned newoffset = reg.nr * REG_SIZE + reg.subnr + bytes;
587b8e80941Smrg   reg.nr = newoffset / REG_SIZE;
588b8e80941Smrg   reg.subnr = newoffset % REG_SIZE;
589b8e80941Smrg   return reg;
590b8e80941Smrg}
591b8e80941Smrg
592b8e80941Smrgstatic inline struct brw_reg
593b8e80941Smrgsuboffset(struct brw_reg reg, unsigned delta)
594b8e80941Smrg{
595b8e80941Smrg   return byte_offset(reg, delta * type_sz(reg.type));
596b8e80941Smrg}
597b8e80941Smrg
598b8e80941Smrg/** Construct unsigned word[16] register */
599b8e80941Smrgstatic inline struct brw_reg
600b8e80941Smrgbrw_uw16_reg(enum brw_reg_file file, unsigned nr, unsigned subnr)
601b8e80941Smrg{
602b8e80941Smrg   return suboffset(retype(brw_vec16_reg(file, nr, 0), BRW_REGISTER_TYPE_UW), subnr);
603b8e80941Smrg}
604b8e80941Smrg
605b8e80941Smrg/** Construct unsigned word[8] register */
606b8e80941Smrgstatic inline struct brw_reg
607b8e80941Smrgbrw_uw8_reg(enum brw_reg_file file, unsigned nr, unsigned subnr)
608b8e80941Smrg{
609b8e80941Smrg   return suboffset(retype(brw_vec8_reg(file, nr, 0), BRW_REGISTER_TYPE_UW), subnr);
610b8e80941Smrg}
611b8e80941Smrg
612b8e80941Smrg/** Construct unsigned word[1] register */
613b8e80941Smrgstatic inline struct brw_reg
614b8e80941Smrgbrw_uw1_reg(enum brw_reg_file file, unsigned nr, unsigned subnr)
615b8e80941Smrg{
616b8e80941Smrg   return suboffset(retype(brw_vec1_reg(file, nr, 0), BRW_REGISTER_TYPE_UW), subnr);
617b8e80941Smrg}
618b8e80941Smrg
619b8e80941Smrgstatic inline struct brw_reg
620b8e80941Smrgbrw_ud1_reg(enum brw_reg_file file, unsigned nr, unsigned subnr)
621b8e80941Smrg{
622b8e80941Smrg   return retype(brw_vec1_reg(file, nr, subnr), BRW_REGISTER_TYPE_UD);
623b8e80941Smrg}
624b8e80941Smrg
625b8e80941Smrgstatic inline struct brw_reg
626b8e80941Smrgbrw_imm_reg(enum brw_reg_type type)
627b8e80941Smrg{
628b8e80941Smrg   return brw_reg(BRW_IMMEDIATE_VALUE,
629b8e80941Smrg                  0,
630b8e80941Smrg                  0,
631b8e80941Smrg                  0,
632b8e80941Smrg                  0,
633b8e80941Smrg                  type,
634b8e80941Smrg                  BRW_VERTICAL_STRIDE_0,
635b8e80941Smrg                  BRW_WIDTH_1,
636b8e80941Smrg                  BRW_HORIZONTAL_STRIDE_0,
637b8e80941Smrg                  0,
638b8e80941Smrg                  0);
639b8e80941Smrg}
640b8e80941Smrg
641b8e80941Smrg/** Construct float immediate register */
642b8e80941Smrgstatic inline struct brw_reg
643b8e80941Smrgbrw_imm_df(double df)
644b8e80941Smrg{
645b8e80941Smrg   struct brw_reg imm = brw_imm_reg(BRW_REGISTER_TYPE_DF);
646b8e80941Smrg   imm.df = df;
647b8e80941Smrg   return imm;
648b8e80941Smrg}
649b8e80941Smrg
650b8e80941Smrgstatic inline struct brw_reg
651b8e80941Smrgbrw_imm_u64(uint64_t u64)
652b8e80941Smrg{
653b8e80941Smrg   struct brw_reg imm = brw_imm_reg(BRW_REGISTER_TYPE_UQ);
654b8e80941Smrg   imm.u64 = u64;
655b8e80941Smrg   return imm;
656b8e80941Smrg}
657b8e80941Smrg
658b8e80941Smrgstatic inline struct brw_reg
659b8e80941Smrgbrw_imm_f(float f)
660b8e80941Smrg{
661b8e80941Smrg   struct brw_reg imm = brw_imm_reg(BRW_REGISTER_TYPE_F);
662b8e80941Smrg   imm.f = f;
663b8e80941Smrg   return imm;
664b8e80941Smrg}
665b8e80941Smrg
666b8e80941Smrg/** Construct int64_t immediate register */
667b8e80941Smrgstatic inline struct brw_reg
668b8e80941Smrgbrw_imm_q(int64_t q)
669b8e80941Smrg{
670b8e80941Smrg   struct brw_reg imm = brw_imm_reg(BRW_REGISTER_TYPE_Q);
671b8e80941Smrg   imm.d64 = q;
672b8e80941Smrg   return imm;
673b8e80941Smrg}
674b8e80941Smrg
675b8e80941Smrg/** Construct int64_t immediate register */
676b8e80941Smrgstatic inline struct brw_reg
677b8e80941Smrgbrw_imm_uq(uint64_t uq)
678b8e80941Smrg{
679b8e80941Smrg   struct brw_reg imm = brw_imm_reg(BRW_REGISTER_TYPE_UQ);
680b8e80941Smrg   imm.u64 = uq;
681b8e80941Smrg   return imm;
682b8e80941Smrg}
683b8e80941Smrg
684b8e80941Smrg/** Construct integer immediate register */
685b8e80941Smrgstatic inline struct brw_reg
686b8e80941Smrgbrw_imm_d(int d)
687b8e80941Smrg{
688b8e80941Smrg   struct brw_reg imm = brw_imm_reg(BRW_REGISTER_TYPE_D);
689b8e80941Smrg   imm.d = d;
690b8e80941Smrg   return imm;
691b8e80941Smrg}
692b8e80941Smrg
693b8e80941Smrg/** Construct uint immediate register */
694b8e80941Smrgstatic inline struct brw_reg
695b8e80941Smrgbrw_imm_ud(unsigned ud)
696b8e80941Smrg{
697b8e80941Smrg   struct brw_reg imm = brw_imm_reg(BRW_REGISTER_TYPE_UD);
698b8e80941Smrg   imm.ud = ud;
699b8e80941Smrg   return imm;
700b8e80941Smrg}
701b8e80941Smrg
702b8e80941Smrg/** Construct ushort immediate register */
703b8e80941Smrgstatic inline struct brw_reg
704b8e80941Smrgbrw_imm_uw(uint16_t uw)
705b8e80941Smrg{
706b8e80941Smrg   struct brw_reg imm = brw_imm_reg(BRW_REGISTER_TYPE_UW);
707b8e80941Smrg   imm.ud = uw | (uw << 16);
708b8e80941Smrg   return imm;
709b8e80941Smrg}
710b8e80941Smrg
711b8e80941Smrg/** Construct short immediate register */
712b8e80941Smrgstatic inline struct brw_reg
713b8e80941Smrgbrw_imm_w(int16_t w)
714b8e80941Smrg{
715b8e80941Smrg   struct brw_reg imm = brw_imm_reg(BRW_REGISTER_TYPE_W);
716b8e80941Smrg   imm.ud = (uint16_t)w | (uint32_t)(uint16_t)w << 16;
717b8e80941Smrg   return imm;
718b8e80941Smrg}
719b8e80941Smrg
720b8e80941Smrg/* brw_imm_b and brw_imm_ub aren't supported by hardware - the type
721b8e80941Smrg * numbers alias with _V and _VF below:
722b8e80941Smrg */
723b8e80941Smrg
724b8e80941Smrg/** Construct vector of eight signed half-byte values */
725b8e80941Smrgstatic inline struct brw_reg
726b8e80941Smrgbrw_imm_v(unsigned v)
727b8e80941Smrg{
728b8e80941Smrg   struct brw_reg imm = brw_imm_reg(BRW_REGISTER_TYPE_V);
729b8e80941Smrg   imm.ud = v;
730b8e80941Smrg   return imm;
731b8e80941Smrg}
732b8e80941Smrg
733b8e80941Smrg/** Construct vector of eight unsigned half-byte values */
734b8e80941Smrgstatic inline struct brw_reg
735b8e80941Smrgbrw_imm_uv(unsigned uv)
736b8e80941Smrg{
737b8e80941Smrg   struct brw_reg imm = brw_imm_reg(BRW_REGISTER_TYPE_UV);
738b8e80941Smrg   imm.ud = uv;
739b8e80941Smrg   return imm;
740b8e80941Smrg}
741b8e80941Smrg
742b8e80941Smrg/** Construct vector of four 8-bit float values */
743b8e80941Smrgstatic inline struct brw_reg
744b8e80941Smrgbrw_imm_vf(unsigned v)
745b8e80941Smrg{
746b8e80941Smrg   struct brw_reg imm = brw_imm_reg(BRW_REGISTER_TYPE_VF);
747b8e80941Smrg   imm.ud = v;
748b8e80941Smrg   return imm;
749b8e80941Smrg}
750b8e80941Smrg
751b8e80941Smrgstatic inline struct brw_reg
752b8e80941Smrgbrw_imm_vf4(unsigned v0, unsigned v1, unsigned v2, unsigned v3)
753b8e80941Smrg{
754b8e80941Smrg   struct brw_reg imm = brw_imm_reg(BRW_REGISTER_TYPE_VF);
755b8e80941Smrg   imm.vstride = BRW_VERTICAL_STRIDE_0;
756b8e80941Smrg   imm.width = BRW_WIDTH_4;
757b8e80941Smrg   imm.hstride = BRW_HORIZONTAL_STRIDE_1;
758b8e80941Smrg   imm.ud = ((v0 << 0) | (v1 << 8) | (v2 << 16) | (v3 << 24));
759b8e80941Smrg   return imm;
760b8e80941Smrg}
761b8e80941Smrg
762b8e80941Smrg
763b8e80941Smrgstatic inline struct brw_reg
764b8e80941Smrgbrw_address(struct brw_reg reg)
765b8e80941Smrg{
766b8e80941Smrg   return brw_imm_uw(reg.nr * REG_SIZE + reg.subnr);
767b8e80941Smrg}
768b8e80941Smrg
769b8e80941Smrg/** Construct float[1] general-purpose register */
770b8e80941Smrgstatic inline struct brw_reg
771b8e80941Smrgbrw_vec1_grf(unsigned nr, unsigned subnr)
772b8e80941Smrg{
773b8e80941Smrg   return brw_vec1_reg(BRW_GENERAL_REGISTER_FILE, nr, subnr);
774b8e80941Smrg}
775b8e80941Smrg
776b8e80941Smrg/** Construct float[2] general-purpose register */
777b8e80941Smrgstatic inline struct brw_reg
778b8e80941Smrgbrw_vec2_grf(unsigned nr, unsigned subnr)
779b8e80941Smrg{
780b8e80941Smrg   return brw_vec2_reg(BRW_GENERAL_REGISTER_FILE, nr, subnr);
781b8e80941Smrg}
782b8e80941Smrg
783b8e80941Smrg/** Construct float[4] general-purpose register */
784b8e80941Smrgstatic inline struct brw_reg
785b8e80941Smrgbrw_vec4_grf(unsigned nr, unsigned subnr)
786b8e80941Smrg{
787b8e80941Smrg   return brw_vec4_reg(BRW_GENERAL_REGISTER_FILE, nr, subnr);
788b8e80941Smrg}
789b8e80941Smrg
790b8e80941Smrg/** Construct float[8] general-purpose register */
791b8e80941Smrgstatic inline struct brw_reg
792b8e80941Smrgbrw_vec8_grf(unsigned nr, unsigned subnr)
793b8e80941Smrg{
794b8e80941Smrg   return brw_vec8_reg(BRW_GENERAL_REGISTER_FILE, nr, subnr);
795b8e80941Smrg}
796b8e80941Smrg
797b8e80941Smrg/** Construct float[16] general-purpose register */
798b8e80941Smrgstatic inline struct brw_reg
799b8e80941Smrgbrw_vec16_grf(unsigned nr, unsigned subnr)
800b8e80941Smrg{
801b8e80941Smrg   return brw_vec16_reg(BRW_GENERAL_REGISTER_FILE, nr, subnr);
802b8e80941Smrg}
803b8e80941Smrg
804b8e80941Smrgstatic inline struct brw_reg
805b8e80941Smrgbrw_vecn_grf(unsigned width, unsigned nr, unsigned subnr)
806b8e80941Smrg{
807b8e80941Smrg   return brw_vecn_reg(width, BRW_GENERAL_REGISTER_FILE, nr, subnr);
808b8e80941Smrg}
809b8e80941Smrg
810b8e80941Smrg
811b8e80941Smrgstatic inline struct brw_reg
812b8e80941Smrgbrw_uw8_grf(unsigned nr, unsigned subnr)
813b8e80941Smrg{
814b8e80941Smrg   return brw_uw8_reg(BRW_GENERAL_REGISTER_FILE, nr, subnr);
815b8e80941Smrg}
816b8e80941Smrg
817b8e80941Smrgstatic inline struct brw_reg
818b8e80941Smrgbrw_uw16_grf(unsigned nr, unsigned subnr)
819b8e80941Smrg{
820b8e80941Smrg   return brw_uw16_reg(BRW_GENERAL_REGISTER_FILE, nr, subnr);
821b8e80941Smrg}
822b8e80941Smrg
823b8e80941Smrg
824b8e80941Smrg/** Construct null register (usually used for setting condition codes) */
825b8e80941Smrgstatic inline struct brw_reg
826b8e80941Smrgbrw_null_reg(void)
827b8e80941Smrg{
828b8e80941Smrg   return brw_vec8_reg(BRW_ARCHITECTURE_REGISTER_FILE, BRW_ARF_NULL, 0);
829b8e80941Smrg}
830b8e80941Smrg
831b8e80941Smrgstatic inline struct brw_reg
832b8e80941Smrgbrw_null_vec(unsigned width)
833b8e80941Smrg{
834b8e80941Smrg   return brw_vecn_reg(width, BRW_ARCHITECTURE_REGISTER_FILE, BRW_ARF_NULL, 0);
835b8e80941Smrg}
836b8e80941Smrg
837b8e80941Smrgstatic inline struct brw_reg
838b8e80941Smrgbrw_address_reg(unsigned subnr)
839b8e80941Smrg{
840b8e80941Smrg   return brw_uw1_reg(BRW_ARCHITECTURE_REGISTER_FILE, BRW_ARF_ADDRESS, subnr);
841b8e80941Smrg}
842b8e80941Smrg
843b8e80941Smrgstatic inline struct brw_reg
844b8e80941Smrgbrw_tdr_reg(void)
845b8e80941Smrg{
846b8e80941Smrg   return brw_uw1_reg(BRW_ARCHITECTURE_REGISTER_FILE, BRW_ARF_TDR, 0);
847b8e80941Smrg}
848b8e80941Smrg
849b8e80941Smrg/* If/else instructions break in align16 mode if writemask & swizzle
850b8e80941Smrg * aren't xyzw.  This goes against the convention for other scalar
851b8e80941Smrg * regs:
852b8e80941Smrg */
853b8e80941Smrgstatic inline struct brw_reg
854b8e80941Smrgbrw_ip_reg(void)
855b8e80941Smrg{
856b8e80941Smrg   return brw_reg(BRW_ARCHITECTURE_REGISTER_FILE,
857b8e80941Smrg                  BRW_ARF_IP,
858b8e80941Smrg                  0,
859b8e80941Smrg                  0,
860b8e80941Smrg                  0,
861b8e80941Smrg                  BRW_REGISTER_TYPE_UD,
862b8e80941Smrg                  BRW_VERTICAL_STRIDE_4, /* ? */
863b8e80941Smrg                  BRW_WIDTH_1,
864b8e80941Smrg                  BRW_HORIZONTAL_STRIDE_0,
865b8e80941Smrg                  BRW_SWIZZLE_XYZW, /* NOTE! */
866b8e80941Smrg                  WRITEMASK_XYZW); /* NOTE! */
867b8e80941Smrg}
868b8e80941Smrg
869b8e80941Smrgstatic inline struct brw_reg
870b8e80941Smrgbrw_notification_reg(void)
871b8e80941Smrg{
872b8e80941Smrg   return brw_reg(BRW_ARCHITECTURE_REGISTER_FILE,
873b8e80941Smrg                  BRW_ARF_NOTIFICATION_COUNT,
874b8e80941Smrg                  0,
875b8e80941Smrg                  0,
876b8e80941Smrg                  0,
877b8e80941Smrg                  BRW_REGISTER_TYPE_UD,
878b8e80941Smrg                  BRW_VERTICAL_STRIDE_0,
879b8e80941Smrg                  BRW_WIDTH_1,
880b8e80941Smrg                  BRW_HORIZONTAL_STRIDE_0,
881b8e80941Smrg                  BRW_SWIZZLE_XXXX,
882b8e80941Smrg                  WRITEMASK_X);
883b8e80941Smrg}
884b8e80941Smrg
885b8e80941Smrgstatic inline struct brw_reg
886b8e80941Smrgbrw_cr0_reg(unsigned subnr)
887b8e80941Smrg{
888b8e80941Smrg   return brw_ud1_reg(BRW_ARCHITECTURE_REGISTER_FILE, BRW_ARF_CONTROL, subnr);
889b8e80941Smrg}
890b8e80941Smrg
891b8e80941Smrgstatic inline struct brw_reg
892b8e80941Smrgbrw_sr0_reg(unsigned subnr)
893b8e80941Smrg{
894b8e80941Smrg   return brw_ud1_reg(BRW_ARCHITECTURE_REGISTER_FILE, BRW_ARF_STATE, subnr);
895b8e80941Smrg}
896b8e80941Smrg
897b8e80941Smrgstatic inline struct brw_reg
898b8e80941Smrgbrw_acc_reg(unsigned width)
899b8e80941Smrg{
900b8e80941Smrg   return brw_vecn_reg(width, BRW_ARCHITECTURE_REGISTER_FILE,
901b8e80941Smrg                       BRW_ARF_ACCUMULATOR, 0);
902b8e80941Smrg}
903b8e80941Smrg
904b8e80941Smrgstatic inline struct brw_reg
905b8e80941Smrgbrw_flag_reg(int reg, int subreg)
906b8e80941Smrg{
907b8e80941Smrg   return brw_uw1_reg(BRW_ARCHITECTURE_REGISTER_FILE,
908b8e80941Smrg                      BRW_ARF_FLAG + reg, subreg);
909b8e80941Smrg}
910b8e80941Smrg
911b8e80941Smrgstatic inline struct brw_reg
912b8e80941Smrgbrw_flag_subreg(unsigned subreg)
913b8e80941Smrg{
914b8e80941Smrg   return brw_uw1_reg(BRW_ARCHITECTURE_REGISTER_FILE,
915b8e80941Smrg                      BRW_ARF_FLAG + subreg / 2, subreg % 2);
916b8e80941Smrg}
917b8e80941Smrg
918b8e80941Smrg/**
919b8e80941Smrg * Return the mask register present in Gen4-5, or the related register present
920b8e80941Smrg * in Gen7.5 and later hardware referred to as "channel enable" register in
921b8e80941Smrg * the documentation.
922b8e80941Smrg */
923b8e80941Smrgstatic inline struct brw_reg
924b8e80941Smrgbrw_mask_reg(unsigned subnr)
925b8e80941Smrg{
926b8e80941Smrg   return brw_uw1_reg(BRW_ARCHITECTURE_REGISTER_FILE, BRW_ARF_MASK, subnr);
927b8e80941Smrg}
928b8e80941Smrg
929b8e80941Smrgstatic inline struct brw_reg
930b8e80941Smrgbrw_vmask_reg()
931b8e80941Smrg{
932b8e80941Smrg   return brw_sr0_reg(3);
933b8e80941Smrg}
934b8e80941Smrg
935b8e80941Smrgstatic inline struct brw_reg
936b8e80941Smrgbrw_dmask_reg()
937b8e80941Smrg{
938b8e80941Smrg   return brw_sr0_reg(2);
939b8e80941Smrg}
940b8e80941Smrg
941b8e80941Smrgstatic inline struct brw_reg
942b8e80941Smrgbrw_message_reg(unsigned nr)
943b8e80941Smrg{
944b8e80941Smrg   return brw_vec8_reg(BRW_MESSAGE_REGISTER_FILE, nr, 0);
945b8e80941Smrg}
946b8e80941Smrg
947b8e80941Smrgstatic inline struct brw_reg
948b8e80941Smrgbrw_uvec_mrf(unsigned width, unsigned nr, unsigned subnr)
949b8e80941Smrg{
950b8e80941Smrg   return retype(brw_vecn_reg(width, BRW_MESSAGE_REGISTER_FILE, nr, subnr),
951b8e80941Smrg                 BRW_REGISTER_TYPE_UD);
952b8e80941Smrg}
953b8e80941Smrg
954b8e80941Smrg/* This is almost always called with a numeric constant argument, so
955b8e80941Smrg * make things easy to evaluate at compile time:
956b8e80941Smrg */
957b8e80941Smrgstatic inline unsigned cvt(unsigned val)
958b8e80941Smrg{
959b8e80941Smrg   switch (val) {
960b8e80941Smrg   case 0: return 0;
961b8e80941Smrg   case 1: return 1;
962b8e80941Smrg   case 2: return 2;
963b8e80941Smrg   case 4: return 3;
964b8e80941Smrg   case 8: return 4;
965b8e80941Smrg   case 16: return 5;
966b8e80941Smrg   case 32: return 6;
967b8e80941Smrg   }
968b8e80941Smrg   return 0;
969b8e80941Smrg}
970b8e80941Smrg
971b8e80941Smrgstatic inline struct brw_reg
972b8e80941Smrgstride(struct brw_reg reg, unsigned vstride, unsigned width, unsigned hstride)
973b8e80941Smrg{
974b8e80941Smrg   reg.vstride = cvt(vstride);
975b8e80941Smrg   reg.width = cvt(width) - 1;
976b8e80941Smrg   reg.hstride = cvt(hstride);
977b8e80941Smrg   return reg;
978b8e80941Smrg}
979b8e80941Smrg
980b8e80941Smrg/**
981b8e80941Smrg * Multiply the vertical and horizontal stride of a register by the given
982b8e80941Smrg * factor \a s.
983b8e80941Smrg */
984b8e80941Smrgstatic inline struct brw_reg
985b8e80941Smrgspread(struct brw_reg reg, unsigned s)
986b8e80941Smrg{
987b8e80941Smrg   if (s) {
988b8e80941Smrg      assert(_mesa_is_pow_two(s));
989b8e80941Smrg
990b8e80941Smrg      if (reg.hstride)
991b8e80941Smrg         reg.hstride += cvt(s) - 1;
992b8e80941Smrg
993b8e80941Smrg      if (reg.vstride)
994b8e80941Smrg         reg.vstride += cvt(s) - 1;
995b8e80941Smrg
996b8e80941Smrg      return reg;
997b8e80941Smrg   } else {
998b8e80941Smrg      return stride(reg, 0, 1, 0);
999b8e80941Smrg   }
1000b8e80941Smrg}
1001b8e80941Smrg
1002b8e80941Smrg/**
1003b8e80941Smrg * Reinterpret each channel of register \p reg as a vector of values of the
1004b8e80941Smrg * given smaller type and take the i-th subcomponent from each.
1005b8e80941Smrg */
1006b8e80941Smrgstatic inline struct brw_reg
1007b8e80941Smrgsubscript(struct brw_reg reg, enum brw_reg_type type, unsigned i)
1008b8e80941Smrg{
1009b8e80941Smrg   if (reg.file == IMM)
1010b8e80941Smrg      return reg;
1011b8e80941Smrg
1012b8e80941Smrg   unsigned scale = type_sz(reg.type) / type_sz(type);
1013b8e80941Smrg   assert(scale >= 1 && i < scale);
1014b8e80941Smrg
1015b8e80941Smrg   return suboffset(retype(spread(reg, scale), type), i);
1016b8e80941Smrg}
1017b8e80941Smrg
1018b8e80941Smrgstatic inline struct brw_reg
1019b8e80941Smrgvec16(struct brw_reg reg)
1020b8e80941Smrg{
1021b8e80941Smrg   return stride(reg, 16,16,1);
1022b8e80941Smrg}
1023b8e80941Smrg
1024b8e80941Smrgstatic inline struct brw_reg
1025b8e80941Smrgvec8(struct brw_reg reg)
1026b8e80941Smrg{
1027b8e80941Smrg   return stride(reg, 8,8,1);
1028b8e80941Smrg}
1029b8e80941Smrg
1030b8e80941Smrgstatic inline struct brw_reg
1031b8e80941Smrgvec4(struct brw_reg reg)
1032b8e80941Smrg{
1033b8e80941Smrg   return stride(reg, 4,4,1);
1034b8e80941Smrg}
1035b8e80941Smrg
1036b8e80941Smrgstatic inline struct brw_reg
1037b8e80941Smrgvec2(struct brw_reg reg)
1038b8e80941Smrg{
1039b8e80941Smrg   return stride(reg, 2,2,1);
1040b8e80941Smrg}
1041b8e80941Smrg
1042b8e80941Smrgstatic inline struct brw_reg
1043b8e80941Smrgvec1(struct brw_reg reg)
1044b8e80941Smrg{
1045b8e80941Smrg   return stride(reg, 0,1,0);
1046b8e80941Smrg}
1047b8e80941Smrg
1048b8e80941Smrg
1049b8e80941Smrgstatic inline struct brw_reg
1050b8e80941Smrgget_element(struct brw_reg reg, unsigned elt)
1051b8e80941Smrg{
1052b8e80941Smrg   return vec1(suboffset(reg, elt));
1053b8e80941Smrg}
1054b8e80941Smrg
1055b8e80941Smrgstatic inline struct brw_reg
1056b8e80941Smrgget_element_ud(struct brw_reg reg, unsigned elt)
1057b8e80941Smrg{
1058b8e80941Smrg   return vec1(suboffset(retype(reg, BRW_REGISTER_TYPE_UD), elt));
1059b8e80941Smrg}
1060b8e80941Smrg
1061b8e80941Smrgstatic inline struct brw_reg
1062b8e80941Smrgget_element_d(struct brw_reg reg, unsigned elt)
1063b8e80941Smrg{
1064b8e80941Smrg   return vec1(suboffset(retype(reg, BRW_REGISTER_TYPE_D), elt));
1065b8e80941Smrg}
1066b8e80941Smrg
1067b8e80941Smrgstatic inline struct brw_reg
1068b8e80941Smrgbrw_swizzle(struct brw_reg reg, unsigned swz)
1069b8e80941Smrg{
1070b8e80941Smrg   if (reg.file == BRW_IMMEDIATE_VALUE)
1071b8e80941Smrg      reg.ud = brw_swizzle_immediate(reg.type, reg.ud, swz);
1072b8e80941Smrg   else
1073b8e80941Smrg      reg.swizzle = brw_compose_swizzle(swz, reg.swizzle);
1074b8e80941Smrg
1075b8e80941Smrg   return reg;
1076b8e80941Smrg}
1077b8e80941Smrg
1078b8e80941Smrgstatic inline struct brw_reg
1079b8e80941Smrgbrw_writemask(struct brw_reg reg, unsigned mask)
1080b8e80941Smrg{
1081b8e80941Smrg   assert(reg.file != BRW_IMMEDIATE_VALUE);
1082b8e80941Smrg   reg.writemask &= mask;
1083b8e80941Smrg   return reg;
1084b8e80941Smrg}
1085b8e80941Smrg
1086b8e80941Smrgstatic inline struct brw_reg
1087b8e80941Smrgbrw_set_writemask(struct brw_reg reg, unsigned mask)
1088b8e80941Smrg{
1089b8e80941Smrg   assert(reg.file != BRW_IMMEDIATE_VALUE);
1090b8e80941Smrg   reg.writemask = mask;
1091b8e80941Smrg   return reg;
1092b8e80941Smrg}
1093b8e80941Smrg
1094b8e80941Smrgstatic inline unsigned
1095b8e80941Smrgbrw_writemask_for_size(unsigned n)
1096b8e80941Smrg{
1097b8e80941Smrg   return (1 << n) - 1;
1098b8e80941Smrg}
1099b8e80941Smrg
1100b8e80941Smrgstatic inline unsigned
1101b8e80941Smrgbrw_writemask_for_component_packing(unsigned n, unsigned first_component)
1102b8e80941Smrg{
1103b8e80941Smrg   assert(first_component + n <= 4);
1104b8e80941Smrg   return (((1 << n) - 1) << first_component);
1105b8e80941Smrg}
1106b8e80941Smrg
1107b8e80941Smrgstatic inline struct brw_reg
1108b8e80941Smrgnegate(struct brw_reg reg)
1109b8e80941Smrg{
1110b8e80941Smrg   reg.negate ^= 1;
1111b8e80941Smrg   return reg;
1112b8e80941Smrg}
1113b8e80941Smrg
1114b8e80941Smrgstatic inline struct brw_reg
1115b8e80941Smrgbrw_abs(struct brw_reg reg)
1116b8e80941Smrg{
1117b8e80941Smrg   reg.abs = 1;
1118b8e80941Smrg   reg.negate = 0;
1119b8e80941Smrg   return reg;
1120b8e80941Smrg}
1121b8e80941Smrg
1122b8e80941Smrg/************************************************************************/
1123b8e80941Smrg
1124b8e80941Smrgstatic inline struct brw_reg
1125b8e80941Smrgbrw_vec4_indirect(unsigned subnr, int offset)
1126b8e80941Smrg{
1127b8e80941Smrg   struct brw_reg reg =  brw_vec4_grf(0, 0);
1128b8e80941Smrg   reg.subnr = subnr;
1129b8e80941Smrg   reg.address_mode = BRW_ADDRESS_REGISTER_INDIRECT_REGISTER;
1130b8e80941Smrg   reg.indirect_offset = offset;
1131b8e80941Smrg   return reg;
1132b8e80941Smrg}
1133b8e80941Smrg
1134b8e80941Smrgstatic inline struct brw_reg
1135b8e80941Smrgbrw_vec1_indirect(unsigned subnr, int offset)
1136b8e80941Smrg{
1137b8e80941Smrg   struct brw_reg reg =  brw_vec1_grf(0, 0);
1138b8e80941Smrg   reg.subnr = subnr;
1139b8e80941Smrg   reg.address_mode = BRW_ADDRESS_REGISTER_INDIRECT_REGISTER;
1140b8e80941Smrg   reg.indirect_offset = offset;
1141b8e80941Smrg   return reg;
1142b8e80941Smrg}
1143b8e80941Smrg
1144b8e80941Smrgstatic inline struct brw_reg
1145b8e80941Smrgbrw_VxH_indirect(unsigned subnr, int offset)
1146b8e80941Smrg{
1147b8e80941Smrg   struct brw_reg reg = brw_vec1_grf(0, 0);
1148b8e80941Smrg   reg.vstride = BRW_VERTICAL_STRIDE_ONE_DIMENSIONAL;
1149b8e80941Smrg   reg.subnr = subnr;
1150b8e80941Smrg   reg.address_mode = BRW_ADDRESS_REGISTER_INDIRECT_REGISTER;
1151b8e80941Smrg   reg.indirect_offset = offset;
1152b8e80941Smrg   return reg;
1153b8e80941Smrg}
1154b8e80941Smrg
1155b8e80941Smrgstatic inline struct brw_reg
1156b8e80941Smrgderef_4f(struct brw_indirect ptr, int offset)
1157b8e80941Smrg{
1158b8e80941Smrg   return brw_vec4_indirect(ptr.addr_subnr, ptr.addr_offset + offset);
1159b8e80941Smrg}
1160b8e80941Smrg
1161b8e80941Smrgstatic inline struct brw_reg
1162b8e80941Smrgderef_1f(struct brw_indirect ptr, int offset)
1163b8e80941Smrg{
1164b8e80941Smrg   return brw_vec1_indirect(ptr.addr_subnr, ptr.addr_offset + offset);
1165b8e80941Smrg}
1166b8e80941Smrg
1167b8e80941Smrgstatic inline struct brw_reg
1168b8e80941Smrgderef_4b(struct brw_indirect ptr, int offset)
1169b8e80941Smrg{
1170b8e80941Smrg   return retype(deref_4f(ptr, offset), BRW_REGISTER_TYPE_B);
1171b8e80941Smrg}
1172b8e80941Smrg
1173b8e80941Smrgstatic inline struct brw_reg
1174b8e80941Smrgderef_1uw(struct brw_indirect ptr, int offset)
1175b8e80941Smrg{
1176b8e80941Smrg   return retype(deref_1f(ptr, offset), BRW_REGISTER_TYPE_UW);
1177b8e80941Smrg}
1178b8e80941Smrg
1179b8e80941Smrgstatic inline struct brw_reg
1180b8e80941Smrgderef_1d(struct brw_indirect ptr, int offset)
1181b8e80941Smrg{
1182b8e80941Smrg   return retype(deref_1f(ptr, offset), BRW_REGISTER_TYPE_D);
1183b8e80941Smrg}
1184b8e80941Smrg
1185b8e80941Smrgstatic inline struct brw_reg
1186b8e80941Smrgderef_1ud(struct brw_indirect ptr, int offset)
1187b8e80941Smrg{
1188b8e80941Smrg   return retype(deref_1f(ptr, offset), BRW_REGISTER_TYPE_UD);
1189b8e80941Smrg}
1190b8e80941Smrg
1191b8e80941Smrgstatic inline struct brw_reg
1192b8e80941Smrgget_addr_reg(struct brw_indirect ptr)
1193b8e80941Smrg{
1194b8e80941Smrg   return brw_address_reg(ptr.addr_subnr);
1195b8e80941Smrg}
1196b8e80941Smrg
1197b8e80941Smrgstatic inline struct brw_indirect
1198b8e80941Smrgbrw_indirect_offset(struct brw_indirect ptr, int offset)
1199b8e80941Smrg{
1200b8e80941Smrg   ptr.addr_offset += offset;
1201b8e80941Smrg   return ptr;
1202b8e80941Smrg}
1203b8e80941Smrg
1204b8e80941Smrgstatic inline struct brw_indirect
1205b8e80941Smrgbrw_indirect(unsigned addr_subnr, int offset)
1206b8e80941Smrg{
1207b8e80941Smrg   struct brw_indirect ptr;
1208b8e80941Smrg   ptr.addr_subnr = addr_subnr;
1209b8e80941Smrg   ptr.addr_offset = offset;
1210b8e80941Smrg   ptr.pad = 0;
1211b8e80941Smrg   return ptr;
1212b8e80941Smrg}
1213b8e80941Smrg
1214b8e80941Smrgstatic inline bool
1215b8e80941Smrgregion_matches(struct brw_reg reg, enum brw_vertical_stride v,
1216b8e80941Smrg               enum brw_width w, enum brw_horizontal_stride h)
1217b8e80941Smrg{
1218b8e80941Smrg   return reg.vstride == v &&
1219b8e80941Smrg          reg.width == w &&
1220b8e80941Smrg          reg.hstride == h;
1221b8e80941Smrg}
1222b8e80941Smrg
1223b8e80941Smrg#define has_scalar_region(reg) \
1224b8e80941Smrg   region_matches(reg, BRW_VERTICAL_STRIDE_0, BRW_WIDTH_1, \
1225b8e80941Smrg                  BRW_HORIZONTAL_STRIDE_0)
1226b8e80941Smrg
1227b8e80941Smrg/* brw_packed_float.c */
1228b8e80941Smrgint brw_float_to_vf(float f);
1229b8e80941Smrgfloat brw_vf_to_float(unsigned char vf);
1230b8e80941Smrg
1231b8e80941Smrg#ifdef __cplusplus
1232b8e80941Smrg}
1233b8e80941Smrg#endif
1234b8e80941Smrg
1235b8e80941Smrg#endif
1236