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