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 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
24 #include "nv50_ir_target.h"
28 class CodeEmitterNV50
: public CodeEmitter
31 CodeEmitterNV50(const Target
*);
33 virtual bool emitInstruction(Instruction
*);
35 virtual uint32_t getMinEncodingSize(const Instruction
*) const;
37 inline void setProgramType(Program::Type pType
) { progType
= pType
; }
42 Program::Type progType
;
45 inline void defId(const ValueDef
&, const int pos
);
46 inline void srcId(const ValueRef
&, const int pos
);
47 inline void srcId(const ValueRef
*, const int pos
);
49 inline void srcAddr16(const ValueRef
&, const int pos
);
50 inline void srcAddr8(const ValueRef
&, const int pos
);
52 void emitFlagsRd(const Instruction
*);
53 void emitFlagsWr(const Instruction
*);
55 void emitCondCode(CondCode cc
, int pos
);
57 inline void setARegBits(unsigned int);
59 void setAReg16(const Instruction
*, int s
);
60 void setImmediate(const Instruction
*, int s
);
62 void setDst(const Value
*);
63 void setDst(const Instruction
*, int d
);
64 void emitSrc0(const ValueRef
&);
65 void emitSrc1(const ValueRef
&);
66 void emitSrc2(const ValueRef
&);
68 void emitForm_MAD(const Instruction
*);
69 void emitForm_ADD(const Instruction
*);
70 void emitForm_MUL(const Instruction
*);
71 void emitForm_IMM(const Instruction
*);
73 void emitLoadStoreSize(DataType ty
, int pos
);
75 void roundMode_MAD(const Instruction
*);
76 void roundMode_CVT(RoundMode
);
78 void emitMNeg12(const Instruction
*);
80 void emitLOAD(const Instruction
*);
81 void emitSTORE(const Instruction
*);
82 void emitMOV(const Instruction
*);
84 void emitINTERP(const Instruction
*);
85 void emitPFETCH(const Instruction
*);
86 void emitOUT(const Instruction
*);
88 void emitUADD(const Instruction
*);
89 void emitAADD(const Instruction
*);
90 void emitFADD(const Instruction
*);
91 void emitUMUL(const Instruction
*);
92 void emitFMUL(const Instruction
*);
93 void emitFMAD(const Instruction
*);
95 void emitMINMAX(const Instruction
*);
97 void emitPreOp(const Instruction
*);
98 void emitSFnOp(const Instruction
*, uint8_t subOp
);
100 void emitShift(const Instruction
*);
101 void emitARL(const Instruction
*);
102 void emitLogicOp(const Instruction
*);
104 void emitCVT(const Instruction
*);
105 void emitSET(const Instruction
*);
107 void emitTEX(const TexInstruction
*);
109 void emitQUADOP(const Instruction
*, uint8_t lane
, uint8_t quOp
);
111 void emitFlow(const Instruction
*, uint8_t flowOp
);
114 #define SDATA(a) ((a).rep()->reg.data)
115 #define DDATA(a) ((a).rep()->reg.data)
117 void CodeEmitterNV50::srcId(const ValueRef
& src
, const int pos
)
120 code
[pos
/ 32] |= SDATA(src
).id
<< (pos
% 32);
123 void CodeEmitterNV50::srcId(const ValueRef
*src
, const int pos
)
126 code
[pos
/ 32] |= SDATA(*src
).id
<< (pos
% 32);
129 void CodeEmitterNV50::srcAddr16(const ValueRef
& src
, const int pos
)
133 uint32_t offset
= SDATA(src
).offset
;
135 assert(offset
<= 0xffff && (pos
% 32) <= 16);
137 code
[pos
/ 32] |= offset
<< (pos
% 32);
140 void CodeEmitterNV50::srcAddr8(const ValueRef
& src
, const int pos
)
144 uint32_t offset
= SDATA(src
).offset
;
146 assert(offset
<= 0x1fc && !(offset
& 0x3));
148 code
[pos
/ 32] |= (offset
>> 2) << (pos
% 32);
151 void CodeEmitterNV50::defId(const ValueDef
& def
, const int pos
)
154 code
[pos
/ 32] |= DDATA(def
).id
<< (pos
% 32);
158 CodeEmitterNV50::roundMode_MAD(const Instruction
*insn
)
161 case ROUND_M
: code
[1] |= 1 << 22; break;
162 case ROUND_P
: code
[1] |= 2 << 22; break;
163 case ROUND_Z
: code
[1] |= 3 << 22; break;
165 assert(insn
->rnd
== ROUND_N
);
171 CodeEmitterNV50::emitMNeg12(const Instruction
*i
)
173 code
[1] |= i
->src
[0].mod
.neg() << 26;
174 code
[1] |= i
->src
[1].mod
.neg() << 27;
177 void CodeEmitterNV50::emitCondCode(CondCode cc
, int pos
)
181 assert(pos
>= 32 || pos
<= 27);
184 case CC_LT
: enc
= 0x1; break;
185 case CC_LTU
: enc
= 0x9; break;
186 case CC_EQ
: enc
= 0x2; break;
187 case CC_EQU
: enc
= 0xa; break;
188 case CC_LE
: enc
= 0x3; break;
189 case CC_LEU
: enc
= 0xb; break;
190 case CC_GT
: enc
= 0x4; break;
191 case CC_GTU
: enc
= 0xc; break;
192 case CC_NE
: enc
= 0x5; break;
193 case CC_NEU
: enc
= 0xd; break;
194 case CC_GE
: enc
= 0x6; break;
195 case CC_GEU
: enc
= 0xe; break;
196 case CC_TR
: enc
= 0xf; break;
197 case CC_FL
: enc
= 0x0; break;
199 case CC_O
: enc
= 0x10; break;
200 case CC_C
: enc
= 0x11; break;
201 case CC_A
: enc
= 0x12; break;
202 case CC_S
: enc
= 0x13; break;
203 case CC_NS
: enc
= 0x1c; break;
204 case CC_NA
: enc
= 0x1d; break;
205 case CC_NC
: enc
= 0x1e; break;
206 case CC_NO
: enc
= 0x1f; break;
210 assert(!"invalid condition code");
213 code
[pos
/ 32] |= enc
<< (pos
% 32);
217 CodeEmitterNV50::emitFlagsRd(const Instruction
*i
)
219 int s
= (i
->flagsSrc
>= 0) ? i
->flagsSrc
: i
->predSrc
;
221 assert(!(code
[1] & 0x00003f80));
224 assert(i
->getSrc(s
)->reg
.file
== FILE_FLAGS
);
225 emitCondCode(i
->cc
, 32 + 7);
226 srcId(i
->src
[s
], 32 + 12);
233 CodeEmitterNV50::emitFlagsWr(const Instruction
*i
)
235 assert(!(code
[1] & 0x70));
237 if (i
->flagsDef
>= 0)
238 code
[1] |= (DDATA(i
->def
[i
->flagsDef
]).id
<< 4) | 0x40;
242 CodeEmitterNV50::setARegBits(unsigned int u
)
244 code
[0] |= (u
& 3) << 26;
249 CodeEmitterNV50::setAReg16(const Instruction
*i
, int s
)
251 s
= i
->src
[s
].indirect
[0];
253 setARegBits(SDATA(i
->src
[s
]).id
+ 1);
257 CodeEmitterNV50::setImmediate(const Instruction
*i
, int s
)
259 const ImmediateValue
*imm
= i
->src
[s
].get()->asImm();
263 code
[0] |= (imm
->reg
.data
.u32
& 0x3f) << 16;
264 code
[1] |= (imm
->reg
.data
.u32
>> 6) << 2;
268 CodeEmitterNV50::setDst(const Value
*dst
)
270 const Storage
*reg
= &dst
->join
->reg
;
272 assert(reg
->file
!= FILE_ADDRESS
);
274 if (reg
->data
.id
< 0) {
275 code
[0] |= (127 << 2) | 1;
278 if (reg
->file
== FILE_SHADER_OUTPUT
)
280 code
[0] |= reg
->data
.id
<< 2;
285 CodeEmitterNV50::setDst(const Instruction
*i
, int d
)
287 if (i
->defExists(d
)) {
288 setDst(i
->getDef(d
));
291 code
[0] |= 0x01fc; // bit bucket
297 CodeEmitterNV50::emitSrc0(const ValueRef
& ref
)
299 const Storage
*reg
= &ref
.rep()->reg
;
301 if (reg
->file
== FILE_SHADER_INPUT
)
302 code
[1] |= 0x00200000;
304 if (reg
->file
!= FILE_GPR
)
305 ERROR("invalid src0 register file: %d\n", reg
->file
);
307 assert(reg
->data
.id
< 128);
308 code
[0] |= reg
->data
.id
<< 9;
312 CodeEmitterNV50::emitSrc1(const ValueRef
& ref
)
314 const Storage
*reg
= &ref
.rep()->reg
;
316 if (reg
->file
== FILE_MEMORY_CONST
) {
317 assert(!(code
[1] & 0x01800000));
319 code
[1] |= reg
->fileIndex
<< 22;
321 if (reg
->file
!= FILE_GPR
) {
322 ERROR("invalid src1 register file: %d\n", reg
->file
);
325 assert(reg
->data
.id
< 128);
326 code
[0] |= reg
->data
.id
<< 16;
330 CodeEmitterNV50::emitSrc2(const ValueRef
& ref
)
332 const Storage
*reg
= &ref
.rep()->reg
;
334 if (reg
->file
== FILE_MEMORY_CONST
) {
335 assert(!(code
[1] & 0x01800000));
337 code
[1] |= reg
->fileIndex
<< 22;
339 if (reg
->file
!= FILE_GPR
) {
340 ERROR("invalid src1 register file: %d\n", reg
->file
);
343 assert(reg
->data
.id
< 128);
344 code
[1] |= reg
->data
.id
<< 14;
348 // - long instruction
349 // - 1 to 3 sources in slots 0, 1, 2
352 CodeEmitterNV50::emitForm_MAD(const Instruction
*i
)
354 assert(i
->encSize
== 8);
374 // like default form, but 2nd source in slot 2, and no 3rd source
376 CodeEmitterNV50::emitForm_ADD(const Instruction
*i
)
378 assert(i
->encSize
== 8);
395 // default short form
397 CodeEmitterNV50::emitForm_MUL(const Instruction
*i
)
399 assert(i
->encSize
== 4 && !(code
[0] & 1));
400 assert(i
->defExists(0));
401 assert(!i
->getPredicate());
412 // usual immediate form
413 // - 1 to 3 sources where last is immediate
414 // - no address or predicate possible
416 CodeEmitterNV50::emitForm_IMM(const Instruction
*i
)
418 assert(i
->encSize
== 8);
421 assert(i
->defExists(0) && i
->srcExists(0));
425 if (i
->srcExists(2)) {
430 if (i
->srcExists(1)) {
439 CodeEmitterNV50::emitLoadStoreSize(DataType ty
, int pos
)
444 case TYPE_F32
: // fall through
445 case TYPE_S32
: // fall through
446 case TYPE_U32
: enc
= 0x6; break;
447 case TYPE_B128
: enc
= 0x5; break;
448 case TYPE_F64
: enc
= 0x4; break;
449 case TYPE_S16
: enc
= 0x3; break;
450 case TYPE_U16
: enc
= 0x2; break;
451 case TYPE_S8
: enc
= 0x1; break;
452 case TYPE_U8
: enc
= 0x0; break;
455 assert(!"invalid load/store type");
458 code
[pos
/ 32] |= enc
<< (pos
% 32);
462 CodeEmitterNV50::emitLOAD(const Instruction
*i
)
464 DataFile sf
= i
->src
[0].getFile();
467 case FILE_SHADER_INPUT
:
468 code
[0] = 0x10000001;
469 code
[1] = 0x04200000 | (i
->lanes
<< 14);
471 case FILE_MEMORY_CONST
:
472 code
[0] = 0x10000001;
473 code
[1] = 0x24000000 | (i
->getSrc(0)->reg
.fileIndex
<< 22);
475 case FILE_MEMORY_LOCAL
:
476 code
[0] = 0xd0000001;
477 code
[1] = 0x40000000;
479 case FILE_MEMORY_GLOBAL
:
480 code
[0] = 0xd0000001 | (i
->getSrc(0)->reg
.fileIndex
<< 16);
481 code
[1] = 0x80000000;
484 assert(!"invalid load source file");
487 if (sf
== FILE_MEMORY_LOCAL
||
488 sf
== FILE_MEMORY_GLOBAL
)
489 emitLoadStoreSize(i
->sType
, 21 + 32);
496 if (i
->src
[0].getFile() == FILE_MEMORY_GLOBAL
) {
497 srcId(*i
->src
[0].getIndirect(0), 9);
500 srcAddr16(i
->src
[0], 9);
505 CodeEmitterNV50::emitSTORE(const Instruction
*i
)
507 DataFile f
= i
->getSrc(0)->reg
.file
;
508 int32_t offset
= i
->getSrc(0)->reg
.data
.offset
;
511 case FILE_SHADER_OUTPUT
:
512 code
[0] = 0x00000001 | ((offset
>> 2) << 2);
513 code
[1] = 0x80c00000;
514 srcId(i
->src
[1], 32 + 15);
516 case FILE_MEMORY_GLOBAL
:
517 code
[0] = 0xd0000000;
518 code
[1] = 0xa0000000;
519 emitLoadStoreSize(i
->dType
, 21 + 32);
521 case FILE_MEMORY_LOCAL
:
522 code
[0] = 0xd0000001;
523 code
[1] = 0x60000000;
524 emitLoadStoreSize(i
->dType
, 21 + 32);
526 case FILE_MEMORY_SHARED
:
527 code
[0] = 0x00000001;
528 code
[1] = 0xe0000000;
529 switch (typeSizeof(i
->dType
)) {
531 code
[0] |= offset
<< 9;
532 code
[1] |= 0x00400000;
535 code
[0] |= (offset
>> 1) << 9;
538 code
[0] |= (offset
>> 2) << 9;
539 code
[1] |= 0x04000000;
547 assert(!"invalid store destination file");
551 if (f
!= FILE_SHADER_OUTPUT
) {
553 if (f
== FILE_MEMORY_GLOBAL
)
554 srcId(*i
->src
[0].getIndirect(0), 9);
555 if (f
== FILE_MEMORY_LOCAL
)
556 srcAddr16(i
->src
[0], 9);
558 if (f
!= FILE_MEMORY_GLOBAL
)
565 CodeEmitterNV50::emitMOV(const Instruction
*i
)
567 DataFile sf
= i
->getSrc(0)->reg
.file
;
568 DataFile df
= i
->getDef(0)->reg
.file
;
570 assert(sf
== FILE_GPR
|| df
== FILE_GPR
);
572 if (sf
== FILE_FLAGS
) {
573 code
[0] = 0x00000001;
574 code
[1] = 0x20000000;
576 srcId(i
->src
[0], 12);
579 if (sf
== FILE_ADDRESS
) {
580 code
[0] = 0x00000001;
581 code
[1] = 0x40000000;
583 setARegBits(SDATA(i
->src
[0]).id
+ 1);
585 if (df
== FILE_FLAGS
) {
586 code
[0] = 0x00000001;
587 code
[1] = 0xa0000000;
592 if (sf
== FILE_IMMEDIATE
) {
593 code
[0] = 0x10008001;
594 code
[1] = 0x00000003;
597 if (i
->encSize
== 4) {
598 code
[0] = 0x10008000;
600 code
[0] = 0x10000001;
601 code
[1] = 0x04000000 | (i
->lanes
<< 14);
606 if (df
== FILE_SHADER_OUTPUT
) {
607 assert(i
->encSize
== 8);
613 CodeEmitterNV50::emitNOP()
615 code
[0] = 0xf0000001;
616 code
[1] = 0xe0000000;
620 CodeEmitterNV50::emitQUADOP(const Instruction
*i
, uint8_t lane
, uint8_t quOp
)
622 code
[0] = 0xc0000000 | (lane
<< 16);
623 code
[1] = 0x80000000;
625 code
[0] |= (quOp
& 0x03) << 20;
626 code
[1] |= (quOp
& 0xfc) << 20;
630 if (!i
->srcExists(1))
631 srcId(i
->src
[0], 32 + 14);
635 CodeEmitterNV50::emitPFETCH(const Instruction
*i
)
637 code
[0] = 0x11800001;
638 code
[1] = 0x04200000 | (0xf << 14);
641 srcAddr8(i
->src
[0], 9);
646 CodeEmitterNV50::emitINTERP(const Instruction
*i
)
648 code
[0] = 0x80000000;
651 srcAddr8(i
->src
[0], 16);
653 if (i
->getInterpMode() == NV50_IR_INTERP_FLAT
) {
656 if (i
->op
== OP_PINTERP
) {
660 if (i
->getSampleMode() == NV50_IR_INTERP_CENTROID
)
664 if (i
->encSize
== 8) {
667 (code
[0] & (3 << 24)) >> (24 - 16) |
668 (code
[0] & (1 << 8)) >> (18 - 8);
669 code
[0] &= ~0x03000100;
675 CodeEmitterNV50::emitMINMAX(const Instruction
*i
)
677 if (i
->dType
== TYPE_F64
) {
678 code
[0] = 0xe0000000;
679 code
[1] = (i
->op
== OP_MIN
) ? 0xa0000000 : 0xc0000000;
681 code
[0] = 0x30000000;
682 code
[1] = 0x80000000;
684 code
[1] |= 0x20000000;
687 case TYPE_F32
: code
[0] |= 0x80000000; break;
688 case TYPE_S32
: code
[1] |= 0x8c000000; break;
689 case TYPE_U32
: code
[1] |= 0x84000000; break;
690 case TYPE_S16
: code
[1] |= 0x80000000; break;
691 case TYPE_U16
: break;
696 code
[1] |= i
->src
[0].mod
.abs() << 20;
697 code
[1] |= i
->src
[1].mod
.abs() << 19;
703 CodeEmitterNV50::emitFMAD(const Instruction
*i
)
705 const int neg_mul
= i
->src
[0].mod
.neg() ^ i
->src
[1].mod
.neg();
706 const int neg_add
= i
->src
[2].mod
.neg();
708 code
[0] = 0xe0000000;
710 if (i
->encSize
== 4) {
712 assert(!neg_mul
&& !neg_add
);
715 code
[1] |= neg_mul
<< 26;
716 code
[1] |= neg_add
<< 27;
723 CodeEmitterNV50::emitFADD(const Instruction
*i
)
725 const int neg0
= i
->src
[0].mod
.neg();
726 const int neg1
= i
->src
[1].mod
.neg() ^ ((i
->op
== OP_SUB
) ? 1 : 0);
728 code
[0] = 0xb0000000;
730 assert(!(i
->src
[0].mod
| i
->src
[1].mod
).abs());
732 if (i
->src
[1].getFile() == FILE_IMMEDIATE
) {
734 code
[0] |= neg0
<< 15;
735 code
[0] |= neg1
<< 22;
737 if (i
->encSize
== 8) {
739 code
[1] |= neg0
<< 26;
740 code
[1] |= neg1
<< 27;
745 code
[0] |= neg0
<< 15;
746 code
[0] |= neg1
<< 22;
751 CodeEmitterNV50::emitUADD(const Instruction
*i
)
753 code
[0] = 0x20008000;
755 if (i
->src
[0].getFile() == FILE_IMMEDIATE
) {
758 if (i
->encSize
== 8) {
759 code
[0] = 0x20000000;
760 code
[1] = 0x04000000;
765 assert(!(i
->src
[0].mod
.neg() && i
->src
[1].mod
.neg()));
766 code
[0] |= i
->src
[0].mod
.neg() << 28;
767 code
[0] |= i
->src
[1].mod
.neg() << 22;
771 CodeEmitterNV50::emitAADD(const Instruction
*i
)
773 const int s
= (i
->op
== OP_MOV
) ? 0 : 1;
775 code
[0] = 0xd0000001 | (i
->getSrc(s
)->reg
.data
.u16
<< 9);
776 code
[1] = 0x20000000;
778 code
[0] |= (DDATA(i
->def
[0]).id
+ 1) << 2;
782 if (s
&& i
->srcExists(0))
783 setARegBits(SDATA(i
->src
[0]).id
+ 1);
787 CodeEmitterNV50::emitFMUL(const Instruction
*i
)
789 const int neg
= (i
->src
[0].mod
^ i
->src
[1].mod
).neg();
791 code
[0] = 0xc0000000;
793 if (i
->src
[0].getFile() == FILE_IMMEDIATE
) {
798 if (i
->encSize
== 8) {
801 code
[1] |= 0x08000000;
810 CodeEmitterNV50::emitSET(const Instruction
*i
)
812 code
[0] = 0x30000000;
813 code
[1] = 0x60000000;
815 emitCondCode(i
->asCmp()->setCond
, 32 + 14);
818 case TYPE_F32
: code
[0] |= 0x80000000; break;
819 case TYPE_S32
: code
[1] |= 0x0c000000; break;
820 case TYPE_U32
: code
[1] |= 0x04000000; break;
821 case TYPE_S16
: code
[1] |= 0x08000000; break;
822 case TYPE_U16
: break;
831 CodeEmitterNV50::roundMode_CVT(RoundMode rnd
)
834 case ROUND_NI
: code
[1] |= 0x08000000; break;
835 case ROUND_M
: code
[1] |= 0x00020000; break;
836 case ROUND_MI
: code
[1] |= 0x08020000; break;
837 case ROUND_P
: code
[1] |= 0x00040000; break;
838 case ROUND_PI
: code
[1] |= 0x08040000; break;
839 case ROUND_Z
: code
[1] |= 0x00060000; break;
840 case ROUND_ZI
: code
[1] |= 0x08060000; break;
842 assert(rnd
== ROUND_N
);
848 CodeEmitterNV50::emitCVT(const Instruction
*i
)
850 const bool f2f
= isFloatType(i
->dType
) && isFloatType(i
->sType
);
854 case OP_CEIL
: rnd
= f2f
? ROUND_PI
: ROUND_P
; break;
855 case OP_FLOOR
: rnd
= f2f
? ROUND_MI
: ROUND_M
; break;
856 case OP_TRUNC
: rnd
= f2f
? ROUND_ZI
: ROUND_Z
; break;
862 code
[0] = 0xa0000000;
867 case TYPE_F64
: code
[1] = 0xc4404000; break;
868 case TYPE_S64
: code
[1] = 0x44414000; break;
869 case TYPE_U64
: code
[1] = 0x44404000; break;
870 case TYPE_F32
: code
[1] = 0xc4400000; break;
871 case TYPE_S32
: code
[1] = 0x44410000; break;
872 case TYPE_U32
: code
[1] = 0x44400000; break;
880 case TYPE_F64
: code
[1] = 0x8c404000; break;
881 case TYPE_F32
: code
[1] = 0x8c400000; break;
889 case TYPE_F64
: code
[1] = 0x84404000; break;
890 case TYPE_F32
: code
[1] = 0x84400000; break;
898 case TYPE_F64
: code
[1] = 0xc0404000; break;
899 case TYPE_S64
: code
[1] = 0x40414000; break;
900 case TYPE_U64
: code
[1] = 0x40404000; break;
901 case TYPE_F32
: code
[1] = 0xc4004000; break;
902 case TYPE_S32
: code
[1] = 0x44014000; break;
903 case TYPE_U32
: code
[1] = 0x44004000; break;
904 case TYPE_F16
: code
[1] = 0xc4000000; break;
912 case TYPE_F64
: code
[1] = 0x88404000; break;
913 case TYPE_F32
: code
[1] = 0x8c004000; break;
914 case TYPE_S32
: code
[1] = 0x0c014000; break;
915 case TYPE_U32
: code
[1] = 0x0c004000; break;
916 case TYPE_F16
: code
[1] = 0x8c000000; break;
917 case TYPE_S16
: code
[1] = 0x0c010000; break;
918 case TYPE_U16
: code
[1] = 0x0c000000; break;
919 case TYPE_S8
: code
[1] = 0x0c018000; break;
920 case TYPE_U8
: code
[1] = 0x0c008000; break;
928 case TYPE_F64
: code
[1] = 0x80404000; break;
929 case TYPE_F32
: code
[1] = 0x84004000; break;
930 case TYPE_S32
: code
[1] = 0x04014000; break;
931 case TYPE_U32
: code
[1] = 0x04004000; break;
932 case TYPE_F16
: code
[1] = 0x84000000; break;
933 case TYPE_S16
: code
[1] = 0x04010000; break;
934 case TYPE_U16
: code
[1] = 0x04000000; break;
935 case TYPE_S8
: code
[1] = 0x04018000; break;
936 case TYPE_U8
: code
[1] = 0x04008000; break;
949 if (typeSizeof(i
->sType
) == 1 && i
->getSrc(0)->reg
.size
== 4)
950 code
[1] |= 0x00004000;
955 case OP_ABS
: code
[1] |= 1 << 20; break;
956 case OP_SAT
: code
[1] |= 1 << 19; break;
957 case OP_NEG
: code
[1] |= 1 << 29; break;
961 code
[1] ^= i
->src
[0].mod
.neg() << 29;
962 code
[1] |= i
->src
[0].mod
.abs() << 20;
966 assert(i
->op
!= OP_ABS
|| !i
->src
[0].mod
.neg());
972 CodeEmitterNV50::emitPreOp(const Instruction
*i
)
974 code
[0] = 0xb0000000;
975 code
[1] = (i
->op
== OP_PREEX2
) ? 0xc0004000 : 0xc0000000;
977 code
[1] |= i
->src
[0].mod
.abs() << 20;
978 code
[1] |= i
->src
[0].mod
.neg() << 26;
984 CodeEmitterNV50::emitSFnOp(const Instruction
*i
, uint8_t subOp
)
986 code
[0] = 0x90000000;
988 if (i
->encSize
== 4) {
989 assert(i
->op
== OP_RCP
);
992 code
[1] = subOp
<< 29;
993 code
[1] |= i
->src
[0].mod
.abs() << 20;
994 code
[1] |= i
->src
[0].mod
.neg() << 26;
1000 CodeEmitterNV50::emitLogicOp(const Instruction
*i
)
1002 code
[0] = 0xd0000000;
1004 if (i
->src
[1].getFile() == FILE_IMMEDIATE
) {
1006 case OP_OR
: code
[0] |= 0x0100; break;
1007 case OP_XOR
: code
[0] |= 0x8000; break;
1009 assert(i
->op
== OP_AND
);
1015 case OP_AND
: code
[1] = 0x04000000; break;
1016 case OP_OR
: code
[1] = 0x04004000; break;
1017 case OP_XOR
: code
[1] = 0x04008000; break;
1027 CodeEmitterNV50::emitARL(const Instruction
*i
)
1029 assert(i
->src
[1].getFile() == FILE_IMMEDIATE
);
1031 code
[0] = 0x00000001 | (i
->getSrc(1)->reg
.data
.u32
& 0x3f) << 16;
1032 code
[1] = 0xc0000000;
1034 code
[0] |= (DDATA(i
->def
[0]).id
+ 1) << 2;
1035 emitSrc0(i
->src
[0]);
1040 CodeEmitterNV50::emitShift(const Instruction
*i
)
1042 if (i
->def
[0].getFile() == FILE_ADDRESS
) {
1045 code
[0] = 0x30000001;
1046 code
[1] = (i
->op
== OP_SHR
) ? 0xe4000000 : 0xc4000000;
1047 if (isSignedType(i
->sType
))
1050 if (i
->src
[1].getFile() == FILE_IMMEDIATE
) {
1052 code
[0] |= (i
->getSrc(1)->reg
.data
.u32
& 0x7f) << 16;
1061 CodeEmitterNV50::emitOUT(const Instruction
*i
)
1063 code
[0] = (i
->op
== OP_EMIT
) ? 0xf0000200 : 0xf0000400;
1064 code
[1] = 0xc0000001;
1070 CodeEmitterNV50::emitTEX(const TexInstruction
*i
)
1072 code
[0] = 0xf0000001;
1073 code
[1] = 0x00000000;
1077 code
[1] = 0x20000000;
1080 code
[1] = 0x40000000;
1083 code
[0] = 0x01000000;
1086 code
[0] = 0x01000000;
1087 code
[1] = 0x80000000;
1090 assert(i
->op
== OP_TEX
);
1094 code
[0] |= i
->tex
.r
<< 9;
1095 code
[0] |= i
->tex
.s
<< 17;
1097 int argc
= i
->tex
.target
.getArgCount();
1099 if (i
->op
== OP_TXB
|| i
->op
== OP_TXL
)
1101 if (i
->tex
.target
.isShadow())
1105 code
[0] |= (argc
- 1) << 22;
1107 if (i
->tex
.target
.isCube()) {
1108 code
[0] |= 0x08000000;
1110 if (i
->tex
.useOffsets
) {
1111 code
[1] |= (i
->tex
.offset
[0][0] & 0xf) << 16;
1112 code
[1] |= (i
->tex
.offset
[0][1] & 0xf) << 20;
1113 code
[1] |= (i
->tex
.offset
[0][2] & 0xf) << 24;
1116 code
[0] |= (i
->tex
.mask
& 0x3) << 25;
1117 code
[1] |= (i
->tex
.mask
& 0xc) << 12;
1119 if (i
->tex
.liveOnly
)
1122 defId(i
->def
[0], 2);
1128 CodeEmitterNV50::emitFlow(const Instruction
*i
, uint8_t flowOp
)
1130 const FlowInstruction
*f
= i
->asFlow();
1132 code
[0] = 0x00000003 | (flowOp
<< 28);
1133 code
[1] = 0x00000000;
1137 if (f
&& f
->target
.bb
) {
1140 if (f
->op
== OP_CALL
) {
1142 pos
= 0; // XXX: TODO
1144 pos
= f
->target
.fn
->binPos
;
1147 pos
= f
->target
.bb
->binPos
;
1150 code
[0] |= ((pos
>> 2) & 0xffff) << 11;
1151 code
[1] |= ((pos
>> 18) & 0x003f) << 14;
1156 CodeEmitterNV50::emitInstruction(Instruction
*insn
)
1158 if (!insn
->encSize
) {
1159 ERROR("skipping unencodable instruction: "); insn
->print();
1162 if (codeSize
+ insn
->encSize
> codeSizeLimit
) {
1163 ERROR("code emitter output buffer too small\n");
1192 if (isFloatType(insn
->dType
))
1198 if (isFloatType(insn
->dType
))
1248 emitTEX(insn
->asTex());
1255 emitFlow(insn
, 0x0);
1258 emitFlow(insn
, 0x1);
1261 emitFlow(insn
, 0x2);
1264 emitFlow(insn
, 0x3);
1267 emitFlow(insn
, 0x4);
1270 emitFlow(insn
, 0x5);
1273 emitFlow(insn
, 0x6);
1276 emitFlow(insn
, 0x7);
1279 emitFlow(insn
, 0xa);
1282 emitFlow(insn
, 0xd);
1285 emitQUADOP(insn
, insn
->lanes
, insn
->subOp
);
1288 emitQUADOP(insn
, 4, insn
->src
[0].mod
.neg() ? 0x66 : 0x99);
1291 emitQUADOP(insn
, 5, insn
->src
[0].mod
.neg() ? 0x5a : 0xa5);
1296 ERROR("operation should have been eliminated");
1310 ERROR("operation should have been lowered\n");
1313 ERROR("unknow op\n");
1322 assert((insn
->encSize
== 8) == (code
[1] & 1));
1324 code
+= insn
->encSize
/ 4;
1325 codeSize
+= insn
->encSize
;
1330 CodeEmitterNV50::getMinEncodingSize(const Instruction
*i
) const
1332 const Target::OpInfo
&info
= targ
->getOpInfo(i
);
1334 if (info
.minEncSize
== 8)
1340 CodeEmitterNV50::CodeEmitterNV50(const Target
*target
) : targ(target
)
1343 codeSize
= codeSizeLimit
= 0;
1347 Target::getCodeEmitter(Program::Type type
)
1349 CodeEmitterNV50
*emit
= new CodeEmitterNV50(this);
1350 emit
->setProgramType(type
);
1354 } // namespace nv50_ir