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"
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
46 nv50_relocate_program(struct nv50_program
*p
,
50 struct nv50_fixup
*f
= (struct nv50_fixup
*)p
->fixups
;
53 for (i
= 0; i
< p
->num_fixups
; ++i
) {
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;
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
;
71 new_fixup(struct nv_pc
*pc
, uint8_t ty
, int w
, uint32_t data
, uint32_t m
, int s
)
75 const unsigned size
= sizeof(struct nv50_fixup
);
76 const unsigned n
= pc
->num_fixups
;
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;
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
101 nv50_inst_min_size(struct nv_instruction
*i
)
105 if (nv50_inst_min_size_tab
[i
->opcode
] > 4)
108 if (i
->def
[0] && i
->def
[0]->reg
.file
!= NV_FILE_GPR
)
110 if (i
->def
[0]->join
->reg
.id
> 63)
113 for (n
= 0; n
< 3; ++n
) {
116 if (i
->src
[n
]->value
->reg
.file
!= NV_FILE_GPR
&&
117 i
->src
[n
]->value
->reg
.file
!= NV_FILE_MEM_V
)
119 if (i
->src
[n
]->value
->reg
.id
> 63)
123 if (i
->flags_def
|| i
->flags_src
|| i
->src
[4])
130 if (i
->saturate
|| i
->src
[2]->mod
)
132 if (i
->src
[0]->mod
^ i
->src
[1]->mod
)
134 if ((i
->src
[0]->mod
| i
->src
[1]->mod
) & NV_MOD_ABS
)
136 if (i
->def
[0]->join
->reg
.id
< 0 ||
137 i
->def
[0]->join
->reg
.id
!= i
->src
[2]->value
->join
->reg
.id
)
141 return nv50_inst_min_size_tab
[i
->opcode
];
145 STYPE(struct nv_instruction
*nvi
, int s
)
147 return nvi
->src
[s
]->typecast
;
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
;
169 SFILE(struct nv_instruction
*nvi
, int s
)
171 return nvi
->src
[s
]->value
->reg
.file
;
175 DFILE(struct nv_instruction
*nvi
, int d
)
177 return nvi
->def
[0]->reg
.file
;
181 SID(struct nv_pc
*pc
, struct nv_ref
*ref
, int pos
)
183 pc
->emit
[pos
/ 32] |= SREG(ref
)->id
<< (pos
% 32);
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
;
200 set_immd_u32(struct nv_pc
*pc
, uint32_t u32
)
203 pc
->emit
[0] |= (u32
& 0x3f) << 16;
204 pc
->emit
[1] |= (u32
>> 6) << 2;
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.
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
)
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
;
237 set_pred(struct nv_pc
*pc
, struct nv_instruction
*i
)
239 assert(!(pc
->emit
[1] & 0x00003f80));
241 pc
->emit
[1] |= i
->cc
<< 7;
243 pc
->emit
[1] |= SREG(i
->flags_src
)->id
<< 12;
247 set_pred_wr(struct nv_pc
*pc
, struct nv_instruction
*i
)
249 assert(!(pc
->emit
[1] & 0x00000070));
252 pc
->emit
[1] |= (DREG(i
->flags_def
)->id
<< 4) | 0x40;
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;
264 set_addr(struct nv_pc
*pc
, struct nv_instruction
*i
)
267 set_a16_bits(pc
, SREG(i
->src
[4])->id
);
271 set_dst(struct nv_pc
*pc
, struct nv_value
*value
)
273 struct nv_reg
*reg
= &value
->join
->reg
;
276 pc
->emit
[0] |= (127 << 2) | 1; /* set 'long'-bit to catch bugs */
281 if (reg
->file
== NV_FILE_OUT
)
284 if (reg
->file
== NV_FILE_ADDR
)
287 pc
->emit
[0] |= reg
->id
<< 2;
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;
298 if (reg
->file
== NV_FILE_MEM_P
)
299 pc
->emit
[0] |= 0x01800000;
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;
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;
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;
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;
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;
348 * - 1 to 3 sources in slots 0, 1, 2
352 emit_form_MAD(struct nv_pc
*pc
, struct nv_instruction
*i
)
360 set_dst(pc
, i
->def
[0]);
362 pc
->emit
[0] |= 0x01fc;
363 pc
->emit
[1] |= 0x0008;
367 set_src_0(pc
, i
->src
[0]);
370 set_src_1(pc
, i
->src
[1]);
373 set_src_2(pc
, i
->src
[2]);
378 /* like default form, but 2nd source in slot 2, no 3rd source */
380 emit_form_ADD(struct nv_pc
*pc
, struct nv_instruction
*i
)
385 set_dst(pc
, i
->def
[0]);
387 pc
->emit
[0] |= 0x01fc;
388 pc
->emit
[1] |= 0x0008;
395 set_src_0(pc
, i
->src
[0]);
398 set_src_2(pc
, i
->src
[1]);
405 emit_form_MUL(struct nv_pc
*pc
, struct nv_instruction
*i
)
407 assert(!i
->is_long
&& !(pc
->emit
[0] & 1));
410 set_dst(pc
, i
->def
[0]);
413 set_src_0(pc
, i
->src
[0]);
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
424 emit_form_IMM(struct nv_pc
*pc
, struct nv_instruction
*i
, ubyte mod_mask
)
430 set_dst(pc
, i
->def
[0]);
432 assert(!i
->src
[4] && !i
->flags_src
&& !i
->flags_def
);
435 set_immd(pc
, i
->src
[2]);
436 set_src_0(pc
, i
->src
[1]);
437 set_src_1(pc
, i
->src
[0]);
440 set_immd(pc
, i
->src
[1]);
441 set_src_0(pc
, i
->src
[0]);
443 set_immd(pc
, i
->src
[0]);
449 set_ld_st_size(struct nv_pc
*pc
, int s
, ubyte type
)
453 pc
->emit
[1] |= 0x8000 << s
;
458 pc
->emit
[1] |= 0xc000 << s
;
461 pc
->emit
[1] |= 0x6000 << s
;
464 pc
->emit
[1] |= 0x4000 << s
;
467 pc
->emit
[1] |= 0x2000 << s
;
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;
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;
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);
507 if (sf
== NV_FILE_MEM_L
) {
508 pc
->emit
[0] = 0xd0000001;
509 pc
->emit
[1] = 0x40000000;
513 NOUVEAU_ERR("invalid ld source file\n");
517 set_ld_st_size(pc
, (sf
== NV_FILE_MEM_L
) ? 8 : 0, STYPE(i
, 0));
519 set_dst(pc
, i
->def
[0]);
524 if (sf
< NV_FILE_MEM_G(0) ||
525 sf
> NV_FILE_MEM_G(15)) {
526 SID(pc
, i
->src
[0], 9);
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));
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
)
558 if (df
!= NV_FILE_OUT
&&
559 df
!= NV_FILE_FLAGS
&&
563 if (sf
== NV_FILE_FLAGS
)
565 if (sf
== NV_FILE_ADDR
)
567 if (sf
== NV_FILE_IMM
&& df
!= NV_FILE_OUT
)
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
)
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);
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
);
590 if (DFILE(i
, 0) == NV_FILE_FLAGS
) {
591 pc
->emit
[0] = 0x00000001;
592 pc
->emit
[1] = 0xa0000000 | (1 << 6);
594 pc
->emit
[0] |= SREG(i
->src
[0])->id
<< 9;
595 pc
->emit
[1] |= DREG(i
->def
[0])->id
<< 4;
597 if (SFILE(i
, 0) == NV_FILE_IMM
) {
598 if (i
->opcode
== NV_OP_LDA
) {
601 pc
->emit
[0] = 0x10008001;
602 pc
->emit
[1] = 0x00000003;
604 emit_form_IMM(pc
, i
, 0);
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;
612 pc
->emit
[0] |= 0x8000;
614 pc
->emit
[0] |= 0x00000001;
615 pc
->emit
[1] = 0x0403c000;
621 if (DFILE(i
, 0) == NV_FILE_OUT
)
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);
637 pc
->emit
[0] |= 1 << 8;
639 if (i
->opcode
== NV_OP_PINTERP
) {
640 pc
->emit
[0] |= 1 << 25;
641 pc
->emit
[0] |= SREG(i
->src
[1])->id
<< 9;
645 pc
->emit
[0] |= 1 << 24;
647 assert(i
->is_long
|| !i
->flags_src
);
653 (pc
->emit
[0] & (3 << 24)) >> (24 - 16) |
654 (pc
->emit
[0] & (1 << 8)) >> (18 - 8);
657 pc
->emit
[0] &= ~0x03000100;
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)) {
669 pc
->emit
[0] |= 0x80000000;
670 pc
->emit
[1] |= 0x80000000;
673 pc
->emit
[1] |= 0x8c000000;
676 pc
->emit
[1] |= 0x84000000;
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;
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;
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;
706 pc
->emit
[1] |= 0x20000000;
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;
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);
724 pc
->emit
[0] = 0x20000000;
725 pc
->emit
[1] = 0x04000000;
726 emit_form_ADD(pc
, i
);
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;
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;
748 set_a16_bits(pc
, SREG(i
->src
[0])->id
);
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;
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;
771 emit_add(struct nv_pc
*pc
, struct nv_instruction
*i
)
773 if (DFILE(i
, 0) == NV_FILE_ADDR
)
776 switch (DTYPE(i
, 0)) {
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;
799 if (i
->opcode
== NV_OP_XOR
)
800 pc
->emit
[0] |= 0x8000;
802 emit_form_MAD(pc
, i
);
804 pc
->emit
[1] |= 0x04000000;
806 if (i
->opcode
== NV_OP_OR
)
807 pc
->emit
[1] |= 0x4000;
809 if (i
->opcode
== NV_OP_XOR
)
810 pc
->emit
[1] |= 0x8000;
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;
827 set_src_0(pc
, i
->src
[0]);
828 pc
->emit
[0] |= (get_immd_u32(i
->src
[1]) & 0x3f) << 16;
832 emit_shift(struct nv_pc
*pc
, struct nv_instruction
*i
)
834 if (DFILE(i
, 0) == NV_FILE_ADDR
) {
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;
851 emit_form_MAD(pc
, i
);
853 if (STYPE(i
, 0) == NV_TYPE_S32
)
854 pc
->emit
[1] |= 1 << 27;
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
);
868 emit_form_MUL(pc
, i
);
869 assert(i
->opcode
== NV_OP_RCP
&& !src0
->mod
);
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;
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;
890 emit_form_MUL(pc
, i
);
891 assert(!neg_mul
&& !neg_add
);
895 emit_form_MAD(pc
, i
);
897 if (neg_mul
) pc
->emit
[1] |= 0x04000000;
898 if (neg_add
) pc
->emit
[1] |= 0x08000000;
901 pc
->emit
[1] |= 0x20000000;
905 emit_mad(struct nv_pc
*pc
, struct nv_instruction
*i
)
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);
921 pc
->emit
[0] |= 0x8000;
924 emit_form_MAD(pc
, i
);
927 pc
->emit
[1] |= 0x08 << 24;
929 emit_form_MUL(pc
, i
);
932 pc
->emit
[0] |= 0x8000;
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;
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
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;
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;
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;
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;
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;
1024 assert(nvi
->opcode
== NV_OP_CVT
);
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
);
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);
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;
1057 pc
->emit
[0] |= 0x08000000;
1059 if (i
->opcode
== NV_OP_TXB
)
1060 pc
->emit
[1] |= 0x20000000;
1062 if (i
->opcode
== NV_OP_TXL
)
1063 pc
->emit
[1] |= 0x40000000;
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;
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);
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);
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;
1130 nv50_emit_instruction(struct nv_pc
*pc
, struct nv_instruction
*i
)
1132 /* nv_print_instruction(i); */
1134 switch (i
->opcode
) {
1136 if (DFILE(i
, 0) == NV_FILE_ADDR
)
1137 emit_add_a16(pc
, i
);
1184 emit_cvt2fixed(pc
, i
);
1194 emit_mul_f32(pc
, i
);
1212 emit_flow(pc
, i
, 0x0);
1215 emit_flow(pc
, i
, 0x1);
1218 emit_flow(pc
, i
, 0x2);
1221 emit_flow(pc
, i
, 0x3);
1223 case NV_OP_BREAKADDR
:
1224 emit_flow(pc
, i
, 0x4);
1227 emit_flow(pc
, i
, 0x5);
1230 emit_flow(pc
, i
, 0xa);
1234 pc
->emit
[0] = 0xf0000001;
1235 pc
->emit
[1] = 0xe0000000;
1240 NOUVEAU_ERR("operation \"%s\" should have been eliminated\n",
1241 nv_opcode_name(i
->opcode
));
1244 NOUVEAU_ERR("unhandled NV_OP: %d\n", i
->opcode
);
1250 assert(i
->is_long
&& !(pc
->emit
[1] & 1));
1254 assert((pc
->emit
[0] & 1) == i
->is_long
);