1/*
2 * Copyright 2020 Red Hat Inc.
3 *
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:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
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 COPYRIGHT HOLDER(S) OR AUTHOR(S) 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.
21 */
22#ifndef __NV50_IR_EMIT_GV100_H__
23#define __NV50_IR_EMIT_GV100_H__
24#include "nv50_ir_target_gv100.h"
25
26namespace nv50_ir {
27
28class CodeEmitterGV100 : public CodeEmitter {
29public:
30   CodeEmitterGV100(TargetGV100 *target);
31
32   virtual bool emitInstruction(Instruction *);
33   virtual uint32_t getMinEncodingSize(const Instruction *) const { return 16; }
34
35private:
36   const Program *prog;
37   const TargetGV100 *targ;
38   const Instruction *insn;
39
40   virtual void prepareEmission(Program *);
41   virtual void prepareEmission(Function *);
42   virtual void prepareEmission(BasicBlock *);
43
44   inline void emitInsn(uint32_t op) {
45      code[0] = op;
46      code[1] = 0;
47      code[2] = 0;
48      code[3] = 0;
49      if (insn->predSrc >= 0) {
50         emitField(12, 3, insn->getSrc(insn->predSrc)->rep()->reg.data.id);
51         emitField(15, 1, insn->cc == CC_NOT_P);
52      } else {
53         emitField(12, 3, 7);
54      }
55   };
56
57   inline void emitField(int b, int s, uint64_t v) {
58      if (b >= 0) {
59         uint64_t m = ~0ULL >> (64 - s);
60         uint64_t d = v & m;
61         assert(!(v & ~m) || (v & ~m) == ~m);
62         if (b < 64 && b + s > 64) {
63            *(uint64_t *)&code[0] |= d << b;
64            *(uint64_t *)&code[2] |= d >> (64 - b);
65         } else {
66            *(uint64_t *)&code[(b/64*2)] |= d << (b & 0x3f);
67         }
68      }
69   };
70
71   inline void emitABS(int pos, int src, bool supported)
72   {
73      if (insn->src(src).mod.abs()) {
74         assert(supported);
75         emitField(pos, 1, 1);
76      }
77   }
78
79   inline void emitABS(int pos, int src)
80   {
81      emitABS(pos, src, true);
82   }
83
84   inline void emitNEG(int pos, int src, bool supported) {
85      if (insn->src(src).mod.neg()) {
86         assert(supported);
87         emitField(pos, 1, 1);
88      }
89   }
90
91   inline void emitNEG(int pos, int src) {
92      emitNEG(pos, src, true);
93   }
94
95   inline void emitNOT(int pos) {
96      emitField(pos, 1, 0);
97   };
98
99   inline void emitNOT(int pos, const ValueRef &ref) {
100      emitField(pos, 1, !!(ref.mod & Modifier(NV50_IR_MOD_NOT)));
101   }
102
103   inline void emitSAT(int pos) {
104      emitField(pos, 1, insn->saturate);
105   }
106
107   inline void emitRND(int rmp, RoundMode rnd, int rip) {
108      int rm = 0, ri = 0;
109      switch (rnd) {
110      case ROUND_NI: ri = 1;
111      case ROUND_N : rm = 0; break;
112      case ROUND_MI: ri = 1;
113      case ROUND_M : rm = 1; break;
114      case ROUND_PI: ri = 1;
115      case ROUND_P : rm = 2; break;
116      case ROUND_ZI: ri = 1;
117      case ROUND_Z : rm = 3; break;
118      default:
119         assert(!"invalid round mode");
120         break;
121      }
122      emitField(rip, 1, ri);
123      emitField(rmp, 2, rm);
124   }
125
126   inline void emitRND(int pos) {
127      emitRND(pos, insn->rnd, -1);
128   }
129
130   inline void emitFMZ(int pos, int len) {
131      emitField(pos, len, insn->dnz << 1 | insn->ftz);
132   }
133
134   inline void emitPDIV(int pos) {
135      emitField(pos, 3, insn->postFactor + 4);
136   }
137
138   inline void emitO(int pos) {
139      emitField(pos, 1, insn->getSrc(0)->reg.file == FILE_SHADER_OUTPUT);
140   }
141
142   inline void emitP(int pos) {
143      emitField(pos, 1, insn->perPatch);
144   }
145
146   inline void emitCond3(int pos, CondCode code) {
147      int data = 0;
148
149      switch (code) {
150      case CC_FL : data = 0x00; break;
151      case CC_LTU:
152      case CC_LT : data = 0x01; break;
153      case CC_EQU:
154      case CC_EQ : data = 0x02; break;
155      case CC_LEU:
156      case CC_LE : data = 0x03; break;
157      case CC_GTU:
158      case CC_GT : data = 0x04; break;
159      case CC_NEU:
160      case CC_NE : data = 0x05; break;
161      case CC_GEU:
162      case CC_GE : data = 0x06; break;
163      case CC_TR : data = 0x07; break;
164      default:
165         assert(!"invalid cond3");
166         break;
167      }
168
169      emitField(pos, 3, data);
170   }
171
172   inline void emitCond4(int pos, CondCode code) {
173      int data = 0;
174
175      switch (code) {
176      case CC_FL: data = 0x00; break;
177      case CC_LT: data = 0x01; break;
178      case CC_EQ: data = 0x02; break;
179      case CC_LE: data = 0x03; break;
180      case CC_GT: data = 0x04; break;
181      case CC_NE: data = 0x05; break;
182      case CC_GE: data = 0x06; break;
183   //   case CC_NUM: data = 0x07; break;
184   //   case CC_NAN: data = 0x08; break;
185      case CC_LTU: data = 0x09; break;
186      case CC_EQU: data = 0x0a; break;
187      case CC_LEU: data = 0x0b; break;
188      case CC_GTU: data = 0x0c; break;
189      case CC_NEU: data = 0x0d; break;
190      case CC_GEU: data = 0x0e; break;
191      case CC_TR:  data = 0x0f; break;
192      default:
193         assert(!"invalid cond4");
194         break;
195      }
196
197      emitField(pos, 4, data);
198   }
199
200   inline void emitSYS(int pos, const Value *val) {
201      int id = val ? val->reg.data.id : -1;
202
203      switch (id) {
204      case SV_LANEID         : id = 0x00; break;
205      case SV_VERTEX_COUNT   : id = 0x10; break;
206      case SV_INVOCATION_ID  : id = 0x11; break;
207      case SV_THREAD_KILL    : id = 0x13; break;
208      case SV_INVOCATION_INFO: id = 0x1d; break;
209      case SV_COMBINED_TID   : id = 0x20; break;
210      case SV_TID            : id = 0x21 + val->reg.data.sv.index; break;
211      case SV_CTAID          : id = 0x25 + val->reg.data.sv.index; break;
212      case SV_LANEMASK_EQ    : id = 0x38; break;
213      case SV_LANEMASK_LT    : id = 0x39; break;
214      case SV_LANEMASK_LE    : id = 0x3a; break;
215      case SV_LANEMASK_GT    : id = 0x3b; break;
216      case SV_LANEMASK_GE    : id = 0x3c; break;
217      case SV_CLOCK          : id = 0x50 + val->reg.data.sv.index; break;
218      default:
219         assert(!"invalid system value");
220         id = 0;
221         break;
222      }
223
224      emitField(pos, 8, id);
225   }
226
227   inline void emitSYS(int pos, const ValueRef &ref) {
228      emitSYS(pos, ref.get() ? ref.rep() : (const Value *)NULL);
229   }
230
231   inline void emitBTS(int pos, const Value *val) {
232      if (val->inFile(FILE_THREAD_STATE)) {
233         TSSemantic ts = val->reg.data.ts == TS_PQUAD_MACTIVE ? TS_MACTIVE : val->reg.data.ts;
234         emitField(pos, 5, ts | 0x10);
235      } else {
236         emitField(pos, 5, val->reg.data.id);
237      }
238   }
239
240   inline void emitBTS(int pos, const ValueRef &ref) {
241      emitBTS(pos, ref.get() ? ref.rep() : (const Value *)NULL);
242   }
243
244   inline void emitBTS(int pos, const ValueDef &def) {
245      emitBTS(pos, def.get() ? def.rep() : (const Value *)NULL);
246   }
247
248   inline void emitGPR(int pos, const Value *val, int off) {
249      emitField(pos, 8, val && !val->inFile(FILE_FLAGS) ?
250                val->reg.data.id + off: 255);
251   }
252
253   inline void emitGPR(int pos, const Value *v) {
254      emitGPR(pos, v, 0);
255   }
256
257   inline void emitGPR(int pos) {
258      emitGPR(pos, (const Value *)NULL);
259   }
260
261   inline void emitGPR(int pos, const ValueRef &ref) {
262      emitGPR(pos, ref.get() ? ref.rep() : (const Value *)NULL);
263   }
264
265   inline void emitGPR(int pos, const ValueRef *ref) {
266      emitGPR(pos, ref ? ref->rep() : (const Value *)NULL);
267   }
268
269   inline void emitGPR(int pos, const ValueDef &def) {
270      emitGPR(pos, def.get() ? def.rep() : (const Value *)NULL);
271   }
272
273   inline void emitGPR(int pos, const ValueDef &def, int off) {
274      emitGPR(pos, def.get() ? def.rep() : (const Value *)NULL, off);
275   }
276
277   inline void emitPRED(int pos, const Value *val) {
278      emitField(pos, 3, val ? val->reg.data.id : 7);
279   };
280
281   inline void emitPRED(int pos) {
282      emitPRED(pos, (const Value *)NULL);
283   }
284
285   inline void emitPRED(int pos, const ValueRef &ref) {
286      emitPRED(pos, ref.get() ? ref.rep() : (const Value *)NULL);
287   }
288
289   inline void emitPRED(int pos, const ValueDef &def) {
290      emitPRED(pos, def.get() ? def.rep() : (const Value *)NULL);
291   }
292
293   inline void emitCBUF(int buf, int gpr, int off, int len, int align,
294                        const ValueRef &ref) {
295      const Value *v = ref.get();
296      const Symbol *s = v->asSym();
297
298      assert(!(s->reg.data.offset & ((1 << align) - 1)));
299
300      emitField(buf,  5, v->reg.fileIndex);
301      if (gpr >= 0)
302         emitGPR(gpr, ref.getIndirect(0));
303      emitField(off, 16, s->reg.data.offset);
304   }
305
306   inline void emitIMMD(int pos, int len, const ValueRef &ref) {
307      const ImmediateValue *imm = ref.get()->asImm();
308      uint32_t val = imm->reg.data.u32;
309
310      if (insn->sType == TYPE_F64) {
311         assert(!(imm->reg.data.u64 & 0x00000000ffffffffULL));
312         val = imm->reg.data.u64 >> 32;
313      }
314
315      emitField(pos, len, val);
316   }
317
318   inline void emitADDR(int gpr, int off, int len, int shr,
319                        const ValueRef &ref) {
320      const Value *v = ref.get();
321      assert(!(v->reg.data.offset & ((1 << shr) - 1)));
322      if (gpr >= 0)
323         emitGPR(gpr, ref.getIndirect(0));
324      emitField(off, len, v->reg.data.offset >> shr);
325   }
326
327   inline void emitFormA(uint16_t op, uint8_t forms, int src0, int src1, int src2);
328   inline void emitFormA_RRR(uint16_t op, int src1, int src2);
329   inline void emitFormA_RRI(uint16_t op, int src1, int src2);
330   inline void emitFormA_RRC(uint16_t op, int src1, int src2);
331   inline void emitFormA_I32(int src);
332
333   void emitBRA();
334   void emitEXIT();
335   void emitKILL();
336   void emitNOP();
337   void emitWARPSYNC();
338
339   void emitCS2R();
340   void emitF2F();
341   void emitF2I();
342   void emitFRND();
343   void emitI2F();
344   void emitMOV();
345   void emitPRMT();
346   void emitS2R();
347   void emitSEL();
348   void emitSHFL();
349
350   void emitFADD();
351   void emitFFMA();
352   void emitFMNMX();
353   void emitFMUL();
354   void emitFSET_BF();
355   void emitFSETP();
356   void emitFSWZADD();
357   void emitMUFU();
358
359   void emitDADD();
360   void emitDFMA();
361   void emitDMUL();
362   void emitDSETP();
363
364   void emitBMSK();
365   void emitBREV();
366   void emitFLO();
367   void emitIABS();
368   void emitIADD3();
369   void emitIMAD();
370   void emitIMAD_WIDE();
371   void emitISETP();
372   void emitLEA();
373   void emitLOP3_LUT();
374   void emitPOPC();
375   void emitSGXT();
376   void emitSHF();
377
378   void emitALD();
379   void emitAST();
380   void emitATOM();
381   void emitATOMS();
382   void emitIPA();
383   void emitISBERD();
384   void emitLDSTc(int, int);
385   void emitLDSTs(int, DataType);
386   void emitLD();
387   void emitLDC();
388   void emitLDL();
389   void emitLDS();
390   void emitOUT();
391   void emitRED();
392   void emitST();
393   void emitSTL();
394   void emitSTS();
395
396   void emitTEXs(int);
397   void emitTEX();
398   void emitTLD();
399   void emitTLD4();
400   void emitTMML();
401   void emitTXD();
402   void emitTXQ();
403
404   void emitSUHandle(const int);
405   void emitSUTarget();
406   void emitSUATOM();
407   void emitSULD();
408   void emitSUST();
409
410   void emitAL2P();
411   void emitBAR();
412   void emitCCTL();
413   void emitMEMBAR();
414   void emitPIXLD();
415   void emitPLOP3_LUT();
416   void emitVOTE();
417};
418
419};
420#endif
421