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 static inline struct brw_reg
348 brw_imm_reg(unsigned type
)
350 return brw_reg(BRW_IMMEDIATE_VALUE
,
354 BRW_VERTICAL_STRIDE_0
,
356 BRW_HORIZONTAL_STRIDE_0
,
361 /** Construct float immediate register */
362 static inline struct brw_reg
365 struct brw_reg imm
= brw_imm_reg(BRW_REGISTER_TYPE_F
);
370 /** Construct integer immediate register */
371 static inline struct brw_reg
374 struct brw_reg imm
= brw_imm_reg(BRW_REGISTER_TYPE_D
);
379 /** Construct uint immediate register */
380 static inline struct brw_reg
381 brw_imm_ud(unsigned ud
)
383 struct brw_reg imm
= brw_imm_reg(BRW_REGISTER_TYPE_UD
);
388 /** Construct ushort immediate register */
389 static inline struct brw_reg
390 brw_imm_uw(uint16_t uw
)
392 struct brw_reg imm
= brw_imm_reg(BRW_REGISTER_TYPE_UW
);
393 imm
.dw1
.ud
= uw
| (uw
<< 16);
397 /** Construct short immediate register */
398 static inline struct brw_reg
401 struct brw_reg imm
= brw_imm_reg(BRW_REGISTER_TYPE_W
);
402 imm
.dw1
.d
= w
| (w
<< 16);
406 /* brw_imm_b and brw_imm_ub aren't supported by hardware - the type
407 * numbers alias with _V and _VF below:
410 /** Construct vector of eight signed half-byte values */
411 static inline struct brw_reg
412 brw_imm_v(unsigned v
)
414 struct brw_reg imm
= brw_imm_reg(BRW_REGISTER_TYPE_V
);
415 imm
.vstride
= BRW_VERTICAL_STRIDE_0
;
416 imm
.width
= BRW_WIDTH_8
;
417 imm
.hstride
= BRW_HORIZONTAL_STRIDE_1
;
422 /** Construct vector of four 8-bit float values */
423 static inline struct brw_reg
424 brw_imm_vf(unsigned v
)
426 struct brw_reg imm
= brw_imm_reg(BRW_REGISTER_TYPE_VF
);
427 imm
.vstride
= BRW_VERTICAL_STRIDE_0
;
428 imm
.width
= BRW_WIDTH_4
;
429 imm
.hstride
= BRW_HORIZONTAL_STRIDE_1
;
436 #define VF_NEG (1<<7)
438 static inline struct brw_reg
439 brw_imm_vf4(unsigned v0
, unsigned v1
, unsigned v2
, unsigned v3
)
441 struct brw_reg imm
= brw_imm_reg(BRW_REGISTER_TYPE_VF
);
442 imm
.vstride
= BRW_VERTICAL_STRIDE_0
;
443 imm
.width
= BRW_WIDTH_4
;
444 imm
.hstride
= BRW_HORIZONTAL_STRIDE_1
;
445 imm
.dw1
.ud
= ((v0
<< 0) | (v1
<< 8) | (v2
<< 16) | (v3
<< 24));
450 static inline struct brw_reg
451 brw_address(struct brw_reg reg
)
453 return brw_imm_uw(reg
.nr
* REG_SIZE
+ reg
.subnr
);
456 /** Construct float[1] general-purpose register */
457 static inline struct brw_reg
458 brw_vec1_grf(unsigned nr
, unsigned subnr
)
460 return brw_vec1_reg(BRW_GENERAL_REGISTER_FILE
, nr
, subnr
);
463 /** Construct float[2] general-purpose register */
464 static inline struct brw_reg
465 brw_vec2_grf(unsigned nr
, unsigned subnr
)
467 return brw_vec2_reg(BRW_GENERAL_REGISTER_FILE
, nr
, subnr
);
470 /** Construct float[4] general-purpose register */
471 static inline struct brw_reg
472 brw_vec4_grf(unsigned nr
, unsigned subnr
)
474 return brw_vec4_reg(BRW_GENERAL_REGISTER_FILE
, nr
, subnr
);
477 /** Construct float[8] general-purpose register */
478 static inline struct brw_reg
479 brw_vec8_grf(unsigned nr
, unsigned subnr
)
481 return brw_vec8_reg(BRW_GENERAL_REGISTER_FILE
, nr
, subnr
);
485 static inline struct brw_reg
486 brw_uw8_grf(unsigned nr
, unsigned subnr
)
488 return brw_uw8_reg(BRW_GENERAL_REGISTER_FILE
, nr
, subnr
);
491 static inline struct brw_reg
492 brw_uw16_grf(unsigned nr
, unsigned subnr
)
494 return brw_uw16_reg(BRW_GENERAL_REGISTER_FILE
, nr
, subnr
);
498 /** Construct null register (usually used for setting condition codes) */
499 static inline struct brw_reg
502 return brw_vec8_reg(BRW_ARCHITECTURE_REGISTER_FILE
, BRW_ARF_NULL
, 0);
505 static inline struct brw_reg
506 brw_address_reg(unsigned subnr
)
508 return brw_uw1_reg(BRW_ARCHITECTURE_REGISTER_FILE
, BRW_ARF_ADDRESS
, subnr
);
511 /* If/else instructions break in align16 mode if writemask & swizzle
512 * aren't xyzw. This goes against the convention for other scalar
515 static inline struct brw_reg
518 return brw_reg(BRW_ARCHITECTURE_REGISTER_FILE
,
521 BRW_REGISTER_TYPE_UD
,
522 BRW_VERTICAL_STRIDE_4
, /* ? */
524 BRW_HORIZONTAL_STRIDE_0
,
525 BRW_SWIZZLE_XYZW
, /* NOTE! */
526 WRITEMASK_XYZW
); /* NOTE! */
529 static inline struct brw_reg
532 return brw_vec8_reg(BRW_ARCHITECTURE_REGISTER_FILE
, BRW_ARF_ACCUMULATOR
, 0);
535 static inline struct brw_reg
536 brw_notification_1_reg(void)
539 return brw_reg(BRW_ARCHITECTURE_REGISTER_FILE
,
540 BRW_ARF_NOTIFICATION_COUNT
,
542 BRW_REGISTER_TYPE_UD
,
543 BRW_VERTICAL_STRIDE_0
,
545 BRW_HORIZONTAL_STRIDE_0
,
551 static inline struct brw_reg
552 brw_flag_reg(int reg
, int subreg
)
554 return brw_uw1_reg(BRW_ARCHITECTURE_REGISTER_FILE
,
555 BRW_ARF_FLAG
+ reg
, subreg
);
559 static inline struct brw_reg
560 brw_mask_reg(unsigned subnr
)
562 return brw_uw1_reg(BRW_ARCHITECTURE_REGISTER_FILE
, BRW_ARF_MASK
, subnr
);
565 static inline struct brw_reg
566 brw_message_reg(unsigned nr
)
568 assert((nr
& ~(1 << 7)) < BRW_MAX_MRF
);
569 return brw_vec8_reg(BRW_MESSAGE_REGISTER_FILE
, nr
, 0);
573 /* This is almost always called with a numeric constant argument, so
574 * make things easy to evaluate at compile time:
576 static inline unsigned cvt(unsigned val
)
590 static inline struct brw_reg
591 stride(struct brw_reg reg
, unsigned vstride
, unsigned width
, unsigned hstride
)
593 reg
.vstride
= cvt(vstride
);
594 reg
.width
= cvt(width
) - 1;
595 reg
.hstride
= cvt(hstride
);
600 static inline struct brw_reg
601 vec16(struct brw_reg reg
)
603 return stride(reg
, 16,16,1);
606 static inline struct brw_reg
607 vec8(struct brw_reg reg
)
609 return stride(reg
, 8,8,1);
612 static inline struct brw_reg
613 vec4(struct brw_reg reg
)
615 return stride(reg
, 4,4,1);
618 static inline struct brw_reg
619 vec2(struct brw_reg reg
)
621 return stride(reg
, 2,2,1);
624 static inline struct brw_reg
625 vec1(struct brw_reg reg
)
627 return stride(reg
, 0,1,0);
631 static inline struct brw_reg
632 get_element(struct brw_reg reg
, unsigned elt
)
634 return vec1(suboffset(reg
, elt
));
637 static inline struct brw_reg
638 get_element_ud(struct brw_reg reg
, unsigned elt
)
640 return vec1(suboffset(retype(reg
, BRW_REGISTER_TYPE_UD
), elt
));
643 static inline struct brw_reg
644 get_element_d(struct brw_reg reg
, unsigned elt
)
646 return vec1(suboffset(retype(reg
, BRW_REGISTER_TYPE_D
), elt
));
650 static inline struct brw_reg
651 brw_swizzle(struct brw_reg reg
, unsigned x
, unsigned y
, unsigned z
, unsigned w
)
653 assert(reg
.file
!= BRW_IMMEDIATE_VALUE
);
655 reg
.dw1
.bits
.swizzle
= BRW_SWIZZLE4(BRW_GET_SWZ(reg
.dw1
.bits
.swizzle
, x
),
656 BRW_GET_SWZ(reg
.dw1
.bits
.swizzle
, y
),
657 BRW_GET_SWZ(reg
.dw1
.bits
.swizzle
, z
),
658 BRW_GET_SWZ(reg
.dw1
.bits
.swizzle
, w
));
663 static inline struct brw_reg
664 brw_swizzle1(struct brw_reg reg
, unsigned x
)
666 return brw_swizzle(reg
, x
, x
, x
, x
);
669 static inline struct brw_reg
670 brw_writemask(struct brw_reg reg
, unsigned mask
)
672 assert(reg
.file
!= BRW_IMMEDIATE_VALUE
);
673 reg
.dw1
.bits
.writemask
&= mask
;
677 static inline struct brw_reg
678 brw_set_writemask(struct brw_reg reg
, unsigned mask
)
680 assert(reg
.file
!= BRW_IMMEDIATE_VALUE
);
681 reg
.dw1
.bits
.writemask
= mask
;
685 static inline struct brw_reg
686 negate(struct brw_reg reg
)
692 static inline struct brw_reg
693 brw_abs(struct brw_reg reg
)
700 /************************************************************************/
702 static inline struct brw_reg
703 brw_vec4_indirect(unsigned subnr
, int offset
)
705 struct brw_reg reg
= brw_vec4_grf(0, 0);
707 reg
.address_mode
= BRW_ADDRESS_REGISTER_INDIRECT_REGISTER
;
708 reg
.dw1
.bits
.indirect_offset
= offset
;
712 static inline struct brw_reg
713 brw_vec1_indirect(unsigned subnr
, int offset
)
715 struct brw_reg reg
= brw_vec1_grf(0, 0);
717 reg
.address_mode
= BRW_ADDRESS_REGISTER_INDIRECT_REGISTER
;
718 reg
.dw1
.bits
.indirect_offset
= offset
;
722 static inline struct brw_reg
723 deref_4f(struct brw_indirect ptr
, int offset
)
725 return brw_vec4_indirect(ptr
.addr_subnr
, ptr
.addr_offset
+ offset
);
728 static inline struct brw_reg
729 deref_1f(struct brw_indirect ptr
, int offset
)
731 return brw_vec1_indirect(ptr
.addr_subnr
, ptr
.addr_offset
+ offset
);
734 static inline struct brw_reg
735 deref_4b(struct brw_indirect ptr
, int offset
)
737 return retype(deref_4f(ptr
, offset
), BRW_REGISTER_TYPE_B
);
740 static inline struct brw_reg
741 deref_1uw(struct brw_indirect ptr
, int offset
)
743 return retype(deref_1f(ptr
, offset
), BRW_REGISTER_TYPE_UW
);
746 static inline struct brw_reg
747 deref_1d(struct brw_indirect ptr
, int offset
)
749 return retype(deref_1f(ptr
, offset
), BRW_REGISTER_TYPE_D
);
752 static inline struct brw_reg
753 deref_1ud(struct brw_indirect ptr
, int offset
)
755 return retype(deref_1f(ptr
, offset
), BRW_REGISTER_TYPE_UD
);
758 static inline struct brw_reg
759 get_addr_reg(struct brw_indirect ptr
)
761 return brw_address_reg(ptr
.addr_subnr
);
764 static inline struct brw_indirect
765 brw_indirect_offset(struct brw_indirect ptr
, int offset
)
767 ptr
.addr_offset
+= offset
;
771 static inline struct brw_indirect
772 brw_indirect(unsigned addr_subnr
, int offset
)
774 struct brw_indirect ptr
;
775 ptr
.addr_subnr
= addr_subnr
;
776 ptr
.addr_offset
= offset
;