2 Copyright (C) Intel Corp. 2006. All Rights Reserved.
3 Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to
4 develop this 3D driver.
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:
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.
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.
26 **********************************************************************/
29 * Keith Whitwell <keith@tungstengraphics.com>
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.
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.
46 #include "program/prog_instruction.h"
47 #include "brw_defines.h"
53 /** Number of general purpose registers (VS, WM, etc) */
54 #define BRW_MAX_GRF 128
57 * First GRF used for the MRF hack.
59 * On gen7, MRFs are no longer used, and contiguous GRFs are used instead. We
60 * haven't converted our compiler to be aware of this, so it asks for MRFs and
61 * brw_eu_emit.c quietly converts them to be accesses of the top GRFs. The
62 * register allocators have to be careful of this to avoid corrupting the "MRF"s
63 * with actual GRF allocations.
65 #define GEN7_MRF_HACK_START 112
67 /** Number of message register file registers */
68 #define BRW_MAX_MRF 16
70 #define BRW_SWIZZLE4(a,b,c,d) (((a)<<0) | ((b)<<2) | ((c)<<4) | ((d)<<6))
71 #define BRW_GET_SWZ(swz, idx) (((swz) >> ((idx)*2)) & 0x3)
73 #define BRW_SWIZZLE_NOOP BRW_SWIZZLE4(0,1,2,3)
74 #define BRW_SWIZZLE_XYZW BRW_SWIZZLE4(0,1,2,3)
75 #define BRW_SWIZZLE_XXXX BRW_SWIZZLE4(0,0,0,0)
76 #define BRW_SWIZZLE_YYYY BRW_SWIZZLE4(1,1,1,1)
77 #define BRW_SWIZZLE_ZZZZ BRW_SWIZZLE4(2,2,2,2)
78 #define BRW_SWIZZLE_WWWW BRW_SWIZZLE4(3,3,3,3)
79 #define BRW_SWIZZLE_XYXY BRW_SWIZZLE4(0,1,0,1)
82 brw_is_single_value_swizzle(int swiz
)
84 return (swiz
== BRW_SWIZZLE_XXXX
||
85 swiz
== BRW_SWIZZLE_YYYY
||
86 swiz
== BRW_SWIZZLE_ZZZZ
||
87 swiz
== BRW_SWIZZLE_WWWW
);
90 #define REG_SIZE (8*4)
92 /* These aren't hardware structs, just something useful for us to pass around:
94 * Align1 operation has a lot of control over input ranges. Used in
95 * WM programs to implement shaders decomposed into "channel serial"
96 * or "structure of array" form:
102 unsigned subnr
:5; /* :1 in align16 */
103 unsigned negate
:1; /* source only */
104 unsigned abs
:1; /* source only */
105 unsigned vstride
:4; /* source only */
106 unsigned width
:3; /* src only, align1 only */
107 unsigned hstride
:2; /* align1 only */
108 unsigned address_mode
:1; /* relative addressing, hopefully! */
113 unsigned swizzle
:8; /* src only, align16 only */
114 unsigned writemask
:4; /* dest only, align16 only */
115 int indirect_offset
:10; /* relative addressing offset */
116 unsigned pad1
:10; /* two dwords total */
126 struct brw_indirect
{
127 unsigned addr_subnr
:4;
134 type_sz(unsigned type
)
137 case BRW_REGISTER_TYPE_UD
:
138 case BRW_REGISTER_TYPE_D
:
139 case BRW_REGISTER_TYPE_F
:
141 case BRW_REGISTER_TYPE_HF
:
142 case BRW_REGISTER_TYPE_UW
:
143 case BRW_REGISTER_TYPE_W
:
145 case BRW_REGISTER_TYPE_UB
:
146 case BRW_REGISTER_TYPE_B
:
154 * Construct a brw_reg.
155 * \param file one of the BRW_x_REGISTER_FILE values
156 * \param nr register number/index
157 * \param subnr register sub number
158 * \param type one of BRW_REGISTER_TYPE_x
159 * \param vstride one of BRW_VERTICAL_STRIDE_x
160 * \param width one of BRW_WIDTH_x
161 * \param hstride one of BRW_HORIZONTAL_STRIDE_x
162 * \param swizzle one of BRW_SWIZZLE_x
163 * \param writemask WRITEMASK_X/Y/Z/W bitfield
165 static inline struct brw_reg
166 brw_reg(unsigned file
,
177 if (file
== BRW_GENERAL_REGISTER_FILE
)
178 assert(nr
< BRW_MAX_GRF
);
179 else if (file
== BRW_MESSAGE_REGISTER_FILE
)
180 assert((nr
& ~(1 << 7)) < BRW_MAX_MRF
);
181 else if (file
== BRW_ARCHITECTURE_REGISTER_FILE
)
182 assert(nr
<= BRW_ARF_TIMESTAMP
);
187 reg
.subnr
= subnr
* type_sz(type
);
190 reg
.vstride
= vstride
;
192 reg
.hstride
= hstride
;
193 reg
.address_mode
= BRW_ADDRESS_DIRECT
;
196 /* Could do better: If the reg is r5.3<0;1,0>, we probably want to
197 * set swizzle and writemask to W, as the lower bits of subnr will
198 * be lost when converted to align16. This is probably too much to
199 * keep track of as you'd want it adjusted by suboffset(), etc.
200 * Perhaps fix up when converting to align16?
202 reg
.dw1
.bits
.swizzle
= swizzle
;
203 reg
.dw1
.bits
.writemask
= writemask
;
204 reg
.dw1
.bits
.indirect_offset
= 0;
205 reg
.dw1
.bits
.pad1
= 0;
209 /** Construct float[16] register */
210 static inline struct brw_reg
211 brw_vec16_reg(unsigned file
, unsigned nr
, unsigned subnr
)
217 BRW_VERTICAL_STRIDE_16
,
219 BRW_HORIZONTAL_STRIDE_1
,
224 /** Construct float[8] register */
225 static inline struct brw_reg
226 brw_vec8_reg(unsigned file
, unsigned nr
, unsigned subnr
)
232 BRW_VERTICAL_STRIDE_8
,
234 BRW_HORIZONTAL_STRIDE_1
,
239 /** Construct float[4] register */
240 static inline struct brw_reg
241 brw_vec4_reg(unsigned file
, unsigned nr
, unsigned subnr
)
247 BRW_VERTICAL_STRIDE_4
,
249 BRW_HORIZONTAL_STRIDE_1
,
254 /** Construct float[2] register */
255 static inline struct brw_reg
256 brw_vec2_reg(unsigned file
, unsigned nr
, unsigned subnr
)
262 BRW_VERTICAL_STRIDE_2
,
264 BRW_HORIZONTAL_STRIDE_1
,
269 /** Construct float[1] register */
270 static inline struct brw_reg
271 brw_vec1_reg(unsigned file
, unsigned nr
, unsigned subnr
)
277 BRW_VERTICAL_STRIDE_0
,
279 BRW_HORIZONTAL_STRIDE_0
,
285 static inline struct brw_reg
286 retype(struct brw_reg reg
, unsigned type
)
292 static inline struct brw_reg
293 sechalf(struct brw_reg reg
)
300 static inline struct brw_reg
301 suboffset(struct brw_reg reg
, unsigned delta
)
303 reg
.subnr
+= delta
* type_sz(reg
.type
);
308 static inline struct brw_reg
309 offset(struct brw_reg reg
, unsigned delta
)
316 static inline struct brw_reg
317 byte_offset(struct brw_reg reg
, unsigned bytes
)
319 unsigned newoffset
= reg
.nr
* REG_SIZE
+ reg
.subnr
+ bytes
;
320 reg
.nr
= newoffset
/ REG_SIZE
;
321 reg
.subnr
= newoffset
% REG_SIZE
;
326 /** Construct unsigned word[16] register */
327 static inline struct brw_reg
328 brw_uw16_reg(unsigned file
, unsigned nr
, unsigned subnr
)
330 return suboffset(retype(brw_vec16_reg(file
, nr
, 0), BRW_REGISTER_TYPE_UW
), subnr
);
333 /** Construct unsigned word[8] register */
334 static inline struct brw_reg
335 brw_uw8_reg(unsigned file
, unsigned nr
, unsigned subnr
)
337 return suboffset(retype(brw_vec8_reg(file
, nr
, 0), BRW_REGISTER_TYPE_UW
), subnr
);
340 /** Construct unsigned word[1] register */
341 static inline struct brw_reg
342 brw_uw1_reg(unsigned file
, unsigned nr
, unsigned subnr
)
344 return suboffset(retype(brw_vec1_reg(file
, nr
, 0), BRW_REGISTER_TYPE_UW
), subnr
);
347 /** Construct unsigned dword[1] register */
348 static inline struct brw_reg
349 brw_ud1_reg(unsigned file
, unsigned nr
, unsigned subnr
)
351 return suboffset(retype(brw_vec1_reg(file
, nr
, 0), BRW_REGISTER_TYPE_UD
), subnr
);
354 static inline struct brw_reg
355 brw_imm_reg(unsigned type
)
357 return brw_reg(BRW_IMMEDIATE_VALUE
,
361 BRW_VERTICAL_STRIDE_0
,
363 BRW_HORIZONTAL_STRIDE_0
,
368 /** Construct float immediate register */
369 static inline struct brw_reg
372 struct brw_reg imm
= brw_imm_reg(BRW_REGISTER_TYPE_F
);
377 /** Construct integer immediate register */
378 static inline struct brw_reg
381 struct brw_reg imm
= brw_imm_reg(BRW_REGISTER_TYPE_D
);
386 /** Construct uint immediate register */
387 static inline struct brw_reg
388 brw_imm_ud(unsigned ud
)
390 struct brw_reg imm
= brw_imm_reg(BRW_REGISTER_TYPE_UD
);
395 /** Construct ushort immediate register */
396 static inline struct brw_reg
397 brw_imm_uw(uint16_t uw
)
399 struct brw_reg imm
= brw_imm_reg(BRW_REGISTER_TYPE_UW
);
400 imm
.dw1
.ud
= uw
| (uw
<< 16);
404 /** Construct short immediate register */
405 static inline struct brw_reg
408 struct brw_reg imm
= brw_imm_reg(BRW_REGISTER_TYPE_W
);
409 imm
.dw1
.d
= w
| (w
<< 16);
413 /* brw_imm_b and brw_imm_ub aren't supported by hardware - the type
414 * numbers alias with _V and _VF below:
417 /** Construct vector of eight signed half-byte values */
418 static inline struct brw_reg
419 brw_imm_v(unsigned v
)
421 struct brw_reg imm
= brw_imm_reg(BRW_REGISTER_TYPE_V
);
422 imm
.vstride
= BRW_VERTICAL_STRIDE_0
;
423 imm
.width
= BRW_WIDTH_8
;
424 imm
.hstride
= BRW_HORIZONTAL_STRIDE_1
;
429 /** Construct vector of four 8-bit float values */
430 static inline struct brw_reg
431 brw_imm_vf(unsigned v
)
433 struct brw_reg imm
= brw_imm_reg(BRW_REGISTER_TYPE_VF
);
434 imm
.vstride
= BRW_VERTICAL_STRIDE_0
;
435 imm
.width
= BRW_WIDTH_4
;
436 imm
.hstride
= BRW_HORIZONTAL_STRIDE_1
;
443 #define VF_NEG (1<<7)
445 static inline struct brw_reg
446 brw_imm_vf4(unsigned v0
, unsigned v1
, unsigned v2
, unsigned v3
)
448 struct brw_reg imm
= brw_imm_reg(BRW_REGISTER_TYPE_VF
);
449 imm
.vstride
= BRW_VERTICAL_STRIDE_0
;
450 imm
.width
= BRW_WIDTH_4
;
451 imm
.hstride
= BRW_HORIZONTAL_STRIDE_1
;
452 imm
.dw1
.ud
= ((v0
<< 0) | (v1
<< 8) | (v2
<< 16) | (v3
<< 24));
457 static inline struct brw_reg
458 brw_address(struct brw_reg reg
)
460 return brw_imm_uw(reg
.nr
* REG_SIZE
+ reg
.subnr
);
463 /** Construct float[1] general-purpose register */
464 static inline struct brw_reg
465 brw_vec1_grf(unsigned nr
, unsigned subnr
)
467 return brw_vec1_reg(BRW_GENERAL_REGISTER_FILE
, nr
, subnr
);
470 /** Construct float[2] general-purpose register */
471 static inline struct brw_reg
472 brw_vec2_grf(unsigned nr
, unsigned subnr
)
474 return brw_vec2_reg(BRW_GENERAL_REGISTER_FILE
, nr
, subnr
);
477 /** Construct float[4] general-purpose register */
478 static inline struct brw_reg
479 brw_vec4_grf(unsigned nr
, unsigned subnr
)
481 return brw_vec4_reg(BRW_GENERAL_REGISTER_FILE
, nr
, subnr
);
484 /** Construct float[8] general-purpose register */
485 static inline struct brw_reg
486 brw_vec8_grf(unsigned nr
, unsigned subnr
)
488 return brw_vec8_reg(BRW_GENERAL_REGISTER_FILE
, nr
, subnr
);
492 static inline struct brw_reg
493 brw_uw8_grf(unsigned nr
, unsigned subnr
)
495 return brw_uw8_reg(BRW_GENERAL_REGISTER_FILE
, nr
, subnr
);
498 static inline struct brw_reg
499 brw_uw16_grf(unsigned nr
, unsigned subnr
)
501 return brw_uw16_reg(BRW_GENERAL_REGISTER_FILE
, nr
, subnr
);
505 /** Construct null register (usually used for setting condition codes) */
506 static inline struct brw_reg
509 return brw_vec8_reg(BRW_ARCHITECTURE_REGISTER_FILE
, BRW_ARF_NULL
, 0);
512 static inline struct brw_reg
513 brw_address_reg(unsigned subnr
)
515 return brw_uw1_reg(BRW_ARCHITECTURE_REGISTER_FILE
, BRW_ARF_ADDRESS
, subnr
);
518 /* If/else instructions break in align16 mode if writemask & swizzle
519 * aren't xyzw. This goes against the convention for other scalar
522 static inline struct brw_reg
525 return brw_reg(BRW_ARCHITECTURE_REGISTER_FILE
,
528 BRW_REGISTER_TYPE_UD
,
529 BRW_VERTICAL_STRIDE_4
, /* ? */
531 BRW_HORIZONTAL_STRIDE_0
,
532 BRW_SWIZZLE_XYZW
, /* NOTE! */
533 WRITEMASK_XYZW
); /* NOTE! */
536 static inline struct brw_reg
539 return brw_vec8_reg(BRW_ARCHITECTURE_REGISTER_FILE
, BRW_ARF_ACCUMULATOR
, 0);
542 static inline struct brw_reg
543 brw_notification_1_reg(void)
546 return brw_reg(BRW_ARCHITECTURE_REGISTER_FILE
,
547 BRW_ARF_NOTIFICATION_COUNT
,
549 BRW_REGISTER_TYPE_UD
,
550 BRW_VERTICAL_STRIDE_0
,
552 BRW_HORIZONTAL_STRIDE_0
,
558 static inline struct brw_reg
559 brw_flag_reg(int reg
, int subreg
)
561 return brw_uw1_reg(BRW_ARCHITECTURE_REGISTER_FILE
,
562 BRW_ARF_FLAG
+ reg
, subreg
);
566 static inline struct brw_reg
567 brw_mask_reg(unsigned subnr
)
569 return brw_uw1_reg(BRW_ARCHITECTURE_REGISTER_FILE
, BRW_ARF_MASK
, subnr
);
572 static inline struct brw_reg
573 brw_message_reg(unsigned nr
)
575 assert((nr
& ~(1 << 7)) < BRW_MAX_MRF
);
576 return brw_vec8_reg(BRW_MESSAGE_REGISTER_FILE
, nr
, 0);
580 /* This is almost always called with a numeric constant argument, so
581 * make things easy to evaluate at compile time:
583 static inline unsigned cvt(unsigned val
)
597 static inline struct brw_reg
598 stride(struct brw_reg reg
, unsigned vstride
, unsigned width
, unsigned hstride
)
600 reg
.vstride
= cvt(vstride
);
601 reg
.width
= cvt(width
) - 1;
602 reg
.hstride
= cvt(hstride
);
607 static inline struct brw_reg
608 vec16(struct brw_reg reg
)
610 return stride(reg
, 16,16,1);
613 static inline struct brw_reg
614 vec8(struct brw_reg reg
)
616 return stride(reg
, 8,8,1);
619 static inline struct brw_reg
620 vec4(struct brw_reg reg
)
622 return stride(reg
, 4,4,1);
625 static inline struct brw_reg
626 vec2(struct brw_reg reg
)
628 return stride(reg
, 2,2,1);
631 static inline struct brw_reg
632 vec1(struct brw_reg reg
)
634 return stride(reg
, 0,1,0);
638 static inline struct brw_reg
639 get_element(struct brw_reg reg
, unsigned elt
)
641 return vec1(suboffset(reg
, elt
));
644 static inline struct brw_reg
645 get_element_ud(struct brw_reg reg
, unsigned elt
)
647 return vec1(suboffset(retype(reg
, BRW_REGISTER_TYPE_UD
), elt
));
650 static inline struct brw_reg
651 get_element_d(struct brw_reg reg
, unsigned elt
)
653 return vec1(suboffset(retype(reg
, BRW_REGISTER_TYPE_D
), elt
));
657 static inline struct brw_reg
658 brw_swizzle(struct brw_reg reg
, unsigned x
, unsigned y
, unsigned z
, unsigned w
)
660 assert(reg
.file
!= BRW_IMMEDIATE_VALUE
);
662 reg
.dw1
.bits
.swizzle
= BRW_SWIZZLE4(BRW_GET_SWZ(reg
.dw1
.bits
.swizzle
, x
),
663 BRW_GET_SWZ(reg
.dw1
.bits
.swizzle
, y
),
664 BRW_GET_SWZ(reg
.dw1
.bits
.swizzle
, z
),
665 BRW_GET_SWZ(reg
.dw1
.bits
.swizzle
, w
));
670 static inline struct brw_reg
671 brw_swizzle1(struct brw_reg reg
, unsigned x
)
673 return brw_swizzle(reg
, x
, x
, x
, x
);
676 static inline struct brw_reg
677 brw_writemask(struct brw_reg reg
, unsigned mask
)
679 assert(reg
.file
!= BRW_IMMEDIATE_VALUE
);
680 reg
.dw1
.bits
.writemask
&= mask
;
684 static inline struct brw_reg
685 brw_set_writemask(struct brw_reg reg
, unsigned mask
)
687 assert(reg
.file
!= BRW_IMMEDIATE_VALUE
);
688 reg
.dw1
.bits
.writemask
= mask
;
692 static inline struct brw_reg
693 negate(struct brw_reg reg
)
699 static inline struct brw_reg
700 brw_abs(struct brw_reg reg
)
707 /************************************************************************/
709 static inline struct brw_reg
710 brw_vec4_indirect(unsigned subnr
, int offset
)
712 struct brw_reg reg
= brw_vec4_grf(0, 0);
714 reg
.address_mode
= BRW_ADDRESS_REGISTER_INDIRECT_REGISTER
;
715 reg
.dw1
.bits
.indirect_offset
= offset
;
719 static inline struct brw_reg
720 brw_vec1_indirect(unsigned subnr
, int offset
)
722 struct brw_reg reg
= brw_vec1_grf(0, 0);
724 reg
.address_mode
= BRW_ADDRESS_REGISTER_INDIRECT_REGISTER
;
725 reg
.dw1
.bits
.indirect_offset
= offset
;
729 static inline struct brw_reg
730 deref_4f(struct brw_indirect ptr
, int offset
)
732 return brw_vec4_indirect(ptr
.addr_subnr
, ptr
.addr_offset
+ offset
);
735 static inline struct brw_reg
736 deref_1f(struct brw_indirect ptr
, int offset
)
738 return brw_vec1_indirect(ptr
.addr_subnr
, ptr
.addr_offset
+ offset
);
741 static inline struct brw_reg
742 deref_4b(struct brw_indirect ptr
, int offset
)
744 return retype(deref_4f(ptr
, offset
), BRW_REGISTER_TYPE_B
);
747 static inline struct brw_reg
748 deref_1uw(struct brw_indirect ptr
, int offset
)
750 return retype(deref_1f(ptr
, offset
), BRW_REGISTER_TYPE_UW
);
753 static inline struct brw_reg
754 deref_1d(struct brw_indirect ptr
, int offset
)
756 return retype(deref_1f(ptr
, offset
), BRW_REGISTER_TYPE_D
);
759 static inline struct brw_reg
760 deref_1ud(struct brw_indirect ptr
, int offset
)
762 return retype(deref_1f(ptr
, offset
), BRW_REGISTER_TYPE_UD
);
765 static inline struct brw_reg
766 get_addr_reg(struct brw_indirect ptr
)
768 return brw_address_reg(ptr
.addr_subnr
);
771 static inline struct brw_indirect
772 brw_indirect_offset(struct brw_indirect ptr
, int offset
)
774 ptr
.addr_offset
+= offset
;
778 static inline struct brw_indirect
779 brw_indirect(unsigned addr_subnr
, int offset
)
781 struct brw_indirect ptr
;
782 ptr
.addr_subnr
= addr_subnr
;
783 ptr
.addr_offset
= offset
;
788 /** Do two brw_regs refer to the same register? */
790 brw_same_reg(struct brw_reg r1
, struct brw_reg r2
)
792 return r1
.file
== r2
.file
&& r1
.nr
== r2
.nr
;
795 void brw_print_reg(struct brw_reg reg
);