nv50: add/fix some license headers
[mesa.git] / src / gallium / drivers / nv50 / nv50_pc.c
1 /*
2 * Copyright 2010 Christoph Bumiller
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
18 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
19 * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20 * SOFTWARE.
21 */
22
23 #include "nv50_pc.h"
24 #include "nv50_program.h"
25
26 #include <stdio.h>
27
28 /* returns TRUE if operands 0 and 1 can be swapped */
29 boolean
30 nv_op_commutative(uint opcode)
31 {
32 switch (opcode) {
33 case NV_OP_ADD:
34 case NV_OP_MUL:
35 case NV_OP_MAD:
36 case NV_OP_AND:
37 case NV_OP_OR:
38 case NV_OP_XOR:
39 case NV_OP_MIN:
40 case NV_OP_MAX:
41 case NV_OP_SAD:
42 return TRUE;
43 default:
44 return FALSE;
45 }
46 }
47
48 /* return operand to which the address register applies */
49 int
50 nv50_indirect_opnd(struct nv_instruction *i)
51 {
52 if (!i->src[4])
53 return -1;
54
55 switch (i->opcode) {
56 case NV_OP_MOV:
57 case NV_OP_LDA:
58 return 0;
59 default:
60 return 1;
61 }
62 }
63
64 boolean
65 nv50_nvi_can_use_imm(struct nv_instruction *nvi, int s)
66 {
67 if (nvi->flags_src || nvi->flags_def)
68 return FALSE;
69
70 switch (nvi->opcode) {
71 case NV_OP_ADD:
72 case NV_OP_MUL:
73 case NV_OP_AND:
74 case NV_OP_OR:
75 case NV_OP_XOR:
76 case NV_OP_SHL:
77 case NV_OP_SHR:
78 return (s == 1) && (nvi->def[0]->reg.file == NV_FILE_GPR);
79 case NV_OP_MOV:
80 assert(s == 0);
81 return (nvi->def[0]->reg.file == NV_FILE_GPR);
82 default:
83 return FALSE;
84 }
85 }
86
87 boolean
88 nv50_nvi_can_load(struct nv_instruction *nvi, int s, struct nv_value *value)
89 {
90 switch (nvi->opcode) {
91 case NV_OP_ABS:
92 case NV_OP_ADD:
93 case NV_OP_CEIL:
94 case NV_OP_FLOOR:
95 case NV_OP_TRUNC:
96 case NV_OP_CVT:
97 case NV_OP_MAD:
98 case NV_OP_MUL:
99 case NV_OP_SAT:
100 case NV_OP_SUB:
101 case NV_OP_MAX:
102 case NV_OP_MIN:
103 if (s == 0 && (value->reg.file == NV_FILE_MEM_S ||
104 value->reg.file == NV_FILE_MEM_P))
105 return TRUE;
106 if (s == 1 &&
107 value->reg.file >= NV_FILE_MEM_C(0) &&
108 value->reg.file <= NV_FILE_MEM_C(15))
109 return TRUE;
110 if (s == 2 && nvi->src[1]->value->reg.file == NV_FILE_GPR)
111 return TRUE;
112 return FALSE;
113 case NV_OP_MOV:
114 assert(s == 0);
115 return TRUE;
116 default:
117 return FALSE;
118 }
119 }
120
121 ubyte
122 nv50_supported_src_mods(uint opcode, int s)
123 {
124 switch (opcode) {
125 case NV_OP_ABS:
126 return NV_MOD_NEG | NV_MOD_ABS; /* obviously */
127 case NV_OP_ADD:
128 case NV_OP_MUL:
129 case NV_OP_MAD:
130 return NV_MOD_NEG;
131 case NV_OP_DFDX:
132 case NV_OP_DFDY:
133 assert(s == 0);
134 return NV_MOD_NEG;
135 case NV_OP_MAX:
136 case NV_OP_MIN:
137 return NV_MOD_ABS;
138 case NV_OP_CVT:
139 case NV_OP_LG2:
140 case NV_OP_NEG:
141 case NV_OP_PREEX2:
142 case NV_OP_PRESIN:
143 case NV_OP_RCP:
144 case NV_OP_RSQ:
145 return NV_MOD_ABS | NV_MOD_NEG;
146 default:
147 return 0;
148 }
149 }
150
151 int
152 nv_nvi_refcount(struct nv_instruction *nvi)
153 {
154 int i, rc;
155
156 rc = nvi->flags_def ? nvi->flags_def->refc : 0;
157
158 for (i = 0; i < 4; ++i) {
159 if (!nvi->def[i])
160 return rc;
161 rc += nvi->def[i]->refc;
162 }
163 return rc;
164 }
165
166 static void
167 nv_pc_free_refs(struct nv_pc *pc)
168 {
169 int i;
170 for (i = 0; i < pc->num_refs; i += 64)
171 FREE(pc->refs[i]);
172 }
173
174 void
175 nv_print_program(struct nv_basic_block *b)
176 {
177 struct nv_instruction *i = b->phi;
178
179 b->priv = 0;
180
181 debug_printf("=== BB %i ", b->id);
182 if (b->out[0])
183 debug_printf("(--0> %i) ", b->out[0]->id);
184 if (b->out[1])
185 debug_printf("(--1> %i) ", b->out[1]->id);
186 debug_printf("===\n");
187
188 if (!i)
189 i = b->entry;
190 for (; i; i = i->next)
191 nv_print_instruction(i);
192
193 if (!b->out[0]) {
194 debug_printf("END\n\n");
195 return;
196 }
197 if (!b->out[1] && ++(b->out[0]->priv) != b->out[0]->num_in)
198 return;
199
200 if (b->out[0] != b)
201 nv_print_program(b->out[0]);
202
203 if (b->out[1] && b->out[1] != b)
204 nv_print_program(b->out[1]);
205 }
206
207 static INLINE void
208 nvcg_show_bincode(struct nv_pc *pc)
209 {
210 int i;
211
212 for (i = 0; i < pc->bin_size / 4; ++i)
213 debug_printf("0x%08x ", pc->emit[i]);
214 debug_printf("\n");
215 }
216
217 static int
218 nv50_emit_program(struct nv_pc *pc)
219 {
220 uint32_t *code = pc->emit;
221 int n;
222
223 debug_printf("emitting program: size = %u\n", pc->bin_size);
224
225 for (n = 0; n < pc->num_blocks; ++n) {
226 struct nv_instruction *i;
227 struct nv_basic_block *b = pc->bb_list[n];
228
229 for (i = b->entry; i; i = i->next) {
230 nv50_emit_instruction(pc, i);
231
232 pc->bin_pos += 1 + (pc->emit[0] & 1);
233 pc->emit += 1 + (pc->emit[0] & 1);
234 }
235 }
236 assert(pc->emit == &code[pc->bin_size / 4]);
237
238 /* XXX: we can do better than this ... */
239 if ((pc->emit[-1] & 3) == 3) {
240 pc->emit[0] = 0xf0000001;
241 pc->emit[1] = 0xe0000000;
242 pc->bin_size += 8;
243 }
244
245 pc->emit = code;
246 code[pc->bin_size / 4 - 1] |= 1;
247
248 nvcg_show_bincode(pc);
249
250 return 0;
251 }
252
253 int
254 nv50_generate_code(struct nv50_translation_info *ti)
255 {
256 struct nv_pc *pc;
257 int ret;
258
259 pc = CALLOC_STRUCT(nv_pc);
260 if (!pc)
261 return 1;
262
263 ret = nv50_tgsi_to_nc(pc, ti);
264 if (ret)
265 goto out;
266
267 /* optimization */
268 ret = nv_pc_exec_pass0(pc);
269 if (ret)
270 goto out;
271
272 /* register allocation */
273 ret = nv_pc_exec_pass1(pc);
274 if (ret)
275 goto out;
276
277 /* prepare for emission */
278 ret = nv_pc_exec_pass2(pc);
279 if (ret)
280 goto out;
281
282 pc->emit = CALLOC(pc->bin_size / 4 + 2, 4);
283 if (!pc->emit) {
284 ret = 3;
285 goto out;
286 }
287 ret = nv50_emit_program(pc);
288 if (ret)
289 goto out;
290
291 ti->p->code_size = pc->bin_size;
292 ti->p->code = pc->emit;
293
294 ti->p->immd_size = pc->immd_count * 4;
295 ti->p->immd = pc->immd_buf;
296
297 ti->p->max_gpr = (pc->max_reg[NV_FILE_GPR] + 1) >> 1;
298 ti->p->max_gpr++;
299
300 ti->p->fixups = pc->fixups;
301 ti->p->num_fixups = pc->num_fixups;
302
303 debug_printf("SHADER TRANSLATION - %s\n", ret ? "failure" : "success");
304
305 out:
306 nv_pc_free_refs(pc);
307 if (ret) {
308 if (pc->emit)
309 free(pc->emit);
310 if (pc->immd_buf)
311 free(pc->immd_buf);
312 if (pc->fixups)
313 free(pc->fixups);
314 }
315 free(pc);
316
317 return ret;
318 }
319
320 static void
321 nvbb_insert_phi(struct nv_basic_block *b, struct nv_instruction *i)
322 {
323 if (!b->phi) {
324 i->prev = NULL;
325 b->phi = i;
326 i->next = b->entry;
327 if (b->entry) {
328 assert(!b->entry->prev && b->exit);
329 b->entry->prev = i;
330 } else {
331 b->entry = i;
332 b->exit = i;
333 }
334 } else {
335 assert(b->entry);
336 if (b->entry->opcode == NV_OP_PHI) { /* insert after entry */
337 assert(b->entry == b->exit);
338 b->entry->next = i;
339 i->prev = b->entry;
340 b->entry = i;
341 b->exit = i;
342 } else { /* insert before entry */
343 assert(b->entry->prev && b->exit);
344 i->next = b->entry;
345 i->prev = b->entry->prev;
346 b->entry->prev = i;
347 i->prev->next = i;
348 }
349 }
350 }
351
352 void
353 nvbb_insert_tail(struct nv_basic_block *b, struct nv_instruction *i)
354 {
355 if (i->opcode == NV_OP_PHI) {
356 nvbb_insert_phi(b, i);
357 } else {
358 i->prev = b->exit;
359 if (b->exit)
360 b->exit->next = i;
361 b->exit = i;
362 if (!b->entry)
363 b->entry = i;
364 else
365 if (i->prev && i->prev->opcode == NV_OP_PHI)
366 b->entry = i;
367 }
368
369 i->bb = b;
370 b->num_instructions++;
371 }
372
373 void
374 nv_nvi_delete(struct nv_instruction *nvi)
375 {
376 struct nv_basic_block *b = nvi->bb;
377 int j;
378
379 debug_printf("REM: "); nv_print_instruction(nvi);
380
381 for (j = 0; j < 4; ++j) {
382 if (!nvi->src[j])
383 break;
384 --(nvi->src[j]->value->refc);
385 nvi->src[j] = NULL;
386 }
387
388 if (nvi->next)
389 nvi->next->prev = nvi->prev;
390 else {
391 assert(nvi == b->exit);
392 b->exit = nvi->prev;
393 }
394
395 if (nvi->prev)
396 nvi->prev->next = nvi->next;
397
398 if (nvi == b->entry) {
399 assert(nvi->opcode != NV_OP_PHI || !nvi->next);
400
401 if (!nvi->next || (nvi->opcode == NV_OP_PHI))
402 b->entry = nvi->prev;
403 else
404 b->entry = nvi->next;
405 }
406
407 if (nvi == b->phi) {
408 assert(!nvi->prev);
409 if (nvi->opcode != NV_OP_PHI)
410 debug_printf("WARN: b->phi points to non-PHI instruction\n");
411
412 if (!nvi->next || nvi->next->opcode != NV_OP_PHI)
413 b->phi = NULL;
414 else
415 b->phi = nvi->next;
416 }
417 }
418
419 void
420 nv_nvi_permute(struct nv_instruction *i1, struct nv_instruction *i2)
421 {
422 struct nv_basic_block *b = i1->bb;
423
424 assert(i1->opcode != NV_OP_PHI &&
425 i2->opcode != NV_OP_PHI);
426 assert(i1->next == i2);
427
428 if (b->exit == i2)
429 b->exit = i1;
430
431 if (b->entry == i1)
432 b->entry = i2;
433
434 i2->prev = i1->prev;
435 i1->next = i2->next;
436 i2->next = i1;
437 i1->prev = i2;
438
439 if (i2->prev)
440 i2->prev->next = i2;
441 if (i1->next)
442 i1->next->prev = i1;
443 }
444
445 void nvbb_attach_block(struct nv_basic_block *parent, struct nv_basic_block *b)
446 {
447 if (parent->out[0]) {
448 assert(!parent->out[1]);
449 parent->out[1] = b;
450 } else
451 parent->out[0] = b;
452
453 b->in[b->num_in++] = parent;
454 }