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