ARM64MCCodeEmitter.cpp [plain text]
#define DEBUG_TYPE "mccodeemitter"
#include "MCTargetDesc/ARM64AddressingModes.h"
#include "MCTargetDesc/ARM64BaseInfo.h"
#include "MCTargetDesc/ARM64FixupKinds.h"
#include "MCTargetDesc/ARM64MCExpr.h"
#include "llvm/MC/MCCodeEmitter.h"
#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCInst.h"
#include "llvm/MC/MCInstrInfo.h"
#include "llvm/MC/MCRegisterInfo.h"
#include "llvm/MC/MCSubtargetInfo.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/Support/raw_ostream.h"
using namespace llvm;
STATISTIC(MCNumEmitted, "Number of MC instructions emitted.");
STATISTIC(MCNumFixups, "Number of MC fixups created.");
namespace {
class ARM64MCCodeEmitter : public MCCodeEmitter {
MCContext &Ctx;
ARM64MCCodeEmitter(const ARM64MCCodeEmitter &); void operator=(const ARM64MCCodeEmitter &); public:
ARM64MCCodeEmitter(const MCInstrInfo &mcii, const MCSubtargetInfo &sti,
MCContext &ctx) : Ctx(ctx) {
}
~ARM64MCCodeEmitter() {}
uint64_t getBinaryCodeForInstr(const MCInst &MI,
SmallVectorImpl<MCFixup> &Fixups) const;
unsigned getMachineOpValue(const MCInst &MI,const MCOperand &MO,
SmallVectorImpl<MCFixup> &Fixups) const;
template<uint32_t FixupKind>
uint32_t getAMIndexed8OpValue(const MCInst &MI, unsigned OpIdx,
SmallVectorImpl<MCFixup> &Fixups) const;
uint32_t getAdrLabelOpValue(const MCInst &MI, unsigned OpIdx,
SmallVectorImpl<MCFixup> &Fixups) const;
uint32_t getAddSubImmOpValue(const MCInst &MI, unsigned OpIdx,
SmallVectorImpl<MCFixup> &) const;
uint32_t getCondBranchTargetOpValue(const MCInst &MI, unsigned OpIdx,
SmallVectorImpl<MCFixup> &) const;
uint32_t getTestBranchTargetOpValue(const MCInst &MI, unsigned OpIdx,
SmallVectorImpl<MCFixup> &) const;
uint32_t getBranchTargetOpValue(const MCInst &MI, unsigned OpIdx,
SmallVectorImpl<MCFixup> &) const;
uint32_t getMoveWideImmOpValue(const MCInst &MI, unsigned OpIdx,
SmallVectorImpl<MCFixup> &Fixups) const;
uint32_t getVecShifterOpValue(const MCInst &MI, unsigned OpIdx,
SmallVectorImpl<MCFixup> &Fixups) const;
uint32_t getMoveVecShifterOpValue(const MCInst &MI, unsigned OpIdx,
SmallVectorImpl<MCFixup> &Fixups) const;
uint32_t getFixedPointScaleOpValue(const MCInst &MI, unsigned OpIdx,
SmallVectorImpl<MCFixup> &Fixups) const;
uint32_t getVecShiftR64OpValue(const MCInst &MI, unsigned OpIdx,
SmallVectorImpl<MCFixup> &Fixups) const;
uint32_t getVecShiftR32OpValue(const MCInst &MI, unsigned OpIdx,
SmallVectorImpl<MCFixup> &Fixups) const;
uint32_t getVecShiftR16OpValue(const MCInst &MI, unsigned OpIdx,
SmallVectorImpl<MCFixup> &Fixups) const;
uint32_t getVecShiftR8OpValue(const MCInst &MI, unsigned OpIdx,
SmallVectorImpl<MCFixup> &Fixups) const;
uint32_t getVecShiftL64OpValue(const MCInst &MI, unsigned OpIdx,
SmallVectorImpl<MCFixup> &Fixups) const;
uint32_t getVecShiftL32OpValue(const MCInst &MI, unsigned OpIdx,
SmallVectorImpl<MCFixup> &Fixups) const;
uint32_t getVecShiftL16OpValue(const MCInst &MI, unsigned OpIdx,
SmallVectorImpl<MCFixup> &Fixups) const;
uint32_t getVecShiftL8OpValue(const MCInst &MI, unsigned OpIdx,
SmallVectorImpl<MCFixup> &Fixups) const;
uint32_t getSIMDShift64OpValue(const MCInst &MI, unsigned OpIdx,
SmallVectorImpl<MCFixup> &Fixups) const;
uint32_t getSIMDShift64_32OpValue(const MCInst &MI, unsigned OpIdx,
SmallVectorImpl<MCFixup> &Fixups) const;
uint32_t getSIMDShift32OpValue(const MCInst &MI, unsigned OpIdx,
SmallVectorImpl<MCFixup> &Fixups) const;
uint32_t getSIMDShift16OpValue(const MCInst &MI, unsigned OpIdx,
SmallVectorImpl<MCFixup> &Fixups) const;
unsigned fixMOVZ(const MCInst &MI, unsigned EncodedValue) const;
void EmitByte(unsigned char C, raw_ostream &OS) const {
OS << (char)C;
}
void EmitConstant(uint64_t Val, unsigned Size, raw_ostream &OS) const {
for (unsigned i = 0; i != Size; ++i) {
EmitByte(Val & 255, OS);
Val >>= 8;
}
}
void EncodeInstruction(const MCInst &MI, raw_ostream &OS,
SmallVectorImpl<MCFixup> &Fixups) const;
};
}
MCCodeEmitter *llvm::createARM64MCCodeEmitter(const MCInstrInfo &MCII,
const MCRegisterInfo &MRI,
const MCSubtargetInfo &STI,
MCContext &Ctx) {
return new ARM64MCCodeEmitter(MCII, STI, Ctx);
}
unsigned ARM64MCCodeEmitter::
getMachineOpValue(const MCInst &MI, const MCOperand &MO,
SmallVectorImpl<MCFixup> &Fixups) const {
if (MO.isReg())
return Ctx.getRegisterInfo()->getEncodingValue(MO.getReg());
else {
assert(MO.isImm() && "did not expect relocated expression");
return static_cast<unsigned>(MO.getImm());
}
assert (0 && "Unable to encode MCOperand!");
return 0;
}
template<uint32_t FixupKind> uint32_t
ARM64MCCodeEmitter::getAMIndexed8OpValue(const MCInst &MI, unsigned OpIdx,
SmallVectorImpl<MCFixup> &Fixups) const {
unsigned BaseReg = MI.getOperand(OpIdx).getReg();
BaseReg = Ctx.getRegisterInfo()->getEncodingValue(BaseReg);
const MCOperand &MO = MI.getOperand(OpIdx+1);
uint32_t ImmVal = 0;
if (MO.isImm())
ImmVal = static_cast<uint32_t>(MO.getImm());
else {
assert(MO.isExpr() && "unable to encode load/store imm operand");
MCFixupKind Kind = MCFixupKind(FixupKind);
Fixups.push_back(MCFixup::Create(0, MO.getExpr(), Kind, MI.getLoc()));
++MCNumFixups;
}
return BaseReg | (ImmVal << 5);
}
uint32_t ARM64MCCodeEmitter::
getAdrLabelOpValue(const MCInst &MI, unsigned OpIdx,
SmallVectorImpl<MCFixup> &Fixups) const {
const MCOperand &MO = MI.getOperand(OpIdx);
if (MO.isImm()) return MO.getImm();
assert(MO.isExpr() && "Unexpected ADR target type!");
const MCExpr *Expr = MO.getExpr();
MCFixupKind Kind = MI.getOpcode() == ARM64::ADR ?
MCFixupKind(ARM64::fixup_arm64_pcrel_adr_imm21) :
MCFixupKind(ARM64::fixup_arm64_pcrel_adrp_imm21);
Fixups.push_back(MCFixup::Create(0, Expr, Kind, MI.getLoc()));
MCNumFixups += 1;
return 0;
}
uint32_t ARM64MCCodeEmitter::
getAddSubImmOpValue(const MCInst &MI, unsigned OpIdx,
SmallVectorImpl<MCFixup> &Fixups) const {
const MCOperand &MO = MI.getOperand(OpIdx);
const MCOperand &MO1 = MI.getOperand(OpIdx + 1);
assert(ARM64_AM::getShiftType(MO1.getImm()) == ARM64_AM::LSL &&
"unexpected shift type for add/sub immediate");
unsigned ShiftVal = ARM64_AM::getShiftValue(MO1.getImm());
assert((ShiftVal == 0 || ShiftVal == 12) &&
"unexpected shift value for add/sub immediate");
if (MO.isImm())
return MO.getImm() | (ShiftVal == 0 ? 0 : (1 << 12));
assert(MO.isExpr() && "Unable to encode MCOperand!");
const MCExpr *Expr = MO.getExpr();
assert(ShiftVal == 0 && "shift not allowed on add/sub immediate with fixup");
MCFixupKind Kind = MCFixupKind(ARM64::fixup_arm64_add_imm12);
Fixups.push_back(MCFixup::Create(0, Expr, Kind, MI.getLoc()));
++MCNumFixups;
return 0;
}
uint32_t ARM64MCCodeEmitter::
getCondBranchTargetOpValue(const MCInst &MI, unsigned OpIdx,
SmallVectorImpl<MCFixup> &Fixups) const {
const MCOperand &MO = MI.getOperand(OpIdx);
if (MO.isImm()) return MO.getImm();
assert(MO.isExpr() && "Unexpected target type!");
MCFixupKind Kind = MCFixupKind(ARM64::fixup_arm64_pcrel_imm19);
Fixups.push_back(MCFixup::Create(0, MO.getExpr(), Kind, MI.getLoc()));
++MCNumFixups;
return 0;
}
uint32_t ARM64MCCodeEmitter::
getMoveWideImmOpValue(const MCInst &MI, unsigned OpIdx,
SmallVectorImpl<MCFixup> &Fixups) const {
const MCOperand &MO = MI.getOperand(OpIdx);
if (MO.isImm()) return MO.getImm();
assert(MO.isExpr() && "Unexpected movz/movk immediate");
Fixups.push_back(MCFixup::Create(
0, MO.getExpr(), MCFixupKind(ARM64::fixup_arm64_movw), MI.getLoc()));
++MCNumFixups;
return 0;
}
uint32_t ARM64MCCodeEmitter::
getTestBranchTargetOpValue(const MCInst &MI, unsigned OpIdx,
SmallVectorImpl<MCFixup> &Fixups) const {
const MCOperand &MO = MI.getOperand(OpIdx);
if (MO.isImm()) return MO.getImm();
assert(MO.isExpr() && "Unexpected ADR target type!");
MCFixupKind Kind = MCFixupKind(ARM64::fixup_arm64_pcrel_branch14);
Fixups.push_back(MCFixup::Create(0, MO.getExpr(), Kind, MI.getLoc()));
++MCNumFixups;
return 0;
}
uint32_t ARM64MCCodeEmitter::
getBranchTargetOpValue(const MCInst &MI, unsigned OpIdx,
SmallVectorImpl<MCFixup> &Fixups) const {
const MCOperand &MO = MI.getOperand(OpIdx);
if (MO.isImm()) return MO.getImm();
assert(MO.isExpr() && "Unexpected ADR target type!");
MCFixupKind Kind = MI.getOpcode() == ARM64::BL ?
MCFixupKind(ARM64::fixup_arm64_pcrel_call26) :
MCFixupKind(ARM64::fixup_arm64_pcrel_branch26);
Fixups.push_back(MCFixup::Create(0, MO.getExpr(), Kind, MI.getLoc()));
++MCNumFixups;
return 0;
}
uint32_t ARM64MCCodeEmitter::
getVecShifterOpValue(const MCInst &MI, unsigned OpIdx,
SmallVectorImpl<MCFixup> &Fixups) const {
const MCOperand &MO = MI.getOperand(OpIdx);
assert(MO.isImm() && "Expected an immediate value for the shift amount!");
switch (MO.getImm()) {
default: break;
case 0: return 0;
case 8: return 1;
case 16: return 2;
case 24: return 3;
}
assert(false && "Invalid value for vector shift amount!");
return 0;
}
uint32_t ARM64MCCodeEmitter::
getSIMDShift64OpValue(const MCInst &MI, unsigned OpIdx,
SmallVectorImpl<MCFixup> &Fixups) const {
const MCOperand &MO = MI.getOperand(OpIdx);
assert(MO.isImm() && "Expected an immediate value for the shift amount!");
return 64 - (MO.getImm());
}
uint32_t ARM64MCCodeEmitter::
getSIMDShift64_32OpValue(const MCInst &MI, unsigned OpIdx,
SmallVectorImpl<MCFixup> &Fixups) const {
const MCOperand &MO = MI.getOperand(OpIdx);
assert(MO.isImm() && "Expected an immediate value for the shift amount!");
return 64 - (MO.getImm() | 32);
}
uint32_t ARM64MCCodeEmitter::
getSIMDShift32OpValue(const MCInst &MI, unsigned OpIdx,
SmallVectorImpl<MCFixup> &Fixups) const {
const MCOperand &MO = MI.getOperand(OpIdx);
assert(MO.isImm() && "Expected an immediate value for the shift amount!");
return 32 - (MO.getImm() | 16);
}
uint32_t ARM64MCCodeEmitter::
getSIMDShift16OpValue(const MCInst &MI, unsigned OpIdx,
SmallVectorImpl<MCFixup> &Fixups) const {
const MCOperand &MO = MI.getOperand(OpIdx);
assert(MO.isImm() && "Expected an immediate value for the shift amount!");
return 16 - (MO.getImm() | 8);
}
uint32_t ARM64MCCodeEmitter::
getFixedPointScaleOpValue(const MCInst &MI, unsigned OpIdx,
SmallVectorImpl<MCFixup> &Fixups) const {
const MCOperand &MO = MI.getOperand(OpIdx);
assert(MO.isImm() && "Expected an immediate value for the scale amount!");
return 64 - MO.getImm();
}
uint32_t ARM64MCCodeEmitter::
getVecShiftR64OpValue(const MCInst &MI, unsigned OpIdx,
SmallVectorImpl<MCFixup> &Fixups) const {
const MCOperand &MO = MI.getOperand(OpIdx);
assert(MO.isImm() && "Expected an immediate value for the scale amount!");
return 64 - MO.getImm();
}
uint32_t ARM64MCCodeEmitter::
getVecShiftR32OpValue(const MCInst &MI, unsigned OpIdx,
SmallVectorImpl<MCFixup> &Fixups) const {
const MCOperand &MO = MI.getOperand(OpIdx);
assert(MO.isImm() && "Expected an immediate value for the scale amount!");
return 32 - MO.getImm();
}
uint32_t ARM64MCCodeEmitter::
getVecShiftR16OpValue(const MCInst &MI, unsigned OpIdx,
SmallVectorImpl<MCFixup> &Fixups) const {
const MCOperand &MO = MI.getOperand(OpIdx);
assert(MO.isImm() && "Expected an immediate value for the scale amount!");
return 16 - MO.getImm();
}
uint32_t ARM64MCCodeEmitter::
getVecShiftR8OpValue(const MCInst &MI, unsigned OpIdx,
SmallVectorImpl<MCFixup> &Fixups) const {
const MCOperand &MO = MI.getOperand(OpIdx);
assert(MO.isImm() && "Expected an immediate value for the scale amount!");
return 8 - MO.getImm();
}
uint32_t ARM64MCCodeEmitter::
getVecShiftL64OpValue(const MCInst &MI, unsigned OpIdx,
SmallVectorImpl<MCFixup> &Fixups) const {
const MCOperand &MO = MI.getOperand(OpIdx);
assert(MO.isImm() && "Expected an immediate value for the scale amount!");
return MO.getImm() - 64;
}
uint32_t ARM64MCCodeEmitter::
getVecShiftL32OpValue(const MCInst &MI, unsigned OpIdx,
SmallVectorImpl<MCFixup> &Fixups) const {
const MCOperand &MO = MI.getOperand(OpIdx);
assert(MO.isImm() && "Expected an immediate value for the scale amount!");
return MO.getImm() - 32;
}
uint32_t ARM64MCCodeEmitter::
getVecShiftL16OpValue(const MCInst &MI, unsigned OpIdx,
SmallVectorImpl<MCFixup> &Fixups) const {
const MCOperand &MO = MI.getOperand(OpIdx);
assert(MO.isImm() && "Expected an immediate value for the scale amount!");
return MO.getImm() - 16;
}
uint32_t ARM64MCCodeEmitter::
getVecShiftL8OpValue(const MCInst &MI, unsigned OpIdx,
SmallVectorImpl<MCFixup> &Fixups) const {
const MCOperand &MO = MI.getOperand(OpIdx);
assert(MO.isImm() && "Expected an immediate value for the scale amount!");
return MO.getImm() - 8;
}
uint32_t ARM64MCCodeEmitter::
getMoveVecShifterOpValue(const MCInst &MI, unsigned OpIdx,
SmallVectorImpl<MCFixup> &Fixups) const {
const MCOperand &MO = MI.getOperand(OpIdx);
assert(MO.isImm() &&"Expected an immediate value for the move shift amount!");
unsigned ShiftVal = ARM64_AM::getShiftValue(MO.getImm());
assert((ShiftVal == 8 || ShiftVal == 16) && "Invalid shift amount!");
return ShiftVal == 8 ? 0 : 1;
}
unsigned
ARM64MCCodeEmitter::fixMOVZ(const MCInst &MI, unsigned EncodedValue) const {
MCOperand UImm16MO = MI.getOperand(1);
if (UImm16MO.isImm())
return EncodedValue;
return EncodedValue & ~(1u << 30);
}
void ARM64MCCodeEmitter::
EncodeInstruction(const MCInst &MI, raw_ostream &OS,
SmallVectorImpl<MCFixup> &Fixups) const {
if (MI.getOpcode() == ARM64::TLSDESCCALL) {
MCFixupKind Fixup = MCFixupKind(ARM64::fixup_arm64_tlsdesc_call);
Fixups.push_back(MCFixup::Create(0, MI.getOperand(0).getExpr(), Fixup));
return;
}
uint64_t Binary = getBinaryCodeForInstr(MI, Fixups);
EmitConstant(Binary, 4, OS);
++MCNumEmitted; }
#include "ARM64GenMCCodeEmitter.inc"