LCOV - code coverage report
Current view: top level - lib/Target/AMDGPU/MCTargetDesc - R600MCCodeEmitter.cpp (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 35 51 68.6 %
Date: 2018-10-20 13:21:21 Functions: 2 6 33.3 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : //===- R600MCCodeEmitter.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             : /// \file
      11             : ///
      12             : /// The R600 code emitter produces machine code that can be executed
      13             : /// directly on the GPU device.
      14             : //
      15             : //===----------------------------------------------------------------------===//
      16             : 
      17             : #include "MCTargetDesc/AMDGPUFixupKinds.h"
      18             : #include "MCTargetDesc/AMDGPUMCTargetDesc.h"
      19             : #include "R600Defines.h"
      20             : #include "llvm/MC/MCCodeEmitter.h"
      21             : #include "llvm/MC/MCContext.h"
      22             : #include "llvm/MC/MCFixup.h"
      23             : #include "llvm/MC/MCInst.h"
      24             : #include "llvm/MC/MCInstrDesc.h"
      25             : #include "llvm/MC/MCInstrInfo.h"
      26             : #include "llvm/MC/MCRegisterInfo.h"
      27             : #include "llvm/MC/MCSubtargetInfo.h"
      28             : #include "llvm/Support/Endian.h"
      29             : #include "llvm/Support/EndianStream.h"
      30             : #include "llvm/Support/raw_ostream.h"
      31             : #include <cassert>
      32             : #include <cstdint>
      33             : 
      34             : using namespace llvm;
      35             : 
      36             : namespace {
      37             : 
      38             : class R600MCCodeEmitter : public MCCodeEmitter {
      39             :   const MCRegisterInfo &MRI;
      40             :   const MCInstrInfo &MCII;
      41             : 
      42             : public:
      43             :   R600MCCodeEmitter(const MCInstrInfo &mcii, const MCRegisterInfo &mri)
      44          31 :     : MRI(mri), MCII(mcii) {}
      45             :   R600MCCodeEmitter(const R600MCCodeEmitter &) = delete;
      46             :   R600MCCodeEmitter &operator=(const R600MCCodeEmitter &) = delete;
      47             : 
      48             :   /// Encode the instruction and write it to the OS.
      49             :   void encodeInstruction(const MCInst &MI, raw_ostream &OS,
      50             :                          SmallVectorImpl<MCFixup> &Fixups,
      51             :                          const MCSubtargetInfo &STI) const;
      52             : 
      53             :   /// \returns the encoding for an MCOperand.
      54             :   uint64_t getMachineOpValue(const MCInst &MI, const MCOperand &MO,
      55             :                              SmallVectorImpl<MCFixup> &Fixups,
      56             :                              const MCSubtargetInfo &STI) const;
      57             : 
      58             : private:
      59             : 
      60             :   void Emit(uint32_t value, raw_ostream &OS) const;
      61             :   void Emit(uint64_t value, raw_ostream &OS) const;
      62             : 
      63             :   unsigned getHWReg(unsigned regNo) const;
      64             : 
      65             :   uint64_t getBinaryCodeForInstr(const MCInst &MI,
      66             :                                  SmallVectorImpl<MCFixup> &Fixups,
      67             :                                  const MCSubtargetInfo &STI) const;
      68             :   uint64_t computeAvailableFeatures(const FeatureBitset &FB) const;
      69             :   void verifyInstructionPredicates(const MCInst &MI,
      70             :                                    uint64_t AvailableFeatures) const;
      71             : 
      72             : };
      73             : 
      74             : } // end anonymous namespace
      75             : 
      76             : enum RegElement {
      77             :   ELEMENT_X = 0,
      78             :   ELEMENT_Y,
      79             :   ELEMENT_Z,
      80             :   ELEMENT_W
      81             : };
      82             : 
      83             : enum FCInstr {
      84             :   FC_IF_PREDICATE = 0,
      85             :   FC_ELSE,
      86             :   FC_ENDIF,
      87             :   FC_BGNLOOP,
      88             :   FC_ENDLOOP,
      89             :   FC_BREAK_PREDICATE,
      90             :   FC_CONTINUE
      91             : };
      92             : 
      93          31 : MCCodeEmitter *llvm::createR600MCCodeEmitter(const MCInstrInfo &MCII,
      94             :                                              const MCRegisterInfo &MRI,
      95             :                                              MCContext &Ctx) {
      96          31 :   return new R600MCCodeEmitter(MCII, MRI);
      97             : }
      98             : 
      99         315 : void R600MCCodeEmitter::encodeInstruction(const MCInst &MI, raw_ostream &OS,
     100             :                                        SmallVectorImpl<MCFixup> &Fixups,
     101             :                                        const MCSubtargetInfo &STI) const {
     102             :   verifyInstructionPredicates(MI,
     103             :                               computeAvailableFeatures(STI.getFeatureBits()));
     104             : 
     105         315 :   const MCInstrDesc &Desc = MCII.get(MI.getOpcode());
     106         315 :   if (MI.getOpcode() == R600::RETURN ||
     107         300 :     MI.getOpcode() == R600::FETCH_CLAUSE ||
     108         268 :     MI.getOpcode() == R600::ALU_CLAUSE ||
     109         583 :     MI.getOpcode() == R600::BUNDLE ||
     110             :     MI.getOpcode() == R600::KILL) {
     111             :     return;
     112         268 :   } else if (IS_VTX(Desc)) {
     113          14 :     uint64_t InstWord01 = getBinaryCodeForInstr(MI, Fixups, STI);
     114          14 :     uint32_t InstWord2 = MI.getOperand(2).getImm(); // Offset
     115          14 :     if (!(STI.getFeatureBits()[R600::FeatureCaymanISA])) {
     116          10 :       InstWord2 |= 1 << 19; // Mega-Fetch bit
     117             :     }
     118             : 
     119             :     Emit(InstWord01, OS);
     120             :     Emit(InstWord2, OS);
     121             :     Emit((uint32_t) 0, OS);
     122         254 :   } else if (IS_TEX(Desc)) {
     123          10 :       int64_t Sampler = MI.getOperand(14).getImm();
     124             : 
     125             :       int64_t SrcSelect[4] = {
     126          10 :         MI.getOperand(2).getImm(),
     127          10 :         MI.getOperand(3).getImm(),
     128          10 :         MI.getOperand(4).getImm(),
     129          10 :         MI.getOperand(5).getImm()
     130             :       };
     131             :       int64_t Offsets[3] = {
     132          10 :         MI.getOperand(6).getImm() & 0x1F,
     133          10 :         MI.getOperand(7).getImm() & 0x1F,
     134          10 :         MI.getOperand(8).getImm() & 0x1F
     135             :       };
     136             : 
     137          10 :       uint64_t Word01 = getBinaryCodeForInstr(MI, Fixups, STI);
     138          30 :       uint32_t Word2 = Sampler << 15 | SrcSelect[ELEMENT_X] << 20 |
     139          30 :           SrcSelect[ELEMENT_Y] << 23 | SrcSelect[ELEMENT_Z] << 26 |
     140          30 :           SrcSelect[ELEMENT_W] << 29 | Offsets[0] << 0 | Offsets[1] << 5 |
     141          10 :           Offsets[2] << 10;
     142             : 
     143             :       Emit(Word01, OS);
     144             :       Emit(Word2, OS);
     145             :       Emit((uint32_t) 0, OS);
     146             :   } else {
     147         244 :     uint64_t Inst = getBinaryCodeForInstr(MI, Fixups, STI);
     148         244 :     if ((STI.getFeatureBits()[R600::FeatureR600ALUInst]) &&
     149          15 :        ((Desc.TSFlags & R600_InstFlag::OP1) ||
     150             :          Desc.TSFlags & R600_InstFlag::OP2)) {
     151             :       uint64_t ISAOpCode = Inst & (0x3FFULL << 39);
     152           1 :       Inst &= ~(0x3FFULL << 39);
     153           1 :       Inst |= ISAOpCode << 1;
     154             :     }
     155             :     Emit(Inst, OS);
     156             :   }
     157             : }
     158             : 
     159           0 : void R600MCCodeEmitter::Emit(uint32_t Value, raw_ostream &OS) const {
     160          24 :   support::endian::write(OS, Value, support::little);
     161           0 : }
     162             : 
     163           0 : void R600MCCodeEmitter::Emit(uint64_t Value, raw_ostream &OS) const {
     164         268 :   support::endian::write(OS, Value, support::little);
     165           0 : }
     166             : 
     167           0 : unsigned R600MCCodeEmitter::getHWReg(unsigned RegNo) const {
     168           0 :   return MRI.getEncodingValue(RegNo) & HW_REG_MASK;
     169             : }
     170             : 
     171           0 : uint64_t R600MCCodeEmitter::getMachineOpValue(const MCInst &MI,
     172             :                                               const MCOperand &MO,
     173             :                                         SmallVectorImpl<MCFixup> &Fixups,
     174             :                                         const MCSubtargetInfo &STI) const {
     175           0 :   if (MO.isReg()) {
     176           0 :     if (HAS_NATIVE_OPERANDS(MCII.get(MI.getOpcode()).TSFlags))
     177           0 :       return MRI.getEncodingValue(MO.getReg());
     178           0 :     return getHWReg(MO.getReg());
     179             :   }
     180             : 
     181           0 :   if (MO.isExpr()) {
     182             :     // We put rodata at the end of code section, then map the entire
     183             :     // code secetion as vtx buf. Thus the section relative address is the
     184             :     // correct one.
     185             :     // Each R600 literal instruction has two operands
     186             :     // We can't easily get the order of the current one, so compare against
     187             :     // the first one and adjust offset.
     188           0 :     const unsigned offset = (&MO == &MI.getOperand(0)) ? 0 : 4;
     189           0 :     Fixups.push_back(MCFixup::create(offset, MO.getExpr(), FK_SecRel_4, MI.getLoc()));
     190           0 :     return 0;
     191             :   }
     192             : 
     193             :   assert(MO.isImm());
     194           0 :   return MO.getImm();
     195             : }
     196             : 
     197             : #define ENABLE_INSTR_PREDICATE_VERIFIER
     198             : #include "R600GenMCCodeEmitter.inc"

Generated by: LCOV version 1.13