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   const MCSubtargetInfo &STI;
     43   MCContext &Ctx;
     44 
     45   /// \brief Can this operand also contain immediate values?
     46   bool isSrcOperand(const MCInstrDesc &Desc, unsigned OpNo) const;
     47 
     48   /// \brief Encode an fp or int literal
     49   uint32_t getLitEncoding(const MCOperand &MO) const;
     50 
     51 public:
     52   SIMCCodeEmitter(const MCInstrInfo &mcii, const MCRegisterInfo &mri,
     53                   const MCSubtargetInfo &sti, MCContext &ctx)
     54     : MCII(mcii), MRI(mri), STI(sti), Ctx(ctx) { }
     55 
     56   ~SIMCCodeEmitter() { }
     57 
     58   /// \breif Encode the instruction and write it to the OS.
     59   virtual void EncodeInstruction(const MCInst &MI, raw_ostream &OS,
     60                          SmallVectorImpl<MCFixup> &Fixups) const;
     61 
     62   /// \returns the encoding for an MCOperand.
     63   virtual uint64_t getMachineOpValue(const MCInst &MI, const MCOperand &MO,
     64                                      SmallVectorImpl<MCFixup> &Fixups) const;
     65 };
     66 
     67 } // End anonymous namespace
     68 
     69 MCCodeEmitter *llvm::createSIMCCodeEmitter(const MCInstrInfo &MCII,
     70                                            const MCRegisterInfo &MRI,
     71                                            const MCSubtargetInfo &STI,
     72                                            MCContext &Ctx) {
     73   return new SIMCCodeEmitter(MCII, MRI, STI, Ctx);
     74 }
     75 
     76 bool 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 
     86 uint32_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 
    129 void SIMCCodeEmitter::EncodeInstruction(const MCInst &MI, raw_ostream &OS,
    130                                        SmallVectorImpl<MCFixup> &Fixups) const {
    131 
    132   uint64_t Encoding = getBinaryCodeForInstr(MI, Fixups);
    133   const MCInstrDesc &Desc = MCII.get(MI.getOpcode());
    134   unsigned bytes = Desc.getSize();
    135 
    136   for (unsigned i = 0; i < bytes; i++) {
    137     OS.write((uint8_t) ((Encoding >> (8 * i)) & 0xff));
    138   }
    139 
    140   if (bytes > 4)
    141     return;
    142 
    143   // Check for additional literals in SRC0/1/2 (Op 1/2/3)
    144   for (unsigned i = 0, e = MI.getNumOperands(); i < e; ++i) {
    145 
    146     // Check if this operand should be encoded as [SV]Src
    147     if (!isSrcOperand(Desc, i))
    148       continue;
    149 
    150     // Is this operand a literal immediate?
    151     const MCOperand &Op = MI.getOperand(i);
    152     if (getLitEncoding(Op) != 255)
    153       continue;
    154 
    155     // Yes! Encode it
    156     IntFloatUnion Imm;
    157     if (Op.isImm())
    158       Imm.I = Op.getImm();
    159     else
    160       Imm.F = Op.getFPImm();
    161 
    162     for (unsigned j = 0; j < 4; j++) {
    163       OS.write((uint8_t) ((Imm.I >> (8 * j)) & 0xff));
    164     }
    165 
    166     // Only one literal value allowed
    167     break;
    168   }
    169 }
    170 
    171 uint64_t SIMCCodeEmitter::getMachineOpValue(const MCInst &MI,
    172                                             const MCOperand &MO,
    173                                        SmallVectorImpl<MCFixup> &Fixups) const {
    174   if (MO.isReg())
    175     return MRI.getEncodingValue(MO.getReg());
    176 
    177   if (MO.isExpr()) {
    178     const MCExpr *Expr = MO.getExpr();
    179     MCFixupKind Kind = MCFixupKind(FK_PCRel_4);
    180     Fixups.push_back(MCFixup::Create(0, Expr, Kind, MI.getLoc()));
    181     return 0;
    182   }
    183 
    184   // Figure out the operand number, needed for isSrcOperand check
    185   unsigned OpNo = 0;
    186   for (unsigned e = MI.getNumOperands(); OpNo < e; ++OpNo) {
    187     if (&MO == &MI.getOperand(OpNo))
    188       break;
    189   }
    190 
    191   const MCInstrDesc &Desc = MCII.get(MI.getOpcode());
    192   if (isSrcOperand(Desc, OpNo)) {
    193     uint32_t Enc = getLitEncoding(MO);
    194     if (Enc != ~0U && (Enc != 255 || Desc.getSize() == 4))
    195       return Enc;
    196 
    197   } else if (MO.isImm())
    198     return MO.getImm();
    199 
    200   llvm_unreachable("Encoding of this operand type is not supported yet.");
    201   return 0;
    202 }
    203 
    204