LCOV - code coverage report
Current view: top level - lib/Target/AMDGPU/MCTargetDesc - R600MCCodeEmitter.cpp (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 59 59 100.0 %
Date: 2017-09-14 15:23:50 Functions: 4 5 80.0 %
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             : /// \brief 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/AMDGPUMCCodeEmitter.h"
      19             : #include "MCTargetDesc/AMDGPUMCTargetDesc.h"
      20             : #include "R600Defines.h"
      21             : #include "llvm/MC/MCCodeEmitter.h"
      22             : #include "llvm/MC/MCContext.h"
      23             : #include "llvm/MC/MCFixup.h"
      24             : #include "llvm/MC/MCInst.h"
      25             : #include "llvm/MC/MCInstrDesc.h"
      26             : #include "llvm/MC/MCInstrInfo.h"
      27             : #include "llvm/MC/MCRegisterInfo.h"
      28             : #include "llvm/MC/MCSubtargetInfo.h"
      29             : #include "llvm/Support/Endian.h"
      30             : #include "llvm/Support/EndianStream.h"
      31             : #include "llvm/Support/raw_ostream.h"
      32             : #include <cassert>
      33             : #include <cstdint>
      34             : 
      35             : using namespace llvm;
      36             : 
      37             : namespace {
      38             : 
      39          28 : class R600MCCodeEmitter : public AMDGPUMCCodeEmitter {
      40             :   const MCRegisterInfo &MRI;
      41             : 
      42             : public:
      43             :   R600MCCodeEmitter(const MCInstrInfo &mcii, const MCRegisterInfo &mri)
      44          28 :     : AMDGPUMCCodeEmitter(mcii), MRI(mri) {}
      45             :   R600MCCodeEmitter(const R600MCCodeEmitter &) = delete;
      46             :   R600MCCodeEmitter &operator=(const R600MCCodeEmitter &) = delete;
      47             : 
      48             :   /// \brief 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 override;
      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 override;
      57             : 
      58             : private:
      59             :   void Emit(uint32_t value, raw_ostream &OS) const;
      60             :   void Emit(uint64_t value, raw_ostream &OS) const;
      61             : 
      62             :   unsigned getHWReg(unsigned regNo) const;
      63             : };
      64             : 
      65             : } // end anonymous namespace
      66             : 
      67             : enum RegElement {
      68             :   ELEMENT_X = 0,
      69             :   ELEMENT_Y,
      70             :   ELEMENT_Z,
      71             :   ELEMENT_W
      72             : };
      73             : 
      74             : enum FCInstr {
      75             :   FC_IF_PREDICATE = 0,
      76             :   FC_ELSE,
      77             :   FC_ENDIF,
      78             :   FC_BGNLOOP,
      79             :   FC_ENDLOOP,
      80             :   FC_BREAK_PREDICATE,
      81             :   FC_CONTINUE
      82             : };
      83             : 
      84          14 : MCCodeEmitter *llvm::createR600MCCodeEmitter(const MCInstrInfo &MCII,
      85             :                                              const MCRegisterInfo &MRI,
      86             :                                              MCContext &Ctx) {
      87          28 :   return new R600MCCodeEmitter(MCII, MRI);
      88             : }
      89             : 
      90         281 : void R600MCCodeEmitter::encodeInstruction(const MCInst &MI, raw_ostream &OS,
      91             :                                        SmallVectorImpl<MCFixup> &Fixups,
      92             :                                        const MCSubtargetInfo &STI) const {
      93         562 :   verifyInstructionPredicates(MI,
      94             :                               computeAvailableFeatures(STI.getFeatureBits()));
      95             : 
      96         562 :   const MCInstrDesc &Desc = MCII.get(MI.getOpcode());
      97         562 :   if (MI.getOpcode() == AMDGPU::RETURN ||
      98         547 :     MI.getOpcode() == AMDGPU::FETCH_CLAUSE ||
      99         500 :     MI.getOpcode() == AMDGPU::ALU_CLAUSE ||
     100         749 :     MI.getOpcode() == AMDGPU::BUNDLE ||
     101         234 :     MI.getOpcode() == AMDGPU::KILL) {
     102             :     return;
     103         234 :   } else if (IS_VTX(Desc)) {
     104          14 :     uint64_t InstWord01 = getBinaryCodeForInstr(MI, Fixups, STI);
     105          14 :     uint32_t InstWord2 = MI.getOperand(2).getImm(); // Offset
     106          28 :     if (!(STI.getFeatureBits()[AMDGPU::FeatureCaymanISA])) {
     107          10 :       InstWord2 |= 1 << 19; // Mega-Fetch bit
     108             :     }
     109             : 
     110          28 :     Emit(InstWord01, OS);
     111          28 :     Emit(InstWord2, OS);
     112          14 :     Emit((uint32_t) 0, OS);
     113         220 :   } else if (IS_TEX(Desc)) {
     114          10 :       int64_t Sampler = MI.getOperand(14).getImm();
     115             : 
     116             :       int64_t SrcSelect[4] = {
     117          10 :         MI.getOperand(2).getImm(),
     118          10 :         MI.getOperand(3).getImm(),
     119          10 :         MI.getOperand(4).getImm(),
     120          10 :         MI.getOperand(5).getImm()
     121          40 :       };
     122             :       int64_t Offsets[3] = {
     123          10 :         MI.getOperand(6).getImm() & 0x1F,
     124          10 :         MI.getOperand(7).getImm() & 0x1F,
     125          10 :         MI.getOperand(8).getImm() & 0x1F
     126          30 :       };
     127             : 
     128          10 :       uint64_t Word01 = getBinaryCodeForInstr(MI, Fixups, STI);
     129          30 :       uint32_t Word2 = Sampler << 15 | SrcSelect[ELEMENT_X] << 20 |
     130          30 :           SrcSelect[ELEMENT_Y] << 23 | SrcSelect[ELEMENT_Z] << 26 |
     131          30 :           SrcSelect[ELEMENT_W] << 29 | Offsets[0] << 0 | Offsets[1] << 5 |
     132          10 :           Offsets[2] << 10;
     133             : 
     134          20 :       Emit(Word01, OS);
     135          20 :       Emit(Word2, OS);
     136          20 :       Emit((uint32_t) 0, OS);
     137             :   } else {
     138         210 :     uint64_t Inst = getBinaryCodeForInstr(MI, Fixups, STI);
     139         425 :     if ((STI.getFeatureBits()[AMDGPU::FeatureR600ALUInst]) &&
     140           5 :        ((Desc.TSFlags & R600_InstFlag::OP1) ||
     141             :          Desc.TSFlags & R600_InstFlag::OP2)) {
     142           1 :       uint64_t ISAOpCode = Inst & (0x3FFULL << 39);
     143           1 :       Inst &= ~(0x3FFULL << 39);
     144           1 :       Inst |= ISAOpCode << 1;
     145             :     }
     146         210 :     Emit(Inst, OS);
     147             :   }
     148             : }
     149             : 
     150             : void R600MCCodeEmitter::Emit(uint32_t Value, raw_ostream &OS) const {
     151          96 :   support::endian::Writer<support::little>(OS).write(Value);
     152             : }
     153             : 
     154             : void R600MCCodeEmitter::Emit(uint64_t Value, raw_ostream &OS) const {
     155         468 :   support::endian::Writer<support::little>(OS).write(Value);
     156             : }
     157             : 
     158             : unsigned R600MCCodeEmitter::getHWReg(unsigned RegNo) const {
     159         162 :   return MRI.getEncodingValue(RegNo) & HW_REG_MASK;
     160             : }
     161             : 
     162        1790 : uint64_t R600MCCodeEmitter::getMachineOpValue(const MCInst &MI,
     163             :                                               const MCOperand &MO,
     164             :                                         SmallVectorImpl<MCFixup> &Fixups,
     165             :                                         const MCSubtargetInfo &STI) const {
     166        1790 :   if (MO.isReg()) {
     167         718 :     if (HAS_NATIVE_OPERANDS(MCII.get(MI.getOpcode()).TSFlags))
     168         556 :       return MRI.getEncodingValue(MO.getReg());
     169         162 :     return getHWReg(MO.getReg());
     170             :   }
     171             : 
     172        1431 :   if (MO.isExpr()) {
     173             :     // We put rodata at the end of code section, then map the entire
     174             :     // code secetion as vtx buf. Thus the section relative address is the
     175             :     // correct one.
     176             :     // Each R600 literal instruction has two operands
     177             :     // We can't easily get the order of the current one, so compare against
     178             :     // the first one and adjust offset.
     179           5 :     const unsigned offset = (&MO == &MI.getOperand(0)) ? 0 : 4;
     180          10 :     Fixups.push_back(MCFixup::create(offset, MO.getExpr(), FK_SecRel_4, MI.getLoc()));
     181           5 :     return 0;
     182             :   }
     183             : 
     184             :   assert(MO.isImm());
     185        1426 :   return MO.getImm();
     186             : }
     187             : 
     188             : #define ENABLE_INSTR_PREDICATE_VERIFIER
     189             : #include "AMDGPUGenMCCodeEmitter.inc"

Generated by: LCOV version 1.13