X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FTarget%2FR600%2FMCTargetDesc%2FSIMCCodeEmitter.cpp;h=760aa378e7a89b9f6f5014e83d3cb17240572523;hb=57849e3bb48269d8005ccd9939404ac7c4b072c4;hp=c47dc995c771d77d7af32f1cc8cc979f3cba538d;hpb=3ee6391e0cddf8d94e2fa441d661c23e494a8489;p=oota-llvm.git diff --git a/lib/Target/R600/MCTargetDesc/SIMCCodeEmitter.cpp b/lib/Target/R600/MCTargetDesc/SIMCCodeEmitter.cpp index c47dc995c77..760aa378e7a 100644 --- a/lib/Target/R600/MCTargetDesc/SIMCCodeEmitter.cpp +++ b/lib/Target/R600/MCTargetDesc/SIMCCodeEmitter.cpp @@ -13,286 +13,277 @@ // //===----------------------------------------------------------------------===// -#include "MCTargetDesc/AMDGPUMCTargetDesc.h" +#include "AMDGPU.h" +#include "MCTargetDesc/AMDGPUFixupKinds.h" #include "MCTargetDesc/AMDGPUMCCodeEmitter.h" +#include "MCTargetDesc/AMDGPUMCTargetDesc.h" +#include "SIDefines.h" #include "llvm/MC/MCCodeEmitter.h" #include "llvm/MC/MCContext.h" +#include "llvm/MC/MCFixup.h" #include "llvm/MC/MCInst.h" #include "llvm/MC/MCInstrInfo.h" #include "llvm/MC/MCRegisterInfo.h" #include "llvm/MC/MCSubtargetInfo.h" -#include "llvm/MC/MCFixup.h" #include "llvm/Support/raw_ostream.h" -#define VGPR_BIT(src_idx) (1ULL << (9 * src_idx - 1)) -#define SI_INSTR_FLAGS_ENCODING_MASK 0xf - -// These must be kept in sync with SIInstructions.td and also the -// InstrEncodingInfo array in SIInstrInfo.cpp. -// -// NOTE: This enum is only used to identify the encoding type within LLVM, -// the actual encoding type that is part of the instruction format is different -namespace SIInstrEncodingType { - enum Encoding { - EXP = 0, - LDS = 1, - MIMG = 2, - MTBUF = 3, - MUBUF = 4, - SMRD = 5, - SOP1 = 6, - SOP2 = 7, - SOPC = 8, - SOPK = 9, - SOPP = 10, - VINTRP = 11, - VOP1 = 12, - VOP2 = 13, - VOP3 = 14, - VOPC = 15 - }; -} - using namespace llvm; namespace { + class SIMCCodeEmitter : public AMDGPUMCCodeEmitter { - SIMCCodeEmitter(const SIMCCodeEmitter &); // DO NOT IMPLEMENT - void operator=(const SIMCCodeEmitter &); // DO NOT IMPLEMENT + SIMCCodeEmitter(const SIMCCodeEmitter &) = delete; + void operator=(const SIMCCodeEmitter &) = delete; const MCInstrInfo &MCII; const MCRegisterInfo &MRI; - const MCSubtargetInfo &STI; MCContext &Ctx; + /// \brief Can this operand also contain immediate values? + bool isSrcOperand(const MCInstrDesc &Desc, unsigned OpNo) const; + + /// \brief Encode an fp or int literal + uint32_t getLitEncoding(const MCOperand &MO, unsigned OpSize) const; + public: SIMCCodeEmitter(const MCInstrInfo &mcii, const MCRegisterInfo &mri, - const MCSubtargetInfo &sti, MCContext &ctx) - : MCII(mcii), MRI(mri), STI(sti), Ctx(ctx) { } + MCContext &ctx) + : MCII(mcii), MRI(mri), Ctx(ctx) { } ~SIMCCodeEmitter() { } - /// \breif Encode the instruction and write it to the OS. - virtual void EncodeInstruction(const MCInst &MI, raw_ostream &OS, - SmallVectorImpl &Fixups) const; + /// \brief Encode the instruction and write it to the OS. + void EncodeInstruction(const MCInst &MI, raw_ostream &OS, + SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI) const override; /// \returns the encoding for an MCOperand. - virtual uint64_t getMachineOpValue(const MCInst &MI, const MCOperand &MO, - SmallVectorImpl &Fixups) const; + uint64_t getMachineOpValue(const MCInst &MI, const MCOperand &MO, + SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI) const override; + + /// \brief Use a fixup to encode the simm16 field for SOPP branch + /// instructions. + unsigned getSOPPBrEncoding(const MCInst &MI, unsigned OpNo, + SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI) const override; +}; -public: +} // End anonymous namespace - /// \brief Encode a sequence of registers with the correct alignment. - unsigned GPRAlign(const MCInst &MI, unsigned OpNo, unsigned shift) const; +MCCodeEmitter *llvm::createSIMCCodeEmitter(const MCInstrInfo &MCII, + const MCRegisterInfo &MRI, + MCContext &Ctx) { + return new SIMCCodeEmitter(MCII, MRI, Ctx); +} - /// \brief Encoding for when 2 consecutive registers are used - virtual unsigned GPR2AlignEncode(const MCInst &MI, unsigned OpNo, - SmallVectorImpl &Fixup) const; +bool SIMCCodeEmitter::isSrcOperand(const MCInstrDesc &Desc, + unsigned OpNo) const { + unsigned OpType = Desc.OpInfo[OpNo].OperandType; - /// \brief Encoding for when 4 consectuive registers are used - virtual unsigned GPR4AlignEncode(const MCInst &MI, unsigned OpNo, - SmallVectorImpl &Fixup) const; + return OpType == AMDGPU::OPERAND_REG_IMM32 || + OpType == AMDGPU::OPERAND_REG_INLINE_C; +} - /// \brief Encoding for SMRD indexed loads - virtual uint32_t SMRDmemriEncode(const MCInst &MI, unsigned OpNo, - SmallVectorImpl &Fixup) const; +// Returns the encoding value to use if the given integer is an integer inline +// immediate value, or 0 if it is not. +template +static uint32_t getIntInlineImmEncoding(IntTy Imm) { + if (Imm >= 0 && Imm <= 64) + return 128 + Imm; - /// \brief Post-Encoder method for VOP instructions - virtual uint64_t VOPPostEncode(const MCInst &MI, uint64_t Value) const; + if (Imm >= -16 && Imm <= -1) + return 192 + std::abs(Imm); -private: + return 0; +} - /// \returns this SIInstrEncodingType for this instruction. - unsigned getEncodingType(const MCInst &MI) const; +static uint32_t getLit32Encoding(uint32_t Val) { + uint32_t IntImm = getIntInlineImmEncoding(static_cast(Val)); + if (IntImm != 0) + return IntImm; - /// \brief Get then size in bytes of this instructions encoding. - unsigned getEncodingBytes(const MCInst &MI) const; + if (Val == FloatToBits(0.5f)) + return 240; - /// \returns the hardware encoding for a register - unsigned getRegBinaryCode(unsigned reg) const; + if (Val == FloatToBits(-0.5f)) + return 241; - /// \brief Generated function that returns the hardware encoding for - /// a register - unsigned getHWRegNum(unsigned reg) const; + if (Val == FloatToBits(1.0f)) + return 242; -}; + if (Val == FloatToBits(-1.0f)) + return 243; -} // End anonymous namespace + if (Val == FloatToBits(2.0f)) + return 244; -MCCodeEmitter *llvm::createSIMCCodeEmitter(const MCInstrInfo &MCII, - const MCRegisterInfo &MRI, - const MCSubtargetInfo &STI, - MCContext &Ctx) { - return new SIMCCodeEmitter(MCII, MRI, STI, Ctx); + if (Val == FloatToBits(-2.0f)) + return 245; + + if (Val == FloatToBits(4.0f)) + return 246; + + if (Val == FloatToBits(-4.0f)) + return 247; + + return 255; +} + +static uint32_t getLit64Encoding(uint64_t Val) { + uint32_t IntImm = getIntInlineImmEncoding(static_cast(Val)); + if (IntImm != 0) + return IntImm; + + if (Val == DoubleToBits(0.5)) + return 240; + + if (Val == DoubleToBits(-0.5)) + return 241; + + if (Val == DoubleToBits(1.0)) + return 242; + + if (Val == DoubleToBits(-1.0)) + return 243; + + if (Val == DoubleToBits(2.0)) + return 244; + + if (Val == DoubleToBits(-2.0)) + return 245; + + if (Val == DoubleToBits(4.0)) + return 246; + + if (Val == DoubleToBits(-4.0)) + return 247; + + return 255; +} + +uint32_t SIMCCodeEmitter::getLitEncoding(const MCOperand &MO, + unsigned OpSize) const { + if (MO.isExpr()) + return 255; + + assert(!MO.isFPImm()); + + if (!MO.isImm()) + return ~0; + + if (OpSize == 4) + return getLit32Encoding(static_cast(MO.getImm())); + + assert(OpSize == 8); + + return getLit64Encoding(static_cast(MO.getImm())); } void SIMCCodeEmitter::EncodeInstruction(const MCInst &MI, raw_ostream &OS, - SmallVectorImpl &Fixups) const { - uint64_t Encoding = getBinaryCodeForInstr(MI, Fixups); - unsigned bytes = getEncodingBytes(MI); + SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI) const { + + uint64_t Encoding = getBinaryCodeForInstr(MI, Fixups, STI); + const MCInstrDesc &Desc = MCII.get(MI.getOpcode()); + unsigned bytes = Desc.getSize(); + for (unsigned i = 0; i < bytes; i++) { OS.write((uint8_t) ((Encoding >> (8 * i)) & 0xff)); } -} -uint64_t SIMCCodeEmitter::getMachineOpValue(const MCInst &MI, - const MCOperand &MO, - SmallVectorImpl &Fixups) const { - if (MO.isReg()) { - return getRegBinaryCode(MO.getReg()); - } else if (MO.isImm()) { - return MO.getImm(); - } else if (MO.isFPImm()) { - // XXX: Not all instructions can use inline literals - // XXX: We should make sure this is a 32-bit constant - union { - float F; - uint32_t I; - } Imm; - Imm.F = MO.getFPImm(); - return Imm.I; - } else if (MO.isExpr()) { - const MCExpr *Expr = MO.getExpr(); - MCFixupKind Kind = MCFixupKind(FK_PCRel_4); - Fixups.push_back(MCFixup::Create(0, Expr, Kind, MI.getLoc())); - return 0; - } else{ - llvm_unreachable("Encoding of this operand type is not supported yet."); - } - return 0; -} + if (bytes > 4) + return; -//===----------------------------------------------------------------------===// -// Custom Operand Encodings -//===----------------------------------------------------------------------===// + // Check for additional literals in SRC0/1/2 (Op 1/2/3) + for (unsigned i = 0, e = MI.getNumOperands(); i < e; ++i) { -unsigned SIMCCodeEmitter::GPRAlign(const MCInst &MI, unsigned OpNo, - unsigned shift) const { - unsigned regCode = getRegBinaryCode(MI.getOperand(OpNo).getReg()); - return regCode >> shift; - return 0; -} -unsigned SIMCCodeEmitter::GPR2AlignEncode(const MCInst &MI, - unsigned OpNo , - SmallVectorImpl &Fixup) const { - return GPRAlign(MI, OpNo, 1); -} + // Check if this operand should be encoded as [SV]Src + if (!isSrcOperand(Desc, i)) + continue; -unsigned SIMCCodeEmitter::GPR4AlignEncode(const MCInst &MI, - unsigned OpNo, - SmallVectorImpl &Fixup) const { - return GPRAlign(MI, OpNo, 2); -} + int RCID = Desc.OpInfo[i].RegClass; + const MCRegisterClass &RC = MRI.getRegClass(RCID); -#define SMRD_OFFSET_MASK 0xff -#define SMRD_IMM_SHIFT 8 -#define SMRD_SBASE_MASK 0x3f -#define SMRD_SBASE_SHIFT 9 -/// This function is responsibe for encoding the offset -/// and the base ptr for SMRD instructions it should return a bit string in -/// this format: -/// -/// OFFSET = bits{7-0} -/// IMM = bits{8} -/// SBASE = bits{14-9} -/// -uint32_t SIMCCodeEmitter::SMRDmemriEncode(const MCInst &MI, unsigned OpNo, - SmallVectorImpl &Fixup) const { - uint32_t Encoding; - - const MCOperand &OffsetOp = MI.getOperand(OpNo + 1); - - //XXX: Use this function for SMRD loads with register offsets - assert(OffsetOp.isImm()); - - Encoding = - (getMachineOpValue(MI, OffsetOp, Fixup) & SMRD_OFFSET_MASK) - | (1 << SMRD_IMM_SHIFT) //XXX If the Offset is a register we shouldn't set this bit - | ((GPR2AlignEncode(MI, OpNo, Fixup) & SMRD_SBASE_MASK) << SMRD_SBASE_SHIFT) - ; - - return Encoding; -} + // Is this operand a literal immediate? + const MCOperand &Op = MI.getOperand(i); + if (getLitEncoding(Op, RC.getSize()) != 255) + continue; -//===----------------------------------------------------------------------===// -// Post Encoder Callbacks -//===----------------------------------------------------------------------===// + // Yes! Encode it + int64_t Imm = 0; -uint64_t SIMCCodeEmitter::VOPPostEncode(const MCInst &MI, uint64_t Value) const{ - unsigned encodingType = getEncodingType(MI); - unsigned numSrcOps; - unsigned vgprBitOffset; - - if (encodingType == SIInstrEncodingType::VOP3) { - numSrcOps = 3; - vgprBitOffset = 32; - } else { - numSrcOps = 1; - vgprBitOffset = 0; - } + if (Op.isImm()) + Imm = Op.getImm(); + else if (!Op.isExpr()) // Exprs will be replaced with a fixup value. + llvm_unreachable("Must be immediate or expr"); - // Add one to skip over the destination reg operand. - for (unsigned opIdx = 1; opIdx < numSrcOps + 1; opIdx++) { - const MCOperand &MO = MI.getOperand(opIdx); - if (MO.isReg()) { - unsigned reg = MI.getOperand(opIdx).getReg(); - if (AMDGPUMCRegisterClasses[AMDGPU::VReg_32RegClassID].contains(reg) || - AMDGPUMCRegisterClasses[AMDGPU::VReg_64RegClassID].contains(reg)) { - Value |= (VGPR_BIT(opIdx)) << vgprBitOffset; - } - } else if (MO.isFPImm()) { - union { - float f; - uint32_t i; - } Imm; - // XXX: Not all instructions can use inline literals - // XXX: We should make sure this is a 32-bit constant - Imm.f = MO.getFPImm(); - Value |= ((uint64_t)Imm.i) << 32; + for (unsigned j = 0; j < 4; j++) { + OS.write((uint8_t) ((Imm >> (8 * j)) & 0xff)); } + + // Only one literal value allowed + break; } - return Value; } -//===----------------------------------------------------------------------===// -// Encoding helper functions -//===----------------------------------------------------------------------===// +unsigned SIMCCodeEmitter::getSOPPBrEncoding(const MCInst &MI, unsigned OpNo, + SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI) const { + const MCOperand &MO = MI.getOperand(OpNo); -unsigned SIMCCodeEmitter::getEncodingType(const MCInst &MI) const { - return MCII.get(MI.getOpcode()).TSFlags & SI_INSTR_FLAGS_ENCODING_MASK; -} + if (MO.isExpr()) { + const MCExpr *Expr = MO.getExpr(); + MCFixupKind Kind = (MCFixupKind)AMDGPU::fixup_si_sopp_br; + Fixups.push_back(MCFixup::Create(0, Expr, Kind, MI.getLoc())); + return 0; + } -unsigned SIMCCodeEmitter::getEncodingBytes(const MCInst &MI) const { + return getMachineOpValue(MI, MO, Fixups, STI); +} - // These instructions aren't real instructions with an encoding type, so - // we need to manually specify their size. - switch (MI.getOpcode()) { - default: break; - case AMDGPU::SI_LOAD_LITERAL_I32: - case AMDGPU::SI_LOAD_LITERAL_F32: - return 4; +uint64_t SIMCCodeEmitter::getMachineOpValue(const MCInst &MI, + const MCOperand &MO, + SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI) const { + if (MO.isReg()) + return MRI.getEncodingValue(MO.getReg()); + + if (MO.isExpr()) { + const MCSymbolRefExpr *Expr = cast(MO.getExpr()); + MCFixupKind Kind; + const MCSymbol *Sym = + Ctx.GetOrCreateSymbol(StringRef(END_OF_TEXT_LABEL_NAME)); + + if (&Expr->getSymbol() == Sym) { + // Add the offset to the beginning of the constant values. + Kind = (MCFixupKind)AMDGPU::fixup_si_end_of_text; + } else { + // This is used for constant data stored in .rodata. + Kind = (MCFixupKind)AMDGPU::fixup_si_rodata; + } + Fixups.push_back(MCFixup::Create(4, Expr, Kind, MI.getLoc())); } - unsigned encoding_type = getEncodingType(MI); - switch (encoding_type) { - case SIInstrEncodingType::EXP: - case SIInstrEncodingType::LDS: - case SIInstrEncodingType::MUBUF: - case SIInstrEncodingType::MTBUF: - case SIInstrEncodingType::MIMG: - case SIInstrEncodingType::VOP3: - return 8; - default: - return 4; + // Figure out the operand number, needed for isSrcOperand check + unsigned OpNo = 0; + for (unsigned e = MI.getNumOperands(); OpNo < e; ++OpNo) { + if (&MO == &MI.getOperand(OpNo)) + break; } -} + const MCInstrDesc &Desc = MCII.get(MI.getOpcode()); + if (isSrcOperand(Desc, OpNo)) { + int RCID = Desc.OpInfo[OpNo].RegClass; + const MCRegisterClass &RC = MRI.getRegClass(RCID); -unsigned SIMCCodeEmitter::getRegBinaryCode(unsigned reg) const { - switch (reg) { - case AMDGPU::M0: return 124; - case AMDGPU::SREG_LIT_0: return 128; - case AMDGPU::SI_LITERAL_CONSTANT: return 255; - default: return MRI.getEncodingValue(reg); - } + uint32_t Enc = getLitEncoding(MO, RC.getSize()); + if (Enc != ~0U && (Enc != 255 || Desc.getSize() == 4)) + return Enc; + + } else if (MO.isImm()) + return MO.getImm(); + + llvm_unreachable("Encoding of this operand type is not supported yet."); + return 0; }