1 #include "nouveau_context.h"
2 #include "nouveau_object.h"
3 #include "nouveau_fifo.h"
4 #include "nouveau_reg.h"
6 #include "nouveau_shader.h"
7 #include "nv20_shader.h"
9 unsigned int NVVP_TX_VOP_COUNT
= 16;
10 unsigned int NVVP_TX_NVS_OP_COUNT
= 16;
11 struct _op_xlat NVVP_TX_VOP
[32];
12 struct _op_xlat NVVP_TX_SOP
[32];
14 nvsSwzComp NV20VP_TX_SWIZZLE
[4] = { NVS_SWZ_X
, NVS_SWZ_Y
, NVS_SWZ_Z
, NVS_SWZ_W
};
16 /*****************************************************************************
20 NV20VPUploadToHW(GLcontext
*ctx
, nouveauShader
*nvs
)
22 nouveauContextPtr nmesa
= NOUVEAU_CONTEXT(ctx
);
25 /* XXX: missing a way to say what insn we're uploading from, and possible
26 * the program start position (if NV20 has one) */
27 for (i
=0; i
<nvs
->program_size
; i
+=4) {
28 BEGIN_RING_SIZE(NvSub3D
, NV20_TCL_PRIMITIVE_3D_VP_UPLOAD_INST0
, 4);
29 OUT_RING(nvs
->program
[i
+ 0]);
30 OUT_RING(nvs
->program
[i
+ 1]);
31 OUT_RING(nvs
->program
[i
+ 2]);
32 OUT_RING(nvs
->program
[i
+ 3]);
37 NV20VPUpdateConst(GLcontext
*ctx
, nouveauShader
*nvs
, int id
)
39 nouveauContextPtr nmesa
= NOUVEAU_CONTEXT(ctx
);
41 /* Worth checking if the value *actually* changed? Mesa doesn't tell us this
44 BEGIN_RING_SIZE(NvSub3D
, NV30_TCL_PRIMITIVE_3D_VP_UPLOAD_CONST_ID
, 1);
46 BEGIN_RING_SIZE(NvSub3D
, NV20_TCL_PRIMITIVE_3D_VP_UPLOAD_CONST_X
, 4);
47 OUT_RINGf(nvs
->params
[id
].source_val
[0]);
48 OUT_RINGf(nvs
->params
[id
].source_val
[1]);
49 OUT_RINGf(nvs
->params
[id
].source_val
[2]);
50 OUT_RINGf(nvs
->params
[id
].source_val
[3]);
53 /*****************************************************************************
57 /*****************************************************************************
58 * Disassembly routines
61 NV20VPTXSwizzle(int hwswz
, nvsSwzComp
*swz
)
63 swz
[NVS_SWZ_X
] = NV20VP_TX_SWIZZLE
[(hwswz
& 0xC0) >> 6];
64 swz
[NVS_SWZ_Y
] = NV20VP_TX_SWIZZLE
[(hwswz
& 0x30) >> 4];
65 swz
[NVS_SWZ_Z
] = NV20VP_TX_SWIZZLE
[(hwswz
& 0x0C) >> 2];
66 swz
[NVS_SWZ_W
] = NV20VP_TX_SWIZZLE
[(hwswz
& 0x03) >> 0];
70 NV20VPHasMergedInst(nvsFunc
* shader
)
72 if (shader
->GetOpcodeHW(shader
, 0) != NV20_VP_INST_OPCODE_NOP
&&
73 shader
->GetOpcodeHW(shader
, 1) != NV20_VP_INST_OPCODE_NOP
)
75 ("\n\n*****both opcode fields have values - PLEASE REPORT*****\n");
80 NV20VPIsLastInst(nvsFunc
* shader
)
82 return ((shader
->inst
[3] & (1 << 0)) ? 1 : 0);
86 NV20VPGetOffsetNext(nvsFunc
* shader
)
91 static struct _op_xlat
*
92 NV20VPGetOPTXRec(nvsFunc
* shader
, int merged
)
97 if (shader
->GetOpcodeSlot(shader
, merged
)) {
99 op
= shader
->GetOpcodeHW(shader
, 1);
100 if (op
>= NVVP_TX_NVS_OP_COUNT
)
105 op
= shader
->GetOpcodeHW(shader
, 0);
106 if (op
>= NVVP_TX_VOP_COUNT
)
110 if (opr
[op
].SOP
== NVS_OP_UNKNOWN
)
115 static struct _op_xlat
*
116 NV20VPGetOPTXFromSOP(nvsOpcode sop
, int *id
)
120 for (i
=0;i
<NVVP_TX_VOP_COUNT
;i
++) {
121 if (NVVP_TX_VOP
[i
].SOP
== sop
) {
123 return &NVVP_TX_VOP
[i
];
127 for (i
=0;i
<NVVP_TX_NVS_OP_COUNT
;i
++) {
128 if (NVVP_TX_SOP
[i
].SOP
== sop
) {
130 return &NVVP_TX_SOP
[i
];
138 NV20VPGetOpcodeSlot(nvsFunc
* shader
, int merged
)
140 if (shader
->HasMergedInst(shader
))
142 if (shader
->GetOpcodeHW(shader
, 0) == NV20_VP_INST_OPCODE_NOP
)
148 NV20VPGetOpcode(nvsFunc
* shader
, int merged
)
150 struct _op_xlat
*opr
;
152 opr
= shader
->GetOPTXRec(shader
, merged
);
154 return NVS_OP_UNKNOWN
;
160 NV20VPGetOpcodeHW(nvsFunc
* shader
, int slot
)
163 return (shader
->inst
[1] & NV20_VP_INST_SCA_OPCODE_MASK
)
164 >> NV20_VP_INST_SCA_OPCODE_SHIFT
;
165 return (shader
->inst
[1] & NV20_VP_INST_VEC_OPCODE_MASK
)
166 >> NV20_VP_INST_VEC_OPCODE_SHIFT
;
170 NV20VPGetDestFile(nvsFunc
* shader
, int merged
)
172 switch (shader
->GetOpcode(shader
, merged
)) {
174 return NVS_FILE_ADDRESS
;
176 /*FIXME: This probably isn't correct.. */
177 if ((shader
->inst
[3] & NV20_VP_INST_DEST_WRITEMASK_MASK
) == 0)
178 return NVS_FILE_TEMP
;
179 return NVS_FILE_RESULT
;
184 NV20VPGetDestID(nvsFunc
* shader
, int merged
)
188 switch (shader
->GetDestFile(shader
, merged
)) {
189 case NVS_FILE_RESULT
:
190 id
= ((shader
->inst
[3] & NV20_VP_INST_DEST_MASK
)
191 >> NV20_VP_INST_DEST_SHIFT
);
193 case NV20_VP_INST_DEST_POS
: return NVS_FR_POSITION
;
194 case NV20_VP_INST_DEST_COL0
: return NVS_FR_COL0
;
195 case NV20_VP_INST_DEST_COL1
: return NVS_FR_COL1
;
196 case NV20_VP_INST_DEST_TC(0): return NVS_FR_TEXCOORD0
;
197 case NV20_VP_INST_DEST_TC(1): return NVS_FR_TEXCOORD1
;
198 case NV20_VP_INST_DEST_TC(2): return NVS_FR_TEXCOORD2
;
199 case NV20_VP_INST_DEST_TC(3): return NVS_FR_TEXCOORD3
;
203 case NVS_FILE_ADDRESS
:
206 id
= ((shader
->inst
[3] & NV20_VP_INST_DEST_TEMP_ID_MASK
)
207 >> NV20_VP_INST_DEST_TEMP_ID_SHIFT
);
215 NV20VPGetDestMask(nvsFunc
* shader
, int merged
)
217 int hwmask
, mask
= 0;
219 /* Special handling for ARL - hardware only supports a
220 * 1-component address reg
222 if (shader
->GetOpcode(shader
, merged
) == NVS_OP_ARL
)
225 if (shader
->GetDestFile(shader
, merged
) == NVS_FILE_RESULT
)
226 hwmask
= (shader
->inst
[3] & NV20_VP_INST_DEST_WRITEMASK_MASK
)
227 >> NV20_VP_INST_DEST_WRITEMASK_SHIFT
;
228 else if (shader
->GetOpcodeSlot(shader
, merged
))
229 hwmask
= (shader
->inst
[3] & NV20_VP_INST_STEMP_WRITEMASK_MASK
)
230 >> NV20_VP_INST_STEMP_WRITEMASK_SHIFT
;
232 hwmask
= (shader
->inst
[3] & NV20_VP_INST_VTEMP_WRITEMASK_MASK
)
233 >> NV20_VP_INST_VTEMP_WRITEMASK_SHIFT
;
235 if (hwmask
& (1 << 3)) mask
|= SMASK_X
;
236 if (hwmask
& (1 << 2)) mask
|= SMASK_Y
;
237 if (hwmask
& (1 << 1)) mask
|= SMASK_Z
;
238 if (hwmask
& (1 << 0)) mask
|= SMASK_W
;
244 NV20VPGetSourceHW(nvsFunc
* shader
, int merged
, int pos
)
246 struct _op_xlat
*opr
;
249 opr
= shader
->GetOPTXRec(shader
, merged
);
253 switch (opr
->srcpos
[pos
]) {
255 src
= ((shader
->inst
[1] & NV20_VP_INST_SRC0H_MASK
)
256 >> NV20_VP_INST_SRC0H_SHIFT
)
257 << NV20_VP_SRC0_HIGH_SHIFT
;
258 src
|= ((shader
->inst
[2] & NV20_VP_INST_SRC0L_MASK
)
259 >> NV20_VP_INST_SRC0L_SHIFT
);
262 src
= ((shader
->inst
[2] & NV20_VP_INST_SRC1_MASK
)
263 >> NV20_VP_INST_SRC1_SHIFT
);
266 src
= ((shader
->inst
[2] & NV20_VP_INST_SRC2H_MASK
)
267 >> NV20_VP_INST_SRC2H_SHIFT
)
268 << NV20_VP_SRC2_HIGH_SHIFT
;
269 src
|= ((shader
->inst
[3] & NV20_VP_INST_SRC2L_MASK
)
270 >> NV20_VP_INST_SRC2L_SHIFT
);
280 NV20VPGetSourceFile(nvsFunc
* shader
, int merged
, int pos
)
283 struct _op_xlat
*opr
;
286 opr
= shader
->GetOPTXRec(shader
, merged
);
287 if (!opr
|| opr
->srcpos
[pos
] == -1)
290 switch (opr
->srcpos
[pos
]) {
292 return NVS_FILE_ADDRESS
;
294 src
= NV20VPGetSourceHW(shader
, merged
, pos
);
295 file
= (src
& NV20_VP_SRC_REG_TYPE_MASK
) >> NV20_VP_SRC_REG_TYPE_SHIFT
;
298 case NV20_VP_SRC_REG_TYPE_TEMP
: return NVS_FILE_TEMP
;
299 case NV20_VP_SRC_REG_TYPE_INPUT
: return NVS_FILE_ATTRIB
;
300 case NV20_VP_SRC_REG_TYPE_CONST
: return NVS_FILE_CONST
;
302 return NVS_FILE_UNKNOWN
;
308 NV20VPGetSourceID(nvsFunc
* shader
, int merged
, int pos
)
312 switch (shader
->GetSourceFile(shader
, merged
, pos
)) {
314 src
= shader
->GetSourceHW(shader
, merged
, pos
);
315 return ((src
& NV20_VP_SRC_REG_TEMP_ID_MASK
) >>
316 NV20_VP_SRC_REG_TEMP_ID_SHIFT
);
318 return ((shader
->inst
[1] & NV20_VP_INST_CONST_SRC_MASK
)
319 >> NV20_VP_INST_CONST_SRC_SHIFT
);
320 case NVS_FILE_ATTRIB
:
321 src
= ((shader
->inst
[1] & NV20_VP_INST_INPUT_SRC_MASK
)
322 >> NV20_VP_INST_INPUT_SRC_SHIFT
);
324 case NV20_VP_INST_INPUT_SRC_POS
: return NVS_FR_POSITION
;
325 case NV20_VP_INST_INPUT_SRC_COL0
: return NVS_FR_COL0
;
326 case NV20_VP_INST_INPUT_SRC_COL1
: return NVS_FR_COL1
;
327 case NV20_VP_INST_INPUT_SRC_TC(0): return NVS_FR_TEXCOORD0
;
328 case NV20_VP_INST_INPUT_SRC_TC(1): return NVS_FR_TEXCOORD1
;
329 case NV20_VP_INST_INPUT_SRC_TC(2): return NVS_FR_TEXCOORD2
;
330 case NV20_VP_INST_INPUT_SRC_TC(3): return NVS_FR_TEXCOORD3
;
332 return NVS_FR_UNKNOWN
;
340 NV20VPGetSourceNegate(nvsFunc
* shader
, int merged
, int pos
)
344 src
= shader
->GetSourceHW(shader
, merged
, pos
);
346 return ((src
& NV20_VP_SRC_REG_NEGATE
) ? 1 : 0);
350 NV20VPGetSourceAbs(nvsFunc
* shader
, int merged
, int pos
)
352 /* NV20 can't do ABS on sources? Appears to be emulated with
359 NV20VPGetSourceSwizzle(nvsFunc
* shader
, int merged
, int pos
, nvsSwzComp
*swz
)
364 src
= shader
->GetSourceHW(shader
, merged
, pos
);
366 (src
& NV20_VP_SRC_REG_SWZ_ALL_MASK
) >> NV20_VP_SRC_REG_SWZ_ALL_SHIFT
;
367 return NV20VPTXSwizzle(swzbits
, swz
);
371 NV20VPGetSourceIndexed(nvsFunc
* shader
, int merged
, int pos
)
373 /* I don't think NV20 can index into attribs, at least no GL
374 * extension is exposed that will allow it.
376 if (shader
->GetSourceFile(shader
, merged
, pos
) != NVS_FILE_CONST
)
378 if (shader
->inst
[3] & NV20_VP_INST_INDEX_CONST
)
384 NV20VPGetAddressRegID(nvsFunc
* shader
)
386 /* Only 1 address reg */
391 NV20VPGetAddressRegSwizzle(nvsFunc
* shader
)
393 /* Only A0.x available */
398 NV20VPInitShaderFuncs(nvsFunc
* shader
)
400 MOD_OPCODE(NVVP_TX_VOP
, NV20_VP_INST_OPCODE_NOP
, NVS_OP_NOP
, -1, -1, -1);
401 MOD_OPCODE(NVVP_TX_VOP
, NV20_VP_INST_OPCODE_MOV
, NVS_OP_MOV
, 0, -1, -1);
402 MOD_OPCODE(NVVP_TX_VOP
, NV20_VP_INST_OPCODE_MUL
, NVS_OP_MUL
, 0, 1, -1);
403 MOD_OPCODE(NVVP_TX_VOP
, NV20_VP_INST_OPCODE_ADD
, NVS_OP_ADD
, 0, 2, -1);
404 MOD_OPCODE(NVVP_TX_VOP
, NV20_VP_INST_OPCODE_MAD
, NVS_OP_MAD
, 0, 1, 2);
405 MOD_OPCODE(NVVP_TX_VOP
, NV20_VP_INST_OPCODE_DP3
, NVS_OP_DP3
, 0, 1, -1);
406 MOD_OPCODE(NVVP_TX_VOP
, NV20_VP_INST_OPCODE_DPH
, NVS_OP_DPH
, 0, 1, -1);
407 MOD_OPCODE(NVVP_TX_VOP
, NV20_VP_INST_OPCODE_DP4
, NVS_OP_DP4
, 0, 1, -1);
408 MOD_OPCODE(NVVP_TX_VOP
, NV20_VP_INST_OPCODE_DST
, NVS_OP_DST
, 0, 1, -1);
409 MOD_OPCODE(NVVP_TX_VOP
, NV20_VP_INST_OPCODE_MIN
, NVS_OP_MIN
, 0, 1, -1);
410 MOD_OPCODE(NVVP_TX_VOP
, NV20_VP_INST_OPCODE_MAX
, NVS_OP_MAX
, 0, 1, -1);
411 MOD_OPCODE(NVVP_TX_VOP
, NV20_VP_INST_OPCODE_SLT
, NVS_OP_SLT
, 0, 1, -1);
412 MOD_OPCODE(NVVP_TX_VOP
, NV20_VP_INST_OPCODE_SGE
, NVS_OP_SGE
, 0, 1, -1);
413 MOD_OPCODE(NVVP_TX_VOP
, NV20_VP_INST_OPCODE_ARL
, NVS_OP_ARL
, 0, -1, -1);
415 MOD_OPCODE(NVVP_TX_SOP
, NV20_VP_INST_OPCODE_NOP
, NVS_OP_NOP
, -1, -1, -1);
416 MOD_OPCODE(NVVP_TX_SOP
, NV20_VP_INST_OPCODE_RCP
, NVS_OP_RCP
, 2, -1, -1);
417 MOD_OPCODE(NVVP_TX_SOP
, NV20_VP_INST_OPCODE_RCC
, NVS_OP_RCC
, 2, -1, -1);
418 MOD_OPCODE(NVVP_TX_SOP
, NV20_VP_INST_OPCODE_RSQ
, NVS_OP_RSQ
, 2, -1, -1);
419 MOD_OPCODE(NVVP_TX_SOP
, NV20_VP_INST_OPCODE_EXP
, NVS_OP_EXP
, 2, -1, -1);
420 MOD_OPCODE(NVVP_TX_SOP
, NV20_VP_INST_OPCODE_LOG
, NVS_OP_LOG
, 2, -1, -1);
421 MOD_OPCODE(NVVP_TX_SOP
, NV20_VP_INST_OPCODE_LIT
, NVS_OP_LIT
, 2, -1, -1);
423 shader
->UploadToHW
= NV20VPUploadToHW
;
424 shader
->UpdateConst
= NV20VPUpdateConst
;
426 shader
->GetOPTXRec
= NV20VPGetOPTXRec
;
427 shader
->GetOPTXFromSOP
= NV20VPGetOPTXFromSOP
;
429 shader
->HasMergedInst
= NV20VPHasMergedInst
;
430 shader
->IsLastInst
= NV20VPIsLastInst
;
431 shader
->GetOffsetNext
= NV20VPGetOffsetNext
;
432 shader
->GetOpcodeSlot
= NV20VPGetOpcodeSlot
;
433 shader
->GetOpcode
= NV20VPGetOpcode
;
434 shader
->GetOpcodeHW
= NV20VPGetOpcodeHW
;
435 shader
->GetDestFile
= NV20VPGetDestFile
;
436 shader
->GetDestID
= NV20VPGetDestID
;
437 shader
->GetDestMask
= NV20VPGetDestMask
;
438 shader
->GetSourceHW
= NV20VPGetSourceHW
;
439 shader
->GetSourceFile
= NV20VPGetSourceFile
;
440 shader
->GetSourceID
= NV20VPGetSourceID
;
441 shader
->GetSourceNegate
= NV20VPGetSourceNegate
;
442 shader
->GetSourceAbs
= NV20VPGetSourceAbs
;
443 shader
->GetSourceSwizzle
= NV20VPGetSourceSwizzle
;
444 shader
->GetSourceIndexed
= NV20VPGetSourceIndexed
;
445 shader
->GetRelAddressRegID
= NV20VPGetAddressRegID
;
446 shader
->GetRelAddressSwizzle
= NV20VPGetAddressRegSwizzle
;