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