xref: /aosp_15_r20/external/mesa3d/src/intel/compiler/elk/elk_reg.h (revision 6104692788411f58d303aa86923a9ff6ecaded22)
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 <[email protected]>
30   */
31 
32 /** @file elk_reg.h
33  *
34  * This file defines struct elk_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 elk_eu_emit.c layer's elk_set_dest/elk_set_src[01] functions encode
39  * the abstract elk_reg type into the actual hardware instruction encoding.
40  */
41 
42 #ifndef ELK_REG_H
43 #define ELK_REG_H
44 
45 #include <stdbool.h>
46 #include "util/compiler.h"
47 #include "util/glheader.h"
48 #include "util/macros.h"
49 #include "util/rounding.h"
50 #include "util/u_math.h"
51 #include "elk_eu_defines.h"
52 #include "elk_reg_type.h"
53 
54 #ifdef __cplusplus
55 extern "C" {
56 #endif
57 
58 struct intel_device_info;
59 
60 /** Size of general purpose register space in REG_SIZE units */
61 #define ELK_MAX_GRF 128
62 #define XE2_MAX_GRF 256
63 
64 /**
65  * First GRF used for the MRF hack.
66  *
67  * On gfx7, MRFs are no longer used, and contiguous GRFs are used instead.  We
68  * haven't converted our compiler to be aware of this, so it asks for MRFs and
69  * elk_eu_emit.c quietly converts them to be accesses of the top GRFs.  The
70  * register allocators have to be careful of this to avoid corrupting the "MRF"s
71  * with actual GRF allocations.
72  */
73 #define GFX7_MRF_HACK_START 112
74 
75 /**
76  * BRW hardware swizzles.
77  * Only defines XYZW to ensure it can be contained in 2 bits
78  */
79 #define ELK_SWIZZLE_X 0
80 #define ELK_SWIZZLE_Y 1
81 #define ELK_SWIZZLE_Z 2
82 #define ELK_SWIZZLE_W 3
83 
84 /** Number of message register file registers */
85 #define ELK_MAX_MRF(gen) (gen == 6 ? 24 : 16)
86 
87 #define ELK_SWIZZLE4(a,b,c,d) (((a)<<0) | ((b)<<2) | ((c)<<4) | ((d)<<6))
88 #define ELK_GET_SWZ(swz, idx) (((swz) >> ((idx)*2)) & 0x3)
89 
90 #define ELK_SWIZZLE_NOOP      ELK_SWIZZLE4(0,1,2,3)
91 #define ELK_SWIZZLE_XYZW      ELK_SWIZZLE4(0,1,2,3)
92 #define ELK_SWIZZLE_XXXX      ELK_SWIZZLE4(0,0,0,0)
93 #define ELK_SWIZZLE_YYYY      ELK_SWIZZLE4(1,1,1,1)
94 #define ELK_SWIZZLE_ZZZZ      ELK_SWIZZLE4(2,2,2,2)
95 #define ELK_SWIZZLE_WWWW      ELK_SWIZZLE4(3,3,3,3)
96 #define ELK_SWIZZLE_XYXY      ELK_SWIZZLE4(0,1,0,1)
97 #define ELK_SWIZZLE_YXYX      ELK_SWIZZLE4(1,0,1,0)
98 #define ELK_SWIZZLE_XZXZ      ELK_SWIZZLE4(0,2,0,2)
99 #define ELK_SWIZZLE_YZXW      ELK_SWIZZLE4(1,2,0,3)
100 #define ELK_SWIZZLE_YWYW      ELK_SWIZZLE4(1,3,1,3)
101 #define ELK_SWIZZLE_ZXYW      ELK_SWIZZLE4(2,0,1,3)
102 #define ELK_SWIZZLE_ZWZW      ELK_SWIZZLE4(2,3,2,3)
103 #define ELK_SWIZZLE_WZWZ      ELK_SWIZZLE4(3,2,3,2)
104 #define ELK_SWIZZLE_WZYX      ELK_SWIZZLE4(3,2,1,0)
105 #define ELK_SWIZZLE_XXZZ      ELK_SWIZZLE4(0,0,2,2)
106 #define ELK_SWIZZLE_YYWW      ELK_SWIZZLE4(1,1,3,3)
107 #define ELK_SWIZZLE_YXWZ      ELK_SWIZZLE4(1,0,3,2)
108 
109 #define ELK_SWZ_COMP_INPUT(comp) (ELK_SWIZZLE_XYZW >> ((comp)*2))
110 #define ELK_SWZ_COMP_OUTPUT(comp) (ELK_SWIZZLE_XYZW << ((comp)*2))
111 
112 static inline bool
elk_is_single_value_swizzle(unsigned swiz)113 elk_is_single_value_swizzle(unsigned swiz)
114 {
115    return (swiz == ELK_SWIZZLE_XXXX ||
116            swiz == ELK_SWIZZLE_YYYY ||
117            swiz == ELK_SWIZZLE_ZZZZ ||
118            swiz == ELK_SWIZZLE_WWWW);
119 }
120 
121 /**
122  * Compute the swizzle obtained from the application of \p swz0 on the result
123  * of \p swz1.  The argument ordering is expected to match function
124  * composition.
125  */
126 static inline unsigned
elk_compose_swizzle(unsigned swz0,unsigned swz1)127 elk_compose_swizzle(unsigned swz0, unsigned swz1)
128 {
129    return ELK_SWIZZLE4(
130       ELK_GET_SWZ(swz1, ELK_GET_SWZ(swz0, 0)),
131       ELK_GET_SWZ(swz1, ELK_GET_SWZ(swz0, 1)),
132       ELK_GET_SWZ(swz1, ELK_GET_SWZ(swz0, 2)),
133       ELK_GET_SWZ(swz1, ELK_GET_SWZ(swz0, 3)));
134 }
135 
136 /**
137  * Return the result of applying swizzle \p swz to shuffle the bits of \p mask
138  * (AKA image).
139  */
140 static inline unsigned
elk_apply_swizzle_to_mask(unsigned swz,unsigned mask)141 elk_apply_swizzle_to_mask(unsigned swz, unsigned mask)
142 {
143    unsigned result = 0;
144 
145    for (unsigned i = 0; i < 4; i++) {
146       if (mask & (1 << ELK_GET_SWZ(swz, i)))
147          result |= 1 << i;
148    }
149 
150    return result;
151 }
152 
153 /**
154  * Return the result of applying the inverse of swizzle \p swz to shuffle the
155  * bits of \p mask (AKA preimage).  Useful to find out which components are
156  * read from a swizzled source given the instruction writemask.
157  */
158 static inline unsigned
elk_apply_inv_swizzle_to_mask(unsigned swz,unsigned mask)159 elk_apply_inv_swizzle_to_mask(unsigned swz, unsigned mask)
160 {
161    unsigned result = 0;
162 
163    for (unsigned i = 0; i < 4; i++) {
164       if (mask & (1 << i))
165          result |= 1 << ELK_GET_SWZ(swz, i);
166    }
167 
168    return result;
169 }
170 
171 /**
172  * Construct an identity swizzle for the set of enabled channels given by \p
173  * mask.  The result will only reference channels enabled in the provided \p
174  * mask, assuming that \p mask is non-zero.  The constructed swizzle will
175  * satisfy the property that for any instruction OP and any mask:
176  *
177  *    elk_OP(p, elk_writemask(dst, mask),
178  *           elk_swizzle(src, elk_swizzle_for_mask(mask)));
179  *
180  * will be equivalent to the same instruction without swizzle:
181  *
182  *    elk_OP(p, elk_writemask(dst, mask), src);
183  */
184 static inline unsigned
elk_swizzle_for_mask(unsigned mask)185 elk_swizzle_for_mask(unsigned mask)
186 {
187    unsigned last = (mask ? ffs(mask) - 1 : 0);
188    unsigned swz[4];
189 
190    for (unsigned i = 0; i < 4; i++)
191       last = swz[i] = (mask & (1 << i) ? i : last);
192 
193    return ELK_SWIZZLE4(swz[0], swz[1], swz[2], swz[3]);
194 }
195 
196 /**
197  * Construct an identity swizzle for the first \p n components of a vector.
198  * When only a subset of channels of a vec4 are used we don't want to
199  * reference the other channels, as that will tell optimization passes that
200  * those other channels are used.
201  */
202 static inline unsigned
elk_swizzle_for_size(unsigned n)203 elk_swizzle_for_size(unsigned n)
204 {
205    return elk_swizzle_for_mask((1 << n) - 1);
206 }
207 
208 /**
209  * Converse of elk_swizzle_for_mask().  Returns the mask of components
210  * accessed by the specified swizzle \p swz.
211  */
212 static inline unsigned
elk_mask_for_swizzle(unsigned swz)213 elk_mask_for_swizzle(unsigned swz)
214 {
215    return elk_apply_inv_swizzle_to_mask(swz, ~0);
216 }
217 
218 uint32_t elk_swizzle_immediate(enum elk_reg_type type, uint32_t x, unsigned swz);
219 
220 #define REG_SIZE (8*4)
221 
222 /* These aren't hardware structs, just something useful for us to pass around:
223  *
224  * Align1 operation has a lot of control over input ranges.  Used in
225  * WM programs to implement shaders decomposed into "channel serial"
226  * or "structure of array" form:
227  */
228 struct elk_reg {
229    union {
230       struct {
231          enum elk_reg_type type:4;
232          enum elk_reg_file file:3;      /* :2 hardware format */
233          unsigned negate:1;             /* source only */
234          unsigned abs:1;                /* source only */
235          unsigned address_mode:1;       /* relative addressing, hopefully! */
236          unsigned pad0:17;
237          unsigned subnr:5;              /* :1 in align16 */
238       };
239       uint32_t bits;
240    };
241 
242    union {
243       struct {
244          unsigned nr;
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       double df;
255       uint64_t u64;
256       int64_t d64;
257       float f;
258       int   d;
259       unsigned ud;
260    };
261 };
262 
263 static inline unsigned
phys_nr(const struct intel_device_info * devinfo,const struct elk_reg reg)264 phys_nr(const struct intel_device_info *devinfo, const struct elk_reg reg)
265 {
266    return reg.nr;
267 }
268 
269 static inline unsigned
phys_subnr(const struct intel_device_info * devinfo,const struct elk_reg reg)270 phys_subnr(const struct intel_device_info *devinfo, const struct elk_reg reg)
271 {
272    return reg.subnr;
273 }
274 
275 static inline bool
elk_regs_equal(const struct elk_reg * a,const struct elk_reg * b)276 elk_regs_equal(const struct elk_reg *a, const struct elk_reg *b)
277 {
278    return a->bits == b->bits && a->u64 == b->u64;
279 }
280 
281 static inline bool
elk_regs_negative_equal(const struct elk_reg * a,const struct elk_reg * b)282 elk_regs_negative_equal(const struct elk_reg *a, const struct elk_reg *b)
283 {
284    if (a->file == IMM) {
285       if (a->bits != b->bits)
286          return false;
287 
288       switch ((enum elk_reg_type) a->type) {
289       case ELK_REGISTER_TYPE_UQ:
290       case ELK_REGISTER_TYPE_Q:
291          return a->d64 == -b->d64;
292       case ELK_REGISTER_TYPE_DF:
293          return a->df == -b->df;
294       case ELK_REGISTER_TYPE_UD:
295       case ELK_REGISTER_TYPE_D:
296          return a->d == -b->d;
297       case ELK_REGISTER_TYPE_F:
298          return a->f == -b->f;
299       case ELK_REGISTER_TYPE_VF:
300          /* It is tempting to treat 0 as a negation of 0 (and -0 as a negation
301           * of -0).  There are occasions where 0 or -0 is used and the exact
302           * bit pattern is desired.  At the very least, changing this to allow
303           * 0 as a negation of 0 causes some fp64 tests to fail on IVB.
304           */
305          return a->ud == (b->ud ^ 0x80808080);
306       case ELK_REGISTER_TYPE_UW:
307       case ELK_REGISTER_TYPE_W:
308       case ELK_REGISTER_TYPE_UV:
309       case ELK_REGISTER_TYPE_V:
310       case ELK_REGISTER_TYPE_HF:
311          /* FINISHME: Implement support for these types once there is
312           * something in the compiler that can generate them.  Until then,
313           * they cannot be tested.
314           */
315          return false;
316       case ELK_REGISTER_TYPE_UB:
317       case ELK_REGISTER_TYPE_B:
318       case ELK_REGISTER_TYPE_NF:
319       default:
320          unreachable("not reached");
321       }
322    } else {
323       struct elk_reg tmp = *a;
324 
325       tmp.negate = !tmp.negate;
326 
327       return elk_regs_equal(&tmp, b);
328    }
329 }
330 
331 struct elk_indirect {
332    unsigned addr_subnr:4;
333    int addr_offset:10;
334    unsigned pad:18;
335 };
336 
337 
338 static inline unsigned
type_sz(unsigned type)339 type_sz(unsigned type)
340 {
341    switch(type) {
342    case ELK_REGISTER_TYPE_UQ:
343    case ELK_REGISTER_TYPE_Q:
344    case ELK_REGISTER_TYPE_DF:
345    case ELK_REGISTER_TYPE_NF:
346       return 8;
347    case ELK_REGISTER_TYPE_UD:
348    case ELK_REGISTER_TYPE_D:
349    case ELK_REGISTER_TYPE_F:
350    case ELK_REGISTER_TYPE_VF:
351       return 4;
352    case ELK_REGISTER_TYPE_UW:
353    case ELK_REGISTER_TYPE_W:
354    case ELK_REGISTER_TYPE_HF:
355    /* [U]V components are 4-bit, but HW unpacks them to 16-bit (2 bytes) */
356    case ELK_REGISTER_TYPE_UV:
357    case ELK_REGISTER_TYPE_V:
358       return 2;
359    case ELK_REGISTER_TYPE_UB:
360    case ELK_REGISTER_TYPE_B:
361       return 1;
362    default:
363       unreachable("not reached");
364    }
365 }
366 
367 static inline enum elk_reg_type
get_exec_type(const enum elk_reg_type type)368 get_exec_type(const enum elk_reg_type type)
369 {
370    switch (type) {
371    case ELK_REGISTER_TYPE_B:
372    case ELK_REGISTER_TYPE_V:
373       return ELK_REGISTER_TYPE_W;
374    case ELK_REGISTER_TYPE_UB:
375    case ELK_REGISTER_TYPE_UV:
376       return ELK_REGISTER_TYPE_UW;
377    case ELK_REGISTER_TYPE_VF:
378       return ELK_REGISTER_TYPE_F;
379    default:
380       return type;
381    }
382 }
383 
384 /**
385  * Return an integer type of the requested size and signedness.
386  */
387 static inline enum elk_reg_type
elk_int_type(unsigned sz,bool is_signed)388 elk_int_type(unsigned sz, bool is_signed)
389 {
390    switch (sz) {
391    case 1:
392       return (is_signed ? ELK_REGISTER_TYPE_B : ELK_REGISTER_TYPE_UB);
393    case 2:
394       return (is_signed ? ELK_REGISTER_TYPE_W : ELK_REGISTER_TYPE_UW);
395    case 4:
396       return (is_signed ? ELK_REGISTER_TYPE_D : ELK_REGISTER_TYPE_UD);
397    case 8:
398       return (is_signed ? ELK_REGISTER_TYPE_Q : ELK_REGISTER_TYPE_UQ);
399    default:
400       unreachable("Not reached.");
401    }
402 }
403 
404 /**
405  * Construct a elk_reg.
406  * \param file      one of the ELK_x_REGISTER_FILE values
407  * \param nr        register number/index
408  * \param subnr     register sub number
409  * \param negate    register negate modifier
410  * \param abs       register abs modifier
411  * \param type      one of ELK_REGISTER_TYPE_x
412  * \param vstride   one of ELK_VERTICAL_STRIDE_x
413  * \param width     one of ELK_WIDTH_x
414  * \param hstride   one of ELK_HORIZONTAL_STRIDE_x
415  * \param swizzle   one of ELK_SWIZZLE_x
416  * \param writemask WRITEMASK_X/Y/Z/W bitfield
417  */
418 static inline struct elk_reg
elk_reg(enum elk_reg_file file,unsigned nr,unsigned subnr,unsigned negate,unsigned abs,enum elk_reg_type type,unsigned vstride,unsigned width,unsigned hstride,unsigned swizzle,unsigned writemask)419 elk_reg(enum elk_reg_file file,
420         unsigned nr,
421         unsigned subnr,
422         unsigned negate,
423         unsigned abs,
424         enum elk_reg_type type,
425         unsigned vstride,
426         unsigned width,
427         unsigned hstride,
428         unsigned swizzle,
429         unsigned writemask)
430 {
431    struct elk_reg reg;
432    if (file == ELK_GENERAL_REGISTER_FILE)
433       assert(nr < XE2_MAX_GRF);
434    else if (file == ELK_ARCHITECTURE_REGISTER_FILE)
435       assert(nr <= ELK_ARF_TIMESTAMP);
436    /* Asserting on the MRF register number requires to know the hardware gen
437     * (gfx6 has 24 MRF registers), which we don't know here, so we assert
438     * for that in the generators and in elk_eu_emit.c
439     */
440 
441    reg.type = type;
442    reg.file = file;
443    reg.negate = negate;
444    reg.abs = abs;
445    reg.address_mode = ELK_ADDRESS_DIRECT;
446    reg.pad0 = 0;
447    reg.subnr = subnr * type_sz(type);
448    reg.nr = nr;
449 
450    /* Could do better: If the reg is r5.3<0;1,0>, we probably want to
451     * set swizzle and writemask to W, as the lower bits of subnr will
452     * be lost when converted to align16.  This is probably too much to
453     * keep track of as you'd want it adjusted by suboffset(), etc.
454     * Perhaps fix up when converting to align16?
455     */
456    reg.swizzle = swizzle;
457    reg.writemask = writemask;
458    reg.indirect_offset = 0;
459    reg.vstride = vstride;
460    reg.width = width;
461    reg.hstride = hstride;
462    reg.pad1 = 0;
463    return reg;
464 }
465 
466 /** Construct float[16] register */
467 static inline struct elk_reg
elk_vec16_reg(enum elk_reg_file file,unsigned nr,unsigned subnr)468 elk_vec16_reg(enum elk_reg_file file, unsigned nr, unsigned subnr)
469 {
470    return elk_reg(file,
471                   nr,
472                   subnr,
473                   0,
474                   0,
475                   ELK_REGISTER_TYPE_F,
476                   ELK_VERTICAL_STRIDE_16,
477                   ELK_WIDTH_16,
478                   ELK_HORIZONTAL_STRIDE_1,
479                   ELK_SWIZZLE_XYZW,
480                   WRITEMASK_XYZW);
481 }
482 
483 /** Construct float[8] register */
484 static inline struct elk_reg
elk_vec8_reg(enum elk_reg_file file,unsigned nr,unsigned subnr)485 elk_vec8_reg(enum elk_reg_file file, unsigned nr, unsigned subnr)
486 {
487    return elk_reg(file,
488                   nr,
489                   subnr,
490                   0,
491                   0,
492                   ELK_REGISTER_TYPE_F,
493                   ELK_VERTICAL_STRIDE_8,
494                   ELK_WIDTH_8,
495                   ELK_HORIZONTAL_STRIDE_1,
496                   ELK_SWIZZLE_XYZW,
497                   WRITEMASK_XYZW);
498 }
499 
500 /** Construct float[4] register */
501 static inline struct elk_reg
elk_vec4_reg(enum elk_reg_file file,unsigned nr,unsigned subnr)502 elk_vec4_reg(enum elk_reg_file file, unsigned nr, unsigned subnr)
503 {
504    return elk_reg(file,
505                   nr,
506                   subnr,
507                   0,
508                   0,
509                   ELK_REGISTER_TYPE_F,
510                   ELK_VERTICAL_STRIDE_4,
511                   ELK_WIDTH_4,
512                   ELK_HORIZONTAL_STRIDE_1,
513                   ELK_SWIZZLE_XYZW,
514                   WRITEMASK_XYZW);
515 }
516 
517 /** Construct float[2] register */
518 static inline struct elk_reg
elk_vec2_reg(enum elk_reg_file file,unsigned nr,unsigned subnr)519 elk_vec2_reg(enum elk_reg_file file, unsigned nr, unsigned subnr)
520 {
521    return elk_reg(file,
522                   nr,
523                   subnr,
524                   0,
525                   0,
526                   ELK_REGISTER_TYPE_F,
527                   ELK_VERTICAL_STRIDE_2,
528                   ELK_WIDTH_2,
529                   ELK_HORIZONTAL_STRIDE_1,
530                   ELK_SWIZZLE_XYXY,
531                   WRITEMASK_XY);
532 }
533 
534 /** Construct float[1] register */
535 static inline struct elk_reg
elk_vec1_reg(enum elk_reg_file file,unsigned nr,unsigned subnr)536 elk_vec1_reg(enum elk_reg_file file, unsigned nr, unsigned subnr)
537 {
538    return elk_reg(file,
539                   nr,
540                   subnr,
541                   0,
542                   0,
543                   ELK_REGISTER_TYPE_F,
544                   ELK_VERTICAL_STRIDE_0,
545                   ELK_WIDTH_1,
546                   ELK_HORIZONTAL_STRIDE_0,
547                   ELK_SWIZZLE_XXXX,
548                   WRITEMASK_X);
549 }
550 
551 static inline struct elk_reg
elk_vecn_reg(unsigned width,enum elk_reg_file file,unsigned nr,unsigned subnr)552 elk_vecn_reg(unsigned width, enum elk_reg_file file,
553              unsigned nr, unsigned subnr)
554 {
555    switch (width) {
556    case 1:
557       return elk_vec1_reg(file, nr, subnr);
558    case 2:
559       return elk_vec2_reg(file, nr, subnr);
560    case 4:
561       return elk_vec4_reg(file, nr, subnr);
562    case 8:
563       return elk_vec8_reg(file, nr, subnr);
564    case 16:
565       return elk_vec16_reg(file, nr, subnr);
566    default:
567       unreachable("Invalid register width");
568    }
569 }
570 
571 static inline struct elk_reg
retype(struct elk_reg reg,enum elk_reg_type type)572 retype(struct elk_reg reg, enum elk_reg_type type)
573 {
574    reg.type = type;
575    return reg;
576 }
577 
578 static inline struct elk_reg
firsthalf(struct elk_reg reg)579 firsthalf(struct elk_reg reg)
580 {
581    return reg;
582 }
583 
584 static inline struct elk_reg
sechalf(struct elk_reg reg)585 sechalf(struct elk_reg reg)
586 {
587    if (reg.vstride)
588       reg.nr++;
589    return reg;
590 }
591 
592 static inline struct elk_reg
offset(struct elk_reg reg,unsigned delta)593 offset(struct elk_reg reg, unsigned delta)
594 {
595    reg.nr += delta;
596    return reg;
597 }
598 
599 
600 static inline struct elk_reg
byte_offset(struct elk_reg reg,unsigned bytes)601 byte_offset(struct elk_reg reg, unsigned bytes)
602 {
603    unsigned newoffset = reg.nr * REG_SIZE + reg.subnr + bytes;
604    reg.nr = newoffset / REG_SIZE;
605    reg.subnr = newoffset % REG_SIZE;
606    return reg;
607 }
608 
609 static inline struct elk_reg
suboffset(struct elk_reg reg,unsigned delta)610 suboffset(struct elk_reg reg, unsigned delta)
611 {
612    return byte_offset(reg, delta * type_sz(reg.type));
613 }
614 
615 /** Construct unsigned word[16] register */
616 static inline struct elk_reg
elk_uw16_reg(enum elk_reg_file file,unsigned nr,unsigned subnr)617 elk_uw16_reg(enum elk_reg_file file, unsigned nr, unsigned subnr)
618 {
619    return suboffset(retype(elk_vec16_reg(file, nr, 0), ELK_REGISTER_TYPE_UW), subnr);
620 }
621 
622 /** Construct unsigned word[8] register */
623 static inline struct elk_reg
elk_uw8_reg(enum elk_reg_file file,unsigned nr,unsigned subnr)624 elk_uw8_reg(enum elk_reg_file file, unsigned nr, unsigned subnr)
625 {
626    return suboffset(retype(elk_vec8_reg(file, nr, 0), ELK_REGISTER_TYPE_UW), subnr);
627 }
628 
629 /** Construct unsigned word[1] register */
630 static inline struct elk_reg
elk_uw1_reg(enum elk_reg_file file,unsigned nr,unsigned subnr)631 elk_uw1_reg(enum elk_reg_file file, unsigned nr, unsigned subnr)
632 {
633    return suboffset(retype(elk_vec1_reg(file, nr, 0), ELK_REGISTER_TYPE_UW), subnr);
634 }
635 
636 static inline struct elk_reg
elk_ud8_reg(enum elk_reg_file file,unsigned nr,unsigned subnr)637 elk_ud8_reg(enum elk_reg_file file, unsigned nr, unsigned subnr)
638 {
639    return retype(elk_vec8_reg(file, nr, subnr), ELK_REGISTER_TYPE_UD);
640 }
641 
642 static inline struct elk_reg
elk_ud1_reg(enum elk_reg_file file,unsigned nr,unsigned subnr)643 elk_ud1_reg(enum elk_reg_file file, unsigned nr, unsigned subnr)
644 {
645    return retype(elk_vec1_reg(file, nr, subnr), ELK_REGISTER_TYPE_UD);
646 }
647 
648 static inline struct elk_reg
elk_imm_reg(enum elk_reg_type type)649 elk_imm_reg(enum elk_reg_type type)
650 {
651    return elk_reg(ELK_IMMEDIATE_VALUE,
652                   0,
653                   0,
654                   0,
655                   0,
656                   type,
657                   ELK_VERTICAL_STRIDE_0,
658                   ELK_WIDTH_1,
659                   ELK_HORIZONTAL_STRIDE_0,
660                   0,
661                   0);
662 }
663 
664 /** Construct float immediate register */
665 static inline struct elk_reg
elk_imm_df(double df)666 elk_imm_df(double df)
667 {
668    struct elk_reg imm = elk_imm_reg(ELK_REGISTER_TYPE_DF);
669    imm.df = df;
670    return imm;
671 }
672 
673 static inline struct elk_reg
elk_imm_u64(uint64_t u64)674 elk_imm_u64(uint64_t u64)
675 {
676    struct elk_reg imm = elk_imm_reg(ELK_REGISTER_TYPE_UQ);
677    imm.u64 = u64;
678    return imm;
679 }
680 
681 static inline struct elk_reg
elk_imm_f(float f)682 elk_imm_f(float f)
683 {
684    struct elk_reg imm = elk_imm_reg(ELK_REGISTER_TYPE_F);
685    imm.f = f;
686    return imm;
687 }
688 
689 /** Construct int64_t immediate register */
690 static inline struct elk_reg
elk_imm_q(int64_t q)691 elk_imm_q(int64_t q)
692 {
693    struct elk_reg imm = elk_imm_reg(ELK_REGISTER_TYPE_Q);
694    imm.d64 = q;
695    return imm;
696 }
697 
698 /** Construct int64_t immediate register */
699 static inline struct elk_reg
elk_imm_uq(uint64_t uq)700 elk_imm_uq(uint64_t uq)
701 {
702    struct elk_reg imm = elk_imm_reg(ELK_REGISTER_TYPE_UQ);
703    imm.u64 = uq;
704    return imm;
705 }
706 
707 /** Construct integer immediate register */
708 static inline struct elk_reg
elk_imm_d(int d)709 elk_imm_d(int d)
710 {
711    struct elk_reg imm = elk_imm_reg(ELK_REGISTER_TYPE_D);
712    imm.d = d;
713    return imm;
714 }
715 
716 /** Construct uint immediate register */
717 static inline struct elk_reg
elk_imm_ud(unsigned ud)718 elk_imm_ud(unsigned ud)
719 {
720    struct elk_reg imm = elk_imm_reg(ELK_REGISTER_TYPE_UD);
721    imm.ud = ud;
722    return imm;
723 }
724 
725 /** Construct ushort immediate register */
726 static inline struct elk_reg
elk_imm_uw(uint16_t uw)727 elk_imm_uw(uint16_t uw)
728 {
729    struct elk_reg imm = elk_imm_reg(ELK_REGISTER_TYPE_UW);
730    imm.ud = uw | ((uint32_t)uw << 16);
731    return imm;
732 }
733 
734 /** Construct short immediate register */
735 static inline struct elk_reg
elk_imm_w(int16_t w)736 elk_imm_w(int16_t w)
737 {
738    struct elk_reg imm = elk_imm_reg(ELK_REGISTER_TYPE_W);
739    imm.ud = (uint16_t)w | (uint32_t)(uint16_t)w << 16;
740    return imm;
741 }
742 
743 /* elk_imm_b and elk_imm_ub aren't supported by hardware - the type
744  * numbers alias with _V and _VF below:
745  */
746 
747 /** Construct vector of eight signed half-byte values */
748 static inline struct elk_reg
elk_imm_v(unsigned v)749 elk_imm_v(unsigned v)
750 {
751    struct elk_reg imm = elk_imm_reg(ELK_REGISTER_TYPE_V);
752    imm.ud = v;
753    return imm;
754 }
755 
756 /** Construct vector of eight unsigned half-byte values */
757 static inline struct elk_reg
elk_imm_uv(unsigned uv)758 elk_imm_uv(unsigned uv)
759 {
760    struct elk_reg imm = elk_imm_reg(ELK_REGISTER_TYPE_UV);
761    imm.ud = uv;
762    return imm;
763 }
764 
765 /** Construct vector of four 8-bit float values */
766 static inline struct elk_reg
elk_imm_vf(unsigned v)767 elk_imm_vf(unsigned v)
768 {
769    struct elk_reg imm = elk_imm_reg(ELK_REGISTER_TYPE_VF);
770    imm.ud = v;
771    return imm;
772 }
773 
774 static inline struct elk_reg
elk_imm_vf4(unsigned v0,unsigned v1,unsigned v2,unsigned v3)775 elk_imm_vf4(unsigned v0, unsigned v1, unsigned v2, unsigned v3)
776 {
777    struct elk_reg imm = elk_imm_reg(ELK_REGISTER_TYPE_VF);
778    imm.vstride = ELK_VERTICAL_STRIDE_0;
779    imm.width = ELK_WIDTH_4;
780    imm.hstride = ELK_HORIZONTAL_STRIDE_1;
781    imm.ud = ((v0 << 0) | (v1 << 8) | (v2 << 16) | (v3 << 24));
782    return imm;
783 }
784 
785 
786 static inline struct elk_reg
elk_address(struct elk_reg reg)787 elk_address(struct elk_reg reg)
788 {
789    return elk_imm_uw(reg.nr * REG_SIZE + reg.subnr);
790 }
791 
792 /** Construct float[1] general-purpose register */
793 static inline struct elk_reg
elk_vec1_grf(unsigned nr,unsigned subnr)794 elk_vec1_grf(unsigned nr, unsigned subnr)
795 {
796    return elk_vec1_reg(ELK_GENERAL_REGISTER_FILE, nr, subnr);
797 }
798 
799 static inline struct elk_reg
xe2_vec1_grf(unsigned nr,unsigned subnr)800 xe2_vec1_grf(unsigned nr, unsigned subnr)
801 {
802    return elk_vec1_reg(ELK_GENERAL_REGISTER_FILE, 2 * nr + subnr / 8, subnr % 8);
803 }
804 
805 /** Construct float[2] general-purpose register */
806 static inline struct elk_reg
elk_vec2_grf(unsigned nr,unsigned subnr)807 elk_vec2_grf(unsigned nr, unsigned subnr)
808 {
809    return elk_vec2_reg(ELK_GENERAL_REGISTER_FILE, nr, subnr);
810 }
811 
812 static inline struct elk_reg
xe2_vec2_grf(unsigned nr,unsigned subnr)813 xe2_vec2_grf(unsigned nr, unsigned subnr)
814 {
815    return elk_vec2_reg(ELK_GENERAL_REGISTER_FILE, 2 * nr + subnr / 8, subnr % 8);
816 }
817 
818 /** Construct float[4] general-purpose register */
819 static inline struct elk_reg
elk_vec4_grf(unsigned nr,unsigned subnr)820 elk_vec4_grf(unsigned nr, unsigned subnr)
821 {
822    return elk_vec4_reg(ELK_GENERAL_REGISTER_FILE, nr, subnr);
823 }
824 
825 static inline struct elk_reg
xe2_vec4_grf(unsigned nr,unsigned subnr)826 xe2_vec4_grf(unsigned nr, unsigned subnr)
827 {
828    return elk_vec4_reg(ELK_GENERAL_REGISTER_FILE, 2 * nr + subnr / 8, subnr % 8);
829 }
830 
831 /** Construct float[8] general-purpose register */
832 static inline struct elk_reg
elk_vec8_grf(unsigned nr,unsigned subnr)833 elk_vec8_grf(unsigned nr, unsigned subnr)
834 {
835    return elk_vec8_reg(ELK_GENERAL_REGISTER_FILE, nr, subnr);
836 }
837 
838 static inline struct elk_reg
xe2_vec8_grf(unsigned nr,unsigned subnr)839 xe2_vec8_grf(unsigned nr, unsigned subnr)
840 {
841    return elk_vec8_reg(ELK_GENERAL_REGISTER_FILE, 2 * nr + subnr / 8, subnr % 8);
842 }
843 
844 /** Construct float[16] general-purpose register */
845 static inline struct elk_reg
elk_vec16_grf(unsigned nr,unsigned subnr)846 elk_vec16_grf(unsigned nr, unsigned subnr)
847 {
848    return elk_vec16_reg(ELK_GENERAL_REGISTER_FILE, nr, subnr);
849 }
850 
851 static inline struct elk_reg
xe2_vec16_grf(unsigned nr,unsigned subnr)852 xe2_vec16_grf(unsigned nr, unsigned subnr)
853 {
854    return elk_vec16_reg(ELK_GENERAL_REGISTER_FILE, 2 * nr + subnr / 8, subnr % 8);
855 }
856 
857 static inline struct elk_reg
elk_vecn_grf(unsigned width,unsigned nr,unsigned subnr)858 elk_vecn_grf(unsigned width, unsigned nr, unsigned subnr)
859 {
860    return elk_vecn_reg(width, ELK_GENERAL_REGISTER_FILE, nr, subnr);
861 }
862 
863 static inline struct elk_reg
xe2_vecn_grf(unsigned width,unsigned nr,unsigned subnr)864 xe2_vecn_grf(unsigned width, unsigned nr, unsigned subnr)
865 {
866    return elk_vecn_reg(width, ELK_GENERAL_REGISTER_FILE, nr + subnr / 8, subnr % 8);
867 }
868 
869 static inline struct elk_reg
elk_uw1_grf(unsigned nr,unsigned subnr)870 elk_uw1_grf(unsigned nr, unsigned subnr)
871 {
872    return elk_uw1_reg(ELK_GENERAL_REGISTER_FILE, nr, subnr);
873 }
874 
875 static inline struct elk_reg
elk_uw8_grf(unsigned nr,unsigned subnr)876 elk_uw8_grf(unsigned nr, unsigned subnr)
877 {
878    return elk_uw8_reg(ELK_GENERAL_REGISTER_FILE, nr, subnr);
879 }
880 
881 static inline struct elk_reg
elk_uw16_grf(unsigned nr,unsigned subnr)882 elk_uw16_grf(unsigned nr, unsigned subnr)
883 {
884    return elk_uw16_reg(ELK_GENERAL_REGISTER_FILE, nr, subnr);
885 }
886 
887 static inline struct elk_reg
elk_ud8_grf(unsigned nr,unsigned subnr)888 elk_ud8_grf(unsigned nr, unsigned subnr)
889 {
890    return elk_ud8_reg(ELK_GENERAL_REGISTER_FILE, nr, subnr);
891 }
892 
893 static inline struct elk_reg
elk_ud1_grf(unsigned nr,unsigned subnr)894 elk_ud1_grf(unsigned nr, unsigned subnr)
895 {
896    return elk_ud1_reg(ELK_GENERAL_REGISTER_FILE, nr, subnr);
897 }
898 
899 
900 /** Construct null register (usually used for setting condition codes) */
901 static inline struct elk_reg
elk_null_reg(void)902 elk_null_reg(void)
903 {
904    return elk_vec8_reg(ELK_ARCHITECTURE_REGISTER_FILE, ELK_ARF_NULL, 0);
905 }
906 
907 static inline struct elk_reg
elk_null_vec(unsigned width)908 elk_null_vec(unsigned width)
909 {
910    return elk_vecn_reg(width, ELK_ARCHITECTURE_REGISTER_FILE, ELK_ARF_NULL, 0);
911 }
912 
913 static inline struct elk_reg
elk_address_reg(unsigned subnr)914 elk_address_reg(unsigned subnr)
915 {
916    return elk_uw1_reg(ELK_ARCHITECTURE_REGISTER_FILE, ELK_ARF_ADDRESS, subnr);
917 }
918 
919 static inline struct elk_reg
elk_tdr_reg(void)920 elk_tdr_reg(void)
921 {
922    return elk_uw1_reg(ELK_ARCHITECTURE_REGISTER_FILE, ELK_ARF_TDR, 0);
923 }
924 
925 /* If/else instructions break in align16 mode if writemask & swizzle
926  * aren't xyzw.  This goes against the convention for other scalar
927  * regs:
928  */
929 static inline struct elk_reg
elk_ip_reg(void)930 elk_ip_reg(void)
931 {
932    return elk_reg(ELK_ARCHITECTURE_REGISTER_FILE,
933                   ELK_ARF_IP,
934                   0,
935                   0,
936                   0,
937                   ELK_REGISTER_TYPE_UD,
938                   ELK_VERTICAL_STRIDE_4, /* ? */
939                   ELK_WIDTH_1,
940                   ELK_HORIZONTAL_STRIDE_0,
941                   ELK_SWIZZLE_XYZW, /* NOTE! */
942                   WRITEMASK_XYZW); /* NOTE! */
943 }
944 
945 static inline struct elk_reg
elk_notification_reg(void)946 elk_notification_reg(void)
947 {
948    return elk_reg(ELK_ARCHITECTURE_REGISTER_FILE,
949                   ELK_ARF_NOTIFICATION_COUNT,
950                   0,
951                   0,
952                   0,
953                   ELK_REGISTER_TYPE_UD,
954                   ELK_VERTICAL_STRIDE_0,
955                   ELK_WIDTH_1,
956                   ELK_HORIZONTAL_STRIDE_0,
957                   ELK_SWIZZLE_XXXX,
958                   WRITEMASK_X);
959 }
960 
961 static inline struct elk_reg
elk_cr0_reg(unsigned subnr)962 elk_cr0_reg(unsigned subnr)
963 {
964    return elk_ud1_reg(ELK_ARCHITECTURE_REGISTER_FILE, ELK_ARF_CONTROL, subnr);
965 }
966 
967 static inline struct elk_reg
elk_sr0_reg(unsigned subnr)968 elk_sr0_reg(unsigned subnr)
969 {
970    return elk_ud1_reg(ELK_ARCHITECTURE_REGISTER_FILE, ELK_ARF_STATE, subnr);
971 }
972 
973 static inline struct elk_reg
elk_acc_reg(unsigned width)974 elk_acc_reg(unsigned width)
975 {
976    return elk_vecn_reg(width, ELK_ARCHITECTURE_REGISTER_FILE,
977                        ELK_ARF_ACCUMULATOR, 0);
978 }
979 
980 static inline struct elk_reg
elk_flag_reg(int reg,int subreg)981 elk_flag_reg(int reg, int subreg)
982 {
983    return elk_uw1_reg(ELK_ARCHITECTURE_REGISTER_FILE,
984                       ELK_ARF_FLAG + reg, subreg);
985 }
986 
987 static inline struct elk_reg
elk_flag_subreg(unsigned subreg)988 elk_flag_subreg(unsigned subreg)
989 {
990    return elk_uw1_reg(ELK_ARCHITECTURE_REGISTER_FILE,
991                       ELK_ARF_FLAG + subreg / 2, subreg % 2);
992 }
993 
994 /**
995  * Return the mask register present in Gfx4-5, or the related register present
996  * in Gfx7.5 and later hardware referred to as "channel enable" register in
997  * the documentation.
998  */
999 static inline struct elk_reg
elk_mask_reg(unsigned subnr)1000 elk_mask_reg(unsigned subnr)
1001 {
1002    return elk_uw1_reg(ELK_ARCHITECTURE_REGISTER_FILE, ELK_ARF_MASK, subnr);
1003 }
1004 
1005 static inline struct elk_reg
elk_vmask_reg()1006 elk_vmask_reg()
1007 {
1008    return elk_sr0_reg(3);
1009 }
1010 
1011 static inline struct elk_reg
elk_dmask_reg()1012 elk_dmask_reg()
1013 {
1014    return elk_sr0_reg(2);
1015 }
1016 
1017 static inline struct elk_reg
elk_mask_stack_reg(unsigned subnr)1018 elk_mask_stack_reg(unsigned subnr)
1019 {
1020    return suboffset(retype(elk_vec16_reg(ELK_ARCHITECTURE_REGISTER_FILE,
1021                                          ELK_ARF_MASK_STACK, 0),
1022                            ELK_REGISTER_TYPE_UB), subnr);
1023 }
1024 
1025 static inline struct elk_reg
elk_mask_stack_depth_reg(unsigned subnr)1026 elk_mask_stack_depth_reg(unsigned subnr)
1027 {
1028    return elk_uw1_reg(ELK_ARCHITECTURE_REGISTER_FILE,
1029                       ELK_ARF_MASK_STACK_DEPTH, subnr);
1030 }
1031 
1032 static inline struct elk_reg
elk_message_reg(unsigned nr)1033 elk_message_reg(unsigned nr)
1034 {
1035    return elk_vec8_reg(ELK_MESSAGE_REGISTER_FILE, nr, 0);
1036 }
1037 
1038 static inline struct elk_reg
elk_uvec_mrf(unsigned width,unsigned nr,unsigned subnr)1039 elk_uvec_mrf(unsigned width, unsigned nr, unsigned subnr)
1040 {
1041    return retype(elk_vecn_reg(width, ELK_MESSAGE_REGISTER_FILE, nr, subnr),
1042                  ELK_REGISTER_TYPE_UD);
1043 }
1044 
1045 /* This is almost always called with a numeric constant argument, so
1046  * make things easy to evaluate at compile time:
1047  */
cvt(unsigned val)1048 static inline unsigned cvt(unsigned val)
1049 {
1050    switch (val) {
1051    case 0: return 0;
1052    case 1: return 1;
1053    case 2: return 2;
1054    case 4: return 3;
1055    case 8: return 4;
1056    case 16: return 5;
1057    case 32: return 6;
1058    }
1059    return 0;
1060 }
1061 
1062 static inline struct elk_reg
stride(struct elk_reg reg,unsigned vstride,unsigned width,unsigned hstride)1063 stride(struct elk_reg reg, unsigned vstride, unsigned width, unsigned hstride)
1064 {
1065    reg.vstride = cvt(vstride);
1066    reg.width = cvt(width) - 1;
1067    reg.hstride = cvt(hstride);
1068    return reg;
1069 }
1070 
1071 /**
1072  * Multiply the vertical and horizontal stride of a register by the given
1073  * factor \a s.
1074  */
1075 static inline struct elk_reg
spread(struct elk_reg reg,unsigned s)1076 spread(struct elk_reg reg, unsigned s)
1077 {
1078    if (s) {
1079       assert(util_is_power_of_two_nonzero(s));
1080 
1081       if (reg.hstride)
1082          reg.hstride += cvt(s) - 1;
1083 
1084       if (reg.vstride)
1085          reg.vstride += cvt(s) - 1;
1086 
1087       return reg;
1088    } else {
1089       return stride(reg, 0, 1, 0);
1090    }
1091 }
1092 
1093 /**
1094  * Reinterpret each channel of register \p reg as a vector of values of the
1095  * given smaller type and take the i-th subcomponent from each.
1096  */
1097 static inline struct elk_reg
subscript(struct elk_reg reg,enum elk_reg_type type,unsigned i)1098 subscript(struct elk_reg reg, enum elk_reg_type type, unsigned i)
1099 {
1100    unsigned scale = type_sz(reg.type) / type_sz(type);
1101    assert(scale >= 1 && i < scale);
1102 
1103    if (reg.file == IMM) {
1104       unsigned bit_size = type_sz(type) * 8;
1105       reg.u64 >>= i * bit_size;
1106       reg.u64 &= BITFIELD64_MASK(bit_size);
1107       if (bit_size <= 16)
1108          reg.u64 |= reg.u64 << 16;
1109       return retype(reg, type);
1110    }
1111 
1112    return suboffset(retype(spread(reg, scale), type), i);
1113 }
1114 
1115 static inline struct elk_reg
vec16(struct elk_reg reg)1116 vec16(struct elk_reg reg)
1117 {
1118    return stride(reg, 16,16,1);
1119 }
1120 
1121 static inline struct elk_reg
vec8(struct elk_reg reg)1122 vec8(struct elk_reg reg)
1123 {
1124    return stride(reg, 8,8,1);
1125 }
1126 
1127 static inline struct elk_reg
vec4(struct elk_reg reg)1128 vec4(struct elk_reg reg)
1129 {
1130    return stride(reg, 4,4,1);
1131 }
1132 
1133 static inline struct elk_reg
vec2(struct elk_reg reg)1134 vec2(struct elk_reg reg)
1135 {
1136    return stride(reg, 2,2,1);
1137 }
1138 
1139 static inline struct elk_reg
vec1(struct elk_reg reg)1140 vec1(struct elk_reg reg)
1141 {
1142    return stride(reg, 0,1,0);
1143 }
1144 
1145 
1146 static inline struct elk_reg
get_element(struct elk_reg reg,unsigned elt)1147 get_element(struct elk_reg reg, unsigned elt)
1148 {
1149    return vec1(suboffset(reg, elt));
1150 }
1151 
1152 static inline struct elk_reg
get_element_ud(struct elk_reg reg,unsigned elt)1153 get_element_ud(struct elk_reg reg, unsigned elt)
1154 {
1155    return vec1(suboffset(retype(reg, ELK_REGISTER_TYPE_UD), elt));
1156 }
1157 
1158 static inline struct elk_reg
get_element_d(struct elk_reg reg,unsigned elt)1159 get_element_d(struct elk_reg reg, unsigned elt)
1160 {
1161    return vec1(suboffset(retype(reg, ELK_REGISTER_TYPE_D), elt));
1162 }
1163 
1164 static inline struct elk_reg
elk_swizzle(struct elk_reg reg,unsigned swz)1165 elk_swizzle(struct elk_reg reg, unsigned swz)
1166 {
1167    if (reg.file == ELK_IMMEDIATE_VALUE)
1168       reg.ud = elk_swizzle_immediate(reg.type, reg.ud, swz);
1169    else
1170       reg.swizzle = elk_compose_swizzle(swz, reg.swizzle);
1171 
1172    return reg;
1173 }
1174 
1175 static inline struct elk_reg
elk_writemask(struct elk_reg reg,unsigned mask)1176 elk_writemask(struct elk_reg reg, unsigned mask)
1177 {
1178    assert(reg.file != ELK_IMMEDIATE_VALUE);
1179    reg.writemask &= mask;
1180    return reg;
1181 }
1182 
1183 static inline struct elk_reg
elk_set_writemask(struct elk_reg reg,unsigned mask)1184 elk_set_writemask(struct elk_reg reg, unsigned mask)
1185 {
1186    assert(reg.file != ELK_IMMEDIATE_VALUE);
1187    reg.writemask = mask;
1188    return reg;
1189 }
1190 
1191 static inline unsigned
elk_writemask_for_size(unsigned n)1192 elk_writemask_for_size(unsigned n)
1193 {
1194    return (1 << n) - 1;
1195 }
1196 
1197 static inline unsigned
elk_writemask_for_component_packing(unsigned n,unsigned first_component)1198 elk_writemask_for_component_packing(unsigned n, unsigned first_component)
1199 {
1200    assert(first_component + n <= 4);
1201    return (((1 << n) - 1) << first_component);
1202 }
1203 
1204 static inline struct elk_reg
negate(struct elk_reg reg)1205 negate(struct elk_reg reg)
1206 {
1207    reg.negate ^= 1;
1208    return reg;
1209 }
1210 
1211 static inline struct elk_reg
elk_abs(struct elk_reg reg)1212 elk_abs(struct elk_reg reg)
1213 {
1214    reg.abs = 1;
1215    reg.negate = 0;
1216    return reg;
1217 }
1218 
1219 /************************************************************************/
1220 
1221 static inline struct elk_reg
elk_vec4_indirect(unsigned subnr,int offset)1222 elk_vec4_indirect(unsigned subnr, int offset)
1223 {
1224    struct elk_reg reg =  elk_vec4_grf(0, 0);
1225    reg.subnr = subnr;
1226    reg.address_mode = ELK_ADDRESS_REGISTER_INDIRECT_REGISTER;
1227    reg.indirect_offset = offset;
1228    return reg;
1229 }
1230 
1231 static inline struct elk_reg
elk_vec1_indirect(unsigned subnr,int offset)1232 elk_vec1_indirect(unsigned subnr, int offset)
1233 {
1234    struct elk_reg reg =  elk_vec1_grf(0, 0);
1235    reg.subnr = subnr;
1236    reg.address_mode = ELK_ADDRESS_REGISTER_INDIRECT_REGISTER;
1237    reg.indirect_offset = offset;
1238    return reg;
1239 }
1240 
1241 static inline struct elk_reg
elk_VxH_indirect(unsigned subnr,int offset)1242 elk_VxH_indirect(unsigned subnr, int offset)
1243 {
1244    struct elk_reg reg = elk_vec1_grf(0, 0);
1245    reg.vstride = ELK_VERTICAL_STRIDE_ONE_DIMENSIONAL;
1246    reg.subnr = subnr;
1247    reg.address_mode = ELK_ADDRESS_REGISTER_INDIRECT_REGISTER;
1248    reg.indirect_offset = offset;
1249    return reg;
1250 }
1251 
1252 static inline struct elk_reg
deref_4f(struct elk_indirect ptr,int offset)1253 deref_4f(struct elk_indirect ptr, int offset)
1254 {
1255    return elk_vec4_indirect(ptr.addr_subnr, ptr.addr_offset + offset);
1256 }
1257 
1258 static inline struct elk_reg
deref_1f(struct elk_indirect ptr,int offset)1259 deref_1f(struct elk_indirect ptr, int offset)
1260 {
1261    return elk_vec1_indirect(ptr.addr_subnr, ptr.addr_offset + offset);
1262 }
1263 
1264 static inline struct elk_reg
deref_4b(struct elk_indirect ptr,int offset)1265 deref_4b(struct elk_indirect ptr, int offset)
1266 {
1267    return retype(deref_4f(ptr, offset), ELK_REGISTER_TYPE_B);
1268 }
1269 
1270 static inline struct elk_reg
deref_1uw(struct elk_indirect ptr,int offset)1271 deref_1uw(struct elk_indirect ptr, int offset)
1272 {
1273    return retype(deref_1f(ptr, offset), ELK_REGISTER_TYPE_UW);
1274 }
1275 
1276 static inline struct elk_reg
deref_1d(struct elk_indirect ptr,int offset)1277 deref_1d(struct elk_indirect ptr, int offset)
1278 {
1279    return retype(deref_1f(ptr, offset), ELK_REGISTER_TYPE_D);
1280 }
1281 
1282 static inline struct elk_reg
deref_1ud(struct elk_indirect ptr,int offset)1283 deref_1ud(struct elk_indirect ptr, int offset)
1284 {
1285    return retype(deref_1f(ptr, offset), ELK_REGISTER_TYPE_UD);
1286 }
1287 
1288 static inline struct elk_reg
get_addr_reg(struct elk_indirect ptr)1289 get_addr_reg(struct elk_indirect ptr)
1290 {
1291    return elk_address_reg(ptr.addr_subnr);
1292 }
1293 
1294 static inline struct elk_indirect
elk_indirect_offset(struct elk_indirect ptr,int offset)1295 elk_indirect_offset(struct elk_indirect ptr, int offset)
1296 {
1297    ptr.addr_offset += offset;
1298    return ptr;
1299 }
1300 
1301 static inline struct elk_indirect
elk_indirect(unsigned addr_subnr,int offset)1302 elk_indirect(unsigned addr_subnr, int offset)
1303 {
1304    struct elk_indirect ptr;
1305    ptr.addr_subnr = addr_subnr;
1306    ptr.addr_offset = offset;
1307    ptr.pad = 0;
1308    return ptr;
1309 }
1310 
1311 static inline bool
region_matches(struct elk_reg reg,enum elk_vertical_stride v,enum elk_width w,enum elk_horizontal_stride h)1312 region_matches(struct elk_reg reg, enum elk_vertical_stride v,
1313                enum elk_width w, enum elk_horizontal_stride h)
1314 {
1315    return reg.vstride == v &&
1316           reg.width == w &&
1317           reg.hstride == h;
1318 }
1319 
1320 #define has_scalar_region(reg) \
1321    region_matches(reg, ELK_VERTICAL_STRIDE_0, ELK_WIDTH_1, \
1322                   ELK_HORIZONTAL_STRIDE_0)
1323 
1324 /**
1325  * Return the size in bytes per data element of register \p reg on the
1326  * corresponding register file.
1327  */
1328 static inline unsigned
element_sz(struct elk_reg reg)1329 element_sz(struct elk_reg reg)
1330 {
1331    if (reg.file == ELK_IMMEDIATE_VALUE || has_scalar_region(reg)) {
1332       return type_sz(reg.type);
1333 
1334    } else if (reg.width == ELK_WIDTH_1 &&
1335               reg.hstride == ELK_HORIZONTAL_STRIDE_0) {
1336       assert(reg.vstride != ELK_VERTICAL_STRIDE_0);
1337       return type_sz(reg.type) << (reg.vstride - 1);
1338 
1339    } else {
1340       assert(reg.hstride != ELK_HORIZONTAL_STRIDE_0);
1341       assert(reg.vstride == reg.hstride + reg.width);
1342       return type_sz(reg.type) << (reg.hstride - 1);
1343    }
1344 }
1345 
1346 /* elk_packed_float.c */
1347 int elk_float_to_vf(float f);
1348 float elk_vf_to_float(unsigned char vf);
1349 
1350 #ifdef __cplusplus
1351 }
1352 #endif
1353 
1354 #endif
1355