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