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