//===-- ARM/ARMMCCodeEmitter.cpp - Convert ARM 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 ARMMCCodeEmitter class.
//
//===----------------------------------------------------------------------===//
#define DEBUG_TYPE "mccodeemitter"
#include "ARM.h"
#include "ARMAddressingModes.h"
#include "ARMFixupKinds.h"
#include "ARMInstrInfo.h"
#include "llvm/MC/MCCodeEmitter.h"
#include "llvm/MC/MCExpr.h"
#include "llvm/MC/MCInst.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/Support/raw_ostream.h"
using namespace llvm;
STATISTIC(MCNumEmitted, "Number of MC instructions emitted.");
STATISTIC(MCNumCPRelocations, "Number of constant pool relocations created.");
namespace {
class ARMMCCodeEmitter : public MCCodeEmitter {
ARMMCCodeEmitter(const ARMMCCodeEmitter &); // DO NOT IMPLEMENT
void operator=(const ARMMCCodeEmitter &); // DO NOT IMPLEMENT
const TargetMachine &TM;
const TargetInstrInfo &TII;
MCContext &Ctx;
public:
ARMMCCodeEmitter(TargetMachine &tm, MCContext &ctx)
: TM(tm), TII(*TM.getInstrInfo()), Ctx(ctx) {
}
~ARMMCCodeEmitter() {}
unsigned getNumFixupKinds() const { return ARM::NumTargetFixupKinds; }
const MCFixupKindInfo &getFixupKindInfo(MCFixupKind Kind) const {
const static MCFixupKindInfo Infos[] = {
// name offset bits flags
{ "fixup_arm_pcrel_12", 2, 12, MCFixupKindInfo::FKF_IsPCRel },
{ "fixup_arm_vfp_pcrel_12", 3, 8, MCFixupKindInfo::FKF_IsPCRel },
{ "fixup_arm_branch", 1, 24, MCFixupKindInfo::FKF_IsPCRel },
};
if (Kind < FirstTargetFixupKind)
return MCCodeEmitter::getFixupKindInfo(Kind);
assert(unsigned(Kind - FirstTargetFixupKind) < getNumFixupKinds() &&
"Invalid kind!");
return Infos[Kind - FirstTargetFixupKind];
}
unsigned getMachineSoImmOpValue(unsigned SoImm) const;
// getBinaryCodeForInstr - TableGen'erated function for getting the
// binary encoding for an instruction.
unsigned getBinaryCodeForInstr(const MCInst &MI,
SmallVectorImpl<MCFixup> &Fixups) const;
/// getMachineOpValue - Return binary encoding of operand. If the machine
/// operand requires relocation, record the relocation and return zero.
unsigned getMachineOpValue(const MCInst &MI,const MCOperand &MO,
SmallVectorImpl<MCFixup> &Fixups) const;
/// getMovtImmOpValue - Return the encoding for the movw/movt pair
uint32_t getMovtImmOpValue(const MCInst &MI, unsigned OpIdx,
SmallVectorImpl<MCFixup> &Fixups) const;
bool EncodeAddrModeOpValues(const MCInst &MI, unsigned OpIdx,
unsigned &Reg, unsigned &Imm,
SmallVectorImpl<MCFixup> &Fixups) const;
/// getBranchTargetOpValue - Return encoding info for 24-bit immediate
/// branch target.
uint32_t getBranchTargetOpValue(const MCInst &MI, unsigned OpIdx,
SmallVectorImpl<MCFixup> &Fixups) const;
/// getAddrModeImm12OpValue - Return encoding info for 'reg +/- imm12'
/// operand.
uint32_t getAddrModeImm12OpValue(const MCInst &MI, unsigned OpIdx,
SmallVectorImpl<MCFixup> &Fixups) const;
/// getLdStSORegOpValue - Return encoding info for 'reg +/- reg shop imm'
/// operand as needed by load/store instructions.
uint32_t getLdStSORegOpValue(const MCInst &MI, unsigned OpIdx,
SmallVectorImpl<MCFixup> &Fixups) const;
/// getLdStmModeOpValue - Return encoding for load/store multiple mode.
uint32_t getLdStmModeOpValue(const MCInst &MI, unsigned OpIdx,
SmallVectorImpl<MCFixup> &Fixups) const {
ARM_AM::AMSubMode Mode = (ARM_AM::AMSubMode)MI.getOperand(OpIdx).getImm();
switch (Mode) {
default: assert(0 && "Unknown addressing sub-mode!");
case ARM_AM::da: return 0;
case ARM_AM::ia: return 1;
case ARM_AM::db: return 2;
case ARM_AM::ib: return 3;
}
}
/// getShiftOp - Return the shift opcode (bit[6:5]) of the immediate value.
///
unsigned getShiftOp(ARM_AM::ShiftOpc ShOpc) const {
switch (ShOpc) {
default: llvm_unreachable("Unknown shift opc!");
case ARM_AM::no_shift:
case ARM_AM::lsl: return 0;
case ARM_AM::lsr: return 1;
case ARM_AM::asr: return 2;
case ARM_AM::ror:
case ARM_AM::rrx: return 3;
}
return 0;
}
/// getAddrMode2OpValue - Return encoding for addrmode2 operands.
uint32_t getAddrMode2OpValue(const MCInst &MI, unsigned OpIdx,
SmallVectorImpl<MCFixup> &