1251607Sdim//===-- SystemZMCCodeEmitter.cpp - Convert SystemZ code to machine code ---===// 2251607Sdim// 3251607Sdim// The LLVM Compiler Infrastructure 4251607Sdim// 5251607Sdim// This file is distributed under the University of Illinois Open Source 6251607Sdim// License. See LICENSE.TXT for details. 7251607Sdim// 8251607Sdim//===----------------------------------------------------------------------===// 9251607Sdim// 10251607Sdim// This file implements the SystemZMCCodeEmitter class. 11251607Sdim// 12251607Sdim//===----------------------------------------------------------------------===// 13251607Sdim 14251607Sdim#define DEBUG_TYPE "mccodeemitter" 15251607Sdim#include "MCTargetDesc/SystemZMCTargetDesc.h" 16251607Sdim#include "MCTargetDesc/SystemZMCFixups.h" 17251607Sdim#include "llvm/MC/MCCodeEmitter.h" 18251607Sdim#include "llvm/MC/MCContext.h" 19251607Sdim#include "llvm/MC/MCExpr.h" 20251607Sdim#include "llvm/MC/MCInstrInfo.h" 21251607Sdim 22251607Sdimusing namespace llvm; 23251607Sdim 24251607Sdimnamespace { 25251607Sdimclass SystemZMCCodeEmitter : public MCCodeEmitter { 26251607Sdim const MCInstrInfo &MCII; 27251607Sdim MCContext &Ctx; 28251607Sdim 29251607Sdimpublic: 30251607Sdim SystemZMCCodeEmitter(const MCInstrInfo &mcii, MCContext &ctx) 31251607Sdim : MCII(mcii), Ctx(ctx) { 32251607Sdim } 33251607Sdim 34251607Sdim ~SystemZMCCodeEmitter() {} 35251607Sdim 36251607Sdim // OVerride MCCodeEmitter. 37251607Sdim virtual void EncodeInstruction(const MCInst &MI, raw_ostream &OS, 38251607Sdim SmallVectorImpl<MCFixup> &Fixups) const 39251607Sdim LLVM_OVERRIDE; 40251607Sdim 41251607Sdimprivate: 42251607Sdim // Automatically generated by TableGen. 43251607Sdim uint64_t getBinaryCodeForInstr(const MCInst &MI, 44251607Sdim SmallVectorImpl<MCFixup> &Fixups) const; 45251607Sdim 46251607Sdim // Called by the TableGen code to get the binary encoding of operand 47251607Sdim // MO in MI. Fixups is the list of fixups against MI. 48263508Sdim uint64_t getMachineOpValue(const MCInst &MI, const MCOperand &MO, 49251607Sdim SmallVectorImpl<MCFixup> &Fixups) const; 50251607Sdim 51263508Sdim // Called by the TableGen code to get the binary encoding of an address. 52263508Sdim // The index or length, if any, is encoded first, followed by the base, 53263508Sdim // followed by the displacement. In a 20-bit displacement, 54263508Sdim // the low 12 bits are encoded before the high 8 bits. 55263508Sdim uint64_t getBDAddr12Encoding(const MCInst &MI, unsigned OpNum, 56263508Sdim SmallVectorImpl<MCFixup> &Fixups) const; 57263508Sdim uint64_t getBDAddr20Encoding(const MCInst &MI, unsigned OpNum, 58263508Sdim SmallVectorImpl<MCFixup> &Fixups) const; 59263508Sdim uint64_t getBDXAddr12Encoding(const MCInst &MI, unsigned OpNum, 60263508Sdim SmallVectorImpl<MCFixup> &Fixups) const; 61263508Sdim uint64_t getBDXAddr20Encoding(const MCInst &MI, unsigned OpNum, 62263508Sdim SmallVectorImpl<MCFixup> &Fixups) const; 63263508Sdim uint64_t getBDLAddr12Len8Encoding(const MCInst &MI, unsigned OpNum, 64263508Sdim SmallVectorImpl<MCFixup> &Fixups) const; 65263508Sdim 66251607Sdim // Operand OpNum of MI needs a PC-relative fixup of kind Kind at 67251607Sdim // Offset bytes from the start of MI. Add the fixup to Fixups 68251607Sdim // and return the in-place addend, which since we're a RELA target 69251607Sdim // is always 0. 70263508Sdim uint64_t getPCRelEncoding(const MCInst &MI, unsigned OpNum, 71251607Sdim SmallVectorImpl<MCFixup> &Fixups, 72251607Sdim unsigned Kind, int64_t Offset) const; 73251607Sdim 74263508Sdim uint64_t getPC16DBLEncoding(const MCInst &MI, unsigned OpNum, 75251607Sdim SmallVectorImpl<MCFixup> &Fixups) const { 76251607Sdim return getPCRelEncoding(MI, OpNum, Fixups, SystemZ::FK_390_PC16DBL, 2); 77251607Sdim } 78263508Sdim uint64_t getPC32DBLEncoding(const MCInst &MI, unsigned OpNum, 79251607Sdim SmallVectorImpl<MCFixup> &Fixups) const { 80251607Sdim return getPCRelEncoding(MI, OpNum, Fixups, SystemZ::FK_390_PC32DBL, 2); 81251607Sdim } 82251607Sdim}; 83251607Sdim} 84251607Sdim 85251607SdimMCCodeEmitter *llvm::createSystemZMCCodeEmitter(const MCInstrInfo &MCII, 86251607Sdim const MCRegisterInfo &MRI, 87251607Sdim const MCSubtargetInfo &MCSTI, 88251607Sdim MCContext &Ctx) { 89251607Sdim return new SystemZMCCodeEmitter(MCII, Ctx); 90251607Sdim} 91251607Sdim 92251607Sdimvoid SystemZMCCodeEmitter:: 93251607SdimEncodeInstruction(const MCInst &MI, raw_ostream &OS, 94251607Sdim SmallVectorImpl<MCFixup> &Fixups) const { 95251607Sdim uint64_t Bits = getBinaryCodeForInstr(MI, Fixups); 96251607Sdim unsigned Size = MCII.get(MI.getOpcode()).getSize(); 97251607Sdim // Big-endian insertion of Size bytes. 98251607Sdim unsigned ShiftValue = (Size * 8) - 8; 99251607Sdim for (unsigned I = 0; I != Size; ++I) { 100251607Sdim OS << uint8_t(Bits >> ShiftValue); 101251607Sdim ShiftValue -= 8; 102251607Sdim } 103251607Sdim} 104251607Sdim 105263508Sdimuint64_t SystemZMCCodeEmitter:: 106251607SdimgetMachineOpValue(const MCInst &MI, const MCOperand &MO, 107251607Sdim SmallVectorImpl<MCFixup> &Fixups) const { 108251607Sdim if (MO.isReg()) 109263508Sdim return Ctx.getRegisterInfo()->getEncodingValue(MO.getReg()); 110251607Sdim if (MO.isImm()) 111263508Sdim return static_cast<uint64_t>(MO.getImm()); 112251607Sdim llvm_unreachable("Unexpected operand type!"); 113251607Sdim} 114251607Sdim 115263508Sdimuint64_t SystemZMCCodeEmitter:: 116263508SdimgetBDAddr12Encoding(const MCInst &MI, unsigned OpNum, 117263508Sdim SmallVectorImpl<MCFixup> &Fixups) const { 118263508Sdim uint64_t Base = getMachineOpValue(MI, MI.getOperand(OpNum), Fixups); 119263508Sdim uint64_t Disp = getMachineOpValue(MI, MI.getOperand(OpNum + 1), Fixups); 120263508Sdim assert(isUInt<4>(Base) && isUInt<12>(Disp)); 121263508Sdim return (Base << 12) | Disp; 122263508Sdim} 123263508Sdim 124263508Sdimuint64_t SystemZMCCodeEmitter:: 125263508SdimgetBDAddr20Encoding(const MCInst &MI, unsigned OpNum, 126263508Sdim SmallVectorImpl<MCFixup> &Fixups) const { 127263508Sdim uint64_t Base = getMachineOpValue(MI, MI.getOperand(OpNum), Fixups); 128263508Sdim uint64_t Disp = getMachineOpValue(MI, MI.getOperand(OpNum + 1), Fixups); 129263508Sdim assert(isUInt<4>(Base) && isInt<20>(Disp)); 130263508Sdim return (Base << 20) | ((Disp & 0xfff) << 8) | ((Disp & 0xff000) >> 12); 131263508Sdim} 132263508Sdim 133263508Sdimuint64_t SystemZMCCodeEmitter:: 134263508SdimgetBDXAddr12Encoding(const MCInst &MI, unsigned OpNum, 135263508Sdim SmallVectorImpl<MCFixup> &Fixups) const { 136263508Sdim uint64_t Base = getMachineOpValue(MI, MI.getOperand(OpNum), Fixups); 137263508Sdim uint64_t Disp = getMachineOpValue(MI, MI.getOperand(OpNum + 1), Fixups); 138263508Sdim uint64_t Index = getMachineOpValue(MI, MI.getOperand(OpNum + 2), Fixups); 139263508Sdim assert(isUInt<4>(Base) && isUInt<12>(Disp) && isUInt<4>(Index)); 140263508Sdim return (Index << 16) | (Base << 12) | Disp; 141263508Sdim} 142263508Sdim 143263508Sdimuint64_t SystemZMCCodeEmitter:: 144263508SdimgetBDXAddr20Encoding(const MCInst &MI, unsigned OpNum, 145263508Sdim SmallVectorImpl<MCFixup> &Fixups) const { 146263508Sdim uint64_t Base = getMachineOpValue(MI, MI.getOperand(OpNum), Fixups); 147263508Sdim uint64_t Disp = getMachineOpValue(MI, MI.getOperand(OpNum + 1), Fixups); 148263508Sdim uint64_t Index = getMachineOpValue(MI, MI.getOperand(OpNum + 2), Fixups); 149263508Sdim assert(isUInt<4>(Base) && isInt<20>(Disp) && isUInt<4>(Index)); 150263508Sdim return (Index << 24) | (Base << 20) | ((Disp & 0xfff) << 8) 151263508Sdim | ((Disp & 0xff000) >> 12); 152263508Sdim} 153263508Sdim 154263508Sdimuint64_t SystemZMCCodeEmitter:: 155263508SdimgetBDLAddr12Len8Encoding(const MCInst &MI, unsigned OpNum, 156263508Sdim SmallVectorImpl<MCFixup> &Fixups) const { 157263508Sdim uint64_t Base = getMachineOpValue(MI, MI.getOperand(OpNum), Fixups); 158263508Sdim uint64_t Disp = getMachineOpValue(MI, MI.getOperand(OpNum + 1), Fixups); 159263508Sdim uint64_t Len = getMachineOpValue(MI, MI.getOperand(OpNum + 2), Fixups) - 1; 160263508Sdim assert(isUInt<4>(Base) && isUInt<12>(Disp) && isUInt<8>(Len)); 161263508Sdim return (Len << 16) | (Base << 12) | Disp; 162263508Sdim} 163263508Sdim 164263508Sdimuint64_t 165263508SdimSystemZMCCodeEmitter::getPCRelEncoding(const MCInst &MI, unsigned OpNum, 166251607Sdim SmallVectorImpl<MCFixup> &Fixups, 167251607Sdim unsigned Kind, int64_t Offset) const { 168251607Sdim const MCOperand &MO = MI.getOperand(OpNum); 169263508Sdim const MCExpr *Expr; 170251607Sdim if (MO.isImm()) 171263508Sdim Expr = MCConstantExpr::Create(MO.getImm() + Offset, Ctx); 172263508Sdim else { 173263508Sdim Expr = MO.getExpr(); 174263508Sdim if (Offset) { 175263508Sdim // The operand value is relative to the start of MI, but the fixup 176263508Sdim // is relative to the operand field itself, which is Offset bytes 177263508Sdim // into MI. Add Offset to the relocation value to cancel out 178263508Sdim // this difference. 179263508Sdim const MCExpr *OffsetExpr = MCConstantExpr::Create(Offset, Ctx); 180263508Sdim Expr = MCBinaryExpr::CreateAdd(Expr, OffsetExpr, Ctx); 181263508Sdim } 182251607Sdim } 183251607Sdim Fixups.push_back(MCFixup::Create(Offset, Expr, (MCFixupKind)Kind)); 184251607Sdim return 0; 185251607Sdim} 186251607Sdim 187251607Sdim#include "SystemZGenMCCodeEmitter.inc" 188