Merge branch 'master' of git+ssh://git.freedesktop.org/git/mesa/mesa
[mesa.git] / src / mesa / drivers / dri / nouveau / nv40_fragprog.c
1 #include "nouveau_shader.h"
2 #include "nv40_shader.h"
3
4 /* branching ops */
5 unsigned int NVFP_TX_BOP_COUNT = 5;
6 struct _op_xlat NVFP_TX_BOP[64];
7
8
9 /*****************************************************************************
10 * Assembly routines
11 * - These extend the NV30 routines, which are almost identical. NV40
12 * just has branching hacked into the instruction set.
13 */
14 static void
15 NV40FPSetBranchTarget(nvsFunc *shader, int addr)
16 {
17 shader->inst[2] &= ~NV40_FP_OP_IADDR_MASK;
18 shader->inst[2] |= (addr << NV40_FP_OP_IADDR_SHIFT);
19 }
20
21 static void
22 NV40FPSetBranchElse(nvsFunc *shader, int addr)
23 {
24 shader->inst[2] &= ~NV40_FP_OP_ELSE_ID_MASK;
25 shader->inst[2] |= (addr << NV40_FP_OP_ELSE_ID_SHIFT);
26 }
27
28 static void
29 NV40FPSetBranchEnd(nvsFunc *shader, int addr)
30 {
31 shader->inst[3] &= ~NV40_FP_OP_END_ID_MASK;
32 shader->inst[3] |= (addr << NV40_FP_OP_END_ID_SHIFT);
33 }
34
35 static void
36 NV40FPSetLoopParams(nvsFunc *shader, int count, int initial, int increment)
37 {
38 shader->inst[2] &= ~(NV40_FP_OP_LOOP_COUNT_MASK |
39 NV40_FP_OP_LOOP_INDEX_MASK |
40 NV40_FP_OP_LOOP_INCR_MASK);
41 shader->inst[2] |= ((count << NV40_FP_OP_LOOP_COUNT_SHIFT) |
42 (initial << NV40_FP_OP_LOOP_INDEX_SHIFT) |
43 (increment << NV40_FP_OP_LOOP_INCR_SHIFT));
44 }
45
46 /*****************************************************************************
47 * Disassembly routines
48 */
49 static struct _op_xlat *
50 NV40FPGetOPTXRec(nvsFunc * shader, int merged)
51 {
52 struct _op_xlat *opr;
53 int op;
54
55 op = shader->GetOpcodeHW(shader, 0);
56 if (shader->inst[2] & NV40_FP_OP_OPCODE_IS_BRANCH) {
57 opr = NVFP_TX_BOP;
58 op &= ~NV40_FP_OP_OPCODE_IS_BRANCH;
59 if (op > NVFP_TX_BOP_COUNT)
60 return NULL;
61 }
62 else {
63 opr = NVFP_TX_AOP;
64 if (op > NVFP_TX_AOP_COUNT)
65 return NULL;
66 }
67
68 if (opr[op].SOP == NVS_OP_UNKNOWN)
69 return NULL;
70 return &opr[op];
71 }
72
73 static int
74 NV40FPGetSourceID(nvsFunc * shader, int merged, int pos)
75 {
76 switch (shader->GetSourceFile(shader, merged, pos)) {
77 case NVS_FILE_ATTRIB:
78 switch ((shader->inst[0] & NV40_FP_OP_INPUT_SRC_MASK)
79 >> NV40_FP_OP_INPUT_SRC_SHIFT) {
80 case NV40_FP_OP_INPUT_SRC_POSITION: return NVS_FR_POSITION;
81 case NV40_FP_OP_INPUT_SRC_COL0 : return NVS_FR_COL0;
82 case NV40_FP_OP_INPUT_SRC_COL1 : return NVS_FR_COL1;
83 case NV40_FP_OP_INPUT_SRC_FOGC : return NVS_FR_FOGCOORD;
84 case NV40_FP_OP_INPUT_SRC_TC(0) : return NVS_FR_TEXCOORD0;
85 case NV40_FP_OP_INPUT_SRC_TC(1) : return NVS_FR_TEXCOORD1;
86 case NV40_FP_OP_INPUT_SRC_TC(2) : return NVS_FR_TEXCOORD2;
87 case NV40_FP_OP_INPUT_SRC_TC(3) : return NVS_FR_TEXCOORD3;
88 case NV40_FP_OP_INPUT_SRC_TC(4) : return NVS_FR_TEXCOORD4;
89 case NV40_FP_OP_INPUT_SRC_TC(5) : return NVS_FR_TEXCOORD5;
90 case NV40_FP_OP_INPUT_SRC_TC(6) : return NVS_FR_TEXCOORD6;
91 case NV40_FP_OP_INPUT_SRC_TC(7) : return NVS_FR_TEXCOORD7;
92 case NV40_FP_OP_INPUT_SRC_FACING : return NVS_FR_FACING;
93 default:
94 return -1;
95 }
96 break;
97 case NVS_FILE_TEMP:
98 {
99 unsigned int src;
100
101 src = shader->GetSourceHW(shader, merged, pos);
102 return ((src & NV40_FP_REG_SRC_MASK) >> NV40_FP_REG_SRC_SHIFT);
103 }
104 case NVS_FILE_CONST: /* inlined into fragprog */
105 default:
106 return -1;
107 }
108 }
109
110 static int
111 NV40FPGetBranch(nvsFunc * shader)
112 {
113 return ((shader->inst[2] & NV40_FP_OP_IADDR_MASK)
114 >> NV40_FP_OP_IADDR_SHIFT);;
115 }
116
117 static int
118 NV40FPGetBranchElse(nvsFunc * shader)
119 {
120 return ((shader->inst[2] & NV40_FP_OP_ELSE_ID_MASK)
121 >> NV40_FP_OP_ELSE_ID_SHIFT);
122 }
123
124 static int
125 NV40FPGetBranchEnd(nvsFunc * shader)
126 {
127 return ((shader->inst[3] & NV40_FP_OP_END_ID_MASK)
128 >> NV40_FP_OP_END_ID_SHIFT);
129 }
130
131 static int
132 NV40FPGetLoopCount(nvsFunc * shader)
133 {
134 return ((shader->inst[2] & NV40_FP_OP_LOOP_COUNT_MASK)
135 >> NV40_FP_OP_LOOP_COUNT_SHIFT);
136 }
137
138 static int
139 NV40FPGetLoopInitial(nvsFunc * shader)
140 {
141 return ((shader->inst[2] & NV40_FP_OP_LOOP_INDEX_MASK)
142 >> NV40_FP_OP_LOOP_INDEX_SHIFT);
143 }
144
145 static int
146 NV40FPGetLoopIncrement(nvsFunc * shader)
147 {
148 return ((shader->inst[2] & NV40_FP_OP_LOOP_INCR_MASK)
149 >> NV40_FP_OP_LOOP_INCR_SHIFT);
150 }
151
152 void
153 NV40FPInitShaderFuncs(nvsFunc * shader)
154 {
155 /* Inherit NV30 FP code, it's mostly the same */
156 NV30FPInitShaderFuncs(shader);
157
158 /* Kill off opcodes seen on NV30, but not seen on NV40 - need to find
159 * out if these actually work or not.
160 *
161 * update: either LIT/RSQ don't work on nv40, or I generate bad code for
162 * them. haven't tested the others yet
163 */
164 MOD_OPCODE(NVFP_TX_AOP, 0x1B, NVS_OP_UNKNOWN, -1, -1, -1); /* NV30 RSQ */
165 MOD_OPCODE(NVFP_TX_AOP, 0x1E, NVS_OP_UNKNOWN, -1, -1, -1); /* NV30 LIT */
166 MOD_OPCODE(NVFP_TX_AOP, 0x1F, NVS_OP_UNKNOWN, -1, -1, -1); /* NV30 LRP */
167 MOD_OPCODE(NVFP_TX_AOP, 0x26, NVS_OP_UNKNOWN, -1, -1, -1); /* NV30 POW */
168 MOD_OPCODE(NVFP_TX_AOP, 0x36, NVS_OP_UNKNOWN, -1, -1, -1); /* NV30 RFL */
169
170 /* Extra opcodes supported on NV40 */
171 MOD_OPCODE(NVFP_TX_AOP, NV40_FP_OP_OPCODE_DIV , NVS_OP_DIV , 0, 1, -1);
172 MOD_OPCODE(NVFP_TX_AOP, NV40_FP_OP_OPCODE_DP2A , NVS_OP_DP2A, 0, 1, 2);
173 MOD_OPCODE(NVFP_TX_AOP, NV40_FP_OP_OPCODE_TXL , NVS_OP_TXL , 0, -1, -1);
174
175 MOD_OPCODE(NVFP_TX_BOP, NV40_FP_OP_BRA_OPCODE_BRK , NVS_OP_BRK , -1, -1, -1);
176 MOD_OPCODE(NVFP_TX_BOP, NV40_FP_OP_BRA_OPCODE_CAL , NVS_OP_CAL , -1, -1, -1);
177 MOD_OPCODE(NVFP_TX_BOP, NV40_FP_OP_BRA_OPCODE_IF , NVS_OP_IF , -1, -1, -1);
178 MOD_OPCODE(NVFP_TX_BOP, NV40_FP_OP_BRA_OPCODE_LOOP, NVS_OP_LOOP, -1, -1, -1);
179 MOD_OPCODE(NVFP_TX_BOP, NV40_FP_OP_BRA_OPCODE_REP , NVS_OP_REP , -1, -1, -1);
180 MOD_OPCODE(NVFP_TX_BOP, NV40_FP_OP_BRA_OPCODE_RET , NVS_OP_RET , -1, -1, -1);
181
182 /* fragment.facing */
183 shader->GetSourceID = NV40FPGetSourceID;
184
185 /* branching */
186 shader->GetOPTXRec = NV40FPGetOPTXRec;
187 shader->GetBranch = NV40FPGetBranch;
188 shader->GetBranchElse = NV40FPGetBranchElse;
189 shader->GetBranchEnd = NV40FPGetBranchEnd;
190 shader->GetLoopCount = NV40FPGetLoopCount;
191 shader->GetLoopInitial = NV40FPGetLoopInitial;
192 shader->GetLoopIncrement = NV40FPGetLoopIncrement;
193 shader->SetBranchTarget = NV40FPSetBranchTarget;
194 shader->SetBranchElse = NV40FPSetBranchElse;
195 shader->SetBranchEnd = NV40FPSetBranchEnd;
196 shader->SetLoopParams = NV40FPSetLoopParams;
197 }