Revert "include/llvm: Add R600 Intrinsics v6"
[oota-llvm.git] / lib / Target / AMDGPU / R600CodeEmitter.cpp
1 //===-- R600CodeEmitter.cpp - Code Emitter for R600->Cayman GPU families --===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This code emitters outputs bytecode that is understood by the r600g driver
11 // in the Mesa [1] project.  The bytecode is very similar to the hardware's ISA,
12 // except that the size of the instruction fields are rounded up to the
13 // nearest byte.
14 //
15 // [1] http://www.mesa3d.org/
16 //
17 //===----------------------------------------------------------------------===//
18
19 #include "AMDGPU.h"
20 #include "AMDGPUUtil.h"
21 #include "AMDILCodeEmitter.h"
22 #include "AMDILInstrInfo.h"
23 #include "AMDILUtilityFunctions.h"
24 #include "R600InstrInfo.h"
25 #include "R600RegisterInfo.h"
26 #include "llvm/CodeGen/MachineFunctionPass.h"
27 #include "llvm/CodeGen/MachineInstrBuilder.h"
28 #include "llvm/CodeGen/MachineRegisterInfo.h"
29 #include "llvm/Support/DataTypes.h"
30 #include "llvm/Support/FormattedStream.h"
31 #include "llvm/Target/TargetMachine.h"
32
33 #include <stdio.h>
34
35 #define SRC_BYTE_COUNT 11
36 #define DST_BYTE_COUNT 5
37
38 using namespace llvm;
39
40 namespace {
41
42 class R600CodeEmitter : public MachineFunctionPass, public AMDILCodeEmitter {
43
44 private:
45
46   static char ID;
47   formatted_raw_ostream &_OS;
48   const TargetMachine * TM;
49   const MachineRegisterInfo * MRI;
50   const R600RegisterInfo * TRI;
51
52   bool IsCube;
53   bool IsReduction;
54   bool IsVector;
55   unsigned currentElement;
56   bool IsLast;
57
58 public:
59
60   R600CodeEmitter(formatted_raw_ostream &OS) : MachineFunctionPass(ID),
61       _OS(OS), TM(NULL), IsCube(false), IsReduction(false), IsVector(false),
62       IsLast(true) { }
63
64   const char *getPassName() const { return "AMDGPU Machine Code Emitter"; }
65
66   bool runOnMachineFunction(MachineFunction &MF);
67   virtual uint64_t getMachineOpValue(const MachineInstr &MI,
68                                      const MachineOperand &MO) const;
69
70 private:
71
72   void EmitALUInstr(MachineInstr  &MI);
73   void EmitSrc(const MachineOperand & MO, int chan_override  = -1);
74   void EmitDst(const MachineOperand & MO);
75   void EmitALU(MachineInstr &MI, unsigned numSrc);
76   void EmitTexInstr(MachineInstr &MI);
77   void EmitFCInstr(MachineInstr &MI);
78
79   void EmitNullBytes(unsigned int byteCount);
80
81   void EmitByte(unsigned int byte);
82
83   void EmitTwoBytes(uint32_t bytes);
84
85   void Emit(uint32_t value);
86   void Emit(uint64_t value);
87
88   unsigned getHWReg(unsigned regNo) const;
89
90 };
91
92 } // End anonymous namespace
93
94 enum RegElement {
95   ELEMENT_X = 0,
96   ELEMENT_Y,
97   ELEMENT_Z,
98   ELEMENT_W
99 };
100
101 enum InstrTypes {
102   INSTR_ALU = 0,
103   INSTR_TEX,
104   INSTR_FC,
105   INSTR_NATIVE,
106   INSTR_VTX
107 };
108
109 enum FCInstr {
110   FC_IF = 0,
111   FC_ELSE,
112   FC_ENDIF,
113   FC_BGNLOOP,
114   FC_ENDLOOP,
115   FC_BREAK,
116   FC_BREAK_NZ_INT,
117   FC_CONTINUE,
118   FC_BREAK_Z_INT
119 };
120
121 enum TextureTypes {
122   TEXTURE_1D = 1,
123   TEXTURE_2D,
124   TEXTURE_3D,
125   TEXTURE_CUBE,
126   TEXTURE_RECT,
127   TEXTURE_SHADOW1D,
128   TEXTURE_SHADOW2D,
129   TEXTURE_SHADOWRECT,
130   TEXTURE_1D_ARRAY,
131   TEXTURE_2D_ARRAY,
132   TEXTURE_SHADOW1D_ARRAY,
133   TEXTURE_SHADOW2D_ARRAY
134 };
135
136 char R600CodeEmitter::ID = 0;
137
138 FunctionPass *llvm::createR600CodeEmitterPass(formatted_raw_ostream &OS) {
139   return new R600CodeEmitter(OS);
140 }
141
142 bool R600CodeEmitter::runOnMachineFunction(MachineFunction &MF) {
143
144   TM = &MF.getTarget();
145   MRI = &MF.getRegInfo();
146   TRI = static_cast<const R600RegisterInfo *>(TM->getRegisterInfo());
147   const R600InstrInfo * TII = static_cast<const R600InstrInfo *>(TM->getInstrInfo());
148   const AMDILSubtarget &STM = TM->getSubtarget<AMDILSubtarget>();
149   std::string gpu = STM.getDeviceName();
150
151   if (STM.dumpCode()) {
152     MF.dump();
153   }
154
155   for (MachineFunction::iterator BB = MF.begin(), BB_E = MF.end();
156                                                   BB != BB_E; ++BB) {
157      MachineBasicBlock &MBB = *BB;
158      for (MachineBasicBlock::iterator I = MBB.begin(), E = MBB.end();
159                                                        I != E; ++I) {
160           MachineInstr &MI = *I;
161           IsReduction = AMDGPU::isReductionOp(MI.getOpcode());
162           IsVector = TII->isVector(MI);
163           IsCube = AMDGPU::isCubeOp(MI.getOpcode());
164           if (MI.getNumOperands() > 1 && MI.getOperand(0).isReg() && MI.getOperand(0).isDead()) {
165             continue;
166           }
167           if (AMDGPU::isTexOp(MI.getOpcode())) {
168             EmitTexInstr(MI);
169           } else if (AMDGPU::isFCOp(MI.getOpcode())){
170             EmitFCInstr(MI);
171           } else if (IsReduction || IsVector || IsCube) {
172             IsLast = false;
173             // XXX: On Cayman, some (all?) of the vector instructions only need
174             // to fill the first three slots.
175             for (currentElement = 0; currentElement < 4; currentElement++) {
176               IsLast = (currentElement == 3);
177               EmitALUInstr(MI);
178             }
179             IsReduction = false;
180             IsVector = false;
181             IsCube = false;
182           } else if (MI.getOpcode() == AMDGPU::RETURN ||
183                      MI.getOpcode() == AMDGPU::BUNDLE ||
184                      MI.getOpcode() == AMDGPU::KILL) {
185             continue;
186           } else {
187             switch(MI.getOpcode()) {
188             case AMDGPU::RAT_WRITE_CACHELESS_eg:
189               {
190                   uint64_t inst = getBinaryCodeForInstr(MI);
191                 // Set End Of Program bit
192                 // XXX: Need better check of end of program.  EOP should be
193                 // encoded in one of the operands of the MI, and it should be
194                 // set in a prior pass.
195                 MachineBasicBlock::iterator NextI = llvm::next(I);
196                 MachineInstr &NextMI = *NextI;
197                 if (NextMI.getOpcode() == AMDGPU::RETURN) {
198                   inst |= (((uint64_t)1) << 53);
199                 }
200                 EmitByte(INSTR_NATIVE);
201                 Emit(inst);
202                 break;
203               }
204             case AMDGPU::VTX_READ_PARAM_i32_eg:
205             case AMDGPU::VTX_READ_PARAM_f32_eg:
206             case AMDGPU::VTX_READ_GLOBAL_i32_eg:
207             case AMDGPU::VTX_READ_GLOBAL_f32_eg:
208             case AMDGPU::VTX_READ_GLOBAL_v4i32_eg:
209             case AMDGPU::VTX_READ_GLOBAL_v4f32_eg:
210               {
211                 uint64_t InstWord01 = getBinaryCodeForInstr(MI);
212                 uint32_t InstWord2 = MI.getOperand(2).getImm(); // Offset
213
214                 EmitByte(INSTR_VTX);
215                 Emit(InstWord01);
216                 Emit(InstWord2);
217                 break;
218               }
219
220             default:
221               EmitALUInstr(MI);
222               break;
223           }
224         }
225     }
226   }
227   return false;
228 }
229
230 void R600CodeEmitter::EmitALUInstr(MachineInstr &MI)
231 {
232
233   unsigned numOperands = MI.getNumExplicitOperands();
234
235    // Some instructions are just place holder instructions that represent
236    // operations that the GPU does automatically.  They should be ignored.
237   if (AMDGPU::isPlaceHolderOpcode(MI.getOpcode())) {
238     return;
239   }
240
241   // XXX Check if instruction writes a result
242   if (numOperands < 1) {
243     return;
244   }
245   const MachineOperand dstOp = MI.getOperand(0);
246
247   // Emit instruction type
248   EmitByte(0);
249
250   if (IsCube) {
251     static const int cube_src_swz[] = {2, 2, 0, 1};
252     EmitSrc(MI.getOperand(1), cube_src_swz[currentElement]);
253     EmitSrc(MI.getOperand(1), cube_src_swz[3-currentElement]);
254     EmitNullBytes(SRC_BYTE_COUNT);
255   } else {
256     unsigned int opIndex;
257     for (opIndex = 1; opIndex < numOperands; opIndex++) {
258       // Literal constants are always stored as the last operand.
259       if (MI.getOperand(opIndex).isImm() || MI.getOperand(opIndex).isFPImm()) {
260         break;
261       }
262       EmitSrc(MI.getOperand(opIndex));
263     }
264
265     // Emit zeros for unused sources
266     for ( ; opIndex < 4; opIndex++) {
267       EmitNullBytes(SRC_BYTE_COUNT);
268     }
269   }
270
271   EmitDst(dstOp);
272
273   EmitALU(MI, numOperands - 1);
274 }
275
276 void R600CodeEmitter::EmitSrc(const MachineOperand & MO, int chan_override)
277 {
278   uint32_t value = 0;
279   // Emit the source select (2 bytes).  For GPRs, this is the register index.
280   // For other potential instruction operands, (e.g. constant registers) the
281   // value of the source select is defined in the r600isa docs.
282   if (MO.isReg()) {
283     unsigned reg = MO.getReg();
284     EmitTwoBytes(getHWReg(reg));
285     if (reg == AMDGPU::ALU_LITERAL_X) {
286       const MachineInstr * parent = MO.getParent();
287       unsigned immOpIndex = parent->getNumExplicitOperands() - 1;
288       MachineOperand immOp = parent->getOperand(immOpIndex);
289       if (immOp.isFPImm()) {
290         value = immOp.getFPImm()->getValueAPF().bitcastToAPInt().getZExtValue();
291       } else {
292         assert(immOp.isImm());
293         value = immOp.getImm();
294       }
295     }
296   } else {
297     // XXX: Handle other operand types.
298     EmitTwoBytes(0);
299   }
300
301   // Emit the source channel (1 byte)
302   if (chan_override != -1) {
303     EmitByte(chan_override);
304   } else if (IsReduction) {
305     EmitByte(currentElement);
306   } else if (MO.isReg()) {
307     EmitByte(TRI->getHWRegChan(MO.getReg()));
308   } else {
309     EmitByte(0);
310   }
311
312   // XXX: Emit isNegated (1 byte)
313   if ((!(MO.getTargetFlags() & MO_FLAG_ABS))
314       && (MO.getTargetFlags() & MO_FLAG_NEG ||
315      (MO.isReg() &&
316       (MO.getReg() == AMDGPU::NEG_ONE || MO.getReg() == AMDGPU::NEG_HALF)))){
317     EmitByte(1);
318   } else {
319     EmitByte(0);
320   }
321
322   // Emit isAbsolute (1 byte)
323   if (MO.getTargetFlags() & MO_FLAG_ABS) {
324     EmitByte(1);
325   } else {
326     EmitByte(0);
327   }
328
329   // XXX: Emit relative addressing mode (1 byte)
330   EmitByte(0);
331
332   // Emit kc_bank, This will be adjusted later by r600_asm
333   EmitByte(0);
334
335   // Emit the literal value, if applicable (4 bytes).
336   Emit(value);
337
338 }
339
340 void R600CodeEmitter::EmitDst(const MachineOperand & MO)
341 {
342   if (MO.isReg()) {
343     // Emit the destination register index (1 byte)
344     EmitByte(getHWReg(MO.getReg()));
345
346     // Emit the element of the destination register (1 byte)
347     if (IsReduction || IsCube || IsVector) {
348       EmitByte(currentElement);
349     } else {
350       EmitByte(TRI->getHWRegChan(MO.getReg()));
351     }
352
353     // Emit isClamped (1 byte)
354     if (MO.getTargetFlags() & MO_FLAG_CLAMP) {
355       EmitByte(1);
356     } else {
357       EmitByte(0);
358     }
359
360     // Emit writemask (1 byte).
361     if (((IsReduction || IsVector) &&
362           currentElement != TRI->getHWRegChan(MO.getReg()))
363        || MO.getTargetFlags() & MO_FLAG_MASK) {
364       EmitByte(0);
365     } else {
366       EmitByte(1);
367     }
368
369     // XXX: Emit relative addressing mode
370     EmitByte(0);
371   } else {
372     // XXX: Handle other operand types.  Are there any for destination regs?
373     EmitNullBytes(DST_BYTE_COUNT);
374   }
375 }
376
377 void R600CodeEmitter::EmitALU(MachineInstr &MI, unsigned numSrc)
378 {
379   // Emit the instruction (2 bytes)
380   EmitTwoBytes(getBinaryCodeForInstr(MI));
381
382   // Emit IsLast (for this instruction group) (1 byte)
383   if (IsLast) {
384     EmitByte(1);
385   } else {
386     EmitByte(0);
387   }
388   // Emit isOp3 (1 byte)
389   if (numSrc == 3) {
390     EmitByte(1);
391   } else {
392     EmitByte(0);
393   }
394
395   // XXX: Emit predicate (1 byte)
396   EmitByte(0);
397
398   // XXX: Emit bank swizzle. (1 byte)  Do we need this?  It looks like
399   // r600_asm.c sets it.
400   EmitByte(0);
401
402   // XXX: Emit bank_swizzle_force (1 byte) Not sure what this is for.
403   EmitByte(0);
404
405   // XXX: Emit OMOD (1 byte) Not implemented.
406   EmitByte(0);
407
408   // XXX: Emit index_mode.  I think this is for indirect addressing, so we
409   // don't need to worry about it.
410   EmitByte(0);
411 }
412
413 void R600CodeEmitter::EmitTexInstr(MachineInstr &MI)
414 {
415
416   unsigned opcode = MI.getOpcode();
417   bool hasOffsets = (opcode == AMDGPU::TEX_LD);
418   unsigned op_offset = hasOffsets ? 3 : 0;
419   int64_t sampler = MI.getOperand(op_offset+2).getImm();
420   int64_t textureType = MI.getOperand(op_offset+3).getImm();
421   unsigned srcSelect[4] = {0, 1, 2, 3};
422
423   // Emit instruction type
424   EmitByte(1);
425
426   // Emit instruction
427   EmitByte(getBinaryCodeForInstr(MI));
428
429   // XXX: Emit resource id r600_shader.c uses sampler + 1.  Why?
430   EmitByte(sampler + 1 + 1);
431
432   // Emit source register
433   EmitByte(getHWReg(MI.getOperand(1).getReg()));
434
435   // XXX: Emit src isRelativeAddress
436   EmitByte(0);
437
438   // Emit destination register
439   EmitByte(getHWReg(MI.getOperand(0).getReg()));
440
441   // XXX: Emit dst isRealtiveAddress
442   EmitByte(0);
443
444   // XXX: Emit dst select
445   EmitByte(0); // X
446   EmitByte(1); // Y
447   EmitByte(2); // Z
448   EmitByte(3); // W
449
450   // XXX: Emit lod bias
451   EmitByte(0);
452
453   // XXX: Emit coord types
454   unsigned coordType[4] = {1, 1, 1, 1};
455
456   if (textureType == TEXTURE_RECT
457       || textureType == TEXTURE_SHADOWRECT) {
458     coordType[ELEMENT_X] = 0;
459     coordType[ELEMENT_Y] = 0;
460   }
461
462   if (textureType == TEXTURE_1D_ARRAY
463       || textureType == TEXTURE_SHADOW1D_ARRAY) {
464     if (opcode == AMDGPU::TEX_SAMPLE_C_L || opcode == AMDGPU::TEX_SAMPLE_C_LB) {
465       coordType[ELEMENT_Y] = 0;
466     } else {
467       coordType[ELEMENT_Z] = 0;
468       srcSelect[ELEMENT_Z] = ELEMENT_Y;
469     }
470   } else if (textureType == TEXTURE_2D_ARRAY
471              || textureType == TEXTURE_SHADOW2D_ARRAY) {
472     coordType[ELEMENT_Z] = 0;
473   }
474
475   for (unsigned i = 0; i < 4; i++) {
476     EmitByte(coordType[i]);
477   }
478
479   // XXX: Emit offsets
480   if (hasOffsets)
481           for (unsigned i = 2; i < 5; i++)
482                   EmitByte(MI.getOperand(i).getImm()<<1);
483   else
484           EmitNullBytes(3);
485
486   // Emit sampler id
487   EmitByte(sampler);
488
489   // XXX:Emit source select
490   if ((textureType == TEXTURE_SHADOW1D
491       || textureType == TEXTURE_SHADOW2D
492       || textureType == TEXTURE_SHADOWRECT
493       || textureType == TEXTURE_SHADOW1D_ARRAY)
494       && opcode != AMDGPU::TEX_SAMPLE_C_L
495       && opcode != AMDGPU::TEX_SAMPLE_C_LB) {
496     srcSelect[ELEMENT_W] = ELEMENT_Z;
497   }
498
499   for (unsigned i = 0; i < 4; i++) {
500     EmitByte(srcSelect[i]);
501   }
502 }
503
504 void R600CodeEmitter::EmitFCInstr(MachineInstr &MI)
505 {
506   // Emit instruction type
507   EmitByte(INSTR_FC);
508
509   // Emit SRC
510   unsigned numOperands = MI.getNumOperands();
511   if (numOperands > 0) {
512     assert(numOperands == 1);
513     EmitSrc(MI.getOperand(0));
514   } else {
515     EmitNullBytes(SRC_BYTE_COUNT);
516   }
517
518   // Emit FC Instruction
519   enum FCInstr instr;
520   switch (MI.getOpcode()) {
521   case AMDGPU::BREAK_LOGICALZ_f32:
522     instr = FC_BREAK;
523     break;
524   case AMDGPU::BREAK_LOGICALNZ_f32:
525   case AMDGPU::BREAK_LOGICALNZ_i32:
526     instr = FC_BREAK_NZ_INT;
527     break;
528   case AMDGPU::BREAK_LOGICALZ_i32:
529     instr = FC_BREAK_Z_INT;
530     break;
531   case AMDGPU::CONTINUE_LOGICALNZ_f32:
532   case AMDGPU::CONTINUE_LOGICALNZ_i32:
533     instr = FC_CONTINUE;
534     break;
535   case AMDGPU::IF_LOGICALNZ_f32:
536   case AMDGPU::IF_LOGICALNZ_i32:
537     instr = FC_IF;
538     break;
539   case AMDGPU::IF_LOGICALZ_f32:
540     abort();
541     break;
542   case AMDGPU::ELSE:
543     instr = FC_ELSE;
544     break;
545   case AMDGPU::ENDIF:
546     instr = FC_ENDIF;
547     break;
548   case AMDGPU::ENDLOOP:
549     instr = FC_ENDLOOP;
550     break;
551   case AMDGPU::WHILELOOP:
552     instr = FC_BGNLOOP;
553     break;
554   default:
555     abort();
556     break;
557   }
558   EmitByte(instr);
559 }
560
561 void R600CodeEmitter::EmitNullBytes(unsigned int byteCount)
562 {
563   for (unsigned int i = 0; i < byteCount; i++) {
564     EmitByte(0);
565   }
566 }
567
568 void R600CodeEmitter::EmitByte(unsigned int byte)
569 {
570   _OS.write((uint8_t) byte & 0xff);
571 }
572 void R600CodeEmitter::EmitTwoBytes(unsigned int bytes)
573 {
574   _OS.write((uint8_t) (bytes & 0xff));
575   _OS.write((uint8_t) ((bytes >> 8) & 0xff));
576 }
577
578 void R600CodeEmitter::Emit(uint32_t value)
579 {
580   for (unsigned i = 0; i < 4; i++) {
581     _OS.write((uint8_t) ((value >> (8 * i)) & 0xff));
582   }
583 }
584
585 void R600CodeEmitter::Emit(uint64_t value)
586 {
587   for (unsigned i = 0; i < 8; i++) {
588     EmitByte((value >> (8 * i)) & 0xff);
589   }
590 }
591
592 unsigned R600CodeEmitter::getHWReg(unsigned regNo) const
593 {
594   unsigned HWReg;
595
596   HWReg = TRI->getEncodingValue(regNo);
597   if (AMDGPU::R600_CReg32RegClass.contains(regNo)) {
598     HWReg += 512;
599   }
600   return HWReg;
601 }
602
603 uint64_t R600CodeEmitter::getMachineOpValue(const MachineInstr &MI,
604                                             const MachineOperand &MO) const
605 {
606   if (MO.isReg()) {
607     return getHWReg(MO.getReg());
608   } else {
609     return MO.getImm();
610   }
611 }
612
613 #include "AMDGPUGenCodeEmitter.inc"
614