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