SIMCCodeEmitter.cpp revision 2809ae3d445bc10a79f119946439431ba73bb069
1600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang//===-- SIMCCodeEmitter.cpp - SI Code Emitter -------------------------------===// 2600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang// 3600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang// The LLVM Compiler Infrastructure 4600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang// 5600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang// This file is distributed under the University of Illinois Open Source 6600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang// License. See LICENSE.TXT for details. 7600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang// 8600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang//===----------------------------------------------------------------------===// 9600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang// 10600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang// The SI code emitter produces machine code that can be executed directly on 11600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang// the GPU device. 12600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang// 13600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang//===----------------------------------------------------------------------===// 14600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 15600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang#include "MCTargetDesc/AMDGPUMCTargetDesc.h" 16600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang#include "MCTargetDesc/AMDGPUMCCodeEmitter.h" 17600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang#include "llvm/MC/MCCodeEmitter.h" 18600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang#include "llvm/MC/MCContext.h" 19600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang#include "llvm/MC/MCInst.h" 20600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang#include "llvm/MC/MCInstrInfo.h" 21600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang#include "llvm/MC/MCRegisterInfo.h" 22600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang#include "llvm/MC/MCSubtargetInfo.h" 23600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang#include "llvm/Support/raw_ostream.h" 24600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 25600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang#define LITERAL_REG 255 26600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang#define VGPR_BIT(src_idx) (1ULL << (9 * src_idx - 1)) 27600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang#define SI_INSTR_FLAGS_ENCODING_MASK 0xf 28600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 29600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 30600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang// These must be kept in sync with SIInstructions.td and also the 31600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang// InstrEncodingInfo array in SIInstrInfo.cpp. 32600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang// 33600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang// NOTE: This enum is only used to identify the encoding type within LLVM, 34600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang// the actual encoding type that is part of the instruction format is different 35600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangnamespace SIInstrEncodingType { 36600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang enum Encoding { 37600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang EXP = 0, 38600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang LDS = 1, 39600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang MIMG = 2, 40600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang MTBUF = 3, 41600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang MUBUF = 4, 42600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang SMRD = 5, 43600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang SOP1 = 6, 44600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang SOP2 = 7, 45600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang SOPC = 8, 46600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang SOPK = 9, 47600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang SOPP = 10, 48600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang VINTRP = 11, 49600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang VOP1 = 12, 50600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang VOP2 = 13, 51600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang VOP3 = 14, 52600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang VOPC = 15 53600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang }; 54600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang} 55600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 56600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangusing namespace llvm; 57600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 58600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangnamespace { 59600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangclass SIMCCodeEmitter : public AMDGPUMCCodeEmitter { 60600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang SIMCCodeEmitter(const SIMCCodeEmitter &); // DO NOT IMPLEMENT 61600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang void operator=(const SIMCCodeEmitter &); // DO NOT IMPLEMENT 62600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang const MCInstrInfo &MCII; 63600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang const MCSubtargetInfo &STI; 64600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang MCContext &Ctx; 65600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 66600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangpublic: 67600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang SIMCCodeEmitter(const MCInstrInfo &mcii, const MCSubtargetInfo &sti, 68600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang MCContext &ctx) 69600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang : MCII(mcii), STI(sti), Ctx(ctx) { } 70600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 71600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang ~SIMCCodeEmitter() { } 72600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 73600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /// EncodeInstruction - Encode the instruction and write it to the OS. 74600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang virtual void EncodeInstruction(const MCInst &MI, raw_ostream &OS, 75600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang SmallVectorImpl<MCFixup> &Fixups) const; 76600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 77600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /// getMachineOpValue - Reutrn the encoding for an MCOperand. 78600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang virtual uint64_t getMachineOpValue(const MCInst &MI, const MCOperand &MO, 79600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang SmallVectorImpl<MCFixup> &Fixups) const; 80600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 81600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangpublic: 82600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 83600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /// GPRAlign - Encode a sequence of registers with the correct alignment. 84600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang unsigned GPRAlign(const MCInst &MI, unsigned OpNo, unsigned shift) const; 85600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 86600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /// GPR2AlignEncode - Encoding for when 2 consecutive registers are used 87600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang virtual unsigned GPR2AlignEncode(const MCInst &MI, unsigned OpNo, 88600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang SmallVectorImpl<MCFixup> &Fixup) const; 89600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 90600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /// GPR4AlignEncode - Encoding for when 4 consectuive registers are used 91600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang virtual unsigned GPR4AlignEncode(const MCInst &MI, unsigned OpNo, 92600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang SmallVectorImpl<MCFixup> &Fixup) const; 93600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 94600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /// i32LiteralEncode - Encode an i32 literal this is used as an operand 95600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /// for an instruction in place of a register. 96600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang virtual uint64_t i32LiteralEncode(const MCInst &MI, unsigned OpNo, 97600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang SmallVectorImpl<MCFixup> &Fixup) const; 98600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 99600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /// SMRDmemriEncode - Encoding for SMRD indexed loads 100600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang virtual uint32_t SMRDmemriEncode(const MCInst &MI, unsigned OpNo, 101600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang SmallVectorImpl<MCFixup> &Fixup) const; 102600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 103600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /// VOPPostEncode - Post-Encoder method for VOP instructions 104600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang virtual uint64_t VOPPostEncode(const MCInst &MI, uint64_t Value) const; 105600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 106600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangprivate: 107600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 108600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang ///getEncodingType = Return this SIInstrEncodingType for this instruction. 109600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang unsigned getEncodingType(const MCInst &MI) const; 110600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 111600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang ///getEncodingBytes - Get then size in bytes of this instructions encoding. 112600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang unsigned getEncodingBytes(const MCInst &MI) const; 113600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 114600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /// getRegBinaryCode - Returns the hardware encoding for a register 115600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang unsigned getRegBinaryCode(unsigned reg) const; 116600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 117600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /// getHWRegNum - Generated function that returns the hardware encoding for 118600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /// a register 119600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang unsigned getHWRegNum(unsigned reg) const; 120600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 121600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang}; 122600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 123600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang} // End anonymous namespace 124 125MCCodeEmitter *llvm::createSIMCCodeEmitter(const MCInstrInfo &MCII, 126 const MCSubtargetInfo &STI, 127 MCContext &Ctx) { 128 return new SIMCCodeEmitter(MCII, STI, Ctx); 129} 130 131void SIMCCodeEmitter::EncodeInstruction(const MCInst &MI, raw_ostream &OS, 132 SmallVectorImpl<MCFixup> &Fixups) const { 133 uint64_t Encoding = getBinaryCodeForInstr(MI, Fixups); 134 unsigned bytes = getEncodingBytes(MI); 135 for (unsigned i = 0; i < bytes; i++) { 136 OS.write((uint8_t) ((Encoding >> (8 * i)) & 0xff)); 137 } 138} 139 140uint64_t SIMCCodeEmitter::getMachineOpValue(const MCInst &MI, 141 const MCOperand &MO, 142 SmallVectorImpl<MCFixup> &Fixups) const { 143 if (MO.isReg()) { 144 return getRegBinaryCode(MO.getReg()); 145 } else if (MO.isImm()) { 146 return MO.getImm(); 147 } else if (MO.isFPImm()) { 148 // XXX: Not all instructions can use inline literals 149 // XXX: We should make sure this is a 32-bit constant 150 return LITERAL_REG; 151 } else{ 152 llvm_unreachable("Encoding of this operand type is not supported yet."); 153 } 154 return 0; 155} 156 157//===----------------------------------------------------------------------===// 158// Custom Operand Encodings 159//===----------------------------------------------------------------------===// 160 161unsigned SIMCCodeEmitter::GPRAlign(const MCInst &MI, unsigned OpNo, 162 unsigned shift) const { 163 unsigned regCode = getRegBinaryCode(MI.getOperand(OpNo).getReg()); 164 return regCode >> shift; 165 return 0; 166} 167unsigned SIMCCodeEmitter::GPR2AlignEncode(const MCInst &MI, 168 unsigned OpNo , 169 SmallVectorImpl<MCFixup> &Fixup) const { 170 return GPRAlign(MI, OpNo, 1); 171} 172 173unsigned SIMCCodeEmitter::GPR4AlignEncode(const MCInst &MI, 174 unsigned OpNo, 175 SmallVectorImpl<MCFixup> &Fixup) const { 176 return GPRAlign(MI, OpNo, 2); 177} 178 179uint64_t SIMCCodeEmitter::i32LiteralEncode(const MCInst &MI, 180 unsigned OpNo, 181 SmallVectorImpl<MCFixup> &Fixup) const { 182 return LITERAL_REG | (MI.getOperand(OpNo).getImm() << 32); 183} 184 185#define SMRD_OFFSET_MASK 0xff 186#define SMRD_IMM_SHIFT 8 187#define SMRD_SBASE_MASK 0x3f 188#define SMRD_SBASE_SHIFT 9 189/// SMRDmemriEncode - This function is responsibe for encoding the offset 190/// and the base ptr for SMRD instructions it should return a bit string in 191/// this format: 192/// 193/// OFFSET = bits{7-0} 194/// IMM = bits{8} 195/// SBASE = bits{14-9} 196/// 197uint32_t SIMCCodeEmitter::SMRDmemriEncode(const MCInst &MI, unsigned OpNo, 198 SmallVectorImpl<MCFixup> &Fixup) const { 199 uint32_t Encoding; 200 201 const MCOperand &OffsetOp = MI.getOperand(OpNo + 1); 202 203 //XXX: Use this function for SMRD loads with register offsets 204 assert(OffsetOp.isImm()); 205 206 Encoding = 207 (getMachineOpValue(MI, OffsetOp, Fixup) & SMRD_OFFSET_MASK) 208 | (1 << SMRD_IMM_SHIFT) //XXX If the Offset is a register we shouldn't set this bit 209 | ((GPR2AlignEncode(MI, OpNo, Fixup) & SMRD_SBASE_MASK) << SMRD_SBASE_SHIFT) 210 ; 211 212 return Encoding; 213} 214 215//===----------------------------------------------------------------------===// 216// Post Encoder Callbacks 217//===----------------------------------------------------------------------===// 218 219uint64_t SIMCCodeEmitter::VOPPostEncode(const MCInst &MI, uint64_t Value) const{ 220 unsigned encodingType = getEncodingType(MI); 221 unsigned numSrcOps; 222 unsigned vgprBitOffset; 223 224 if (encodingType == SIInstrEncodingType::VOP3) { 225 numSrcOps = 3; 226 vgprBitOffset = 32; 227 } else { 228 numSrcOps = 1; 229 vgprBitOffset = 0; 230 } 231 232 // Add one to skip over the destination reg operand. 233 for (unsigned opIdx = 1; opIdx < numSrcOps + 1; opIdx++) { 234 const MCOperand &MO = MI.getOperand(opIdx); 235 if (MO.isReg()) { 236 unsigned reg = MI.getOperand(opIdx).getReg(); 237 if (AMDGPUMCRegisterClasses[AMDGPU::VReg_32RegClassID].contains(reg) || 238 AMDGPUMCRegisterClasses[AMDGPU::VReg_64RegClassID].contains(reg)) { 239 Value |= (VGPR_BIT(opIdx)) << vgprBitOffset; 240 } 241 } else if (MO.isFPImm()) { 242 union { 243 float f; 244 uint32_t i; 245 } Imm; 246 // XXX: Not all instructions can use inline literals 247 // XXX: We should make sure this is a 32-bit constant 248 Imm.f = MO.getFPImm(); 249 Value |= ((uint64_t)Imm.i) << 32; 250 } 251 } 252 return Value; 253} 254 255//===----------------------------------------------------------------------===// 256// Encoding helper functions 257//===----------------------------------------------------------------------===// 258 259unsigned SIMCCodeEmitter::getEncodingType(const MCInst &MI) const { 260 return MCII.get(MI.getOpcode()).TSFlags & SI_INSTR_FLAGS_ENCODING_MASK; 261} 262 263unsigned SIMCCodeEmitter::getEncodingBytes(const MCInst &MI) const { 264 265 // Instructions with literal constants are expanded to 64-bits, and 266 // the constant is stored in bits [63:32] 267 for (unsigned i = 0; i < MI.getNumOperands(); i++) { 268 if (MI.getOperand(i).isFPImm()) { 269 return 8; 270 } 271 } 272 273 // This instruction always has a literal 274 if (MI.getOpcode() == AMDGPU::S_MOV_IMM_I32) { 275 return 8; 276 } 277 278 unsigned encoding_type = getEncodingType(MI); 279 switch (encoding_type) { 280 case SIInstrEncodingType::EXP: 281 case SIInstrEncodingType::LDS: 282 case SIInstrEncodingType::MUBUF: 283 case SIInstrEncodingType::MTBUF: 284 case SIInstrEncodingType::MIMG: 285 case SIInstrEncodingType::VOP3: 286 return 8; 287 default: 288 return 4; 289 } 290} 291 292 293unsigned SIMCCodeEmitter::getRegBinaryCode(unsigned reg) const { 294 switch (reg) { 295 case AMDGPU::M0: return 124; 296 case AMDGPU::SREG_LIT_0: return 128; 297 default: return getHWRegNum(reg); 298 } 299} 300 301#define SIRegisterInfo SIMCCodeEmitter 302#include "SIRegisterGetHWRegNum.inc" 303#undef SIRegisterInfo 304