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