brw_reg.h revision 24be658d13b13fdb8a1977208038b4ba43bce4ac
1/*
2 Copyright (C) Intel Corp.  2006.  All Rights Reserved.
3 Intel funded Tungsten Graphics to
4 develop this 3D driver.
5
6 Permission is hereby granted, free of charge, to any person obtaining
7 a copy of this software and associated documentation files (the
8 "Software"), to deal in the Software without restriction, including
9 without limitation the rights to use, copy, modify, merge, publish,
10 distribute, sublicense, and/or sell copies of the Software, and to
11 permit persons to whom the Software is furnished to do so, subject to
12 the following conditions:
13
14 The above copyright notice and this permission notice (including the
15 next paragraph) shall be included in all copies or substantial
16 portions of the Software.
17
18 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
21 IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
22 LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
23 OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
24 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25
26 **********************************************************************/
27 /*
28  * Authors:
29  *   Keith Whitwell <keithw@vmware.com>
30  */
31
32/** @file brw_reg.h
33 *
34 * This file defines struct brw_reg, which is our representation for EU
35 * registers.  They're not a hardware specific format, just an abstraction
36 * that intends to capture the full flexibility of the hardware registers.
37 *
38 * The brw_eu_emit.c layer's brw_set_dest/brw_set_src[01] functions encode
39 * the abstract brw_reg type into the actual hardware instruction encoding.
40 */
41
42#ifndef BRW_REG_H
43#define BRW_REG_H
44
45#include <stdbool.h>
46#include "main/compiler.h"
47#include "main/macros.h"
48#include "program/prog_instruction.h"
49#include "brw_defines.h"
50
51#ifdef __cplusplus
52extern "C" {
53#endif
54
55struct brw_device_info;
56
57/** Number of general purpose registers (VS, WM, etc) */
58#define BRW_MAX_GRF 128
59
60/**
61 * First GRF used for the MRF hack.
62 *
63 * On gen7, MRFs are no longer used, and contiguous GRFs are used instead.  We
64 * haven't converted our compiler to be aware of this, so it asks for MRFs and
65 * brw_eu_emit.c quietly converts them to be accesses of the top GRFs.  The
66 * register allocators have to be careful of this to avoid corrupting the "MRF"s
67 * with actual GRF allocations.
68 */
69#define GEN7_MRF_HACK_START 112
70
71/** Number of message register file registers */
72#define BRW_MAX_MRF(gen) (gen == 6 ? 24 : 16)
73
74#define BRW_SWIZZLE4(a,b,c,d) (((a)<<0) | ((b)<<2) | ((c)<<4) | ((d)<<6))
75#define BRW_GET_SWZ(swz, idx) (((swz) >> ((idx)*2)) & 0x3)
76
77#define BRW_SWIZZLE_NOOP      BRW_SWIZZLE4(0,1,2,3)
78#define BRW_SWIZZLE_XYZW      BRW_SWIZZLE4(0,1,2,3)
79#define BRW_SWIZZLE_XXXX      BRW_SWIZZLE4(0,0,0,0)
80#define BRW_SWIZZLE_YYYY      BRW_SWIZZLE4(1,1,1,1)
81#define BRW_SWIZZLE_ZZZZ      BRW_SWIZZLE4(2,2,2,2)
82#define BRW_SWIZZLE_WWWW      BRW_SWIZZLE4(3,3,3,3)
83#define BRW_SWIZZLE_XYXY      BRW_SWIZZLE4(0,1,0,1)
84#define BRW_SWIZZLE_YZXW      BRW_SWIZZLE4(1,2,0,3)
85#define BRW_SWIZZLE_ZXYW      BRW_SWIZZLE4(2,0,1,3)
86#define BRW_SWIZZLE_ZWZW      BRW_SWIZZLE4(2,3,2,3)
87#define BRW_SWIZZLE_WZYX      BRW_SWIZZLE4(3,2,1,0)
88
89static inline bool
90brw_is_single_value_swizzle(unsigned swiz)
91{
92   return (swiz == BRW_SWIZZLE_XXXX ||
93           swiz == BRW_SWIZZLE_YYYY ||
94           swiz == BRW_SWIZZLE_ZZZZ ||
95           swiz == BRW_SWIZZLE_WWWW);
96}
97
98/**
99 * Compute the swizzle obtained from the application of \p swz0 on the result
100 * of \p swz1.  The argument ordering is expected to match function
101 * composition.
102 */
103static inline unsigned
104brw_compose_swizzle(unsigned swz0, unsigned swz1)
105{
106   return BRW_SWIZZLE4(
107      BRW_GET_SWZ(swz1, BRW_GET_SWZ(swz0, 0)),
108      BRW_GET_SWZ(swz1, BRW_GET_SWZ(swz0, 1)),
109      BRW_GET_SWZ(swz1, BRW_GET_SWZ(swz0, 2)),
110      BRW_GET_SWZ(swz1, BRW_GET_SWZ(swz0, 3)));
111}
112
113/**
114 * Return the result of applying swizzle \p swz to shuffle the bits of \p mask
115 * (AKA image).
116 */
117static inline unsigned
118brw_apply_swizzle_to_mask(unsigned swz, unsigned mask)
119{
120   unsigned result = 0;
121
122   for (unsigned i = 0; i < 4; i++) {
123      if (mask & (1 << BRW_GET_SWZ(swz, i)))
124         result |= 1 << i;
125   }
126
127   return result;
128}
129
130/**
131 * Return the result of applying the inverse of swizzle \p swz to shuffle the
132 * bits of \p mask (AKA preimage).  Useful to find out which components are
133 * read from a swizzled source given the instruction writemask.
134 */
135static inline unsigned
136brw_apply_inv_swizzle_to_mask(unsigned swz, unsigned mask)
137{
138   unsigned result = 0;
139
140   for (unsigned i = 0; i < 4; i++) {
141      if (mask & (1 << i))
142         result |= 1 << BRW_GET_SWZ(swz, i);
143   }
144
145   return result;
146}
147
148/**
149 * Construct an identity swizzle for the set of enabled channels given by \p
150 * mask.  The result will only reference channels enabled in the provided \p
151 * mask, assuming that \p mask is non-zero.  The constructed swizzle will
152 * satisfy the property that for any instruction OP and any mask:
153 *
154 *    brw_OP(p, brw_writemask(dst, mask),
155 *           brw_swizzle(src, brw_swizzle_for_mask(mask)));
156 *
157 * will be equivalent to the same instruction without swizzle:
158 *
159 *    brw_OP(p, brw_writemask(dst, mask), src);
160 */
161static inline unsigned
162brw_swizzle_for_mask(unsigned mask)
163{
164   unsigned last = (mask ? ffs(mask) - 1 : 0);
165   unsigned swz[4];
166
167   for (unsigned i = 0; i < 4; i++)
168      last = swz[i] = (mask & (1 << i) ? i : last);
169
170   return BRW_SWIZZLE4(swz[0], swz[1], swz[2], swz[3]);
171}
172
173/**
174 * Construct an identity swizzle for the first \p n components of a vector.
175 * When only a subset of channels of a vec4 are used we don't want to
176 * reference the other channels, as that will tell optimization passes that
177 * those other channels are used.
178 */
179static inline unsigned
180brw_swizzle_for_size(unsigned n)
181{
182   return brw_swizzle_for_mask((1 << n) - 1);
183}
184
185/**
186 * Converse of brw_swizzle_for_mask().  Returns the mask of components
187 * accessed by the specified swizzle \p swz.
188 */
189static inline unsigned
190brw_mask_for_swizzle(unsigned swz)
191{
192   return brw_apply_inv_swizzle_to_mask(swz, ~0);
193}
194
195enum PACKED brw_reg_type {
196   BRW_REGISTER_TYPE_UD = 0,
197   BRW_REGISTER_TYPE_D,
198   BRW_REGISTER_TYPE_UW,
199   BRW_REGISTER_TYPE_W,
200   BRW_REGISTER_TYPE_F,
201
202   /** Non-immediates only: @{ */
203   BRW_REGISTER_TYPE_UB,
204   BRW_REGISTER_TYPE_B,
205   /** @} */
206
207   /** Immediates only: @{ */
208   BRW_REGISTER_TYPE_UV, /* Gen6+ */
209   BRW_REGISTER_TYPE_V,
210   BRW_REGISTER_TYPE_VF,
211   /** @} */
212
213   BRW_REGISTER_TYPE_DF, /* Gen7+ (no immediates until Gen8+) */
214
215   /* Gen8+ */
216   BRW_REGISTER_TYPE_HF,
217   BRW_REGISTER_TYPE_UQ,
218   BRW_REGISTER_TYPE_Q,
219};
220
221unsigned brw_reg_type_to_hw_type(const struct brw_device_info *devinfo,
222                                 enum brw_reg_type type, enum brw_reg_file file);
223const char *brw_reg_type_letters(unsigned brw_reg_type);
224
225#define REG_SIZE (8*4)
226
227/* These aren't hardware structs, just something useful for us to pass around:
228 *
229 * Align1 operation has a lot of control over input ranges.  Used in
230 * WM programs to implement shaders decomposed into "channel serial"
231 * or "structure of array" form:
232 */
233struct brw_reg {
234   enum brw_reg_type type:4;
235   enum brw_reg_file file:3;      /* :2 hardware format */
236   unsigned negate:1;             /* source only */
237   unsigned abs:1;                /* source only */
238   unsigned address_mode:1;       /* relative addressing, hopefully! */
239   unsigned pad0:1;
240   unsigned subnr:5;              /* :1 in align16 */
241   unsigned nr:16;
242
243   union {
244      struct {
245         unsigned swizzle:8;      /* src only, align16 only */
246         unsigned writemask:4;    /* dest only, align16 only */
247         int  indirect_offset:10; /* relative addressing offset */
248         unsigned vstride:4;      /* source only */
249         unsigned width:3;        /* src only, align1 only */
250         unsigned hstride:2;      /* align1 only */
251         unsigned pad1:1;
252      };
253
254      float f;
255      int   d;
256      unsigned ud;
257   };
258};
259
260
261struct brw_indirect {
262   unsigned addr_subnr:4;
263   int addr_offset:10;
264   unsigned pad:18;
265};
266
267
268static inline unsigned
269type_sz(unsigned type)
270{
271   switch(type) {
272   case BRW_REGISTER_TYPE_UQ:
273   case BRW_REGISTER_TYPE_Q:
274      return 8;
275   case BRW_REGISTER_TYPE_UD:
276   case BRW_REGISTER_TYPE_D:
277   case BRW_REGISTER_TYPE_F:
278      return 4;
279   case BRW_REGISTER_TYPE_UW:
280   case BRW_REGISTER_TYPE_W:
281      return 2;
282   case BRW_REGISTER_TYPE_UB:
283   case BRW_REGISTER_TYPE_B:
284      return 1;
285   default:
286      return 0;
287   }
288}
289
290static inline bool
291type_is_signed(unsigned type)
292{
293   switch(type) {
294   case BRW_REGISTER_TYPE_D:
295   case BRW_REGISTER_TYPE_W:
296   case BRW_REGISTER_TYPE_F:
297   case BRW_REGISTER_TYPE_B:
298   case BRW_REGISTER_TYPE_V:
299   case BRW_REGISTER_TYPE_VF:
300   case BRW_REGISTER_TYPE_DF:
301   case BRW_REGISTER_TYPE_HF:
302   case BRW_REGISTER_TYPE_Q:
303      return true;
304
305   case BRW_REGISTER_TYPE_UD:
306   case BRW_REGISTER_TYPE_UW:
307   case BRW_REGISTER_TYPE_UB:
308   case BRW_REGISTER_TYPE_UV:
309   case BRW_REGISTER_TYPE_UQ:
310      return false;
311
312   default:
313      unreachable("not reached");
314   }
315}
316
317/**
318 * Construct a brw_reg.
319 * \param file      one of the BRW_x_REGISTER_FILE values
320 * \param nr        register number/index
321 * \param subnr     register sub number
322 * \param negate    register negate modifier
323 * \param abs       register abs modifier
324 * \param type      one of BRW_REGISTER_TYPE_x
325 * \param vstride   one of BRW_VERTICAL_STRIDE_x
326 * \param width     one of BRW_WIDTH_x
327 * \param hstride   one of BRW_HORIZONTAL_STRIDE_x
328 * \param swizzle   one of BRW_SWIZZLE_x
329 * \param writemask WRITEMASK_X/Y/Z/W bitfield
330 */
331static inline struct brw_reg
332brw_reg(enum brw_reg_file file,
333        unsigned nr,
334        unsigned subnr,
335        unsigned negate,
336        unsigned abs,
337        enum brw_reg_type type,
338        unsigned vstride,
339        unsigned width,
340        unsigned hstride,
341        unsigned swizzle,
342        unsigned writemask)
343{
344   struct brw_reg reg;
345   if (file == BRW_GENERAL_REGISTER_FILE)
346      assert(nr < BRW_MAX_GRF);
347   else if (file == BRW_ARCHITECTURE_REGISTER_FILE)
348      assert(nr <= BRW_ARF_TIMESTAMP);
349   /* Asserting on the MRF register number requires to know the hardware gen
350    * (gen6 has 24 MRF registers), which we don't know here, so we assert
351    * for that in the generators and in brw_eu_emit.c
352    */
353
354   reg.type = type;
355   reg.file = file;
356   reg.negate = negate;
357   reg.abs = abs;
358   reg.address_mode = BRW_ADDRESS_DIRECT;
359   reg.pad0 = 0;
360   reg.subnr = subnr * type_sz(type);
361   reg.nr = nr;
362
363   /* Could do better: If the reg is r5.3<0;1,0>, we probably want to
364    * set swizzle and writemask to W, as the lower bits of subnr will
365    * be lost when converted to align16.  This is probably too much to
366    * keep track of as you'd want it adjusted by suboffset(), etc.
367    * Perhaps fix up when converting to align16?
368    */
369   reg.swizzle = swizzle;
370   reg.writemask = writemask;
371   reg.indirect_offset = 0;
372   reg.vstride = vstride;
373   reg.width = width;
374   reg.hstride = hstride;
375   reg.pad1 = 0;
376   return reg;
377}
378
379/** Construct float[16] register */
380static inline struct brw_reg
381brw_vec16_reg(enum brw_reg_file file, unsigned nr, unsigned subnr)
382{
383   return brw_reg(file,
384                  nr,
385                  subnr,
386                  0,
387                  0,
388                  BRW_REGISTER_TYPE_F,
389                  BRW_VERTICAL_STRIDE_16,
390                  BRW_WIDTH_16,
391                  BRW_HORIZONTAL_STRIDE_1,
392                  BRW_SWIZZLE_XYZW,
393                  WRITEMASK_XYZW);
394}
395
396/** Construct float[8] register */
397static inline struct brw_reg
398brw_vec8_reg(enum brw_reg_file file, unsigned nr, unsigned subnr)
399{
400   return brw_reg(file,
401                  nr,
402                  subnr,
403                  0,
404                  0,
405                  BRW_REGISTER_TYPE_F,
406                  BRW_VERTICAL_STRIDE_8,
407                  BRW_WIDTH_8,
408                  BRW_HORIZONTAL_STRIDE_1,
409                  BRW_SWIZZLE_XYZW,
410                  WRITEMASK_XYZW);
411}
412
413/** Construct float[4] register */
414static inline struct brw_reg
415brw_vec4_reg(enum brw_reg_file file, unsigned nr, unsigned subnr)
416{
417   return brw_reg(file,
418                  nr,
419                  subnr,
420                  0,
421                  0,
422                  BRW_REGISTER_TYPE_F,
423                  BRW_VERTICAL_STRIDE_4,
424                  BRW_WIDTH_4,
425                  BRW_HORIZONTAL_STRIDE_1,
426                  BRW_SWIZZLE_XYZW,
427                  WRITEMASK_XYZW);
428}
429
430/** Construct float[2] register */
431static inline struct brw_reg
432brw_vec2_reg(enum brw_reg_file file, unsigned nr, unsigned subnr)
433{
434   return brw_reg(file,
435                  nr,
436                  subnr,
437                  0,
438                  0,
439                  BRW_REGISTER_TYPE_F,
440                  BRW_VERTICAL_STRIDE_2,
441                  BRW_WIDTH_2,
442                  BRW_HORIZONTAL_STRIDE_1,
443                  BRW_SWIZZLE_XYXY,
444                  WRITEMASK_XY);
445}
446
447/** Construct float[1] register */
448static inline struct brw_reg
449brw_vec1_reg(enum brw_reg_file file, unsigned nr, unsigned subnr)
450{
451   return brw_reg(file,
452                  nr,
453                  subnr,
454                  0,
455                  0,
456                  BRW_REGISTER_TYPE_F,
457                  BRW_VERTICAL_STRIDE_0,
458                  BRW_WIDTH_1,
459                  BRW_HORIZONTAL_STRIDE_0,
460                  BRW_SWIZZLE_XXXX,
461                  WRITEMASK_X);
462}
463
464static inline struct brw_reg
465brw_vecn_reg(unsigned width, enum brw_reg_file file,
466             unsigned nr, unsigned subnr)
467{
468   switch (width) {
469   case 1:
470      return brw_vec1_reg(file, nr, subnr);
471   case 2:
472      return brw_vec2_reg(file, nr, subnr);
473   case 4:
474      return brw_vec4_reg(file, nr, subnr);
475   case 8:
476      return brw_vec8_reg(file, nr, subnr);
477   case 16:
478      return brw_vec16_reg(file, nr, subnr);
479   default:
480      unreachable("Invalid register width");
481   }
482}
483
484static inline struct brw_reg
485retype(struct brw_reg reg, enum brw_reg_type type)
486{
487   reg.type = type;
488   return reg;
489}
490
491static inline struct brw_reg
492firsthalf(struct brw_reg reg)
493{
494   return reg;
495}
496
497static inline struct brw_reg
498sechalf(struct brw_reg reg)
499{
500   if (reg.vstride)
501      reg.nr++;
502   return reg;
503}
504
505static inline struct brw_reg
506suboffset(struct brw_reg reg, unsigned delta)
507{
508   reg.subnr += delta * type_sz(reg.type);
509   return reg;
510}
511
512
513static inline struct brw_reg
514offset(struct brw_reg reg, unsigned delta)
515{
516   reg.nr += delta;
517   return reg;
518}
519
520
521static inline struct brw_reg
522byte_offset(struct brw_reg reg, unsigned bytes)
523{
524   unsigned newoffset = reg.nr * REG_SIZE + reg.subnr + bytes;
525   reg.nr = newoffset / REG_SIZE;
526   reg.subnr = newoffset % REG_SIZE;
527   return reg;
528}
529
530
531/** Construct unsigned word[16] register */
532static inline struct brw_reg
533brw_uw16_reg(enum brw_reg_file file, unsigned nr, unsigned subnr)
534{
535   return suboffset(retype(brw_vec16_reg(file, nr, 0), BRW_REGISTER_TYPE_UW), subnr);
536}
537
538/** Construct unsigned word[8] register */
539static inline struct brw_reg
540brw_uw8_reg(enum brw_reg_file file, unsigned nr, unsigned subnr)
541{
542   return suboffset(retype(brw_vec8_reg(file, nr, 0), BRW_REGISTER_TYPE_UW), subnr);
543}
544
545/** Construct unsigned word[1] register */
546static inline struct brw_reg
547brw_uw1_reg(enum brw_reg_file file, unsigned nr, unsigned subnr)
548{
549   return suboffset(retype(brw_vec1_reg(file, nr, 0), BRW_REGISTER_TYPE_UW), subnr);
550}
551
552static inline struct brw_reg
553brw_imm_reg(enum brw_reg_type type)
554{
555   return brw_reg(BRW_IMMEDIATE_VALUE,
556                  0,
557                  0,
558                  0,
559                  0,
560                  type,
561                  BRW_VERTICAL_STRIDE_0,
562                  BRW_WIDTH_1,
563                  BRW_HORIZONTAL_STRIDE_0,
564                  0,
565                  0);
566}
567
568/** Construct float immediate register */
569static inline struct brw_reg
570brw_imm_f(float f)
571{
572   struct brw_reg imm = brw_imm_reg(BRW_REGISTER_TYPE_F);
573   imm.f = f;
574   return imm;
575}
576
577/** Construct integer immediate register */
578static inline struct brw_reg
579brw_imm_d(int d)
580{
581   struct brw_reg imm = brw_imm_reg(BRW_REGISTER_TYPE_D);
582   imm.d = d;
583   return imm;
584}
585
586/** Construct uint immediate register */
587static inline struct brw_reg
588brw_imm_ud(unsigned ud)
589{
590   struct brw_reg imm = brw_imm_reg(BRW_REGISTER_TYPE_UD);
591   imm.ud = ud;
592   return imm;
593}
594
595/** Construct ushort immediate register */
596static inline struct brw_reg
597brw_imm_uw(uint16_t uw)
598{
599   struct brw_reg imm = brw_imm_reg(BRW_REGISTER_TYPE_UW);
600   imm.ud = uw | (uw << 16);
601   return imm;
602}
603
604/** Construct short immediate register */
605static inline struct brw_reg
606brw_imm_w(int16_t w)
607{
608   struct brw_reg imm = brw_imm_reg(BRW_REGISTER_TYPE_W);
609   imm.d = w | (w << 16);
610   return imm;
611}
612
613/* brw_imm_b and brw_imm_ub aren't supported by hardware - the type
614 * numbers alias with _V and _VF below:
615 */
616
617/** Construct vector of eight signed half-byte values */
618static inline struct brw_reg
619brw_imm_v(unsigned v)
620{
621   struct brw_reg imm = brw_imm_reg(BRW_REGISTER_TYPE_V);
622   imm.ud = v;
623   return imm;
624}
625
626/** Construct vector of eight unsigned half-byte values */
627static inline struct brw_reg
628brw_imm_uv(unsigned uv)
629{
630   struct brw_reg imm = brw_imm_reg(BRW_REGISTER_TYPE_UV);
631   imm.ud = uv;
632   return imm;
633}
634
635/** Construct vector of four 8-bit float values */
636static inline struct brw_reg
637brw_imm_vf(unsigned v)
638{
639   struct brw_reg imm = brw_imm_reg(BRW_REGISTER_TYPE_VF);
640   imm.ud = v;
641   return imm;
642}
643
644static inline struct brw_reg
645brw_imm_vf4(unsigned v0, unsigned v1, unsigned v2, unsigned v3)
646{
647   struct brw_reg imm = brw_imm_reg(BRW_REGISTER_TYPE_VF);
648   imm.vstride = BRW_VERTICAL_STRIDE_0;
649   imm.width = BRW_WIDTH_4;
650   imm.hstride = BRW_HORIZONTAL_STRIDE_1;
651   imm.ud = ((v0 << 0) | (v1 << 8) | (v2 << 16) | (v3 << 24));
652   return imm;
653}
654
655
656static inline struct brw_reg
657brw_address(struct brw_reg reg)
658{
659   return brw_imm_uw(reg.nr * REG_SIZE + reg.subnr);
660}
661
662/** Construct float[1] general-purpose register */
663static inline struct brw_reg
664brw_vec1_grf(unsigned nr, unsigned subnr)
665{
666   return brw_vec1_reg(BRW_GENERAL_REGISTER_FILE, nr, subnr);
667}
668
669/** Construct float[2] general-purpose register */
670static inline struct brw_reg
671brw_vec2_grf(unsigned nr, unsigned subnr)
672{
673   return brw_vec2_reg(BRW_GENERAL_REGISTER_FILE, nr, subnr);
674}
675
676/** Construct float[4] general-purpose register */
677static inline struct brw_reg
678brw_vec4_grf(unsigned nr, unsigned subnr)
679{
680   return brw_vec4_reg(BRW_GENERAL_REGISTER_FILE, nr, subnr);
681}
682
683/** Construct float[8] general-purpose register */
684static inline struct brw_reg
685brw_vec8_grf(unsigned nr, unsigned subnr)
686{
687   return brw_vec8_reg(BRW_GENERAL_REGISTER_FILE, nr, subnr);
688}
689
690/** Construct float[16] general-purpose register */
691static inline struct brw_reg
692brw_vec16_grf(unsigned nr, unsigned subnr)
693{
694   return brw_vec16_reg(BRW_GENERAL_REGISTER_FILE, nr, subnr);
695}
696
697
698static inline struct brw_reg
699brw_uw8_grf(unsigned nr, unsigned subnr)
700{
701   return brw_uw8_reg(BRW_GENERAL_REGISTER_FILE, nr, subnr);
702}
703
704static inline struct brw_reg
705brw_uw16_grf(unsigned nr, unsigned subnr)
706{
707   return brw_uw16_reg(BRW_GENERAL_REGISTER_FILE, nr, subnr);
708}
709
710
711/** Construct null register (usually used for setting condition codes) */
712static inline struct brw_reg
713brw_null_reg(void)
714{
715   return brw_vec8_reg(BRW_ARCHITECTURE_REGISTER_FILE, BRW_ARF_NULL, 0);
716}
717
718static inline struct brw_reg
719brw_null_vec(unsigned width)
720{
721   return brw_vecn_reg(width, BRW_ARCHITECTURE_REGISTER_FILE, BRW_ARF_NULL, 0);
722}
723
724static inline struct brw_reg
725brw_address_reg(unsigned subnr)
726{
727   return brw_uw1_reg(BRW_ARCHITECTURE_REGISTER_FILE, BRW_ARF_ADDRESS, subnr);
728}
729
730/* If/else instructions break in align16 mode if writemask & swizzle
731 * aren't xyzw.  This goes against the convention for other scalar
732 * regs:
733 */
734static inline struct brw_reg
735brw_ip_reg(void)
736{
737   return brw_reg(BRW_ARCHITECTURE_REGISTER_FILE,
738                  BRW_ARF_IP,
739                  0,
740                  0,
741                  0,
742                  BRW_REGISTER_TYPE_UD,
743                  BRW_VERTICAL_STRIDE_4, /* ? */
744                  BRW_WIDTH_1,
745                  BRW_HORIZONTAL_STRIDE_0,
746                  BRW_SWIZZLE_XYZW, /* NOTE! */
747                  WRITEMASK_XYZW); /* NOTE! */
748}
749
750static inline struct brw_reg
751brw_notification_reg(void)
752{
753   return brw_reg(BRW_ARCHITECTURE_REGISTER_FILE,
754                  BRW_ARF_NOTIFICATION_COUNT,
755                  0,
756                  0,
757                  0,
758                  BRW_REGISTER_TYPE_UD,
759                  BRW_VERTICAL_STRIDE_0,
760                  BRW_WIDTH_1,
761                  BRW_HORIZONTAL_STRIDE_0,
762                  BRW_SWIZZLE_XXXX,
763                  WRITEMASK_X);
764}
765
766static inline struct brw_reg
767brw_acc_reg(unsigned width)
768{
769   return brw_vecn_reg(width, BRW_ARCHITECTURE_REGISTER_FILE,
770                       BRW_ARF_ACCUMULATOR, 0);
771}
772
773static inline struct brw_reg
774brw_flag_reg(int reg, int subreg)
775{
776   return brw_uw1_reg(BRW_ARCHITECTURE_REGISTER_FILE,
777                      BRW_ARF_FLAG + reg, subreg);
778}
779
780/**
781 * Return the mask register present in Gen4-5, or the related register present
782 * in Gen7.5 and later hardware referred to as "channel enable" register in
783 * the documentation.
784 */
785static inline struct brw_reg
786brw_mask_reg(unsigned subnr)
787{
788   return brw_uw1_reg(BRW_ARCHITECTURE_REGISTER_FILE, BRW_ARF_MASK, subnr);
789}
790
791static inline struct brw_reg
792brw_message_reg(unsigned nr)
793{
794   return brw_vec8_reg(BRW_MESSAGE_REGISTER_FILE, nr, 0);
795}
796
797static inline struct brw_reg
798brw_uvec_mrf(unsigned width, unsigned nr, unsigned subnr)
799{
800   return retype(brw_vecn_reg(width, BRW_MESSAGE_REGISTER_FILE, nr, subnr),
801                 BRW_REGISTER_TYPE_UD);
802}
803
804/* This is almost always called with a numeric constant argument, so
805 * make things easy to evaluate at compile time:
806 */
807static inline unsigned cvt(unsigned val)
808{
809   switch (val) {
810   case 0: return 0;
811   case 1: return 1;
812   case 2: return 2;
813   case 4: return 3;
814   case 8: return 4;
815   case 16: return 5;
816   case 32: return 6;
817   }
818   return 0;
819}
820
821static inline struct brw_reg
822stride(struct brw_reg reg, unsigned vstride, unsigned width, unsigned hstride)
823{
824   reg.vstride = cvt(vstride);
825   reg.width = cvt(width) - 1;
826   reg.hstride = cvt(hstride);
827   return reg;
828}
829
830/**
831 * Multiply the vertical and horizontal stride of a register by the given
832 * factor \a s.
833 */
834static inline struct brw_reg
835spread(struct brw_reg reg, unsigned s)
836{
837   if (s) {
838      assert(_mesa_is_pow_two(s));
839
840      if (reg.hstride)
841         reg.hstride += cvt(s) - 1;
842
843      if (reg.vstride)
844         reg.vstride += cvt(s) - 1;
845
846      return reg;
847   } else {
848      return stride(reg, 0, 1, 0);
849   }
850}
851
852static inline struct brw_reg
853vec16(struct brw_reg reg)
854{
855   return stride(reg, 16,16,1);
856}
857
858static inline struct brw_reg
859vec8(struct brw_reg reg)
860{
861   return stride(reg, 8,8,1);
862}
863
864static inline struct brw_reg
865vec4(struct brw_reg reg)
866{
867   return stride(reg, 4,4,1);
868}
869
870static inline struct brw_reg
871vec2(struct brw_reg reg)
872{
873   return stride(reg, 2,2,1);
874}
875
876static inline struct brw_reg
877vec1(struct brw_reg reg)
878{
879   return stride(reg, 0,1,0);
880}
881
882
883static inline struct brw_reg
884get_element(struct brw_reg reg, unsigned elt)
885{
886   return vec1(suboffset(reg, elt));
887}
888
889static inline struct brw_reg
890get_element_ud(struct brw_reg reg, unsigned elt)
891{
892   return vec1(suboffset(retype(reg, BRW_REGISTER_TYPE_UD), elt));
893}
894
895static inline struct brw_reg
896get_element_d(struct brw_reg reg, unsigned elt)
897{
898   return vec1(suboffset(retype(reg, BRW_REGISTER_TYPE_D), elt));
899}
900
901
902static inline struct brw_reg
903brw_swizzle(struct brw_reg reg, unsigned x, unsigned y, unsigned z, unsigned w)
904{
905   assert(reg.file != BRW_IMMEDIATE_VALUE);
906
907   reg.swizzle = brw_compose_swizzle(BRW_SWIZZLE4(x, y, z, w),
908                                              reg.swizzle);
909   return reg;
910}
911
912
913static inline struct brw_reg
914brw_swizzle1(struct brw_reg reg, unsigned x)
915{
916   return brw_swizzle(reg, x, x, x, x);
917}
918
919static inline struct brw_reg
920brw_writemask(struct brw_reg reg, unsigned mask)
921{
922   assert(reg.file != BRW_IMMEDIATE_VALUE);
923   reg.writemask &= mask;
924   return reg;
925}
926
927static inline struct brw_reg
928brw_set_writemask(struct brw_reg reg, unsigned mask)
929{
930   assert(reg.file != BRW_IMMEDIATE_VALUE);
931   reg.writemask = mask;
932   return reg;
933}
934
935static inline unsigned
936brw_writemask_for_size(unsigned n)
937{
938   return (1 << n) - 1;
939}
940
941static inline struct brw_reg
942negate(struct brw_reg reg)
943{
944   reg.negate ^= 1;
945   return reg;
946}
947
948static inline struct brw_reg
949brw_abs(struct brw_reg reg)
950{
951   reg.abs = 1;
952   reg.negate = 0;
953   return reg;
954}
955
956/************************************************************************/
957
958static inline struct brw_reg
959brw_vec4_indirect(unsigned subnr, int offset)
960{
961   struct brw_reg reg =  brw_vec4_grf(0, 0);
962   reg.subnr = subnr;
963   reg.address_mode = BRW_ADDRESS_REGISTER_INDIRECT_REGISTER;
964   reg.indirect_offset = offset;
965   return reg;
966}
967
968static inline struct brw_reg
969brw_vec1_indirect(unsigned subnr, int offset)
970{
971   struct brw_reg reg =  brw_vec1_grf(0, 0);
972   reg.subnr = subnr;
973   reg.address_mode = BRW_ADDRESS_REGISTER_INDIRECT_REGISTER;
974   reg.indirect_offset = offset;
975   return reg;
976}
977
978static inline struct brw_reg
979brw_VxH_indirect(unsigned subnr, int offset)
980{
981   struct brw_reg reg = brw_vec1_grf(0, 0);
982   reg.vstride = BRW_VERTICAL_STRIDE_ONE_DIMENSIONAL;
983   reg.subnr = subnr;
984   reg.address_mode = BRW_ADDRESS_REGISTER_INDIRECT_REGISTER;
985   reg.indirect_offset = offset;
986   return reg;
987}
988
989static inline struct brw_reg
990deref_4f(struct brw_indirect ptr, int offset)
991{
992   return brw_vec4_indirect(ptr.addr_subnr, ptr.addr_offset + offset);
993}
994
995static inline struct brw_reg
996deref_1f(struct brw_indirect ptr, int offset)
997{
998   return brw_vec1_indirect(ptr.addr_subnr, ptr.addr_offset + offset);
999}
1000
1001static inline struct brw_reg
1002deref_4b(struct brw_indirect ptr, int offset)
1003{
1004   return retype(deref_4f(ptr, offset), BRW_REGISTER_TYPE_B);
1005}
1006
1007static inline struct brw_reg
1008deref_1uw(struct brw_indirect ptr, int offset)
1009{
1010   return retype(deref_1f(ptr, offset), BRW_REGISTER_TYPE_UW);
1011}
1012
1013static inline struct brw_reg
1014deref_1d(struct brw_indirect ptr, int offset)
1015{
1016   return retype(deref_1f(ptr, offset), BRW_REGISTER_TYPE_D);
1017}
1018
1019static inline struct brw_reg
1020deref_1ud(struct brw_indirect ptr, int offset)
1021{
1022   return retype(deref_1f(ptr, offset), BRW_REGISTER_TYPE_UD);
1023}
1024
1025static inline struct brw_reg
1026get_addr_reg(struct brw_indirect ptr)
1027{
1028   return brw_address_reg(ptr.addr_subnr);
1029}
1030
1031static inline struct brw_indirect
1032brw_indirect_offset(struct brw_indirect ptr, int offset)
1033{
1034   ptr.addr_offset += offset;
1035   return ptr;
1036}
1037
1038static inline struct brw_indirect
1039brw_indirect(unsigned addr_subnr, int offset)
1040{
1041   struct brw_indirect ptr;
1042   ptr.addr_subnr = addr_subnr;
1043   ptr.addr_offset = offset;
1044   ptr.pad = 0;
1045   return ptr;
1046}
1047
1048static inline bool
1049region_matches(struct brw_reg reg, enum brw_vertical_stride v,
1050               enum brw_width w, enum brw_horizontal_stride h)
1051{
1052   return reg.vstride == v &&
1053          reg.width == w &&
1054          reg.hstride == h;
1055}
1056
1057#define has_scalar_region(reg) \
1058   region_matches(reg, BRW_VERTICAL_STRIDE_0, BRW_WIDTH_1, \
1059                  BRW_HORIZONTAL_STRIDE_0)
1060
1061/* brw_packed_float.c */
1062int brw_float_to_vf(float f);
1063float brw_vf_to_float(unsigned char vf);
1064
1065#ifdef __cplusplus
1066}
1067#endif
1068
1069#endif
1070