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