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
23 #include "nv50_context.h"
28 #define FLAGS_CC_SHIFT 7
29 #define FLAGS_ID_SHIFT 12
30 #define FLAGS_WR_ID_SHIFT 4
31 #define FLAGS_CC_MASK (0x1f << FLAGS_CC_SHIFT)
32 #define FLAGS_ID_MASK (0x03 << FLAGS_ID_SHIFT)
33 #define FLAGS_WR_EN (1 << 6)
34 #define FLAGS_WR_ID_MASK (0x3 << FLAGS_WR_ID_SHIFT)
36 const ubyte nv50_inst_min_size_tab
[NV_OP_COUNT
] =
38 0, 0, 0, 8, 8, 4, 4, 4, 8, 4, 4, 8, 8, 8, 8, 8, /* 15 */
39 8, 8, 8, 4, 0, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 4, /* 31 */
40 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 4, /* 47 */
41 4, 8, 8, 8, 8, 8, 0, 0, 8
44 /* XXX: silence, you ! */
46 nv50_inst_min_size(struct nv_instruction
*i
);
49 nv50_inst_min_size(struct nv_instruction
*i
)
53 if (nv50_inst_min_size_tab
[i
->opcode
] > 4)
56 if (i
->def
[0] && i
->def
[0]->reg
.file
!= NV_FILE_GPR
)
58 if (i
->def
[0]->join
->reg
.id
> 63)
61 for (n
= 0; n
< 3; ++n
) {
64 if (i
->src
[n
]->value
->reg
.file
!= NV_FILE_GPR
&&
65 i
->src
[n
]->value
->reg
.file
!= NV_FILE_MEM_V
)
67 if (i
->src
[n
]->value
->reg
.id
> 63)
71 if (i
->flags_def
|| i
->flags_src
|| i
->src
[4])
78 if (i
->saturate
|| i
->src
[2]->mod
)
80 if (i
->src
[0]->mod
^ i
->src
[1]->mod
)
82 if ((i
->src
[0]->mod
| i
->src
[1]->mod
) & NV_MOD_ABS
)
84 if (i
->def
[0]->join
->reg
.id
< 0 ||
85 i
->def
[0]->join
->reg
.id
!= i
->src
[2]->value
->join
->reg
.id
)
89 return nv50_inst_min_size_tab
[i
->opcode
];
93 STYPE(struct nv_instruction
*nvi
, int s
)
95 return nvi
->src
[s
]->typecast
;
99 DTYPE(struct nv_instruction
*nvi
, int d
)
101 return nvi
->def
[d
]->reg
.type
;
104 static INLINE
struct nv_reg
*
105 SREG(struct nv_ref
*ref
)
107 return &ref
->value
->join
->reg
;
110 static INLINE
struct nv_reg
*
111 DREG(struct nv_value
*val
)
113 return &val
->join
->reg
;
117 SFILE(struct nv_instruction
*nvi
, int s
)
119 return nvi
->src
[s
]->value
->reg
.file
;
123 DFILE(struct nv_instruction
*nvi
, int d
)
125 return nvi
->def
[0]->reg
.file
;
129 SID(struct nv_pc
*pc
, struct nv_ref
*ref
, int pos
)
131 pc
->emit
[pos
/ 32] |= SREG(ref
)->id
<< (pos
% 32);
135 DID(struct nv_pc
*pc
, struct nv_value
*val
, int pos
)
137 pc
->emit
[pos
/ 32] |= DREG(val
)->id
<< (pos
% 32);
140 static INLINE
uint32_t
141 get_immd_u32(struct nv_ref
*ref
)
143 assert(ref
->value
->reg
.file
== NV_FILE_IMM
);
144 return ref
->value
->reg
.imm
.u32
;
148 set_immd_u32(struct nv_pc
*pc
, uint32_t u32
)
151 pc
->emit
[0] |= (u32
& 0x3f) << 16;
152 pc
->emit
[1] |= (u32
>> 6) << 2;
156 set_immd(struct nv_pc
*pc
, struct nv_ref
*ref
)
158 assert(ref
->value
->reg
.file
== NV_FILE_IMM
);
159 set_immd_u32(pc
, get_immd_u32(ref
));
163 new_fixup(struct nv_pc
*pc
, unsigned type
, uint32_t data
, uint32_t m
, int s
)
165 const unsigned size
= sizeof(struct nv_fixup
);
166 const unsigned n
= pc
->num_fixups
;
170 pc
->fixups
= REALLOC(pc
->fixups
, n
* size
, (n
+ 8) * size
);
172 pc
->fixups
[n
].offset
= pc
->bin_pos
+ (s
/ 32);
173 pc
->fixups
[n
].type
= type
;
174 pc
->fixups
[n
].data
= data
;
175 pc
->fixups
[n
].mask
= m
<< (s
% 32);
176 pc
->fixups
[n
].shift
= s
% 32;
180 assert(((data
<< (s
% 32)) & pc
->fixups
[n
].mask
) == (data
<< (s
% 32)));
184 nv_pc_alloc_immd(struct nv_pc
*pc
, struct nv_ref
*ref
)
186 uint32_t i
, val
= get_immd_u32(ref
);
188 for (i
= 0; i
< pc
->immd_count
; ++i
)
189 if (pc
->immd_buf
[i
] == val
)
192 if (i
== pc
->immd_count
) {
193 if (!(pc
->immd_count
% 8))
194 pc
->immd_buf
= REALLOC(pc
->immd_buf
,
195 pc
->immd_count
* 4, (pc
->immd_count
+ 8) * 4);
196 pc
->immd_buf
[pc
->immd_count
++] = val
;
203 set_pred(struct nv_pc
*pc
, struct nv_instruction
*i
)
205 assert(!(pc
->emit
[1] & 0x00003f80));
207 pc
->emit
[1] |= i
->cc
<< 7;
209 pc
->emit
[1] |= SREG(i
->flags_src
)->id
<< 12;
213 set_pred_wr(struct nv_pc
*pc
, struct nv_instruction
*i
)
215 assert(!(pc
->emit
[1] & 0x00000070));
218 pc
->emit
[1] |= (DREG(i
->flags_def
)->id
<< 4) | 0x40;
222 set_a16_bits(struct nv_pc
*pc
, uint id
)
224 ++id
; /* $a0 is always 0 */
225 pc
->emit
[0] |= (id
& 3) << 26;
226 pc
->emit
[1] |= id
& 4;
230 set_addr(struct nv_pc
*pc
, struct nv_instruction
*i
)
233 set_a16_bits(pc
, SREG(i
->src
[4])->id
);
237 set_dst(struct nv_pc
*pc
, struct nv_value
*value
)
239 struct nv_reg
*reg
= &value
->join
->reg
;
242 debug_printf("WARNING: unused dst, hope we can bucket it !\n");
243 pc
->emit
[0] |= 127 << 2;
248 if (reg
->file
== NV_FILE_OUT
)
251 if (reg
->file
== NV_FILE_ADDR
)
254 pc
->emit
[0] |= reg
->id
<< 2;
258 set_src_0(struct nv_pc
*pc
, struct nv_ref
*ref
)
260 struct nv_reg
*reg
= SREG(ref
);
262 if (reg
->file
== NV_FILE_MEM_S
)
263 pc
->emit
[1] |= 0x00200000;
265 if (reg
->file
== NV_FILE_MEM_P
)
266 pc
->emit
[0] |= 0x01800000;
268 if (reg
->file
!= NV_FILE_GPR
)
269 NOUVEAU_ERR("invalid src0 register file: %d\n", reg
->file
);
271 assert(reg
->id
< 128);
272 pc
->emit
[0] |= reg
->id
<< 9;
276 set_src_1(struct nv_pc
*pc
, struct nv_ref
*ref
)
278 struct nv_reg
*reg
= SREG(ref
);
280 if (reg
->file
>= NV_FILE_MEM_C(0) &&
281 reg
->file
<= NV_FILE_MEM_C(15)) {
282 assert(!(pc
->emit
[1] & 0x01800000));
284 pc
->emit
[0] |= 0x00800000;
285 pc
->emit
[1] |= (reg
->file
- NV_FILE_MEM_C(0)) << 22;
287 if (reg
->file
!= NV_FILE_GPR
)
288 NOUVEAU_ERR("invalid src1 register file: %d\n", reg
->file
);
290 assert(reg
->id
< 128);
291 pc
->emit
[0] |= reg
->id
<< 16;
295 set_src_2(struct nv_pc
*pc
, struct nv_ref
*ref
)
297 struct nv_reg
*reg
= SREG(ref
);
299 if (reg
->file
>= NV_FILE_MEM_C(0) &&
300 reg
->file
<= NV_FILE_MEM_C(15)) {
301 assert(!(pc
->emit
[1] & 0x01800000));
303 pc
->emit
[0] |= 0x01000000;
304 pc
->emit
[1] |= (reg
->file
- NV_FILE_MEM_C(0)) << 22;
306 if (reg
->file
!= NV_FILE_GPR
)
307 NOUVEAU_ERR("invalid src2 register file: %d\n", reg
->file
);
309 assert(reg
->id
< 128);
310 pc
->emit
[1] |= reg
->id
<< 14;
315 * - 1 to 3 sources in slots 0, 1, 2
319 emit_form_MAD(struct nv_pc
*pc
, struct nv_instruction
*i
)
327 set_dst(pc
, i
->def
[0]);
329 pc
->emit
[0] |= 0x01fc;
330 pc
->emit
[1] |= 0x0008;
334 set_src_0(pc
, i
->src
[0]);
337 set_src_1(pc
, i
->src
[1]);
340 set_src_2(pc
, i
->src
[2]);
345 /* like default form, but 2nd source in slot 2, no 3rd source */
347 emit_form_ADD(struct nv_pc
*pc
, struct nv_instruction
*i
)
352 set_dst(pc
, i
->def
[0]);
354 pc
->emit
[0] |= 0x01fc;
355 pc
->emit
[1] |= 0x0008;
362 set_src_0(pc
, i
->src
[0]);
365 set_src_2(pc
, i
->src
[1]);
372 emit_form_MUL(struct nv_pc
*pc
, struct nv_instruction
*i
)
374 assert(!i
->is_long
&& !(pc
->emit
[0] & 1));
377 set_dst(pc
, i
->def
[0]);
380 set_src_0(pc
, i
->src
[0]);
383 set_src_1(pc
, i
->src
[1]);
386 /* default immediate form
387 * - 1 to 3 sources where last is immediate
388 * - no address or predicate possible
391 emit_form_IMM(struct nv_pc
*pc
, struct nv_instruction
*i
, ubyte mod_mask
)
397 set_dst(pc
, i
->def
[0]);
399 assert(!i
->src
[4] && !i
->flags_src
&& !i
->flags_def
);
402 set_immd(pc
, i
->src
[2]);
403 set_src_0(pc
, i
->src
[1]);
404 set_src_1(pc
, i
->src
[0]);
407 set_immd(pc
, i
->src
[1]);
408 set_src_0(pc
, i
->src
[0]);
410 set_immd(pc
, i
->src
[0]);
416 set_ld_st_size(struct nv_pc
*pc
, ubyte type
)
420 pc
->emit
[1] |= 0x8000;
425 pc
->emit
[1] |= 0xc000;
428 pc
->emit
[1] |= 0x6000;
431 pc
->emit
[1] |= 0x4000;
434 pc
->emit
[1] |= 0x2000;
442 emit_ld(struct nv_pc
*pc
, struct nv_instruction
*i
)
444 ubyte sf
= SFILE(i
, 0);
446 if (sf
== NV_FILE_IMM
) {
447 sf
= NV_FILE_MEM_C(0);
448 nv_pc_alloc_immd(pc
, i
->src
[0]);
450 new_fixup(pc
, NV_FIXUP_PARAM_RELOC
, SREG(i
->src
[0])->id
, 0xffff, 9);
453 if (sf
== NV_FILE_MEM_S
||
454 sf
== NV_FILE_MEM_P
) {
455 pc
->emit
[0] = 0x10000001;
456 pc
->emit
[1] = 0x04200000 | (0x3c << 12);
457 if (sf
== NV_FILE_MEM_P
)
458 pc
->emit
[0] |= 0x01800000;
460 if (sf
>= NV_FILE_MEM_C(0) &&
461 sf
<= NV_FILE_MEM_C(15)) {
462 pc
->emit
[0] = 0x10000001;
463 pc
->emit
[1] = 0x24000000;
464 pc
->emit
[1] |= (sf
- NV_FILE_MEM_C(0)) << 22;
466 if (sf
>= NV_FILE_MEM_G(0) &&
467 sf
<= NV_FILE_MEM_G(15)) {
468 pc
->emit
[0] = 0xd0000001 | ((sf
- NV_FILE_MEM_G(0)) << 16);
469 pc
->emit
[1] = 0xa0000000;
471 assert(i
->src
[4] && SREG(i
->src
[4])->file
== NV_FILE_GPR
);
472 SID(pc
, i
->src
[4], 9);
474 if (sf
== NV_FILE_MEM_L
) {
475 pc
->emit
[0] = 0xd0000001;
476 pc
->emit
[1] = 0x40000000;
478 NOUVEAU_ERR("invalid ld source file\n");
482 set_ld_st_size(pc
, STYPE(i
, 0));
484 set_dst(pc
, i
->def
[0]);
489 if (sf
< NV_FILE_MEM_G(0) ||
490 sf
> NV_FILE_MEM_G(15)) {
491 SID(pc
, i
->src
[0], 9);
497 emit_st(struct nv_pc
*pc
, struct nv_instruction
*i
)
503 verify_mov(struct nv_instruction
*i
)
505 ubyte sf
= SFILE(i
, 0);
506 ubyte df
= DFILE(i
, 0);
508 if (df
== NV_FILE_GPR
)
511 if (df
!= NV_FILE_OUT
&&
512 df
!= NV_FILE_FLAGS
&&
516 if (sf
== NV_FILE_FLAGS
)
518 if (sf
== NV_FILE_ADDR
)
520 if (sf
== NV_FILE_IMM
&& df
!= NV_FILE_OUT
)
527 emit_mov(struct nv_pc
*pc
, struct nv_instruction
*i
)
529 assert(!verify_mov(i
));
531 if (SFILE(i
, 0) >= NV_FILE_MEM_S
)
534 if (SFILE(i
, 0) == NV_FILE_FLAGS
) {
535 pc
->emit
[0] = 0x00000001 | (DREG(i
->def
[0])->id
<< 2);
536 pc
->emit
[1] = 0x20000780 | (SREG(i
->src
[0])->id
<< 12);
538 if (SFILE(i
, 0) == NV_FILE_ADDR
) {
539 pc
->emit
[0] = 0x00000001 | (DREG(i
->def
[0])->id
<< 2);
540 pc
->emit
[1] = 0x40000780;
541 set_a16_bits(pc
, SREG(i
->src
[0])->id
);
543 if (DFILE(i
, 0) == NV_FILE_FLAGS
) {
544 pc
->emit
[0] = 0x000001fd;
545 pc
->emit
[1] = 0xa0000788 | (1 << 6);
546 pc
->emit
[0] |= SREG(i
->src
[0])->id
<< 9;
547 pc
->emit
[1] |= DREG(i
->def
[0])->id
<< 4;
549 if (SFILE(i
, 0) == NV_FILE_IMM
) {
550 if (i
->opcode
== NV_OP_LDA
) {
553 pc
->emit
[0] = 0x10008001;
554 pc
->emit
[1] = 0x00000003;
556 emit_form_IMM(pc
, i
, 0);
559 pc
->emit
[0] = 0x10000000;
560 pc
->emit
[0] |= DREG(i
->def
[0])->id
<< 2;
561 pc
->emit
[0] |= SREG(i
->src
[0])->id
<< 9;
564 pc
->emit
[0] |= 0x8000;
566 pc
->emit
[0] |= 0x00000001;
567 pc
->emit
[1] = 0x0403c000;
573 if (DFILE(i
, 0) == NV_FILE_OUT
)
578 emit_interp(struct nv_pc
*pc
, struct nv_instruction
*i
)
580 pc
->emit
[0] = 0x80000000;
582 assert(DFILE(i
, 0) == NV_FILE_GPR
);
583 assert(SFILE(i
, 0) == NV_FILE_MEM_V
);
585 DID(pc
, i
->def
[0], 2);
586 SID(pc
, i
->src
[0], 16);
589 pc
->emit
[0] |= 1 << 8;
591 if (i
->opcode
== NV_OP_PINTERP
) {
592 pc
->emit
[0] |= 1 << 25;
593 pc
->emit
[0] |= SREG(i
->src
[1])->id
<< 9;
597 pc
->emit
[0] |= 1 << 24;
599 assert(i
->is_long
|| !i
->flags_src
);
605 (pc
->emit
[0] & (3 << 24)) >> (24 - 16) |
606 (pc
->emit
[0] & (1 << 8)) >> (18 - 8);
609 pc
->emit
[0] &= ~0x03000100;
614 emit_minmax(struct nv_pc
*pc
, struct nv_instruction
*i
)
616 pc
->emit
[0] = 0x30000000;
617 pc
->emit
[1] = (i
->opcode
== NV_OP_MIN
) ? (2 << 28) : 0;
619 switch (DTYPE(i
, 0)) {
621 pc
->emit
[0] |= 0x80000000;
622 pc
->emit
[1] |= 0x80000000;
625 pc
->emit
[1] |= 0x8c000000;
628 pc
->emit
[1] |= 0x84000000;
632 emit_form_MAD(pc
, i
);
634 if (i
->src
[0]->mod
& NV_MOD_ABS
) pc
->emit
[1] |= 0x00100000;
635 if (i
->src
[1]->mod
& NV_MOD_ABS
) pc
->emit
[1] |= 0x00080000;
639 emit_add_f32(struct nv_pc
*pc
, struct nv_instruction
*i
)
641 pc
->emit
[0] = 0xb0000000;
643 if (SFILE(i
, 1) == NV_FILE_IMM
) {
644 emit_form_IMM(pc
, i
, 0);
646 if (i
->src
[0]->mod
& NV_MOD_NEG
) pc
->emit
[0] |= 0x8000;
647 if (i
->src
[1]->mod
& NV_MOD_NEG
) pc
->emit
[0] |= 1 << 22;
650 emit_form_ADD(pc
, i
);
652 if (i
->src
[0]->mod
& NV_MOD_NEG
) pc
->emit
[1] |= 1 << 26;
653 if (i
->src
[1]->mod
& NV_MOD_NEG
) pc
->emit
[1] |= 1 << 27;
655 emit_form_MUL(pc
, i
);
657 if (i
->src
[0]->mod
& NV_MOD_NEG
) pc
->emit
[0] |= 0x8000;
658 if (i
->src
[1]->mod
& NV_MOD_NEG
) pc
->emit
[0] |= 1 << 22;
663 emit_add_b32(struct nv_pc
*pc
, struct nv_instruction
*i
)
665 pc
->emit
[0] = 0x20008000;
667 if (SFILE(i
, 1) == NV_FILE_IMM
) {
668 emit_form_IMM(pc
, i
, 0);
671 pc
->emit
[0] = 0x20000000;
672 pc
->emit
[1] = 0x04000000;
673 emit_form_ADD(pc
, i
);
675 emit_form_MUL(pc
, i
);
678 if (i
->src
[0]->mod
& NV_MOD_NEG
) pc
->emit
[0] |= 1 << 28;
679 if (i
->src
[1]->mod
& NV_MOD_NEG
) pc
->emit
[0] |= 1 << 22;
683 emit_add_a16(struct nv_pc
*pc
, struct nv_instruction
*i
)
685 pc
->emit
[0] = 0xd0000001 | (get_immd_u32(i
->src
[0]) << 9);
686 pc
->emit
[1] = 0x20000000;
688 pc
->emit
[0] |= (DREG(i
->def
[0])->id
+ 1) << 2;
693 set_a16_bits(pc
, SREG(i
->src
[1])->id
);
697 emit_flow(struct nv_pc
*pc
, struct nv_instruction
*i
, ubyte flow_op
)
699 pc
->emit
[0] = 0x00000003 | (flow_op
<< 28);
700 pc
->emit
[1] = 0x00000000;
704 if (i
->target
&& (i
->opcode
!= NV_OP_BREAK
)) {
705 new_fixup(pc
, NV_FIXUP_CFLOW_RELOC
, i
->target
->bin_pos
, 0x7ff800, 11);
706 pc
->emit
[0] |= (i
->target
->bin_pos
/ 4) << 11;
711 emit_add(struct nv_pc
*pc
, struct nv_instruction
*i
)
713 if (DFILE(i
, 0) == NV_FILE_ADDR
)
716 switch (DTYPE(i
, 0)) {
729 emit_bitop2(struct nv_pc
*pc
, struct nv_instruction
*i
)
731 pc
->emit
[0] = 0xd0000000;
733 if (SFILE(i
, 0) == NV_FILE_IMM
) {
734 emit_form_IMM(pc
, i
, 0);
736 if (i
->opcode
== NV_OP_OR
)
737 pc
->emit
[0] |= 0x0100;
739 if (i
->opcode
== NV_OP_XOR
)
740 pc
->emit
[0] |= 0x8000;
742 emit_form_MAD(pc
, i
);
744 pc
->emit
[1] |= 0x04000000;
746 if (i
->opcode
== NV_OP_OR
)
747 pc
->emit
[1] |= 0x4000;
749 if (i
->opcode
== NV_OP_XOR
)
750 pc
->emit
[1] |= 0x8000;
755 emit_arl(struct nv_pc
*pc
, struct nv_instruction
*i
)
757 assert(SFILE(i
, 0) == NV_FILE_GPR
);
758 assert(SFILE(i
, 1) == NV_FILE_IMM
);
760 assert(!i
->flags_def
);
762 pc
->emit
[0] = 0x00000001;
763 pc
->emit
[1] = 0xc0000000;
765 set_dst(pc
, i
->def
[0]);
767 set_src_0(pc
, i
->src
[0]);
768 pc
->emit
[0] |= (get_immd_u32(i
->src
[1]) & 0x3f) << 16;
772 emit_shift(struct nv_pc
*pc
, struct nv_instruction
*i
)
774 if (DFILE(i
, 0) == NV_FILE_ADDR
) {
779 pc
->emit
[0] = 0x30000001;
780 pc
->emit
[1] = 0xc4000000;
782 if (i
->opcode
== NV_OP_SHR
)
783 pc
->emit
[1] |= 1 << 29;
785 if (SFILE(i
, 1) == NV_FILE_IMM
) {
786 pc
->emit
[1] |= 1 << 20;
787 pc
->emit
[0] |= (get_immd_u32(i
->src
[1]) & 0x7f) << 16;
791 emit_form_MAD(pc
, i
);
793 if (STYPE(i
, 0) == NV_TYPE_S32
)
794 pc
->emit
[1] |= 1 << 27;
798 emit_flop(struct nv_pc
*pc
, struct nv_instruction
*i
)
800 struct nv_ref
*src0
= i
->src
[0];
802 pc
->emit
[0] = 0x90000000;
804 assert(SREG(src0
)->type
== NV_TYPE_F32
);
805 assert(SREG(src0
)->file
== NV_FILE_GPR
);
808 emit_form_MUL(pc
, i
);
809 assert(i
->opcode
== NV_OP_RCP
&& !src0
->mod
);
813 pc
->emit
[1] = (i
->opcode
- NV_OP_RCP
) << 29;
815 emit_form_MAD(pc
, i
);
817 if (src0
->mod
& NV_MOD_NEG
) pc
->emit
[1] |= 0x04000000;
818 if (src0
->mod
& NV_MOD_ABS
) pc
->emit
[1] |= 0x00100000;
822 emit_mad_f32(struct nv_pc
*pc
, struct nv_instruction
*i
)
824 const boolean neg_mul
= (i
->src
[0]->mod
^ i
->src
[1]->mod
) & NV_MOD_NEG
;
825 const boolean neg_add
= (i
->src
[2]->mod
& NV_MOD_NEG
);
827 pc
->emit
[0] = 0xe0000000;
830 emit_form_MUL(pc
, i
);
831 assert(!neg_mul
&& !neg_add
);
835 emit_form_MAD(pc
, i
);
837 if (neg_mul
) pc
->emit
[1] |= 0x04000000;
838 if (neg_add
) pc
->emit
[1] |= 0x08000000;
841 pc
->emit
[1] |= 0x20000000;
845 emit_mad(struct nv_pc
*pc
, struct nv_instruction
*i
)
851 emit_mul_f32(struct nv_pc
*pc
, struct nv_instruction
*i
)
853 boolean neg
= (i
->src
[0]->mod
^ i
->src
[1]->mod
) & NV_MOD_NEG
;
855 pc
->emit
[0] = 0xc0000000;
857 if (SFILE(i
, 1) == NV_FILE_IMM
) {
858 emit_form_IMM(pc
, i
, 0);
861 pc
->emit
[0] |= 0x8000;
864 emit_form_MAD(pc
, i
);
867 pc
->emit
[1] |= 0x08 << 24;
869 emit_form_MUL(pc
, i
);
872 pc
->emit
[0] |= 0x8000;
877 emit_set(struct nv_pc
*pc
, struct nv_instruction
*nvi
)
879 assert(nvi
->is_long
);
881 pc
->emit
[0] = 0x30000000;
882 pc
->emit
[1] = 0x60000000;
884 pc
->emit
[1] |= nvi
->set_cond
<< 14;
886 switch (STYPE(nvi
, 0)) {
887 case NV_TYPE_U32
: pc
->emit
[1] |= 0x04000000; break;
888 case NV_TYPE_S32
: pc
->emit
[1] |= 0x0c000000; break;
889 case NV_TYPE_F32
: pc
->emit
[0] |= 0x80000000; break;
895 emit_form_MAD(pc
, nvi
);
898 #define CVT_RN (0x00 << 16)
899 #define CVT_FLOOR (0x02 << 16)
900 #define CVT_CEIL (0x04 << 16)
901 #define CVT_TRUNC (0x06 << 16)
902 #define CVT_SAT (0x08 << 16)
903 #define CVT_ABS (0x10 << 16)
905 #define CVT_X32_X32 0x04004000
906 #define CVT_X32_S32 0x04014000
907 #define CVT_F32_F32 ((0xc0 << 24) | CVT_X32_X32)
908 #define CVT_S32_F32 ((0x88 << 24) | CVT_X32_X32)
909 #define CVT_U32_F32 ((0x80 << 24) | CVT_X32_X32)
910 #define CVT_F32_S32 ((0x40 << 24) | CVT_X32_S32)
911 #define CVT_F32_U32 ((0x40 << 24) | CVT_X32_X32)
912 #define CVT_S32_S32 ((0x08 << 24) | CVT_X32_S32)
913 #define CVT_S32_U32 ((0x08 << 24) | CVT_X32_X32)
914 #define CVT_U32_S32 ((0x00 << 24) | CVT_X32_S32)
915 #define CVT_U32_U32 ((0x00 << 24) | CVT_X32_X32)
917 #define CVT_NEG 0x20000000
918 #define CVT_RI 0x08000000
921 emit_cvt(struct nv_pc
*pc
, struct nv_instruction
*nvi
)
923 ubyte dst_type
= nvi
->def
[0] ? DTYPE(nvi
, 0) : STYPE(nvi
, 0);
925 pc
->emit
[0] = 0xa0000000;
929 switch (STYPE(nvi
, 0)) {
930 case NV_TYPE_F32
: pc
->emit
[1] = CVT_F32_F32
; break;
931 case NV_TYPE_S32
: pc
->emit
[1] = CVT_F32_S32
; break;
932 case NV_TYPE_U32
: pc
->emit
[1] = CVT_F32_U32
; break;
936 switch (STYPE(nvi
, 0)) {
937 case NV_TYPE_F32
: pc
->emit
[1] = CVT_S32_F32
; break;
938 case NV_TYPE_S32
: pc
->emit
[1] = CVT_S32_S32
; break;
939 case NV_TYPE_U32
: pc
->emit
[1] = CVT_S32_U32
; break;
943 switch (STYPE(nvi
, 0)) {
944 case NV_TYPE_F32
: pc
->emit
[1] = CVT_U32_F32
; break;
945 case NV_TYPE_S32
: pc
->emit
[1] = CVT_U32_S32
; break;
946 case NV_TYPE_U32
: pc
->emit
[1] = CVT_U32_U32
; break;
950 if (pc
->emit
[1] == CVT_F32_F32
&&
951 (nvi
->opcode
== NV_OP_CEIL
|| nvi
->opcode
== NV_OP_FLOOR
||
952 nvi
->opcode
== NV_OP_TRUNC
))
953 pc
->emit
[1] |= CVT_RI
;
955 switch (nvi
->opcode
) {
956 case NV_OP_CEIL
: pc
->emit
[1] |= CVT_CEIL
; break;
957 case NV_OP_FLOOR
: pc
->emit
[1] |= CVT_FLOOR
; break;
958 case NV_OP_TRUNC
: pc
->emit
[1] |= CVT_TRUNC
; break;
960 case NV_OP_ABS
: pc
->emit
[1] |= CVT_ABS
; break;
961 case NV_OP_SAT
: pc
->emit
[1] |= CVT_SAT
; break;
962 case NV_OP_NEG
: pc
->emit
[1] |= CVT_NEG
; break;
964 assert(nvi
->opcode
== NV_OP_CVT
);
967 assert(nvi
->opcode
!= NV_OP_ABS
|| !(nvi
->src
[0]->mod
& NV_MOD_NEG
));
969 if (nvi
->src
[0]->mod
& NV_MOD_NEG
) pc
->emit
[1] ^= CVT_NEG
;
970 if (nvi
->src
[0]->mod
& NV_MOD_ABS
) pc
->emit
[1] |= CVT_ABS
;
972 emit_form_MAD(pc
, nvi
);
976 emit_tex(struct nv_pc
*pc
, struct nv_instruction
*i
)
978 pc
->emit
[0] = 0xf0000001;
979 pc
->emit
[1] = 0x00000000;
981 DID(pc
, i
->def
[0], 2);
985 pc
->emit
[0] |= i
->tex_t
<< 9;
986 pc
->emit
[0] |= i
->tex_s
<< 17;
988 pc
->emit
[0] |= i
->tex_argc
<< 22;
990 pc
->emit
[0] |= (i
->tex_mask
& 0x3) << 25;
991 pc
->emit
[1] |= (i
->tex_mask
& 0xc) << 12;
997 pc
->emit
[0] |= 0x08000000;
999 if (i
->opcode
== NV_OP_TXB
)
1000 pc
->emit
[1] |= 0x20000000;
1002 if (i
->opcode
== NV_OP_TXL
)
1003 pc
->emit
[1] |= 0x40000000;
1005 pc
->emit
[0] -= 1 << 22;
1009 emit_cvt2fixed(struct nv_pc
*pc
, struct nv_instruction
*i
)
1011 ubyte mod
= i
->src
[0]->mod
;
1013 pc
->emit
[0] = 0xb0000000;
1014 pc
->emit
[1] = 0xc0000000;
1016 if (i
->opcode
== NV_OP_PREEX2
)
1017 pc
->emit
[1] |= 0x4000;
1019 emit_form_MAD(pc
, i
);
1021 if (mod
& NV_MOD_NEG
) pc
->emit
[1] |= 0x04000000;
1022 if (mod
& NV_MOD_ABS
) pc
->emit
[1] |= 0x00100000;
1026 emit_ddx(struct nv_pc
*pc
, struct nv_instruction
*i
)
1028 assert(i
->is_long
&& SFILE(i
, 0) == NV_FILE_GPR
);
1030 pc
->emit
[0] = (i
->src
[0]->mod
& NV_MOD_NEG
) ? 0xc0240001 : 0xc0140001;
1031 pc
->emit
[1] = (i
->src
[0]->mod
& NV_MOD_NEG
) ? 0x86400000 : 0x89800000;
1033 DID(pc
, i
->def
[0], 2);
1034 SID(pc
, i
->src
[0], 9);
1035 SID(pc
, i
->src
[0], 32 + 14);
1042 emit_ddy(struct nv_pc
*pc
, struct nv_instruction
*i
)
1044 assert(i
->is_long
&& SFILE(i
, 0) == NV_FILE_GPR
);
1046 pc
->emit
[0] = (i
->src
[0]->mod
& NV_MOD_NEG
) ? 0xc0250001 : 0xc0150001;
1047 pc
->emit
[1] = (i
->src
[0]->mod
& NV_MOD_NEG
) ? 0x85800000 : 0x8a400000;
1049 DID(pc
, i
->def
[0], 2);
1050 SID(pc
, i
->src
[0], 9);
1051 SID(pc
, i
->src
[0], 32 + 14);
1058 nv50_emit_instruction(struct nv_pc
*pc
, struct nv_instruction
*i
)
1060 // nv_print_instruction(i);
1062 switch (i
->opcode
) {
1064 if (DFILE(i
, 0) == NV_FILE_ADDR
)
1065 emit_add_a16(pc
, i
);
1112 emit_cvt2fixed(pc
, i
);
1122 emit_mul_f32(pc
, i
);
1137 emit_flow(pc
, i
, 0x0);
1140 emit_flow(pc
, i
, 0x1);
1143 emit_flow(pc
, i
, 0x2);
1146 emit_flow(pc
, i
, 0x3);
1148 case NV_OP_BREAKADDR
:
1149 emit_flow(pc
, i
, 0x4);
1152 emit_flow(pc
, i
, 0x5);
1155 emit_flow(pc
, i
, 0xa);
1159 pc
->emit
[0] = 0xf0000001;
1160 pc
->emit
[1] = 0xe0000000;
1165 NOUVEAU_ERR("operation \"%s\" should have been eliminated\n",
1166 nv_opcode_name(i
->opcode
));
1169 NOUVEAU_ERR("unhandled NV_OP: %d\n", i
->opcode
);
1175 assert(i
->is_long
&& !(pc
->emit
[1] & 1));
1179 assert((pc
->emit
[0] & 1) == i
->is_long
);