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