1 /*
2  * Copyright (C) 2009 Nicolai Haehnle.
3  *
4  * All Rights Reserved.
5  *
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:
13  *
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.
17  *
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.
25  *
26  */
27 
28 #include "radeon_opcodes.h"
29 #include "radeon_program.h"
30 
31 #include "radeon_program_constants.h"
32 
33 #include "util/compiler.h"
34 
35 const struct rc_opcode_info rc_opcodes[MAX_RC_OPCODE] = {
36 	{
37 		.Opcode = RC_OPCODE_NOP,
38 		.Name = "NOP"
39 	},
40 	{
41 		.Opcode = RC_OPCODE_ILLEGAL_OPCODE,
42 		.Name = "ILLEGAL OPCODE"
43 	},
44 	{
45 		.Opcode = RC_OPCODE_ABS,
46 		.Name = "ABS",
47 		.NumSrcRegs = 1,
48 		.HasDstReg = 1,
49 		.IsComponentwise = 1
50 	},
51 	{
52 		.Opcode = RC_OPCODE_ADD,
53 		.Name = "ADD",
54 		.NumSrcRegs = 2,
55 		.HasDstReg = 1,
56 		.IsComponentwise = 1
57 	},
58 	{
59 		.Opcode = RC_OPCODE_ARL,
60 		.Name = "ARL",
61 		.NumSrcRegs = 1,
62 		.HasDstReg = 1
63 	},
64 	{
65 		.Opcode = RC_OPCODE_ARR,
66 		.Name = "ARR",
67 		.NumSrcRegs = 1,
68 		.HasDstReg = 1
69 	},
70 	{
71 		.Opcode = RC_OPCODE_CEIL,
72 		.Name = "CEIL",
73 		.NumSrcRegs = 1,
74 		.HasDstReg = 1,
75 		.IsComponentwise = 1
76 	},
77 	{
78 		.Opcode = RC_OPCODE_CLAMP,
79 		.Name = "CLAMP",
80 		.NumSrcRegs = 3,
81 		.HasDstReg = 1,
82 		.IsComponentwise = 1
83 	},
84 	{
85 		.Opcode = RC_OPCODE_CMP,
86 		.Name = "CMP",
87 		.NumSrcRegs = 3,
88 		.HasDstReg = 1,
89 		.IsComponentwise = 1
90 	},
91 	{
92 		.Opcode = RC_OPCODE_CND,
93 		.Name = "CND",
94 		.NumSrcRegs = 3,
95 		.HasDstReg = 1,
96 		.IsComponentwise = 1
97 	},
98 	{
99 		.Opcode = RC_OPCODE_COS,
100 		.Name = "COS",
101 		.NumSrcRegs = 1,
102 		.HasDstReg = 1,
103 		.IsStandardScalar = 1
104 	},
105 	{
106 		.Opcode = RC_OPCODE_DDX,
107 		.Name = "DDX",
108 		.NumSrcRegs = 2,
109 		.HasDstReg = 1,
110 		.IsComponentwise = 1
111 	},
112 	{
113 		.Opcode = RC_OPCODE_DDY,
114 		.Name = "DDY",
115 		.NumSrcRegs = 2,
116 		.HasDstReg = 1,
117 		.IsComponentwise = 1
118 	},
119 	{
120 		.Opcode = RC_OPCODE_DP2,
121 		.Name = "DP2",
122 		.NumSrcRegs = 2,
123 		.HasDstReg = 1
124 	},
125 	{
126 		.Opcode = RC_OPCODE_DP3,
127 		.Name = "DP3",
128 		.NumSrcRegs = 2,
129 		.HasDstReg = 1
130 	},
131 	{
132 		.Opcode = RC_OPCODE_DP4,
133 		.Name = "DP4",
134 		.NumSrcRegs = 2,
135 		.HasDstReg = 1
136 	},
137 	{
138 		.Opcode = RC_OPCODE_DPH,
139 		.Name = "DPH",
140 		.NumSrcRegs = 2,
141 		.HasDstReg = 1
142 	},
143 	{
144 		.Opcode = RC_OPCODE_DST,
145 		.Name = "DST",
146 		.NumSrcRegs = 2,
147 		.HasDstReg = 1
148 	},
149 	{
150 		.Opcode = RC_OPCODE_EX2,
151 		.Name = "EX2",
152 		.NumSrcRegs = 1,
153 		.HasDstReg = 1,
154 		.IsStandardScalar = 1
155 	},
156 	{
157 		.Opcode = RC_OPCODE_EXP,
158 		.Name = "EXP",
159 		.NumSrcRegs = 1,
160 		.HasDstReg = 1
161 	},
162 	{
163 		.Opcode = RC_OPCODE_FLR,
164 		.Name = "FLR",
165 		.NumSrcRegs = 1,
166 		.HasDstReg = 1,
167 		.IsComponentwise = 1
168 	},
169 	{
170 		.Opcode = RC_OPCODE_FRC,
171 		.Name = "FRC",
172 		.NumSrcRegs = 1,
173 		.HasDstReg = 1,
174 		.IsComponentwise = 1
175 	},
176 	{
177 		.Opcode = RC_OPCODE_KIL,
178 		.Name = "KIL",
179 		.NumSrcRegs = 1
180 	},
181 	{
182 		.Opcode = RC_OPCODE_LG2,
183 		.Name = "LG2",
184 		.NumSrcRegs = 1,
185 		.HasDstReg = 1,
186 		.IsStandardScalar = 1
187 	},
188 	{
189 		.Opcode = RC_OPCODE_LIT,
190 		.Name = "LIT",
191 		.NumSrcRegs = 1,
192 		.HasDstReg = 1
193 	},
194 	{
195 		.Opcode = RC_OPCODE_LOG,
196 		.Name = "LOG",
197 		.NumSrcRegs = 1,
198 		.HasDstReg = 1
199 	},
200 	{
201 		.Opcode = RC_OPCODE_LRP,
202 		.Name = "LRP",
203 		.NumSrcRegs = 3,
204 		.HasDstReg = 1,
205 		.IsComponentwise = 1
206 	},
207 	{
208 		.Opcode = RC_OPCODE_MAD,
209 		.Name = "MAD",
210 		.NumSrcRegs = 3,
211 		.HasDstReg = 1,
212 		.IsComponentwise = 1
213 	},
214 	{
215 		.Opcode = RC_OPCODE_MAX,
216 		.Name = "MAX",
217 		.NumSrcRegs = 2,
218 		.HasDstReg = 1,
219 		.IsComponentwise = 1
220 	},
221 	{
222 		.Opcode = RC_OPCODE_MIN,
223 		.Name = "MIN",
224 		.NumSrcRegs = 2,
225 		.HasDstReg = 1,
226 		.IsComponentwise = 1
227 	},
228 	{
229 		.Opcode = RC_OPCODE_MOV,
230 		.Name = "MOV",
231 		.NumSrcRegs = 1,
232 		.HasDstReg = 1,
233 		.IsComponentwise = 1
234 	},
235 	{
236 		.Opcode = RC_OPCODE_MUL,
237 		.Name = "MUL",
238 		.NumSrcRegs = 2,
239 		.HasDstReg = 1,
240 		.IsComponentwise = 1
241 	},
242 	{
243 		.Opcode = RC_OPCODE_POW,
244 		.Name = "POW",
245 		.NumSrcRegs = 2,
246 		.HasDstReg = 1,
247 		.IsStandardScalar = 1
248 	},
249 	{
250 		.Opcode = RC_OPCODE_RCP,
251 		.Name = "RCP",
252 		.NumSrcRegs = 1,
253 		.HasDstReg = 1,
254 		.IsStandardScalar = 1
255 	},
256 	{
257 		.Opcode = RC_OPCODE_ROUND,
258 		.Name = "ROUND",
259 		.NumSrcRegs = 1,
260 		.HasDstReg = 1,
261 		.IsComponentwise = 1
262 	},
263 	{
264 		.Opcode = RC_OPCODE_RSQ,
265 		.Name = "RSQ",
266 		.NumSrcRegs = 1,
267 		.HasDstReg = 1,
268 		.IsStandardScalar = 1
269 	},
270 	{
271 		.Opcode = RC_OPCODE_SCS,
272 		.Name = "SCS",
273 		.NumSrcRegs = 1,
274 		.HasDstReg = 1
275 	},
276 	{
277 		.Opcode = RC_OPCODE_SEQ,
278 		.Name = "SEQ",
279 		.NumSrcRegs = 2,
280 		.HasDstReg = 1,
281 		.IsComponentwise = 1
282 	},
283 	{
284 		.Opcode = RC_OPCODE_SFL,
285 		.Name = "SFL",
286 		.NumSrcRegs = 0,
287 		.HasDstReg = 1,
288 		.IsComponentwise = 1
289 	},
290 	{
291 		.Opcode = RC_OPCODE_SGE,
292 		.Name = "SGE",
293 		.NumSrcRegs = 2,
294 		.HasDstReg = 1,
295 		.IsComponentwise = 1
296 	},
297 	{
298 		.Opcode = RC_OPCODE_SGT,
299 		.Name = "SGT",
300 		.NumSrcRegs = 2,
301 		.HasDstReg = 1,
302 		.IsComponentwise = 1
303 	},
304 	{
305 		.Opcode = RC_OPCODE_SIN,
306 		.Name = "SIN",
307 		.NumSrcRegs = 1,
308 		.HasDstReg = 1,
309 		.IsStandardScalar = 1
310 	},
311 	{
312 		.Opcode = RC_OPCODE_SLE,
313 		.Name = "SLE",
314 		.NumSrcRegs = 2,
315 		.HasDstReg = 1,
316 		.IsComponentwise = 1
317 	},
318 	{
319 		.Opcode = RC_OPCODE_SLT,
320 		.Name = "SLT",
321 		.NumSrcRegs = 2,
322 		.HasDstReg = 1,
323 		.IsComponentwise = 1
324 	},
325 	{
326 		.Opcode = RC_OPCODE_SNE,
327 		.Name = "SNE",
328 		.NumSrcRegs = 2,
329 		.HasDstReg = 1,
330 		.IsComponentwise = 1
331 	},
332 	{
333 		.Opcode = RC_OPCODE_SSG,
334 		.Name = "SSG",
335 		.NumSrcRegs = 1,
336 		.HasDstReg = 1,
337 		.IsComponentwise = 1
338 	},
339 	{
340 		.Opcode = RC_OPCODE_SUB,
341 		.Name = "SUB",
342 		.NumSrcRegs = 2,
343 		.HasDstReg = 1,
344 		.IsComponentwise = 1
345 	},
346 	{
347 		.Opcode = RC_OPCODE_SWZ,
348 		.Name = "SWZ",
349 		.NumSrcRegs = 1,
350 		.HasDstReg = 1,
351 		.IsComponentwise = 1
352 	},
353 	{
354 		.Opcode = RC_OPCODE_TRUNC,
355 		.Name = "TRUNC",
356 		.NumSrcRegs = 1,
357 		.HasDstReg = 1,
358 		.IsComponentwise = 1
359 	},
360 	{
361 		.Opcode = RC_OPCODE_XPD,
362 		.Name = "XPD",
363 		.NumSrcRegs = 2,
364 		.HasDstReg = 1
365 	},
366 	{
367 		.Opcode = RC_OPCODE_TEX,
368 		.Name = "TEX",
369 		.HasTexture = 1,
370 		.NumSrcRegs = 1,
371 		.HasDstReg = 1
372 	},
373 	{
374 		.Opcode = RC_OPCODE_TXB,
375 		.Name = "TXB",
376 		.HasTexture = 1,
377 		.NumSrcRegs = 1,
378 		.HasDstReg = 1
379 	},
380 	{
381 		.Opcode = RC_OPCODE_TXD,
382 		.Name = "TXD",
383 		.HasTexture = 1,
384 		.NumSrcRegs = 3,
385 		.HasDstReg = 1
386 	},
387 	{
388 		.Opcode = RC_OPCODE_TXL,
389 		.Name = "TXL",
390 		.HasTexture = 1,
391 		.NumSrcRegs = 1,
392 		.HasDstReg = 1
393 	},
394 	{
395 		.Opcode = RC_OPCODE_TXP,
396 		.Name = "TXP",
397 		.HasTexture = 1,
398 		.NumSrcRegs = 1,
399 		.HasDstReg = 1
400 	},
401 	{
402 		.Opcode = RC_OPCODE_IF,
403 		.Name = "IF",
404 		.IsFlowControl = 1,
405 		.NumSrcRegs = 1
406 	},
407 	{
408 		.Opcode = RC_OPCODE_ELSE,
409 		.Name = "ELSE",
410 		.IsFlowControl = 1,
411 		.NumSrcRegs = 0
412 	},
413 	{
414 		.Opcode = RC_OPCODE_ENDIF,
415 		.Name = "ENDIF",
416 		.IsFlowControl = 1,
417 		.NumSrcRegs = 0
418 	},
419 	{
420 		.Opcode = RC_OPCODE_BGNLOOP,
421 		.Name = "BGNLOOP",
422 		.IsFlowControl = 1,
423 		.NumSrcRegs = 0
424 	},
425 	{
426 		.Opcode = RC_OPCODE_BRK,
427 		.Name = "BRK",
428 		.IsFlowControl = 1,
429 		.NumSrcRegs = 0
430 	},
431 	{
432 		.Opcode = RC_OPCODE_ENDLOOP,
433 		.Name = "ENDLOOP",
434 		.IsFlowControl = 1,
435 		.NumSrcRegs = 0,
436 	},
437 	{
438 		.Opcode = RC_OPCODE_CONT,
439 		.Name = "CONT",
440 		.IsFlowControl = 1,
441 		.NumSrcRegs = 0
442 	},
443 	{
444 		.Opcode = RC_OPCODE_REPL_ALPHA,
445 		.Name = "REPL_ALPHA",
446 		.HasDstReg = 1
447 	},
448 	{
449 		.Opcode = RC_OPCODE_BEGIN_TEX,
450 		.Name = "BEGIN_TEX"
451 	},
452 	{
453 		.Opcode = RC_OPCODE_KILP,
454 		.Name = "KILP",
455 	},
456 	{
457 		.Opcode = RC_ME_PRED_SEQ,
458 		.Name = "ME_PRED_SEQ",
459 		.NumSrcRegs = 1,
460 		.HasDstReg = 1
461 	},
462 	{
463 		.Opcode = RC_ME_PRED_SGT,
464 		.Name = "ME_PRED_SGT",
465 		.NumSrcRegs = 1,
466 		.HasDstReg = 1
467 	},
468 	{
469 		.Opcode = RC_ME_PRED_SGE,
470 		.Name = "ME_PRED_SGE",
471 		.NumSrcRegs = 1,
472 		.HasDstReg = 1
473 	},
474 	{
475 		.Opcode = RC_ME_PRED_SNEQ,
476 		.Name = "ME_PRED_SNEQ",
477 		.NumSrcRegs = 1,
478 		.HasDstReg = 1
479 	},
480 	{
481 		.Opcode = RC_ME_PRED_SET_CLR,
482 		.Name = "ME_PRED_SET_CLEAR",
483 		.NumSrcRegs = 1,
484 		.HasDstReg = 1
485 	},
486 	{
487 		.Opcode = RC_ME_PRED_SET_INV,
488 		.Name = "ME_PRED_SET_INV",
489 		.NumSrcRegs = 1,
490 		.HasDstReg = 1
491 	},
492 	{
493 		.Opcode = RC_ME_PRED_SET_POP,
494 		.Name = "ME_PRED_SET_POP",
495 		.NumSrcRegs = 1,
496 		.HasDstReg = 1
497 	},
498 	{
499 		.Opcode = RC_ME_PRED_SET_RESTORE,
500 		.Name = "ME_PRED_SET_RESTORE",
501 		.NumSrcRegs = 1,
502 		.HasDstReg = 1
503 	},
504 	{
505 		.Opcode = RC_VE_PRED_SEQ_PUSH,
506 		.Name = "VE_PRED_SEQ_PUSH",
507 		.NumSrcRegs = 2,
508 		.HasDstReg = 1
509 	},
510 	{
511 		.Opcode = RC_VE_PRED_SGT_PUSH,
512 		.Name = "VE_PRED_SGT_PUSH",
513 		.NumSrcRegs = 2,
514 		.HasDstReg = 1
515 	},
516 	{
517 		.Opcode = RC_VE_PRED_SGE_PUSH,
518 		.Name = "VE_PRED_SGE_PUSH",
519 		.NumSrcRegs = 2,
520 		.HasDstReg = 1
521 	},
522 	{
523 		.Opcode = RC_VE_PRED_SNEQ_PUSH,
524 		.Name = "VE_PRED_SNEQ_PUSH",
525 		.NumSrcRegs = 2,
526 		.HasDstReg = 1
527 	}
528 };
529 
rc_compute_sources_for_writemask(const struct rc_instruction * inst,unsigned int writemask,unsigned int * srcmasks)530 void rc_compute_sources_for_writemask(
531 		const struct rc_instruction *inst,
532 		unsigned int writemask,
533 		unsigned int *srcmasks)
534 {
535 	const struct rc_opcode_info * opcode = rc_get_opcode_info(inst->U.I.Opcode);
536 	srcmasks[0] = 0;
537 	srcmasks[1] = 0;
538 	srcmasks[2] = 0;
539 
540 	if (opcode->Opcode == RC_OPCODE_KIL)
541 		srcmasks[0] |= RC_MASK_XYZW;
542 	else if (opcode->Opcode == RC_OPCODE_IF)
543 		srcmasks[0] |= RC_MASK_X;
544 
545 	if (!writemask)
546 		return;
547 
548 	if (opcode->IsComponentwise) {
549 		for(unsigned int src = 0; src < opcode->NumSrcRegs; ++src)
550 			srcmasks[src] |= writemask;
551 	} else if (opcode->IsStandardScalar) {
552 		for(unsigned int src = 0; src < opcode->NumSrcRegs; ++src)
553 			srcmasks[src] |= writemask;
554 	} else {
555 		switch(opcode->Opcode) {
556 		case RC_OPCODE_ARL:
557 		case RC_OPCODE_ARR:
558 			srcmasks[0] |= RC_MASK_X;
559 			break;
560 		case RC_OPCODE_DP2:
561 			srcmasks[0] |= RC_MASK_XY;
562 			srcmasks[1] |= RC_MASK_XY;
563 			break;
564 		case RC_OPCODE_DP3:
565 		case RC_OPCODE_XPD:
566 			srcmasks[0] |= RC_MASK_XYZ;
567 			srcmasks[1] |= RC_MASK_XYZ;
568 			break;
569 		case RC_OPCODE_DP4:
570 			srcmasks[0] |= RC_MASK_XYZW;
571 			srcmasks[1] |= RC_MASK_XYZW;
572 			break;
573 		case RC_OPCODE_DPH:
574 			srcmasks[0] |= RC_MASK_XYZ;
575 			srcmasks[1] |= RC_MASK_XYZW;
576 			break;
577 		case RC_OPCODE_TXB:
578 		case RC_OPCODE_TXP:
579 		case RC_OPCODE_TXL:
580 			srcmasks[0] |= RC_MASK_W;
581 			FALLTHROUGH;
582 		case RC_OPCODE_TEX:
583 			switch (inst->U.I.TexSrcTarget) {
584 				case RC_TEXTURE_1D:
585 					srcmasks[0] |= RC_MASK_X;
586 					break;
587 				case RC_TEXTURE_2D:
588 				case RC_TEXTURE_RECT:
589 				case RC_TEXTURE_1D_ARRAY:
590 					srcmasks[0] |= RC_MASK_XY;
591 					break;
592 				case RC_TEXTURE_3D:
593 				case RC_TEXTURE_CUBE:
594 				case RC_TEXTURE_2D_ARRAY:
595 					srcmasks[0] |= RC_MASK_XYZ;
596 					break;
597 			}
598 			break;
599 		case RC_OPCODE_TXD:
600 			switch (inst->U.I.TexSrcTarget) {
601 				case RC_TEXTURE_1D_ARRAY:
602 					srcmasks[0] |= RC_MASK_Y;
603 					FALLTHROUGH;
604 				case RC_TEXTURE_1D:
605 					srcmasks[0] |= RC_MASK_X;
606 					srcmasks[1] |= RC_MASK_X;
607 					srcmasks[2] |= RC_MASK_X;
608 					break;
609 				case RC_TEXTURE_2D_ARRAY:
610 					srcmasks[0] |= RC_MASK_Z;
611 					FALLTHROUGH;
612 				case RC_TEXTURE_2D:
613 				case RC_TEXTURE_RECT:
614 					srcmasks[0] |= RC_MASK_XY;
615 					srcmasks[1] |= RC_MASK_XY;
616 					srcmasks[2] |= RC_MASK_XY;
617 					break;
618 				case RC_TEXTURE_3D:
619 				case RC_TEXTURE_CUBE:
620 					srcmasks[0] |= RC_MASK_XYZ;
621 					srcmasks[1] |= RC_MASK_XYZ;
622 					srcmasks[2] |= RC_MASK_XYZ;
623 					break;
624 			}
625 			break;
626 		case RC_OPCODE_DST:
627 			srcmasks[0] |= RC_MASK_Y | RC_MASK_Z;
628 			srcmasks[1] |= RC_MASK_Y | RC_MASK_W;
629 			break;
630 		case RC_OPCODE_EXP:
631 		case RC_OPCODE_LOG:
632 			srcmasks[0] |= RC_MASK_XY;
633 			break;
634 		case RC_OPCODE_LIT:
635 			srcmasks[0] |= RC_MASK_X | RC_MASK_Y | RC_MASK_W;
636 			break;
637 		default:
638 			break;
639 		}
640 	}
641 }
642