SIMCCodeEmitter.cpp revision 36b56886974eae4f9c5ebc96befd3e7bfe5de338
1//===-- SIMCCodeEmitter.cpp - SI Code Emitter -------------------------------===// 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/// \brief The SI code emitter produces machine code that can be executed 12/// directly on the GPU device. 13// 14//===----------------------------------------------------------------------===// 15 16#include "MCTargetDesc/AMDGPUMCTargetDesc.h" 17#include "MCTargetDesc/AMDGPUMCCodeEmitter.h" 18#include "llvm/MC/MCCodeEmitter.h" 19#include "llvm/MC/MCContext.h" 20#include "llvm/MC/MCFixup.h" 21#include "llvm/MC/MCInst.h" 22#include "llvm/MC/MCInstrInfo.h" 23#include "llvm/MC/MCRegisterInfo.h" 24#include "llvm/MC/MCSubtargetInfo.h" 25#include "llvm/Support/raw_ostream.h" 26 27using namespace llvm; 28 29namespace { 30 31/// \brief Helper type used in encoding 32typedef union { 33 int32_t I; 34 float F; 35} IntFloatUnion; 36 37class SIMCCodeEmitter : public AMDGPUMCCodeEmitter { 38 SIMCCodeEmitter(const SIMCCodeEmitter &) LLVM_DELETED_FUNCTION; 39 void operator=(const SIMCCodeEmitter &) LLVM_DELETED_FUNCTION; 40 const MCInstrInfo &MCII; 41 const MCRegisterInfo &MRI; 42 43 /// \brief Can this operand also contain immediate values? 44 bool isSrcOperand(const MCInstrDesc &Desc, unsigned OpNo) const; 45 46 /// \brief Encode an fp or int literal 47 uint32_t getLitEncoding(const MCOperand &MO) const; 48 49public: 50 SIMCCodeEmitter(const MCInstrInfo &mcii, const MCRegisterInfo &mri, 51 MCContext &ctx) 52 : MCII(mcii), MRI(mri) { } 53 54 ~SIMCCodeEmitter() { } 55 56 /// \brief Encode the instruction and write it to the OS. 57 virtual void EncodeInstruction(const MCInst &MI, raw_ostream &OS, 58 SmallVectorImpl<MCFixup> &Fixups, 59 const MCSubtargetInfo &STI) const; 60 61 /// \returns the encoding for an MCOperand. 62 virtual uint64_t getMachineOpValue(const MCInst &MI, const MCOperand &MO, 63 SmallVectorImpl<MCFixup> &Fixups, 64 const MCSubtargetInfo &STI) const; 65}; 66 67} // End anonymous namespace 68 69MCCodeEmitter *llvm::createSIMCCodeEmitter(const MCInstrInfo &MCII, 70 const MCRegisterInfo &MRI, 71 const MCSubtargetInfo &STI, 72 MCContext &Ctx) { 73 return new SIMCCodeEmitter(MCII, MRI, Ctx); 74} 75 76bool SIMCCodeEmitter::isSrcOperand(const MCInstrDesc &Desc, 77 unsigned OpNo) const { 78 79 unsigned RegClass = Desc.OpInfo[OpNo].RegClass; 80 return (AMDGPU::SSrc_32RegClassID == RegClass) || 81 (AMDGPU::SSrc_64RegClassID == RegClass) || 82 (AMDGPU::VSrc_32RegClassID == RegClass) || 83 (AMDGPU::VSrc_64RegClassID == RegClass); 84} 85 86uint32_t SIMCCodeEmitter::getLitEncoding(const MCOperand &MO) const { 87 88 IntFloatUnion Imm; 89 if (MO.isImm()) 90 Imm.I = MO.getImm(); 91 else if (MO.isFPImm()) 92 Imm.F = MO.getFPImm(); 93 else 94 return ~0; 95 96 if (Imm.I >= 0 && Imm.I <= 64) 97 return 128 + Imm.I; 98 99 if (Imm.I >= -16 && Imm.I <= -1) 100 return 192 + abs(Imm.I); 101 102 if (Imm.F == 0.5f) 103 return 240; 104 105 if (Imm.F == -0.5f) 106 return 241; 107 108 if (Imm.F == 1.0f) 109 return 242; 110 111 if (Imm.F == -1.0f) 112 return 243; 113 114 if (Imm.F == 2.0f) 115 return 244; 116 117 if (Imm.F == -2.0f) 118 return 245; 119 120 if (Imm.F == 4.0f) 121 return 246; 122 123 if (Imm.F == -4.0f) 124 return 247; 125 126 return 255; 127} 128 129void SIMCCodeEmitter::EncodeInstruction(const MCInst &MI, raw_ostream &OS, 130 SmallVectorImpl<MCFixup> &Fixups, 131 const MCSubtargetInfo &STI) const { 132 133 uint64_t Encoding = getBinaryCodeForInstr(MI, Fixups, STI); 134 const MCInstrDesc &Desc = MCII.get(MI.getOpcode()); 135 unsigned bytes = Desc.getSize(); 136 137 for (unsigned i = 0; i < bytes; i++) { 138 OS.write((uint8_t) ((Encoding >> (8 * i)) & 0xff)); 139 } 140 141 if (bytes > 4) 142 return; 143 144 // Check for additional literals in SRC0/1/2 (Op 1/2/3) 145 for (unsigned i = 0, e = MI.getNumOperands(); i < e; ++i) { 146 147 // Check if this operand should be encoded as [SV]Src 148 if (!isSrcOperand(Desc, i)) 149 continue; 150 151 // Is this operand a literal immediate? 152 const MCOperand &Op = MI.getOperand(i); 153 if (getLitEncoding(Op) != 255) 154 continue; 155 156 // Yes! Encode it 157 IntFloatUnion Imm; 158 if (Op.isImm()) 159 Imm.I = Op.getImm(); 160 else 161 Imm.F = Op.getFPImm(); 162 163 for (unsigned j = 0; j < 4; j++) { 164 OS.write((uint8_t) ((Imm.I >> (8 * j)) & 0xff)); 165 } 166 167 // Only one literal value allowed 168 break; 169 } 170} 171 172uint64_t SIMCCodeEmitter::getMachineOpValue(const MCInst &MI, 173 const MCOperand &MO, 174 SmallVectorImpl<MCFixup> &Fixups, 175 const MCSubtargetInfo &STI) const { 176 if (MO.isReg()) 177 return MRI.getEncodingValue(MO.getReg()); 178 179 if (MO.isExpr()) { 180 const MCExpr *Expr = MO.getExpr(); 181 MCFixupKind Kind = MCFixupKind(FK_PCRel_4); 182 Fixups.push_back(MCFixup::Create(0, Expr, Kind, MI.getLoc())); 183 return 0; 184 } 185 186 // Figure out the operand number, needed for isSrcOperand check 187 unsigned OpNo = 0; 188 for (unsigned e = MI.getNumOperands(); OpNo < e; ++OpNo) { 189 if (&MO == &MI.getOperand(OpNo)) 190 break; 191 } 192 193 const MCInstrDesc &Desc = MCII.get(MI.getOpcode()); 194 if (isSrcOperand(Desc, OpNo)) { 195 uint32_t Enc = getLitEncoding(MO); 196 if (Enc != ~0U && (Enc != 255 || Desc.getSize() == 4)) 197 return Enc; 198 199 } else if (MO.isImm()) 200 return MO.getImm(); 201 202 llvm_unreachable("Encoding of this operand type is not supported yet."); 203 return 0; 204} 205 206