Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
5564 | serge | 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 |
||
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 |
||
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 |
||
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 |
||
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 |
||
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 |
||
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 |
||
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 |
||
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 |
||
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 |
||
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 |
||
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 |
||
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 |
||
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 |
||
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 |
||
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 |
||
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 |
||
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 |
||
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 |
||
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 |
||
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 |
||
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 |
||
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 |
||
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 |
||
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 |
||
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 |
||
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 |
||
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 |
||
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 |
||
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 |
||
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 |
||
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 |
||
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 |
||
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 |
||
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 |
||
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 |
||
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 |
||
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 |
||
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 |
||
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 |
||
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 |
||
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 |
||
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 |
||
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 |
||
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 |
||
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 |
||
795 | tsrc_imm_v(uint32_t v) |
||
796 | { |
||
797 | return tsrc_imm(TOY_TYPE_V, v); |
||
798 | } |
||
799 | |||
800 | #endif /* TOY_REG_H */>>>>>>><>><>><>><>=>>>><>><>><>><> |