LLVM API Documentation

R600MCCodeEmitter.cpp
Go to the documentation of this file.
00001 //===- R600MCCodeEmitter.cpp - Code Emitter for R600->Cayman GPU families -===//
00002 //
00003 //                     The LLVM Compiler Infrastructure
00004 //
00005 // This file is distributed under the University of Illinois Open Source
00006 // License. See LICENSE.TXT for details.
00007 //
00008 //===----------------------------------------------------------------------===//
00009 //
00010 /// \file
00011 ///
00012 /// \brief The R600 code emitter produces machine code that can be executed
00013 /// directly on the GPU device.
00014 //
00015 //===----------------------------------------------------------------------===//
00016 
00017 #include "R600Defines.h"
00018 #include "MCTargetDesc/AMDGPUMCCodeEmitter.h"
00019 #include "MCTargetDesc/AMDGPUMCTargetDesc.h"
00020 #include "llvm/MC/MCCodeEmitter.h"
00021 #include "llvm/MC/MCContext.h"
00022 #include "llvm/MC/MCInst.h"
00023 #include "llvm/MC/MCInstrInfo.h"
00024 #include "llvm/MC/MCRegisterInfo.h"
00025 #include "llvm/MC/MCSubtargetInfo.h"
00026 #include "llvm/Support/raw_ostream.h"
00027 
00028 using namespace llvm;
00029 
00030 namespace {
00031 
00032 class R600MCCodeEmitter : public AMDGPUMCCodeEmitter {
00033   R600MCCodeEmitter(const R600MCCodeEmitter &) LLVM_DELETED_FUNCTION;
00034   void operator=(const R600MCCodeEmitter &) LLVM_DELETED_FUNCTION;
00035   const MCInstrInfo &MCII;
00036   const MCRegisterInfo &MRI;
00037 
00038 public:
00039 
00040   R600MCCodeEmitter(const MCInstrInfo &mcii, const MCRegisterInfo &mri)
00041     : MCII(mcii), MRI(mri) { }
00042 
00043   /// \brief Encode the instruction and write it to the OS.
00044   void EncodeInstruction(const MCInst &MI, raw_ostream &OS,
00045                          SmallVectorImpl<MCFixup> &Fixups,
00046                          const MCSubtargetInfo &STI) const override;
00047 
00048   /// \returns the encoding for an MCOperand.
00049   uint64_t getMachineOpValue(const MCInst &MI, const MCOperand &MO,
00050                              SmallVectorImpl<MCFixup> &Fixups,
00051                              const MCSubtargetInfo &STI) const override;
00052 private:
00053 
00054   void EmitByte(unsigned int byte, raw_ostream &OS) const;
00055 
00056   void Emit(uint32_t value, raw_ostream &OS) const;
00057   void Emit(uint64_t value, raw_ostream &OS) const;
00058 
00059   unsigned getHWRegChan(unsigned reg) const;
00060   unsigned getHWReg(unsigned regNo) const;
00061 
00062 };
00063 
00064 } // End anonymous namespace
00065 
00066 enum RegElement {
00067   ELEMENT_X = 0,
00068   ELEMENT_Y,
00069   ELEMENT_Z,
00070   ELEMENT_W
00071 };
00072 
00073 enum FCInstr {
00074   FC_IF_PREDICATE = 0,
00075   FC_ELSE,
00076   FC_ENDIF,
00077   FC_BGNLOOP,
00078   FC_ENDLOOP,
00079   FC_BREAK_PREDICATE,
00080   FC_CONTINUE
00081 };
00082 
00083 MCCodeEmitter *llvm::createR600MCCodeEmitter(const MCInstrInfo &MCII,
00084                                            const MCRegisterInfo &MRI,
00085                                            const MCSubtargetInfo &STI) {
00086   return new R600MCCodeEmitter(MCII, MRI);
00087 }
00088 
00089 void R600MCCodeEmitter::EncodeInstruction(const MCInst &MI, raw_ostream &OS,
00090                                        SmallVectorImpl<MCFixup> &Fixups,
00091                                        const MCSubtargetInfo &STI) const {
00092   const MCInstrDesc &Desc = MCII.get(MI.getOpcode());
00093   if (MI.getOpcode() == AMDGPU::RETURN ||
00094     MI.getOpcode() == AMDGPU::FETCH_CLAUSE ||
00095     MI.getOpcode() == AMDGPU::ALU_CLAUSE ||
00096     MI.getOpcode() == AMDGPU::BUNDLE ||
00097     MI.getOpcode() == AMDGPU::KILL) {
00098     return;
00099   } else if (IS_VTX(Desc)) {
00100     uint64_t InstWord01 = getBinaryCodeForInstr(MI, Fixups, STI);
00101     uint32_t InstWord2 = MI.getOperand(2).getImm(); // Offset
00102     if (!(STI.getFeatureBits() & AMDGPU::FeatureCaymanISA)) {
00103       InstWord2 |= 1 << 19; // Mega-Fetch bit
00104     }
00105 
00106     Emit(InstWord01, OS);
00107     Emit(InstWord2, OS);
00108     Emit((uint32_t) 0, OS);
00109   } else if (IS_TEX(Desc)) {
00110       int64_t Sampler = MI.getOperand(14).getImm();
00111 
00112       int64_t SrcSelect[4] = {
00113         MI.getOperand(2).getImm(),
00114         MI.getOperand(3).getImm(),
00115         MI.getOperand(4).getImm(),
00116         MI.getOperand(5).getImm()
00117       };
00118       int64_t Offsets[3] = {
00119         MI.getOperand(6).getImm() & 0x1F,
00120         MI.getOperand(7).getImm() & 0x1F,
00121         MI.getOperand(8).getImm() & 0x1F
00122       };
00123 
00124       uint64_t Word01 = getBinaryCodeForInstr(MI, Fixups, STI);
00125       uint32_t Word2 = Sampler << 15 | SrcSelect[ELEMENT_X] << 20 |
00126           SrcSelect[ELEMENT_Y] << 23 | SrcSelect[ELEMENT_Z] << 26 |
00127           SrcSelect[ELEMENT_W] << 29 | Offsets[0] << 0 | Offsets[1] << 5 |
00128           Offsets[2] << 10;
00129 
00130       Emit(Word01, OS);
00131       Emit(Word2, OS);
00132       Emit((uint32_t) 0, OS);
00133   } else {
00134     uint64_t Inst = getBinaryCodeForInstr(MI, Fixups, STI);
00135     if ((STI.getFeatureBits() & AMDGPU::FeatureR600ALUInst) &&
00136        ((Desc.TSFlags & R600_InstFlag::OP1) ||
00137          Desc.TSFlags & R600_InstFlag::OP2)) {
00138       uint64_t ISAOpCode = Inst & (0x3FFULL << 39);
00139       Inst &= ~(0x3FFULL << 39);
00140       Inst |= ISAOpCode << 1;
00141     }
00142     Emit(Inst, OS);
00143   }
00144 }
00145 
00146 void R600MCCodeEmitter::EmitByte(unsigned int Byte, raw_ostream &OS) const {
00147   OS.write((uint8_t) Byte & 0xff);
00148 }
00149 
00150 void R600MCCodeEmitter::Emit(uint32_t Value, raw_ostream &OS) const {
00151   for (unsigned i = 0; i < 4; i++) {
00152     OS.write((uint8_t) ((Value >> (8 * i)) & 0xff));
00153   }
00154 }
00155 
00156 void R600MCCodeEmitter::Emit(uint64_t Value, raw_ostream &OS) const {
00157   for (unsigned i = 0; i < 8; i++) {
00158     EmitByte((Value >> (8 * i)) & 0xff, OS);
00159   }
00160 }
00161 
00162 unsigned R600MCCodeEmitter::getHWRegChan(unsigned reg) const {
00163   return MRI.getEncodingValue(reg) >> HW_CHAN_SHIFT;
00164 }
00165 
00166 unsigned R600MCCodeEmitter::getHWReg(unsigned RegNo) const {
00167   return MRI.getEncodingValue(RegNo) & HW_REG_MASK;
00168 }
00169 
00170 uint64_t R600MCCodeEmitter::getMachineOpValue(const MCInst &MI,
00171                                               const MCOperand &MO,
00172                                         SmallVectorImpl<MCFixup> &Fixup,
00173                                         const MCSubtargetInfo &STI) const {
00174   if (MO.isReg()) {
00175     if (HAS_NATIVE_OPERANDS(MCII.get(MI.getOpcode()).TSFlags))
00176       return MRI.getEncodingValue(MO.getReg());
00177     return getHWReg(MO.getReg());
00178   }
00179 
00180   assert(MO.isImm());
00181   return MO.getImm();
00182 }
00183 
00184 #include "AMDGPUGenMCCodeEmitter.inc"