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