Check for SYS/GL during library init. Reason is that
[AROS.git] / workbench / libs / mesa / src / gallium / drivers / nv50 / nv50_pc_emit.c
blob600850da011cc13519603d6263e6728a97e3fc5a
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 "nv50_context.h"
24 #include "nv50_pc.h"
26 #define FLAGS_CC_SHIFT 7
27 #define FLAGS_ID_SHIFT 12
28 #define FLAGS_WR_ID_SHIFT 4
29 #define FLAGS_CC_MASK (0x1f << FLAGS_CC_SHIFT)
30 #define FLAGS_ID_MASK (0x03 << FLAGS_ID_SHIFT)
31 #define FLAGS_WR_EN (1 << 6)
32 #define FLAGS_WR_ID_MASK (0x3 << FLAGS_WR_ID_SHIFT)
34 #define NV50_FIXUP_CODE_RELOC 0
35 #define NV50_FIXUP_DATA_RELOC 1
37 struct nv50_fixup {
38 uint8_t type;
39 int8_t shift;
40 uint32_t mask;
41 uint32_t data;
42 uint32_t offset;
45 void
46 nv50_relocate_program(struct nv50_program *p,
47 uint32_t code_base,
48 uint32_t data_base)
50 struct nv50_fixup *f = (struct nv50_fixup *)p->fixups;
51 unsigned i;
53 for (i = 0; i < p->num_fixups; ++i) {
54 uint32_t data;
56 switch (f[i].type) {
57 case NV50_FIXUP_CODE_RELOC: data = code_base + f[i].data; break;
58 case NV50_FIXUP_DATA_RELOC: data = data_base + f[i].data; break;
59 default:
60 data = f[i].data;
61 break;
63 data = (f[i].shift < 0) ? (data >> -f[i].shift) : (data << f[i].shift);
65 p->code[f[i].offset / 4] &= ~f[i].mask;
66 p->code[f[i].offset / 4] |= data & f[i].mask;
70 static void
71 new_fixup(struct nv_pc *pc, uint8_t ty, int w, uint32_t data, uint32_t m, int s)
73 struct nv50_fixup *f;
75 const unsigned size = sizeof(struct nv50_fixup);
76 const unsigned n = pc->num_fixups;
78 if (!(n % 8))
79 pc->fixups = REALLOC(pc->fixups, n * size, (n + 8) * size);
81 f = (struct nv50_fixup *)pc->fixups;
83 f[n].offset = (pc->bin_pos + w) * 4;
84 f[n].type = ty;
85 f[n].data = data;
86 f[n].mask = m;
87 f[n].shift = s;
89 ++pc->num_fixups;
92 const ubyte nv50_inst_min_size_tab[NV_OP_COUNT] =
94 0, 0, 0, 8, 8, 4, 4, 4, 8, 4, 4, 8, 8, 8, 8, 8, /* 15 */
95 8, 8, 8, 4, 0, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 4, /* 31 */
96 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 4, /* 47 */
97 4, 8, 8, 8, 8, 8, 0, 0, 8
100 unsigned
101 nv50_inst_min_size(struct nv_instruction *i)
103 int n;
105 if (nv50_inst_min_size_tab[i->opcode] > 4)
106 return 8;
108 if (i->def[0] && i->def[0]->reg.file != NV_FILE_GPR)
109 return 8;
110 if (i->def[0]->join->reg.id > 63)
111 return 8;
113 for (n = 0; n < 3; ++n) {
114 if (!i->src[n])
115 break;
116 if (i->src[n]->value->reg.file != NV_FILE_GPR &&
117 i->src[n]->value->reg.file != NV_FILE_MEM_V)
118 return 8;
119 if (i->src[n]->value->reg.id > 63)
120 return 8;
123 if (i->flags_def || i->flags_src || i->src[4])
124 return 8;
126 if (i->is_join)
127 return 8;
129 if (i->src[2]) {
130 if (i->saturate || i->src[2]->mod)
131 return 8;
132 if (i->src[0]->mod ^ i->src[1]->mod)
133 return 8;
134 if ((i->src[0]->mod | i->src[1]->mod) & NV_MOD_ABS)
135 return 8;
136 if (i->def[0]->join->reg.id < 0 ||
137 i->def[0]->join->reg.id != i->src[2]->value->join->reg.id)
138 return 8;
141 return nv50_inst_min_size_tab[i->opcode];
144 static INLINE ubyte
145 STYPE(struct nv_instruction *nvi, int s)
147 return nvi->src[s]->typecast;
150 static INLINE ubyte
151 DTYPE(struct nv_instruction *nvi, int d)
153 return nvi->def[d]->reg.type;
156 static INLINE struct nv_reg *
157 SREG(struct nv_ref *ref)
159 return &ref->value->join->reg;
162 static INLINE struct nv_reg *
163 DREG(struct nv_value *val)
165 return &val->join->reg;
168 static INLINE ubyte
169 SFILE(struct nv_instruction *nvi, int s)
171 return nvi->src[s]->value->reg.file;
174 static INLINE ubyte
175 DFILE(struct nv_instruction *nvi, int d)
177 return nvi->def[0]->reg.file;
180 static INLINE void
181 SID(struct nv_pc *pc, struct nv_ref *ref, int pos)
183 pc->emit[pos / 32] |= SREG(ref)->id << (pos % 32);
186 static INLINE void
187 DID(struct nv_pc *pc, struct nv_value *val, int pos)
189 pc->emit[pos / 32] |= DREG(val)->id << (pos % 32);
192 static INLINE uint32_t
193 get_immd_u32(struct nv_ref *ref)
195 assert(ref->value->reg.file == NV_FILE_IMM);
196 return ref->value->reg.imm.u32;
199 static INLINE void
200 set_immd_u32(struct nv_pc *pc, uint32_t u32)
202 pc->emit[1] |= 3;
203 pc->emit[0] |= (u32 & 0x3f) << 16;
204 pc->emit[1] |= (u32 >> 6) << 2;
207 static INLINE void
208 set_immd(struct nv_pc *pc, struct nv_ref *ref)
210 assert(ref->value->reg.file == NV_FILE_IMM);
211 set_immd_u32(pc, get_immd_u32(ref));
214 /* Allocate data in immediate buffer, if we want to load the immediate
215 * for a constant buffer instead of inlining it into the code.
217 static void
218 nv_pc_alloc_immd(struct nv_pc *pc, struct nv_ref *ref)
220 uint32_t i, val = get_immd_u32(ref);
222 for (i = 0; i < pc->immd_count; ++i)
223 if (pc->immd_buf[i] == val)
224 break;
226 if (i == pc->immd_count) {
227 if (!(pc->immd_count % 8))
228 pc->immd_buf = REALLOC(pc->immd_buf,
229 pc->immd_count * 4, (pc->immd_count + 8) * 4);
230 pc->immd_buf[pc->immd_count++] = val;
233 SREG(ref)->id = i;
236 static INLINE void
237 set_pred(struct nv_pc *pc, struct nv_instruction *i)
239 assert(!(pc->emit[1] & 0x00003f80));
241 pc->emit[1] |= i->cc << 7;
242 if (i->flags_src)
243 pc->emit[1] |= SREG(i->flags_src)->id << 12;
246 static INLINE void
247 set_pred_wr(struct nv_pc *pc, struct nv_instruction *i)
249 assert(!(pc->emit[1] & 0x00000070));
251 if (i->flags_def)
252 pc->emit[1] |= (DREG(i->flags_def)->id << 4) | 0x40;
255 static INLINE void
256 set_a16_bits(struct nv_pc *pc, uint id)
258 ++id; /* $a0 is always 0 */
259 pc->emit[0] |= (id & 3) << 26;
260 pc->emit[1] |= id & 4;
263 static INLINE void
264 set_addr(struct nv_pc *pc, struct nv_instruction *i)
266 if (i->src[4])
267 set_a16_bits(pc, SREG(i->src[4])->id);
270 static void
271 set_dst(struct nv_pc *pc, struct nv_value *value)
273 struct nv_reg *reg = &value->join->reg;
275 if (reg->id < 0) {
276 pc->emit[0] |= (127 << 2) | 1; /* set 'long'-bit to catch bugs */
277 pc->emit[1] |= 0x8;
278 return;
281 if (reg->file == NV_FILE_OUT)
282 pc->emit[1] |= 0x8;
283 else
284 if (reg->file == NV_FILE_ADDR)
285 assert(0);
287 pc->emit[0] |= reg->id << 2;
290 static void
291 set_src_0(struct nv_pc *pc, struct nv_ref *ref)
293 struct nv_reg *reg = SREG(ref);
295 if (reg->file == NV_FILE_MEM_S)
296 pc->emit[1] |= 0x00200000;
297 else
298 if (reg->file == NV_FILE_MEM_P)
299 pc->emit[0] |= 0x01800000;
300 else
301 if (reg->file != NV_FILE_GPR)
302 NOUVEAU_ERR("invalid src0 register file: %d\n", reg->file);
304 assert(reg->id < 128);
305 pc->emit[0] |= reg->id << 9;
308 static void
309 set_src_1(struct nv_pc *pc, struct nv_ref *ref)
311 struct nv_reg *reg = SREG(ref);
313 if (reg->file >= NV_FILE_MEM_C(0) &&
314 reg->file <= NV_FILE_MEM_C(15)) {
315 assert(!(pc->emit[1] & 0x01800000));
317 pc->emit[0] |= 0x00800000;
318 pc->emit[1] |= (reg->file - NV_FILE_MEM_C(0)) << 22;
319 } else
320 if (reg->file != NV_FILE_GPR)
321 NOUVEAU_ERR("invalid src1 register file: %d\n", reg->file);
323 assert(reg->id < 128);
324 pc->emit[0] |= reg->id << 16;
327 static void
328 set_src_2(struct nv_pc *pc, struct nv_ref *ref)
330 struct nv_reg *reg = SREG(ref);
332 if (reg->file >= NV_FILE_MEM_C(0) &&
333 reg->file <= NV_FILE_MEM_C(15)) {
334 assert(!(pc->emit[1] & 0x01800000));
336 pc->emit[0] |= 0x01000000;
337 pc->emit[1] |= (reg->file - NV_FILE_MEM_C(0)) << 22;
338 } else
339 if (reg->file != NV_FILE_GPR)
340 NOUVEAU_ERR("invalid src2 register file: %d\n", reg->file);
342 assert(reg->id < 128);
343 pc->emit[1] |= reg->id << 14;
346 /* the default form:
347 * - long instruction
348 * - 1 to 3 sources in slots 0, 1, 2
349 * - address & flags
351 static void
352 emit_form_MAD(struct nv_pc *pc, struct nv_instruction *i)
354 pc->emit[0] |= 1;
356 set_pred(pc, i);
357 set_pred_wr(pc, i);
359 if (i->def[0])
360 set_dst(pc, i->def[0]);
361 else {
362 pc->emit[0] |= 0x01fc;
363 pc->emit[1] |= 0x0008;
366 if (i->src[0])
367 set_src_0(pc, i->src[0]);
369 if (i->src[1])
370 set_src_1(pc, i->src[1]);
372 if (i->src[2])
373 set_src_2(pc, i->src[2]);
375 set_addr(pc, i);
378 /* like default form, but 2nd source in slot 2, no 3rd source */
379 static void
380 emit_form_ADD(struct nv_pc *pc, struct nv_instruction *i)
382 pc->emit[0] |= 1;
384 if (i->def[0])
385 set_dst(pc, i->def[0]);
386 else {
387 pc->emit[0] |= 0x01fc;
388 pc->emit[1] |= 0x0008;
391 set_pred(pc, i);
392 set_pred_wr(pc, i);
394 if (i->src[0])
395 set_src_0(pc, i->src[0]);
397 if (i->src[1])
398 set_src_2(pc, i->src[1]);
400 set_addr(pc, i);
403 /* short mul */
404 static void
405 emit_form_MUL(struct nv_pc *pc, struct nv_instruction *i)
407 assert(!i->is_long && !(pc->emit[0] & 1));
409 assert(i->def[0]);
410 set_dst(pc, i->def[0]);
412 if (i->src[0])
413 set_src_0(pc, i->src[0]);
415 if (i->src[1])
416 set_src_1(pc, i->src[1]);
419 /* default immediate form
420 * - 1 to 3 sources where last is immediate
421 * - no address or predicate possible
423 static void
424 emit_form_IMM(struct nv_pc *pc, struct nv_instruction *i, ubyte mod_mask)
426 pc->emit[0] |= 1;
428 assert(i->def[0]);
429 assert(i->src[0]);
430 set_dst(pc, i->def[0]);
432 assert(!i->src[4] && !i->flags_src && !i->flags_def);
434 if (i->src[2]) {
435 set_immd(pc, i->src[2]);
436 set_src_0(pc, i->src[1]);
437 set_src_1(pc, i->src[0]);
438 } else
439 if (i->src[1]) {
440 set_immd(pc, i->src[1]);
441 set_src_0(pc, i->src[0]);
442 } else
443 set_immd(pc, i->src[0]);
445 assert(!mod_mask);
448 static void
449 set_ld_st_size(struct nv_pc *pc, int s, ubyte type)
451 switch (type) {
452 case NV_TYPE_F64:
453 pc->emit[1] |= 0x8000 << s;
454 break;
455 case NV_TYPE_F32:
456 case NV_TYPE_S32:
457 case NV_TYPE_U32:
458 pc->emit[1] |= 0xc000 << s;
459 break;
460 case NV_TYPE_S16:
461 pc->emit[1] |= 0x6000 << s;
462 break;
463 case NV_TYPE_U16:
464 pc->emit[1] |= 0x4000 << s;
465 break;
466 case NV_TYPE_S8:
467 pc->emit[1] |= 0x2000 << s;
468 break;
469 default:
470 break;
474 static void
475 emit_ld(struct nv_pc *pc, struct nv_instruction *i)
477 ubyte sf = SFILE(i, 0);
479 if (sf == NV_FILE_IMM) {
480 sf = NV_FILE_MEM_C(0);
481 nv_pc_alloc_immd(pc, i->src[0]);
483 new_fixup(pc, NV50_FIXUP_DATA_RELOC, 0, SREG(i->src[0])->id, 0xffff, 9);
486 if (sf == NV_FILE_MEM_S ||
487 sf == NV_FILE_MEM_P) {
488 pc->emit[0] = 0x10000001;
489 pc->emit[1] = 0x04200000 | (0x3c << 12);
490 if (sf == NV_FILE_MEM_P)
491 pc->emit[0] |= 0x01800000;
492 } else
493 if (sf >= NV_FILE_MEM_C(0) &&
494 sf <= NV_FILE_MEM_C(15)) {
495 pc->emit[0] = 0x10000001;
496 pc->emit[1] = 0x24000000;
497 pc->emit[1] |= (sf - NV_FILE_MEM_C(0)) << 22;
498 } else
499 if (sf >= NV_FILE_MEM_G(0) &&
500 sf <= NV_FILE_MEM_G(15)) {
501 pc->emit[0] = 0xd0000001 | ((sf - NV_FILE_MEM_G(0)) << 16);
502 pc->emit[1] = 0xa0000000;
504 assert(i->src[4] && SREG(i->src[4])->file == NV_FILE_GPR);
505 SID(pc, i->src[4], 9);
506 } else
507 if (sf == NV_FILE_MEM_L) {
508 pc->emit[0] = 0xd0000001;
509 pc->emit[1] = 0x40000000;
511 set_addr(pc, i);
512 } else {
513 NOUVEAU_ERR("invalid ld source file\n");
514 abort();
517 set_ld_st_size(pc, (sf == NV_FILE_MEM_L) ? 8 : 0, STYPE(i, 0));
519 set_dst(pc, i->def[0]);
520 set_pred_wr(pc, i);
522 set_pred(pc, i);
524 if (sf < NV_FILE_MEM_G(0) ||
525 sf > NV_FILE_MEM_G(15)) {
526 SID(pc, i->src[0], 9);
527 set_addr(pc, i);
531 static void
532 emit_st(struct nv_pc *pc, struct nv_instruction *i)
534 assert(SFILE(i, 1) == NV_FILE_GPR);
535 assert(SFILE(i, 0) == NV_FILE_MEM_L);
537 pc->emit[0] = 0xd0000001;
538 pc->emit[1] = 0x60000000;
540 SID(pc, i->src[1], 2);
541 SID(pc, i->src[0], 9);
543 set_ld_st_size(pc, 8, STYPE(i, 1));
545 set_addr(pc, i);
546 set_pred(pc, i);
549 static int
550 verify_mov(struct nv_instruction *i)
552 ubyte sf = SFILE(i, 0);
553 ubyte df = DFILE(i, 0);
555 if (df == NV_FILE_GPR)
556 return 0;
558 if (df != NV_FILE_OUT &&
559 df != NV_FILE_FLAGS &&
560 df != NV_FILE_ADDR)
561 return 1;
563 if (sf == NV_FILE_FLAGS)
564 return 2;
565 if (sf == NV_FILE_ADDR)
566 return 3;
567 if (sf == NV_FILE_IMM && df != NV_FILE_OUT)
568 return 4;
570 return 0;
573 static void
574 emit_mov(struct nv_pc *pc, struct nv_instruction *i)
576 assert(!verify_mov(i));
578 if (SFILE(i, 0) >= NV_FILE_MEM_S)
579 emit_ld(pc, i);
580 else
581 if (SFILE(i, 0) == NV_FILE_FLAGS) {
582 pc->emit[0] = 0x00000001 | (DREG(i->def[0])->id << 2);
583 pc->emit[1] = 0x20000780 | (SREG(i->src[0])->id << 12);
584 } else
585 if (SFILE(i, 0) == NV_FILE_ADDR) {
586 pc->emit[0] = 0x00000001 | (DREG(i->def[0])->id << 2);
587 pc->emit[1] = 0x40000780;
588 set_a16_bits(pc, SREG(i->src[0])->id);
589 } else
590 if (DFILE(i, 0) == NV_FILE_FLAGS) {
591 pc->emit[0] = 0x00000001;
592 pc->emit[1] = 0xa0000000 | (1 << 6);
593 set_pred(pc, i);
594 pc->emit[0] |= SREG(i->src[0])->id << 9;
595 pc->emit[1] |= DREG(i->def[0])->id << 4;
596 } else
597 if (SFILE(i, 0) == NV_FILE_IMM) {
598 if (i->opcode == NV_OP_LDA) {
599 emit_ld(pc, i);
600 } else {
601 pc->emit[0] = 0x10008001;
602 pc->emit[1] = 0x00000003;
604 emit_form_IMM(pc, i, 0);
606 } else {
607 pc->emit[0] = 0x10000000;
608 pc->emit[0] |= DREG(i->def[0])->id << 2;
609 pc->emit[0] |= SREG(i->src[0])->id << 9;
611 if (!i->is_long) {
612 pc->emit[0] |= 0x8000;
613 } else {
614 pc->emit[0] |= 0x00000001;
615 pc->emit[1] = 0x0403c000;
617 set_pred(pc, i);
621 if (DFILE(i, 0) == NV_FILE_OUT)
622 pc->emit[1] |= 0x8;
625 static void
626 emit_interp(struct nv_pc *pc, struct nv_instruction *i)
628 pc->emit[0] = 0x80000000;
630 assert(DFILE(i, 0) == NV_FILE_GPR);
631 assert(SFILE(i, 0) == NV_FILE_MEM_V);
633 DID(pc, i->def[0], 2);
634 SID(pc, i->src[0], 16);
636 if (i->flat)
637 pc->emit[0] |= 1 << 8;
638 else
639 if (i->opcode == NV_OP_PINTERP) {
640 pc->emit[0] |= 1 << 25;
641 pc->emit[0] |= SREG(i->src[1])->id << 9;
644 if (i->centroid)
645 pc->emit[0] |= 1 << 24;
647 assert(i->is_long || !i->flags_src);
649 if (i->is_long) {
650 set_pred(pc, i);
652 pc->emit[1] |=
653 (pc->emit[0] & (3 << 24)) >> (24 - 16) |
654 (pc->emit[0] & (1 << 8)) >> (18 - 8);
656 pc->emit[0] |= 1;
657 pc->emit[0] &= ~0x03000100;
661 static void
662 emit_minmax(struct nv_pc *pc, struct nv_instruction *i)
664 pc->emit[0] = 0x30000000;
665 pc->emit[1] = (i->opcode == NV_OP_MIN) ? (2 << 28) : 0;
667 switch (DTYPE(i, 0)) {
668 case NV_TYPE_F32:
669 pc->emit[0] |= 0x80000000;
670 pc->emit[1] |= 0x80000000;
671 break;
672 case NV_TYPE_S32:
673 pc->emit[1] |= 0x8c000000;
674 break;
675 case NV_TYPE_U32:
676 pc->emit[1] |= 0x84000000;
677 break;
680 emit_form_MAD(pc, i);
682 if (i->src[0]->mod & NV_MOD_ABS) pc->emit[1] |= 0x00100000;
683 if (i->src[1]->mod & NV_MOD_ABS) pc->emit[1] |= 0x00080000;
686 static void
687 emit_add_f32(struct nv_pc *pc, struct nv_instruction *i)
689 pc->emit[0] = 0xb0000000;
691 assert(!((i->src[0]->mod | i->src[1]->mod) & NV_MOD_ABS));
693 if (SFILE(i, 1) == NV_FILE_IMM) {
694 emit_form_IMM(pc, i, 0);
696 if (i->src[0]->mod & NV_MOD_NEG) pc->emit[0] |= 0x8000;
697 if (i->src[1]->mod & NV_MOD_NEG) pc->emit[0] |= 1 << 22;
698 } else
699 if (i->is_long) {
700 emit_form_ADD(pc, i);
702 if (i->src[0]->mod & NV_MOD_NEG) pc->emit[1] |= 1 << 26;
703 if (i->src[1]->mod & NV_MOD_NEG) pc->emit[1] |= 1 << 27;
705 if (i->saturate)
706 pc->emit[1] |= 0x20000000;
707 } else {
708 emit_form_MUL(pc, i);
710 if (i->src[0]->mod & NV_MOD_NEG) pc->emit[0] |= 0x8000;
711 if (i->src[1]->mod & NV_MOD_NEG) pc->emit[0] |= 1 << 22;
715 static void
716 emit_add_b32(struct nv_pc *pc, struct nv_instruction *i)
718 pc->emit[0] = 0x20008000;
720 if (SFILE(i, 1) == NV_FILE_IMM) {
721 emit_form_IMM(pc, i, 0);
722 } else
723 if (i->is_long) {
724 pc->emit[0] = 0x20000000;
725 pc->emit[1] = 0x04000000;
726 emit_form_ADD(pc, i);
727 } else {
728 emit_form_MUL(pc, i);
731 if (i->src[0]->mod & NV_MOD_NEG) pc->emit[0] |= 1 << 28;
732 if (i->src[1]->mod & NV_MOD_NEG) pc->emit[0] |= 1 << 22;
735 static void
736 emit_add_a16(struct nv_pc *pc, struct nv_instruction *i)
738 int s = (i->opcode == NV_OP_MOV) ? 0 : 1;
740 pc->emit[0] = 0xd0000001 | ((uint16_t)get_immd_u32(i->src[s]) << 9);
741 pc->emit[1] = 0x20000000;
743 pc->emit[0] |= (DREG(i->def[0])->id + 1) << 2;
745 set_pred(pc, i);
747 if (s && i->src[0])
748 set_a16_bits(pc, SREG(i->src[0])->id);
751 static void
752 emit_flow(struct nv_pc *pc, struct nv_instruction *i, ubyte flow_op)
754 pc->emit[0] = 0x00000003 | (flow_op << 28);
755 pc->emit[1] = 0x00000000;
757 set_pred(pc, i);
759 if (i->target && (i->opcode != NV_OP_BREAK)) {
760 uint32_t pos = i->target->bin_pos;
762 new_fixup(pc, NV50_FIXUP_CODE_RELOC, 0, pos, 0xffff << 11, 9);
763 new_fixup(pc, NV50_FIXUP_CODE_RELOC, 1, pos, 0x3f << 14, -4);
765 pc->emit[0] |= ((pos >> 2) & 0xffff) << 11;
766 pc->emit[1] |= ((pos >> 18) & 0x003f) << 14;
770 static INLINE void
771 emit_add(struct nv_pc *pc, struct nv_instruction *i)
773 if (DFILE(i, 0) == NV_FILE_ADDR)
774 emit_add_a16(pc, i);
775 else {
776 switch (DTYPE(i, 0)) {
777 case NV_TYPE_F32:
778 emit_add_f32(pc, i);
779 break;
780 case NV_TYPE_U32:
781 case NV_TYPE_S32:
782 emit_add_b32(pc, i);
783 break;
788 static void
789 emit_bitop2(struct nv_pc *pc, struct nv_instruction *i)
791 pc->emit[0] = 0xd0000000;
793 if (SFILE(i, 1) == NV_FILE_IMM) {
794 emit_form_IMM(pc, i, 0);
796 if (i->opcode == NV_OP_OR)
797 pc->emit[0] |= 0x0100;
798 else
799 if (i->opcode == NV_OP_XOR)
800 pc->emit[0] |= 0x8000;
801 } else {
802 emit_form_MAD(pc, i);
804 pc->emit[1] |= 0x04000000;
806 if (i->opcode == NV_OP_OR)
807 pc->emit[1] |= 0x4000;
808 else
809 if (i->opcode == NV_OP_XOR)
810 pc->emit[1] |= 0x8000;
814 static void
815 emit_arl(struct nv_pc *pc, struct nv_instruction *i)
817 assert(SFILE(i, 0) == NV_FILE_GPR);
818 assert(SFILE(i, 1) == NV_FILE_IMM);
820 assert(!i->flags_def);
822 pc->emit[0] = 0x00000001;
823 pc->emit[1] = 0xc0000000;
825 pc->emit[0] |= (i->def[0]->reg.id + 1) << 2;
826 set_pred(pc, i);
827 set_src_0(pc, i->src[0]);
828 pc->emit[0] |= (get_immd_u32(i->src[1]) & 0x3f) << 16;
831 static void
832 emit_shift(struct nv_pc *pc, struct nv_instruction *i)
834 if (DFILE(i, 0) == NV_FILE_ADDR) {
835 emit_arl(pc, i);
836 return;
839 pc->emit[0] = 0x30000001;
840 pc->emit[1] = 0xc4000000;
842 if (i->opcode == NV_OP_SHR)
843 pc->emit[1] |= 1 << 29;
845 if (SFILE(i, 1) == NV_FILE_IMM) {
846 pc->emit[1] |= 1 << 20;
847 pc->emit[0] |= (get_immd_u32(i->src[1]) & 0x7f) << 16;
849 set_pred(pc, i);
850 } else
851 emit_form_MAD(pc, i);
853 if (STYPE(i, 0) == NV_TYPE_S32)
854 pc->emit[1] |= 1 << 27;
857 static void
858 emit_flop(struct nv_pc *pc, struct nv_instruction *i)
860 struct nv_ref *src0 = i->src[0];
862 pc->emit[0] = 0x90000000;
864 assert(STYPE(i, 0) == NV_TYPE_F32);
865 assert(SFILE(i, 0) == NV_FILE_GPR);
867 if (!i->is_long) {
868 emit_form_MUL(pc, i);
869 assert(i->opcode == NV_OP_RCP && !src0->mod);
870 return;
873 pc->emit[1] = (i->opcode - NV_OP_RCP) << 29;
875 emit_form_MAD(pc, i);
877 if (src0->mod & NV_MOD_NEG) pc->emit[1] |= 0x04000000;
878 if (src0->mod & NV_MOD_ABS) pc->emit[1] |= 0x00100000;
881 static void
882 emit_mad_f32(struct nv_pc *pc, struct nv_instruction *i)
884 const boolean neg_mul = (i->src[0]->mod ^ i->src[1]->mod) & NV_MOD_NEG;
885 const boolean neg_add = (i->src[2]->mod & NV_MOD_NEG);
887 pc->emit[0] = 0xe0000000;
889 if (!i->is_long) {
890 emit_form_MUL(pc, i);
891 assert(!neg_mul && !neg_add);
892 return;
895 emit_form_MAD(pc, i);
897 if (neg_mul) pc->emit[1] |= 0x04000000;
898 if (neg_add) pc->emit[1] |= 0x08000000;
900 if (i->saturate)
901 pc->emit[1] |= 0x20000000;
904 static INLINE void
905 emit_mad(struct nv_pc *pc, struct nv_instruction *i)
907 emit_mad_f32(pc, i);
910 static void
911 emit_mul_f32(struct nv_pc *pc, struct nv_instruction *i)
913 boolean neg = (i->src[0]->mod ^ i->src[1]->mod) & NV_MOD_NEG;
915 pc->emit[0] = 0xc0000000;
917 if (SFILE(i, 1) == NV_FILE_IMM) {
918 emit_form_IMM(pc, i, 0);
920 if (neg)
921 pc->emit[0] |= 0x8000;
922 } else
923 if (i->is_long) {
924 emit_form_MAD(pc, i);
926 if (neg)
927 pc->emit[1] |= 0x08 << 24;
928 } else {
929 emit_form_MUL(pc, i);
931 if (neg)
932 pc->emit[0] |= 0x8000;
936 static void
937 emit_set(struct nv_pc *pc, struct nv_instruction *nvi)
939 assert(nvi->is_long);
941 pc->emit[0] = 0x30000000;
942 pc->emit[1] = 0x60000000;
944 pc->emit[1] |= nvi->set_cond << 14;
946 switch (STYPE(nvi, 0)) {
947 case NV_TYPE_U32: pc->emit[1] |= 0x04000000; break;
948 case NV_TYPE_S32: pc->emit[1] |= 0x0c000000; break;
949 case NV_TYPE_F32: pc->emit[0] |= 0x80000000; break;
950 default:
951 assert(0);
952 break;
955 emit_form_MAD(pc, nvi);
958 #define CVT_RN (0x00 << 16)
959 #define CVT_FLOOR (0x02 << 16)
960 #define CVT_CEIL (0x04 << 16)
961 #define CVT_TRUNC (0x06 << 16)
962 #define CVT_SAT (0x08 << 16)
963 #define CVT_ABS (0x10 << 16)
965 #define CVT_X32_X32 0x04004000
966 #define CVT_X32_S32 0x04014000
967 #define CVT_F32_F32 ((0xc0 << 24) | CVT_X32_X32)
968 #define CVT_S32_F32 ((0x88 << 24) | CVT_X32_X32)
969 #define CVT_U32_F32 ((0x80 << 24) | CVT_X32_X32)
970 #define CVT_F32_S32 ((0x40 << 24) | CVT_X32_S32)
971 #define CVT_F32_U32 ((0x40 << 24) | CVT_X32_X32)
972 #define CVT_S32_S32 ((0x08 << 24) | CVT_X32_S32)
973 #define CVT_S32_U32 ((0x08 << 24) | CVT_X32_X32)
974 #define CVT_U32_S32 ((0x00 << 24) | CVT_X32_S32)
975 #define CVT_U32_U32 ((0x00 << 24) | CVT_X32_X32)
977 #define CVT_NEG 0x20000000
978 #define CVT_RI 0x08000000
980 static void
981 emit_cvt(struct nv_pc *pc, struct nv_instruction *nvi)
983 ubyte dst_type = nvi->def[0] ? DTYPE(nvi, 0) : STYPE(nvi, 0);
985 pc->emit[0] = 0xa0000000;
987 switch (dst_type) {
988 case NV_TYPE_F32:
989 switch (STYPE(nvi, 0)) {
990 case NV_TYPE_F32: pc->emit[1] = CVT_F32_F32; break;
991 case NV_TYPE_S32: pc->emit[1] = CVT_F32_S32; break;
992 case NV_TYPE_U32: pc->emit[1] = CVT_F32_U32; break;
994 break;
995 case NV_TYPE_S32:
996 switch (STYPE(nvi, 0)) {
997 case NV_TYPE_F32: pc->emit[1] = CVT_S32_F32; break;
998 case NV_TYPE_S32: pc->emit[1] = CVT_S32_S32; break;
999 case NV_TYPE_U32: pc->emit[1] = CVT_S32_U32; break;
1001 break;
1002 case NV_TYPE_U32:
1003 switch (STYPE(nvi, 0)) {
1004 case NV_TYPE_F32: pc->emit[1] = CVT_U32_F32; break;
1005 case NV_TYPE_S32: pc->emit[1] = CVT_U32_S32; break;
1006 case NV_TYPE_U32: pc->emit[1] = CVT_U32_U32; break;
1008 break;
1010 if (pc->emit[1] == CVT_F32_F32 &&
1011 (nvi->opcode == NV_OP_CEIL || nvi->opcode == NV_OP_FLOOR ||
1012 nvi->opcode == NV_OP_TRUNC))
1013 pc->emit[1] |= CVT_RI;
1015 switch (nvi->opcode) {
1016 case NV_OP_CEIL: pc->emit[1] |= CVT_CEIL; break;
1017 case NV_OP_FLOOR: pc->emit[1] |= CVT_FLOOR; break;
1018 case NV_OP_TRUNC: pc->emit[1] |= CVT_TRUNC; break;
1020 case NV_OP_ABS: pc->emit[1] |= CVT_ABS; break;
1021 case NV_OP_SAT: pc->emit[1] |= CVT_SAT; break;
1022 case NV_OP_NEG: pc->emit[1] |= CVT_NEG; break;
1023 default:
1024 assert(nvi->opcode == NV_OP_CVT);
1025 break;
1027 assert(nvi->opcode != NV_OP_ABS || !(nvi->src[0]->mod & NV_MOD_NEG));
1029 if (nvi->src[0]->mod & NV_MOD_NEG) pc->emit[1] ^= CVT_NEG;
1030 if (nvi->src[0]->mod & NV_MOD_ABS) pc->emit[1] |= CVT_ABS;
1032 emit_form_MAD(pc, nvi);
1035 static void
1036 emit_tex(struct nv_pc *pc, struct nv_instruction *i)
1038 pc->emit[0] = 0xf0000001;
1039 pc->emit[1] = 0x00000000;
1041 DID(pc, i->def[0], 2);
1043 set_pred(pc, i);
1045 pc->emit[0] |= i->tex_t << 9;
1046 pc->emit[0] |= i->tex_s << 17;
1048 pc->emit[0] |= (i->tex_argc - 1) << 22;
1050 pc->emit[0] |= (i->tex_mask & 0x3) << 25;
1051 pc->emit[1] |= (i->tex_mask & 0xc) << 12;
1053 if (i->tex_live)
1054 pc->emit[1] |= 4;
1056 if (i->tex_cube)
1057 pc->emit[0] |= 0x08000000;
1059 if (i->opcode == NV_OP_TXB)
1060 pc->emit[1] |= 0x20000000;
1061 else
1062 if (i->opcode == NV_OP_TXL)
1063 pc->emit[1] |= 0x40000000;
1066 static void
1067 emit_cvt2fixed(struct nv_pc *pc, struct nv_instruction *i)
1069 ubyte mod = i->src[0]->mod;
1071 pc->emit[0] = 0xb0000000;
1072 pc->emit[1] = 0xc0000000;
1074 if (i->opcode == NV_OP_PREEX2)
1075 pc->emit[1] |= 0x4000;
1077 emit_form_MAD(pc, i);
1079 if (mod & NV_MOD_NEG) pc->emit[1] |= 0x04000000;
1080 if (mod & NV_MOD_ABS) pc->emit[1] |= 0x00100000;
1083 static void
1084 emit_ddx(struct nv_pc *pc, struct nv_instruction *i)
1086 assert(i->is_long && SFILE(i, 0) == NV_FILE_GPR);
1088 pc->emit[0] = (i->src[0]->mod & NV_MOD_NEG) ? 0xc0240001 : 0xc0140001;
1089 pc->emit[1] = (i->src[0]->mod & NV_MOD_NEG) ? 0x86400000 : 0x89800000;
1091 DID(pc, i->def[0], 2);
1092 SID(pc, i->src[0], 9);
1093 SID(pc, i->src[0], 32 + 14);
1095 set_pred(pc, i);
1096 set_pred_wr(pc, i);
1099 static void
1100 emit_ddy(struct nv_pc *pc, struct nv_instruction *i)
1102 assert(i->is_long && SFILE(i, 0) == NV_FILE_GPR);
1104 pc->emit[0] = (i->src[0]->mod & NV_MOD_NEG) ? 0xc0250001 : 0xc0150001;
1105 pc->emit[1] = (i->src[0]->mod & NV_MOD_NEG) ? 0x85800000 : 0x8a400000;
1107 DID(pc, i->def[0], 2);
1108 SID(pc, i->src[0], 9);
1109 SID(pc, i->src[0], 32 + 14);
1111 set_pred(pc, i);
1112 set_pred_wr(pc, i);
1115 static void
1116 emit_quadop(struct nv_pc *pc, struct nv_instruction *i)
1118 pc->emit[0] = 0xc0000000;
1119 pc->emit[1] = 0x80000000;
1121 emit_form_ADD(pc, i);
1123 pc->emit[0] |= i->lanes << 16;
1125 pc->emit[0] |= (i->quadop & 0x03) << 20;
1126 pc->emit[1] |= (i->quadop & 0xfc) << 20;
1129 void
1130 nv50_emit_instruction(struct nv_pc *pc, struct nv_instruction *i)
1132 /* nv_print_instruction(i); */
1134 switch (i->opcode) {
1135 case NV_OP_MOV:
1136 if (DFILE(i, 0) == NV_FILE_ADDR)
1137 emit_add_a16(pc, i);
1138 else
1139 emit_mov(pc, i);
1140 break;
1141 case NV_OP_LDA:
1142 emit_mov(pc, i);
1143 break;
1144 case NV_OP_STA:
1145 emit_st(pc, i);
1146 break;
1147 case NV_OP_LINTERP:
1148 case NV_OP_PINTERP:
1149 emit_interp(pc, i);
1150 break;
1151 case NV_OP_ADD:
1152 emit_add(pc, i);
1153 break;
1154 case NV_OP_AND:
1155 case NV_OP_OR:
1156 case NV_OP_XOR:
1157 emit_bitop2(pc, i);
1158 break;
1159 case NV_OP_CVT:
1160 case NV_OP_ABS:
1161 case NV_OP_NEG:
1162 case NV_OP_SAT:
1163 case NV_OP_CEIL:
1164 case NV_OP_FLOOR:
1165 case NV_OP_TRUNC:
1166 emit_cvt(pc, i);
1167 break;
1168 case NV_OP_DFDX:
1169 emit_ddx(pc, i);
1170 break;
1171 case NV_OP_DFDY:
1172 emit_ddy(pc, i);
1173 break;
1174 case NV_OP_RCP:
1175 case NV_OP_RSQ:
1176 case NV_OP_LG2:
1177 case NV_OP_SIN:
1178 case NV_OP_COS:
1179 case NV_OP_EX2:
1180 emit_flop(pc, i);
1181 break;
1182 case NV_OP_PRESIN:
1183 case NV_OP_PREEX2:
1184 emit_cvt2fixed(pc, i);
1185 break;
1186 case NV_OP_MAD:
1187 emit_mad(pc, i);
1188 break;
1189 case NV_OP_MAX:
1190 case NV_OP_MIN:
1191 emit_minmax(pc, i);
1192 break;
1193 case NV_OP_MUL:
1194 emit_mul_f32(pc, i);
1195 break;
1196 case NV_OP_SET:
1197 emit_set(pc, i);
1198 break;
1199 case NV_OP_SHL:
1200 case NV_OP_SHR:
1201 emit_shift(pc, i);
1202 break;
1203 case NV_OP_TEX:
1204 case NV_OP_TXB:
1205 case NV_OP_TXL:
1206 emit_tex(pc, i);
1207 break;
1208 case NV_OP_QUADOP:
1209 emit_quadop(pc, i);
1210 break;
1211 case NV_OP_KIL:
1212 emit_flow(pc, i, 0x0);
1213 break;
1214 case NV_OP_BRA:
1215 emit_flow(pc, i, 0x1);
1216 break;
1217 case NV_OP_CALL:
1218 emit_flow(pc, i, 0x2);
1219 break;
1220 case NV_OP_RET:
1221 emit_flow(pc, i, 0x3);
1222 break;
1223 case NV_OP_BREAKADDR:
1224 emit_flow(pc, i, 0x4);
1225 break;
1226 case NV_OP_BREAK:
1227 emit_flow(pc, i, 0x5);
1228 break;
1229 case NV_OP_JOINAT:
1230 emit_flow(pc, i, 0xa);
1231 break;
1232 case NV_OP_NOP:
1233 case NV_OP_JOIN:
1234 pc->emit[0] = 0xf0000001;
1235 pc->emit[1] = 0xe0000000;
1236 break;
1237 case NV_OP_PHI:
1238 case NV_OP_UNDEF:
1239 case NV_OP_SUB:
1240 NOUVEAU_ERR("operation \"%s\" should have been eliminated\n",
1241 nv_opcode_name(i->opcode));
1242 break;
1243 default:
1244 NOUVEAU_ERR("unhandled NV_OP: %d\n", i->opcode);
1245 abort();
1246 break;
1249 if (i->is_join) {
1250 assert(i->is_long && !(pc->emit[1] & 1));
1251 pc->emit[1] |= 2;
1254 assert((pc->emit[0] & 1) == i->is_long);