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