Merge branch 'nouveau-import'
[mesa.git] / src / mesa / drivers / dri / nouveau / nv30_vertprog.c
1 #include "nouveau_context.h"
2 #include "nouveau_object.h"
3 #include "nouveau_fifo.h"
4 #include "nouveau_reg.h"
5
6 #include "nouveau_shader.h"
7 #include "nv30_shader.h"
8
9 extern nvsSwzComp NV20VP_TX_SWIZZLE[4];
10 extern void NV20VPTXSwizzle(int hwswz, nvsSwzComp *swz);
11
12 /*****************************************************************************
13 * Support routines
14 */
15 static void
16 NV30VPUploadToHW(GLcontext *ctx, nouveauShader *nvs)
17 {
18 nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
19 int i;
20
21 /* We can do better here and keep more than one VP on the hardware, and
22 * switch between them with PROGRAM_START_ID..
23 */
24 BEGIN_RING_SIZE(NvSub3D, NV30_TCL_PRIMITIVE_3D_VP_UPLOAD_FROM_ID, 1);
25 OUT_RING(0);
26 for (i=0; i<nvs->program_size; i+=4) {
27 BEGIN_RING_SIZE(NvSub3D, NV30_TCL_PRIMITIVE_3D_VP_UPLOAD_INST0, 4);
28 OUT_RING(nvs->program[i + 0]);
29 OUT_RING(nvs->program[i + 1]);
30 OUT_RING(nvs->program[i + 2]);
31 OUT_RING(nvs->program[i + 3]);
32 }
33 BEGIN_RING_SIZE(NvSub3D, NV30_TCL_PRIMITIVE_3D_VP_PROGRAM_START_ID, 1);
34 OUT_RING(0);
35 }
36
37 static void
38 NV30VPUpdateConst(GLcontext *ctx, nouveauShader *nvs, int id)
39 {
40 nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
41 GLfloat *val;
42
43 val = nvs->params[id].source_val ?
44 nvs->params[id].source_val : nvs->params[id].val;
45
46 BEGIN_RING_SIZE(NvSub3D, NV30_TCL_PRIMITIVE_3D_VP_UPLOAD_CONST_ID, 5);
47 OUT_RING (id);
48 OUT_RINGp(val, 4);
49 }
50
51 /*****************************************************************************
52 * Assembly routines
53 */
54
55 /*****************************************************************************
56 * Disassembly routines
57 */
58 static unsigned int
59 NV30VPGetOpcodeHW(nvsFunc * shader, int slot)
60 {
61 int op;
62
63 if (slot) {
64 op = (shader->inst[1] & NV30_VP_INST_SCA_OPCODEL_MASK)
65 >> NV30_VP_INST_SCA_OPCODEL_SHIFT;
66 op |= ((shader->inst[0] & NV30_VP_INST_SCA_OPCODEH_MASK)
67 >> NV30_VP_INST_SCA_OPCODEH_SHIFT) << 4;
68 }
69 else {
70 op = (shader->inst[1] & NV30_VP_INST_VEC_OPCODE_MASK)
71 >> NV30_VP_INST_VEC_OPCODE_SHIFT;
72 }
73
74 return op;
75 }
76
77 static nvsRegFile
78 NV30VPGetDestFile(nvsFunc * shader, int merged)
79 {
80 switch (shader->GetOpcode(shader, merged)) {
81 case NVS_OP_ARL:
82 case NVS_OP_ARR:
83 case NVS_OP_ARA:
84 return NVS_FILE_ADDRESS;
85 default:
86 /*FIXME: This probably isn't correct.. */
87 if ((shader->inst[3] & NV30_VP_INST_VDEST_WRITEMASK_MASK) != 0)
88 return NVS_FILE_RESULT;
89 if ((shader->inst[3] & NV30_VP_INST_SDEST_WRITEMASK_MASK) != 0)
90 return NVS_FILE_RESULT;
91 return NVS_FILE_TEMP;
92 }
93 }
94
95 static unsigned int
96 NV30VPGetDestID(nvsFunc * shader, int merged)
97 {
98 int id;
99
100 switch (shader->GetDestFile(shader, merged)) {
101 case NVS_FILE_RESULT:
102 id = ((shader->inst[3] & NV30_VP_INST_DEST_ID_MASK)
103 >> NV30_VP_INST_DEST_ID_SHIFT);
104 switch (id) {
105 case NV30_VP_INST_DEST_POS : return NVS_FR_POSITION;
106 case NV30_VP_INST_DEST_COL0 : return NVS_FR_COL0;
107 case NV30_VP_INST_DEST_COL1 : return NVS_FR_COL1;
108 case NV30_VP_INST_DEST_TC(0): return NVS_FR_TEXCOORD0;
109 case NV30_VP_INST_DEST_TC(1): return NVS_FR_TEXCOORD1;
110 case NV30_VP_INST_DEST_TC(2): return NVS_FR_TEXCOORD2;
111 case NV30_VP_INST_DEST_TC(3): return NVS_FR_TEXCOORD3;
112 case NV30_VP_INST_DEST_TC(4): return NVS_FR_TEXCOORD4;
113 case NV30_VP_INST_DEST_TC(5): return NVS_FR_TEXCOORD5;
114 case NV30_VP_INST_DEST_TC(6): return NVS_FR_TEXCOORD6;
115 case NV30_VP_INST_DEST_TC(7): return NVS_FR_TEXCOORD7;
116 default:
117 return -1;
118 }
119 case NVS_FILE_ADDRESS:
120 case NVS_FILE_TEMP:
121 return (shader->inst[0] & NV30_VP_INST_DEST_TEMP_ID_MASK)
122 >> NV30_VP_INST_DEST_TEMP_ID_SHIFT;
123 default:
124 return -1;
125 }
126 }
127
128 static unsigned int
129 NV30VPGetDestMask(nvsFunc * shader, int merged)
130 {
131 int hwmask, mask = 0;
132
133 if (shader->GetDestFile(shader, merged) == NVS_FILE_RESULT)
134 if (shader->GetOpcodeSlot(shader, merged))
135 hwmask = (shader->inst[3] & NV30_VP_INST_SDEST_WRITEMASK_MASK)
136 >> NV30_VP_INST_SDEST_WRITEMASK_SHIFT;
137 else
138 hwmask = (shader->inst[3] & NV30_VP_INST_VDEST_WRITEMASK_MASK)
139 >> NV30_VP_INST_VDEST_WRITEMASK_SHIFT;
140 else if (shader->GetOpcodeSlot(shader, merged))
141 hwmask = (shader->inst[3] & NV30_VP_INST_STEMP_WRITEMASK_MASK)
142 >> NV30_VP_INST_STEMP_WRITEMASK_SHIFT;
143 else
144 hwmask = (shader->inst[3] & NV30_VP_INST_VTEMP_WRITEMASK_MASK)
145 >> NV30_VP_INST_VTEMP_WRITEMASK_SHIFT;
146
147 if (hwmask & (1 << 3)) mask |= SMASK_X;
148 if (hwmask & (1 << 2)) mask |= SMASK_Y;
149 if (hwmask & (1 << 1)) mask |= SMASK_Z;
150 if (hwmask & (1 << 0)) mask |= SMASK_W;
151
152 return mask;
153 }
154
155 static int
156 NV30VPGetSourceID(nvsFunc * shader, int merged, int pos)
157 {
158 unsigned int src;
159
160 switch (shader->GetSourceFile(shader, merged, pos)) {
161 case NVS_FILE_TEMP:
162 src = shader->GetSourceHW(shader, merged, pos);
163 return ((src & NV30_VP_SRC_REG_TEMP_ID_MASK) >>
164 NV30_VP_SRC_REG_TEMP_ID_SHIFT);
165 case NVS_FILE_CONST:
166 return ((shader->inst[1] & NV30_VP_INST_CONST_SRC_MASK)
167 >> NV30_VP_INST_CONST_SRC_SHIFT);
168 case NVS_FILE_ATTRIB:
169 src = ((shader->inst[1] & NV30_VP_INST_INPUT_SRC_MASK)
170 >> NV30_VP_INST_INPUT_SRC_SHIFT);
171 switch (src) {
172 case NV30_VP_INST_IN_POS : return NVS_FR_POSITION;
173 case NV30_VP_INST_IN_COL0 : return NVS_FR_COL0;
174 case NV30_VP_INST_IN_COL1 : return NVS_FR_COL1;
175 case NV30_VP_INST_IN_TC(0): return NVS_FR_TEXCOORD0;
176 case NV30_VP_INST_IN_TC(1): return NVS_FR_TEXCOORD1;
177 case NV30_VP_INST_IN_TC(2): return NVS_FR_TEXCOORD2;
178 case NV30_VP_INST_IN_TC(3): return NVS_FR_TEXCOORD3;
179 case NV30_VP_INST_IN_TC(4): return NVS_FR_TEXCOORD4;
180 case NV30_VP_INST_IN_TC(5): return NVS_FR_TEXCOORD5;
181 case NV30_VP_INST_IN_TC(6): return NVS_FR_TEXCOORD6;
182 case NV30_VP_INST_IN_TC(7): return NVS_FR_TEXCOORD7;
183 default:
184 return NVS_FR_UNKNOWN;
185 }
186 default:
187 return -1;
188 }
189 }
190
191 static int
192 NV30VPGetSourceAbs(nvsFunc * shader, int merged, int pos)
193 {
194 struct _op_xlat *opr;
195 static unsigned int abspos[3] = {
196 NV30_VP_INST_SRC0_ABS,
197 NV30_VP_INST_SRC1_ABS,
198 NV30_VP_INST_SRC2_ABS,
199 };
200
201 opr = shader->GetOPTXRec(shader, merged);
202 if (!opr || opr->srcpos[pos] == -1 || opr->srcpos[pos] > 2)
203 return 0;
204
205 return ((shader->inst[0] & abspos[opr->srcpos[pos]]) ? 1 : 0);
206 }
207
208 static int
209 NV30VPGetRelAddressRegID(nvsFunc * shader)
210 {
211 return ((shader->inst[0] & NV30_VP_INST_ADDR_REG_SELECT_1) ? 1 : 0);
212 }
213
214 static nvsSwzComp
215 NV30VPGetRelAddressSwizzle(nvsFunc * shader)
216 {
217 nvsSwzComp swz;
218
219 swz = NV20VP_TX_SWIZZLE[(shader->inst[0] & NV30_VP_INST_ADDR_SWZ_MASK)
220 >> NV30_VP_INST_ADDR_SWZ_SHIFT];
221 return swz;
222 }
223
224 static int
225 NV30VPSupportsConditional(nvsFunc * shader)
226 {
227 /*FIXME: Is this true of all ops? */
228 return 1;
229 }
230
231 static int
232 NV30VPGetConditionUpdate(nvsFunc * shader)
233 {
234 return ((shader->inst[0] & NV30_VP_INST_COND_UPDATE_ENABLE) ? 1 : 0);
235 }
236
237 static int
238 NV30VPGetConditionTest(nvsFunc * shader)
239 {
240 int op;
241
242 /* The condition test is unconditionally enabled on some
243 * instructions. ie: the condition test bit does *NOT* have
244 * to be set.
245 *
246 * FIXME: check other relevant ops for this situation.
247 */
248 op = shader->GetOpcodeHW(shader, 1);
249 switch (op) {
250 case NV30_VP_INST_OP_BRA:
251 return 1;
252 default:
253 return ((shader->inst[0] & NV30_VP_INST_COND_TEST_ENABLE) ? 1 : 0);
254 }
255 }
256
257 static nvsCond
258 NV30VPGetCondition(nvsFunc * shader)
259 {
260 int cond;
261
262 cond = ((shader->inst[0] & NV30_VP_INST_COND_MASK)
263 >> NV30_VP_INST_COND_SHIFT);
264
265 switch (cond) {
266 case NV30_VP_INST_COND_FL: return NVS_COND_FL;
267 case NV30_VP_INST_COND_LT: return NVS_COND_LT;
268 case NV30_VP_INST_COND_EQ: return NVS_COND_EQ;
269 case NV30_VP_INST_COND_LE: return NVS_COND_LE;
270 case NV30_VP_INST_COND_GT: return NVS_COND_GT;
271 case NV30_VP_INST_COND_NE: return NVS_COND_NE;
272 case NV30_VP_INST_COND_GE: return NVS_COND_GE;
273 case NV30_VP_INST_COND_TR: return NVS_COND_TR;
274 default:
275 return NVS_COND_UNKNOWN;
276 }
277 }
278
279 static void
280 NV30VPGetCondRegSwizzle(nvsFunc * shader, nvsSwzComp *swz)
281 {
282 int swzbits;
283
284 swzbits = (shader->inst[0] & NV30_VP_INST_COND_SWZ_ALL_MASK)
285 >> NV30_VP_INST_COND_SWZ_ALL_SHIFT;
286 NV20VPTXSwizzle(swzbits, swz);
287 }
288
289 static int
290 NV30VPGetCondRegID(nvsFunc * shader)
291 {
292 return 0;
293 }
294
295
296 static int
297 NV30VPGetBranch(nvsFunc * shader)
298 {
299 return ((shader->inst[2] & NV30_VP_INST_IADDR_MASK)
300 >> NV30_VP_INST_IADDR_SHIFT);
301 }
302
303 void
304 NV30VPInitShaderFuncs(nvsFunc * shader)
305 {
306 /* Inherit NV20 code, a lot of it is the same */
307 NV20VPInitShaderFuncs(shader);
308
309 /* Increase max valid opcode ID, and add new instructions */
310 NVVP_TX_VOP_COUNT = NVVP_TX_NVS_OP_COUNT = 32;
311
312 MOD_OPCODE(NVVP_TX_VOP, NV30_VP_INST_OP_FRC, NVS_OP_FRC, 0, -1, -1);
313 MOD_OPCODE(NVVP_TX_VOP, NV30_VP_INST_OP_FLR, NVS_OP_FLR, 0, -1, -1);
314 MOD_OPCODE(NVVP_TX_VOP, NV30_VP_INST_OP_SEQ, NVS_OP_SEQ, 0, 1, -1);
315 MOD_OPCODE(NVVP_TX_VOP, NV30_VP_INST_OP_SFL, NVS_OP_SFL, 0, 1, -1);
316 MOD_OPCODE(NVVP_TX_VOP, NV30_VP_INST_OP_SGT, NVS_OP_SGT, 0, 1, -1);
317 MOD_OPCODE(NVVP_TX_VOP, NV30_VP_INST_OP_SLE, NVS_OP_SLE, 0, 1, -1);
318 MOD_OPCODE(NVVP_TX_VOP, NV30_VP_INST_OP_SNE, NVS_OP_SNE, 0, 1, -1);
319 MOD_OPCODE(NVVP_TX_VOP, NV30_VP_INST_OP_STR, NVS_OP_STR, 0, 1, -1);
320 MOD_OPCODE(NVVP_TX_VOP, NV30_VP_INST_OP_SSG, NVS_OP_SSG, 0, -1, -1);
321 MOD_OPCODE(NVVP_TX_VOP, NV30_VP_INST_OP_ARR, NVS_OP_ARR, 0, -1, -1);
322 MOD_OPCODE(NVVP_TX_VOP, NV30_VP_INST_OP_ARA, NVS_OP_ARA, 3, -1, -1);
323
324 MOD_OPCODE(NVVP_TX_SOP, NV30_VP_INST_OP_BRA, NVS_OP_BRA, -1, -1, -1);
325 MOD_OPCODE(NVVP_TX_SOP, NV30_VP_INST_OP_CAL, NVS_OP_CAL, -1, -1, -1);
326 MOD_OPCODE(NVVP_TX_SOP, NV30_VP_INST_OP_RET, NVS_OP_RET, -1, -1, -1);
327 MOD_OPCODE(NVVP_TX_SOP, NV30_VP_INST_OP_LG2, NVS_OP_LG2, 2, -1, -1);
328 MOD_OPCODE(NVVP_TX_SOP, NV30_VP_INST_OP_EX2, NVS_OP_EX2, 2, -1, -1);
329 MOD_OPCODE(NVVP_TX_SOP, NV30_VP_INST_OP_SIN, NVS_OP_SIN, 2, -1, -1);
330 MOD_OPCODE(NVVP_TX_SOP, NV30_VP_INST_OP_COS, NVS_OP_COS, 2, -1, -1);
331
332 shader->UploadToHW = NV30VPUploadToHW;
333 shader->UpdateConst = NV30VPUpdateConst;
334
335 shader->GetOpcodeHW = NV30VPGetOpcodeHW;
336
337 shader->GetDestFile = NV30VPGetDestFile;
338 shader->GetDestID = NV30VPGetDestID;
339 shader->GetDestMask = NV30VPGetDestMask;
340
341 shader->GetSourceID = NV30VPGetSourceID;
342 shader->GetSourceAbs = NV30VPGetSourceAbs;
343
344 shader->GetRelAddressRegID = NV30VPGetRelAddressRegID;
345 shader->GetRelAddressSwizzle = NV30VPGetRelAddressSwizzle;
346
347 shader->SupportsConditional = NV30VPSupportsConditional;
348 shader->GetConditionUpdate = NV30VPGetConditionUpdate;
349 shader->GetConditionTest = NV30VPGetConditionTest;
350 shader->GetCondition = NV30VPGetCondition;
351 shader->GetCondRegSwizzle = NV30VPGetCondRegSwizzle;
352 shader->GetCondRegID = NV30VPGetCondRegID;
353
354 shader->GetBranch = NV30VPGetBranch;
355 }
356