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)
80 #define BRW_SWIZZLE_ZWZW BRW_SWIZZLE4(2,3,2,3)
83 brw_is_single_value_swizzle(int swiz
)
85 return (swiz
== BRW_SWIZZLE_XXXX
||
86 swiz
== BRW_SWIZZLE_YYYY
||
87 swiz
== BRW_SWIZZLE_ZZZZ
||
88 swiz
== BRW_SWIZZLE_WWWW
);
92 BRW_REGISTER_TYPE_UD
= 0,
98 /** Non-immediates only: @{ */
103 /** Immediates only: @{ */
104 BRW_REGISTER_TYPE_UV
,
106 BRW_REGISTER_TYPE_VF
,
110 unsigned brw_reg_type_to_hw_type(const struct brw_context
*brw
,
111 enum brw_reg_type type
, unsigned file
);
113 #define REG_SIZE (8*4)
115 /* These aren't hardware structs, just something useful for us to pass around:
117 * Align1 operation has a lot of control over input ranges. Used in
118 * WM programs to implement shaders decomposed into "channel serial"
119 * or "structure of array" form:
125 unsigned subnr
:5; /* :1 in align16 */
126 unsigned negate
:1; /* source only */
127 unsigned abs
:1; /* source only */
128 unsigned vstride
:4; /* source only */
129 unsigned width
:3; /* src only, align1 only */
130 unsigned hstride
:2; /* align1 only */
131 unsigned address_mode
:1; /* relative addressing, hopefully! */
136 unsigned swizzle
:8; /* src only, align16 only */
137 unsigned writemask
:4; /* dest only, align16 only */
138 int indirect_offset
:10; /* relative addressing offset */
139 unsigned pad1
:10; /* two dwords total */
149 struct brw_indirect
{
150 unsigned addr_subnr
:4;
157 type_sz(unsigned type
)
160 case BRW_REGISTER_TYPE_UD
:
161 case BRW_REGISTER_TYPE_D
:
162 case BRW_REGISTER_TYPE_F
:
164 case BRW_REGISTER_TYPE_UW
:
165 case BRW_REGISTER_TYPE_W
:
167 case BRW_REGISTER_TYPE_UB
:
168 case BRW_REGISTER_TYPE_B
:
176 * Construct a brw_reg.
177 * \param file one of the BRW_x_REGISTER_FILE values
178 * \param nr register number/index
179 * \param subnr register sub number
180 * \param type one of BRW_REGISTER_TYPE_x
181 * \param vstride one of BRW_VERTICAL_STRIDE_x
182 * \param width one of BRW_WIDTH_x
183 * \param hstride one of BRW_HORIZONTAL_STRIDE_x
184 * \param swizzle one of BRW_SWIZZLE_x
185 * \param writemask WRITEMASK_X/Y/Z/W bitfield
187 static inline struct brw_reg
188 brw_reg(unsigned file
,
199 if (file
== BRW_GENERAL_REGISTER_FILE
)
200 assert(nr
< BRW_MAX_GRF
);
201 else if (file
== BRW_MESSAGE_REGISTER_FILE
)
202 assert((nr
& ~(1 << 7)) < BRW_MAX_MRF
);
203 else if (file
== BRW_ARCHITECTURE_REGISTER_FILE
)
204 assert(nr
<= BRW_ARF_TIMESTAMP
);
209 reg
.subnr
= subnr
* type_sz(type
);
212 reg
.vstride
= vstride
;
214 reg
.hstride
= hstride
;
215 reg
.address_mode
= BRW_ADDRESS_DIRECT
;
218 /* Could do better: If the reg is r5.3<0;1,0>, we probably want to
219 * set swizzle and writemask to W, as the lower bits of subnr will
220 * be lost when converted to align16. This is probably too much to
221 * keep track of as you'd want it adjusted by suboffset(), etc.
222 * Perhaps fix up when converting to align16?
224 reg
.dw1
.bits
.swizzle
= swizzle
;
225 reg
.dw1
.bits
.writemask
= writemask
;
226 reg
.dw1
.bits
.indirect_offset
= 0;
227 reg
.dw1
.bits
.pad1
= 0;
231 /** Construct float[16] register */
232 static inline struct brw_reg
233 brw_vec16_reg(unsigned file
, unsigned nr
, unsigned subnr
)
239 BRW_VERTICAL_STRIDE_16
,
241 BRW_HORIZONTAL_STRIDE_1
,
246 /** Construct float[8] register */
247 static inline struct brw_reg
248 brw_vec8_reg(unsigned file
, unsigned nr
, unsigned subnr
)
254 BRW_VERTICAL_STRIDE_8
,
256 BRW_HORIZONTAL_STRIDE_1
,
261 /** Construct float[4] register */
262 static inline struct brw_reg
263 brw_vec4_reg(unsigned file
, unsigned nr
, unsigned subnr
)
269 BRW_VERTICAL_STRIDE_4
,
271 BRW_HORIZONTAL_STRIDE_1
,
276 /** Construct float[2] register */
277 static inline struct brw_reg
278 brw_vec2_reg(unsigned file
, unsigned nr
, unsigned subnr
)
284 BRW_VERTICAL_STRIDE_2
,
286 BRW_HORIZONTAL_STRIDE_1
,
291 /** Construct float[1] register */
292 static inline struct brw_reg
293 brw_vec1_reg(unsigned file
, unsigned nr
, unsigned subnr
)
299 BRW_VERTICAL_STRIDE_0
,
301 BRW_HORIZONTAL_STRIDE_0
,
306 static inline struct brw_reg
307 brw_vecn_reg(unsigned width
, unsigned file
, unsigned nr
, unsigned subnr
)
311 return brw_vec1_reg(file
, nr
, subnr
);
313 return brw_vec2_reg(file
, nr
, subnr
);
315 return brw_vec4_reg(file
, nr
, subnr
);
317 return brw_vec8_reg(file
, nr
, subnr
);
319 return brw_vec16_reg(file
, nr
, subnr
);
321 assert(!"Invalid register width");
326 static inline struct brw_reg
327 retype(struct brw_reg reg
, unsigned type
)
333 static inline struct brw_reg
334 sechalf(struct brw_reg reg
)
341 static inline struct brw_reg
342 suboffset(struct brw_reg reg
, unsigned delta
)
344 reg
.subnr
+= delta
* type_sz(reg
.type
);
349 static inline struct brw_reg
350 offset(struct brw_reg reg
, unsigned delta
)
357 static inline struct brw_reg
358 byte_offset(struct brw_reg reg
, unsigned bytes
)
360 unsigned newoffset
= reg
.nr
* REG_SIZE
+ reg
.subnr
+ bytes
;
361 reg
.nr
= newoffset
/ REG_SIZE
;
362 reg
.subnr
= newoffset
% REG_SIZE
;
367 /** Construct unsigned word[16] register */
368 static inline struct brw_reg
369 brw_uw16_reg(unsigned file
, unsigned nr
, unsigned subnr
)
371 return suboffset(retype(brw_vec16_reg(file
, nr
, 0), BRW_REGISTER_TYPE_UW
), subnr
);
374 /** Construct unsigned word[8] register */
375 static inline struct brw_reg
376 brw_uw8_reg(unsigned file
, unsigned nr
, unsigned subnr
)
378 return suboffset(retype(brw_vec8_reg(file
, nr
, 0), BRW_REGISTER_TYPE_UW
), subnr
);
381 /** Construct unsigned word[1] register */
382 static inline struct brw_reg
383 brw_uw1_reg(unsigned file
, unsigned nr
, unsigned subnr
)
385 return suboffset(retype(brw_vec1_reg(file
, nr
, 0), BRW_REGISTER_TYPE_UW
), subnr
);
388 static inline struct brw_reg
389 brw_imm_reg(unsigned type
)
391 return brw_reg(BRW_IMMEDIATE_VALUE
,
395 BRW_VERTICAL_STRIDE_0
,
397 BRW_HORIZONTAL_STRIDE_0
,
402 /** Construct float immediate register */
403 static inline struct brw_reg
406 struct brw_reg imm
= brw_imm_reg(BRW_REGISTER_TYPE_F
);
411 /** Construct integer immediate register */
412 static inline struct brw_reg
415 struct brw_reg imm
= brw_imm_reg(BRW_REGISTER_TYPE_D
);
420 /** Construct uint immediate register */
421 static inline struct brw_reg
422 brw_imm_ud(unsigned ud
)
424 struct brw_reg imm
= brw_imm_reg(BRW_REGISTER_TYPE_UD
);
429 /** Construct ushort immediate register */
430 static inline struct brw_reg
431 brw_imm_uw(uint16_t uw
)
433 struct brw_reg imm
= brw_imm_reg(BRW_REGISTER_TYPE_UW
);
434 imm
.dw1
.ud
= uw
| (uw
<< 16);
438 /** Construct short immediate register */
439 static inline struct brw_reg
442 struct brw_reg imm
= brw_imm_reg(BRW_REGISTER_TYPE_W
);
443 imm
.dw1
.d
= w
| (w
<< 16);
447 /* brw_imm_b and brw_imm_ub aren't supported by hardware - the type
448 * numbers alias with _V and _VF below:
451 /** Construct vector of eight signed half-byte values */
452 static inline struct brw_reg
453 brw_imm_v(unsigned v
)
455 struct brw_reg imm
= brw_imm_reg(BRW_REGISTER_TYPE_V
);
456 imm
.vstride
= BRW_VERTICAL_STRIDE_0
;
457 imm
.width
= BRW_WIDTH_8
;
458 imm
.hstride
= BRW_HORIZONTAL_STRIDE_1
;
463 /** Construct vector of four 8-bit float values */
464 static inline struct brw_reg
465 brw_imm_vf(unsigned v
)
467 struct brw_reg imm
= brw_imm_reg(BRW_REGISTER_TYPE_VF
);
468 imm
.vstride
= BRW_VERTICAL_STRIDE_0
;
469 imm
.width
= BRW_WIDTH_4
;
470 imm
.hstride
= BRW_HORIZONTAL_STRIDE_1
;
477 #define VF_NEG (1<<7)
479 static inline struct brw_reg
480 brw_imm_vf4(unsigned v0
, unsigned v1
, unsigned v2
, unsigned v3
)
482 struct brw_reg imm
= brw_imm_reg(BRW_REGISTER_TYPE_VF
);
483 imm
.vstride
= BRW_VERTICAL_STRIDE_0
;
484 imm
.width
= BRW_WIDTH_4
;
485 imm
.hstride
= BRW_HORIZONTAL_STRIDE_1
;
486 imm
.dw1
.ud
= ((v0
<< 0) | (v1
<< 8) | (v2
<< 16) | (v3
<< 24));
491 static inline struct brw_reg
492 brw_address(struct brw_reg reg
)
494 return brw_imm_uw(reg
.nr
* REG_SIZE
+ reg
.subnr
);
497 /** Construct float[1] general-purpose register */
498 static inline struct brw_reg
499 brw_vec1_grf(unsigned nr
, unsigned subnr
)
501 return brw_vec1_reg(BRW_GENERAL_REGISTER_FILE
, nr
, subnr
);
504 /** Construct float[2] general-purpose register */
505 static inline struct brw_reg
506 brw_vec2_grf(unsigned nr
, unsigned subnr
)
508 return brw_vec2_reg(BRW_GENERAL_REGISTER_FILE
, nr
, subnr
);
511 /** Construct float[4] general-purpose register */
512 static inline struct brw_reg
513 brw_vec4_grf(unsigned nr
, unsigned subnr
)
515 return brw_vec4_reg(BRW_GENERAL_REGISTER_FILE
, nr
, subnr
);
518 /** Construct float[8] general-purpose register */
519 static inline struct brw_reg
520 brw_vec8_grf(unsigned nr
, unsigned subnr
)
522 return brw_vec8_reg(BRW_GENERAL_REGISTER_FILE
, nr
, subnr
);
526 static inline struct brw_reg
527 brw_uw8_grf(unsigned nr
, unsigned subnr
)
529 return brw_uw8_reg(BRW_GENERAL_REGISTER_FILE
, nr
, subnr
);
532 static inline struct brw_reg
533 brw_uw16_grf(unsigned nr
, unsigned subnr
)
535 return brw_uw16_reg(BRW_GENERAL_REGISTER_FILE
, nr
, subnr
);
539 /** Construct null register (usually used for setting condition codes) */
540 static inline struct brw_reg
543 return brw_vec8_reg(BRW_ARCHITECTURE_REGISTER_FILE
, BRW_ARF_NULL
, 0);
546 static inline struct brw_reg
547 brw_address_reg(unsigned subnr
)
549 return brw_uw1_reg(BRW_ARCHITECTURE_REGISTER_FILE
, BRW_ARF_ADDRESS
, subnr
);
552 /* If/else instructions break in align16 mode if writemask & swizzle
553 * aren't xyzw. This goes against the convention for other scalar
556 static inline struct brw_reg
559 return brw_reg(BRW_ARCHITECTURE_REGISTER_FILE
,
562 BRW_REGISTER_TYPE_UD
,
563 BRW_VERTICAL_STRIDE_4
, /* ? */
565 BRW_HORIZONTAL_STRIDE_0
,
566 BRW_SWIZZLE_XYZW
, /* NOTE! */
567 WRITEMASK_XYZW
); /* NOTE! */
570 static inline struct brw_reg
573 return brw_vec8_reg(BRW_ARCHITECTURE_REGISTER_FILE
, BRW_ARF_ACCUMULATOR
, 0);
576 static inline struct brw_reg
577 brw_notification_1_reg(void)
580 return brw_reg(BRW_ARCHITECTURE_REGISTER_FILE
,
581 BRW_ARF_NOTIFICATION_COUNT
,
583 BRW_REGISTER_TYPE_UD
,
584 BRW_VERTICAL_STRIDE_0
,
586 BRW_HORIZONTAL_STRIDE_0
,
592 static inline struct brw_reg
593 brw_flag_reg(int reg
, int subreg
)
595 return brw_uw1_reg(BRW_ARCHITECTURE_REGISTER_FILE
,
596 BRW_ARF_FLAG
+ reg
, subreg
);
600 static inline struct brw_reg
601 brw_mask_reg(unsigned subnr
)
603 return brw_uw1_reg(BRW_ARCHITECTURE_REGISTER_FILE
, BRW_ARF_MASK
, subnr
);
606 static inline struct brw_reg
607 brw_message_reg(unsigned nr
)
609 assert((nr
& ~(1 << 7)) < BRW_MAX_MRF
);
610 return brw_vec8_reg(BRW_MESSAGE_REGISTER_FILE
, nr
, 0);
613 static inline struct brw_reg
614 brw_uvec_mrf(unsigned width
, unsigned nr
, unsigned subnr
)
616 return retype(brw_vecn_reg(width
, BRW_MESSAGE_REGISTER_FILE
, nr
, subnr
),
617 BRW_REGISTER_TYPE_UD
);
620 /* This is almost always called with a numeric constant argument, so
621 * make things easy to evaluate at compile time:
623 static inline unsigned cvt(unsigned val
)
637 static inline struct brw_reg
638 stride(struct brw_reg reg
, unsigned vstride
, unsigned width
, unsigned hstride
)
640 reg
.vstride
= cvt(vstride
);
641 reg
.width
= cvt(width
) - 1;
642 reg
.hstride
= cvt(hstride
);
647 static inline struct brw_reg
648 vec16(struct brw_reg reg
)
650 return stride(reg
, 16,16,1);
653 static inline struct brw_reg
654 vec8(struct brw_reg reg
)
656 return stride(reg
, 8,8,1);
659 static inline struct brw_reg
660 vec4(struct brw_reg reg
)
662 return stride(reg
, 4,4,1);
665 static inline struct brw_reg
666 vec2(struct brw_reg reg
)
668 return stride(reg
, 2,2,1);
671 static inline struct brw_reg
672 vec1(struct brw_reg reg
)
674 return stride(reg
, 0,1,0);
678 static inline struct brw_reg
679 get_element(struct brw_reg reg
, unsigned elt
)
681 return vec1(suboffset(reg
, elt
));
684 static inline struct brw_reg
685 get_element_ud(struct brw_reg reg
, unsigned elt
)
687 return vec1(suboffset(retype(reg
, BRW_REGISTER_TYPE_UD
), elt
));
690 static inline struct brw_reg
691 get_element_d(struct brw_reg reg
, unsigned elt
)
693 return vec1(suboffset(retype(reg
, BRW_REGISTER_TYPE_D
), elt
));
697 static inline struct brw_reg
698 brw_swizzle(struct brw_reg reg
, unsigned x
, unsigned y
, unsigned z
, unsigned w
)
700 assert(reg
.file
!= BRW_IMMEDIATE_VALUE
);
702 reg
.dw1
.bits
.swizzle
= BRW_SWIZZLE4(BRW_GET_SWZ(reg
.dw1
.bits
.swizzle
, x
),
703 BRW_GET_SWZ(reg
.dw1
.bits
.swizzle
, y
),
704 BRW_GET_SWZ(reg
.dw1
.bits
.swizzle
, z
),
705 BRW_GET_SWZ(reg
.dw1
.bits
.swizzle
, w
));
710 static inline struct brw_reg
711 brw_swizzle1(struct brw_reg reg
, unsigned x
)
713 return brw_swizzle(reg
, x
, x
, x
, x
);
716 static inline struct brw_reg
717 brw_writemask(struct brw_reg reg
, unsigned mask
)
719 assert(reg
.file
!= BRW_IMMEDIATE_VALUE
);
720 reg
.dw1
.bits
.writemask
&= mask
;
724 static inline struct brw_reg
725 brw_set_writemask(struct brw_reg reg
, unsigned mask
)
727 assert(reg
.file
!= BRW_IMMEDIATE_VALUE
);
728 reg
.dw1
.bits
.writemask
= mask
;
732 static inline struct brw_reg
733 negate(struct brw_reg reg
)
739 static inline struct brw_reg
740 brw_abs(struct brw_reg reg
)
747 /************************************************************************/
749 static inline struct brw_reg
750 brw_vec4_indirect(unsigned subnr
, int offset
)
752 struct brw_reg reg
= brw_vec4_grf(0, 0);
754 reg
.address_mode
= BRW_ADDRESS_REGISTER_INDIRECT_REGISTER
;
755 reg
.dw1
.bits
.indirect_offset
= offset
;
759 static inline struct brw_reg
760 brw_vec1_indirect(unsigned subnr
, int offset
)
762 struct brw_reg reg
= brw_vec1_grf(0, 0);
764 reg
.address_mode
= BRW_ADDRESS_REGISTER_INDIRECT_REGISTER
;
765 reg
.dw1
.bits
.indirect_offset
= offset
;
769 static inline struct brw_reg
770 deref_4f(struct brw_indirect ptr
, int offset
)
772 return brw_vec4_indirect(ptr
.addr_subnr
, ptr
.addr_offset
+ offset
);
775 static inline struct brw_reg
776 deref_1f(struct brw_indirect ptr
, int offset
)
778 return brw_vec1_indirect(ptr
.addr_subnr
, ptr
.addr_offset
+ offset
);
781 static inline struct brw_reg
782 deref_4b(struct brw_indirect ptr
, int offset
)
784 return retype(deref_4f(ptr
, offset
), BRW_REGISTER_TYPE_B
);
787 static inline struct brw_reg
788 deref_1uw(struct brw_indirect ptr
, int offset
)
790 return retype(deref_1f(ptr
, offset
), BRW_REGISTER_TYPE_UW
);
793 static inline struct brw_reg
794 deref_1d(struct brw_indirect ptr
, int offset
)
796 return retype(deref_1f(ptr
, offset
), BRW_REGISTER_TYPE_D
);
799 static inline struct brw_reg
800 deref_1ud(struct brw_indirect ptr
, int offset
)
802 return retype(deref_1f(ptr
, offset
), BRW_REGISTER_TYPE_UD
);
805 static inline struct brw_reg
806 get_addr_reg(struct brw_indirect ptr
)
808 return brw_address_reg(ptr
.addr_subnr
);
811 static inline struct brw_indirect
812 brw_indirect_offset(struct brw_indirect ptr
, int offset
)
814 ptr
.addr_offset
+= offset
;
818 static inline struct brw_indirect
819 brw_indirect(unsigned addr_subnr
, int offset
)
821 struct brw_indirect ptr
;
822 ptr
.addr_subnr
= addr_subnr
;
823 ptr
.addr_offset
= offset
;