2 * Mesa 3-D graphics library
4 * Copyright (C) 2012-2013 LunarG, Inc.
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
13 * The above copyright notice and this permission notice shall be included
14 * in all copies or substantial portions of the Software.
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 * DEALINGS IN THE SOFTWARE.
25 * Chia-I Wu <olv@lunarg.com>
31 #include "pipe/p_compiler.h"
32 #include "util/u_debug.h" /* for assert() */
33 #include "util/u_math.h" /* for union fi */
35 /* a toy reg is 256-bit wide */
36 #define TOY_REG_WIDTH 32
42 /* virtual register file */
62 TOY_TYPE_V
, /* only valid for immediates */
68 * Register rectangles. The three numbers stand for vertical stride, width,
69 * and horizontal stride respectively.
83 * Source swizzles. They are compatible with TGSI_SWIZZLE_x and hardware
94 * Destination writemasks. They are compatible with TGSI_WRITEMASK_x and
98 TOY_WRITEMASK_X
= (1 << TOY_SWIZZLE_X
),
99 TOY_WRITEMASK_Y
= (1 << TOY_SWIZZLE_Y
),
100 TOY_WRITEMASK_Z
= (1 << TOY_SWIZZLE_Z
),
101 TOY_WRITEMASK_W
= (1 << TOY_SWIZZLE_W
),
102 TOY_WRITEMASK_XY
= (TOY_WRITEMASK_X
| TOY_WRITEMASK_Y
),
103 TOY_WRITEMASK_XZ
= (TOY_WRITEMASK_X
| TOY_WRITEMASK_Z
),
104 TOY_WRITEMASK_XW
= (TOY_WRITEMASK_X
| TOY_WRITEMASK_W
),
105 TOY_WRITEMASK_YZ
= (TOY_WRITEMASK_Y
| TOY_WRITEMASK_Z
),
106 TOY_WRITEMASK_YW
= (TOY_WRITEMASK_Y
| TOY_WRITEMASK_W
),
107 TOY_WRITEMASK_ZW
= (TOY_WRITEMASK_Z
| TOY_WRITEMASK_W
),
108 TOY_WRITEMASK_XYZ
= (TOY_WRITEMASK_X
| TOY_WRITEMASK_Y
| TOY_WRITEMASK_Z
),
109 TOY_WRITEMASK_XYW
= (TOY_WRITEMASK_X
| TOY_WRITEMASK_Y
| TOY_WRITEMASK_W
),
110 TOY_WRITEMASK_XZW
= (TOY_WRITEMASK_X
| TOY_WRITEMASK_Z
| TOY_WRITEMASK_W
),
111 TOY_WRITEMASK_YZW
= (TOY_WRITEMASK_Y
| TOY_WRITEMASK_Z
| TOY_WRITEMASK_W
),
112 TOY_WRITEMASK_XYZW
= (TOY_WRITEMASK_X
| TOY_WRITEMASK_Y
|
113 TOY_WRITEMASK_Z
| TOY_WRITEMASK_W
),
117 * Destination operand.
120 unsigned file
:3; /* TOY_FILE_x */
121 unsigned type
:3; /* TOY_TYPE_x */
122 unsigned rect
:3; /* TOY_RECT_x */
123 unsigned indirect
:1; /* true or false */
124 unsigned indirect_subreg
:6; /* which subreg of a0? */
126 unsigned writemask
:4; /* TOY_WRITEMASK_x */
136 unsigned file
:3; /* TOY_FILE_x */
137 unsigned type
:3; /* TOY_TYPE_x */
138 unsigned rect
:3; /* TOY_RECT_x */
139 unsigned indirect
:1; /* true or false */
140 unsigned indirect_subreg
:6; /* which subreg of a0? */
142 unsigned swizzle_x
:2; /* TOY_SWIZZLE_x */
143 unsigned swizzle_y
:2; /* TOY_SWIZZLE_x */
144 unsigned swizzle_z
:2; /* TOY_SWIZZLE_x */
145 unsigned swizzle_w
:2; /* TOY_SWIZZLE_x */
146 unsigned absolute
:1; /* true or false */
147 unsigned negate
:1; /* true or false */
154 * Return true if the file is virtual.
157 toy_file_is_virtual(enum toy_file file
)
159 return (file
== TOY_FILE_VRF
);
163 * Return true if the file is a hardware one.
166 toy_file_is_hw(enum toy_file file
)
168 return !toy_file_is_virtual(file
);
172 * Return the size of the file.
174 static inline uint32_t
175 toy_file_size(enum toy_file file
)
179 return 256 * TOY_REG_WIDTH
;
181 /* there is no MRF on GEN7+ */
182 return 256 * TOY_REG_WIDTH
;
184 assert(!"invalid toy file");
190 * Return the size of the type.
193 toy_type_size(enum toy_type type
)
205 assert(!"invalid toy type");
211 * Return true if the destination operand is null.
214 tdst_is_null(struct toy_dst dst
)
216 /* BRW_ARF_NULL happens to be 0 */
217 return (dst
.file
== TOY_FILE_ARF
&& dst
.val32
== 0);
221 * Validate the destination operand.
223 static inline struct toy_dst
224 tdst_validate(struct toy_dst dst
)
230 assert(!dst
.indirect
);
231 if (dst
.file
== TOY_FILE_MRF
)
232 assert(dst
.val32
< toy_file_size(dst
.file
));
236 assert(dst
.val32
< toy_file_size(dst
.file
));
239 /* yes, dst can be IMM of type W (for IF/ELSE/ENDIF/WHILE) */
240 assert(!dst
.indirect
);
241 assert(dst
.type
== TOY_TYPE_W
);
244 assert(!"invalid dst file");
250 assert(!"invalid dst type");
256 assert(dst
.rect
== TOY_RECT_LINEAR
);
257 if (dst
.file
!= TOY_FILE_IMM
)
258 assert(dst
.val32
% toy_type_size(dst
.type
) == 0);
260 assert(dst
.writemask
<= TOY_WRITEMASK_XYZW
);
266 * Change the type of the destination operand.
268 static inline struct toy_dst
269 tdst_type(struct toy_dst dst
, enum toy_type type
)
272 return tdst_validate(dst
);
276 * Change the type of the destination operand to TOY_TYPE_D.
278 static inline struct toy_dst
279 tdst_d(struct toy_dst dst
)
281 return tdst_type(dst
, TOY_TYPE_D
);
285 * Change the type of the destination operand to TOY_TYPE_UD.
287 static inline struct toy_dst
288 tdst_ud(struct toy_dst dst
)
290 return tdst_type(dst
, TOY_TYPE_UD
);
294 * Change the type of the destination operand to TOY_TYPE_W.
296 static inline struct toy_dst
297 tdst_w(struct toy_dst dst
)
299 return tdst_type(dst
, TOY_TYPE_W
);
303 * Change the type of the destination operand to TOY_TYPE_UW.
305 static inline struct toy_dst
306 tdst_uw(struct toy_dst dst
)
308 return tdst_type(dst
, TOY_TYPE_UW
);
312 * Change the rectangle of the destination operand.
314 static inline struct toy_dst
315 tdst_rect(struct toy_dst dst
, enum toy_rect rect
)
318 return tdst_validate(dst
);
322 * Apply writemask to the destination operand. Note that the current
323 * writemask is honored.
325 static inline struct toy_dst
326 tdst_writemask(struct toy_dst dst
, enum toy_writemask writemask
)
328 dst
.writemask
&= writemask
;
329 return tdst_validate(dst
);
333 * Offset the destination operand.
335 static inline struct toy_dst
336 tdst_offset(struct toy_dst dst
, int reg
, int subreg
)
338 dst
.val32
+= reg
* TOY_REG_WIDTH
+ subreg
* toy_type_size(dst
.type
);
339 return tdst_validate(dst
);
343 * Construct a destination operand.
345 static inline struct toy_dst
346 tdst_full(enum toy_file file
, enum toy_type type
, enum toy_rect rect
,
347 bool indirect
, unsigned indirect_subreg
,
348 enum toy_writemask writemask
, uint32_t val32
)
355 dst
.indirect
= indirect
;
356 dst
.indirect_subreg
= indirect_subreg
;
357 dst
.writemask
= writemask
;
362 return tdst_validate(dst
);
366 * Construct a null destination operand.
368 static inline struct toy_dst
371 static const struct toy_dst null_dst
= {
372 .file
= TOY_FILE_ARF
,
374 .rect
= TOY_RECT_LINEAR
,
376 .indirect_subreg
= 0,
377 .writemask
= TOY_WRITEMASK_XYZW
,
386 * Construct a destination operand from a source operand.
388 static inline struct toy_dst
389 tdst_from(struct toy_src src
)
391 const enum toy_writemask writemask
=
392 (1 << src
.swizzle_x
) |
393 (1 << src
.swizzle_y
) |
394 (1 << src
.swizzle_z
) |
395 (1 << src
.swizzle_w
);
397 return tdst_full(src
.file
, src
.type
, src
.rect
,
398 src
.indirect
, src
.indirect_subreg
, writemask
, src
.val32
);
402 * Construct a destination operand, assuming the type is TOY_TYPE_F, the
403 * rectangle is TOY_RECT_LINEAR, and the writemask is TOY_WRITEMASK_XYZW.
405 static inline struct toy_dst
406 tdst(enum toy_file file
, unsigned reg
, unsigned subreg_in_bytes
)
408 const enum toy_type type
= TOY_TYPE_F
;
409 const enum toy_rect rect
= TOY_RECT_LINEAR
;
410 const uint32_t val32
= reg
* TOY_REG_WIDTH
+ subreg_in_bytes
;
412 return tdst_full(file
, type
, rect
,
413 false, 0, TOY_WRITEMASK_XYZW
, val32
);
417 * Construct an immediate destination operand of type TOY_TYPE_W.
419 static inline struct toy_dst
420 tdst_imm_w(int16_t w
)
422 const union fi fi
= { .i
= w
};
424 return tdst_full(TOY_FILE_IMM
, TOY_TYPE_W
, TOY_RECT_LINEAR
,
425 false, 0, TOY_WRITEMASK_XYZW
, fi
.ui
);
429 * Return true if the source operand is null.
432 tsrc_is_null(struct toy_src src
)
434 /* BRW_ARF_NULL happens to be 0 */
435 return (src
.file
== TOY_FILE_ARF
&& src
.val32
== 0);
439 * Return true if the source operand is swizzled.
442 tsrc_is_swizzled(struct toy_src src
)
444 return (src
.swizzle_x
!= TOY_SWIZZLE_X
||
445 src
.swizzle_y
!= TOY_SWIZZLE_Y
||
446 src
.swizzle_z
!= TOY_SWIZZLE_Z
||
447 src
.swizzle_w
!= TOY_SWIZZLE_W
);
451 * Return true if the source operand is swizzled to the same channel.
454 tsrc_is_swizzle1(struct toy_src src
)
456 return (src
.swizzle_x
== src
.swizzle_y
&&
457 src
.swizzle_x
== src
.swizzle_z
&&
458 src
.swizzle_x
== src
.swizzle_w
);
462 * Validate the source operand.
464 static inline struct toy_src
465 tsrc_validate(struct toy_src src
)
471 assert(!src
.indirect
);
472 if (src
.file
== TOY_FILE_MRF
)
473 assert(src
.val32
< toy_file_size(src
.file
));
477 assert(src
.val32
< toy_file_size(src
.file
));
480 assert(!src
.indirect
);
483 assert(!"invalid src file");
489 assert(src
.file
== TOY_FILE_IMM
);
495 if (src
.file
!= TOY_FILE_IMM
)
496 assert(src
.val32
% toy_type_size(src
.type
) == 0);
498 assert(src
.swizzle_x
< 4 && src
.swizzle_y
< 4 &&
499 src
.swizzle_z
< 4 && src
.swizzle_w
< 4);
505 * Change the type of the source operand.
507 static inline struct toy_src
508 tsrc_type(struct toy_src src
, enum toy_type type
)
511 return tsrc_validate(src
);
515 * Change the type of the source operand to TOY_TYPE_D.
517 static inline struct toy_src
518 tsrc_d(struct toy_src src
)
520 return tsrc_type(src
, TOY_TYPE_D
);
524 * Change the type of the source operand to TOY_TYPE_UD.
526 static inline struct toy_src
527 tsrc_ud(struct toy_src src
)
529 return tsrc_type(src
, TOY_TYPE_UD
);
533 * Change the type of the source operand to TOY_TYPE_W.
535 static inline struct toy_src
536 tsrc_w(struct toy_src src
)
538 return tsrc_type(src
, TOY_TYPE_W
);
542 * Change the type of the source operand to TOY_TYPE_UW.
544 static inline struct toy_src
545 tsrc_uw(struct toy_src src
)
547 return tsrc_type(src
, TOY_TYPE_UW
);
551 * Change the rectangle of the source operand.
553 static inline struct toy_src
554 tsrc_rect(struct toy_src src
, enum toy_rect rect
)
557 return tsrc_validate(src
);
561 * Swizzle the source operand. Note that the current swizzles are honored.
563 static inline struct toy_src
564 tsrc_swizzle(struct toy_src src
,
565 enum toy_swizzle swizzle_x
, enum toy_swizzle swizzle_y
,
566 enum toy_swizzle swizzle_z
, enum toy_swizzle swizzle_w
)
568 const enum toy_swizzle current
[4] = {
569 src
.swizzle_x
, src
.swizzle_y
,
570 src
.swizzle_z
, src
.swizzle_w
,
573 src
.swizzle_x
= current
[swizzle_x
];
574 src
.swizzle_y
= current
[swizzle_y
];
575 src
.swizzle_z
= current
[swizzle_z
];
576 src
.swizzle_w
= current
[swizzle_w
];
578 return tsrc_validate(src
);
582 * Swizzle the source operand to the same channel. Note that the current
583 * swizzles are honored.
585 static inline struct toy_src
586 tsrc_swizzle1(struct toy_src src
, enum toy_swizzle swizzle
)
588 return tsrc_swizzle(src
, swizzle
, swizzle
, swizzle
, swizzle
);
592 * Set absolute and unset negate of the source operand.
594 static inline struct toy_src
595 tsrc_absolute(struct toy_src src
)
599 return tsrc_validate(src
);
603 * Negate the source operand.
605 static inline struct toy_src
606 tsrc_negate(struct toy_src src
)
608 src
.negate
= !src
.negate
;
609 return tsrc_validate(src
);
613 * Offset the source operand.
615 static inline struct toy_src
616 tsrc_offset(struct toy_src src
, int reg
, int subreg
)
618 src
.val32
+= reg
* TOY_REG_WIDTH
+ subreg
* toy_type_size(src
.type
);
619 return tsrc_validate(src
);
623 * Construct a source operand.
625 static inline struct toy_src
626 tsrc_full(enum toy_file file
, enum toy_type type
,
627 enum toy_rect rect
, bool indirect
, unsigned indirect_subreg
,
628 enum toy_swizzle swizzle_x
, enum toy_swizzle swizzle_y
,
629 enum toy_swizzle swizzle_z
, enum toy_swizzle swizzle_w
,
630 bool absolute
, bool negate
,
638 src
.indirect
= indirect
;
639 src
.indirect_subreg
= indirect_subreg
;
640 src
.swizzle_x
= swizzle_x
;
641 src
.swizzle_y
= swizzle_y
;
642 src
.swizzle_z
= swizzle_z
;
643 src
.swizzle_w
= swizzle_w
;
644 src
.absolute
= absolute
;
650 return tsrc_validate(src
);
654 * Construct a null source operand.
656 static inline struct toy_src
659 static const struct toy_src null_src
= {
660 .file
= TOY_FILE_ARF
,
662 .rect
= TOY_RECT_LINEAR
,
664 .indirect_subreg
= 0,
665 .swizzle_x
= TOY_SWIZZLE_X
,
666 .swizzle_y
= TOY_SWIZZLE_Y
,
667 .swizzle_z
= TOY_SWIZZLE_Z
,
668 .swizzle_w
= TOY_SWIZZLE_W
,
679 * Construct a source operand from a destination operand.
681 static inline struct toy_src
682 tsrc_from(struct toy_dst dst
)
684 enum toy_swizzle swizzle
[4];
686 if (dst
.writemask
== TOY_WRITEMASK_XYZW
) {
687 swizzle
[0] = TOY_SWIZZLE_X
;
688 swizzle
[1] = TOY_SWIZZLE_Y
;
689 swizzle
[2] = TOY_SWIZZLE_Z
;
690 swizzle
[3] = TOY_SWIZZLE_W
;
693 const enum toy_swizzle first
=
694 (dst
.writemask
& TOY_WRITEMASK_X
) ? TOY_SWIZZLE_X
:
695 (dst
.writemask
& TOY_WRITEMASK_Y
) ? TOY_SWIZZLE_Y
:
696 (dst
.writemask
& TOY_WRITEMASK_Z
) ? TOY_SWIZZLE_Z
:
697 (dst
.writemask
& TOY_WRITEMASK_W
) ? TOY_SWIZZLE_W
:
700 swizzle
[0] = (dst
.writemask
& TOY_WRITEMASK_X
) ? TOY_SWIZZLE_X
: first
;
701 swizzle
[1] = (dst
.writemask
& TOY_WRITEMASK_Y
) ? TOY_SWIZZLE_Y
: first
;
702 swizzle
[2] = (dst
.writemask
& TOY_WRITEMASK_Z
) ? TOY_SWIZZLE_Z
: first
;
703 swizzle
[3] = (dst
.writemask
& TOY_WRITEMASK_W
) ? TOY_SWIZZLE_W
: first
;
706 return tsrc_full(dst
.file
, dst
.type
, dst
.rect
,
707 dst
.indirect
, dst
.indirect_subreg
,
708 swizzle
[0], swizzle
[1], swizzle
[2], swizzle
[3],
709 false, false, dst
.val32
);
713 * Construct a source operand, assuming the type is TOY_TYPE_F, the
714 * rectangle is TOY_RECT_LINEAR, and no swizzles/absolute/negate.
716 static inline struct toy_src
717 tsrc(enum toy_file file
, unsigned reg
, unsigned subreg_in_bytes
)
719 const enum toy_type type
= TOY_TYPE_F
;
720 const enum toy_rect rect
= TOY_RECT_LINEAR
;
721 const uint32_t val32
= reg
* TOY_REG_WIDTH
+ subreg_in_bytes
;
723 return tsrc_full(file
, type
, rect
, false, 0,
724 TOY_SWIZZLE_X
, TOY_SWIZZLE_Y
,
725 TOY_SWIZZLE_Z
, TOY_SWIZZLE_W
,
726 false, false, val32
);
730 * Construct an immediate source operand.
732 static inline struct toy_src
733 tsrc_imm(enum toy_type type
, uint32_t val32
)
735 return tsrc_full(TOY_FILE_IMM
, type
, TOY_RECT_LINEAR
, false, 0,
736 TOY_SWIZZLE_X
, TOY_SWIZZLE_Y
,
737 TOY_SWIZZLE_Z
, TOY_SWIZZLE_W
,
738 false, false, val32
);
742 * Construct an immediate source operand of type TOY_TYPE_F.
744 static inline struct toy_src
747 const union fi fi
= { .f
= f
};
748 return tsrc_imm(TOY_TYPE_F
, fi
.ui
);
752 * Construct an immediate source operand of type TOY_TYPE_D.
754 static inline struct toy_src
755 tsrc_imm_d(int32_t d
)
757 const union fi fi
= { .i
= d
};
758 return tsrc_imm(TOY_TYPE_D
, fi
.ui
);
762 * Construct an immediate source operand of type TOY_TYPE_UD.
764 static inline struct toy_src
765 tsrc_imm_ud(uint32_t ud
)
767 const union fi fi
= { .ui
= ud
};
768 return tsrc_imm(TOY_TYPE_UD
, fi
.ui
);
772 * Construct an immediate source operand of type TOY_TYPE_W.
774 static inline struct toy_src
775 tsrc_imm_w(int16_t w
)
777 const union fi fi
= { .i
= w
};
778 return tsrc_imm(TOY_TYPE_W
, fi
.ui
);
782 * Construct an immediate source operand of type TOY_TYPE_UW.
784 static inline struct toy_src
785 tsrc_imm_uw(uint16_t uw
)
787 const union fi fi
= { .ui
= uw
};
788 return tsrc_imm(TOY_TYPE_UW
, fi
.ui
);
792 * Construct an immediate source operand of type TOY_TYPE_V.
794 static inline struct toy_src
795 tsrc_imm_v(uint32_t v
)
797 return tsrc_imm(TOY_TYPE_V
, v
);
800 #endif /* TOY_REG_H */