Home | History | Annotate | Download | only in MCTargetDesc
      1 //===-- SystemZMCCodeEmitter.cpp - Convert SystemZ code to machine code ---===//
      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 // This file implements the SystemZMCCodeEmitter class.
     11 //
     12 //===----------------------------------------------------------------------===//
     13 
     14 #include "MCTargetDesc/SystemZMCTargetDesc.h"
     15 #include "MCTargetDesc/SystemZMCFixups.h"
     16 #include "llvm/MC/MCCodeEmitter.h"
     17 #include "llvm/MC/MCContext.h"
     18 #include "llvm/MC/MCExpr.h"
     19 #include "llvm/MC/MCInst.h"
     20 #include "llvm/MC/MCInstrInfo.h"
     21 #include "llvm/MC/MCRegisterInfo.h"
     22 
     23 using namespace llvm;
     24 
     25 #define DEBUG_TYPE "mccodeemitter"
     26 
     27 namespace {
     28 class SystemZMCCodeEmitter : public MCCodeEmitter {
     29   const MCInstrInfo &MCII;
     30   MCContext &Ctx;
     31 
     32 public:
     33   SystemZMCCodeEmitter(const MCInstrInfo &mcii, MCContext &ctx)
     34     : MCII(mcii), Ctx(ctx) {
     35   }
     36 
     37   ~SystemZMCCodeEmitter() override {}
     38 
     39   // OVerride MCCodeEmitter.
     40   void encodeInstruction(const MCInst &MI, raw_ostream &OS,
     41                          SmallVectorImpl<MCFixup> &Fixups,
     42                          const MCSubtargetInfo &STI) const override;
     43 
     44 private:
     45   // Automatically generated by TableGen.
     46   uint64_t getBinaryCodeForInstr(const MCInst &MI,
     47                                  SmallVectorImpl<MCFixup> &Fixups,
     48                                  const MCSubtargetInfo &STI) const;
     49 
     50   // Called by the TableGen code to get the binary encoding of operand
     51   // MO in MI.  Fixups is the list of fixups against MI.
     52   uint64_t getMachineOpValue(const MCInst &MI, const MCOperand &MO,
     53                              SmallVectorImpl<MCFixup> &Fixups,
     54                              const MCSubtargetInfo &STI) const;
     55 
     56   // Called by the TableGen code to get the binary encoding of an address.
     57   // The index or length, if any, is encoded first, followed by the base,
     58   // followed by the displacement.  In a 20-bit displacement,
     59   // the low 12 bits are encoded before the high 8 bits.
     60   uint64_t getBDAddr12Encoding(const MCInst &MI, unsigned OpNum,
     61                                SmallVectorImpl<MCFixup> &Fixups,
     62                                const MCSubtargetInfo &STI) const;
     63   uint64_t getBDAddr20Encoding(const MCInst &MI, unsigned OpNum,
     64                                SmallVectorImpl<MCFixup> &Fixups,
     65                                const MCSubtargetInfo &STI) const;
     66   uint64_t getBDXAddr12Encoding(const MCInst &MI, unsigned OpNum,
     67                                 SmallVectorImpl<MCFixup> &Fixups,
     68                                 const MCSubtargetInfo &STI) const;
     69   uint64_t getBDXAddr20Encoding(const MCInst &MI, unsigned OpNum,
     70                                 SmallVectorImpl<MCFixup> &Fixups,
     71                                 const MCSubtargetInfo &STI) const;
     72   uint64_t getBDLAddr12Len8Encoding(const MCInst &MI, unsigned OpNum,
     73                                     SmallVectorImpl<MCFixup> &Fixups,
     74                                     const MCSubtargetInfo &STI) const;
     75   uint64_t getBDVAddr12Encoding(const MCInst &MI, unsigned OpNum,
     76                                 SmallVectorImpl<MCFixup> &Fixups,
     77                                 const MCSubtargetInfo &STI) const;
     78 
     79   // Operand OpNum of MI needs a PC-relative fixup of kind Kind at
     80   // Offset bytes from the start of MI.  Add the fixup to Fixups
     81   // and return the in-place addend, which since we're a RELA target
     82   // is always 0.  If AllowTLS is true and optional operand OpNum + 1
     83   // is present, also emit a TLS call fixup for it.
     84   uint64_t getPCRelEncoding(const MCInst &MI, unsigned OpNum,
     85                             SmallVectorImpl<MCFixup> &Fixups,
     86                             unsigned Kind, int64_t Offset,
     87                             bool AllowTLS) const;
     88 
     89   uint64_t getPC16DBLEncoding(const MCInst &MI, unsigned OpNum,
     90                               SmallVectorImpl<MCFixup> &Fixups,
     91                               const MCSubtargetInfo &STI) const {
     92     return getPCRelEncoding(MI, OpNum, Fixups,
     93                             SystemZ::FK_390_PC16DBL, 2, false);
     94   }
     95   uint64_t getPC32DBLEncoding(const MCInst &MI, unsigned OpNum,
     96                               SmallVectorImpl<MCFixup> &Fixups,
     97                               const MCSubtargetInfo &STI) const {
     98     return getPCRelEncoding(MI, OpNum, Fixups,
     99                             SystemZ::FK_390_PC32DBL, 2, false);
    100   }
    101   uint64_t getPC16DBLTLSEncoding(const MCInst &MI, unsigned OpNum,
    102                                  SmallVectorImpl<MCFixup> &Fixups,
    103                                  const MCSubtargetInfo &STI) const {
    104     return getPCRelEncoding(MI, OpNum, Fixups,
    105                             SystemZ::FK_390_PC16DBL, 2, true);
    106   }
    107   uint64_t getPC32DBLTLSEncoding(const MCInst &MI, unsigned OpNum,
    108                                  SmallVectorImpl<MCFixup> &Fixups,
    109                                  const MCSubtargetInfo &STI) const {
    110     return getPCRelEncoding(MI, OpNum, Fixups,
    111                             SystemZ::FK_390_PC32DBL, 2, true);
    112   }
    113 };
    114 } // end anonymous namespace
    115 
    116 MCCodeEmitter *llvm::createSystemZMCCodeEmitter(const MCInstrInfo &MCII,
    117                                                 const MCRegisterInfo &MRI,
    118                                                 MCContext &Ctx) {
    119   return new SystemZMCCodeEmitter(MCII, Ctx);
    120 }
    121 
    122 void SystemZMCCodeEmitter::
    123 encodeInstruction(const MCInst &MI, raw_ostream &OS,
    124                   SmallVectorImpl<MCFixup> &Fixups,
    125                   const MCSubtargetInfo &STI) const {
    126   uint64_t Bits = getBinaryCodeForInstr(MI, Fixups, STI);
    127   unsigned Size = MCII.get(MI.getOpcode()).getSize();
    128   // Big-endian insertion of Size bytes.
    129   unsigned ShiftValue = (Size * 8) - 8;
    130   for (unsigned I = 0; I != Size; ++I) {
    131     OS << uint8_t(Bits >> ShiftValue);
    132     ShiftValue -= 8;
    133   }
    134 }
    135 
    136 uint64_t SystemZMCCodeEmitter::
    137 getMachineOpValue(const MCInst &MI, const MCOperand &MO,
    138                   SmallVectorImpl<MCFixup> &Fixups,
    139                   const MCSubtargetInfo &STI) const {
    140   if (MO.isReg())
    141     return Ctx.getRegisterInfo()->getEncodingValue(MO.getReg());
    142   if (MO.isImm())
    143     return static_cast<uint64_t>(MO.getImm());
    144   llvm_unreachable("Unexpected operand type!");
    145 }
    146 
    147 uint64_t SystemZMCCodeEmitter::
    148 getBDAddr12Encoding(const MCInst &MI, unsigned OpNum,
    149                     SmallVectorImpl<MCFixup> &Fixups,
    150                     const MCSubtargetInfo &STI) const {
    151   uint64_t Base = getMachineOpValue(MI, MI.getOperand(OpNum), Fixups, STI);
    152   uint64_t Disp = getMachineOpValue(MI, MI.getOperand(OpNum + 1), Fixups, STI);
    153   assert(isUInt<4>(Base) && isUInt<12>(Disp));
    154   return (Base << 12) | Disp;
    155 }
    156 
    157 uint64_t SystemZMCCodeEmitter::
    158 getBDAddr20Encoding(const MCInst &MI, unsigned OpNum,
    159                     SmallVectorImpl<MCFixup> &Fixups,
    160                     const MCSubtargetInfo &STI) const {
    161   uint64_t Base = getMachineOpValue(MI, MI.getOperand(OpNum), Fixups, STI);
    162   uint64_t Disp = getMachineOpValue(MI, MI.getOperand(OpNum + 1), Fixups, STI);
    163   assert(isUInt<4>(Base) && isInt<20>(Disp));
    164   return (Base << 20) | ((Disp & 0xfff) << 8) | ((Disp & 0xff000) >> 12);
    165 }
    166 
    167 uint64_t SystemZMCCodeEmitter::
    168 getBDXAddr12Encoding(const MCInst &MI, unsigned OpNum,
    169                      SmallVectorImpl<MCFixup> &Fixups,
    170                      const MCSubtargetInfo &STI) const {
    171   uint64_t Base = getMachineOpValue(MI, MI.getOperand(OpNum), Fixups, STI);
    172   uint64_t Disp = getMachineOpValue(MI, MI.getOperand(OpNum + 1), Fixups, STI);
    173   uint64_t Index = getMachineOpValue(MI, MI.getOperand(OpNum + 2), Fixups, STI);
    174   assert(isUInt<4>(Base) && isUInt<12>(Disp) && isUInt<4>(Index));
    175   return (Index << 16) | (Base << 12) | Disp;
    176 }
    177 
    178 uint64_t SystemZMCCodeEmitter::
    179 getBDXAddr20Encoding(const MCInst &MI, unsigned OpNum,
    180                      SmallVectorImpl<MCFixup> &Fixups,
    181                      const MCSubtargetInfo &STI) const {
    182   uint64_t Base = getMachineOpValue(MI, MI.getOperand(OpNum), Fixups, STI);
    183   uint64_t Disp = getMachineOpValue(MI, MI.getOperand(OpNum + 1), Fixups, STI);
    184   uint64_t Index = getMachineOpValue(MI, MI.getOperand(OpNum + 2), Fixups, STI);
    185   assert(isUInt<4>(Base) && isInt<20>(Disp) && isUInt<4>(Index));
    186   return (Index << 24) | (Base << 20) | ((Disp & 0xfff) << 8)
    187     | ((Disp & 0xff000) >> 12);
    188 }
    189 
    190 uint64_t SystemZMCCodeEmitter::
    191 getBDLAddr12Len8Encoding(const MCInst &MI, unsigned OpNum,
    192                          SmallVectorImpl<MCFixup> &Fixups,
    193                          const MCSubtargetInfo &STI) const {
    194   uint64_t Base = getMachineOpValue(MI, MI.getOperand(OpNum), Fixups, STI);
    195   uint64_t Disp = getMachineOpValue(MI, MI.getOperand(OpNum + 1), Fixups, STI);
    196   uint64_t Len  = getMachineOpValue(MI, MI.getOperand(OpNum + 2), Fixups, STI) - 1;
    197   assert(isUInt<4>(Base) && isUInt<12>(Disp) && isUInt<8>(Len));
    198   return (Len << 16) | (Base << 12) | Disp;
    199 }
    200 
    201 uint64_t SystemZMCCodeEmitter::
    202 getBDVAddr12Encoding(const MCInst &MI, unsigned OpNum,
    203                      SmallVectorImpl<MCFixup> &Fixups,
    204                      const MCSubtargetInfo &STI) const {
    205   uint64_t Base = getMachineOpValue(MI, MI.getOperand(OpNum), Fixups, STI);
    206   uint64_t Disp = getMachineOpValue(MI, MI.getOperand(OpNum + 1), Fixups, STI);
    207   uint64_t Index = getMachineOpValue(MI, MI.getOperand(OpNum + 2), Fixups, STI);
    208   assert(isUInt<4>(Base) && isUInt<12>(Disp) && isUInt<5>(Index));
    209   return (Index << 16) | (Base << 12) | Disp;
    210 }
    211 
    212 uint64_t
    213 SystemZMCCodeEmitter::getPCRelEncoding(const MCInst &MI, unsigned OpNum,
    214                                        SmallVectorImpl<MCFixup> &Fixups,
    215                                        unsigned Kind, int64_t Offset,
    216                                        bool AllowTLS) const {
    217   const MCOperand &MO = MI.getOperand(OpNum);
    218   const MCExpr *Expr;
    219   if (MO.isImm())
    220     Expr = MCConstantExpr::create(MO.getImm() + Offset, Ctx);
    221   else {
    222     Expr = MO.getExpr();
    223     if (Offset) {
    224       // The operand value is relative to the start of MI, but the fixup
    225       // is relative to the operand field itself, which is Offset bytes
    226       // into MI.  Add Offset to the relocation value to cancel out
    227       // this difference.
    228       const MCExpr *OffsetExpr = MCConstantExpr::create(Offset, Ctx);
    229       Expr = MCBinaryExpr::createAdd(Expr, OffsetExpr, Ctx);
    230     }
    231   }
    232   Fixups.push_back(MCFixup::create(Offset, Expr, (MCFixupKind)Kind));
    233 
    234   // Output the fixup for the TLS marker if present.
    235   if (AllowTLS && OpNum + 1 < MI.getNumOperands()) {
    236     const MCOperand &MOTLS = MI.getOperand(OpNum + 1);
    237     Fixups.push_back(MCFixup::create(0, MOTLS.getExpr(),
    238                                      (MCFixupKind)SystemZ::FK_390_TLS_CALL));
    239   }
    240   return 0;
    241 }
    242 
    243 #include "SystemZGenMCCodeEmitter.inc"
    244