eaf6620998e50ac2a2f9e5e985f2d6d563cadf08
[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/imports.h"
47 #include "main/compiler.h"
48 #include "main/macros.h"
49 #include "program/prog_instruction.h"
50 #include "brw_defines.h"
51
52 #ifdef __cplusplus
53 extern "C" {
54 #endif
55
56 struct brw_context;
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 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_YZXW BRW_SWIZZLE4(1,2,0,3)
86 #define BRW_SWIZZLE_ZXYW BRW_SWIZZLE4(2,0,1,3)
87 #define BRW_SWIZZLE_ZWZW BRW_SWIZZLE4(2,3,2,3)
88
89 static inline bool
90 brw_is_single_value_swizzle(int swiz)
91 {
92 return (swiz == BRW_SWIZZLE_XXXX ||
93 swiz == BRW_SWIZZLE_YYYY ||
94 swiz == BRW_SWIZZLE_ZZZZ ||
95 swiz == BRW_SWIZZLE_WWWW);
96 }
97
98 enum PACKED brw_reg_type {
99 BRW_REGISTER_TYPE_UD = 0,
100 BRW_REGISTER_TYPE_D,
101 BRW_REGISTER_TYPE_UW,
102 BRW_REGISTER_TYPE_W,
103 BRW_REGISTER_TYPE_F,
104
105 /** Non-immediates only: @{ */
106 BRW_REGISTER_TYPE_UB,
107 BRW_REGISTER_TYPE_B,
108 /** @} */
109
110 /** Immediates only: @{ */
111 BRW_REGISTER_TYPE_UV,
112 BRW_REGISTER_TYPE_V,
113 BRW_REGISTER_TYPE_VF,
114 /** @} */
115
116 BRW_REGISTER_TYPE_DF, /* Gen7+ (no immediates until Gen8+) */
117
118 /* Gen8+ */
119 BRW_REGISTER_TYPE_HF,
120 BRW_REGISTER_TYPE_UQ,
121 BRW_REGISTER_TYPE_Q,
122 };
123
124 unsigned brw_reg_type_to_hw_type(const struct brw_context *brw,
125 enum brw_reg_type type, unsigned file);
126 const char *brw_reg_type_letters(unsigned brw_reg_type);
127
128 #define REG_SIZE (8*4)
129
130 /* These aren't hardware structs, just something useful for us to pass around:
131 *
132 * Align1 operation has a lot of control over input ranges. Used in
133 * WM programs to implement shaders decomposed into "channel serial"
134 * or "structure of array" form:
135 */
136 struct brw_reg {
137 enum brw_reg_type type:4;
138 unsigned file:2;
139 unsigned nr:8;
140 unsigned subnr:5; /* :1 in align16 */
141 unsigned negate:1; /* source only */
142 unsigned abs:1; /* source only */
143 unsigned vstride:4; /* source only */
144 unsigned width:3; /* src only, align1 only */
145 unsigned hstride:2; /* align1 only */
146 unsigned address_mode:1; /* relative addressing, hopefully! */
147 unsigned pad0:1;
148
149 union {
150 struct {
151 unsigned swizzle:8; /* src only, align16 only */
152 unsigned writemask:4; /* dest only, align16 only */
153 int indirect_offset:10; /* relative addressing offset */
154 unsigned pad1:10; /* two dwords total */
155 } bits;
156
157 float f;
158 int d;
159 unsigned ud;
160 } dw1;
161 };
162
163
164 struct brw_indirect {
165 unsigned addr_subnr:4;
166 int addr_offset:10;
167 unsigned pad:18;
168 };
169
170
171 static inline int
172 type_sz(unsigned type)
173 {
174 switch(type) {
175 case BRW_REGISTER_TYPE_UQ:
176 case BRW_REGISTER_TYPE_Q:
177 return 8;
178 case BRW_REGISTER_TYPE_UD:
179 case BRW_REGISTER_TYPE_D:
180 case BRW_REGISTER_TYPE_F:
181 return 4;
182 case BRW_REGISTER_TYPE_UW:
183 case BRW_REGISTER_TYPE_W:
184 return 2;
185 case BRW_REGISTER_TYPE_UB:
186 case BRW_REGISTER_TYPE_B:
187 return 1;
188 default:
189 return 0;
190 }
191 }
192
193 static inline bool
194 type_is_signed(unsigned type)
195 {
196 switch(type) {
197 case BRW_REGISTER_TYPE_D:
198 case BRW_REGISTER_TYPE_W:
199 case BRW_REGISTER_TYPE_F:
200 case BRW_REGISTER_TYPE_B:
201 case BRW_REGISTER_TYPE_V:
202 case BRW_REGISTER_TYPE_VF:
203 case BRW_REGISTER_TYPE_DF:
204 case BRW_REGISTER_TYPE_HF:
205 case BRW_REGISTER_TYPE_Q:
206 return true;
207
208 case BRW_REGISTER_TYPE_UD:
209 case BRW_REGISTER_TYPE_UW:
210 case BRW_REGISTER_TYPE_UB:
211 case BRW_REGISTER_TYPE_UV:
212 case BRW_REGISTER_TYPE_UQ:
213 return false;
214
215 default:
216 unreachable("not reached");
217 }
218 }
219
220 /**
221 * Construct a brw_reg.
222 * \param file one of the BRW_x_REGISTER_FILE values
223 * \param nr register number/index
224 * \param subnr register sub number
225 * \param negate register negate modifier
226 * \param abs register abs modifier
227 * \param type one of BRW_REGISTER_TYPE_x
228 * \param vstride one of BRW_VERTICAL_STRIDE_x
229 * \param width one of BRW_WIDTH_x
230 * \param hstride one of BRW_HORIZONTAL_STRIDE_x
231 * \param swizzle one of BRW_SWIZZLE_x
232 * \param writemask WRITEMASK_X/Y/Z/W bitfield
233 */
234 static inline struct brw_reg
235 brw_reg(unsigned file,
236 unsigned nr,
237 unsigned subnr,
238 unsigned negate,
239 unsigned abs,
240 enum brw_reg_type type,
241 unsigned vstride,
242 unsigned width,
243 unsigned hstride,
244 unsigned swizzle,
245 unsigned writemask)
246 {
247 struct brw_reg reg;
248 if (file == BRW_GENERAL_REGISTER_FILE)
249 assert(nr < BRW_MAX_GRF);
250 else if (file == BRW_MESSAGE_REGISTER_FILE)
251 assert((nr & ~(1 << 7)) < BRW_MAX_MRF);
252 else if (file == BRW_ARCHITECTURE_REGISTER_FILE)
253 assert(nr <= BRW_ARF_TIMESTAMP);
254
255 reg.type = type;
256 reg.file = file;
257 reg.nr = nr;
258 reg.subnr = subnr * type_sz(type);
259 reg.negate = negate;
260 reg.abs = abs;
261 reg.vstride = vstride;
262 reg.width = width;
263 reg.hstride = hstride;
264 reg.address_mode = BRW_ADDRESS_DIRECT;
265 reg.pad0 = 0;
266
267 /* Could do better: If the reg is r5.3<0;1,0>, we probably want to
268 * set swizzle and writemask to W, as the lower bits of subnr will
269 * be lost when converted to align16. This is probably too much to
270 * keep track of as you'd want it adjusted by suboffset(), etc.
271 * Perhaps fix up when converting to align16?
272 */
273 reg.dw1.bits.swizzle = swizzle;
274 reg.dw1.bits.writemask = writemask;
275 reg.dw1.bits.indirect_offset = 0;
276 reg.dw1.bits.pad1 = 0;
277 return reg;
278 }
279
280 /** Construct float[16] register */
281 static inline struct brw_reg
282 brw_vec16_reg(unsigned file, unsigned nr, unsigned subnr)
283 {
284 return brw_reg(file,
285 nr,
286 subnr,
287 0,
288 0,
289 BRW_REGISTER_TYPE_F,
290 BRW_VERTICAL_STRIDE_16,
291 BRW_WIDTH_16,
292 BRW_HORIZONTAL_STRIDE_1,
293 BRW_SWIZZLE_XYZW,
294 WRITEMASK_XYZW);
295 }
296
297 /** Construct float[8] register */
298 static inline struct brw_reg
299 brw_vec8_reg(unsigned file, unsigned nr, unsigned subnr)
300 {
301 return brw_reg(file,
302 nr,
303 subnr,
304 0,
305 0,
306 BRW_REGISTER_TYPE_F,
307 BRW_VERTICAL_STRIDE_8,
308 BRW_WIDTH_8,
309 BRW_HORIZONTAL_STRIDE_1,
310 BRW_SWIZZLE_XYZW,
311 WRITEMASK_XYZW);
312 }
313
314 /** Construct float[4] register */
315 static inline struct brw_reg
316 brw_vec4_reg(unsigned file, unsigned nr, unsigned subnr)
317 {
318 return brw_reg(file,
319 nr,
320 subnr,
321 0,
322 0,
323 BRW_REGISTER_TYPE_F,
324 BRW_VERTICAL_STRIDE_4,
325 BRW_WIDTH_4,
326 BRW_HORIZONTAL_STRIDE_1,
327 BRW_SWIZZLE_XYZW,
328 WRITEMASK_XYZW);
329 }
330
331 /** Construct float[2] register */
332 static inline struct brw_reg
333 brw_vec2_reg(unsigned file, unsigned nr, unsigned subnr)
334 {
335 return brw_reg(file,
336 nr,
337 subnr,
338 0,
339 0,
340 BRW_REGISTER_TYPE_F,
341 BRW_VERTICAL_STRIDE_2,
342 BRW_WIDTH_2,
343 BRW_HORIZONTAL_STRIDE_1,
344 BRW_SWIZZLE_XYXY,
345 WRITEMASK_XY);
346 }
347
348 /** Construct float[1] register */
349 static inline struct brw_reg
350 brw_vec1_reg(unsigned file, unsigned nr, unsigned subnr)
351 {
352 return brw_reg(file,
353 nr,
354 subnr,
355 0,
356 0,
357 BRW_REGISTER_TYPE_F,
358 BRW_VERTICAL_STRIDE_0,
359 BRW_WIDTH_1,
360 BRW_HORIZONTAL_STRIDE_0,
361 BRW_SWIZZLE_XXXX,
362 WRITEMASK_X);
363 }
364
365 static inline struct brw_reg
366 brw_vecn_reg(unsigned width, unsigned file, unsigned nr, unsigned subnr)
367 {
368 switch (width) {
369 case 1:
370 return brw_vec1_reg(file, nr, subnr);
371 case 2:
372 return brw_vec2_reg(file, nr, subnr);
373 case 4:
374 return brw_vec4_reg(file, nr, subnr);
375 case 8:
376 return brw_vec8_reg(file, nr, subnr);
377 case 16:
378 return brw_vec16_reg(file, nr, subnr);
379 default:
380 unreachable("Invalid register width");
381 }
382 }
383
384 static inline struct brw_reg
385 retype(struct brw_reg reg, enum brw_reg_type type)
386 {
387 reg.type = type;
388 return reg;
389 }
390
391 static inline struct brw_reg
392 firsthalf(struct brw_reg reg)
393 {
394 return reg;
395 }
396
397 static inline struct brw_reg
398 sechalf(struct brw_reg reg)
399 {
400 if (reg.vstride)
401 reg.nr++;
402 return reg;
403 }
404
405 static inline struct brw_reg
406 suboffset(struct brw_reg reg, unsigned delta)
407 {
408 reg.subnr += delta * type_sz(reg.type);
409 return reg;
410 }
411
412
413 static inline struct brw_reg
414 offset(struct brw_reg reg, unsigned delta)
415 {
416 reg.nr += delta;
417 return reg;
418 }
419
420
421 static inline struct brw_reg
422 byte_offset(struct brw_reg reg, unsigned bytes)
423 {
424 unsigned newoffset = reg.nr * REG_SIZE + reg.subnr + bytes;
425 reg.nr = newoffset / REG_SIZE;
426 reg.subnr = newoffset % REG_SIZE;
427 return reg;
428 }
429
430
431 /** Construct unsigned word[16] register */
432 static inline struct brw_reg
433 brw_uw16_reg(unsigned file, unsigned nr, unsigned subnr)
434 {
435 return suboffset(retype(brw_vec16_reg(file, nr, 0), BRW_REGISTER_TYPE_UW), subnr);
436 }
437
438 /** Construct unsigned word[8] register */
439 static inline struct brw_reg
440 brw_uw8_reg(unsigned file, unsigned nr, unsigned subnr)
441 {
442 return suboffset(retype(brw_vec8_reg(file, nr, 0), BRW_REGISTER_TYPE_UW), subnr);
443 }
444
445 /** Construct unsigned word[1] register */
446 static inline struct brw_reg
447 brw_uw1_reg(unsigned file, unsigned nr, unsigned subnr)
448 {
449 return suboffset(retype(brw_vec1_reg(file, nr, 0), BRW_REGISTER_TYPE_UW), subnr);
450 }
451
452 static inline struct brw_reg
453 brw_imm_reg(enum brw_reg_type type)
454 {
455 return brw_reg(BRW_IMMEDIATE_VALUE,
456 0,
457 0,
458 0,
459 0,
460 type,
461 BRW_VERTICAL_STRIDE_0,
462 BRW_WIDTH_1,
463 BRW_HORIZONTAL_STRIDE_0,
464 0,
465 0);
466 }
467
468 /** Construct float immediate register */
469 static inline struct brw_reg
470 brw_imm_f(float f)
471 {
472 struct brw_reg imm = brw_imm_reg(BRW_REGISTER_TYPE_F);
473 imm.dw1.f = f;
474 return imm;
475 }
476
477 /** Construct integer immediate register */
478 static inline struct brw_reg
479 brw_imm_d(int d)
480 {
481 struct brw_reg imm = brw_imm_reg(BRW_REGISTER_TYPE_D);
482 imm.dw1.d = d;
483 return imm;
484 }
485
486 /** Construct uint immediate register */
487 static inline struct brw_reg
488 brw_imm_ud(unsigned ud)
489 {
490 struct brw_reg imm = brw_imm_reg(BRW_REGISTER_TYPE_UD);
491 imm.dw1.ud = ud;
492 return imm;
493 }
494
495 /** Construct ushort immediate register */
496 static inline struct brw_reg
497 brw_imm_uw(uint16_t uw)
498 {
499 struct brw_reg imm = brw_imm_reg(BRW_REGISTER_TYPE_UW);
500 imm.dw1.ud = uw | (uw << 16);
501 return imm;
502 }
503
504 /** Construct short immediate register */
505 static inline struct brw_reg
506 brw_imm_w(int16_t w)
507 {
508 struct brw_reg imm = brw_imm_reg(BRW_REGISTER_TYPE_W);
509 imm.dw1.d = w | (w << 16);
510 return imm;
511 }
512
513 /* brw_imm_b and brw_imm_ub aren't supported by hardware - the type
514 * numbers alias with _V and _VF below:
515 */
516
517 /** Construct vector of eight signed half-byte values */
518 static inline struct brw_reg
519 brw_imm_v(unsigned v)
520 {
521 struct brw_reg imm = brw_imm_reg(BRW_REGISTER_TYPE_V);
522 imm.vstride = BRW_VERTICAL_STRIDE_0;
523 imm.width = BRW_WIDTH_8;
524 imm.hstride = BRW_HORIZONTAL_STRIDE_1;
525 imm.dw1.ud = v;
526 return imm;
527 }
528
529 /** Construct vector of four 8-bit float values */
530 static inline struct brw_reg
531 brw_imm_vf(unsigned v)
532 {
533 struct brw_reg imm = brw_imm_reg(BRW_REGISTER_TYPE_VF);
534 imm.vstride = BRW_VERTICAL_STRIDE_0;
535 imm.width = BRW_WIDTH_4;
536 imm.hstride = BRW_HORIZONTAL_STRIDE_1;
537 imm.dw1.ud = v;
538 return imm;
539 }
540
541 /**
542 * Convert an integer into a "restricted" 8-bit float, used in vector
543 * immediates. The 8-bit floating point format has a sign bit, an
544 * excess-3 3-bit exponent, and a 4-bit mantissa. All integer values
545 * from -31 to 31 can be represented exactly.
546 */
547 static inline uint8_t
548 int_to_float8(int x)
549 {
550 if (x == 0) {
551 return 0;
552 } else if (x < 0) {
553 return 1 << 7 | int_to_float8(-x);
554 } else {
555 const unsigned exponent = _mesa_logbase2(x);
556 const unsigned mantissa = (x - (1 << exponent)) << (4 - exponent);
557 assert(exponent <= 4);
558 return (exponent + 3) << 4 | mantissa;
559 }
560 }
561
562 /**
563 * Construct a floating-point packed vector immediate from its integer
564 * values. \sa int_to_float8()
565 */
566 static inline struct brw_reg
567 brw_imm_vf4(int v0, int v1, int v2, int v3)
568 {
569 return brw_imm_vf((int_to_float8(v0) << 0) |
570 (int_to_float8(v1) << 8) |
571 (int_to_float8(v2) << 16) |
572 (int_to_float8(v3) << 24));
573 }
574
575
576 static inline struct brw_reg
577 brw_address(struct brw_reg reg)
578 {
579 return brw_imm_uw(reg.nr * REG_SIZE + reg.subnr);
580 }
581
582 /** Construct float[1] general-purpose register */
583 static inline struct brw_reg
584 brw_vec1_grf(unsigned nr, unsigned subnr)
585 {
586 return brw_vec1_reg(BRW_GENERAL_REGISTER_FILE, nr, subnr);
587 }
588
589 /** Construct float[2] general-purpose register */
590 static inline struct brw_reg
591 brw_vec2_grf(unsigned nr, unsigned subnr)
592 {
593 return brw_vec2_reg(BRW_GENERAL_REGISTER_FILE, nr, subnr);
594 }
595
596 /** Construct float[4] general-purpose register */
597 static inline struct brw_reg
598 brw_vec4_grf(unsigned nr, unsigned subnr)
599 {
600 return brw_vec4_reg(BRW_GENERAL_REGISTER_FILE, nr, subnr);
601 }
602
603 /** Construct float[8] general-purpose register */
604 static inline struct brw_reg
605 brw_vec8_grf(unsigned nr, unsigned subnr)
606 {
607 return brw_vec8_reg(BRW_GENERAL_REGISTER_FILE, nr, subnr);
608 }
609
610
611 static inline struct brw_reg
612 brw_uw8_grf(unsigned nr, unsigned subnr)
613 {
614 return brw_uw8_reg(BRW_GENERAL_REGISTER_FILE, nr, subnr);
615 }
616
617 static inline struct brw_reg
618 brw_uw16_grf(unsigned nr, unsigned subnr)
619 {
620 return brw_uw16_reg(BRW_GENERAL_REGISTER_FILE, nr, subnr);
621 }
622
623
624 /** Construct null register (usually used for setting condition codes) */
625 static inline struct brw_reg
626 brw_null_reg(void)
627 {
628 return brw_vec8_reg(BRW_ARCHITECTURE_REGISTER_FILE, BRW_ARF_NULL, 0);
629 }
630
631 static inline struct brw_reg
632 brw_null_vec(unsigned width)
633 {
634 return brw_vecn_reg(width, BRW_ARCHITECTURE_REGISTER_FILE, BRW_ARF_NULL, 0);
635 }
636
637 static inline struct brw_reg
638 brw_address_reg(unsigned subnr)
639 {
640 return brw_uw1_reg(BRW_ARCHITECTURE_REGISTER_FILE, BRW_ARF_ADDRESS, subnr);
641 }
642
643 /* If/else instructions break in align16 mode if writemask & swizzle
644 * aren't xyzw. This goes against the convention for other scalar
645 * regs:
646 */
647 static inline struct brw_reg
648 brw_ip_reg(void)
649 {
650 return brw_reg(BRW_ARCHITECTURE_REGISTER_FILE,
651 BRW_ARF_IP,
652 0,
653 0,
654 0,
655 BRW_REGISTER_TYPE_UD,
656 BRW_VERTICAL_STRIDE_4, /* ? */
657 BRW_WIDTH_1,
658 BRW_HORIZONTAL_STRIDE_0,
659 BRW_SWIZZLE_XYZW, /* NOTE! */
660 WRITEMASK_XYZW); /* NOTE! */
661 }
662
663 static inline struct brw_reg
664 brw_acc_reg(unsigned width)
665 {
666 return brw_vecn_reg(width, BRW_ARCHITECTURE_REGISTER_FILE,
667 BRW_ARF_ACCUMULATOR, 0);
668 }
669
670 static inline struct brw_reg
671 brw_flag_reg(int reg, int subreg)
672 {
673 return brw_uw1_reg(BRW_ARCHITECTURE_REGISTER_FILE,
674 BRW_ARF_FLAG + reg, subreg);
675 }
676
677
678 static inline struct brw_reg
679 brw_mask_reg(unsigned subnr)
680 {
681 return brw_uw1_reg(BRW_ARCHITECTURE_REGISTER_FILE, BRW_ARF_MASK, subnr);
682 }
683
684 static inline struct brw_reg
685 brw_message_reg(unsigned nr)
686 {
687 assert((nr & ~(1 << 7)) < BRW_MAX_MRF);
688 return brw_vec8_reg(BRW_MESSAGE_REGISTER_FILE, nr, 0);
689 }
690
691 static inline struct brw_reg
692 brw_uvec_mrf(unsigned width, unsigned nr, unsigned subnr)
693 {
694 return retype(brw_vecn_reg(width, BRW_MESSAGE_REGISTER_FILE, nr, subnr),
695 BRW_REGISTER_TYPE_UD);
696 }
697
698 /* This is almost always called with a numeric constant argument, so
699 * make things easy to evaluate at compile time:
700 */
701 static inline unsigned cvt(unsigned val)
702 {
703 switch (val) {
704 case 0: return 0;
705 case 1: return 1;
706 case 2: return 2;
707 case 4: return 3;
708 case 8: return 4;
709 case 16: return 5;
710 case 32: return 6;
711 }
712 return 0;
713 }
714
715 static inline struct brw_reg
716 stride(struct brw_reg reg, unsigned vstride, unsigned width, unsigned hstride)
717 {
718 reg.vstride = cvt(vstride);
719 reg.width = cvt(width) - 1;
720 reg.hstride = cvt(hstride);
721 return reg;
722 }
723
724 /**
725 * Multiply the vertical and horizontal stride of a register by the given
726 * factor \a s.
727 */
728 static inline struct brw_reg
729 spread(struct brw_reg reg, unsigned s)
730 {
731 if (s) {
732 assert(is_power_of_two(s));
733
734 if (reg.hstride)
735 reg.hstride += cvt(s) - 1;
736
737 if (reg.vstride)
738 reg.vstride += cvt(s) - 1;
739
740 return reg;
741 } else {
742 return stride(reg, 0, 1, 0);
743 }
744 }
745
746 static inline struct brw_reg
747 vec16(struct brw_reg reg)
748 {
749 return stride(reg, 16,16,1);
750 }
751
752 static inline struct brw_reg
753 vec8(struct brw_reg reg)
754 {
755 return stride(reg, 8,8,1);
756 }
757
758 static inline struct brw_reg
759 vec4(struct brw_reg reg)
760 {
761 return stride(reg, 4,4,1);
762 }
763
764 static inline struct brw_reg
765 vec2(struct brw_reg reg)
766 {
767 return stride(reg, 2,2,1);
768 }
769
770 static inline struct brw_reg
771 vec1(struct brw_reg reg)
772 {
773 return stride(reg, 0,1,0);
774 }
775
776
777 static inline struct brw_reg
778 get_element(struct brw_reg reg, unsigned elt)
779 {
780 return vec1(suboffset(reg, elt));
781 }
782
783 static inline struct brw_reg
784 get_element_ud(struct brw_reg reg, unsigned elt)
785 {
786 return vec1(suboffset(retype(reg, BRW_REGISTER_TYPE_UD), elt));
787 }
788
789 static inline struct brw_reg
790 get_element_d(struct brw_reg reg, unsigned elt)
791 {
792 return vec1(suboffset(retype(reg, BRW_REGISTER_TYPE_D), elt));
793 }
794
795
796 static inline struct brw_reg
797 brw_swizzle(struct brw_reg reg, unsigned x, unsigned y, unsigned z, unsigned w)
798 {
799 assert(reg.file != BRW_IMMEDIATE_VALUE);
800
801 reg.dw1.bits.swizzle = BRW_SWIZZLE4(BRW_GET_SWZ(reg.dw1.bits.swizzle, x),
802 BRW_GET_SWZ(reg.dw1.bits.swizzle, y),
803 BRW_GET_SWZ(reg.dw1.bits.swizzle, z),
804 BRW_GET_SWZ(reg.dw1.bits.swizzle, w));
805 return reg;
806 }
807
808
809 static inline struct brw_reg
810 brw_swizzle1(struct brw_reg reg, unsigned x)
811 {
812 return brw_swizzle(reg, x, x, x, x);
813 }
814
815 static inline struct brw_reg
816 brw_writemask(struct brw_reg reg, unsigned mask)
817 {
818 assert(reg.file != BRW_IMMEDIATE_VALUE);
819 reg.dw1.bits.writemask &= mask;
820 return reg;
821 }
822
823 static inline struct brw_reg
824 brw_set_writemask(struct brw_reg reg, unsigned mask)
825 {
826 assert(reg.file != BRW_IMMEDIATE_VALUE);
827 reg.dw1.bits.writemask = mask;
828 return reg;
829 }
830
831 static inline struct brw_reg
832 negate(struct brw_reg reg)
833 {
834 reg.negate ^= 1;
835 return reg;
836 }
837
838 static inline struct brw_reg
839 brw_abs(struct brw_reg reg)
840 {
841 reg.abs = 1;
842 reg.negate = 0;
843 return reg;
844 }
845
846 /************************************************************************/
847
848 static inline struct brw_reg
849 brw_vec4_indirect(unsigned subnr, int offset)
850 {
851 struct brw_reg reg = brw_vec4_grf(0, 0);
852 reg.subnr = subnr;
853 reg.address_mode = BRW_ADDRESS_REGISTER_INDIRECT_REGISTER;
854 reg.dw1.bits.indirect_offset = offset;
855 return reg;
856 }
857
858 static inline struct brw_reg
859 brw_vec1_indirect(unsigned subnr, int offset)
860 {
861 struct brw_reg reg = brw_vec1_grf(0, 0);
862 reg.subnr = subnr;
863 reg.address_mode = BRW_ADDRESS_REGISTER_INDIRECT_REGISTER;
864 reg.dw1.bits.indirect_offset = offset;
865 return reg;
866 }
867
868 static inline struct brw_reg
869 deref_4f(struct brw_indirect ptr, int offset)
870 {
871 return brw_vec4_indirect(ptr.addr_subnr, ptr.addr_offset + offset);
872 }
873
874 static inline struct brw_reg
875 deref_1f(struct brw_indirect ptr, int offset)
876 {
877 return brw_vec1_indirect(ptr.addr_subnr, ptr.addr_offset + offset);
878 }
879
880 static inline struct brw_reg
881 deref_4b(struct brw_indirect ptr, int offset)
882 {
883 return retype(deref_4f(ptr, offset), BRW_REGISTER_TYPE_B);
884 }
885
886 static inline struct brw_reg
887 deref_1uw(struct brw_indirect ptr, int offset)
888 {
889 return retype(deref_1f(ptr, offset), BRW_REGISTER_TYPE_UW);
890 }
891
892 static inline struct brw_reg
893 deref_1d(struct brw_indirect ptr, int offset)
894 {
895 return retype(deref_1f(ptr, offset), BRW_REGISTER_TYPE_D);
896 }
897
898 static inline struct brw_reg
899 deref_1ud(struct brw_indirect ptr, int offset)
900 {
901 return retype(deref_1f(ptr, offset), BRW_REGISTER_TYPE_UD);
902 }
903
904 static inline struct brw_reg
905 get_addr_reg(struct brw_indirect ptr)
906 {
907 return brw_address_reg(ptr.addr_subnr);
908 }
909
910 static inline struct brw_indirect
911 brw_indirect_offset(struct brw_indirect ptr, int offset)
912 {
913 ptr.addr_offset += offset;
914 return ptr;
915 }
916
917 static inline struct brw_indirect
918 brw_indirect(unsigned addr_subnr, int offset)
919 {
920 struct brw_indirect ptr;
921 ptr.addr_subnr = addr_subnr;
922 ptr.addr_offset = offset;
923 ptr.pad = 0;
924 return ptr;
925 }
926
927 static inline bool
928 region_matches(struct brw_reg reg, enum brw_vertical_stride v,
929 enum brw_width w, enum brw_horizontal_stride h)
930 {
931 return reg.vstride == v &&
932 reg.width == w &&
933 reg.hstride == h;
934 }
935
936 #define has_scalar_region(reg) \
937 region_matches(reg, BRW_VERTICAL_STRIDE_0, BRW_WIDTH_1, \
938 BRW_HORIZONTAL_STRIDE_0)
939
940 /* brw_packed_float.c */
941 int brw_float_to_vf(float f);
942 float brw_vf_to_float(unsigned char vf);
943
944 #ifdef __cplusplus
945 }
946 #endif
947
948 #endif