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
35const 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
530void 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