i965: Move MRF register asserts out of brw_reg.h
[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_ARCHITECTURE_REGISTER_FILE)
348 assert(nr <= BRW_ARF_TIMESTAMP);
349 /* Asserting on the MRF register number requires to know the hardware gen
350 * (gen6 has 24 MRF registers), which we don't know here, so we assert
351 * for that in the generators and in brw_eu_emit.c
352 */
353
354 reg.type = type;
355 reg.file = file;
356 reg.nr = nr;
357 reg.subnr = subnr * type_sz(type);
358 reg.negate = negate;
359 reg.abs = abs;
360 reg.vstride = vstride;
361 reg.width = width;
362 reg.hstride = hstride;
363 reg.address_mode = BRW_ADDRESS_DIRECT;
364 reg.pad0 = 0;
365
366 /* Could do better: If the reg is r5.3<0;1,0>, we probably want to
367 * set swizzle and writemask to W, as the lower bits of subnr will
368 * be lost when converted to align16. This is probably too much to
369 * keep track of as you'd want it adjusted by suboffset(), etc.
370 * Perhaps fix up when converting to align16?
371 */
372 reg.dw1.bits.swizzle = swizzle;
373 reg.dw1.bits.writemask = writemask;
374 reg.dw1.bits.indirect_offset = 0;
375 reg.dw1.bits.pad1 = 0;
376 return reg;
377 }
378
379 /** Construct float[16] register */
380 static inline struct brw_reg
381 brw_vec16_reg(unsigned file, unsigned nr, unsigned subnr)
382 {
383 return brw_reg(file,
384 nr,
385 subnr,
386 0,
387 0,
388 BRW_REGISTER_TYPE_F,
389 BRW_VERTICAL_STRIDE_16,
390 BRW_WIDTH_16,
391 BRW_HORIZONTAL_STRIDE_1,
392 BRW_SWIZZLE_XYZW,
393 WRITEMASK_XYZW);
394 }
395
396 /** Construct float[8] register */
397 static inline struct brw_reg
398 brw_vec8_reg(unsigned file, unsigned nr, unsigned subnr)
399 {
400 return brw_reg(file,
401 nr,
402 subnr,
403 0,
404 0,
405 BRW_REGISTER_TYPE_F,
406 BRW_VERTICAL_STRIDE_8,
407 BRW_WIDTH_8,
408 BRW_HORIZONTAL_STRIDE_1,
409 BRW_SWIZZLE_XYZW,
410 WRITEMASK_XYZW);
411 }
412
413 /** Construct float[4] register */
414 static inline struct brw_reg
415 brw_vec4_reg(unsigned file, unsigned nr, unsigned subnr)
416 {
417 return brw_reg(file,
418 nr,
419 subnr,
420 0,
421 0,
422 BRW_REGISTER_TYPE_F,
423 BRW_VERTICAL_STRIDE_4,
424 BRW_WIDTH_4,
425 BRW_HORIZONTAL_STRIDE_1,
426 BRW_SWIZZLE_XYZW,
427 WRITEMASK_XYZW);
428 }
429
430 /** Construct float[2] register */
431 static inline struct brw_reg
432 brw_vec2_reg(unsigned file, unsigned nr, unsigned subnr)
433 {
434 return brw_reg(file,
435 nr,
436 subnr,
437 0,
438 0,
439 BRW_REGISTER_TYPE_F,
440 BRW_VERTICAL_STRIDE_2,
441 BRW_WIDTH_2,
442 BRW_HORIZONTAL_STRIDE_1,
443 BRW_SWIZZLE_XYXY,
444 WRITEMASK_XY);
445 }
446
447 /** Construct float[1] register */
448 static inline struct brw_reg
449 brw_vec1_reg(unsigned file, unsigned nr, unsigned subnr)
450 {
451 return brw_reg(file,
452 nr,
453 subnr,
454 0,
455 0,
456 BRW_REGISTER_TYPE_F,
457 BRW_VERTICAL_STRIDE_0,
458 BRW_WIDTH_1,
459 BRW_HORIZONTAL_STRIDE_0,
460 BRW_SWIZZLE_XXXX,
461 WRITEMASK_X);
462 }
463
464 static inline struct brw_reg
465 brw_vecn_reg(unsigned width, unsigned file, unsigned nr, unsigned subnr)
466 {
467 switch (width) {
468 case 1:
469 return brw_vec1_reg(file, nr, subnr);
470 case 2:
471 return brw_vec2_reg(file, nr, subnr);
472 case 4:
473 return brw_vec4_reg(file, nr, subnr);
474 case 8:
475 return brw_vec8_reg(file, nr, subnr);
476 case 16:
477 return brw_vec16_reg(file, nr, subnr);
478 default:
479 unreachable("Invalid register width");
480 }
481 }
482
483 static inline struct brw_reg
484 retype(struct brw_reg reg, enum brw_reg_type type)
485 {
486 reg.type = type;
487 return reg;
488 }
489
490 static inline struct brw_reg
491 firsthalf(struct brw_reg reg)
492 {
493 return reg;
494 }
495
496 static inline struct brw_reg
497 sechalf(struct brw_reg reg)
498 {
499 if (reg.vstride)
500 reg.nr++;
501 return reg;
502 }
503
504 static inline struct brw_reg
505 suboffset(struct brw_reg reg, unsigned delta)
506 {
507 reg.subnr += delta * type_sz(reg.type);
508 return reg;
509 }
510
511
512 static inline struct brw_reg
513 offset(struct brw_reg reg, unsigned delta)
514 {
515 reg.nr += delta;
516 return reg;
517 }
518
519
520 static inline struct brw_reg
521 byte_offset(struct brw_reg reg, unsigned bytes)
522 {
523 unsigned newoffset = reg.nr * REG_SIZE + reg.subnr + bytes;
524 reg.nr = newoffset / REG_SIZE;
525 reg.subnr = newoffset % REG_SIZE;
526 return reg;
527 }
528
529
530 /** Construct unsigned word[16] register */
531 static inline struct brw_reg
532 brw_uw16_reg(unsigned file, unsigned nr, unsigned subnr)
533 {
534 return suboffset(retype(brw_vec16_reg(file, nr, 0), BRW_REGISTER_TYPE_UW), subnr);
535 }
536
537 /** Construct unsigned word[8] register */
538 static inline struct brw_reg
539 brw_uw8_reg(unsigned file, unsigned nr, unsigned subnr)
540 {
541 return suboffset(retype(brw_vec8_reg(file, nr, 0), BRW_REGISTER_TYPE_UW), subnr);
542 }
543
544 /** Construct unsigned word[1] register */
545 static inline struct brw_reg
546 brw_uw1_reg(unsigned file, unsigned nr, unsigned subnr)
547 {
548 return suboffset(retype(brw_vec1_reg(file, nr, 0), BRW_REGISTER_TYPE_UW), subnr);
549 }
550
551 static inline struct brw_reg
552 brw_imm_reg(enum brw_reg_type type)
553 {
554 return brw_reg(BRW_IMMEDIATE_VALUE,
555 0,
556 0,
557 0,
558 0,
559 type,
560 BRW_VERTICAL_STRIDE_0,
561 BRW_WIDTH_1,
562 BRW_HORIZONTAL_STRIDE_0,
563 0,
564 0);
565 }
566
567 /** Construct float immediate register */
568 static inline struct brw_reg
569 brw_imm_f(float f)
570 {
571 struct brw_reg imm = brw_imm_reg(BRW_REGISTER_TYPE_F);
572 imm.dw1.f = f;
573 return imm;
574 }
575
576 /** Construct integer immediate register */
577 static inline struct brw_reg
578 brw_imm_d(int d)
579 {
580 struct brw_reg imm = brw_imm_reg(BRW_REGISTER_TYPE_D);
581 imm.dw1.d = d;
582 return imm;
583 }
584
585 /** Construct uint immediate register */
586 static inline struct brw_reg
587 brw_imm_ud(unsigned ud)
588 {
589 struct brw_reg imm = brw_imm_reg(BRW_REGISTER_TYPE_UD);
590 imm.dw1.ud = ud;
591 return imm;
592 }
593
594 /** Construct ushort immediate register */
595 static inline struct brw_reg
596 brw_imm_uw(uint16_t uw)
597 {
598 struct brw_reg imm = brw_imm_reg(BRW_REGISTER_TYPE_UW);
599 imm.dw1.ud = uw | (uw << 16);
600 return imm;
601 }
602
603 /** Construct short immediate register */
604 static inline struct brw_reg
605 brw_imm_w(int16_t w)
606 {
607 struct brw_reg imm = brw_imm_reg(BRW_REGISTER_TYPE_W);
608 imm.dw1.d = w | (w << 16);
609 return imm;
610 }
611
612 /* brw_imm_b and brw_imm_ub aren't supported by hardware - the type
613 * numbers alias with _V and _VF below:
614 */
615
616 /** Construct vector of eight signed half-byte values */
617 static inline struct brw_reg
618 brw_imm_v(unsigned v)
619 {
620 struct brw_reg imm = brw_imm_reg(BRW_REGISTER_TYPE_V);
621 imm.vstride = BRW_VERTICAL_STRIDE_0;
622 imm.width = BRW_WIDTH_8;
623 imm.hstride = BRW_HORIZONTAL_STRIDE_1;
624 imm.dw1.ud = v;
625 return imm;
626 }
627
628 /** Construct vector of four 8-bit float values */
629 static inline struct brw_reg
630 brw_imm_vf(unsigned v)
631 {
632 struct brw_reg imm = brw_imm_reg(BRW_REGISTER_TYPE_VF);
633 imm.vstride = BRW_VERTICAL_STRIDE_0;
634 imm.width = BRW_WIDTH_4;
635 imm.hstride = BRW_HORIZONTAL_STRIDE_1;
636 imm.dw1.ud = v;
637 return imm;
638 }
639
640 /**
641 * Convert an integer into a "restricted" 8-bit float, used in vector
642 * immediates. The 8-bit floating point format has a sign bit, an
643 * excess-3 3-bit exponent, and a 4-bit mantissa. All integer values
644 * from -31 to 31 can be represented exactly.
645 */
646 static inline uint8_t
647 int_to_float8(int x)
648 {
649 if (x == 0) {
650 return 0;
651 } else if (x < 0) {
652 return 1 << 7 | int_to_float8(-x);
653 } else {
654 const unsigned exponent = _mesa_logbase2(x);
655 const unsigned mantissa = (x - (1 << exponent)) << (4 - exponent);
656 assert(exponent <= 4);
657 return (exponent + 3) << 4 | mantissa;
658 }
659 }
660
661 /**
662 * Construct a floating-point packed vector immediate from its integer
663 * values. \sa int_to_float8()
664 */
665 static inline struct brw_reg
666 brw_imm_vf4(int v0, int v1, int v2, int v3)
667 {
668 return brw_imm_vf((int_to_float8(v0) << 0) |
669 (int_to_float8(v1) << 8) |
670 (int_to_float8(v2) << 16) |
671 (int_to_float8(v3) << 24));
672 }
673
674
675 static inline struct brw_reg
676 brw_address(struct brw_reg reg)
677 {
678 return brw_imm_uw(reg.nr * REG_SIZE + reg.subnr);
679 }
680
681 /** Construct float[1] general-purpose register */
682 static inline struct brw_reg
683 brw_vec1_grf(unsigned nr, unsigned subnr)
684 {
685 return brw_vec1_reg(BRW_GENERAL_REGISTER_FILE, nr, subnr);
686 }
687
688 /** Construct float[2] general-purpose register */
689 static inline struct brw_reg
690 brw_vec2_grf(unsigned nr, unsigned subnr)
691 {
692 return brw_vec2_reg(BRW_GENERAL_REGISTER_FILE, nr, subnr);
693 }
694
695 /** Construct float[4] general-purpose register */
696 static inline struct brw_reg
697 brw_vec4_grf(unsigned nr, unsigned subnr)
698 {
699 return brw_vec4_reg(BRW_GENERAL_REGISTER_FILE, nr, subnr);
700 }
701
702 /** Construct float[8] general-purpose register */
703 static inline struct brw_reg
704 brw_vec8_grf(unsigned nr, unsigned subnr)
705 {
706 return brw_vec8_reg(BRW_GENERAL_REGISTER_FILE, nr, subnr);
707 }
708
709 /** Construct float[16] general-purpose register */
710 static inline struct brw_reg
711 brw_vec16_grf(unsigned nr, unsigned subnr)
712 {
713 return brw_vec16_reg(BRW_GENERAL_REGISTER_FILE, nr, subnr);
714 }
715
716
717 static inline struct brw_reg
718 brw_uw8_grf(unsigned nr, unsigned subnr)
719 {
720 return brw_uw8_reg(BRW_GENERAL_REGISTER_FILE, nr, subnr);
721 }
722
723 static inline struct brw_reg
724 brw_uw16_grf(unsigned nr, unsigned subnr)
725 {
726 return brw_uw16_reg(BRW_GENERAL_REGISTER_FILE, nr, subnr);
727 }
728
729
730 /** Construct null register (usually used for setting condition codes) */
731 static inline struct brw_reg
732 brw_null_reg(void)
733 {
734 return brw_vec8_reg(BRW_ARCHITECTURE_REGISTER_FILE, BRW_ARF_NULL, 0);
735 }
736
737 static inline struct brw_reg
738 brw_null_vec(unsigned width)
739 {
740 return brw_vecn_reg(width, BRW_ARCHITECTURE_REGISTER_FILE, BRW_ARF_NULL, 0);
741 }
742
743 static inline struct brw_reg
744 brw_address_reg(unsigned subnr)
745 {
746 return brw_uw1_reg(BRW_ARCHITECTURE_REGISTER_FILE, BRW_ARF_ADDRESS, subnr);
747 }
748
749 /* If/else instructions break in align16 mode if writemask & swizzle
750 * aren't xyzw. This goes against the convention for other scalar
751 * regs:
752 */
753 static inline struct brw_reg
754 brw_ip_reg(void)
755 {
756 return brw_reg(BRW_ARCHITECTURE_REGISTER_FILE,
757 BRW_ARF_IP,
758 0,
759 0,
760 0,
761 BRW_REGISTER_TYPE_UD,
762 BRW_VERTICAL_STRIDE_4, /* ? */
763 BRW_WIDTH_1,
764 BRW_HORIZONTAL_STRIDE_0,
765 BRW_SWIZZLE_XYZW, /* NOTE! */
766 WRITEMASK_XYZW); /* NOTE! */
767 }
768
769 static inline struct brw_reg
770 brw_notification_reg(void)
771 {
772 return brw_reg(BRW_ARCHITECTURE_REGISTER_FILE,
773 BRW_ARF_NOTIFICATION_COUNT,
774 0,
775 0,
776 0,
777 BRW_REGISTER_TYPE_UD,
778 BRW_VERTICAL_STRIDE_0,
779 BRW_WIDTH_1,
780 BRW_HORIZONTAL_STRIDE_0,
781 BRW_SWIZZLE_XXXX,
782 WRITEMASK_X);
783 }
784
785 static inline struct brw_reg
786 brw_acc_reg(unsigned width)
787 {
788 return brw_vecn_reg(width, BRW_ARCHITECTURE_REGISTER_FILE,
789 BRW_ARF_ACCUMULATOR, 0);
790 }
791
792 static inline struct brw_reg
793 brw_flag_reg(int reg, int subreg)
794 {
795 return brw_uw1_reg(BRW_ARCHITECTURE_REGISTER_FILE,
796 BRW_ARF_FLAG + reg, subreg);
797 }
798
799 /**
800 * Return the mask register present in Gen4-5, or the related register present
801 * in Gen7.5 and later hardware referred to as "channel enable" register in
802 * the documentation.
803 */
804 static inline struct brw_reg
805 brw_mask_reg(unsigned subnr)
806 {
807 return brw_uw1_reg(BRW_ARCHITECTURE_REGISTER_FILE, BRW_ARF_MASK, subnr);
808 }
809
810 static inline struct brw_reg
811 brw_message_reg(unsigned nr)
812 {
813 return brw_vec8_reg(BRW_MESSAGE_REGISTER_FILE, nr, 0);
814 }
815
816 static inline struct brw_reg
817 brw_uvec_mrf(unsigned width, unsigned nr, unsigned subnr)
818 {
819 return retype(brw_vecn_reg(width, BRW_MESSAGE_REGISTER_FILE, nr, subnr),
820 BRW_REGISTER_TYPE_UD);
821 }
822
823 /* This is almost always called with a numeric constant argument, so
824 * make things easy to evaluate at compile time:
825 */
826 static inline unsigned cvt(unsigned val)
827 {
828 switch (val) {
829 case 0: return 0;
830 case 1: return 1;
831 case 2: return 2;
832 case 4: return 3;
833 case 8: return 4;
834 case 16: return 5;
835 case 32: return 6;
836 }
837 return 0;
838 }
839
840 static inline struct brw_reg
841 stride(struct brw_reg reg, unsigned vstride, unsigned width, unsigned hstride)
842 {
843 reg.vstride = cvt(vstride);
844 reg.width = cvt(width) - 1;
845 reg.hstride = cvt(hstride);
846 return reg;
847 }
848
849 /**
850 * Multiply the vertical and horizontal stride of a register by the given
851 * factor \a s.
852 */
853 static inline struct brw_reg
854 spread(struct brw_reg reg, unsigned s)
855 {
856 if (s) {
857 assert(_mesa_is_pow_two(s));
858
859 if (reg.hstride)
860 reg.hstride += cvt(s) - 1;
861
862 if (reg.vstride)
863 reg.vstride += cvt(s) - 1;
864
865 return reg;
866 } else {
867 return stride(reg, 0, 1, 0);
868 }
869 }
870
871 static inline struct brw_reg
872 vec16(struct brw_reg reg)
873 {
874 return stride(reg, 16,16,1);
875 }
876
877 static inline struct brw_reg
878 vec8(struct brw_reg reg)
879 {
880 return stride(reg, 8,8,1);
881 }
882
883 static inline struct brw_reg
884 vec4(struct brw_reg reg)
885 {
886 return stride(reg, 4,4,1);
887 }
888
889 static inline struct brw_reg
890 vec2(struct brw_reg reg)
891 {
892 return stride(reg, 2,2,1);
893 }
894
895 static inline struct brw_reg
896 vec1(struct brw_reg reg)
897 {
898 return stride(reg, 0,1,0);
899 }
900
901
902 static inline struct brw_reg
903 get_element(struct brw_reg reg, unsigned elt)
904 {
905 return vec1(suboffset(reg, elt));
906 }
907
908 static inline struct brw_reg
909 get_element_ud(struct brw_reg reg, unsigned elt)
910 {
911 return vec1(suboffset(retype(reg, BRW_REGISTER_TYPE_UD), elt));
912 }
913
914 static inline struct brw_reg
915 get_element_d(struct brw_reg reg, unsigned elt)
916 {
917 return vec1(suboffset(retype(reg, BRW_REGISTER_TYPE_D), elt));
918 }
919
920
921 static inline struct brw_reg
922 brw_swizzle(struct brw_reg reg, unsigned x, unsigned y, unsigned z, unsigned w)
923 {
924 assert(reg.file != BRW_IMMEDIATE_VALUE);
925
926 reg.dw1.bits.swizzle = brw_compose_swizzle(BRW_SWIZZLE4(x, y, z, w),
927 reg.dw1.bits.swizzle);
928 return reg;
929 }
930
931
932 static inline struct brw_reg
933 brw_swizzle1(struct brw_reg reg, unsigned x)
934 {
935 return brw_swizzle(reg, x, x, x, x);
936 }
937
938 static inline struct brw_reg
939 brw_writemask(struct brw_reg reg, unsigned mask)
940 {
941 assert(reg.file != BRW_IMMEDIATE_VALUE);
942 reg.dw1.bits.writemask &= mask;
943 return reg;
944 }
945
946 static inline struct brw_reg
947 brw_set_writemask(struct brw_reg reg, unsigned mask)
948 {
949 assert(reg.file != BRW_IMMEDIATE_VALUE);
950 reg.dw1.bits.writemask = mask;
951 return reg;
952 }
953
954 static inline unsigned
955 brw_writemask_for_size(unsigned n)
956 {
957 return (1 << n) - 1;
958 }
959
960 static inline struct brw_reg
961 negate(struct brw_reg reg)
962 {
963 reg.negate ^= 1;
964 return reg;
965 }
966
967 static inline struct brw_reg
968 brw_abs(struct brw_reg reg)
969 {
970 reg.abs = 1;
971 reg.negate = 0;
972 return reg;
973 }
974
975 /************************************************************************/
976
977 static inline struct brw_reg
978 brw_vec4_indirect(unsigned subnr, int offset)
979 {
980 struct brw_reg reg = brw_vec4_grf(0, 0);
981 reg.subnr = subnr;
982 reg.address_mode = BRW_ADDRESS_REGISTER_INDIRECT_REGISTER;
983 reg.dw1.bits.indirect_offset = offset;
984 return reg;
985 }
986
987 static inline struct brw_reg
988 brw_vec1_indirect(unsigned subnr, int offset)
989 {
990 struct brw_reg reg = brw_vec1_grf(0, 0);
991 reg.subnr = subnr;
992 reg.address_mode = BRW_ADDRESS_REGISTER_INDIRECT_REGISTER;
993 reg.dw1.bits.indirect_offset = offset;
994 return reg;
995 }
996
997 static inline struct brw_reg
998 deref_4f(struct brw_indirect ptr, int offset)
999 {
1000 return brw_vec4_indirect(ptr.addr_subnr, ptr.addr_offset + offset);
1001 }
1002
1003 static inline struct brw_reg
1004 deref_1f(struct brw_indirect ptr, int offset)
1005 {
1006 return brw_vec1_indirect(ptr.addr_subnr, ptr.addr_offset + offset);
1007 }
1008
1009 static inline struct brw_reg
1010 deref_4b(struct brw_indirect ptr, int offset)
1011 {
1012 return retype(deref_4f(ptr, offset), BRW_REGISTER_TYPE_B);
1013 }
1014
1015 static inline struct brw_reg
1016 deref_1uw(struct brw_indirect ptr, int offset)
1017 {
1018 return retype(deref_1f(ptr, offset), BRW_REGISTER_TYPE_UW);
1019 }
1020
1021 static inline struct brw_reg
1022 deref_1d(struct brw_indirect ptr, int offset)
1023 {
1024 return retype(deref_1f(ptr, offset), BRW_REGISTER_TYPE_D);
1025 }
1026
1027 static inline struct brw_reg
1028 deref_1ud(struct brw_indirect ptr, int offset)
1029 {
1030 return retype(deref_1f(ptr, offset), BRW_REGISTER_TYPE_UD);
1031 }
1032
1033 static inline struct brw_reg
1034 get_addr_reg(struct brw_indirect ptr)
1035 {
1036 return brw_address_reg(ptr.addr_subnr);
1037 }
1038
1039 static inline struct brw_indirect
1040 brw_indirect_offset(struct brw_indirect ptr, int offset)
1041 {
1042 ptr.addr_offset += offset;
1043 return ptr;
1044 }
1045
1046 static inline struct brw_indirect
1047 brw_indirect(unsigned addr_subnr, int offset)
1048 {
1049 struct brw_indirect ptr;
1050 ptr.addr_subnr = addr_subnr;
1051 ptr.addr_offset = offset;
1052 ptr.pad = 0;
1053 return ptr;
1054 }
1055
1056 static inline bool
1057 region_matches(struct brw_reg reg, enum brw_vertical_stride v,
1058 enum brw_width w, enum brw_horizontal_stride h)
1059 {
1060 return reg.vstride == v &&
1061 reg.width == w &&
1062 reg.hstride == h;
1063 }
1064
1065 #define has_scalar_region(reg) \
1066 region_matches(reg, BRW_VERTICAL_STRIDE_0, BRW_WIDTH_1, \
1067 BRW_HORIZONTAL_STRIDE_0)
1068
1069 /* brw_packed_float.c */
1070 int brw_float_to_vf(float f);
1071 float brw_vf_to_float(unsigned char vf);
1072
1073 #ifdef __cplusplus
1074 }
1075 #endif
1076
1077 #endif