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
*);
91 void emitINTERP(const Instruction
*);
92 void emitPFETCH(const Instruction
*);
93 void emitOUT(const Instruction
*);
95 void emitUADD(const Instruction
*);
96 void emitAADD(const Instruction
*);
97 void emitFADD(const Instruction
*);
98 void emitIMUL(const Instruction
*);
99 void emitFMUL(const Instruction
*);
100 void emitFMAD(const Instruction
*);
101 void emitIMAD(const Instruction
*);
102 void emitISAD(const Instruction
*);
104 void emitMINMAX(const Instruction
*);
106 void emitPreOp(const Instruction
*);
107 void emitSFnOp(const Instruction
*, uint8_t subOp
);
109 void emitShift(const Instruction
*);
110 void emitARL(const Instruction
*, unsigned int shl
);
111 void emitLogicOp(const Instruction
*);
112 void emitNOT(const Instruction
*);
114 void emitCVT(const Instruction
*);
115 void emitSET(const Instruction
*);
117 void emitTEX(const TexInstruction
*);
118 void emitTXQ(const TexInstruction
*);
119 void emitTEXPREP(const TexInstruction
*);
121 void emitQUADOP(const Instruction
*, uint8_t lane
, uint8_t quOp
);
123 void emitFlow(const Instruction
*, uint8_t flowOp
);
124 void emitPRERETEmu(const FlowInstruction
*);
125 void emitBAR(const Instruction
*);
127 void emitATOM(const Instruction
*);
130 #define SDATA(a) ((a).rep()->reg.data)
131 #define DDATA(a) ((a).rep()->reg.data)
133 void CodeEmitterNV50::srcId(const ValueRef
& src
, const int pos
)
136 code
[pos
/ 32] |= SDATA(src
).id
<< (pos
% 32);
139 void CodeEmitterNV50::srcId(const ValueRef
*src
, const int pos
)
142 code
[pos
/ 32] |= SDATA(*src
).id
<< (pos
% 32);
145 void CodeEmitterNV50::srcAddr16(const ValueRef
& src
, bool adj
, const int pos
)
149 int32_t offset
= SDATA(src
).offset
;
151 assert(!adj
|| src
.get()->reg
.size
<= 4);
153 offset
/= src
.get()->reg
.size
;
155 assert(offset
<= 0x7fff && offset
>= (int32_t)-0x8000 && (pos
% 32) <= 16);
158 offset
&= adj
? (0xffff >> (src
.get()->reg
.size
>> 1)) : 0xffff;
160 code
[pos
/ 32] |= offset
<< (pos
% 32);
163 void CodeEmitterNV50::srcAddr8(const ValueRef
& src
, const int pos
)
167 uint32_t offset
= SDATA(src
).offset
;
169 assert((offset
<= 0x1fc || offset
== 0x3fc) && !(offset
& 0x3));
171 code
[pos
/ 32] |= (offset
>> 2) << (pos
% 32);
174 void CodeEmitterNV50::defId(const ValueDef
& def
, const int pos
)
176 assert(def
.get() && def
.getFile() != FILE_SHADER_OUTPUT
);
178 code
[pos
/ 32] |= DDATA(def
).id
<< (pos
% 32);
182 CodeEmitterNV50::roundMode_MAD(const Instruction
*insn
)
185 case ROUND_M
: code
[1] |= 1 << 22; break;
186 case ROUND_P
: code
[1] |= 2 << 22; break;
187 case ROUND_Z
: code
[1] |= 3 << 22; break;
189 assert(insn
->rnd
== ROUND_N
);
195 CodeEmitterNV50::emitMNeg12(const Instruction
*i
)
197 code
[1] |= i
->src(0).mod
.neg() << 26;
198 code
[1] |= i
->src(1).mod
.neg() << 27;
201 void CodeEmitterNV50::emitCondCode(CondCode cc
, DataType ty
, int pos
)
205 assert(pos
>= 32 || pos
<= 27);
208 case CC_LT
: enc
= 0x1; break;
209 case CC_LTU
: enc
= 0x9; break;
210 case CC_EQ
: enc
= 0x2; break;
211 case CC_EQU
: enc
= 0xa; break;
212 case CC_LE
: enc
= 0x3; break;
213 case CC_LEU
: enc
= 0xb; break;
214 case CC_GT
: enc
= 0x4; break;
215 case CC_GTU
: enc
= 0xc; break;
216 case CC_NE
: enc
= 0x5; break;
217 case CC_NEU
: enc
= 0xd; break;
218 case CC_GE
: enc
= 0x6; break;
219 case CC_GEU
: enc
= 0xe; break;
220 case CC_TR
: enc
= 0xf; break;
221 case CC_FL
: enc
= 0x0; break;
223 case CC_O
: enc
= 0x10; break;
224 case CC_C
: enc
= 0x11; break;
225 case CC_A
: enc
= 0x12; break;
226 case CC_S
: enc
= 0x13; break;
227 case CC_NS
: enc
= 0x1c; break;
228 case CC_NA
: enc
= 0x1d; break;
229 case CC_NC
: enc
= 0x1e; break;
230 case CC_NO
: enc
= 0x1f; break;
234 assert(!"invalid condition code");
237 if (ty
!= TYPE_NONE
&& !isFloatType(ty
))
238 enc
&= ~0x8; // unordered only exists for float types
240 code
[pos
/ 32] |= enc
<< (pos
% 32);
244 CodeEmitterNV50::emitFlagsRd(const Instruction
*i
)
246 int s
= (i
->flagsSrc
>= 0) ? i
->flagsSrc
: i
->predSrc
;
248 assert(!(code
[1] & 0x00003f80));
251 assert(i
->getSrc(s
)->reg
.file
== FILE_FLAGS
);
252 emitCondCode(i
->cc
, TYPE_NONE
, 32 + 7);
253 srcId(i
->src(s
), 32 + 12);
260 CodeEmitterNV50::emitFlagsWr(const Instruction
*i
)
262 assert(!(code
[1] & 0x70));
264 int flagsDef
= i
->flagsDef
;
266 // find flags definition and check that it is the last def
268 for (int d
= 0; i
->defExists(d
); ++d
)
269 if (i
->def(d
).getFile() == FILE_FLAGS
)
271 if (flagsDef
>= 0 && 0) // TODO: enforce use of flagsDef at some point
272 WARN("Instruction::flagsDef was not set properly\n");
274 if (flagsDef
== 0 && i
->defExists(1))
275 WARN("flags def should not be the primary definition\n");
278 code
[1] |= (DDATA(i
->def(flagsDef
)).id
<< 4) | 0x40;
283 CodeEmitterNV50::setARegBits(unsigned int u
)
285 code
[0] |= (u
& 3) << 26;
290 CodeEmitterNV50::setAReg16(const Instruction
*i
, int s
)
292 if (i
->srcExists(s
)) {
293 s
= i
->src(s
).indirect
[0];
295 setARegBits(SDATA(i
->src(s
)).id
+ 1);
300 CodeEmitterNV50::setImmediate(const Instruction
*i
, int s
)
302 const ImmediateValue
*imm
= i
->src(s
).get()->asImm();
305 uint32_t u
= imm
->reg
.data
.u32
;
307 if (i
->src(s
).mod
& Modifier(NV50_IR_MOD_NOT
))
311 code
[0] |= (u
& 0x3f) << 16;
312 code
[1] |= (u
>> 6) << 2;
316 CodeEmitterNV50::setDst(const Value
*dst
)
318 const Storage
*reg
= &dst
->join
->reg
;
320 assert(reg
->file
!= FILE_ADDRESS
);
322 if (reg
->data
.id
< 0 || reg
->file
== FILE_FLAGS
) {
323 code
[0] |= (127 << 2) | 1;
327 if (reg
->file
== FILE_SHADER_OUTPUT
) {
329 id
= reg
->data
.offset
/ 4;
338 CodeEmitterNV50::setDst(const Instruction
*i
, int d
)
340 if (i
->defExists(d
)) {
341 setDst(i
->getDef(d
));
344 code
[0] |= 0x01fc; // bit bucket
355 CodeEmitterNV50::setSrcFileBits(const Instruction
*i
, int enc
)
359 for (unsigned int s
= 0; s
< Target::operationSrcNr
[i
->op
]; ++s
) {
360 switch (i
->src(s
).getFile()) {
363 case FILE_MEMORY_SHARED
:
364 case FILE_SHADER_INPUT
:
365 mode
|= 1 << (s
* 2);
367 case FILE_MEMORY_CONST
:
368 mode
|= 2 << (s
* 2);
371 mode
|= 3 << (s
* 2);
374 ERROR("invalid file on source %i: %u\n", s
, i
->src(s
).getFile());
382 case 0x01: // arr/grr
383 if (progType
== Program::TYPE_GEOMETRY
) {
384 code
[0] |= 0x01800000;
385 if (enc
== NV50_OP_ENC_LONG
|| enc
== NV50_OP_ENC_LONG_ALT
)
386 code
[1] |= 0x00200000;
388 if (enc
== NV50_OP_ENC_SHORT
)
389 code
[0] |= 0x01000000;
391 code
[1] |= 0x00200000;
395 assert(i
->op
== OP_MOV
);
400 code
[0] |= 0x01000000;
401 assert(progType
== Program::TYPE_GEOMETRY
||
402 progType
== Program::TYPE_COMPUTE
);
405 code
[0] |= (enc
== NV50_OP_ENC_LONG_ALT
) ? 0x01000000 : 0x00800000;
406 code
[1] |= (i
->getSrc(1)->reg
.fileIndex
<< 22);
408 case 0x09: // acr/gcr
409 if (progType
== Program::TYPE_GEOMETRY
) {
410 code
[0] |= 0x01800000;
412 code
[0] |= (enc
== NV50_OP_ENC_LONG_ALT
) ? 0x01000000 : 0x00800000;
413 code
[1] |= 0x00200000;
415 code
[1] |= (i
->getSrc(1)->reg
.fileIndex
<< 22);
418 code
[0] |= 0x01000000;
419 code
[1] |= (i
->getSrc(2)->reg
.fileIndex
<< 22);
422 code
[0] |= 0x01000000;
423 code
[1] |= 0x00200000 | (i
->getSrc(2)->reg
.fileIndex
<< 22);
424 assert(progType
!= Program::TYPE_GEOMETRY
);
427 ERROR("not encodable: %x\n", mode
);
431 if (progType
!= Program::TYPE_COMPUTE
)
434 if ((mode
& 3) == 1) {
435 const int pos
= i
->src(1).getFile() == FILE_IMMEDIATE
? 13 : 14;
437 switch (i
->getSrc(0)->reg
.type
) {
448 assert(i
->getSrc(0)->reg
.size
== 4);
455 CodeEmitterNV50::setSrc(const Instruction
*i
, unsigned int s
, int slot
)
457 if (Target::operationSrcNr
[i
->op
] <= s
)
459 const Storage
*reg
= &i
->src(s
).rep()->reg
;
461 unsigned int id
= (reg
->file
== FILE_GPR
) ?
463 reg
->data
.offset
>> (reg
->size
>> 1); // no > 4 byte sources here
466 case 0: code
[0] |= id
<< 9; break;
467 case 1: code
[0] |= id
<< 16; break;
468 case 2: code
[1] |= id
<< 14; break;
476 // - long instruction
477 // - 1 to 3 sources in slots 0, 1, 2 (rrr, arr, rcr, acr, rrc, arc, gcr, grr)
480 CodeEmitterNV50::emitForm_MAD(const Instruction
*i
)
482 assert(i
->encSize
== 8);
490 setSrcFileBits(i
, NV50_OP_ENC_LONG
);
498 // like default form, but 2nd source in slot 2, and no 3rd source
500 CodeEmitterNV50::emitForm_ADD(const Instruction
*i
)
502 assert(i
->encSize
== 8);
510 setSrcFileBits(i
, NV50_OP_ENC_LONG_ALT
);
517 // default short form (rr, ar, rc, gr)
519 CodeEmitterNV50::emitForm_MUL(const Instruction
*i
)
521 assert(i
->encSize
== 4 && !(code
[0] & 1));
522 assert(i
->defExists(0));
523 assert(!i
->getPredicate());
527 setSrcFileBits(i
, NV50_OP_ENC_SHORT
);
532 // usual immediate form
533 // - 1 to 3 sources where last is immediate (rir, gir)
534 // - no address or predicate possible
536 CodeEmitterNV50::emitForm_IMM(const Instruction
*i
)
538 assert(i
->encSize
== 8);
541 assert(i
->defExists(0) && i
->srcExists(0));
545 setSrcFileBits(i
, NV50_OP_ENC_IMM
);
546 if (Target::operationSrcNr
[i
->op
] > 1) {
556 CodeEmitterNV50::emitLoadStoreSizeLG(DataType ty
, int pos
)
561 case TYPE_F32
: // fall through
562 case TYPE_S32
: // fall through
563 case TYPE_U32
: enc
= 0x6; break;
564 case TYPE_B128
: enc
= 0x5; break;
565 case TYPE_F64
: // fall through
566 case TYPE_S64
: // fall through
567 case TYPE_U64
: enc
= 0x4; break;
568 case TYPE_S16
: enc
= 0x3; break;
569 case TYPE_U16
: enc
= 0x2; break;
570 case TYPE_S8
: enc
= 0x1; break;
571 case TYPE_U8
: enc
= 0x0; break;
574 assert(!"invalid load/store type");
577 code
[pos
/ 32] |= enc
<< (pos
% 32);
581 CodeEmitterNV50::emitLoadStoreSizeCS(DataType ty
)
585 case TYPE_U16
: code
[1] |= 0x4000; break;
586 case TYPE_S16
: code
[1] |= 0x8000; break;
589 case TYPE_U32
: code
[1] |= 0xc000; break;
597 CodeEmitterNV50::emitLOAD(const Instruction
*i
)
599 DataFile sf
= i
->src(0).getFile();
600 int32_t offset
= i
->getSrc(0)->reg
.data
.offset
;
603 case FILE_SHADER_INPUT
:
604 // use 'mov' where we can
605 code
[0] = i
->src(0).isIndirect(0) ? 0x00000001 : 0x10000001;
606 code
[1] = 0x00200000 | (i
->lanes
<< 14);
607 if (typeSizeof(i
->dType
) == 4)
608 code
[1] |= 0x04000000;
610 case FILE_MEMORY_SHARED
:
611 if (targ
->getChipset() >= 0x84) {
612 assert(offset
<= (int32_t)(0x3fff * typeSizeof(i
->sType
)));
613 code
[0] = 0x10000001;
614 code
[1] = 0x40000000;
616 if (typeSizeof(i
->dType
) == 4)
617 code
[1] |= 0x04000000;
619 emitLoadStoreSizeCS(i
->sType
);
621 assert(offset
<= (int32_t)(0x1f * typeSizeof(i
->sType
)));
622 code
[0] = 0x10000001;
623 code
[1] = 0x00200000 | (i
->lanes
<< 14);
624 emitLoadStoreSizeCS(i
->sType
);
627 case FILE_MEMORY_CONST
:
628 code
[0] = 0x10000001;
629 code
[1] = 0x20000000 | (i
->getSrc(0)->reg
.fileIndex
<< 22);
630 if (typeSizeof(i
->dType
) == 4)
631 code
[1] |= 0x04000000;
632 emitLoadStoreSizeCS(i
->sType
);
634 case FILE_MEMORY_LOCAL
:
635 code
[0] = 0xd0000001;
636 code
[1] = 0x40000000;
638 case FILE_MEMORY_GLOBAL
:
639 code
[0] = 0xd0000001 | (i
->getSrc(0)->reg
.fileIndex
<< 16);
640 code
[1] = 0x80000000;
643 assert(!"invalid load source file");
646 if (sf
== FILE_MEMORY_LOCAL
||
647 sf
== FILE_MEMORY_GLOBAL
)
648 emitLoadStoreSizeLG(i
->sType
, 21 + 32);
655 if (i
->src(0).getFile() == FILE_MEMORY_GLOBAL
) {
656 srcId(*i
->src(0).getIndirect(0), 9);
659 srcAddr16(i
->src(0), i
->src(0).getFile() != FILE_MEMORY_LOCAL
, 9);
664 CodeEmitterNV50::emitSTORE(const Instruction
*i
)
666 DataFile f
= i
->getSrc(0)->reg
.file
;
667 int32_t offset
= i
->getSrc(0)->reg
.data
.offset
;
670 case FILE_SHADER_OUTPUT
:
671 code
[0] = 0x00000001 | ((offset
>> 2) << 9);
672 code
[1] = 0x80c00000;
673 srcId(i
->src(1), 32 + 14);
675 case FILE_MEMORY_GLOBAL
:
676 code
[0] = 0xd0000001 | (i
->getSrc(0)->reg
.fileIndex
<< 16);
677 code
[1] = 0xa0000000;
678 emitLoadStoreSizeLG(i
->dType
, 21 + 32);
681 case FILE_MEMORY_LOCAL
:
682 code
[0] = 0xd0000001;
683 code
[1] = 0x60000000;
684 emitLoadStoreSizeLG(i
->dType
, 21 + 32);
687 case FILE_MEMORY_SHARED
:
688 code
[0] = 0x00000001;
689 code
[1] = 0xe0000000;
690 switch (typeSizeof(i
->dType
)) {
692 code
[0] |= offset
<< 9;
693 code
[1] |= 0x00400000;
696 code
[0] |= (offset
>> 1) << 9;
699 code
[0] |= (offset
>> 2) << 9;
700 code
[1] |= 0x04200000;
706 srcId(i
->src(1), 32 + 14);
709 assert(!"invalid store destination file");
713 if (f
== FILE_MEMORY_GLOBAL
)
714 srcId(*i
->src(0).getIndirect(0), 9);
718 if (f
== FILE_MEMORY_LOCAL
)
719 srcAddr16(i
->src(0), false, 9);
725 CodeEmitterNV50::emitMOV(const Instruction
*i
)
727 DataFile sf
= i
->getSrc(0)->reg
.file
;
728 DataFile df
= i
->getDef(0)->reg
.file
;
730 assert(sf
== FILE_GPR
|| df
== FILE_GPR
);
732 if (sf
== FILE_FLAGS
) {
733 code
[0] = 0x00000001;
734 code
[1] = 0x20000000;
736 srcId(i
->src(0), 12);
739 if (sf
== FILE_ADDRESS
) {
740 code
[0] = 0x00000001;
741 code
[1] = 0x40000000;
743 setARegBits(SDATA(i
->src(0)).id
+ 1);
746 if (df
== FILE_FLAGS
) {
747 code
[0] = 0x00000001;
748 code
[1] = 0xa0000000;
753 if (sf
== FILE_IMMEDIATE
) {
754 code
[0] = 0x10008001;
755 code
[1] = 0x00000003;
758 if (i
->encSize
== 4) {
759 code
[0] = 0x10008000;
761 code
[0] = 0x10000001;
762 code
[1] = (typeSizeof(i
->dType
) == 2) ? 0 : 0x04000000;
763 code
[1] |= (i
->lanes
<< 14);
769 if (df
== FILE_SHADER_OUTPUT
) {
770 assert(i
->encSize
== 8);
776 CodeEmitterNV50::emitNOP()
778 code
[0] = 0xf0000001;
779 code
[1] = 0xe0000000;
783 CodeEmitterNV50::emitQUADOP(const Instruction
*i
, uint8_t lane
, uint8_t quOp
)
785 code
[0] = 0xc0000000 | (lane
<< 16);
786 code
[1] = 0x80000000;
788 code
[0] |= (quOp
& 0x03) << 20;
789 code
[1] |= (quOp
& 0xfc) << 20;
793 if (!i
->srcExists(1))
794 srcId(i
->src(0), 32 + 14);
798 CodeEmitterNV50::emitPFETCH(const Instruction
*i
)
800 code
[0] = 0x11800001;
801 code
[1] = 0x04200000 | (0xf << 14);
804 srcAddr8(i
->src(0), 9);
809 CodeEmitterNV50::emitINTERP(const Instruction
*i
)
811 code
[0] = 0x80000000;
814 srcAddr8(i
->src(0), 16);
816 if (i
->getInterpMode() == NV50_IR_INTERP_FLAT
) {
819 if (i
->op
== OP_PINTERP
) {
823 if (i
->getSampleMode() == NV50_IR_INTERP_CENTROID
)
827 if (i
->encSize
== 8) {
829 (code
[0] & (3 << 24)) >> (24 - 16) |
830 (code
[0] & (1 << 8)) << (18 - 8);
831 code
[0] &= ~0x03000100;
838 CodeEmitterNV50::emitMINMAX(const Instruction
*i
)
840 if (i
->dType
== TYPE_F64
) {
841 code
[0] = 0xe0000000;
842 code
[1] = (i
->op
== OP_MIN
) ? 0xa0000000 : 0xc0000000;
844 code
[0] = 0x30000000;
845 code
[1] = 0x80000000;
847 code
[1] |= 0x20000000;
850 case TYPE_F32
: code
[0] |= 0x80000000; break;
851 case TYPE_S32
: code
[1] |= 0x8c000000; break;
852 case TYPE_U32
: code
[1] |= 0x84000000; break;
853 case TYPE_S16
: code
[1] |= 0x80000000; break;
854 case TYPE_U16
: break;
859 code
[1] |= i
->src(0).mod
.abs() << 20;
860 code
[1] |= i
->src(1).mod
.abs() << 19;
866 CodeEmitterNV50::emitFMAD(const Instruction
*i
)
868 const int neg_mul
= i
->src(0).mod
.neg() ^ i
->src(1).mod
.neg();
869 const int neg_add
= i
->src(2).mod
.neg();
871 code
[0] = 0xe0000000;
873 if (i
->encSize
== 4) {
875 assert(!neg_mul
&& !neg_add
);
877 code
[1] = neg_mul
<< 26;
878 code
[1] |= neg_add
<< 27;
886 CodeEmitterNV50::emitFADD(const Instruction
*i
)
888 const int neg0
= i
->src(0).mod
.neg();
889 const int neg1
= i
->src(1).mod
.neg() ^ ((i
->op
== OP_SUB
) ? 1 : 0);
891 code
[0] = 0xb0000000;
893 assert(!(i
->src(0).mod
| i
->src(1).mod
).abs());
895 if (i
->src(1).getFile() == FILE_IMMEDIATE
) {
898 code
[0] |= neg0
<< 15;
899 code
[0] |= neg1
<< 22;
903 if (i
->encSize
== 8) {
906 code
[1] |= neg0
<< 26;
907 code
[1] |= neg1
<< 27;
912 code
[0] |= neg0
<< 15;
913 code
[0] |= neg1
<< 22;
920 CodeEmitterNV50::emitUADD(const Instruction
*i
)
922 const int neg0
= i
->src(0).mod
.neg();
923 const int neg1
= i
->src(1).mod
.neg() ^ ((i
->op
== OP_SUB
) ? 1 : 0);
925 code
[0] = 0x20008000;
927 if (i
->src(1).getFile() == FILE_IMMEDIATE
) {
931 if (i
->encSize
== 8) {
932 code
[0] = 0x20000000;
933 code
[1] = (typeSizeof(i
->dType
) == 2) ? 0 : 0x04000000;
938 assert(!(neg0
&& neg1
));
939 code
[0] |= neg0
<< 28;
940 code
[0] |= neg1
<< 22;
942 if (i
->flagsSrc
>= 0) {
943 // addc == sub | subr
944 assert(!(code
[0] & 0x10400000) && !i
->getPredicate());
945 code
[0] |= 0x10400000;
946 srcId(i
->src(i
->flagsSrc
), 32 + 12);
951 CodeEmitterNV50::emitAADD(const Instruction
*i
)
953 const int s
= (i
->op
== OP_MOV
) ? 0 : 1;
955 code
[0] = 0xd0000001 | (i
->getSrc(s
)->reg
.data
.u16
<< 9);
956 code
[1] = 0x20000000;
958 code
[0] |= (DDATA(i
->def(0)).id
+ 1) << 2;
962 if (s
&& i
->srcExists(0))
963 setARegBits(SDATA(i
->src(0)).id
+ 1);
967 CodeEmitterNV50::emitIMUL(const Instruction
*i
)
969 code
[0] = 0x40000000;
971 if (i
->encSize
== 8) {
972 code
[1] = (i
->sType
== TYPE_S16
) ? (0x8000 | 0x4000) : 0x0000;
975 if (i
->sType
== TYPE_S16
)
982 CodeEmitterNV50::emitFMUL(const Instruction
*i
)
984 const int neg
= (i
->src(0).mod
^ i
->src(1).mod
).neg();
986 code
[0] = 0xc0000000;
988 if (i
->src(1).getFile() == FILE_IMMEDIATE
) {
994 if (i
->encSize
== 8) {
995 code
[1] = i
->rnd
== ROUND_Z
? 0x0000c000 : 0;
997 code
[1] |= 0x08000000;
1007 CodeEmitterNV50::emitIMAD(const Instruction
*i
)
1009 code
[0] = 0x60000000;
1010 if (isSignedType(i
->sType
))
1011 code
[1] = i
->saturate
? 0x40000000 : 0x20000000;
1013 code
[1] = 0x00000000;
1015 int neg1
= i
->src(0).mod
.neg() ^ i
->src(1).mod
.neg();
1016 int neg2
= i
->src(2).mod
.neg();
1018 assert(!(neg1
& neg2
));
1019 code
[1] |= neg1
<< 27;
1020 code
[1] |= neg2
<< 26;
1024 if (i
->flagsSrc
>= 0) {
1025 // add with carry from $cX
1026 assert(!(code
[1] & 0x0c000000) && !i
->getPredicate());
1027 code
[1] |= 0xc << 24;
1028 srcId(i
->src(i
->flagsSrc
), 32 + 12);
1033 CodeEmitterNV50::emitISAD(const Instruction
*i
)
1035 if (i
->encSize
== 8) {
1036 code
[0] = 0x50000000;
1038 case TYPE_U32
: code
[1] = 0x04000000; break;
1039 case TYPE_S32
: code
[1] = 0x0c000000; break;
1040 case TYPE_U16
: code
[1] = 0x00000000; break;
1041 case TYPE_S16
: code
[1] = 0x08000000; break;
1049 case TYPE_U32
: code
[0] = 0x50008000; break;
1050 case TYPE_S32
: code
[0] = 0x50008100; break;
1051 case TYPE_U16
: code
[0] = 0x50000000; break;
1052 case TYPE_S16
: code
[0] = 0x50000100; break;
1062 CodeEmitterNV50::emitSET(const Instruction
*i
)
1064 code
[0] = 0x30000000;
1065 code
[1] = 0x60000000;
1067 emitCondCode(i
->asCmp()->setCond
, i
->sType
, 32 + 14);
1070 case TYPE_F32
: code
[0] |= 0x80000000; break;
1071 case TYPE_S32
: code
[1] |= 0x0c000000; break;
1072 case TYPE_U32
: code
[1] |= 0x04000000; break;
1073 case TYPE_S16
: code
[1] |= 0x08000000; break;
1074 case TYPE_U16
: break;
1079 if (i
->src(0).mod
.neg()) code
[1] |= 0x04000000;
1080 if (i
->src(1).mod
.neg()) code
[1] |= 0x08000000;
1081 if (i
->src(0).mod
.abs()) code
[1] |= 0x00100000;
1082 if (i
->src(1).mod
.abs()) code
[1] |= 0x00080000;
1088 CodeEmitterNV50::roundMode_CVT(RoundMode rnd
)
1091 case ROUND_NI
: code
[1] |= 0x08000000; break;
1092 case ROUND_M
: code
[1] |= 0x00020000; break;
1093 case ROUND_MI
: code
[1] |= 0x08020000; break;
1094 case ROUND_P
: code
[1] |= 0x00040000; break;
1095 case ROUND_PI
: code
[1] |= 0x08040000; break;
1096 case ROUND_Z
: code
[1] |= 0x00060000; break;
1097 case ROUND_ZI
: code
[1] |= 0x08060000; break;
1099 assert(rnd
== ROUND_N
);
1105 CodeEmitterNV50::emitCVT(const Instruction
*i
)
1107 const bool f2f
= isFloatType(i
->dType
) && isFloatType(i
->sType
);
1112 case OP_CEIL
: rnd
= f2f
? ROUND_PI
: ROUND_P
; break;
1113 case OP_FLOOR
: rnd
= f2f
? ROUND_MI
: ROUND_M
; break;
1114 case OP_TRUNC
: rnd
= f2f
? ROUND_ZI
: ROUND_Z
; break;
1120 if (i
->op
== OP_NEG
&& i
->dType
== TYPE_U32
)
1125 code
[0] = 0xa0000000;
1130 case TYPE_F64
: code
[1] = 0xc4404000; break;
1131 case TYPE_S64
: code
[1] = 0x44414000; break;
1132 case TYPE_U64
: code
[1] = 0x44404000; break;
1133 case TYPE_F32
: code
[1] = 0xc4400000; break;
1134 case TYPE_S32
: code
[1] = 0x44410000; break;
1135 case TYPE_U32
: code
[1] = 0x44400000; break;
1143 case TYPE_F64
: code
[1] = 0x8c404000; break;
1144 case TYPE_F32
: code
[1] = 0x8c400000; break;
1152 case TYPE_F64
: code
[1] = 0x84404000; break;
1153 case TYPE_F32
: code
[1] = 0x84400000; break;
1161 case TYPE_F64
: code
[1] = 0xc0404000; break;
1162 case TYPE_S64
: code
[1] = 0x40414000; break;
1163 case TYPE_U64
: code
[1] = 0x40404000; break;
1164 case TYPE_F32
: code
[1] = 0xc4004000; break;
1165 case TYPE_S32
: code
[1] = 0x44014000; break;
1166 case TYPE_U32
: code
[1] = 0x44004000; break;
1167 case TYPE_F16
: code
[1] = 0xc4000000; break;
1175 case TYPE_F64
: code
[1] = 0x88404000; break;
1176 case TYPE_F32
: code
[1] = 0x8c004000; break;
1177 case TYPE_S32
: code
[1] = 0x0c014000; break;
1178 case TYPE_U32
: code
[1] = 0x0c004000; break;
1179 case TYPE_F16
: code
[1] = 0x8c000000; break;
1180 case TYPE_S16
: code
[1] = 0x0c010000; break;
1181 case TYPE_U16
: code
[1] = 0x0c000000; break;
1182 case TYPE_S8
: code
[1] = 0x0c018000; break;
1183 case TYPE_U8
: code
[1] = 0x0c008000; break;
1191 case TYPE_F64
: code
[1] = 0x80404000; break;
1192 case TYPE_F32
: code
[1] = 0x84004000; break;
1193 case TYPE_S32
: code
[1] = 0x04014000; break;
1194 case TYPE_U32
: code
[1] = 0x04004000; break;
1195 case TYPE_F16
: code
[1] = 0x84000000; break;
1196 case TYPE_S16
: code
[1] = 0x04010000; break;
1197 case TYPE_U16
: code
[1] = 0x04000000; break;
1198 case TYPE_S8
: code
[1] = 0x04018000; break;
1199 case TYPE_U8
: code
[1] = 0x04008000; break;
1213 if (typeSizeof(i
->sType
) == 1 && i
->getSrc(0)->reg
.size
== 4)
1214 code
[1] |= 0x00004000;
1219 case OP_ABS
: code
[1] |= 1 << 20; break;
1220 case OP_SAT
: code
[1] |= 1 << 19; break;
1221 case OP_NEG
: code
[1] |= 1 << 29; break;
1225 code
[1] ^= i
->src(0).mod
.neg() << 29;
1226 code
[1] |= i
->src(0).mod
.abs() << 20;
1230 assert(i
->op
!= OP_ABS
|| !i
->src(0).mod
.neg());
1236 CodeEmitterNV50::emitPreOp(const Instruction
*i
)
1238 code
[0] = 0xb0000000;
1239 code
[1] = (i
->op
== OP_PREEX2
) ? 0xc0004000 : 0xc0000000;
1241 code
[1] |= i
->src(0).mod
.abs() << 20;
1242 code
[1] |= i
->src(0).mod
.neg() << 26;
1248 CodeEmitterNV50::emitSFnOp(const Instruction
*i
, uint8_t subOp
)
1250 code
[0] = 0x90000000;
1252 if (i
->encSize
== 4) {
1253 assert(i
->op
== OP_RCP
);
1254 code
[0] |= i
->src(0).mod
.abs() << 15;
1255 code
[0] |= i
->src(0).mod
.neg() << 22;
1258 code
[1] = subOp
<< 29;
1259 code
[1] |= i
->src(0).mod
.abs() << 20;
1260 code
[1] |= i
->src(0).mod
.neg() << 26;
1266 CodeEmitterNV50::emitNOT(const Instruction
*i
)
1268 code
[0] = 0xd0000000;
1269 code
[1] = 0x0002c000;
1274 code
[1] |= 0x04000000;
1284 CodeEmitterNV50::emitLogicOp(const Instruction
*i
)
1286 code
[0] = 0xd0000000;
1289 if (i
->src(1).getFile() == FILE_IMMEDIATE
) {
1291 case OP_OR
: code
[0] |= 0x0100; break;
1292 case OP_XOR
: code
[0] |= 0x8000; break;
1294 assert(i
->op
== OP_AND
);
1297 if (i
->src(0).mod
& Modifier(NV50_IR_MOD_NOT
))
1303 case OP_AND
: code
[1] = 0x04000000; break;
1304 case OP_OR
: code
[1] = 0x04004000; break;
1305 case OP_XOR
: code
[1] = 0x04008000; break;
1310 if (i
->src(0).mod
& Modifier(NV50_IR_MOD_NOT
))
1312 if (i
->src(1).mod
& Modifier(NV50_IR_MOD_NOT
))
1320 CodeEmitterNV50::emitARL(const Instruction
*i
, unsigned int shl
)
1322 code
[0] = 0x00000001 | (shl
<< 16);
1323 code
[1] = 0xc0000000;
1325 code
[0] |= (DDATA(i
->def(0)).id
+ 1) << 2;
1327 setSrcFileBits(i
, NV50_OP_ENC_IMM
);
1333 CodeEmitterNV50::emitShift(const Instruction
*i
)
1335 if (i
->def(0).getFile() == FILE_ADDRESS
) {
1336 assert(i
->srcExists(1) && i
->src(1).getFile() == FILE_IMMEDIATE
);
1337 emitARL(i
, i
->getSrc(1)->reg
.data
.u32
& 0x3f);
1339 code
[0] = 0x30000001;
1340 code
[1] = (i
->op
== OP_SHR
) ? 0xe4000000 : 0xc4000000;
1341 if (i
->op
== OP_SHR
&& isSignedType(i
->sType
))
1344 if (i
->src(1).getFile() == FILE_IMMEDIATE
) {
1346 code
[0] |= (i
->getSrc(1)->reg
.data
.u32
& 0x7f) << 16;
1347 defId(i
->def(0), 2);
1348 srcId(i
->src(0), 9);
1357 CodeEmitterNV50::emitOUT(const Instruction
*i
)
1359 code
[0] = (i
->op
== OP_EMIT
) ? 0xf0000200 : 0xf0000400;
1360 code
[1] = 0xc0000001;
1366 CodeEmitterNV50::emitTEX(const TexInstruction
*i
)
1368 code
[0] = 0xf0000001;
1369 code
[1] = 0x00000000;
1373 code
[1] = 0x20000000;
1376 code
[1] = 0x40000000;
1379 code
[0] |= 0x01000000;
1382 code
[0] = 0x01000000;
1383 code
[1] = 0x80000000;
1386 assert(i
->op
== OP_TEX
);
1390 code
[0] |= i
->tex
.r
<< 9;
1391 code
[0] |= i
->tex
.s
<< 17;
1393 int argc
= i
->tex
.target
.getArgCount();
1395 if (i
->op
== OP_TXB
|| i
->op
== OP_TXL
|| i
->op
== OP_TXF
)
1397 if (i
->tex
.target
.isShadow())
1401 code
[0] |= (argc
- 1) << 22;
1403 if (i
->tex
.target
.isCube()) {
1404 code
[0] |= 0x08000000;
1406 if (i
->tex
.useOffsets
) {
1407 code
[1] |= (i
->tex
.offset
[0][0] & 0xf) << 24;
1408 code
[1] |= (i
->tex
.offset
[0][1] & 0xf) << 20;
1409 code
[1] |= (i
->tex
.offset
[0][2] & 0xf) << 16;
1412 code
[0] |= (i
->tex
.mask
& 0x3) << 25;
1413 code
[1] |= (i
->tex
.mask
& 0xc) << 12;
1415 if (i
->tex
.liveOnly
)
1418 defId(i
->def(0), 2);
1424 CodeEmitterNV50::emitTXQ(const TexInstruction
*i
)
1426 assert(i
->tex
.query
== TXQ_DIMS
);
1428 code
[0] = 0xf0000001;
1429 code
[1] = 0x60000000;
1431 code
[0] |= i
->tex
.r
<< 9;
1432 code
[0] |= i
->tex
.s
<< 17;
1434 code
[0] |= (i
->tex
.mask
& 0x3) << 25;
1435 code
[1] |= (i
->tex
.mask
& 0xc) << 12;
1437 defId(i
->def(0), 2);
1443 CodeEmitterNV50::emitTEXPREP(const TexInstruction
*i
)
1445 code
[0] = 0xf8000001 | (3 << 22) | (i
->tex
.s
<< 17) | (i
->tex
.r
<< 9);
1446 code
[1] = 0x60010000;
1448 code
[0] |= (i
->tex
.mask
& 0x3) << 25;
1449 code
[1] |= (i
->tex
.mask
& 0xc) << 12;
1450 defId(i
->def(0), 2);
1456 CodeEmitterNV50::emitPRERETEmu(const FlowInstruction
*i
)
1458 uint32_t pos
= i
->target
.bb
->binPos
+ 8; // +8 to skip an op */
1460 code
[0] = 0x10000003; // bra
1461 code
[1] = 0x00000780; // always
1464 case NV50_IR_SUBOP_EMU_PRERET
+ 0: // bra to the call
1466 case NV50_IR_SUBOP_EMU_PRERET
+ 1: // bra to skip the call
1470 assert(i
->subOp
== (NV50_IR_SUBOP_EMU_PRERET
+ 2));
1471 code
[0] = 0x20000003; // call
1472 code
[1] = 0x00000000; // no predicate
1475 addReloc(RelocEntry::TYPE_CODE
, 0, pos
, 0x07fff800, 9);
1476 addReloc(RelocEntry::TYPE_CODE
, 1, pos
, 0x000fc000, -4);
1480 CodeEmitterNV50::emitFlow(const Instruction
*i
, uint8_t flowOp
)
1482 const FlowInstruction
*f
= i
->asFlow();
1483 bool hasPred
= false;
1484 bool hasTarg
= false;
1486 code
[0] = 0x00000003 | (flowOp
<< 28);
1487 code
[1] = 0x00000000;
1507 if (i
->subOp
>= NV50_IR_SUBOP_EMU_PRERET
) {
1522 if (f
->op
== OP_CALL
) {
1524 pos
= targNV50
->getBuiltinOffset(f
->target
.builtin
);
1526 pos
= f
->target
.fn
->binPos
;
1529 pos
= f
->target
.bb
->binPos
;
1532 code
[0] |= ((pos
>> 2) & 0xffff) << 11;
1533 code
[1] |= ((pos
>> 18) & 0x003f) << 14;
1535 RelocEntry::Type relocTy
;
1537 relocTy
= f
->builtin
? RelocEntry::TYPE_BUILTIN
: RelocEntry::TYPE_CODE
;
1539 addReloc(relocTy
, 0, pos
, 0x07fff800, 9);
1540 addReloc(relocTy
, 1, pos
, 0x000fc000, -4);
1545 CodeEmitterNV50::emitBAR(const Instruction
*i
)
1547 ImmediateValue
*barId
= i
->getSrc(0)->asImm();
1550 code
[0] = 0x82000003 | (barId
->reg
.data
.u32
<< 21);
1551 code
[1] = 0x00004000;
1553 if (i
->subOp
== NV50_IR_SUBOP_BAR_SYNC
)
1558 CodeEmitterNV50::emitATOM(const Instruction
*i
)
1562 case NV50_IR_SUBOP_ATOM_ADD
: subOp
= 0x0; break;
1563 case NV50_IR_SUBOP_ATOM_MIN
: subOp
= 0x7; break;
1564 case NV50_IR_SUBOP_ATOM_MAX
: subOp
= 0x6; break;
1565 case NV50_IR_SUBOP_ATOM_INC
: subOp
= 0x4; break;
1566 case NV50_IR_SUBOP_ATOM_DEC
: subOp
= 0x5; break;
1567 case NV50_IR_SUBOP_ATOM_AND
: subOp
= 0xa; break;
1568 case NV50_IR_SUBOP_ATOM_OR
: subOp
= 0xb; break;
1569 case NV50_IR_SUBOP_ATOM_XOR
: subOp
= 0xc; break;
1570 case NV50_IR_SUBOP_ATOM_CAS
: subOp
= 0x2; break;
1571 case NV50_IR_SUBOP_ATOM_EXCH
: subOp
= 0x1; break;
1573 assert(!"invalid subop");
1576 code
[0] = 0xd0000001;
1577 code
[1] = 0xe0c00000 | (subOp
<< 2);
1578 if (isSignedType(i
->dType
))
1585 if (i
->subOp
== NV50_IR_SUBOP_ATOM_CAS
)
1589 code
[0] |= i
->getSrc(0)->reg
.fileIndex
<< 23;
1590 srcId(i
->getIndirect(0, 0), 9);
1594 CodeEmitterNV50::emitInstruction(Instruction
*insn
)
1596 if (!insn
->encSize
) {
1597 ERROR("skipping unencodable instruction: "); insn
->print();
1600 if (codeSize
+ insn
->encSize
> codeSizeLimit
) {
1601 ERROR("code emitter output buffer too small\n");
1605 if (insn
->bb
->getProgram()->dbgFlags
& NV50_IR_DEBUG_BASIC
) {
1606 INFO("EMIT: "); insn
->print();
1635 if (isFloatType(insn
->dType
))
1637 else if (insn
->getDef(0)->reg
.file
== FILE_ADDRESS
)
1643 if (isFloatType(insn
->dType
))
1650 if (isFloatType(insn
->dType
))
1686 if (insn
->def(0).getFile() == FILE_ADDRESS
)
1689 if (insn
->def(0).getFile() == FILE_FLAGS
||
1690 insn
->src(0).getFile() == FILE_FLAGS
||
1691 insn
->src(0).getFile() == FILE_ADDRESS
)
1722 emitTEX(insn
->asTex());
1725 emitTXQ(insn
->asTex());
1728 emitTEXPREP(insn
->asTex());
1735 emitFlow(insn
, 0x0);
1738 emitFlow(insn
, 0x1);
1741 emitFlow(insn
, 0x2);
1744 emitFlow(insn
, 0x3);
1747 emitFlow(insn
, 0x4);
1750 emitFlow(insn
, 0x5);
1753 emitFlow(insn
, 0x6);
1756 emitFlow(insn
, 0x7);
1759 emitFlow(insn
, 0xa);
1762 emitFlow(insn
, 0xd);
1765 emitQUADOP(insn
, insn
->lanes
, insn
->subOp
);
1768 emitQUADOP(insn
, 4, insn
->src(0).mod
.neg() ? 0x66 : 0x99);
1771 emitQUADOP(insn
, 5, insn
->src(0).mod
.neg() ? 0x5a : 0xa5);
1782 ERROR("operation should have been eliminated\n");
1796 ERROR("operation should have been lowered\n");
1799 ERROR("unknown op: %u\n", insn
->op
);
1802 if (insn
->join
|| insn
->op
== OP_JOIN
)
1805 if (insn
->exit
|| insn
->op
== OP_EXIT
)
1808 assert((insn
->encSize
== 8) == (code
[0] & 1));
1810 code
+= insn
->encSize
/ 4;
1811 codeSize
+= insn
->encSize
;
1816 CodeEmitterNV50::getMinEncodingSize(const Instruction
*i
) const
1818 const Target::OpInfo
&info
= targ
->getOpInfo(i
);
1820 if (info
.minEncSize
> 4)
1823 // check constraints on dst and src operands
1824 for (int d
= 0; i
->defExists(d
); ++d
) {
1825 if (i
->def(d
).rep()->reg
.data
.id
> 63 ||
1826 i
->def(d
).rep()->reg
.file
!= FILE_GPR
)
1830 for (int s
= 0; i
->srcExists(s
); ++s
) {
1831 DataFile sf
= i
->src(s
).getFile();
1833 if (sf
!= FILE_SHADER_INPUT
|| progType
!= Program::TYPE_FRAGMENT
)
1835 if (i
->src(s
).rep()->reg
.data
.id
> 63)
1839 // check modifiers & rounding
1840 if (i
->join
|| i
->lanes
!= 0xf || i
->exit
)
1842 if (i
->op
== OP_MUL
&& i
->rnd
!= ROUND_N
)
1846 return 8; // TODO: short tex encoding
1848 // check constraints on short MAD
1849 if (info
.srcNr
>= 2 && i
->srcExists(2)) {
1850 if (i
->saturate
|| i
->src(2).mod
)
1852 if ((i
->src(0).mod
^ i
->src(1).mod
) ||
1853 (i
->src(0).mod
| i
->src(1).mod
).abs())
1855 if (!i
->defExists(0) ||
1856 i
->def(0).rep()->reg
.data
.id
!= i
->src(2).rep()->reg
.data
.id
)
1860 return info
.minEncSize
;
1863 // Change the encoding size of an instruction after BBs have been scheduled.
1865 makeInstructionLong(Instruction
*insn
)
1867 if (insn
->encSize
== 8)
1869 Function
*fn
= insn
->bb
->getFunction();
1873 for (Instruction
*i
= insn
->next
; i
&& i
->encSize
== 4; ++n
, i
= i
->next
);
1877 insn
->next
->encSize
= 8;
1879 if (insn
->prev
&& insn
->prev
->encSize
== 4) {
1881 insn
->prev
->encSize
= 8;
1885 for (int i
= fn
->bbCount
- 1; i
>= 0 && fn
->bbArray
[i
] != insn
->bb
; --i
) {
1886 fn
->bbArray
[i
]->binPos
+= 4;
1889 insn
->bb
->binSize
+= adj
;
1893 trySetExitModifier(Instruction
*insn
)
1895 if (insn
->op
== OP_DISCARD
||
1896 insn
->op
== OP_QUADON
||
1897 insn
->op
== OP_QUADPOP
)
1899 for (int s
= 0; insn
->srcExists(s
); ++s
)
1900 if (insn
->src(s
).getFile() == FILE_IMMEDIATE
)
1902 if (insn
->asFlow()) {
1903 if (insn
->op
== OP_CALL
) // side effects !
1905 if (insn
->getPredicate()) // cannot do conditional exit (or can we ?)
1910 makeInstructionLong(insn
);
1915 replaceExitWithModifier(Function
*func
)
1917 BasicBlock
*epilogue
= BasicBlock::get(func
->cfgExit
);
1919 if (!epilogue
->getExit() ||
1920 epilogue
->getExit()->op
!= OP_EXIT
) // only main will use OP_EXIT
1923 if (epilogue
->getEntry()->op
!= OP_EXIT
) {
1924 Instruction
*insn
= epilogue
->getExit()->prev
;
1925 if (!insn
|| !trySetExitModifier(insn
))
1929 for (Graph::EdgeIterator ei
= func
->cfgExit
->incident();
1930 !ei
.end(); ei
.next()) {
1931 BasicBlock
*bb
= BasicBlock::get(ei
.getNode());
1932 Instruction
*i
= bb
->getExit();
1934 if (!i
|| !trySetExitModifier(i
))
1938 epilogue
->binSize
-= 8;
1940 delete_Instruction(func
->getProgram(), epilogue
->getExit());
1944 CodeEmitterNV50::prepareEmission(Function
*func
)
1946 CodeEmitter::prepareEmission(func
);
1948 replaceExitWithModifier(func
);
1951 CodeEmitterNV50::CodeEmitterNV50(const TargetNV50
*target
) :
1952 CodeEmitter(target
), targNV50(target
)
1954 targ
= target
; // specialized
1956 codeSize
= codeSizeLimit
= 0;
1961 TargetNV50::getCodeEmitter(Program::Type type
)
1963 CodeEmitterNV50
*emit
= new CodeEmitterNV50(this);
1964 emit
->setProgramType(type
);
1968 } // namespace nv50_ir