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#ifndef RADEON_OPCODES_H
29#define RADEON_OPCODES_H
30
31#include <assert.h>
32
33/**
34 * Opcodes understood by the Radeon compiler.
35 */
36typedef enum {
37	RC_OPCODE_NOP = 0,
38	RC_OPCODE_ILLEGAL_OPCODE,
39
40	/** vec4 instruction: dst.c = src0.c + src1.c; */
41	RC_OPCODE_ADD,
42
43	/** special instruction: load address register
44	 * dst.x = floor(src.x), where dst must be an address register */
45	RC_OPCODE_ARL,
46
47	/** special instruction: load address register with round
48	 * dst.x = round(src.x), where dst must be an address register */
49	RC_OPCODE_ARR,
50
51	/** vec4 instruction: dst.c = ceil(src0.c) */
52	RC_OPCODE_CEIL,
53
54	/** vec4 instruction: dst.c = src0.c < 0.0 ? src1.c : src2.c */
55	RC_OPCODE_CMP,
56
57	/** vec4 instruction: dst.c = src2.c > 0.5 ? src0.c : src1.c */
58	RC_OPCODE_CND,
59
60	/** scalar instruction: dst = cos(src0.x) */
61	RC_OPCODE_COS,
62
63	/** special instruction: take vec4 partial derivative in X direction
64	 * dst.c = d src0.c / dx */
65	RC_OPCODE_DDX,
66
67	/** special instruction: take vec4 partial derivative in Y direction
68	 * dst.c = d src0.c / dy */
69	RC_OPCODE_DDY,
70
71	/** scalar instruction: dst = src0.x*src1.x + src0.y*src1.y */
72	RC_OPCODE_DP2,
73
74	/** scalar instruction: dst = src0.x*src1.x + src0.y*src1.y + src0.z*src1.z */
75	RC_OPCODE_DP3,
76
77	/** scalar instruction: dst = src0.x*src1.x + src0.y*src1.y + src0.z*src1.z + src0.w*src1.w */
78	RC_OPCODE_DP4,
79
80	/** special instruction, see ARB_fragment_program */
81	RC_OPCODE_DST,
82
83	/** scalar instruction: dst = 2**src0.x */
84	RC_OPCODE_EX2,
85
86	/** special instruction, see ARB_vertex_program */
87	RC_OPCODE_EXP,
88
89	/** vec4 instruction: dst.c = floor(src0.c) */
90	RC_OPCODE_FLR,
91
92	/** vec4 instruction: dst.c = src0.c - floor(src0.c) */
93	RC_OPCODE_FRC,
94
95	/** special instruction: stop execution if any component of src0 is negative */
96	RC_OPCODE_KIL,
97
98	/** scalar instruction: dst = log_2(src0.x) */
99	RC_OPCODE_LG2,
100
101	/** special instruction, see ARB_vertex_program */
102	RC_OPCODE_LIT,
103
104	/** special instruction, see ARB_vertex_program */
105	RC_OPCODE_LOG,
106
107	/** vec4 instruction: dst.c = src0.c*src1.c + (1 - src0.c)*src2.c */
108	RC_OPCODE_LRP,
109
110	/** vec4 instruction: dst.c = src0.c*src1.c + src2.c */
111	RC_OPCODE_MAD,
112
113	/** vec4 instruction: dst.c = max(src0.c, src1.c) */
114	RC_OPCODE_MAX,
115
116	/** vec4 instruction: dst.c = min(src0.c, src1.c) */
117	RC_OPCODE_MIN,
118
119	/** vec4 instruction: dst.c = src0.c */
120	RC_OPCODE_MOV,
121
122	/** vec4 instruction: dst.c = src0.c*src1.c */
123	RC_OPCODE_MUL,
124
125	/** scalar instruction: dst = src0.x ** src1.x */
126	RC_OPCODE_POW,
127
128	/** scalar instruction: dst = 1 / src0.x */
129	RC_OPCODE_RCP,
130
131	/** vec4 instruction: dst.c = floor(src0.c + 0.5) */
132	RC_OPCODE_ROUND,
133
134	/** scalar instruction: dst = 1 / sqrt(src0.x) */
135	RC_OPCODE_RSQ,
136
137	/** vec4 instruction: dst.c = (src0.c == src1.c) ? 1.0 : 0.0 */
138	RC_OPCODE_SEQ,
139
140	/** vec4 instruction: dst.c = (src0.c >= src1.c) ? 1.0 : 0.0 */
141	RC_OPCODE_SGE,
142
143	/** vec4 instruction: dst.c = (src0.c > src1.c) ? 1.0 : 0.0 */
144	RC_OPCODE_SGT,
145
146	/** scalar instruction: dst = sin(src0.x) */
147	RC_OPCODE_SIN,
148
149	/** vec4 instruction: dst.c = (src0.c <= src1.c) ? 1.0 : 0.0 */
150	RC_OPCODE_SLE,
151
152	/** vec4 instruction: dst.c = (src0.c < src1.c) ? 1.0 : 0.0 */
153	RC_OPCODE_SLT,
154
155	/** vec4 instruction: dst.c = (src0.c != src1.c) ? 1.0 : 0.0 */
156	RC_OPCODE_SNE,
157
158	/** vec4 instruction: dst.c = (src0.c < 0 ?) -1 : ((src0.c > 0) : 1 : 0) */
159	RC_OPCODE_SSG,
160
161	/** vec4 instruction: dst.c = src0.c - src1.c */
162	RC_OPCODE_SUB,
163
164	/** vec4 instruction: dst.c = (abs(src0.c) - fract(abs(src0.c))) * sgn(src0.c) */
165	RC_OPCODE_TRUNC,
166
167	RC_OPCODE_TEX,
168	RC_OPCODE_TXB,
169	RC_OPCODE_TXD,
170	RC_OPCODE_TXL,
171	RC_OPCODE_TXP,
172
173	/** branch instruction:
174	 * If src0.x != 0.0, continue with the next instruction;
175	 * otherwise, jump to matching RC_OPCODE_ELSE or RC_OPCODE_ENDIF.
176	 */
177	RC_OPCODE_IF,
178
179	/** branch instruction: jump to matching RC_OPCODE_ENDIF */
180	RC_OPCODE_ELSE,
181
182	/** branch instruction: has no effect */
183	RC_OPCODE_ENDIF,
184
185	RC_OPCODE_BGNLOOP,
186
187	RC_OPCODE_BRK,
188
189	RC_OPCODE_ENDLOOP,
190
191	RC_OPCODE_CONT,
192
193	/** special instruction, used in R300-R500 fragment program pair instructions
194	 * indicates that the result of the alpha operation shall be replicated
195	 * across all other channels */
196	RC_OPCODE_REPL_ALPHA,
197
198	/** special instruction, used in R300-R500 fragment programs
199	 * to indicate the start of a block of texture instructions that
200	 * can run simultaneously. */
201	RC_OPCODE_BEGIN_TEX,
202
203	/** Stop execution of the shader (GLSL discard) */
204	RC_OPCODE_KILP,
205
206	/* Vertex shader CF Instructions */
207	RC_ME_PRED_SEQ,
208	RC_ME_PRED_SGT,
209	RC_ME_PRED_SGE,
210	RC_ME_PRED_SNEQ,
211	RC_ME_PRED_SET_CLR,
212	RC_ME_PRED_SET_INV,
213	RC_ME_PRED_SET_POP,
214	RC_ME_PRED_SET_RESTORE,
215
216	RC_VE_PRED_SEQ_PUSH,
217	RC_VE_PRED_SGT_PUSH,
218	RC_VE_PRED_SGE_PUSH,
219	RC_VE_PRED_SNEQ_PUSH,
220
221	MAX_RC_OPCODE
222} rc_opcode;
223
224
225struct rc_opcode_info {
226	rc_opcode Opcode;
227	const char * Name;
228
229	/** true if the instruction reads from a texture.
230	 *
231	 * \note This is false for the KIL instruction, even though KIL is
232	 * a texture instruction from a hardware point of view. */
233	unsigned int HasTexture:1;
234
235	unsigned int NumSrcRegs:2;
236	unsigned int HasDstReg:1;
237
238	/** true if this instruction affects control flow */
239	unsigned int IsFlowControl:1;
240
241	/** true if this is a vector instruction that operates on components in parallel
242	 * without any cross-component interaction */
243	unsigned int IsComponentwise:1;
244
245	/** true if this instruction sources only its operands X components
246	 * to compute one result which is smeared across all output channels */
247	unsigned int IsStandardScalar:1;
248};
249
250extern const struct rc_opcode_info rc_opcodes[MAX_RC_OPCODE];
251
252static inline const struct rc_opcode_info * rc_get_opcode_info(rc_opcode opcode)
253{
254	assert((unsigned int)opcode < MAX_RC_OPCODE);
255	assert(rc_opcodes[opcode].Opcode == opcode);
256
257	return &rc_opcodes[opcode];
258}
259
260struct rc_instruction;
261
262void rc_compute_sources_for_writemask(
263		const struct rc_instruction *inst,
264		unsigned int writemask,
265		unsigned int *srcmasks);
266
267#endif /* RADEON_OPCODES_H */
268