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
,
109 BRW_REGISTER_TYPE_DF
, /* Gen7+ (no immediates until Gen8+) */
112 BRW_REGISTER_TYPE_HF
,
113 BRW_REGISTER_TYPE_UQ
,
117 unsigned brw_reg_type_to_hw_type(const struct brw_context
*brw
,
118 enum brw_reg_type type
, unsigned file
);
120 #define REG_SIZE (8*4)
122 /* These aren't hardware structs, just something useful for us to pass around:
124 * Align1 operation has a lot of control over input ranges. Used in
125 * WM programs to implement shaders decomposed into "channel serial"
126 * or "structure of array" form:
132 unsigned subnr
:5; /* :1 in align16 */
133 unsigned negate
:1; /* source only */
134 unsigned abs
:1; /* source only */
135 unsigned vstride
:4; /* source only */
136 unsigned width
:3; /* src only, align1 only */
137 unsigned hstride
:2; /* align1 only */
138 unsigned address_mode
:1; /* relative addressing, hopefully! */
143 unsigned swizzle
:8; /* src only, align16 only */
144 unsigned writemask
:4; /* dest only, align16 only */
145 int indirect_offset
:10; /* relative addressing offset */
146 unsigned pad1
:10; /* two dwords total */
156 struct brw_indirect
{
157 unsigned addr_subnr
:4;
164 type_sz(unsigned type
)
167 case BRW_REGISTER_TYPE_UD
:
168 case BRW_REGISTER_TYPE_D
:
169 case BRW_REGISTER_TYPE_F
:
171 case BRW_REGISTER_TYPE_UW
:
172 case BRW_REGISTER_TYPE_W
:
174 case BRW_REGISTER_TYPE_UB
:
175 case BRW_REGISTER_TYPE_B
:
183 * Construct a brw_reg.
184 * \param file one of the BRW_x_REGISTER_FILE values
185 * \param nr register number/index
186 * \param subnr register sub number
187 * \param type one of BRW_REGISTER_TYPE_x
188 * \param vstride one of BRW_VERTICAL_STRIDE_x
189 * \param width one of BRW_WIDTH_x
190 * \param hstride one of BRW_HORIZONTAL_STRIDE_x
191 * \param swizzle one of BRW_SWIZZLE_x
192 * \param writemask WRITEMASK_X/Y/Z/W bitfield
194 static inline struct brw_reg
195 brw_reg(unsigned file
,
206 if (file
== BRW_GENERAL_REGISTER_FILE
)
207 assert(nr
< BRW_MAX_GRF
);
208 else if (file
== BRW_MESSAGE_REGISTER_FILE
)
209 assert((nr
& ~(1 << 7)) < BRW_MAX_MRF
);
210 else if (file
== BRW_ARCHITECTURE_REGISTER_FILE
)
211 assert(nr
<= BRW_ARF_TIMESTAMP
);
216 reg
.subnr
= subnr
* type_sz(type
);
219 reg
.vstride
= vstride
;
221 reg
.hstride
= hstride
;
222 reg
.address_mode
= BRW_ADDRESS_DIRECT
;
225 /* Could do better: If the reg is r5.3<0;1,0>, we probably want to
226 * set swizzle and writemask to W, as the lower bits of subnr will
227 * be lost when converted to align16. This is probably too much to
228 * keep track of as you'd want it adjusted by suboffset(), etc.
229 * Perhaps fix up when converting to align16?
231 reg
.dw1
.bits
.swizzle
= swizzle
;
232 reg
.dw1
.bits
.writemask
= writemask
;
233 reg
.dw1
.bits
.indirect_offset
= 0;
234 reg
.dw1
.bits
.pad1
= 0;
238 /** Construct float[16] register */
239 static inline struct brw_reg
240 brw_vec16_reg(unsigned file
, unsigned nr
, unsigned subnr
)
246 BRW_VERTICAL_STRIDE_16
,
248 BRW_HORIZONTAL_STRIDE_1
,
253 /** Construct float[8] register */
254 static inline struct brw_reg
255 brw_vec8_reg(unsigned file
, unsigned nr
, unsigned subnr
)
261 BRW_VERTICAL_STRIDE_8
,
263 BRW_HORIZONTAL_STRIDE_1
,
268 /** Construct float[4] register */
269 static inline struct brw_reg
270 brw_vec4_reg(unsigned file
, unsigned nr
, unsigned subnr
)
276 BRW_VERTICAL_STRIDE_4
,
278 BRW_HORIZONTAL_STRIDE_1
,
283 /** Construct float[2] register */
284 static inline struct brw_reg
285 brw_vec2_reg(unsigned file
, unsigned nr
, unsigned subnr
)
291 BRW_VERTICAL_STRIDE_2
,
293 BRW_HORIZONTAL_STRIDE_1
,
298 /** Construct float[1] register */
299 static inline struct brw_reg
300 brw_vec1_reg(unsigned file
, unsigned nr
, unsigned subnr
)
306 BRW_VERTICAL_STRIDE_0
,
308 BRW_HORIZONTAL_STRIDE_0
,
313 static inline struct brw_reg
314 brw_vecn_reg(unsigned width
, unsigned file
, unsigned nr
, unsigned subnr
)
318 return brw_vec1_reg(file
, nr
, subnr
);
320 return brw_vec2_reg(file
, nr
, subnr
);
322 return brw_vec4_reg(file
, nr
, subnr
);
324 return brw_vec8_reg(file
, nr
, subnr
);
326 return brw_vec16_reg(file
, nr
, subnr
);
328 assert(!"Invalid register width");
333 static inline struct brw_reg
334 retype(struct brw_reg reg
, unsigned type
)
340 static inline struct brw_reg
341 sechalf(struct brw_reg reg
)
348 static inline struct brw_reg
349 suboffset(struct brw_reg reg
, unsigned delta
)
351 reg
.subnr
+= delta
* type_sz(reg
.type
);
356 static inline struct brw_reg
357 offset(struct brw_reg reg
, unsigned delta
)
364 static inline struct brw_reg
365 byte_offset(struct brw_reg reg
, unsigned bytes
)
367 unsigned newoffset
= reg
.nr
* REG_SIZE
+ reg
.subnr
+ bytes
;
368 reg
.nr
= newoffset
/ REG_SIZE
;
369 reg
.subnr
= newoffset
% REG_SIZE
;
374 /** Construct unsigned word[16] register */
375 static inline struct brw_reg
376 brw_uw16_reg(unsigned file
, unsigned nr
, unsigned subnr
)
378 return suboffset(retype(brw_vec16_reg(file
, nr
, 0), BRW_REGISTER_TYPE_UW
), subnr
);
381 /** Construct unsigned word[8] register */
382 static inline struct brw_reg
383 brw_uw8_reg(unsigned file
, unsigned nr
, unsigned subnr
)
385 return suboffset(retype(brw_vec8_reg(file
, nr
, 0), BRW_REGISTER_TYPE_UW
), subnr
);
388 /** Construct unsigned word[1] register */
389 static inline struct brw_reg
390 brw_uw1_reg(unsigned file
, unsigned nr
, unsigned subnr
)
392 return suboffset(retype(brw_vec1_reg(file
, nr
, 0), BRW_REGISTER_TYPE_UW
), subnr
);
395 static inline struct brw_reg
396 brw_imm_reg(unsigned type
)
398 return brw_reg(BRW_IMMEDIATE_VALUE
,
402 BRW_VERTICAL_STRIDE_0
,
404 BRW_HORIZONTAL_STRIDE_0
,
409 /** Construct float immediate register */
410 static inline struct brw_reg
413 struct brw_reg imm
= brw_imm_reg(BRW_REGISTER_TYPE_F
);
418 /** Construct integer immediate register */
419 static inline struct brw_reg
422 struct brw_reg imm
= brw_imm_reg(BRW_REGISTER_TYPE_D
);
427 /** Construct uint immediate register */
428 static inline struct brw_reg
429 brw_imm_ud(unsigned ud
)
431 struct brw_reg imm
= brw_imm_reg(BRW_REGISTER_TYPE_UD
);
436 /** Construct ushort immediate register */
437 static inline struct brw_reg
438 brw_imm_uw(uint16_t uw
)
440 struct brw_reg imm
= brw_imm_reg(BRW_REGISTER_TYPE_UW
);
441 imm
.dw1
.ud
= uw
| (uw
<< 16);
445 /** Construct short immediate register */
446 static inline struct brw_reg
449 struct brw_reg imm
= brw_imm_reg(BRW_REGISTER_TYPE_W
);
450 imm
.dw1
.d
= w
| (w
<< 16);
454 /* brw_imm_b and brw_imm_ub aren't supported by hardware - the type
455 * numbers alias with _V and _VF below:
458 /** Construct vector of eight signed half-byte values */
459 static inline struct brw_reg
460 brw_imm_v(unsigned v
)
462 struct brw_reg imm
= brw_imm_reg(BRW_REGISTER_TYPE_V
);
463 imm
.vstride
= BRW_VERTICAL_STRIDE_0
;
464 imm
.width
= BRW_WIDTH_8
;
465 imm
.hstride
= BRW_HORIZONTAL_STRIDE_1
;
470 /** Construct vector of four 8-bit float values */
471 static inline struct brw_reg
472 brw_imm_vf(unsigned v
)
474 struct brw_reg imm
= brw_imm_reg(BRW_REGISTER_TYPE_VF
);
475 imm
.vstride
= BRW_VERTICAL_STRIDE_0
;
476 imm
.width
= BRW_WIDTH_4
;
477 imm
.hstride
= BRW_HORIZONTAL_STRIDE_1
;
484 #define VF_NEG (1<<7)
486 static inline struct brw_reg
487 brw_imm_vf4(unsigned v0
, unsigned v1
, unsigned v2
, unsigned v3
)
489 struct brw_reg imm
= brw_imm_reg(BRW_REGISTER_TYPE_VF
);
490 imm
.vstride
= BRW_VERTICAL_STRIDE_0
;
491 imm
.width
= BRW_WIDTH_4
;
492 imm
.hstride
= BRW_HORIZONTAL_STRIDE_1
;
493 imm
.dw1
.ud
= ((v0
<< 0) | (v1
<< 8) | (v2
<< 16) | (v3
<< 24));
498 static inline struct brw_reg
499 brw_address(struct brw_reg reg
)
501 return brw_imm_uw(reg
.nr
* REG_SIZE
+ reg
.subnr
);
504 /** Construct float[1] general-purpose register */
505 static inline struct brw_reg
506 brw_vec1_grf(unsigned nr
, unsigned subnr
)
508 return brw_vec1_reg(BRW_GENERAL_REGISTER_FILE
, nr
, subnr
);
511 /** Construct float[2] general-purpose register */
512 static inline struct brw_reg
513 brw_vec2_grf(unsigned nr
, unsigned subnr
)
515 return brw_vec2_reg(BRW_GENERAL_REGISTER_FILE
, nr
, subnr
);
518 /** Construct float[4] general-purpose register */
519 static inline struct brw_reg
520 brw_vec4_grf(unsigned nr
, unsigned subnr
)
522 return brw_vec4_reg(BRW_GENERAL_REGISTER_FILE
, nr
, subnr
);
525 /** Construct float[8] general-purpose register */
526 static inline struct brw_reg
527 brw_vec8_grf(unsigned nr
, unsigned subnr
)
529 return brw_vec8_reg(BRW_GENERAL_REGISTER_FILE
, nr
, subnr
);
533 static inline struct brw_reg
534 brw_uw8_grf(unsigned nr
, unsigned subnr
)
536 return brw_uw8_reg(BRW_GENERAL_REGISTER_FILE
, nr
, subnr
);
539 static inline struct brw_reg
540 brw_uw16_grf(unsigned nr
, unsigned subnr
)
542 return brw_uw16_reg(BRW_GENERAL_REGISTER_FILE
, nr
, subnr
);
546 /** Construct null register (usually used for setting condition codes) */
547 static inline struct brw_reg
550 return brw_vec8_reg(BRW_ARCHITECTURE_REGISTER_FILE
, BRW_ARF_NULL
, 0);
553 static inline struct brw_reg
554 brw_address_reg(unsigned subnr
)
556 return brw_uw1_reg(BRW_ARCHITECTURE_REGISTER_FILE
, BRW_ARF_ADDRESS
, subnr
);
559 /* If/else instructions break in align16 mode if writemask & swizzle
560 * aren't xyzw. This goes against the convention for other scalar
563 static inline struct brw_reg
566 return brw_reg(BRW_ARCHITECTURE_REGISTER_FILE
,
569 BRW_REGISTER_TYPE_UD
,
570 BRW_VERTICAL_STRIDE_4
, /* ? */
572 BRW_HORIZONTAL_STRIDE_0
,
573 BRW_SWIZZLE_XYZW
, /* NOTE! */
574 WRITEMASK_XYZW
); /* NOTE! */
577 static inline struct brw_reg
580 return brw_vec8_reg(BRW_ARCHITECTURE_REGISTER_FILE
, BRW_ARF_ACCUMULATOR
, 0);
583 static inline struct brw_reg
584 brw_notification_1_reg(void)
587 return brw_reg(BRW_ARCHITECTURE_REGISTER_FILE
,
588 BRW_ARF_NOTIFICATION_COUNT
,
590 BRW_REGISTER_TYPE_UD
,
591 BRW_VERTICAL_STRIDE_0
,
593 BRW_HORIZONTAL_STRIDE_0
,
599 static inline struct brw_reg
600 brw_flag_reg(int reg
, int subreg
)
602 return brw_uw1_reg(BRW_ARCHITECTURE_REGISTER_FILE
,
603 BRW_ARF_FLAG
+ reg
, subreg
);
607 static inline struct brw_reg
608 brw_mask_reg(unsigned subnr
)
610 return brw_uw1_reg(BRW_ARCHITECTURE_REGISTER_FILE
, BRW_ARF_MASK
, subnr
);
613 static inline struct brw_reg
614 brw_message_reg(unsigned nr
)
616 assert((nr
& ~(1 << 7)) < BRW_MAX_MRF
);
617 return brw_vec8_reg(BRW_MESSAGE_REGISTER_FILE
, nr
, 0);
620 static inline struct brw_reg
621 brw_uvec_mrf(unsigned width
, unsigned nr
, unsigned subnr
)
623 return retype(brw_vecn_reg(width
, BRW_MESSAGE_REGISTER_FILE
, nr
, subnr
),
624 BRW_REGISTER_TYPE_UD
);
627 /* This is almost always called with a numeric constant argument, so
628 * make things easy to evaluate at compile time:
630 static inline unsigned cvt(unsigned val
)
644 static inline struct brw_reg
645 stride(struct brw_reg reg
, unsigned vstride
, unsigned width
, unsigned hstride
)
647 reg
.vstride
= cvt(vstride
);
648 reg
.width
= cvt(width
) - 1;
649 reg
.hstride
= cvt(hstride
);
654 static inline struct brw_reg
655 vec16(struct brw_reg reg
)
657 return stride(reg
, 16,16,1);
660 static inline struct brw_reg
661 vec8(struct brw_reg reg
)
663 return stride(reg
, 8,8,1);
666 static inline struct brw_reg
667 vec4(struct brw_reg reg
)
669 return stride(reg
, 4,4,1);
672 static inline struct brw_reg
673 vec2(struct brw_reg reg
)
675 return stride(reg
, 2,2,1);
678 static inline struct brw_reg
679 vec1(struct brw_reg reg
)
681 return stride(reg
, 0,1,0);
685 static inline struct brw_reg
686 get_element(struct brw_reg reg
, unsigned elt
)
688 return vec1(suboffset(reg
, elt
));
691 static inline struct brw_reg
692 get_element_ud(struct brw_reg reg
, unsigned elt
)
694 return vec1(suboffset(retype(reg
, BRW_REGISTER_TYPE_UD
), elt
));
697 static inline struct brw_reg
698 get_element_d(struct brw_reg reg
, unsigned elt
)
700 return vec1(suboffset(retype(reg
, BRW_REGISTER_TYPE_D
), elt
));
704 static inline struct brw_reg
705 brw_swizzle(struct brw_reg reg
, unsigned x
, unsigned y
, unsigned z
, unsigned w
)
707 assert(reg
.file
!= BRW_IMMEDIATE_VALUE
);
709 reg
.dw1
.bits
.swizzle
= BRW_SWIZZLE4(BRW_GET_SWZ(reg
.dw1
.bits
.swizzle
, x
),
710 BRW_GET_SWZ(reg
.dw1
.bits
.swizzle
, y
),
711 BRW_GET_SWZ(reg
.dw1
.bits
.swizzle
, z
),
712 BRW_GET_SWZ(reg
.dw1
.bits
.swizzle
, w
));
717 static inline struct brw_reg
718 brw_swizzle1(struct brw_reg reg
, unsigned x
)
720 return brw_swizzle(reg
, x
, x
, x
, x
);
723 static inline struct brw_reg
724 brw_writemask(struct brw_reg reg
, unsigned mask
)
726 assert(reg
.file
!= BRW_IMMEDIATE_VALUE
);
727 reg
.dw1
.bits
.writemask
&= mask
;
731 static inline struct brw_reg
732 brw_set_writemask(struct brw_reg reg
, unsigned mask
)
734 assert(reg
.file
!= BRW_IMMEDIATE_VALUE
);
735 reg
.dw1
.bits
.writemask
= mask
;
739 static inline struct brw_reg
740 negate(struct brw_reg reg
)
746 static inline struct brw_reg
747 brw_abs(struct brw_reg reg
)
754 /************************************************************************/
756 static inline struct brw_reg
757 brw_vec4_indirect(unsigned subnr
, int offset
)
759 struct brw_reg reg
= brw_vec4_grf(0, 0);
761 reg
.address_mode
= BRW_ADDRESS_REGISTER_INDIRECT_REGISTER
;
762 reg
.dw1
.bits
.indirect_offset
= offset
;
766 static inline struct brw_reg
767 brw_vec1_indirect(unsigned subnr
, int offset
)
769 struct brw_reg reg
= brw_vec1_grf(0, 0);
771 reg
.address_mode
= BRW_ADDRESS_REGISTER_INDIRECT_REGISTER
;
772 reg
.dw1
.bits
.indirect_offset
= offset
;
776 static inline struct brw_reg
777 deref_4f(struct brw_indirect ptr
, int offset
)
779 return brw_vec4_indirect(ptr
.addr_subnr
, ptr
.addr_offset
+ offset
);
782 static inline struct brw_reg
783 deref_1f(struct brw_indirect ptr
, int offset
)
785 return brw_vec1_indirect(ptr
.addr_subnr
, ptr
.addr_offset
+ offset
);
788 static inline struct brw_reg
789 deref_4b(struct brw_indirect ptr
, int offset
)
791 return retype(deref_4f(ptr
, offset
), BRW_REGISTER_TYPE_B
);
794 static inline struct brw_reg
795 deref_1uw(struct brw_indirect ptr
, int offset
)
797 return retype(deref_1f(ptr
, offset
), BRW_REGISTER_TYPE_UW
);
800 static inline struct brw_reg
801 deref_1d(struct brw_indirect ptr
, int offset
)
803 return retype(deref_1f(ptr
, offset
), BRW_REGISTER_TYPE_D
);
806 static inline struct brw_reg
807 deref_1ud(struct brw_indirect ptr
, int offset
)
809 return retype(deref_1f(ptr
, offset
), BRW_REGISTER_TYPE_UD
);
812 static inline struct brw_reg
813 get_addr_reg(struct brw_indirect ptr
)
815 return brw_address_reg(ptr
.addr_subnr
);
818 static inline struct brw_indirect
819 brw_indirect_offset(struct brw_indirect ptr
, int offset
)
821 ptr
.addr_offset
+= offset
;
825 static inline struct brw_indirect
826 brw_indirect(unsigned addr_subnr
, int offset
)
828 struct brw_indirect ptr
;
829 ptr
.addr_subnr
= addr_subnr
;
830 ptr
.addr_offset
= offset
;