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