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