• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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