forked from OSchip/llvm-project
132 lines
4.9 KiB
C++
132 lines
4.9 KiB
C++
|
//===-- SystemZMCCodeEmitter.cpp - Convert SystemZ code to machine code ---===//
|
||
|
//
|
||
|
// The LLVM Compiler Infrastructure
|
||
|
//
|
||
|
// This file is distributed under the University of Illinois Open Source
|
||
|
// License. See LICENSE.TXT for details.
|
||
|
//
|
||
|
//===----------------------------------------------------------------------===//
|
||
|
//
|
||
|
// This file implements the SystemZMCCodeEmitter class.
|
||
|
//
|
||
|
//===----------------------------------------------------------------------===//
|
||
|
|
||
|
#define DEBUG_TYPE "mccodeemitter"
|
||
|
#include "MCTargetDesc/SystemZMCTargetDesc.h"
|
||
|
#include "MCTargetDesc/SystemZMCFixups.h"
|
||
|
#include "llvm/MC/MCCodeEmitter.h"
|
||
|
#include "llvm/MC/MCContext.h"
|
||
|
#include "llvm/MC/MCExpr.h"
|
||
|
#include "llvm/MC/MCInstrInfo.h"
|
||
|
|
||
|
using namespace llvm;
|
||
|
|
||
|
namespace {
|
||
|
class SystemZMCCodeEmitter : public MCCodeEmitter {
|
||
|
const MCInstrInfo &MCII;
|
||
|
MCContext &Ctx;
|
||
|
|
||
|
public:
|
||
|
SystemZMCCodeEmitter(const MCInstrInfo &mcii, MCContext &ctx)
|
||
|
: MCII(mcii), Ctx(ctx) {
|
||
|
}
|
||
|
|
||
|
~SystemZMCCodeEmitter() {}
|
||
|
|
||
|
// OVerride MCCodeEmitter.
|
||
|
virtual void EncodeInstruction(const MCInst &MI, raw_ostream &OS,
|
||
|
SmallVectorImpl<MCFixup> &Fixups) const
|
||
|
LLVM_OVERRIDE;
|
||
|
|
||
|
private:
|
||
|
// Automatically generated by TableGen.
|
||
|
uint64_t getBinaryCodeForInstr(const MCInst &MI,
|
||
|
SmallVectorImpl<MCFixup> &Fixups) const;
|
||
|
|
||
|
// Called by the TableGen code to get the binary encoding of operand
|
||
|
// MO in MI. Fixups is the list of fixups against MI.
|
||
|
unsigned getMachineOpValue(const MCInst &MI, const MCOperand &MO,
|
||
|
SmallVectorImpl<MCFixup> &Fixups) const;
|
||
|
|
||
|
// Operand OpNum of MI needs a PC-relative fixup of kind Kind at
|
||
|
// Offset bytes from the start of MI. Add the fixup to Fixups
|
||
|
// and return the in-place addend, which since we're a RELA target
|
||
|
// is always 0.
|
||
|
unsigned getPCRelEncoding(const MCInst &MI, unsigned int OpNum,
|
||
|
SmallVectorImpl<MCFixup> &Fixups,
|
||
|
unsigned Kind, int64_t Offset) const;
|
||
|
|
||
|
unsigned getPC16DBLEncoding(const MCInst &MI, unsigned int OpNum,
|
||
|
SmallVectorImpl<MCFixup> &Fixups) const {
|
||
|
return getPCRelEncoding(MI, OpNum, Fixups, SystemZ::FK_390_PC16DBL, 2);
|
||
|
}
|
||
|
unsigned getPC32DBLEncoding(const MCInst &MI, unsigned int OpNum,
|
||
|
SmallVectorImpl<MCFixup> &Fixups) const {
|
||
|
return getPCRelEncoding(MI, OpNum, Fixups, SystemZ::FK_390_PC32DBL, 2);
|
||
|
}
|
||
|
unsigned getPLT16DBLEncoding(const MCInst &MI, unsigned int OpNum,
|
||
|
SmallVectorImpl<MCFixup> &Fixups) const {
|
||
|
return getPCRelEncoding(MI, OpNum, Fixups, SystemZ::FK_390_PLT16DBL, 2);
|
||
|
}
|
||
|
unsigned getPLT32DBLEncoding(const MCInst &MI, unsigned int OpNum,
|
||
|
SmallVectorImpl<MCFixup> &Fixups) const {
|
||
|
return getPCRelEncoding(MI, OpNum, Fixups, SystemZ::FK_390_PLT32DBL, 2);
|
||
|
}
|
||
|
};
|
||
|
}
|
||
|
|
||
|
MCCodeEmitter *llvm::createSystemZMCCodeEmitter(const MCInstrInfo &MCII,
|
||
|
const MCRegisterInfo &MRI,
|
||
|
const MCSubtargetInfo &MCSTI,
|
||
|
MCContext &Ctx) {
|
||
|
return new SystemZMCCodeEmitter(MCII, Ctx);
|
||
|
}
|
||
|
|
||
|
void SystemZMCCodeEmitter::
|
||
|
EncodeInstruction(const MCInst &MI, raw_ostream &OS,
|
||
|
SmallVectorImpl<MCFixup> &Fixups) const {
|
||
|
uint64_t Bits = getBinaryCodeForInstr(MI, Fixups);
|
||
|
unsigned Size = MCII.get(MI.getOpcode()).getSize();
|
||
|
// Big-endian insertion of Size bytes.
|
||
|
unsigned ShiftValue = (Size * 8) - 8;
|
||
|
for (unsigned I = 0; I != Size; ++I) {
|
||
|
OS << uint8_t(Bits >> ShiftValue);
|
||
|
ShiftValue -= 8;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
unsigned SystemZMCCodeEmitter::
|
||
|
getMachineOpValue(const MCInst &MI, const MCOperand &MO,
|
||
|
SmallVectorImpl<MCFixup> &Fixups) const {
|
||
|
if (MO.isReg())
|
||
|
return Ctx.getRegisterInfo().getEncodingValue(MO.getReg());
|
||
|
if (MO.isImm())
|
||
|
return static_cast<unsigned>(MO.getImm());
|
||
|
llvm_unreachable("Unexpected operand type!");
|
||
|
}
|
||
|
|
||
|
unsigned
|
||
|
SystemZMCCodeEmitter::getPCRelEncoding(const MCInst &MI, unsigned int OpNum,
|
||
|
SmallVectorImpl<MCFixup> &Fixups,
|
||
|
unsigned Kind, int64_t Offset) const {
|
||
|
const MCOperand &MO = MI.getOperand(OpNum);
|
||
|
// For compatibility with the GNU assembler, treat constant operands as
|
||
|
// unadjusted PC-relative offsets.
|
||
|
if (MO.isImm())
|
||
|
return MO.getImm() / 2;
|
||
|
|
||
|
const MCExpr *Expr = MO.getExpr();
|
||
|
if (Offset) {
|
||
|
// The operand value is relative to the start of MI, but the fixup
|
||
|
// is relative to the operand field itself, which is Offset bytes
|
||
|
// into MI. Add Offset to the relocation value to cancel out
|
||
|
// this difference.
|
||
|
const MCExpr *OffsetExpr = MCConstantExpr::Create(Offset, Ctx);
|
||
|
Expr = MCBinaryExpr::CreateAdd(Expr, OffsetExpr, Ctx);
|
||
|
}
|
||
|
Fixups.push_back(MCFixup::Create(Offset, Expr, (MCFixupKind)Kind));
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
#include "SystemZGenMCCodeEmitter.inc"
|