1 /*
2 * Mesa 3-D graphics library
3 *
4 * Copyright (C) 2012-2013 LunarG, Inc.
5 *
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:
12 *
13 * The above copyright notice and this permission notice shall be included
14 * in all copies or substantial portions of the Software.
15 *
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.
23 *
24 * Authors:
25 * Chia-I Wu <olv@lunarg.com>
26 */
27
28 #ifndef TOY_REG_H
29 #define TOY_REG_H
30
31 #include "pipe/p_compiler.h"
32 #include "util/u_debug.h" /* for assert() */
33 #include "util/u_math.h" /* for union fi */
34
35 /* a toy reg is 256-bit wide */
36 #define TOY_REG_WIDTH 32
37
38 /**
39 * Register files.
40 */
41 enum toy_file {
42 /* virtual register file */
43 TOY_FILE_VRF,
44
45 TOY_FILE_ARF,
46 TOY_FILE_GRF,
47 TOY_FILE_MRF,
48 TOY_FILE_IMM,
49
50 TOY_FILE_COUNT,
51 };
52
53 /**
54 * Register types.
55 */
56 enum toy_type {
57 TOY_TYPE_F,
58 TOY_TYPE_D,
59 TOY_TYPE_UD,
60 TOY_TYPE_W,
61 TOY_TYPE_UW,
62 TOY_TYPE_V, /* only valid for immediates */
63
64 TOY_TYPE_COUNT,
65 };
66
67 /**
68 * Register rectangles. The three numbers stand for vertical stride, width,
69 * and horizontal stride respectively.
70 */
71 enum toy_rect {
72 TOY_RECT_LINEAR,
73 TOY_RECT_041,
74 TOY_RECT_010,
75 TOY_RECT_220,
76 TOY_RECT_440,
77 TOY_RECT_240,
78
79 TOY_RECT_COUNT,
80 };
81
82 /**
83 * Source swizzles. They are compatible with TGSI_SWIZZLE_x and hardware
84 * values.
85 */
86 enum toy_swizzle {
87 TOY_SWIZZLE_X = 0,
88 TOY_SWIZZLE_Y = 1,
89 TOY_SWIZZLE_Z = 2,
90 TOY_SWIZZLE_W = 3,
91 };
92
93 /**
94 * Destination writemasks. They are compatible with TGSI_WRITEMASK_x and
95 * hardware values.
96 */
97 enum toy_writemask {
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),
114 };
115
116 /**
117 * Destination operand.
118 */
119 struct toy_dst {
120 unsigned file:3; /* TOY_FILE_x */
121 unsigned type:4; /* 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? */
125
126 unsigned writemask:4; /* TOY_WRITEMASK_x */
127 unsigned pad:11;
128
129 uint32_t val32;
130 };
131
132 /**
133 * Source operand.
134 */
135 struct toy_src {
136 unsigned file:3; /* TOY_FILE_x */
137 unsigned type:4; /* 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? */
141
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 */
148 unsigned pad:5;
149
150 uint32_t val32;
151 };
152
153 /**
154 * Return true if the file is virtual.
155 */
156 static inline bool
toy_file_is_virtual(enum toy_file file)157 toy_file_is_virtual(enum toy_file file)
158 {
159 return (file == TOY_FILE_VRF);
160 }
161
162 /**
163 * Return true if the file is a hardware one.
164 */
165 static inline bool
toy_file_is_hw(enum toy_file file)166 toy_file_is_hw(enum toy_file file)
167 {
168 return !toy_file_is_virtual(file);
169 }
170
171 /**
172 * Return the size of the file.
173 */
174 static inline uint32_t
toy_file_size(enum toy_file file)175 toy_file_size(enum toy_file file)
176 {
177 switch (file) {
178 case TOY_FILE_GRF:
179 return 256 * TOY_REG_WIDTH;
180 case TOY_FILE_MRF:
181 /* there is no MRF on GEN7+ */
182 return 256 * TOY_REG_WIDTH;
183 default:
184 assert(!"invalid toy file");
185 return 0;
186 }
187 }
188
189 /**
190 * Return the size of the type.
191 */
192 static inline int
toy_type_size(enum toy_type type)193 toy_type_size(enum toy_type type)
194 {
195 switch (type) {
196 case TOY_TYPE_F:
197 case TOY_TYPE_D:
198 case TOY_TYPE_UD:
199 return 4;
200 case TOY_TYPE_W:
201 case TOY_TYPE_UW:
202 return 2;
203 case TOY_TYPE_V:
204 default:
205 assert(!"invalid toy type");
206 return 0;
207 }
208 }
209
210 /**
211 * Return true if the destination operand is null.
212 */
213 static inline bool
tdst_is_null(struct toy_dst dst)214 tdst_is_null(struct toy_dst dst)
215 {
216 /* GEN6_ARF_NULL happens to be 0 */
217 return (dst.file == TOY_FILE_ARF && dst.val32 == 0);
218 }
219
220 /**
221 * Validate the destination operand.
222 */
223 static inline struct toy_dst
tdst_validate(struct toy_dst dst)224 tdst_validate(struct toy_dst dst)
225 {
226 switch (dst.file) {
227 case TOY_FILE_VRF:
228 case TOY_FILE_ARF:
229 case TOY_FILE_MRF:
230 assert(!dst.indirect);
231 if (dst.file == TOY_FILE_MRF)
232 assert(dst.val32 < toy_file_size(dst.file));
233 break;
234 case TOY_FILE_GRF:
235 if (!dst.indirect)
236 assert(dst.val32 < toy_file_size(dst.file));
237 break;
238 case TOY_FILE_IMM:
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);
242 break;
243 default:
244 assert(!"invalid dst file");
245 break;
246 }
247
248 switch (dst.type) {
249 case TOY_TYPE_V:
250 assert(!"invalid dst type");
251 break;
252 default:
253 break;
254 }
255
256 assert(dst.rect == TOY_RECT_LINEAR);
257 if (dst.file != TOY_FILE_IMM)
258 assert(dst.val32 % toy_type_size(dst.type) == 0);
259
260 assert(dst.writemask <= TOY_WRITEMASK_XYZW);
261
262 return dst;
263 }
264
265 /**
266 * Change the type of the destination operand.
267 */
268 static inline struct toy_dst
tdst_type(struct toy_dst dst,enum toy_type type)269 tdst_type(struct toy_dst dst, enum toy_type type)
270 {
271 dst.type = type;
272 return tdst_validate(dst);
273 }
274
275 /**
276 * Change the type of the destination operand to TOY_TYPE_D.
277 */
278 static inline struct toy_dst
tdst_d(struct toy_dst dst)279 tdst_d(struct toy_dst dst)
280 {
281 return tdst_type(dst, TOY_TYPE_D);
282 }
283
284 /**
285 * Change the type of the destination operand to TOY_TYPE_UD.
286 */
287 static inline struct toy_dst
tdst_ud(struct toy_dst dst)288 tdst_ud(struct toy_dst dst)
289 {
290 return tdst_type(dst, TOY_TYPE_UD);
291 }
292
293 /**
294 * Change the type of the destination operand to TOY_TYPE_W.
295 */
296 static inline struct toy_dst
tdst_w(struct toy_dst dst)297 tdst_w(struct toy_dst dst)
298 {
299 return tdst_type(dst, TOY_TYPE_W);
300 }
301
302 /**
303 * Change the type of the destination operand to TOY_TYPE_UW.
304 */
305 static inline struct toy_dst
tdst_uw(struct toy_dst dst)306 tdst_uw(struct toy_dst dst)
307 {
308 return tdst_type(dst, TOY_TYPE_UW);
309 }
310
311 /**
312 * Change the rectangle of the destination operand.
313 */
314 static inline struct toy_dst
tdst_rect(struct toy_dst dst,enum toy_rect rect)315 tdst_rect(struct toy_dst dst, enum toy_rect rect)
316 {
317 dst.rect = rect;
318 return tdst_validate(dst);
319 }
320
321 /**
322 * Apply writemask to the destination operand. Note that the current
323 * writemask is honored.
324 */
325 static inline struct toy_dst
tdst_writemask(struct toy_dst dst,enum toy_writemask writemask)326 tdst_writemask(struct toy_dst dst, enum toy_writemask writemask)
327 {
328 dst.writemask &= writemask;
329 return tdst_validate(dst);
330 }
331
332 /**
333 * Offset the destination operand.
334 */
335 static inline struct toy_dst
tdst_offset(struct toy_dst dst,int reg,int subreg)336 tdst_offset(struct toy_dst dst, int reg, int subreg)
337 {
338 dst.val32 += reg * TOY_REG_WIDTH + subreg * toy_type_size(dst.type);
339 return tdst_validate(dst);
340 }
341
342 /**
343 * Construct a destination operand.
344 */
345 static inline struct toy_dst
tdst_full(enum toy_file file,enum toy_type type,enum toy_rect rect,bool indirect,unsigned indirect_subreg,enum toy_writemask writemask,uint32_t val32)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)
349 {
350 struct toy_dst dst;
351
352 dst.file = file;
353 dst.type = type;
354 dst.rect = rect;
355 dst.indirect = indirect;
356 dst.indirect_subreg = indirect_subreg;
357 dst.writemask = writemask;
358 dst.pad = 0;
359
360 dst.val32 = val32;
361
362 return tdst_validate(dst);
363 }
364
365 /**
366 * Construct a null destination operand.
367 */
368 static inline struct toy_dst
tdst_null(void)369 tdst_null(void)
370 {
371 static const struct toy_dst null_dst = {
372 .file = TOY_FILE_ARF,
373 .type = TOY_TYPE_F,
374 .rect = TOY_RECT_LINEAR,
375 .indirect = false,
376 .indirect_subreg = 0,
377 .writemask = TOY_WRITEMASK_XYZW,
378 .pad = 0,
379 .val32 = 0,
380 };
381
382 return null_dst;
383 }
384
385 /**
386 * Construct a destination operand from a source operand.
387 */
388 static inline struct toy_dst
tdst_from(struct toy_src src)389 tdst_from(struct toy_src src)
390 {
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);
396
397 return tdst_full(src.file, src.type, src.rect,
398 src.indirect, src.indirect_subreg, writemask, src.val32);
399 }
400
401 /**
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.
404 */
405 static inline struct toy_dst
tdst(enum toy_file file,unsigned reg,unsigned subreg_in_bytes)406 tdst(enum toy_file file, unsigned reg, unsigned subreg_in_bytes)
407 {
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;
411
412 return tdst_full(file, type, rect,
413 false, 0, TOY_WRITEMASK_XYZW, val32);
414 }
415
416 /**
417 * Construct an immediate destination operand of type TOY_TYPE_W.
418 */
419 static inline struct toy_dst
tdst_imm_w(int16_t w)420 tdst_imm_w(int16_t w)
421 {
422 const union fi fi = { .i = w };
423
424 return tdst_full(TOY_FILE_IMM, TOY_TYPE_W, TOY_RECT_LINEAR,
425 false, 0, TOY_WRITEMASK_XYZW, fi.ui);
426 }
427
428 /**
429 * Return true if the source operand is null.
430 */
431 static inline bool
tsrc_is_null(struct toy_src src)432 tsrc_is_null(struct toy_src src)
433 {
434 /* GEN6_ARF_NULL happens to be 0 */
435 return (src.file == TOY_FILE_ARF && src.val32 == 0);
436 }
437
438 /**
439 * Return true if the source operand is swizzled.
440 */
441 static inline bool
tsrc_is_swizzled(struct toy_src src)442 tsrc_is_swizzled(struct toy_src src)
443 {
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);
448 }
449
450 /**
451 * Return true if the source operand is swizzled to the same channel.
452 */
453 static inline bool
tsrc_is_swizzle1(struct toy_src src)454 tsrc_is_swizzle1(struct toy_src src)
455 {
456 return (src.swizzle_x == src.swizzle_y &&
457 src.swizzle_x == src.swizzle_z &&
458 src.swizzle_x == src.swizzle_w);
459 }
460
461 /**
462 * Validate the source operand.
463 */
464 static inline struct toy_src
tsrc_validate(struct toy_src src)465 tsrc_validate(struct toy_src src)
466 {
467 switch (src.file) {
468 case TOY_FILE_VRF:
469 case TOY_FILE_ARF:
470 case TOY_FILE_MRF:
471 assert(!src.indirect);
472 if (src.file == TOY_FILE_MRF)
473 assert(src.val32 < toy_file_size(src.file));
474 break;
475 case TOY_FILE_GRF:
476 if (!src.indirect)
477 assert(src.val32 < toy_file_size(src.file));
478 break;
479 case TOY_FILE_IMM:
480 assert(!src.indirect);
481 break;
482 default:
483 assert(!"invalid src file");
484 break;
485 }
486
487 switch (src.type) {
488 case TOY_TYPE_V:
489 assert(src.file == TOY_FILE_IMM);
490 break;
491 default:
492 break;
493 }
494
495 if (src.file != TOY_FILE_IMM)
496 assert(src.val32 % toy_type_size(src.type) == 0);
497
498 assert(src.swizzle_x < 4 && src.swizzle_y < 4 &&
499 src.swizzle_z < 4 && src.swizzle_w < 4);
500
501 return src;
502 }
503
504 /**
505 * Change the type of the source operand.
506 */
507 static inline struct toy_src
tsrc_type(struct toy_src src,enum toy_type type)508 tsrc_type(struct toy_src src, enum toy_type type)
509 {
510 src.type = type;
511 return tsrc_validate(src);
512 }
513
514 /**
515 * Change the type of the source operand to TOY_TYPE_D.
516 */
517 static inline struct toy_src
tsrc_d(struct toy_src src)518 tsrc_d(struct toy_src src)
519 {
520 return tsrc_type(src, TOY_TYPE_D);
521 }
522
523 /**
524 * Change the type of the source operand to TOY_TYPE_UD.
525 */
526 static inline struct toy_src
tsrc_ud(struct toy_src src)527 tsrc_ud(struct toy_src src)
528 {
529 return tsrc_type(src, TOY_TYPE_UD);
530 }
531
532 /**
533 * Change the type of the source operand to TOY_TYPE_W.
534 */
535 static inline struct toy_src
tsrc_w(struct toy_src src)536 tsrc_w(struct toy_src src)
537 {
538 return tsrc_type(src, TOY_TYPE_W);
539 }
540
541 /**
542 * Change the type of the source operand to TOY_TYPE_UW.
543 */
544 static inline struct toy_src
tsrc_uw(struct toy_src src)545 tsrc_uw(struct toy_src src)
546 {
547 return tsrc_type(src, TOY_TYPE_UW);
548 }
549
550 /**
551 * Change the rectangle of the source operand.
552 */
553 static inline struct toy_src
tsrc_rect(struct toy_src src,enum toy_rect rect)554 tsrc_rect(struct toy_src src, enum toy_rect rect)
555 {
556 src.rect = rect;
557 return tsrc_validate(src);
558 }
559
560 /**
561 * Swizzle the source operand. Note that the current swizzles are honored.
562 */
563 static inline struct toy_src
tsrc_swizzle(struct toy_src src,enum toy_swizzle swizzle_x,enum toy_swizzle swizzle_y,enum toy_swizzle swizzle_z,enum toy_swizzle swizzle_w)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)
567 {
568 const enum toy_swizzle current[4] = {
569 src.swizzle_x, src.swizzle_y,
570 src.swizzle_z, src.swizzle_w,
571 };
572
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];
577
578 return tsrc_validate(src);
579 }
580
581 /**
582 * Swizzle the source operand to the same channel. Note that the current
583 * swizzles are honored.
584 */
585 static inline struct toy_src
tsrc_swizzle1(struct toy_src src,enum toy_swizzle swizzle)586 tsrc_swizzle1(struct toy_src src, enum toy_swizzle swizzle)
587 {
588 return tsrc_swizzle(src, swizzle, swizzle, swizzle, swizzle);
589 }
590
591 /**
592 * Set absolute and unset negate of the source operand.
593 */
594 static inline struct toy_src
tsrc_absolute(struct toy_src src)595 tsrc_absolute(struct toy_src src)
596 {
597 src.absolute = true;
598 src.negate = false;
599 return tsrc_validate(src);
600 }
601
602 /**
603 * Negate the source operand.
604 */
605 static inline struct toy_src
tsrc_negate(struct toy_src src)606 tsrc_negate(struct toy_src src)
607 {
608 src.negate = !src.negate;
609 return tsrc_validate(src);
610 }
611
612 /**
613 * Offset the source operand.
614 */
615 static inline struct toy_src
tsrc_offset(struct toy_src src,int reg,int subreg)616 tsrc_offset(struct toy_src src, int reg, int subreg)
617 {
618 src.val32 += reg * TOY_REG_WIDTH + subreg * toy_type_size(src.type);
619 return tsrc_validate(src);
620 }
621
622 /**
623 * Construct a source operand.
624 */
625 static inline struct toy_src
tsrc_full(enum toy_file file,enum toy_type type,enum toy_rect rect,bool indirect,unsigned indirect_subreg,enum toy_swizzle swizzle_x,enum toy_swizzle swizzle_y,enum toy_swizzle swizzle_z,enum toy_swizzle swizzle_w,bool absolute,bool negate,uint32_t val32)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,
631 uint32_t val32)
632 {
633 struct toy_src src;
634
635 src.file = file;
636 src.type = type;
637 src.rect = rect;
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;
645 src.negate = negate;
646 src.pad = 0;
647
648 src.val32 = val32;
649
650 return tsrc_validate(src);
651 }
652
653 /**
654 * Construct a null source operand.
655 */
656 static inline struct toy_src
tsrc_null(void)657 tsrc_null(void)
658 {
659 static const struct toy_src null_src = {
660 .file = TOY_FILE_ARF,
661 .type = TOY_TYPE_F,
662 .rect = TOY_RECT_LINEAR,
663 .indirect = false,
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,
669 .absolute = false,
670 .negate = false,
671 .pad = 0,
672 .val32 = 0,
673 };
674
675 return null_src;
676 }
677
678 /**
679 * Construct a source operand from a destination operand.
680 */
681 static inline struct toy_src
tsrc_from(struct toy_dst dst)682 tsrc_from(struct toy_dst dst)
683 {
684 enum toy_swizzle swizzle[4];
685
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;
691 }
692 else {
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 :
698 TOY_SWIZZLE_X;
699
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;
704 }
705
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);
710 }
711
712 /**
713 * Construct a source operand, assuming the type is TOY_TYPE_F, the
714 * rectangle is TOY_RECT_LINEAR, and no swizzles/absolute/negate.
715 */
716 static inline struct toy_src
tsrc(enum toy_file file,unsigned reg,unsigned subreg_in_bytes)717 tsrc(enum toy_file file, unsigned reg, unsigned subreg_in_bytes)
718 {
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;
722
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);
727 }
728
729 /**
730 * Construct an immediate source operand.
731 */
732 static inline struct toy_src
tsrc_imm(enum toy_type type,uint32_t val32)733 tsrc_imm(enum toy_type type, uint32_t val32)
734 {
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);
739 }
740
741 /**
742 * Construct an immediate source operand of type TOY_TYPE_F.
743 */
744 static inline struct toy_src
tsrc_imm_f(float f)745 tsrc_imm_f(float f)
746 {
747 const union fi fi = { .f = f };
748 return tsrc_imm(TOY_TYPE_F, fi.ui);
749 }
750
751 /**
752 * Construct an immediate source operand of type TOY_TYPE_D.
753 */
754 static inline struct toy_src
tsrc_imm_d(int32_t d)755 tsrc_imm_d(int32_t d)
756 {
757 const union fi fi = { .i = d };
758 return tsrc_imm(TOY_TYPE_D, fi.ui);
759 }
760
761 /**
762 * Construct an immediate source operand of type TOY_TYPE_UD.
763 */
764 static inline struct toy_src
tsrc_imm_ud(uint32_t ud)765 tsrc_imm_ud(uint32_t ud)
766 {
767 const union fi fi = { .ui = ud };
768 return tsrc_imm(TOY_TYPE_UD, fi.ui);
769 }
770
771 /**
772 * Construct an immediate source operand of type TOY_TYPE_W.
773 */
774 static inline struct toy_src
tsrc_imm_w(int16_t w)775 tsrc_imm_w(int16_t w)
776 {
777 const union fi fi = { .i = w };
778 return tsrc_imm(TOY_TYPE_W, fi.ui);
779 }
780
781 /**
782 * Construct an immediate source operand of type TOY_TYPE_UW.
783 */
784 static inline struct toy_src
tsrc_imm_uw(uint16_t uw)785 tsrc_imm_uw(uint16_t uw)
786 {
787 const union fi fi = { .ui = uw };
788 return tsrc_imm(TOY_TYPE_UW, fi.ui);
789 }
790
791 /**
792 * Construct an immediate source operand of type TOY_TYPE_V.
793 */
794 static inline struct toy_src
tsrc_imm_v(uint32_t v)795 tsrc_imm_v(uint32_t v)
796 {
797 return tsrc_imm(TOY_TYPE_V, v);
798 }
799
800 #endif /* TOY_REG_H */
801