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