nvc0: fix immediate arg for SHL/SHR
[mesa.git] / src / gallium / drivers / nvc0 / nvc0_pc_emit.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 "nvc0_pc.h"
24 #include "nvc0_program.h"
25
26 #define NVC0_FIXUP_CODE_RELOC 0
27 #define NVC0_FIXUP_DATA_RELOC 1
28
29 struct nvc0_fixup {
30 uint8_t type;
31 int8_t shift;
32 uint32_t mask;
33 uint32_t data;
34 uint32_t ofst;
35 };
36
37 void
38 nvc0_relocate_program(struct nvc0_program *prog,
39 uint32_t code_base,
40 uint32_t data_base)
41 {
42 struct nvc0_fixup *f = (struct nvc0_fixup *)prog->relocs;
43 unsigned i;
44
45 for (i = 0; i < prog->num_relocs; ++i) {
46 uint32_t data;
47
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;
54 }
55 data = (f[i].shift < 0) ? (data >> -f[i].shift) : (data << f[i].shift);
56
57 prog->code[f[i].ofst / 4] &= ~f[i].mask;
58 prog->code[f[i].ofst / 4] |= data & f[i].mask;
59 }
60 }
61
62 static void
63 create_fixup(struct nv_pc *pc, uint8_t ty,
64 int w, uint32_t data, uint32_t m, int s)
65 {
66 struct nvc0_fixup *f;
67
68 const unsigned size = sizeof(struct nvc0_fixup);
69 const unsigned n = pc->num_relocs;
70
71 if (!(n % 8))
72 pc->reloc_entries = REALLOC(pc->reloc_entries, n * size, (n + 8) * size);
73
74 f = (struct nvc0_fixup *)pc->reloc_entries;
75
76 f[n].ofst = (pc->emit_pos + w) * 4;
77 f[n].type = ty;
78 f[n].data = data;
79 f[n].mask = m;
80 f[n].shift = s;
81
82 ++pc->num_relocs;
83 }
84
85 static INLINE ubyte
86 SSIZE(struct nv_instruction *nvi, int s)
87 {
88 return nvi->src[s]->value->reg.size;
89 }
90
91 static INLINE ubyte
92 DSIZE(struct nv_instruction *nvi, int d)
93 {
94 return nvi->def[d]->reg.size;
95 }
96
97 static INLINE struct nv_reg *
98 SREG(struct nv_ref *ref)
99 {
100 if (!ref)
101 return NULL;
102 return &ref->value->join->reg;
103 }
104
105 static INLINE struct nv_reg *
106 DREG(struct nv_value *val)
107 {
108 if (!val)
109 return NULL;
110 return &val->join->reg;
111 }
112
113 static INLINE ubyte
114 SFILE(struct nv_instruction *nvi, int s)
115 {
116 return nvi->src[s]->value->reg.file;
117 }
118
119 static INLINE ubyte
120 DFILE(struct nv_instruction *nvi, int d)
121 {
122 return nvi->def[0]->reg.file;
123 }
124
125 static INLINE void
126 SID(struct nv_pc *pc, struct nv_ref *ref, int pos)
127 {
128 pc->emit[pos / 32] |= (SREG(ref) ? SREG(ref)->id : 63) << (pos % 32);
129 }
130
131 static INLINE void
132 DID(struct nv_pc *pc, struct nv_value *val, int pos)
133 {
134 pc->emit[pos / 32] |= (DREG(val) ? DREG(val)->id : 63) << (pos % 32);
135 }
136
137 static INLINE uint32_t
138 get_immd_u32(struct nv_ref *ref) /* XXX: dependent on [0]:2 */
139 {
140 assert(ref->value->reg.file == NV_FILE_IMM);
141 return ref->value->reg.imm.u32;
142 }
143
144 static INLINE void
145 set_immd_u32_l(struct nv_pc *pc, uint32_t u32)
146 {
147 pc->emit[0] |= (u32 & 0x3f) << 26;
148 pc->emit[1] |= u32 >> 6;
149 }
150
151 static INLINE void
152 set_immd_u32(struct nv_pc *pc, uint32_t u32)
153 {
154 if ((pc->emit[0] & 0xf) == 0x2) {
155 set_immd_u32_l(pc, u32);
156 } else
157 if ((pc->emit[0] & 0xf) == 0x3) {
158 assert(!(pc->emit[1] & 0xc000));
159 pc->emit[1] |= 0xc000;
160 assert(!(u32 & 0xfff00000));
161 set_immd_u32_l(pc, u32);
162 } else {
163 assert(!(pc->emit[1] & 0xc000));
164 pc->emit[1] |= 0xc000;
165 assert(!(u32 & 0xfff));
166 set_immd_u32_l(pc, u32 >> 12);
167 }
168 }
169
170 static INLINE void
171 set_immd(struct nv_pc *pc, struct nv_instruction *i, int s)
172 {
173 set_immd_u32(pc, get_immd_u32(i->src[s]));
174 }
175
176 static INLINE void
177 DVS(struct nv_pc *pc, struct nv_instruction *i)
178 {
179 uint s = i->def[0]->reg.size;
180 int n;
181 for (n = 1; n < 4 && i->def[n]; ++n)
182 s += i->def[n]->reg.size;
183 pc->emit[0] |= ((s / 4) - 1) << 5;
184 }
185
186 static INLINE void
187 SVS(struct nv_pc *pc, struct nv_ref *src)
188 {
189 pc->emit[0] |= (SREG(src)->size / 4 - 1) << 5;
190 }
191
192 static void
193 set_pred(struct nv_pc *pc, struct nv_instruction *i)
194 {
195 if (i->predicate >= 0) {
196 SID(pc, i->src[i->predicate], 6);
197 if (i->cc)
198 pc->emit[0] |= 0x2000; /* negate */
199 } else {
200 pc->emit[0] |= 0x1c00;
201 }
202 }
203
204 static INLINE void
205 set_address_16(struct nv_pc *pc, struct nv_ref *src)
206 {
207 pc->emit[0] |= (src->value->reg.address & 0x003f) << 26;
208 pc->emit[1] |= (src->value->reg.address & 0xffc0) >> 6;
209 }
210
211 static INLINE unsigned
212 const_space_index(struct nv_instruction *i, int s)
213 {
214 return SFILE(i, s) - NV_FILE_MEM_C(0);
215 }
216
217 static void
218 emit_flow(struct nv_pc *pc, struct nv_instruction *i, uint8_t op)
219 {
220 pc->emit[0] = 0x000001e7;
221 pc->emit[1] = op << 24;
222
223 set_pred(pc, i);
224
225 if (i->target) {
226 uint32_t pos = i->target->emit_pos;
227
228 create_fixup(pc, NVC0_FIXUP_CODE_RELOC, 0, pos, 26, 0xfc000000);
229 create_fixup(pc, NVC0_FIXUP_CODE_RELOC, 1, pos, -6, 0x0001ffff);
230
231 pc->emit[0] |= (pos & 0x3f) << 26;
232 pc->emit[1] |= (pos >> 6) & 0x1ffff;
233 }
234 }
235
236 /* doesn't work for vfetch, export, ld, st, mov ... */
237 static void
238 emit_form_0(struct nv_pc *pc, struct nv_instruction *i)
239 {
240 int s;
241
242 set_pred(pc, i);
243
244 DID(pc, i->def[0], 14);
245
246 for (s = 0; s < 3 && i->src[s]; ++s) {
247 if (SFILE(i, s) >= NV_FILE_MEM_C(0) &&
248 SFILE(i, s) <= NV_FILE_MEM_C(15)) {
249 assert(!(pc->emit[1] & 0xc000));
250 assert(s <= 1);
251 pc->emit[1] |= 0x4000 | (const_space_index(i, s) << 10);
252 set_address_16(pc, i->src[s]);
253 } else
254 if (SFILE(i, s) == NV_FILE_GPR) {
255 SID(pc, i->src[s], s ? ((s == 2) ? 49 : 26) : 20);
256 } else
257 if (SFILE(i, s) == NV_FILE_IMM) {
258 assert(!(pc->emit[1] & 0xc000));
259 assert(s == 1 || i->opcode == NV_OP_MOV);
260 set_immd(pc, i, s);
261 }
262 }
263 }
264
265 static void
266 emit_form_1(struct nv_pc *pc, struct nv_instruction *i)
267 {
268 int s;
269
270 set_pred(pc, i);
271
272 DID(pc, i->def[0], 14);
273
274 for (s = 0; s < 1 && i->src[s]; ++s) {
275 if (SFILE(i, s) >= NV_FILE_MEM_C(0) &&
276 SFILE(i, s) <= NV_FILE_MEM_C(15)) {
277 assert(!(pc->emit[1] & 0xc000));
278 assert(s <= 1);
279 pc->emit[1] |= 0x4000 | (const_space_index(i, s) << 10);
280 set_address_16(pc, i->src[s]);
281 } else
282 if (SFILE(i, s) == NV_FILE_GPR) {
283 SID(pc, i->src[s], 26);
284 } else
285 if (SFILE(i, s) == NV_FILE_IMM) {
286 assert(!(pc->emit[1] & 0xc000));
287 assert(s == 1 || i->opcode == NV_OP_MOV);
288 set_immd(pc, i, s);
289 }
290 }
291 }
292
293 static void
294 emit_neg_abs_1_2(struct nv_pc *pc, struct nv_instruction *i)
295 {
296 if (i->src[0]->mod & NV_MOD_ABS)
297 pc->emit[0] |= 1 << 7;
298 if (i->src[0]->mod & NV_MOD_NEG)
299 pc->emit[0] |= 1 << 9;
300 if (i->src[1]->mod & NV_MOD_ABS)
301 pc->emit[0] |= 1 << 6;
302 if (i->src[1]->mod & NV_MOD_NEG)
303 pc->emit[0] |= 1 << 8;
304 }
305
306 static void
307 emit_add_f32(struct nv_pc *pc, struct nv_instruction *i)
308 {
309 pc->emit[0] = 0x00000000;
310 pc->emit[1] = 0x50000000;
311
312 emit_form_0(pc, i);
313
314 emit_neg_abs_1_2(pc, i);
315
316 if (i->saturate)
317 pc->emit[1] |= 1 << 17;
318 }
319
320 static void
321 emit_mul_f32(struct nv_pc *pc, struct nv_instruction *i)
322 {
323 pc->emit[0] = 0x00000000;
324 pc->emit[1] = 0x58000000;
325
326 emit_form_0(pc, i);
327
328 if ((i->src[0]->mod ^ i->src[1]->mod) & NV_MOD_NEG)
329 pc->emit[1] |= 1 << 25;
330
331 if (i->saturate)
332 pc->emit[0] |= 1 << 5;
333 }
334
335 static void
336 emit_mad_f32(struct nv_pc *pc, struct nv_instruction *i)
337 {
338 pc->emit[0] = 0x00000000;
339 pc->emit[1] = 0x30000000;
340
341 emit_form_0(pc, i);
342
343 if ((i->src[0]->mod ^ i->src[1]->mod) & NV_MOD_NEG)
344 pc->emit[0] |= 1 << 9;
345
346 if (i->src[2]->mod & NV_MOD_NEG)
347 pc->emit[0] |= 1 << 8;
348
349 if (i->saturate)
350 pc->emit[0] |= 1 << 5;
351 }
352
353 static void
354 emit_minmax(struct nv_pc *pc, struct nv_instruction *i)
355 {
356 pc->emit[0] = 0x00000000;
357 pc->emit[1] = 0x08000000;
358
359 if (NV_BASEOP(i->opcode) == NV_OP_MAX)
360 pc->emit[1] |= 0x001e0000;
361 else
362 pc->emit[1] |= 0x000e0000; /* predicate ? */
363
364 emit_form_0(pc, i);
365
366 emit_neg_abs_1_2(pc, i);
367
368 switch (i->opcode) {
369 case NV_OP_MIN_U32:
370 case NV_OP_MAX_U32:
371 pc->emit[0] |= 3;
372 break;
373 case NV_OP_MIN_S32:
374 case NV_OP_MAX_S32:
375 pc->emit[0] |= 3 | (1 << 5);
376 break;
377 case NV_OP_MIN_F32:
378 case NV_OP_MAX_F32:
379 default:
380 break;
381 }
382 }
383
384 static void
385 emit_tex(struct nv_pc *pc, struct nv_instruction *i)
386 {
387 pc->emit[0] = 0x00000086;
388 pc->emit[1] = 0x80000000;
389
390 if (i->opcode == NV_OP_TXB) pc->emit[1] |= 0x04000000;
391 else
392 if (i->opcode == NV_OP_TXL) pc->emit[1] |= 0x06000000;
393
394 set_pred(pc, i);
395
396 if (1)
397 pc->emit[0] |= 63 << 26; /* explicit derivatives */
398
399 DID(pc, i->def[0], 14);
400 SID(pc, i->src[0], 20);
401
402 pc->emit[1] |= i->tex_mask << 14;
403 pc->emit[1] |= (i->tex_argc - 1) << 20;
404
405 assert(i->ext.tex.s < 16);
406
407 pc->emit[1] |= i->ext.tex.t;
408 pc->emit[1] |= i->ext.tex.s << 8;
409
410 if (i->tex_live)
411 pc->emit[0] |= 1 << 9;
412 }
413
414 /* 0: cos, 1: sin, 2: ex2, 3: lg2, 4: rcp, 5: rsqrt */
415 static void
416 emit_flop(struct nv_pc *pc, struct nv_instruction *i, ubyte op)
417 {
418 pc->emit[0] = 0x00000000;
419 pc->emit[1] = 0xc8000000;
420
421 set_pred(pc, i);
422
423 DID(pc, i->def[0], 14);
424 SID(pc, i->src[0], 20);
425
426 pc->emit[0] |= op << 26;
427
428 if (op >= 4) {
429 if (i->src[0]->mod & NV_MOD_NEG) pc->emit[0] |= 1 << 9;
430 if (i->src[0]->mod & NV_MOD_ABS) pc->emit[0] |= 1 << 7;
431 } else {
432 assert(!i->src[0]->mod);
433 }
434 }
435
436 static void
437 emit_quadop(struct nv_pc *pc, struct nv_instruction *i)
438 {
439 pc->emit[0] = 0x00000000;
440 pc->emit[1] = 0x48000000;
441
442 set_pred(pc, i);
443
444 assert(SFILE(i, 0) == NV_FILE_GPR && SFILE(i, 1) == NV_FILE_GPR);
445
446 DID(pc, i->def[0], 14);
447 SID(pc, i->src[0], 20);
448 SID(pc, i->src[0], 26);
449
450 pc->emit[0] |= i->lanes << 6; /* l0, l1, l2, l3, dx, dy */
451 pc->emit[1] |= i->quadop;
452 }
453
454 static void
455 emit_ddx(struct nv_pc *pc, struct nv_instruction *i)
456 {
457 i->quadop = 0x99;
458 i->lanes = 4;
459 emit_quadop(pc, i);
460 }
461
462 static void
463 emit_ddy(struct nv_pc *pc, struct nv_instruction *i)
464 {
465 i->quadop = 0xa5;
466 i->lanes = 5;
467 emit_quadop(pc, i);
468 }
469
470 /* preparation op (preex2, presin / convert to fixed point) */
471 static void
472 emit_preop(struct nv_pc *pc, struct nv_instruction *i)
473 {
474 pc->emit[0] = 0x00000000;
475 pc->emit[1] = 0x60000000;
476
477 if (i->opcode == NV_OP_PREEX2)
478 pc->emit[0] |= 0x20;
479
480 emit_form_1(pc, i);
481
482 if (i->src[0]->mod & NV_MOD_NEG) pc->emit[0] |= 1 << 8;
483 if (i->src[0]->mod & NV_MOD_ABS) pc->emit[0] |= 1 << 6;
484 }
485
486 static void
487 emit_shift(struct nv_pc *pc, struct nv_instruction *i)
488 {
489 pc->emit[0] = 0x00000003;
490
491 switch (i->opcode) {
492 case NV_OP_SAR:
493 pc->emit[0] |= 0x20; /* fall through */
494 case NV_OP_SHR:
495 pc->emit[1] = 0x58000000;
496 break;
497 case NV_OP_SHL:
498 default:
499 pc->emit[1] = 0x60000000;
500 break;
501 }
502
503 emit_form_0(pc, i);
504 }
505
506 static void
507 emit_bitop(struct nv_pc *pc, struct nv_instruction *i)
508 {
509 if (SFILE(i, 1) == NV_FILE_IMM) {
510 pc->emit[0] = 0x00000002;
511 pc->emit[1] = 0x38000000;
512 } else {
513 pc->emit[0] = 0x00000003;
514 pc->emit[1] = 0x68000000;
515 }
516
517 switch (i->opcode) {
518 case NV_OP_OR:
519 pc->emit[0] |= 0x40;
520 break;
521 case NV_OP_XOR:
522 pc->emit[0] |= 0x80;
523 break;
524 case NV_OP_AND:
525 default:
526 break;
527 }
528
529 emit_form_0(pc, i);
530 }
531
532 static void
533 emit_set(struct nv_pc *pc, struct nv_instruction *i)
534 {
535 pc->emit[0] = 0x00000000;
536
537 switch (i->opcode) {
538 case NV_OP_SET_S32:
539 pc->emit[0] |= 0x20; /* fall through */
540 case NV_OP_SET_U32:
541 pc->emit[0] |= 0x3;
542 pc->emit[1] = 0x100e0000;
543 break;
544 case NV_OP_SET_F32_AND:
545 pc->emit[1] = 0x18000000;
546 break;
547 case NV_OP_SET_F32_OR:
548 pc->emit[1] = 0x18200000;
549 break;
550 case NV_OP_SET_F32_XOR:
551 pc->emit[1] = 0x18400000;
552 break;
553 case NV_OP_FSET_F32:
554 pc->emit[0] |= 0x20; /* fall through */
555 case NV_OP_SET_F32:
556 default:
557 pc->emit[1] = 0x180e0000;
558 break;
559 }
560
561 if (DFILE(i, 0) == NV_FILE_PRED) {
562 pc->emit[0] |= 0x1c000;
563 pc->emit[1] += 0x08000000;
564 }
565
566 pc->emit[1] |= i->set_cond << 23;
567
568 emit_form_0(pc, i);
569
570 emit_neg_abs_1_2(pc, i); /* maybe assert that U/S32 don't use mods */
571 }
572
573 static void
574 emit_selp(struct nv_pc *pc, struct nv_instruction *i)
575 {
576 pc->emit[0] = 0x00000004;
577 pc->emit[1] = 0x20000000;
578
579 emit_form_0(pc, i);
580
581 if (i->cc || (i->src[2]->mod & NV_MOD_NOT))
582 pc->emit[1] |= 1 << 20;
583 }
584
585 static void
586 emit_slct(struct nv_pc *pc, struct nv_instruction *i)
587 {
588 pc->emit[0] = 0x00000000;
589
590 switch (i->opcode) {
591 case NV_OP_SLCT_S32:
592 pc->emit[0] |= 0x20; /* fall through */
593 case NV_OP_SLCT_U32:
594 pc->emit[0] |= 0x3;
595 pc->emit[1] = 0x30000000;
596 break;
597 case NV_OP_SLCT_F32:
598 default:
599 pc->emit[1] = 0x38000000;
600 break;
601 }
602
603 emit_form_0(pc, i);
604
605 pc->emit[1] |= i->set_cond << 23;
606 }
607
608 static void
609 emit_cvt(struct nv_pc *pc, struct nv_instruction *i)
610 {
611 pc->emit[0] = 0x00000004;
612 pc->emit[1] = 0x10000000;
613
614 if (i->opcode != NV_OP_CVT)
615 i->ext.cvt.d = i->ext.cvt.s = NV_OPTYPE(i->opcode);
616
617 switch (i->ext.cvt.d) {
618 case NV_TYPE_F32:
619 switch (i->ext.cvt.s) {
620 case NV_TYPE_F32: pc->emit[1] = 0x10000000; break;
621 case NV_TYPE_S32: pc->emit[0] |= 0x200;
622 case NV_TYPE_U32: pc->emit[1] = 0x18000000; break;
623 }
624 break;
625 case NV_TYPE_S32: pc->emit[0] |= 0x80;
626 case NV_TYPE_U32:
627 switch (i->ext.cvt.s) {
628 case NV_TYPE_F32: pc->emit[1] = 0x14000000; break;
629 case NV_TYPE_S32: pc->emit[0] |= 0x200;
630 case NV_TYPE_U32: pc->emit[1] = 0x1c000000; break;
631 }
632 break;
633 default:
634 assert(!"cvt: unknown type");
635 break;
636 }
637
638 if (i->opcode == NV_OP_FLOOR)
639 pc->emit[1] |= 0x00020000;
640 else
641 if (i->opcode == NV_OP_CEIL)
642 pc->emit[1] |= 0x00040000;
643 else
644 if (i->opcode == NV_OP_TRUNC)
645 pc->emit[1] |= 0x00060000;
646
647 if (i->saturate || i->opcode == NV_OP_SAT)
648 pc->emit[0] |= 0x20;
649
650 if (NV_BASEOP(i->opcode) == NV_OP_ABS || i->src[0]->mod & NV_MOD_ABS)
651 pc->emit[0] |= 1 << 6;
652 if (NV_BASEOP(i->opcode) == NV_OP_NEG || i->src[0]->mod & NV_MOD_NEG)
653 pc->emit[0] |= 1 << 8;
654
655 pc->emit[0] |= util_logbase2(DREG(i->def[0])->size) << 20;
656 pc->emit[0] |= util_logbase2(SREG(i->src[0])->size) << 23;
657
658 emit_form_1(pc, i);
659 }
660
661 static void
662 emit_interp(struct nv_pc *pc, struct nv_instruction *i)
663 {
664 pc->emit[0] = 0x00000000;
665 pc->emit[1] = 0xc07e0000;
666
667 DID(pc, i->def[0], 14);
668
669 set_pred(pc, i);
670
671 if (i->indirect)
672 SID(pc, i->src[i->indirect], 20);
673 else
674 SID(pc, NULL, 20);
675
676 if (i->opcode == NV_OP_PINTERP) {
677 pc->emit[0] |= 0x040;
678 SID(pc, i->src[1], 26);
679 } else {
680 SID(pc, NULL, 26);
681 }
682
683 pc->emit[1] |= i->src[0]->value->reg.address & 0xffff;
684
685 if (i->centroid)
686 pc->emit[0] |= 0x100;
687 else
688 if (i->flat)
689 pc->emit[0] |= 0x080;
690 }
691
692 static void
693 emit_vfetch(struct nv_pc *pc, struct nv_instruction *i)
694 {
695 pc->emit[0] = 0x03f00006;
696 pc->emit[1] = 0x06000000 | i->src[0]->value->reg.address;
697 if (i->patch)
698 pc->emit[0] |= 0x100;
699
700 set_pred(pc, i);
701
702 DVS(pc, i);
703 DID(pc, i->def[0], 14);
704
705 SID(pc, (i->indirect >= 0) ? i->src[i->indirect] : NULL, 26);
706 }
707
708 static void
709 emit_export(struct nv_pc *pc, struct nv_instruction *i)
710 {
711 pc->emit[0] = 0x00000006;
712 pc->emit[1] = 0x0a000000;
713 if (i->patch)
714 pc->emit[0] |= 0x100;
715
716 set_pred(pc, i);
717
718 assert(SFILE(i, 0) == NV_FILE_MEM_V);
719 assert(SFILE(i, 1) == NV_FILE_GPR);
720
721 SID(pc, i->src[1], 26); /* register source */
722 SVS(pc, i->src[0]);
723
724 pc->emit[1] |= i->src[0]->value->reg.address & 0xfff;
725
726 SID(pc, (i->indirect >= 0) ? i->src[i->indirect] : NULL, 20);
727 }
728
729 static void
730 emit_mov(struct nv_pc *pc, struct nv_instruction *i)
731 {
732 if (i->opcode == NV_OP_MOV)
733 i->lanes = 0xf;
734
735 if (SFILE(i, 0) == NV_FILE_IMM) {
736 pc->emit[0] = 0x000001e2;
737 pc->emit[1] = 0x18000000;
738 } else
739 if (SFILE(i, 0) == NV_FILE_PRED) {
740 pc->emit[0] = 0x1c000004;
741 pc->emit[1] = 0x080e0000;
742 } else {
743 pc->emit[0] = 0x00000004 | (i->lanes << 5);
744 pc->emit[1] = 0x28000000;
745 }
746
747 emit_form_1(pc, i);
748 }
749
750 static void
751 emit_ldst_size(struct nv_pc *pc, struct nv_instruction *i)
752 {
753 assert(NV_IS_MEMORY_FILE(SFILE(i, 0)));
754
755 switch (SSIZE(i, 0)) {
756 case 1:
757 if (NV_TYPE_ISSGD(i->ext.cvt.s))
758 pc->emit[0] |= 0x20;
759 break;
760 case 2:
761 pc->emit[0] |= 0x40;
762 if (NV_TYPE_ISSGD(i->ext.cvt.s))
763 pc->emit[0] |= 0x20;
764 break;
765 case 4: pc->emit[0] |= 0x80; break;
766 case 8: pc->emit[0] |= 0xa0; break;
767 case 16: pc->emit[0] |= 0xc0; break;
768 default:
769 NOUVEAU_ERR("invalid load/store size %u\n", SSIZE(i, 0));
770 break;
771 }
772 }
773
774 static void
775 emit_ld_const(struct nv_pc *pc, struct nv_instruction *i)
776 {
777 pc->emit[0] = 0x00000006;
778 pc->emit[1] = 0x14000000 | (const_space_index(i, 0) << 10);
779
780 emit_ldst_size(pc, i);
781
782 set_pred(pc, i);
783 set_address_16(pc, i->src[0]);
784
785 SID(pc, (i->indirect >= 0) ? i->src[i->indirect] : NULL, 20);
786 DID(pc, i->def[0], 14);
787 }
788
789 static void
790 emit_ld(struct nv_pc *pc, struct nv_instruction *i)
791 {
792 if (SFILE(i, 0) >= NV_FILE_MEM_C(0) &&
793 SFILE(i, 0) <= NV_FILE_MEM_C(15)) {
794 emit_ld_const(pc, i);
795 } else {
796 NOUVEAU_ERR("emit_ld(%u): not handled yet\n", SFILE(i, 0));
797 abort();
798 }
799 }
800
801 static void
802 emit_st(struct nv_pc *pc, struct nv_instruction *i)
803 {
804 NOUVEAU_ERR("emit_st: not handled yet\n");
805 abort();
806 }
807
808 void
809 nvc0_emit_instruction(struct nv_pc *pc, struct nv_instruction *i)
810 {
811 debug_printf("EMIT: "); nvc0_print_instruction(i);
812
813 switch (i->opcode) {
814 case NV_OP_VFETCH:
815 emit_vfetch(pc, i);
816 break;
817 case NV_OP_EXPORT:
818 if (!pc->is_fragprog)
819 emit_export(pc, i);
820 break;
821 case NV_OP_MOV:
822 emit_mov(pc, i);
823 break;
824 case NV_OP_LD:
825 emit_ld(pc, i);
826 break;
827 case NV_OP_ST:
828 emit_st(pc, i);
829 break;
830 case NV_OP_LINTERP:
831 case NV_OP_PINTERP:
832 emit_interp(pc, i);
833 break;
834 case NV_OP_ADD_F32:
835 emit_add_f32(pc, i);
836 break;
837 case NV_OP_AND:
838 case NV_OP_OR:
839 case NV_OP_XOR:
840 emit_bitop(pc, i);
841 break;
842 case NV_OP_CVT:
843 case NV_OP_ABS_F32:
844 case NV_OP_ABS_S32:
845 case NV_OP_NEG_F32:
846 case NV_OP_NEG_S32:
847 case NV_OP_SAT:
848 case NV_OP_CEIL:
849 case NV_OP_FLOOR:
850 case NV_OP_TRUNC:
851 emit_cvt(pc, i);
852 break;
853 case NV_OP_DFDX:
854 emit_ddx(pc, i);
855 break;
856 case NV_OP_DFDY:
857 emit_ddy(pc, i);
858 break;
859 case NV_OP_COS:
860 emit_flop(pc, i, 0);
861 break;
862 case NV_OP_SIN:
863 emit_flop(pc, i, 1);
864 break;
865 case NV_OP_EX2:
866 emit_flop(pc, i, 2);
867 break;
868 case NV_OP_LG2:
869 emit_flop(pc, i, 3);
870 break;
871 case NV_OP_RCP:
872 emit_flop(pc, i, 4);
873 break;
874 case NV_OP_RSQ:
875 emit_flop(pc, i, 5);
876 break;
877 case NV_OP_PRESIN:
878 case NV_OP_PREEX2:
879 emit_preop(pc, i);
880 break;
881 case NV_OP_MAD_F32:
882 emit_mad_f32(pc, i);
883 break;
884 case NV_OP_MAX_F32:
885 case NV_OP_MAX_S32:
886 case NV_OP_MAX_U32:
887 case NV_OP_MIN_F32:
888 case NV_OP_MIN_S32:
889 case NV_OP_MIN_U32:
890 emit_minmax(pc, i);
891 break;
892 case NV_OP_MUL_F32:
893 emit_mul_f32(pc, i);
894 break;
895 case NV_OP_SET_F32:
896 case NV_OP_FSET_F32:
897 emit_set(pc, i);
898 break;
899 case NV_OP_SHL:
900 case NV_OP_SHR:
901 case NV_OP_SAR:
902 emit_shift(pc, i);
903 break;
904 case NV_OP_TEX:
905 case NV_OP_TXB:
906 case NV_OP_TXL:
907 emit_tex(pc, i);
908 break;
909 case NV_OP_BRA:
910 emit_flow(pc, i, 0x40);
911 break;
912 case NV_OP_CALL:
913 emit_flow(pc, i, 0x50);
914 break;
915 case NV_OP_JOINAT:
916 emit_flow(pc, i, 0x60);
917 break;
918 case NV_OP_EXIT:
919 emit_flow(pc, i, 0x80);
920 break;
921 case NV_OP_RET:
922 emit_flow(pc, i, 0x90);
923 break;
924 case NV_OP_KIL:
925 emit_flow(pc, i, 0x98);
926 break;
927 case NV_OP_JOIN:
928 case NV_OP_NOP:
929 pc->emit[0] = 0x00003c00;
930 pc->emit[1] = 0x00000000;
931 break;
932 case NV_OP_SELP:
933 emit_selp(pc, i);
934 break;
935 case NV_OP_SLCT_F32:
936 case NV_OP_SLCT_S32:
937 case NV_OP_SLCT_U32:
938 emit_slct(pc, i);
939 break;
940 default:
941 NOUVEAU_ERR("unhandled NV_OP: %d\n", i->opcode);
942 abort();
943 break;
944 }
945
946 if (i->join)
947 pc->emit[0] |= 0x10;
948 }