SystemZMCCodeEmitter.cpp revision 285830
121308Sache//===-- SystemZMCCodeEmitter.cpp - Convert SystemZ code to machine code ---===//
221308Sache//
321308Sache//                     The LLVM Compiler Infrastructure
421308Sache//
521308Sache// This file is distributed under the University of Illinois Open Source
621308Sache// License. See LICENSE.TXT for details.
721308Sache//
821308Sache//===----------------------------------------------------------------------===//
921308Sache//
1021308Sache// This file implements the SystemZMCCodeEmitter class.
1121308Sache//
1221308Sache//===----------------------------------------------------------------------===//
1321308Sache
1421308Sache#define DEBUG_TYPE "mccodeemitter"
1521308Sache#include "MCTargetDesc/SystemZMCTargetDesc.h"
1621308Sache#include "MCTargetDesc/SystemZMCFixups.h"
1721308Sache#include "llvm/MC/MCCodeEmitter.h"
1821308Sache#include "llvm/MC/MCContext.h"
1921308Sache#include "llvm/MC/MCExpr.h"
2021308Sache#include "llvm/MC/MCInstrInfo.h"
2121308Sache
2221308Sacheusing namespace llvm;
2321308Sache
2421308Sachenamespace {
2521308Sacheclass SystemZMCCodeEmitter : public MCCodeEmitter {
2621308Sache  const MCInstrInfo &MCII;
2721308Sache  MCContext &Ctx;
2821308Sache
2921308Sachepublic:
3021308Sache  SystemZMCCodeEmitter(const MCInstrInfo &mcii, MCContext &ctx)
3121308Sache    : MCII(mcii), Ctx(ctx) {
3221308Sache  }
3321308Sache
3421308Sache  ~SystemZMCCodeEmitter() {}
3521308Sache
3626497Sache  // OVerride MCCodeEmitter.
3726497Sache  virtual void EncodeInstruction(const MCInst &MI, raw_ostream &OS,
3826497Sache                                 SmallVectorImpl<MCFixup> &Fixups) const
3926497Sache    LLVM_OVERRIDE;
4026497Sache
4126497Sacheprivate:
4221308Sache  // Automatically generated by TableGen.
4321308Sache  uint64_t getBinaryCodeForInstr(const MCInst &MI,
4421308Sache                                 SmallVectorImpl<MCFixup> &Fixups) const;
4521308Sache
4626497Sache  // Called by the TableGen code to get the binary encoding of operand
4726497Sache  // MO in MI.  Fixups is the list of fixups against MI.
4826497Sache  uint64_t getMachineOpValue(const MCInst &MI, const MCOperand &MO,
4926497Sache                             SmallVectorImpl<MCFixup> &Fixups) const;
5021308Sache
5121308Sache  // Called by the TableGen code to get the binary encoding of an address.
5221308Sache  // The index or length, if any, is encoded first, followed by the base,
5321308Sache  // followed by the displacement.  In a 20-bit displacement,
5421308Sache  // the low 12 bits are encoded before the high 8 bits.
5521308Sache  uint64_t getBDAddr12Encoding(const MCInst &MI, unsigned OpNum,
5621308Sache                               SmallVectorImpl<MCFixup> &Fixups) const;
5721308Sache  uint64_t getBDAddr20Encoding(const MCInst &MI, unsigned OpNum,
5821308Sache                               SmallVectorImpl<MCFixup> &Fixups) const;
5921308Sache  uint64_t getBDXAddr12Encoding(const MCInst &MI, unsigned OpNum,
6021308Sache                                SmallVectorImpl<MCFixup> &Fixups) const;
6121308Sache  uint64_t getBDXAddr20Encoding(const MCInst &MI, unsigned OpNum,
6221308Sache                                SmallVectorImpl<MCFixup> &Fixups) const;
6321308Sache  uint64_t getBDLAddr12Len8Encoding(const MCInst &MI, unsigned OpNum,
6421308Sache                                    SmallVectorImpl<MCFixup> &Fixups) const;
6521308Sache
6621308Sache  // Operand OpNum of MI needs a PC-relative fixup of kind Kind at
6721308Sache  // Offset bytes from the start of MI.  Add the fixup to Fixups
6821308Sache  // and return the in-place addend, which since we're a RELA target
6921308Sache  // is always 0.
7021308Sache  uint64_t getPCRelEncoding(const MCInst &MI, unsigned OpNum,
7121308Sache                            SmallVectorImpl<MCFixup> &Fixups,
7221308Sache                            unsigned Kind, int64_t Offset) const;
7321308Sache
7421308Sache  uint64_t getPC16DBLEncoding(const MCInst &MI, unsigned OpNum,
7521308Sache                              SmallVectorImpl<MCFixup> &Fixups) const {
7621308Sache    return getPCRelEncoding(MI, OpNum, Fixups, SystemZ::FK_390_PC16DBL, 2);
7721308Sache  }
7821308Sache  uint64_t getPC32DBLEncoding(const MCInst &MI, unsigned OpNum,
7921308Sache                              SmallVectorImpl<MCFixup> &Fixups) const {
8021308Sache    return getPCRelEncoding(MI, OpNum, Fixups, SystemZ::FK_390_PC32DBL, 2);
8121308Sache  }
8221308Sache};
8321308Sache}
8421308Sache
8521308SacheMCCodeEmitter *llvm::createSystemZMCCodeEmitter(const MCInstrInfo &MCII,
8621308Sache                                                const MCRegisterInfo &MRI,
8721308Sache                                                const MCSubtargetInfo &MCSTI,
8821308Sache                                                MCContext &Ctx) {
8921308Sache  return new SystemZMCCodeEmitter(MCII, Ctx);
9021308Sache}
9121308Sache
9221308Sachevoid SystemZMCCodeEmitter::
9321308SacheEncodeInstruction(const MCInst &MI, raw_ostream &OS,
9421308Sache                  SmallVectorImpl<MCFixup> &Fixups) const {
9521308Sache  uint64_t Bits = getBinaryCodeForInstr(MI, Fixups);
9621308Sache  unsigned Size = MCII.get(MI.getOpcode()).getSize();
9721308Sache  // Big-endian insertion of Size bytes.
9821308Sache  unsigned ShiftValue = (Size * 8) - 8;
9921308Sache  for (unsigned I = 0; I != Size; ++I) {
10021308Sache    OS << uint8_t(Bits >> ShiftValue);
10121308Sache    ShiftValue -= 8;
10221308Sache  }
10321308Sache}
10421308Sache
10521308Sacheuint64_t SystemZMCCodeEmitter::
10621308SachegetMachineOpValue(const MCInst &MI, const MCOperand &MO,
10721308Sache                  SmallVectorImpl<MCFixup> &Fixups) const {
10821308Sache  if (MO.isReg())
10921308Sache    return Ctx.getRegisterInfo()->getEncodingValue(MO.getReg());
11021308Sache  if (MO.isImm())
11121308Sache    return static_cast<uint64_t>(MO.getImm());
11221308Sache  llvm_unreachable("Unexpected operand type!");
11321308Sache}
11421308Sache
11521308Sacheuint64_t SystemZMCCodeEmitter::
11621308SachegetBDAddr12Encoding(const MCInst &MI, unsigned OpNum,
11721308Sache                    SmallVectorImpl<MCFixup> &Fixups) const {
11821308Sache  uint64_t Base = getMachineOpValue(MI, MI.getOperand(OpNum), Fixups);
11921308Sache  uint64_t Disp = getMachineOpValue(MI, MI.getOperand(OpNum + 1), Fixups);
12021308Sache  assert(isUInt<4>(Base) && isUInt<12>(Disp));
12121308Sache  return (Base << 12) | Disp;
12221308Sache}
12321308Sache
12421308Sacheuint64_t SystemZMCCodeEmitter::
12521308SachegetBDAddr20Encoding(const MCInst &MI, unsigned OpNum,
12621308Sache                    SmallVectorImpl<MCFixup> &Fixups) const {
12721308Sache  uint64_t Base = getMachineOpValue(MI, MI.getOperand(OpNum), Fixups);
12821308Sache  uint64_t Disp = getMachineOpValue(MI, MI.getOperand(OpNum + 1), Fixups);
12921308Sache  assert(isUInt<4>(Base) && isInt<20>(Disp));
13021308Sache  return (Base << 20) | ((Disp & 0xfff) << 8) | ((Disp & 0xff000) >> 12);
13121308Sache}
13221308Sache
13321308Sacheuint64_t SystemZMCCodeEmitter::
13421308SachegetBDXAddr12Encoding(const MCInst &MI, unsigned OpNum,
13521308Sache                     SmallVectorImpl<MCFixup> &Fixups) const {
13621308Sache  uint64_t Base = getMachineOpValue(MI, MI.getOperand(OpNum), Fixups);
13721308Sache  uint64_t Disp = getMachineOpValue(MI, MI.getOperand(OpNum + 1), Fixups);
13821308Sache  uint64_t Index = getMachineOpValue(MI, MI.getOperand(OpNum + 2), Fixups);
13921308Sache  assert(isUInt<4>(Base) && isUInt<12>(Disp) && isUInt<4>(Index));
14021308Sache  return (Index << 16) | (Base << 12) | Disp;
14121308Sache}
14221308Sache
14321308Sacheuint64_t SystemZMCCodeEmitter::
14421308SachegetBDXAddr20Encoding(const MCInst &MI, unsigned OpNum,
14521308Sache                     SmallVectorImpl<MCFixup> &Fixups) const {
14621308Sache  uint64_t Base = getMachineOpValue(MI, MI.getOperand(OpNum), Fixups);
14721308Sache  uint64_t Disp = getMachineOpValue(MI, MI.getOperand(OpNum + 1), Fixups);
14821308Sache  uint64_t Index = getMachineOpValue(MI, MI.getOperand(OpNum + 2), Fixups);
14921308Sache  assert(isUInt<4>(Base) && isInt<20>(Disp) && isUInt<4>(Index));
15021308Sache  return (Index << 24) | (Base << 20) | ((Disp & 0xfff) << 8)
15121308Sache    | ((Disp & 0xff000) >> 12);
15221308Sache}
15321308Sache
15421308Sacheuint64_t SystemZMCCodeEmitter::
15521308SachegetBDLAddr12Len8Encoding(const MCInst &MI, unsigned OpNum,
15621308Sache                         SmallVectorImpl<MCFixup> &Fixups) const {
15721308Sache  uint64_t Base = getMachineOpValue(MI, MI.getOperand(OpNum), Fixups);
15821308Sache  uint64_t Disp = getMachineOpValue(MI, MI.getOperand(OpNum + 1), Fixups);
15921308Sache  uint64_t Len  = getMachineOpValue(MI, MI.getOperand(OpNum + 2), Fixups) - 1;
16021308Sache  assert(isUInt<4>(Base) && isUInt<12>(Disp) && isUInt<8>(Len));
16121308Sache  return (Len << 16) | (Base << 12) | Disp;
16221308Sache}
16321308Sache
16421308Sacheuint64_t
16521308SacheSystemZMCCodeEmitter::getPCRelEncoding(const MCInst &MI, unsigned OpNum,
16621308Sache                                       SmallVectorImpl<MCFixup> &Fixups,
16721308Sache                                       unsigned Kind, int64_t Offset) const {
16821308Sache  const MCOperand &MO = MI.getOperand(OpNum);
16921308Sache  const MCExpr *Expr;
17021308Sache  if (MO.isImm())
17121308Sache    Expr = MCConstantExpr::Create(MO.getImm() + Offset, Ctx);
17221308Sache  else {
17321308Sache    Expr = MO.getExpr();
17421308Sache    if (Offset) {
17521308Sache      // The operand value is relative to the start of MI, but the fixup
17621308Sache      // is relative to the operand field itself, which is Offset bytes
17721308Sache      // into MI.  Add Offset to the relocation value to cancel out
17821308Sache      // this difference.
17921308Sache      const MCExpr *OffsetExpr = MCConstantExpr::Create(Offset, Ctx);
18021308Sache      Expr = MCBinaryExpr::CreateAdd(Expr, OffsetExpr, Ctx);
18121308Sache    }
18221308Sache  }
18321308Sache  Fixups.push_back(MCFixup::Create(Offset, Expr, (MCFixupKind)Kind));
18421308Sache  return 0;
18521308Sache}
18621308Sache
18721308Sache#include "SystemZGenMCCodeEmitter.inc"
18821308Sache