revert between 56095 -> 55830 in arch
[AROS.git] / workbench / libs / mesa / src / gallium / drivers / nvc0 / nvc0_pc_emit.c
blobb53a6318db87c939d3dc29798d0d88c6ddfdb010
1 /*
2 * Copyright 2010 Christoph Bumiller
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:
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
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.
23 #include "nvc0_pc.h"
24 #include "nvc0_program.h"
26 #define NVC0_FIXUP_CODE_RELOC 0
27 #define NVC0_FIXUP_DATA_RELOC 1
29 struct nvc0_fixup {
30 uint8_t type;
31 int8_t shift;
32 uint32_t mask;
33 uint32_t data;
34 uint32_t ofst;
37 void
38 nvc0_relocate_program(struct nvc0_program *prog,
39 uint32_t code_base,
40 uint32_t data_base)
42 struct nvc0_fixup *f = (struct nvc0_fixup *)prog->relocs;
43 unsigned i;
45 for (i = 0; i < prog->num_relocs; ++i) {
46 uint32_t data;
48 switch (f[i].type) {
49 case NVC0_FIXUP_CODE_RELOC: data = code_base + f[i].data; break;
50 case NVC0_FIXUP_DATA_RELOC: data = data_base + f[i].data; break;
51 default:
52 data = f[i].data;
53 break;
55 data = (f[i].shift < 0) ? (data >> -f[i].shift) : (data << f[i].shift);
57 prog->code[f[i].ofst / 4] &= ~f[i].mask;
58 prog->code[f[i].ofst / 4] |= data & f[i].mask;
62 #ifdef USE_UNUSED_CODE
63 static void
64 create_fixup(struct nv_pc *pc, uint8_t ty,
65 int w, uint32_t data, uint32_t m, int s)
67 struct nvc0_fixup *f;
69 const unsigned size = sizeof(struct nvc0_fixup);
70 const unsigned n = pc->num_relocs;
72 if (!(n % 8))
73 pc->reloc_entries = REALLOC(pc->reloc_entries, n * size, (n + 8) * size);
75 f = (struct nvc0_fixup *)pc->reloc_entries;
77 f[n].ofst = pc->emit_pos + w * 4;
78 f[n].type = ty;
79 f[n].data = data;
80 f[n].mask = m;
81 f[n].shift = s;
83 ++pc->num_relocs;
85 #endif
87 static INLINE ubyte
88 SSIZE(struct nv_instruction *nvi, int s)
90 return nvi->src[s]->value->reg.size;
93 static INLINE ubyte
94 DSIZE(struct nv_instruction *nvi, int d)
96 return nvi->def[d]->reg.size;
99 static INLINE struct nv_reg *
100 SREG(struct nv_ref *ref)
102 if (!ref)
103 return NULL;
104 return &ref->value->join->reg;
107 static INLINE struct nv_reg *
108 DREG(struct nv_value *val)
110 if (!val)
111 return NULL;
112 return &val->join->reg;
115 static INLINE ubyte
116 SFILE(struct nv_instruction *nvi, int s)
118 return nvi->src[s]->value->reg.file;
121 static INLINE ubyte
122 DFILE(struct nv_instruction *nvi, int d)
124 return nvi->def[0]->reg.file;
127 static INLINE void
128 SID(struct nv_pc *pc, struct nv_ref *ref, int pos)
130 pc->emit[pos / 32] |= (SREG(ref) ? SREG(ref)->id : 63) << (pos % 32);
133 static INLINE void
134 DID(struct nv_pc *pc, struct nv_value *val, int pos)
136 pc->emit[pos / 32] |= (DREG(val) ? DREG(val)->id : 63) << (pos % 32);
139 static INLINE uint32_t
140 get_immd_u32(struct nv_ref *ref) /* XXX: dependent on [0]:2 */
142 assert(ref->value->reg.file == NV_FILE_IMM);
143 return ref->value->reg.imm.u32;
146 static INLINE void
147 set_immd_u32_l(struct nv_pc *pc, uint32_t u32)
149 pc->emit[0] |= (u32 & 0x3f) << 26;
150 pc->emit[1] |= u32 >> 6;
153 static INLINE void
154 set_immd_u32(struct nv_pc *pc, uint32_t u32)
156 if ((pc->emit[0] & 0xf) == 0x2) {
157 set_immd_u32_l(pc, u32);
158 } else
159 if ((pc->emit[0] & 0xf) == 0x3) {
160 assert(!(pc->emit[1] & 0xc000));
161 pc->emit[1] |= 0xc000;
162 assert(!(u32 & 0xfff00000));
163 set_immd_u32_l(pc, u32);
164 } else {
165 assert(!(pc->emit[1] & 0xc000));
166 pc->emit[1] |= 0xc000;
167 assert(!(u32 & 0xfff));
168 set_immd_u32_l(pc, u32 >> 12);
172 static INLINE void
173 set_immd(struct nv_pc *pc, struct nv_instruction *i, int s)
175 set_immd_u32(pc, get_immd_u32(i->src[s]));
178 static INLINE void
179 DVS(struct nv_pc *pc, struct nv_instruction *i)
181 uint s = i->def[0]->reg.size;
182 int n;
183 for (n = 1; n < 4 && i->def[n]; ++n)
184 s += i->def[n]->reg.size;
185 pc->emit[0] |= ((s / 4) - 1) << 5;
188 static INLINE void
189 SVS(struct nv_pc *pc, struct nv_ref *src)
191 pc->emit[0] |= (SREG(src)->size / 4 - 1) << 5;
194 static void
195 set_pred(struct nv_pc *pc, struct nv_instruction *i)
197 if (i->predicate >= 0) {
198 SID(pc, i->src[i->predicate], 6);
199 if (i->cc)
200 pc->emit[0] |= 0x2000; /* negate */
201 } else {
202 pc->emit[0] |= 0x1c00;
206 static INLINE void
207 set_address_16(struct nv_pc *pc, struct nv_ref *src)
209 pc->emit[0] |= (src->value->reg.address & 0x003f) << 26;
210 pc->emit[1] |= (src->value->reg.address & 0xffc0) >> 6;
213 static INLINE unsigned
214 const_space_index(struct nv_instruction *i, int s)
216 return SFILE(i, s) - NV_FILE_MEM_C(0);
219 static void
220 emit_flow(struct nv_pc *pc, struct nv_instruction *i, uint8_t op)
222 pc->emit[0] = 0x00000007;
223 pc->emit[1] = op << 24;
225 if (op == 0x40 || (op >= 0x80 && op <= 0x98)) {
226 /* bra, exit, ret or kil */
227 pc->emit[0] |= 0x1e0;
228 set_pred(pc, i);
231 if (i->target) {
232 int32_t pcrel = i->target->emit_pos - (pc->emit_pos + 8);
234 /* we will need relocations only for global functions */
236 create_fixup(pc, NVC0_FIXUP_CODE_RELOC, 0, pos, 26, 0xfc000000);
237 create_fixup(pc, NVC0_FIXUP_CODE_RELOC, 1, pos, -6, 0x0001ffff);
240 pc->emit[0] |= (pcrel & 0x3f) << 26;
241 pc->emit[1] |= (pcrel >> 6) & 0x3ffff;
245 /* doesn't work for vfetch, export, ld, st, mov ... */
246 static void
247 emit_form_0(struct nv_pc *pc, struct nv_instruction *i)
249 int s;
251 set_pred(pc, i);
253 DID(pc, i->def[0], 14);
255 for (s = 0; s < 3 && i->src[s]; ++s) {
256 if (SFILE(i, s) >= NV_FILE_MEM_C(0) &&
257 SFILE(i, s) <= NV_FILE_MEM_C(15)) {
258 assert(!(pc->emit[1] & 0xc000));
259 assert(s <= 1);
260 pc->emit[1] |= 0x4000 | (const_space_index(i, s) << 10);
261 set_address_16(pc, i->src[s]);
262 } else
263 if (SFILE(i, s) == NV_FILE_GPR) {
264 SID(pc, i->src[s], s ? ((s == 2) ? 49 : 26) : 20);
265 } else
266 if (SFILE(i, s) == NV_FILE_IMM) {
267 assert(!(pc->emit[1] & 0xc000));
268 assert(s == 1 || i->opcode == NV_OP_MOV);
269 set_immd(pc, i, s);
274 static void
275 emit_form_1(struct nv_pc *pc, struct nv_instruction *i)
277 int s;
279 set_pred(pc, i);
281 DID(pc, i->def[0], 14);
283 for (s = 0; s < 1 && i->src[s]; ++s) {
284 if (SFILE(i, s) >= NV_FILE_MEM_C(0) &&
285 SFILE(i, s) <= NV_FILE_MEM_C(15)) {
286 assert(!(pc->emit[1] & 0xc000));
287 assert(s <= 1);
288 pc->emit[1] |= 0x4000 | (const_space_index(i, s) << 10);
289 set_address_16(pc, i->src[s]);
290 } else
291 if (SFILE(i, s) == NV_FILE_GPR) {
292 SID(pc, i->src[s], 26);
293 } else
294 if (SFILE(i, s) == NV_FILE_IMM) {
295 assert(!(pc->emit[1] & 0xc000));
296 assert(s == 1 || i->opcode == NV_OP_MOV);
297 set_immd(pc, i, s);
302 static void
303 emit_neg_abs_1_2(struct nv_pc *pc, struct nv_instruction *i)
305 if (i->src[0]->mod & NV_MOD_ABS)
306 pc->emit[0] |= 1 << 7;
307 if (i->src[0]->mod & NV_MOD_NEG)
308 pc->emit[0] |= 1 << 9;
309 if (i->src[1]->mod & NV_MOD_ABS)
310 pc->emit[0] |= 1 << 6;
311 if (i->src[1]->mod & NV_MOD_NEG)
312 pc->emit[0] |= 1 << 8;
315 static void
316 emit_add_f32(struct nv_pc *pc, struct nv_instruction *i)
318 pc->emit[0] = 0x00000000;
319 pc->emit[1] = 0x50000000;
321 emit_form_0(pc, i);
323 emit_neg_abs_1_2(pc, i);
325 if (i->saturate)
326 pc->emit[1] |= 1 << 17;
329 static void
330 emit_mul_f32(struct nv_pc *pc, struct nv_instruction *i)
332 pc->emit[0] = 0x00000000;
333 pc->emit[1] = 0x58000000;
335 emit_form_0(pc, i);
337 if ((i->src[0]->mod ^ i->src[1]->mod) & NV_MOD_NEG)
338 pc->emit[1] |= 1 << 25;
340 if (i->saturate)
341 pc->emit[0] |= 1 << 5;
344 static void
345 emit_mad_f32(struct nv_pc *pc, struct nv_instruction *i)
347 pc->emit[0] = 0x00000000;
348 pc->emit[1] = 0x30000000;
350 emit_form_0(pc, i);
352 if ((i->src[0]->mod ^ i->src[1]->mod) & NV_MOD_NEG)
353 pc->emit[0] |= 1 << 9;
355 if (i->src[2]->mod & NV_MOD_NEG)
356 pc->emit[0] |= 1 << 8;
358 if (i->saturate)
359 pc->emit[0] |= 1 << 5;
362 static void
363 emit_minmax(struct nv_pc *pc, struct nv_instruction *i)
365 pc->emit[0] = 0x00000000;
366 pc->emit[1] = 0x08000000;
368 if (NV_BASEOP(i->opcode) == NV_OP_MAX)
369 pc->emit[1] |= 0x001e0000;
370 else
371 pc->emit[1] |= 0x000e0000; /* predicate ? */
373 emit_form_0(pc, i);
375 emit_neg_abs_1_2(pc, i);
377 switch (i->opcode) {
378 case NV_OP_MIN_U32:
379 case NV_OP_MAX_U32:
380 pc->emit[0] |= 3;
381 break;
382 case NV_OP_MIN_S32:
383 case NV_OP_MAX_S32:
384 pc->emit[0] |= 3 | (1 << 5);
385 break;
386 case NV_OP_MIN_F32:
387 case NV_OP_MAX_F32:
388 default:
389 break;
393 static void
394 emit_tex(struct nv_pc *pc, struct nv_instruction *i)
396 int src1 = i->tex_array + i->tex_dim + i->tex_cube;
398 assert(src1 < 6);
400 pc->emit[0] = 0x00000086;
401 pc->emit[1] = 0x80000000;
403 switch (i->opcode) {
404 case NV_OP_TEX: pc->emit[1] = 0x80000000; break;
405 case NV_OP_TXB: pc->emit[1] = 0x84000000; break;
406 case NV_OP_TXL: pc->emit[1] = 0x86000000; break;
407 case NV_OP_TXF: pc->emit[1] = 0x90000000; break;
408 case NV_OP_TXG: pc->emit[1] = 0xe0000000; break;
409 default:
410 assert(0);
411 break;
414 if (i->tex_array)
415 pc->emit[1] |= 0x00080000; /* layer index is u16, first value of SRC0 */
416 if (i->tex_shadow)
417 pc->emit[1] |= 0x01000000; /* shadow is part of SRC1, after bias/lod */
419 set_pred(pc, i);
421 DID(pc, i->def[0], 14);
422 SID(pc, i->src[0], 20);
423 SID(pc, i->src[src1], 26); /* may be NULL -> $r63 */
425 pc->emit[1] |= i->tex_mask << 14;
426 pc->emit[1] |= (i->tex_dim - 1) << 20;
427 if (i->tex_cube)
428 pc->emit[1] |= 3 << 20;
430 assert(i->ext.tex.s < 16);
432 pc->emit[1] |= i->ext.tex.t;
433 pc->emit[1] |= i->ext.tex.s << 8;
435 if (i->tex_live)
436 pc->emit[0] |= 1 << 9;
439 /* 0: cos, 1: sin, 2: ex2, 3: lg2, 4: rcp, 5: rsqrt */
440 static void
441 emit_flop(struct nv_pc *pc, struct nv_instruction *i, ubyte op)
443 pc->emit[0] = 0x00000000;
444 pc->emit[1] = 0xc8000000;
446 set_pred(pc, i);
448 DID(pc, i->def[0], 14);
449 SID(pc, i->src[0], 20);
451 pc->emit[0] |= op << 26;
453 if (op >= 3) {
454 if (i->src[0]->mod & NV_MOD_NEG) pc->emit[0] |= 1 << 9;
455 if (i->src[0]->mod & NV_MOD_ABS) pc->emit[0] |= 1 << 7;
456 } else {
457 assert(!i->src[0]->mod);
461 static void
462 emit_quadop(struct nv_pc *pc, struct nv_instruction *i)
464 pc->emit[0] = 0x00000000;
465 pc->emit[1] = 0x48000000;
467 set_pred(pc, i);
469 assert(SFILE(i, 0) == NV_FILE_GPR && SFILE(i, 1) == NV_FILE_GPR);
471 DID(pc, i->def[0], 14);
472 SID(pc, i->src[0], 20);
473 SID(pc, i->src[0], 26);
475 pc->emit[0] |= i->lanes << 6; /* l0, l1, l2, l3, dx, dy */
476 pc->emit[1] |= i->quadop;
479 static void
480 emit_ddx(struct nv_pc *pc, struct nv_instruction *i)
482 i->quadop = 0x99;
483 i->lanes = 4;
484 i->src[1] = i->src[0];
485 emit_quadop(pc, i);
488 static void
489 emit_ddy(struct nv_pc *pc, struct nv_instruction *i)
491 i->quadop = 0xa5;
492 i->lanes = 5;
493 i->src[1] = i->src[0];
494 emit_quadop(pc, i);
497 /* preparation op (preex2, presin / convert to fixed point) */
498 static void
499 emit_preop(struct nv_pc *pc, struct nv_instruction *i)
501 pc->emit[0] = 0x00000000;
502 pc->emit[1] = 0x60000000;
504 if (i->opcode == NV_OP_PREEX2)
505 pc->emit[0] |= 0x20;
507 emit_form_1(pc, i);
509 if (i->src[0]->mod & NV_MOD_NEG) pc->emit[0] |= 1 << 8;
510 if (i->src[0]->mod & NV_MOD_ABS) pc->emit[0] |= 1 << 6;
513 static void
514 emit_shift(struct nv_pc *pc, struct nv_instruction *i)
516 pc->emit[0] = 0x00000003;
518 switch (i->opcode) {
519 case NV_OP_SAR:
520 pc->emit[0] |= 0x20; /* fall through */
521 case NV_OP_SHR:
522 pc->emit[1] = 0x58000000;
523 break;
524 case NV_OP_SHL:
525 default:
526 pc->emit[1] = 0x60000000;
527 break;
530 emit_form_0(pc, i);
533 static void
534 emit_bitop(struct nv_pc *pc, struct nv_instruction *i)
536 if (SFILE(i, 1) == NV_FILE_IMM) {
537 pc->emit[0] = 0x00000002;
538 pc->emit[1] = 0x38000000;
539 } else {
540 pc->emit[0] = 0x00000003;
541 pc->emit[1] = 0x68000000;
544 switch (i->opcode) {
545 case NV_OP_OR:
546 pc->emit[0] |= 0x40;
547 break;
548 case NV_OP_XOR:
549 pc->emit[0] |= 0x80;
550 break;
551 case NV_OP_AND:
552 default:
553 break;
556 emit_form_0(pc, i);
559 static void
560 emit_set(struct nv_pc *pc, struct nv_instruction *i)
562 pc->emit[0] = 0x00000000;
564 switch (i->opcode) {
565 case NV_OP_SET_S32:
566 pc->emit[0] |= 0x20; /* fall through */
567 case NV_OP_SET_U32:
568 pc->emit[0] |= 0x3;
569 pc->emit[1] = 0x100e0000;
570 break;
571 case NV_OP_SET_F32_AND:
572 pc->emit[1] = 0x18000000;
573 break;
574 case NV_OP_SET_F32_OR:
575 pc->emit[1] = 0x18200000;
576 break;
577 case NV_OP_SET_F32_XOR:
578 pc->emit[1] = 0x18400000;
579 break;
580 case NV_OP_FSET_F32:
581 pc->emit[0] |= 0x20; /* fall through */
582 case NV_OP_SET_F32:
583 default:
584 pc->emit[1] = 0x180e0000;
585 break;
588 if (DFILE(i, 0) == NV_FILE_PRED) {
589 pc->emit[0] |= 0x1c000;
590 pc->emit[1] += 0x08000000;
593 pc->emit[1] |= i->set_cond << 23;
595 emit_form_0(pc, i);
597 emit_neg_abs_1_2(pc, i); /* maybe assert that U/S32 don't use mods */
600 static void
601 emit_selp(struct nv_pc *pc, struct nv_instruction *i)
603 pc->emit[0] = 0x00000004;
604 pc->emit[1] = 0x20000000;
606 emit_form_0(pc, i);
608 if (i->cc || (i->src[2]->mod & NV_MOD_NOT))
609 pc->emit[1] |= 1 << 20;
612 static void
613 emit_slct(struct nv_pc *pc, struct nv_instruction *i)
615 uint8_t cc = i->set_cond;
617 pc->emit[0] = 0x00000000;
619 switch (i->opcode) {
620 case NV_OP_SLCT_S32:
621 pc->emit[0] |= 0x20; /* fall through */
622 case NV_OP_SLCT_U32:
623 pc->emit[0] |= 0x3;
624 pc->emit[1] = 0x30000000;
625 break;
626 case NV_OP_SLCT_F32:
627 default:
628 pc->emit[1] = 0x38000000;
629 break;
632 emit_form_0(pc, i);
634 if (i->src[2]->mod & NV_MOD_NEG)
635 cc = nvc0_ir_reverse_cc(cc);
637 pc->emit[1] |= cc << 23;
640 static void
641 emit_cvt(struct nv_pc *pc, struct nv_instruction *i)
643 uint32_t rint;
645 pc->emit[0] = 0x00000004;
646 pc->emit[1] = 0x10000000;
648 /* if no type conversion specified, get type from opcode */
649 if (i->opcode != NV_OP_CVT && i->ext.cvt.d == i->ext.cvt.s)
650 i->ext.cvt.d = i->ext.cvt.s = NV_OPTYPE(i->opcode);
652 switch (i->ext.cvt.d) {
653 case NV_TYPE_F32:
654 switch (i->ext.cvt.s) {
655 case NV_TYPE_F32: pc->emit[1] = 0x10000000; break;
656 case NV_TYPE_S32: pc->emit[0] |= 0x200; /* fall through */
657 case NV_TYPE_U32: pc->emit[1] = 0x18000000; break;
659 break;
660 case NV_TYPE_S32: pc->emit[0] |= 0x80; /* fall through */
661 case NV_TYPE_U32:
662 switch (i->ext.cvt.s) {
663 case NV_TYPE_F32: pc->emit[1] = 0x14000000; break;
664 case NV_TYPE_S32: pc->emit[0] |= 0x200; /* fall through */
665 case NV_TYPE_U32: pc->emit[1] = 0x1c000000; break;
667 break;
668 default:
669 assert(!"cvt: unknown type");
670 break;
673 rint = (i->ext.cvt.d == NV_TYPE_F32) ? 1 << 7 : 0;
675 if (i->opcode == NV_OP_FLOOR) {
676 pc->emit[0] |= rint;
677 pc->emit[1] |= 2 << 16;
678 } else
679 if (i->opcode == NV_OP_CEIL) {
680 pc->emit[0] |= rint;
681 pc->emit[1] |= 4 << 16;
682 } else
683 if (i->opcode == NV_OP_TRUNC) {
684 pc->emit[0] |= rint;
685 pc->emit[1] |= 6 << 16;
688 if (i->saturate || i->opcode == NV_OP_SAT)
689 pc->emit[0] |= 0x20;
691 if (NV_BASEOP(i->opcode) == NV_OP_ABS || i->src[0]->mod & NV_MOD_ABS)
692 pc->emit[0] |= 1 << 6;
693 if (NV_BASEOP(i->opcode) == NV_OP_NEG || i->src[0]->mod & NV_MOD_NEG)
694 pc->emit[0] |= 1 << 8;
696 pc->emit[0] |= util_logbase2(DREG(i->def[0])->size) << 20;
697 pc->emit[0] |= util_logbase2(SREG(i->src[0])->size) << 23;
699 emit_form_1(pc, i);
702 static void
703 emit_interp(struct nv_pc *pc, struct nv_instruction *i)
705 pc->emit[0] = 0x00000000;
706 pc->emit[1] = 0xc07e0000;
708 DID(pc, i->def[0], 14);
710 set_pred(pc, i);
712 if (i->indirect)
713 SID(pc, i->src[i->indirect], 20);
714 else
715 SID(pc, NULL, 20);
717 if (i->opcode == NV_OP_PINTERP) {
718 pc->emit[0] |= 0x040;
719 SID(pc, i->src[1], 26);
721 if (i->src[0]->value->reg.address >= 0x280 &&
722 i->src[0]->value->reg.address <= 0x29c)
723 pc->emit[0] |= 0x080; /* XXX: ? */
724 } else {
725 SID(pc, NULL, 26);
728 pc->emit[1] |= i->src[0]->value->reg.address & 0xffff;
730 if (i->centroid)
731 pc->emit[0] |= 0x100;
732 else
733 if (i->flat)
734 pc->emit[0] |= 0x080;
737 static void
738 emit_vfetch(struct nv_pc *pc, struct nv_instruction *i)
740 pc->emit[0] = 0x03f00006;
741 pc->emit[1] = 0x06000000 | i->src[0]->value->reg.address;
742 if (i->patch)
743 pc->emit[0] |= 0x100;
745 set_pred(pc, i);
747 DVS(pc, i);
748 DID(pc, i->def[0], 14);
750 SID(pc, (i->indirect >= 0) ? i->src[i->indirect] : NULL, 26);
753 static void
754 emit_export(struct nv_pc *pc, struct nv_instruction *i)
756 pc->emit[0] = 0x00000006;
757 pc->emit[1] = 0x0a000000;
758 if (i->patch)
759 pc->emit[0] |= 0x100;
761 set_pred(pc, i);
763 assert(SFILE(i, 0) == NV_FILE_MEM_V);
764 assert(SFILE(i, 1) == NV_FILE_GPR);
766 SID(pc, i->src[1], 26); /* register source */
767 SVS(pc, i->src[0]);
769 pc->emit[1] |= i->src[0]->value->reg.address & 0xfff;
771 SID(pc, (i->indirect >= 0) ? i->src[i->indirect] : NULL, 20);
774 static void
775 emit_mov(struct nv_pc *pc, struct nv_instruction *i)
777 if (i->opcode == NV_OP_MOV)
778 i->lanes = 0xf;
780 if (SFILE(i, 0) == NV_FILE_IMM) {
781 pc->emit[0] = 0x000001e2;
782 pc->emit[1] = 0x18000000;
783 } else
784 if (SFILE(i, 0) == NV_FILE_PRED) {
785 pc->emit[0] = 0x1c000004;
786 pc->emit[1] = 0x080e0000;
787 } else {
788 pc->emit[0] = 0x00000004 | (i->lanes << 5);
789 pc->emit[1] = 0x28000000;
792 emit_form_1(pc, i);
795 static void
796 emit_ldst_size(struct nv_pc *pc, struct nv_instruction *i)
798 assert(NV_IS_MEMORY_FILE(SFILE(i, 0)));
800 switch (SSIZE(i, 0)) {
801 case 1:
802 if (NV_TYPE_ISSGD(i->ext.cvt.s))
803 pc->emit[0] |= 0x20;
804 break;
805 case 2:
806 pc->emit[0] |= 0x40;
807 if (NV_TYPE_ISSGD(i->ext.cvt.s))
808 pc->emit[0] |= 0x20;
809 break;
810 case 4: pc->emit[0] |= 0x80; break;
811 case 8: pc->emit[0] |= 0xa0; break;
812 case 16: pc->emit[0] |= 0xc0; break;
813 default:
814 NOUVEAU_ERR("invalid load/store size %u\n", SSIZE(i, 0));
815 break;
819 static void
820 emit_ld_common(struct nv_pc *pc, struct nv_instruction *i)
822 emit_ldst_size(pc, i);
824 set_pred(pc, i);
825 set_address_16(pc, i->src[0]);
827 SID(pc, (i->indirect >= 0) ? i->src[i->indirect] : NULL, 20);
828 DID(pc, i->def[0], 14);
831 static void
832 emit_ld_const(struct nv_pc *pc, struct nv_instruction *i)
834 pc->emit[0] = 0x00000006;
835 pc->emit[1] = 0x14000000 | (const_space_index(i, 0) << 10);
837 emit_ld_common(pc, i);
840 static void
841 emit_ld(struct nv_pc *pc, struct nv_instruction *i)
843 if (SFILE(i, 0) >= NV_FILE_MEM_C(0) &&
844 SFILE(i, 0) <= NV_FILE_MEM_C(15)) {
845 if (SSIZE(i, 0) == 4 && i->indirect < 0) {
846 i->lanes = 0xf;
847 emit_mov(pc, i);
848 } else {
849 emit_ld_const(pc, i);
851 } else
852 if (SFILE(i, 0) == NV_FILE_MEM_L) {
853 pc->emit[0] = 0x00000005;
854 pc->emit[1] = 0xc0000000;
856 emit_ld_common(pc, i);
857 } else {
858 NOUVEAU_ERR("emit_ld(%u): not handled yet\n", SFILE(i, 0));
859 abort();
863 static void
864 emit_st(struct nv_pc *pc, struct nv_instruction *i)
866 if (SFILE(i, 0) != NV_FILE_MEM_L)
867 NOUVEAU_ERR("emit_st(%u): file not handled yet\n", SFILE(i, 0));
869 pc->emit[0] = 0x00000005 | (0 << 8); /* write-back caching */
870 pc->emit[1] = 0xc8000000;
872 emit_ldst_size(pc, i);
874 set_pred(pc, i);
875 set_address_16(pc, i->src[0]);
877 SID(pc, (i->indirect >= 0) ? i->src[i->indirect] : NULL, 20);
878 DID(pc, i->src[1]->value, 14);
881 void
882 nvc0_emit_instruction(struct nv_pc *pc, struct nv_instruction *i)
884 #if NV50_DEBUG & NV50_DEBUG_SHADER
885 debug_printf("EMIT: "); nvc0_print_instruction(i);
886 #endif
888 switch (i->opcode) {
889 case NV_OP_VFETCH:
890 emit_vfetch(pc, i);
891 break;
892 case NV_OP_EXPORT:
893 if (!pc->is_fragprog)
894 emit_export(pc, i);
895 break;
896 case NV_OP_MOV:
897 emit_mov(pc, i);
898 break;
899 case NV_OP_LD:
900 emit_ld(pc, i);
901 break;
902 case NV_OP_ST:
903 emit_st(pc, i);
904 break;
905 case NV_OP_LINTERP:
906 case NV_OP_PINTERP:
907 emit_interp(pc, i);
908 break;
909 case NV_OP_ADD_F32:
910 emit_add_f32(pc, i);
911 break;
912 case NV_OP_AND:
913 case NV_OP_OR:
914 case NV_OP_XOR:
915 emit_bitop(pc, i);
916 break;
917 case NV_OP_CVT:
918 case NV_OP_ABS_F32:
919 case NV_OP_ABS_S32:
920 case NV_OP_NEG_F32:
921 case NV_OP_NEG_S32:
922 case NV_OP_SAT:
923 case NV_OP_CEIL:
924 case NV_OP_FLOOR:
925 case NV_OP_TRUNC:
926 emit_cvt(pc, i);
927 break;
928 case NV_OP_DFDX:
929 emit_ddx(pc, i);
930 break;
931 case NV_OP_DFDY:
932 emit_ddy(pc, i);
933 break;
934 case NV_OP_COS:
935 emit_flop(pc, i, 0);
936 break;
937 case NV_OP_SIN:
938 emit_flop(pc, i, 1);
939 break;
940 case NV_OP_EX2:
941 emit_flop(pc, i, 2);
942 break;
943 case NV_OP_LG2:
944 emit_flop(pc, i, 3);
945 break;
946 case NV_OP_RCP:
947 emit_flop(pc, i, 4);
948 break;
949 case NV_OP_RSQ:
950 emit_flop(pc, i, 5);
951 break;
952 case NV_OP_PRESIN:
953 case NV_OP_PREEX2:
954 emit_preop(pc, i);
955 break;
956 case NV_OP_MAD_F32:
957 emit_mad_f32(pc, i);
958 break;
959 case NV_OP_MAX_F32:
960 case NV_OP_MAX_S32:
961 case NV_OP_MAX_U32:
962 case NV_OP_MIN_F32:
963 case NV_OP_MIN_S32:
964 case NV_OP_MIN_U32:
965 emit_minmax(pc, i);
966 break;
967 case NV_OP_MUL_F32:
968 emit_mul_f32(pc, i);
969 break;
970 case NV_OP_SET_F32:
971 case NV_OP_SET_F32_AND:
972 case NV_OP_SET_F32_OR:
973 case NV_OP_SET_F32_XOR:
974 case NV_OP_SET_S32:
975 case NV_OP_SET_U32:
976 case NV_OP_FSET_F32:
977 emit_set(pc, i);
978 break;
979 case NV_OP_SHL:
980 case NV_OP_SHR:
981 case NV_OP_SAR:
982 emit_shift(pc, i);
983 break;
984 case NV_OP_TEX:
985 case NV_OP_TXB:
986 case NV_OP_TXL:
987 emit_tex(pc, i);
988 break;
989 case NV_OP_BRA:
990 emit_flow(pc, i, 0x40);
991 break;
992 case NV_OP_CALL:
993 emit_flow(pc, i, 0x50);
994 break;
995 case NV_OP_JOINAT:
996 emit_flow(pc, i, 0x60);
997 break;
998 case NV_OP_EXIT:
999 emit_flow(pc, i, 0x80);
1000 break;
1001 case NV_OP_RET:
1002 emit_flow(pc, i, 0x90);
1003 break;
1004 case NV_OP_KIL:
1005 emit_flow(pc, i, 0x98);
1006 break;
1007 case NV_OP_JOIN:
1008 case NV_OP_NOP:
1009 pc->emit[0] = 0x00003de4;
1010 pc->emit[1] = 0x40000000;
1011 break;
1012 case NV_OP_SELP:
1013 emit_selp(pc, i);
1014 break;
1015 case NV_OP_SLCT_F32:
1016 case NV_OP_SLCT_S32:
1017 case NV_OP_SLCT_U32:
1018 emit_slct(pc, i);
1019 break;
1020 default:
1021 NOUVEAU_ERR("unhandled NV_OP: %d\n", i->opcode);
1022 abort();
1023 break;
1026 if (i->join)
1027 pc->emit[0] |= 0x10;