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