2 * Copyright 2011 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 OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
23 #include "codegen/nv50_ir.h"
24 #include "codegen/nv50_ir_target_nv50.h"
28 #define NV50_OP_ENC_LONG 0
29 #define NV50_OP_ENC_SHORT 1
30 #define NV50_OP_ENC_IMM 2
31 #define NV50_OP_ENC_LONG_ALT 3
33 class CodeEmitterNV50
: public CodeEmitter
36 CodeEmitterNV50(const TargetNV50
*);
38 virtual bool emitInstruction(Instruction
*);
40 virtual uint32_t getMinEncodingSize(const Instruction
*) const;
42 inline void setProgramType(Program::Type pType
) { progType
= pType
; }
44 virtual void prepareEmission(Function
*);
47 Program::Type progType
;
49 const TargetNV50
*targNV50
;
52 inline void defId(const ValueDef
&, const int pos
);
53 inline void srcId(const ValueRef
&, const int pos
);
54 inline void srcId(const ValueRef
*, const int pos
);
56 inline void srcAddr16(const ValueRef
&, bool adj
, const int pos
);
57 inline void srcAddr8(const ValueRef
&, const int pos
);
59 void emitFlagsRd(const Instruction
*);
60 void emitFlagsWr(const Instruction
*);
62 void emitCondCode(CondCode cc
, DataType ty
, int pos
);
64 inline void setARegBits(unsigned int);
66 void setAReg16(const Instruction
*, int s
);
67 void setImmediate(const Instruction
*, int s
);
69 void setDst(const Value
*);
70 void setDst(const Instruction
*, int d
);
71 void setSrcFileBits(const Instruction
*, int enc
);
72 void setSrc(const Instruction
*, unsigned int s
, int slot
);
74 void emitForm_MAD(const Instruction
*);
75 void emitForm_ADD(const Instruction
*);
76 void emitForm_MUL(const Instruction
*);
77 void emitForm_IMM(const Instruction
*);
79 void emitLoadStoreSizeLG(DataType ty
, int pos
);
80 void emitLoadStoreSizeCS(DataType ty
);
82 void roundMode_MAD(const Instruction
*);
83 void roundMode_CVT(RoundMode
);
85 void emitMNeg12(const Instruction
*);
87 void emitLOAD(const Instruction
*);
88 void emitSTORE(const Instruction
*);
89 void emitMOV(const Instruction
*);
90 void emitRDSV(const Instruction
*);
92 void emitINTERP(const Instruction
*);
93 void emitPFETCH(const Instruction
*);
94 void emitOUT(const Instruction
*);
96 void emitUADD(const Instruction
*);
97 void emitAADD(const Instruction
*);
98 void emitFADD(const Instruction
*);
99 void emitDADD(const Instruction
*);
100 void emitIMUL(const Instruction
*);
101 void emitFMUL(const Instruction
*);
102 void emitDMUL(const Instruction
*);
103 void emitFMAD(const Instruction
*);
104 void emitDMAD(const Instruction
*);
105 void emitIMAD(const Instruction
*);
106 void emitISAD(const Instruction
*);
108 void emitMINMAX(const Instruction
*);
110 void emitPreOp(const Instruction
*);
111 void emitSFnOp(const Instruction
*, uint8_t subOp
);
113 void emitShift(const Instruction
*);
114 void emitARL(const Instruction
*, unsigned int shl
);
115 void emitLogicOp(const Instruction
*);
116 void emitNOT(const Instruction
*);
118 void emitCVT(const Instruction
*);
119 void emitSET(const Instruction
*);
121 void emitTEX(const TexInstruction
*);
122 void emitTXQ(const TexInstruction
*);
123 void emitTEXPREP(const TexInstruction
*);
125 void emitQUADOP(const Instruction
*, uint8_t lane
, uint8_t quOp
);
127 void emitFlow(const Instruction
*, uint8_t flowOp
);
128 void emitPRERETEmu(const FlowInstruction
*);
129 void emitBAR(const Instruction
*);
131 void emitATOM(const Instruction
*);
134 #define SDATA(a) ((a).rep()->reg.data)
135 #define DDATA(a) ((a).rep()->reg.data)
137 void CodeEmitterNV50::srcId(const ValueRef
& src
, const int pos
)
140 code
[pos
/ 32] |= SDATA(src
).id
<< (pos
% 32);
143 void CodeEmitterNV50::srcId(const ValueRef
*src
, const int pos
)
146 code
[pos
/ 32] |= SDATA(*src
).id
<< (pos
% 32);
149 void CodeEmitterNV50::srcAddr16(const ValueRef
& src
, bool adj
, const int pos
)
153 int32_t offset
= SDATA(src
).offset
;
155 assert(!adj
|| src
.get()->reg
.size
<= 4);
157 offset
/= src
.get()->reg
.size
;
159 assert(offset
<= 0x7fff && offset
>= (int32_t)-0x8000 && (pos
% 32) <= 16);
162 offset
&= adj
? (0xffff >> (src
.get()->reg
.size
>> 1)) : 0xffff;
164 code
[pos
/ 32] |= offset
<< (pos
% 32);
167 void CodeEmitterNV50::srcAddr8(const ValueRef
& src
, const int pos
)
171 uint32_t offset
= SDATA(src
).offset
;
173 assert((offset
<= 0x1fc || offset
== 0x3fc) && !(offset
& 0x3));
175 code
[pos
/ 32] |= (offset
>> 2) << (pos
% 32);
178 void CodeEmitterNV50::defId(const ValueDef
& def
, const int pos
)
180 assert(def
.get() && def
.getFile() != FILE_SHADER_OUTPUT
);
182 code
[pos
/ 32] |= DDATA(def
).id
<< (pos
% 32);
186 CodeEmitterNV50::roundMode_MAD(const Instruction
*insn
)
189 case ROUND_M
: code
[1] |= 1 << 22; break;
190 case ROUND_P
: code
[1] |= 2 << 22; break;
191 case ROUND_Z
: code
[1] |= 3 << 22; break;
193 assert(insn
->rnd
== ROUND_N
);
199 CodeEmitterNV50::emitMNeg12(const Instruction
*i
)
201 code
[1] |= i
->src(0).mod
.neg() << 26;
202 code
[1] |= i
->src(1).mod
.neg() << 27;
205 void CodeEmitterNV50::emitCondCode(CondCode cc
, DataType ty
, int pos
)
209 assert(pos
>= 32 || pos
<= 27);
212 case CC_LT
: enc
= 0x1; break;
213 case CC_LTU
: enc
= 0x9; break;
214 case CC_EQ
: enc
= 0x2; break;
215 case CC_EQU
: enc
= 0xa; break;
216 case CC_LE
: enc
= 0x3; break;
217 case CC_LEU
: enc
= 0xb; break;
218 case CC_GT
: enc
= 0x4; break;
219 case CC_GTU
: enc
= 0xc; break;
220 case CC_NE
: enc
= 0x5; break;
221 case CC_NEU
: enc
= 0xd; break;
222 case CC_GE
: enc
= 0x6; break;
223 case CC_GEU
: enc
= 0xe; break;
224 case CC_TR
: enc
= 0xf; break;
225 case CC_FL
: enc
= 0x0; break;
227 case CC_O
: enc
= 0x10; break;
228 case CC_C
: enc
= 0x11; break;
229 case CC_A
: enc
= 0x12; break;
230 case CC_S
: enc
= 0x13; break;
231 case CC_NS
: enc
= 0x1c; break;
232 case CC_NA
: enc
= 0x1d; break;
233 case CC_NC
: enc
= 0x1e; break;
234 case CC_NO
: enc
= 0x1f; break;
238 assert(!"invalid condition code");
241 if (ty
!= TYPE_NONE
&& !isFloatType(ty
))
242 enc
&= ~0x8; // unordered only exists for float types
244 code
[pos
/ 32] |= enc
<< (pos
% 32);
248 CodeEmitterNV50::emitFlagsRd(const Instruction
*i
)
250 int s
= (i
->flagsSrc
>= 0) ? i
->flagsSrc
: i
->predSrc
;
252 assert(!(code
[1] & 0x00003f80));
255 assert(i
->getSrc(s
)->reg
.file
== FILE_FLAGS
);
256 emitCondCode(i
->cc
, TYPE_NONE
, 32 + 7);
257 srcId(i
->src(s
), 32 + 12);
264 CodeEmitterNV50::emitFlagsWr(const Instruction
*i
)
266 assert(!(code
[1] & 0x70));
268 int flagsDef
= i
->flagsDef
;
270 // find flags definition and check that it is the last def
272 for (int d
= 0; i
->defExists(d
); ++d
)
273 if (i
->def(d
).getFile() == FILE_FLAGS
)
275 if (flagsDef
>= 0 && 0) // TODO: enforce use of flagsDef at some point
276 WARN("Instruction::flagsDef was not set properly\n");
278 if (flagsDef
== 0 && i
->defExists(1))
279 WARN("flags def should not be the primary definition\n");
282 code
[1] |= (DDATA(i
->def(flagsDef
)).id
<< 4) | 0x40;
287 CodeEmitterNV50::setARegBits(unsigned int u
)
289 code
[0] |= (u
& 3) << 26;
294 CodeEmitterNV50::setAReg16(const Instruction
*i
, int s
)
296 if (i
->srcExists(s
)) {
297 s
= i
->src(s
).indirect
[0];
299 setARegBits(SDATA(i
->src(s
)).id
+ 1);
304 CodeEmitterNV50::setImmediate(const Instruction
*i
, int s
)
306 const ImmediateValue
*imm
= i
->src(s
).get()->asImm();
309 uint32_t u
= imm
->reg
.data
.u32
;
311 if (i
->src(s
).mod
& Modifier(NV50_IR_MOD_NOT
))
315 code
[0] |= (u
& 0x3f) << 16;
316 code
[1] |= (u
>> 6) << 2;
320 CodeEmitterNV50::setDst(const Value
*dst
)
322 const Storage
*reg
= &dst
->join
->reg
;
324 assert(reg
->file
!= FILE_ADDRESS
);
326 if (reg
->data
.id
< 0 || reg
->file
== FILE_FLAGS
) {
327 code
[0] |= (127 << 2) | 1;
331 if (reg
->file
== FILE_SHADER_OUTPUT
) {
333 id
= reg
->data
.offset
/ 4;
342 CodeEmitterNV50::setDst(const Instruction
*i
, int d
)
344 if (i
->defExists(d
)) {
345 setDst(i
->getDef(d
));
348 code
[0] |= 0x01fc; // bit bucket
359 CodeEmitterNV50::setSrcFileBits(const Instruction
*i
, int enc
)
363 for (unsigned int s
= 0; s
< Target::operationSrcNr
[i
->op
]; ++s
) {
364 switch (i
->src(s
).getFile()) {
367 case FILE_MEMORY_SHARED
:
368 case FILE_SHADER_INPUT
:
369 mode
|= 1 << (s
* 2);
371 case FILE_MEMORY_CONST
:
372 mode
|= 2 << (s
* 2);
375 mode
|= 3 << (s
* 2);
378 ERROR("invalid file on source %i: %u\n", s
, i
->src(s
).getFile());
386 case 0x01: // arr/grr
387 if (progType
== Program::TYPE_GEOMETRY
&& i
->src(0).isIndirect(0)) {
388 code
[0] |= 0x01800000;
389 if (enc
== NV50_OP_ENC_LONG
|| enc
== NV50_OP_ENC_LONG_ALT
)
390 code
[1] |= 0x00200000;
392 if (enc
== NV50_OP_ENC_SHORT
)
393 code
[0] |= 0x01000000;
395 code
[1] |= 0x00200000;
399 assert(i
->op
== OP_MOV
);
404 assert(progType
== Program::TYPE_GEOMETRY
||
405 progType
== Program::TYPE_COMPUTE
);
406 code
[0] |= 0x01000000;
407 if (progType
== Program::TYPE_GEOMETRY
&& i
->src(0).isIndirect(0)) {
408 int reg
= i
->src(0).getIndirect(0)->rep()->reg
.data
.id
;
410 code
[0] |= (reg
+ 1) << 26;
414 code
[0] |= (enc
== NV50_OP_ENC_LONG_ALT
) ? 0x01000000 : 0x00800000;
415 code
[1] |= (i
->getSrc(1)->reg
.fileIndex
<< 22);
417 case 0x09: // acr/gcr
418 if (progType
== Program::TYPE_GEOMETRY
&& i
->src(0).isIndirect(0)) {
419 code
[0] |= 0x01800000;
421 code
[0] |= (enc
== NV50_OP_ENC_LONG_ALT
) ? 0x01000000 : 0x00800000;
422 code
[1] |= 0x00200000;
424 code
[1] |= (i
->getSrc(1)->reg
.fileIndex
<< 22);
427 code
[0] |= 0x01000000;
428 code
[1] |= (i
->getSrc(2)->reg
.fileIndex
<< 22);
431 code
[0] |= 0x01000000;
432 code
[1] |= 0x00200000 | (i
->getSrc(2)->reg
.fileIndex
<< 22);
433 assert(progType
!= Program::TYPE_GEOMETRY
);
436 ERROR("not encodable: %x\n", mode
);
440 if (progType
!= Program::TYPE_COMPUTE
)
443 if ((mode
& 3) == 1) {
444 const int pos
= ((mode
>> 2) & 3) == 3 ? 13 : 14;
457 assert(i
->getSrc(0)->reg
.size
== 4);
464 CodeEmitterNV50::setSrc(const Instruction
*i
, unsigned int s
, int slot
)
466 if (Target::operationSrcNr
[i
->op
] <= s
)
468 const Storage
*reg
= &i
->src(s
).rep()->reg
;
470 unsigned int id
= (reg
->file
== FILE_GPR
) ?
472 reg
->data
.offset
>> (reg
->size
>> 1); // no > 4 byte sources here
475 case 0: code
[0] |= id
<< 9; break;
476 case 1: code
[0] |= id
<< 16; break;
477 case 2: code
[1] |= id
<< 14; break;
485 // - long instruction
486 // - 1 to 3 sources in slots 0, 1, 2 (rrr, arr, rcr, acr, rrc, arc, gcr, grr)
489 CodeEmitterNV50::emitForm_MAD(const Instruction
*i
)
491 assert(i
->encSize
== 8);
499 setSrcFileBits(i
, NV50_OP_ENC_LONG
);
504 if (i
->getIndirect(0, 0)) {
505 assert(!i
->srcExists(1) || !i
->getIndirect(1, 0));
506 assert(!i
->srcExists(2) || !i
->getIndirect(2, 0));
508 } else if (i
->srcExists(1) && i
->getIndirect(1, 0)) {
509 assert(!i
->srcExists(2) || !i
->getIndirect(2, 0));
516 // like default form, but 2nd source in slot 2, and no 3rd source
518 CodeEmitterNV50::emitForm_ADD(const Instruction
*i
)
520 assert(i
->encSize
== 8);
528 setSrcFileBits(i
, NV50_OP_ENC_LONG_ALT
);
533 if (i
->getIndirect(0, 0)) {
534 assert(!i
->getIndirect(1, 0));
541 // default short form (rr, ar, rc, gr)
543 CodeEmitterNV50::emitForm_MUL(const Instruction
*i
)
545 assert(i
->encSize
== 4 && !(code
[0] & 1));
546 assert(i
->defExists(0));
547 assert(!i
->getPredicate());
551 setSrcFileBits(i
, NV50_OP_ENC_SHORT
);
556 // usual immediate form
557 // - 1 to 3 sources where second is immediate (rir, gir)
558 // - no address or predicate possible
560 CodeEmitterNV50::emitForm_IMM(const Instruction
*i
)
562 assert(i
->encSize
== 8);
565 assert(i
->defExists(0) && i
->srcExists(0));
569 setSrcFileBits(i
, NV50_OP_ENC_IMM
);
570 if (Target::operationSrcNr
[i
->op
] > 1) {
573 // If there is another source, it has to be the same as the dest reg.
580 CodeEmitterNV50::emitLoadStoreSizeLG(DataType ty
, int pos
)
585 case TYPE_F32
: // fall through
586 case TYPE_S32
: // fall through
587 case TYPE_U32
: enc
= 0x6; break;
588 case TYPE_B128
: enc
= 0x5; break;
589 case TYPE_F64
: // fall through
590 case TYPE_S64
: // fall through
591 case TYPE_U64
: enc
= 0x4; break;
592 case TYPE_S16
: enc
= 0x3; break;
593 case TYPE_U16
: enc
= 0x2; break;
594 case TYPE_S8
: enc
= 0x1; break;
595 case TYPE_U8
: enc
= 0x0; break;
598 assert(!"invalid load/store type");
601 code
[pos
/ 32] |= enc
<< (pos
% 32);
605 CodeEmitterNV50::emitLoadStoreSizeCS(DataType ty
)
609 case TYPE_U16
: code
[1] |= 0x4000; break;
610 case TYPE_S16
: code
[1] |= 0x8000; break;
613 case TYPE_U32
: code
[1] |= 0xc000; break;
621 CodeEmitterNV50::emitLOAD(const Instruction
*i
)
623 DataFile sf
= i
->src(0).getFile();
624 int32_t offset
= i
->getSrc(0)->reg
.data
.offset
;
627 case FILE_SHADER_INPUT
:
628 if (progType
== Program::TYPE_GEOMETRY
&& i
->src(0).isIndirect(0))
629 code
[0] = 0x11800001;
631 // use 'mov' where we can
632 code
[0] = i
->src(0).isIndirect(0) ? 0x00000001 : 0x10000001;
633 code
[1] = 0x00200000 | (i
->lanes
<< 14);
634 if (typeSizeof(i
->dType
) == 4)
635 code
[1] |= 0x04000000;
637 case FILE_MEMORY_SHARED
:
638 if (targ
->getChipset() >= 0x84) {
639 assert(offset
<= (int32_t)(0x3fff * typeSizeof(i
->sType
)));
640 code
[0] = 0x10000001;
641 code
[1] = 0x40000000;
643 if (typeSizeof(i
->dType
) == 4)
644 code
[1] |= 0x04000000;
646 emitLoadStoreSizeCS(i
->sType
);
648 assert(offset
<= (int32_t)(0x1f * typeSizeof(i
->sType
)));
649 code
[0] = 0x10000001;
650 code
[1] = 0x00200000 | (i
->lanes
<< 14);
651 emitLoadStoreSizeCS(i
->sType
);
654 case FILE_MEMORY_CONST
:
655 code
[0] = 0x10000001;
656 code
[1] = 0x20000000 | (i
->getSrc(0)->reg
.fileIndex
<< 22);
657 if (typeSizeof(i
->dType
) == 4)
658 code
[1] |= 0x04000000;
659 emitLoadStoreSizeCS(i
->sType
);
661 case FILE_MEMORY_LOCAL
:
662 code
[0] = 0xd0000001;
663 code
[1] = 0x40000000;
665 case FILE_MEMORY_GLOBAL
:
666 code
[0] = 0xd0000001 | (i
->getSrc(0)->reg
.fileIndex
<< 16);
667 code
[1] = 0x80000000;
670 assert(!"invalid load source file");
673 if (sf
== FILE_MEMORY_LOCAL
||
674 sf
== FILE_MEMORY_GLOBAL
)
675 emitLoadStoreSizeLG(i
->sType
, 21 + 32);
682 if (i
->src(0).getFile() == FILE_MEMORY_GLOBAL
) {
683 srcId(*i
->src(0).getIndirect(0), 9);
686 srcAddr16(i
->src(0), i
->src(0).getFile() != FILE_MEMORY_LOCAL
, 9);
691 CodeEmitterNV50::emitSTORE(const Instruction
*i
)
693 DataFile f
= i
->getSrc(0)->reg
.file
;
694 int32_t offset
= i
->getSrc(0)->reg
.data
.offset
;
697 case FILE_SHADER_OUTPUT
:
698 code
[0] = 0x00000001 | ((offset
>> 2) << 9);
699 code
[1] = 0x80c00000;
700 srcId(i
->src(1), 32 + 14);
702 case FILE_MEMORY_GLOBAL
:
703 code
[0] = 0xd0000001 | (i
->getSrc(0)->reg
.fileIndex
<< 16);
704 code
[1] = 0xa0000000;
705 emitLoadStoreSizeLG(i
->dType
, 21 + 32);
708 case FILE_MEMORY_LOCAL
:
709 code
[0] = 0xd0000001;
710 code
[1] = 0x60000000;
711 emitLoadStoreSizeLG(i
->dType
, 21 + 32);
714 case FILE_MEMORY_SHARED
:
715 code
[0] = 0x00000001;
716 code
[1] = 0xe0000000;
717 switch (typeSizeof(i
->dType
)) {
719 code
[0] |= offset
<< 9;
720 code
[1] |= 0x00400000;
723 code
[0] |= (offset
>> 1) << 9;
726 code
[0] |= (offset
>> 2) << 9;
727 code
[1] |= 0x04200000;
733 srcId(i
->src(1), 32 + 14);
736 assert(!"invalid store destination file");
740 if (f
== FILE_MEMORY_GLOBAL
)
741 srcId(*i
->src(0).getIndirect(0), 9);
745 if (f
== FILE_MEMORY_LOCAL
)
746 srcAddr16(i
->src(0), false, 9);
752 CodeEmitterNV50::emitMOV(const Instruction
*i
)
754 DataFile sf
= i
->getSrc(0)->reg
.file
;
755 DataFile df
= i
->getDef(0)->reg
.file
;
757 assert(sf
== FILE_GPR
|| df
== FILE_GPR
);
759 if (sf
== FILE_FLAGS
) {
760 assert(i
->flagsSrc
>= 0);
761 code
[0] = 0x00000001;
762 code
[1] = 0x20000000;
766 if (sf
== FILE_ADDRESS
) {
767 code
[0] = 0x00000001;
768 code
[1] = 0x40000000;
770 setARegBits(SDATA(i
->src(0)).id
+ 1);
773 if (df
== FILE_FLAGS
) {
774 assert(i
->flagsDef
>= 0);
775 code
[0] = 0x00000001;
776 code
[1] = 0xa0000000;
781 if (sf
== FILE_IMMEDIATE
) {
782 code
[0] = 0x10008001;
783 code
[1] = 0x00000003;
786 if (i
->encSize
== 4) {
787 code
[0] = 0x10008000;
789 code
[0] = 0x10000001;
790 code
[1] = (typeSizeof(i
->dType
) == 2) ? 0 : 0x04000000;
791 code
[1] |= (i
->lanes
<< 14);
797 if (df
== FILE_SHADER_OUTPUT
) {
798 assert(i
->encSize
== 8);
803 static inline uint8_t getSRegEncoding(const ValueRef
&ref
)
805 switch (SDATA(ref
).sv
.sv
) {
806 case SV_PHYSID
: return 0;
807 case SV_CLOCK
: return 1;
808 case SV_VERTEX_STRIDE
: return 3;
809 // case SV_PM_COUNTER: return 4 + SDATA(ref).sv.index;
810 case SV_SAMPLE_INDEX
: return 8;
812 assert(!"no sreg for system value");
818 CodeEmitterNV50::emitRDSV(const Instruction
*i
)
820 code
[0] = 0x00000001;
821 code
[1] = 0x60000000 | (getSRegEncoding(i
->src(0)) << 14);
827 CodeEmitterNV50::emitNOP()
829 code
[0] = 0xf0000001;
830 code
[1] = 0xe0000000;
834 CodeEmitterNV50::emitQUADOP(const Instruction
*i
, uint8_t lane
, uint8_t quOp
)
836 code
[0] = 0xc0000000 | (lane
<< 16);
837 code
[1] = 0x80000000;
839 code
[0] |= (quOp
& 0x03) << 20;
840 code
[1] |= (quOp
& 0xfc) << 20;
844 if (!i
->srcExists(1) || i
->predSrc
== 1)
845 srcId(i
->src(0), 32 + 14);
848 /* NOTE: This returns the base address of a vertex inside the primitive.
849 * src0 is an immediate, the index (not offset) of the vertex
850 * inside the primitive. XXX: signed or unsigned ?
851 * src1 (may be NULL) should use whatever units the hardware requires
852 * (on nv50 this is bytes, so, relative index * 4; signed 16 bit value).
855 CodeEmitterNV50::emitPFETCH(const Instruction
*i
)
857 const uint32_t prim
= i
->src(0).get()->reg
.data
.u32
;
860 if (i
->def(0).getFile() == FILE_ADDRESS
) {
862 code
[0] = 0x00000001 | ((DDATA(i
->def(0)).id
+ 1) << 2);
863 code
[1] = 0xc0200000;
864 code
[0] |= prim
<< 9;
865 assert(!i
->srcExists(1));
867 if (i
->srcExists(1)) {
868 // ld b32 $rX a[$aX+base]
869 code
[0] = 0x00000001;
870 code
[1] = 0x04200000 | (0xf << 14);
872 code
[0] |= prim
<< 9;
873 setARegBits(SDATA(i
->src(1)).id
+ 1);
876 code
[0] = 0x10000001;
877 code
[1] = 0x04200000 | (0xf << 14);
879 code
[0] |= prim
<< 9;
885 interpApply(const FixupEntry
*entry
, uint32_t *code
, const FixupData
& data
)
887 int ipa
= entry
->ipa
;
888 int encSize
= entry
->reg
;
889 int loc
= entry
->loc
;
891 if ((ipa
& NV50_IR_INTERP_SAMPLE_MASK
) == NV50_IR_INTERP_DEFAULT
&&
892 (ipa
& NV50_IR_INTERP_MODE_MASK
) != NV50_IR_INTERP_FLAT
) {
893 if (data
.force_persample_interp
) {
895 code
[loc
+ 1] |= 1 << 16;
897 code
[loc
+ 0] |= 1 << 24;
900 code
[loc
+ 1] &= ~(1 << 16);
902 code
[loc
+ 0] &= ~(1 << 24);
908 CodeEmitterNV50::emitINTERP(const Instruction
*i
)
910 code
[0] = 0x80000000;
913 srcAddr8(i
->src(0), 16);
916 if (i
->encSize
!= 8 && i
->getInterpMode() == NV50_IR_INTERP_FLAT
) {
919 if (i
->op
== OP_PINTERP
) {
923 if (i
->getSampleMode() == NV50_IR_INTERP_CENTROID
)
927 if (i
->encSize
== 8) {
928 if (i
->getInterpMode() == NV50_IR_INTERP_FLAT
)
931 code
[1] = (code
[0] & (3 << 24)) >> (24 - 16);
932 code
[0] &= ~0x03000000;
937 addInterp(i
->ipa
, i
->encSize
, interpApply
);
941 CodeEmitterNV50::emitMINMAX(const Instruction
*i
)
943 if (i
->dType
== TYPE_F64
) {
944 code
[0] = 0xe0000000;
945 code
[1] = (i
->op
== OP_MIN
) ? 0xa0000000 : 0xc0000000;
947 code
[0] = 0x30000000;
948 code
[1] = 0x80000000;
950 code
[1] |= 0x20000000;
953 case TYPE_F32
: code
[0] |= 0x80000000; break;
954 case TYPE_S32
: code
[1] |= 0x8c000000; break;
955 case TYPE_U32
: code
[1] |= 0x84000000; break;
956 case TYPE_S16
: code
[1] |= 0x80000000; break;
957 case TYPE_U16
: break;
964 code
[1] |= i
->src(0).mod
.abs() << 20;
965 code
[1] |= i
->src(0).mod
.neg() << 26;
966 code
[1] |= i
->src(1).mod
.abs() << 19;
967 code
[1] |= i
->src(1).mod
.neg() << 27;
973 CodeEmitterNV50::emitFMAD(const Instruction
*i
)
975 const int neg_mul
= i
->src(0).mod
.neg() ^ i
->src(1).mod
.neg();
976 const int neg_add
= i
->src(2).mod
.neg();
978 code
[0] = 0xe0000000;
980 if (i
->src(1).getFile() == FILE_IMMEDIATE
) {
983 code
[0] |= neg_mul
<< 15;
984 code
[0] |= neg_add
<< 22;
988 if (i
->encSize
== 4) {
990 code
[0] |= neg_mul
<< 15;
991 code
[0] |= neg_add
<< 22;
995 code
[1] = neg_mul
<< 26;
996 code
[1] |= neg_add
<< 27;
1004 CodeEmitterNV50::emitDMAD(const Instruction
*i
)
1006 const int neg_mul
= i
->src(0).mod
.neg() ^ i
->src(1).mod
.neg();
1007 const int neg_add
= i
->src(2).mod
.neg();
1009 assert(i
->encSize
== 8);
1010 assert(!i
->saturate
);
1012 code
[1] = 0x40000000;
1013 code
[0] = 0xe0000000;
1015 code
[1] |= neg_mul
<< 26;
1016 code
[1] |= neg_add
<< 27;
1024 CodeEmitterNV50::emitFADD(const Instruction
*i
)
1026 const int neg0
= i
->src(0).mod
.neg();
1027 const int neg1
= i
->src(1).mod
.neg() ^ ((i
->op
== OP_SUB
) ? 1 : 0);
1029 code
[0] = 0xb0000000;
1031 assert(!(i
->src(0).mod
| i
->src(1).mod
).abs());
1033 if (i
->src(1).getFile() == FILE_IMMEDIATE
) {
1036 code
[0] |= neg0
<< 15;
1037 code
[0] |= neg1
<< 22;
1041 if (i
->encSize
== 8) {
1044 code
[1] |= neg0
<< 26;
1045 code
[1] |= neg1
<< 27;
1050 code
[0] |= neg0
<< 15;
1051 code
[0] |= neg1
<< 22;
1058 CodeEmitterNV50::emitDADD(const Instruction
*i
)
1060 const int neg0
= i
->src(0).mod
.neg();
1061 const int neg1
= i
->src(1).mod
.neg() ^ ((i
->op
== OP_SUB
) ? 1 : 0);
1063 assert(!(i
->src(0).mod
| i
->src(1).mod
).abs());
1064 assert(!i
->saturate
);
1065 assert(i
->encSize
== 8);
1067 code
[1] = 0x60000000;
1068 code
[0] = 0xe0000000;
1072 code
[1] |= neg0
<< 26;
1073 code
[1] |= neg1
<< 27;
1077 CodeEmitterNV50::emitUADD(const Instruction
*i
)
1079 const int neg0
= i
->src(0).mod
.neg();
1080 const int neg1
= i
->src(1).mod
.neg() ^ ((i
->op
== OP_SUB
) ? 1 : 0);
1082 code
[0] = 0x20008000;
1084 if (i
->src(1).getFile() == FILE_IMMEDIATE
) {
1088 if (i
->encSize
== 8) {
1089 code
[0] = 0x20000000;
1090 code
[1] = (typeSizeof(i
->dType
) == 2) ? 0 : 0x04000000;
1095 assert(!(neg0
&& neg1
));
1096 code
[0] |= neg0
<< 28;
1097 code
[0] |= neg1
<< 22;
1099 if (i
->flagsSrc
>= 0) {
1100 // addc == sub | subr
1101 assert(!(code
[0] & 0x10400000) && !i
->getPredicate());
1102 code
[0] |= 0x10400000;
1103 srcId(i
->src(i
->flagsSrc
), 32 + 12);
1108 CodeEmitterNV50::emitAADD(const Instruction
*i
)
1110 const int s
= (i
->op
== OP_MOV
) ? 0 : 1;
1112 code
[0] = 0xd0000001 | (i
->getSrc(s
)->reg
.data
.u16
<< 9);
1113 code
[1] = 0x20000000;
1115 code
[0] |= (DDATA(i
->def(0)).id
+ 1) << 2;
1119 if (s
&& i
->srcExists(0))
1120 setARegBits(SDATA(i
->src(0)).id
+ 1);
1124 CodeEmitterNV50::emitIMUL(const Instruction
*i
)
1126 code
[0] = 0x40000000;
1128 if (i
->src(1).getFile() == FILE_IMMEDIATE
) {
1129 if (i
->sType
== TYPE_S16
)
1134 if (i
->encSize
== 8) {
1135 code
[1] = (i
->sType
== TYPE_S16
) ? (0x8000 | 0x4000) : 0x0000;
1138 if (i
->sType
== TYPE_S16
)
1145 CodeEmitterNV50::emitFMUL(const Instruction
*i
)
1147 const int neg
= (i
->src(0).mod
^ i
->src(1).mod
).neg();
1149 code
[0] = 0xc0000000;
1151 if (i
->src(1).getFile() == FILE_IMMEDIATE
) {
1159 if (i
->encSize
== 8) {
1160 code
[1] = i
->rnd
== ROUND_Z
? 0x0000c000 : 0;
1162 code
[1] |= 0x08000000;
1176 CodeEmitterNV50::emitDMUL(const Instruction
*i
)
1178 const int neg
= (i
->src(0).mod
^ i
->src(1).mod
).neg();
1180 assert(!i
->saturate
);
1181 assert(i
->encSize
== 8);
1183 code
[1] = 0x80000000;
1184 code
[0] = 0xe0000000;
1187 code
[1] |= 0x08000000;
1189 roundMode_CVT(i
->rnd
);
1195 CodeEmitterNV50::emitIMAD(const Instruction
*i
)
1198 code
[0] = 0x60000000;
1200 assert(!i
->src(0).mod
&& !i
->src(1).mod
&& !i
->src(2).mod
);
1201 if (!isSignedType(i
->sType
))
1203 else if (i
->saturate
)
1208 if (i
->src(1).getFile() == FILE_IMMEDIATE
) {
1211 code
[0] |= (mode
& 1) << 8 | (mode
& 2) << 14;
1212 if (i
->flagsSrc
>= 0) {
1213 assert(!(code
[0] & 0x10400000));
1214 assert(SDATA(i
->src(i
->flagsSrc
)).id
== 0);
1215 code
[0] |= 0x10400000;
1218 if (i
->encSize
== 4) {
1220 code
[0] |= (mode
& 1) << 8 | (mode
& 2) << 14;
1221 if (i
->flagsSrc
>= 0) {
1222 assert(!(code
[0] & 0x10400000));
1223 assert(SDATA(i
->src(i
->flagsSrc
)).id
== 0);
1224 code
[0] |= 0x10400000;
1227 code
[1] = mode
<< 29;
1230 if (i
->flagsSrc
>= 0) {
1231 // add with carry from $cX
1232 assert(!(code
[1] & 0x0c000000) && !i
->getPredicate());
1233 code
[1] |= 0xc << 24;
1234 srcId(i
->src(i
->flagsSrc
), 32 + 12);
1240 CodeEmitterNV50::emitISAD(const Instruction
*i
)
1242 if (i
->encSize
== 8) {
1243 code
[0] = 0x50000000;
1245 case TYPE_U32
: code
[1] = 0x04000000; break;
1246 case TYPE_S32
: code
[1] = 0x0c000000; break;
1247 case TYPE_U16
: code
[1] = 0x00000000; break;
1248 case TYPE_S16
: code
[1] = 0x08000000; break;
1256 case TYPE_U32
: code
[0] = 0x50008000; break;
1257 case TYPE_S32
: code
[0] = 0x50008100; break;
1258 case TYPE_U16
: code
[0] = 0x50000000; break;
1259 case TYPE_S16
: code
[0] = 0x50000100; break;
1269 alphatestSet(const FixupEntry
*entry
, uint32_t *code
, const FixupData
& data
)
1271 int loc
= entry
->loc
;
1274 switch (data
.alphatest
) {
1275 case PIPE_FUNC_NEVER
: enc
= 0x0; break;
1276 case PIPE_FUNC_LESS
: enc
= 0x1; break;
1277 case PIPE_FUNC_EQUAL
: enc
= 0x2; break;
1278 case PIPE_FUNC_LEQUAL
: enc
= 0x3; break;
1279 case PIPE_FUNC_GREATER
: enc
= 0x4; break;
1280 case PIPE_FUNC_NOTEQUAL
: enc
= 0x5; break;
1281 case PIPE_FUNC_GEQUAL
: enc
= 0x6; break;
1283 case PIPE_FUNC_ALWAYS
: enc
= 0xf; break;
1286 code
[loc
+ 1] &= ~(0x1f << 14);
1287 code
[loc
+ 1] |= enc
<< 14;
1291 CodeEmitterNV50::emitSET(const Instruction
*i
)
1293 code
[0] = 0x30000000;
1294 code
[1] = 0x60000000;
1298 code
[0] = 0xe0000000;
1299 code
[1] = 0xe0000000;
1301 case TYPE_F32
: code
[0] |= 0x80000000; break;
1302 case TYPE_S32
: code
[1] |= 0x0c000000; break;
1303 case TYPE_U32
: code
[1] |= 0x04000000; break;
1304 case TYPE_S16
: code
[1] |= 0x08000000; break;
1305 case TYPE_U16
: break;
1311 emitCondCode(i
->asCmp()->setCond
, i
->sType
, 32 + 14);
1313 if (i
->src(0).mod
.neg()) code
[1] |= 0x04000000;
1314 if (i
->src(1).mod
.neg()) code
[1] |= 0x08000000;
1315 if (i
->src(0).mod
.abs()) code
[1] |= 0x00100000;
1316 if (i
->src(1).mod
.abs()) code
[1] |= 0x00080000;
1320 if (i
->subOp
== 1) {
1321 addInterp(0, 0, alphatestSet
);
1326 CodeEmitterNV50::roundMode_CVT(RoundMode rnd
)
1329 case ROUND_NI
: code
[1] |= 0x08000000; break;
1330 case ROUND_M
: code
[1] |= 0x00020000; break;
1331 case ROUND_MI
: code
[1] |= 0x08020000; break;
1332 case ROUND_P
: code
[1] |= 0x00040000; break;
1333 case ROUND_PI
: code
[1] |= 0x08040000; break;
1334 case ROUND_Z
: code
[1] |= 0x00060000; break;
1335 case ROUND_ZI
: code
[1] |= 0x08060000; break;
1337 assert(rnd
== ROUND_N
);
1343 CodeEmitterNV50::emitCVT(const Instruction
*i
)
1345 const bool f2f
= isFloatType(i
->dType
) && isFloatType(i
->sType
);
1350 case OP_CEIL
: rnd
= f2f
? ROUND_PI
: ROUND_P
; break;
1351 case OP_FLOOR
: rnd
= f2f
? ROUND_MI
: ROUND_M
; break;
1352 case OP_TRUNC
: rnd
= f2f
? ROUND_ZI
: ROUND_Z
; break;
1358 if (i
->op
== OP_NEG
&& i
->dType
== TYPE_U32
)
1363 code
[0] = 0xa0000000;
1368 case TYPE_F64
: code
[1] = 0xc4404000; break;
1369 case TYPE_S64
: code
[1] = 0x44414000; break;
1370 case TYPE_U64
: code
[1] = 0x44404000; break;
1371 case TYPE_F32
: code
[1] = 0xc4400000; break;
1372 case TYPE_S32
: code
[1] = 0x44410000; break;
1373 case TYPE_U32
: code
[1] = 0x44400000; break;
1381 case TYPE_F64
: code
[1] = 0x8c404000; break;
1382 case TYPE_F32
: code
[1] = 0x8c400000; break;
1390 case TYPE_F64
: code
[1] = 0x84404000; break;
1391 case TYPE_F32
: code
[1] = 0x84400000; break;
1399 case TYPE_F64
: code
[1] = 0xc0404000; break;
1400 case TYPE_S64
: code
[1] = 0x40414000; break;
1401 case TYPE_U64
: code
[1] = 0x40404000; break;
1402 case TYPE_F32
: code
[1] = 0xc4004000; break;
1403 case TYPE_S32
: code
[1] = 0x44014000; break;
1404 case TYPE_U32
: code
[1] = 0x44004000; break;
1405 case TYPE_F16
: code
[1] = 0xc4000000; break;
1406 case TYPE_U16
: code
[1] = 0x44000000; break;
1414 case TYPE_F64
: code
[1] = 0x88404000; break;
1415 case TYPE_F32
: code
[1] = 0x8c004000; break;
1416 case TYPE_S32
: code
[1] = 0x0c014000; break;
1417 case TYPE_U32
: code
[1] = 0x0c004000; break;
1418 case TYPE_F16
: code
[1] = 0x8c000000; break;
1419 case TYPE_S16
: code
[1] = 0x0c010000; break;
1420 case TYPE_U16
: code
[1] = 0x0c000000; break;
1421 case TYPE_S8
: code
[1] = 0x0c018000; break;
1422 case TYPE_U8
: code
[1] = 0x0c008000; break;
1430 case TYPE_F64
: code
[1] = 0x80404000; break;
1431 case TYPE_F32
: code
[1] = 0x84004000; break;
1432 case TYPE_S32
: code
[1] = 0x04014000; break;
1433 case TYPE_U32
: code
[1] = 0x04004000; break;
1434 case TYPE_F16
: code
[1] = 0x84000000; break;
1435 case TYPE_S16
: code
[1] = 0x04010000; break;
1436 case TYPE_U16
: code
[1] = 0x04000000; break;
1437 case TYPE_S8
: code
[1] = 0x04018000; break;
1438 case TYPE_U8
: code
[1] = 0x04008000; break;
1452 if (typeSizeof(i
->sType
) == 1 && i
->getSrc(0)->reg
.size
== 4)
1453 code
[1] |= 0x00004000;
1458 case OP_ABS
: code
[1] |= 1 << 20; break;
1459 case OP_SAT
: code
[1] |= 1 << 19; break;
1460 case OP_NEG
: code
[1] |= 1 << 29; break;
1464 code
[1] ^= i
->src(0).mod
.neg() << 29;
1465 code
[1] |= i
->src(0).mod
.abs() << 20;
1469 assert(i
->op
!= OP_ABS
|| !i
->src(0).mod
.neg());
1475 CodeEmitterNV50::emitPreOp(const Instruction
*i
)
1477 code
[0] = 0xb0000000;
1478 code
[1] = (i
->op
== OP_PREEX2
) ? 0xc0004000 : 0xc0000000;
1480 code
[1] |= i
->src(0).mod
.abs() << 20;
1481 code
[1] |= i
->src(0).mod
.neg() << 26;
1487 CodeEmitterNV50::emitSFnOp(const Instruction
*i
, uint8_t subOp
)
1489 code
[0] = 0x90000000;
1491 if (i
->encSize
== 4) {
1492 assert(i
->op
== OP_RCP
);
1493 assert(!i
->saturate
);
1494 code
[0] |= i
->src(0).mod
.abs() << 15;
1495 code
[0] |= i
->src(0).mod
.neg() << 22;
1498 code
[1] = subOp
<< 29;
1499 code
[1] |= i
->src(0).mod
.abs() << 20;
1500 code
[1] |= i
->src(0).mod
.neg() << 26;
1502 assert(subOp
== 6 && i
->op
== OP_EX2
);
1510 CodeEmitterNV50::emitNOT(const Instruction
*i
)
1512 code
[0] = 0xd0000000;
1513 code
[1] = 0x0002c000;
1518 code
[1] |= 0x04000000;
1528 CodeEmitterNV50::emitLogicOp(const Instruction
*i
)
1530 code
[0] = 0xd0000000;
1533 if (i
->src(1).getFile() == FILE_IMMEDIATE
) {
1535 case OP_OR
: code
[0] |= 0x0100; break;
1536 case OP_XOR
: code
[0] |= 0x8000; break;
1538 assert(i
->op
== OP_AND
);
1541 if (i
->src(0).mod
& Modifier(NV50_IR_MOD_NOT
))
1547 case OP_AND
: code
[1] = 0x04000000; break;
1548 case OP_OR
: code
[1] = 0x04004000; break;
1549 case OP_XOR
: code
[1] = 0x04008000; break;
1554 if (i
->src(0).mod
& Modifier(NV50_IR_MOD_NOT
))
1556 if (i
->src(1).mod
& Modifier(NV50_IR_MOD_NOT
))
1564 CodeEmitterNV50::emitARL(const Instruction
*i
, unsigned int shl
)
1566 code
[0] = 0x00000001 | (shl
<< 16);
1567 code
[1] = 0xc0000000;
1569 code
[0] |= (DDATA(i
->def(0)).id
+ 1) << 2;
1571 setSrcFileBits(i
, NV50_OP_ENC_IMM
);
1577 CodeEmitterNV50::emitShift(const Instruction
*i
)
1579 if (i
->def(0).getFile() == FILE_ADDRESS
) {
1580 assert(i
->srcExists(1) && i
->src(1).getFile() == FILE_IMMEDIATE
);
1581 emitARL(i
, i
->getSrc(1)->reg
.data
.u32
& 0x3f);
1583 code
[0] = 0x30000001;
1584 code
[1] = (i
->op
== OP_SHR
) ? 0xe4000000 : 0xc4000000;
1585 if (i
->op
== OP_SHR
&& isSignedType(i
->sType
))
1588 if (i
->src(1).getFile() == FILE_IMMEDIATE
) {
1590 code
[0] |= (i
->getSrc(1)->reg
.data
.u32
& 0x7f) << 16;
1591 defId(i
->def(0), 2);
1592 srcId(i
->src(0), 9);
1601 CodeEmitterNV50::emitOUT(const Instruction
*i
)
1603 code
[0] = (i
->op
== OP_EMIT
) ? 0xf0000201 : 0xf0000401;
1604 code
[1] = 0xc0000000;
1610 CodeEmitterNV50::emitTEX(const TexInstruction
*i
)
1612 code
[0] = 0xf0000001;
1613 code
[1] = 0x00000000;
1617 code
[1] = 0x20000000;
1620 code
[1] = 0x40000000;
1623 code
[0] |= 0x01000000;
1626 code
[0] |= 0x01000000;
1627 code
[1] = 0x80000000;
1630 code
[1] = 0x60020000;
1633 assert(i
->op
== OP_TEX
);
1637 code
[0] |= i
->tex
.r
<< 9;
1638 code
[0] |= i
->tex
.s
<< 17;
1640 int argc
= i
->tex
.target
.getArgCount();
1642 if (i
->op
== OP_TXB
|| i
->op
== OP_TXL
|| i
->op
== OP_TXF
)
1644 if (i
->tex
.target
.isShadow())
1648 code
[0] |= (argc
- 1) << 22;
1650 if (i
->tex
.target
.isCube()) {
1651 code
[0] |= 0x08000000;
1653 if (i
->tex
.useOffsets
) {
1654 code
[1] |= (i
->tex
.offset
[0] & 0xf) << 24;
1655 code
[1] |= (i
->tex
.offset
[1] & 0xf) << 20;
1656 code
[1] |= (i
->tex
.offset
[2] & 0xf) << 16;
1659 code
[0] |= (i
->tex
.mask
& 0x3) << 25;
1660 code
[1] |= (i
->tex
.mask
& 0xc) << 12;
1662 if (i
->tex
.liveOnly
)
1664 if (i
->tex
.derivAll
)
1667 defId(i
->def(0), 2);
1673 CodeEmitterNV50::emitTXQ(const TexInstruction
*i
)
1675 assert(i
->tex
.query
== TXQ_DIMS
);
1677 code
[0] = 0xf0000001;
1678 code
[1] = 0x60000000;
1680 code
[0] |= i
->tex
.r
<< 9;
1681 code
[0] |= i
->tex
.s
<< 17;
1683 code
[0] |= (i
->tex
.mask
& 0x3) << 25;
1684 code
[1] |= (i
->tex
.mask
& 0xc) << 12;
1686 defId(i
->def(0), 2);
1692 CodeEmitterNV50::emitTEXPREP(const TexInstruction
*i
)
1694 code
[0] = 0xf8000001 | (3 << 22) | (i
->tex
.s
<< 17) | (i
->tex
.r
<< 9);
1695 code
[1] = 0x60010000;
1697 code
[0] |= (i
->tex
.mask
& 0x3) << 25;
1698 code
[1] |= (i
->tex
.mask
& 0xc) << 12;
1699 defId(i
->def(0), 2);
1705 CodeEmitterNV50::emitPRERETEmu(const FlowInstruction
*i
)
1707 uint32_t pos
= i
->target
.bb
->binPos
+ 8; // +8 to skip an op */
1709 code
[0] = 0x10000003; // bra
1710 code
[1] = 0x00000780; // always
1713 case NV50_IR_SUBOP_EMU_PRERET
+ 0: // bra to the call
1715 case NV50_IR_SUBOP_EMU_PRERET
+ 1: // bra to skip the call
1719 assert(i
->subOp
== (NV50_IR_SUBOP_EMU_PRERET
+ 2));
1720 code
[0] = 0x20000003; // call
1721 code
[1] = 0x00000000; // no predicate
1724 addReloc(RelocEntry::TYPE_CODE
, 0, pos
, 0x07fff800, 9);
1725 addReloc(RelocEntry::TYPE_CODE
, 1, pos
, 0x000fc000, -4);
1729 CodeEmitterNV50::emitFlow(const Instruction
*i
, uint8_t flowOp
)
1731 const FlowInstruction
*f
= i
->asFlow();
1732 bool hasPred
= false;
1733 bool hasTarg
= false;
1735 code
[0] = 0x00000003 | (flowOp
<< 28);
1736 code
[1] = 0x00000000;
1756 if (i
->subOp
>= NV50_IR_SUBOP_EMU_PRERET
) {
1771 if (f
->op
== OP_CALL
) {
1773 pos
= targNV50
->getBuiltinOffset(f
->target
.builtin
);
1775 pos
= f
->target
.fn
->binPos
;
1778 pos
= f
->target
.bb
->binPos
;
1781 code
[0] |= ((pos
>> 2) & 0xffff) << 11;
1782 code
[1] |= ((pos
>> 18) & 0x003f) << 14;
1784 RelocEntry::Type relocTy
;
1786 relocTy
= f
->builtin
? RelocEntry::TYPE_BUILTIN
: RelocEntry::TYPE_CODE
;
1788 addReloc(relocTy
, 0, pos
, 0x07fff800, 9);
1789 addReloc(relocTy
, 1, pos
, 0x000fc000, -4);
1794 CodeEmitterNV50::emitBAR(const Instruction
*i
)
1796 ImmediateValue
*barId
= i
->getSrc(0)->asImm();
1799 code
[0] = 0x82000003 | (barId
->reg
.data
.u32
<< 21);
1800 code
[1] = 0x00004000;
1802 if (i
->subOp
== NV50_IR_SUBOP_BAR_SYNC
)
1807 CodeEmitterNV50::emitATOM(const Instruction
*i
)
1811 case NV50_IR_SUBOP_ATOM_ADD
: subOp
= 0x0; break;
1812 case NV50_IR_SUBOP_ATOM_MIN
: subOp
= 0x7; break;
1813 case NV50_IR_SUBOP_ATOM_MAX
: subOp
= 0x6; break;
1814 case NV50_IR_SUBOP_ATOM_INC
: subOp
= 0x4; break;
1815 case NV50_IR_SUBOP_ATOM_DEC
: subOp
= 0x5; break;
1816 case NV50_IR_SUBOP_ATOM_AND
: subOp
= 0xa; break;
1817 case NV50_IR_SUBOP_ATOM_OR
: subOp
= 0xb; break;
1818 case NV50_IR_SUBOP_ATOM_XOR
: subOp
= 0xc; break;
1819 case NV50_IR_SUBOP_ATOM_CAS
: subOp
= 0x2; break;
1820 case NV50_IR_SUBOP_ATOM_EXCH
: subOp
= 0x1; break;
1822 assert(!"invalid subop");
1825 code
[0] = 0xd0000001;
1826 code
[1] = 0xe0c00000 | (subOp
<< 2);
1827 if (isSignedType(i
->dType
))
1834 if (i
->subOp
== NV50_IR_SUBOP_ATOM_CAS
)
1838 code
[0] |= i
->getSrc(0)->reg
.fileIndex
<< 23;
1839 srcId(i
->getIndirect(0, 0), 9);
1843 CodeEmitterNV50::emitInstruction(Instruction
*insn
)
1845 if (!insn
->encSize
) {
1846 ERROR("skipping unencodable instruction: "); insn
->print();
1849 if (codeSize
+ insn
->encSize
> codeSizeLimit
) {
1850 ERROR("code emitter output buffer too small\n");
1854 if (insn
->bb
->getProgram()->dbgFlags
& NV50_IR_DEBUG_BASIC
) {
1855 INFO("EMIT: "); insn
->print();
1887 if (insn
->dType
== TYPE_F64
)
1889 else if (isFloatType(insn
->dType
))
1891 else if (insn
->getDef(0)->reg
.file
== FILE_ADDRESS
)
1897 if (insn
->dType
== TYPE_F64
)
1899 else if (isFloatType(insn
->dType
))
1906 if (insn
->dType
== TYPE_F64
)
1908 else if (isFloatType(insn
->dType
))
1944 if (insn
->def(0).getFile() == FILE_ADDRESS
)
1947 if (insn
->def(0).getFile() == FILE_FLAGS
||
1948 insn
->src(0).getFile() == FILE_FLAGS
||
1949 insn
->src(0).getFile() == FILE_ADDRESS
)
1982 emitTEX(insn
->asTex());
1985 emitTXQ(insn
->asTex());
1988 emitTEXPREP(insn
->asTex());
1995 emitFlow(insn
, 0x0);
1998 emitFlow(insn
, 0x1);
2001 emitFlow(insn
, 0x2);
2004 emitFlow(insn
, 0x3);
2007 emitFlow(insn
, 0x4);
2010 emitFlow(insn
, 0x5);
2013 emitFlow(insn
, 0x6);
2016 emitFlow(insn
, 0x7);
2019 emitFlow(insn
, 0xa);
2022 emitFlow(insn
, 0xd);
2025 emitQUADOP(insn
, insn
->lanes
, insn
->subOp
);
2028 emitQUADOP(insn
, 4, insn
->src(0).mod
.neg() ? 0x66 : 0x99);
2031 emitQUADOP(insn
, 5, insn
->src(0).mod
.neg() ? 0x5a : 0xa5);
2042 ERROR("operation should have been eliminated\n");
2056 ERROR("operation should have been lowered\n");
2059 ERROR("unknown op: %u\n", insn
->op
);
2062 if (insn
->join
|| insn
->op
== OP_JOIN
)
2065 if (insn
->exit
|| insn
->op
== OP_EXIT
)
2068 assert((insn
->encSize
== 8) == (code
[0] & 1));
2070 code
+= insn
->encSize
/ 4;
2071 codeSize
+= insn
->encSize
;
2076 CodeEmitterNV50::getMinEncodingSize(const Instruction
*i
) const
2078 const Target::OpInfo
&info
= targ
->getOpInfo(i
);
2080 if (info
.minEncSize
> 4 || i
->dType
== TYPE_F64
)
2083 // check constraints on dst and src operands
2084 for (int d
= 0; i
->defExists(d
); ++d
) {
2085 if (i
->def(d
).rep()->reg
.data
.id
> 63 ||
2086 i
->def(d
).rep()->reg
.file
!= FILE_GPR
)
2090 for (int s
= 0; i
->srcExists(s
); ++s
) {
2091 DataFile sf
= i
->src(s
).getFile();
2093 if (sf
!= FILE_SHADER_INPUT
|| progType
!= Program::TYPE_FRAGMENT
)
2095 if (i
->src(s
).rep()->reg
.data
.id
> 63)
2099 // check modifiers & rounding
2100 if (i
->join
|| i
->lanes
!= 0xf || i
->exit
)
2102 if (i
->op
== OP_MUL
&& i
->rnd
!= ROUND_N
)
2106 return 8; // TODO: short tex encoding
2108 // check constraints on short MAD
2109 if (info
.srcNr
>= 2 && i
->srcExists(2)) {
2110 if (!i
->defExists(0) ||
2111 (i
->flagsSrc
>= 0 && SDATA(i
->src(i
->flagsSrc
)).id
> 0) ||
2112 DDATA(i
->def(0)).id
!= SDATA(i
->src(2)).id
)
2116 return info
.minEncSize
;
2119 // Change the encoding size of an instruction after BBs have been scheduled.
2121 makeInstructionLong(Instruction
*insn
)
2123 if (insn
->encSize
== 8)
2125 Function
*fn
= insn
->bb
->getFunction();
2129 for (Instruction
*i
= insn
->next
; i
&& i
->encSize
== 4; ++n
, i
= i
->next
);
2133 insn
->next
->encSize
= 8;
2135 if (insn
->prev
&& insn
->prev
->encSize
== 4) {
2137 insn
->prev
->encSize
= 8;
2141 for (int i
= fn
->bbCount
- 1; i
>= 0 && fn
->bbArray
[i
] != insn
->bb
; --i
) {
2142 fn
->bbArray
[i
]->binPos
+= adj
;
2145 insn
->bb
->binSize
+= adj
;
2149 trySetExitModifier(Instruction
*insn
)
2151 if (insn
->op
== OP_DISCARD
||
2152 insn
->op
== OP_QUADON
||
2153 insn
->op
== OP_QUADPOP
)
2155 for (int s
= 0; insn
->srcExists(s
); ++s
)
2156 if (insn
->src(s
).getFile() == FILE_IMMEDIATE
)
2158 if (insn
->asFlow()) {
2159 if (insn
->op
== OP_CALL
) // side effects !
2161 if (insn
->getPredicate()) // cannot do conditional exit (or can we ?)
2166 makeInstructionLong(insn
);
2171 replaceExitWithModifier(Function
*func
)
2173 BasicBlock
*epilogue
= BasicBlock::get(func
->cfgExit
);
2175 if (!epilogue
->getExit() ||
2176 epilogue
->getExit()->op
!= OP_EXIT
) // only main will use OP_EXIT
2179 if (epilogue
->getEntry()->op
!= OP_EXIT
) {
2180 Instruction
*insn
= epilogue
->getExit()->prev
;
2181 if (!insn
|| !trySetExitModifier(insn
))
2185 for (Graph::EdgeIterator ei
= func
->cfgExit
->incident();
2186 !ei
.end(); ei
.next()) {
2187 BasicBlock
*bb
= BasicBlock::get(ei
.getNode());
2188 Instruction
*i
= bb
->getExit();
2190 if (!i
|| !trySetExitModifier(i
))
2195 int adj
= epilogue
->getExit()->encSize
;
2196 epilogue
->binSize
-= adj
;
2197 func
->binSize
-= adj
;
2198 delete_Instruction(func
->getProgram(), epilogue
->getExit());
2200 // There may be BB's that are laid out after the exit block
2201 for (int i
= func
->bbCount
- 1; i
>= 0 && func
->bbArray
[i
] != epilogue
; --i
) {
2202 func
->bbArray
[i
]->binPos
-= adj
;
2207 CodeEmitterNV50::prepareEmission(Function
*func
)
2209 CodeEmitter::prepareEmission(func
);
2211 replaceExitWithModifier(func
);
2214 CodeEmitterNV50::CodeEmitterNV50(const TargetNV50
*target
) :
2215 CodeEmitter(target
), targNV50(target
)
2217 targ
= target
; // specialized
2219 codeSize
= codeSizeLimit
= 0;
2224 TargetNV50::getCodeEmitter(Program::Type type
)
2226 CodeEmitterNV50
*emit
= new CodeEmitterNV50(this);
2227 emit
->setProgramType(type
);
2231 } // namespace nv50_ir