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