#define DEBUG_TYPE "x86-emitter"
#include "X86.h"
#include "X86InstrInfo.h"
+#include "X86FixupKinds.h"
#include "llvm/MC/MCCodeEmitter.h"
+#include "llvm/MC/MCExpr.h"
#include "llvm/MC/MCInst.h"
#include "llvm/Support/raw_ostream.h"
using namespace llvm;
-// FIXME: This should move to a header.
-namespace llvm {
-namespace X86 {
-enum Fixups {
- reloc_pcrel_4byte = FirstTargetFixupKind, // 32-bit pcrel, e.g. a branch.
- reloc_pcrel_1byte // 8-bit pcrel, e.g. branch_1
-};
-}
-}
-
namespace {
class X86MCCodeEmitter : public MCCodeEmitter {
X86MCCodeEmitter(const X86MCCodeEmitter &); // DO NOT IMPLEMENT
void operator=(const X86MCCodeEmitter &); // DO NOT IMPLEMENT
const TargetMachine &TM;
const TargetInstrInfo &TII;
+ MCContext &Ctx;
bool Is64BitMode;
public:
- X86MCCodeEmitter(TargetMachine &tm, bool is64Bit)
- : TM(tm), TII(*TM.getInstrInfo()) {
+ X86MCCodeEmitter(TargetMachine &tm, MCContext &ctx, bool is64Bit)
+ : TM(tm), TII(*TM.getInstrInfo()), Ctx(ctx) {
Is64BitMode = is64Bit;
}
~X86MCCodeEmitter() {}
unsigned getNumFixupKinds() const {
- return 2;
+ return 4;
}
const MCFixupKindInfo &getFixupKindInfo(MCFixupKind Kind) const {
const static MCFixupKindInfo Infos[] = {
- { "reloc_pcrel_4byte", 0, 4 * 8 },
- { "reloc_pcrel_1byte", 0, 1 * 8 }
+ { "reloc_pcrel_4byte", 0, 4 * 8, MCFixupKindInfo::FKF_IsPCRel },
+ { "reloc_pcrel_1byte", 0, 1 * 8, MCFixupKindInfo::FKF_IsPCRel },
+ { "reloc_riprel_4byte", 0, 4 * 8, MCFixupKindInfo::FKF_IsPCRel },
+ { "reloc_riprel_4byte_movq_load", 0, 4 * 8, MCFixupKindInfo::FKF_IsPCRel }
};
if (Kind < FirstTargetFixupKind)
void EmitImmediate(const MCOperand &Disp,
unsigned ImmSize, MCFixupKind FixupKind,
unsigned &CurByte, raw_ostream &OS,
- SmallVectorImpl<MCFixup> &Fixups) const;
+ SmallVectorImpl<MCFixup> &Fixups,
+ int ImmOffset = 0) const;
inline static unsigned char ModRMByte(unsigned Mod, unsigned RegOpcode,
unsigned RM) {
void EmitMemModRMByte(const MCInst &MI, unsigned Op,
unsigned RegOpcodeField,
- unsigned &CurByte, raw_ostream &OS,
+ uint64_t TSFlags, unsigned &CurByte, raw_ostream &OS,
SmallVectorImpl<MCFixup> &Fixups) const;
void EncodeInstruction(const MCInst &MI, raw_ostream &OS,
SmallVectorImpl<MCFixup> &Fixups) const;
+ void EmitVEXOpcodePrefix(uint64_t TSFlags, unsigned &CurByte,
+ const MCInst &MI, const TargetInstrDesc &Desc,
+ raw_ostream &OS) const;
+
+ void EmitOpcodePrefix(uint64_t TSFlags, unsigned &CurByte,
+ const MCInst &MI, const TargetInstrDesc &Desc,
+ raw_ostream &OS) const;
};
} // end anonymous namespace
MCCodeEmitter *llvm::createX86_32MCCodeEmitter(const Target &,
- TargetMachine &TM) {
- return new X86MCCodeEmitter(TM, false);
+ TargetMachine &TM,
+ MCContext &Ctx) {
+ return new X86MCCodeEmitter(TM, Ctx, false);
}
MCCodeEmitter *llvm::createX86_64MCCodeEmitter(const Target &,
- TargetMachine &TM) {
- return new X86MCCodeEmitter(TM, true);
+ TargetMachine &TM,
+ MCContext &Ctx) {
+ return new X86MCCodeEmitter(TM, Ctx, true);
}
/// getImmFixupKind - Return the appropriate fixup kind to use for an immediate
/// in an instruction with the specified TSFlags.
-static MCFixupKind getImmFixupKind(unsigned TSFlags) {
+static MCFixupKind getImmFixupKind(uint64_t TSFlags) {
unsigned Size = X86II::getSizeOfImm(TSFlags);
bool isPCRel = X86II::isImmPCRel(TSFlags);
- // FIXME: Pass in the relocation type, this is just a hack..
switch (Size) {
default: assert(0 && "Unknown immediate size");
case 1: return isPCRel ? MCFixupKind(X86::reloc_pcrel_1byte) : FK_Data_1;
void X86MCCodeEmitter::
EmitImmediate(const MCOperand &DispOp, unsigned Size, MCFixupKind FixupKind,
unsigned &CurByte, raw_ostream &OS,
- SmallVectorImpl<MCFixup> &Fixups) const {
+ SmallVectorImpl<MCFixup> &Fixups, int ImmOffset) const {
// If this is a simple integer displacement that doesn't require a relocation,
// emit it now.
if (DispOp.isImm()) {
- EmitConstant(DispOp.getImm(), Size, CurByte, OS);
+ // FIXME: is this right for pc-rel encoding?? Probably need to emit this as
+ // a fixup if so.
+ EmitConstant(DispOp.getImm()+ImmOffset, Size, CurByte, OS);
return;
}
+ // If we have an immoffset, add it to the expression.
+ const MCExpr *Expr = DispOp.getExpr();
+
+ // If the fixup is pc-relative, we need to bias the value to be relative to
+ // the start of the field, not the end of the field.
+ if (FixupKind == MCFixupKind(X86::reloc_pcrel_4byte) ||
+ FixupKind == MCFixupKind(X86::reloc_riprel_4byte) ||
+ FixupKind == MCFixupKind(X86::reloc_riprel_4byte_movq_load))
+ ImmOffset -= 4;
+ if (FixupKind == MCFixupKind(X86::reloc_pcrel_1byte))
+ ImmOffset -= 1;
+
+ if (ImmOffset)
+ Expr = MCBinaryExpr::CreateAdd(Expr, MCConstantExpr::Create(ImmOffset, Ctx),
+ Ctx);
+
// Emit a symbolic constant as a fixup and 4 zeros.
- Fixups.push_back(MCFixup::Create(CurByte, DispOp.getExpr(), FixupKind));
+ Fixups.push_back(MCFixup::Create(CurByte, Expr, FixupKind));
EmitConstant(0, Size, CurByte, OS);
}
void X86MCCodeEmitter::EmitMemModRMByte(const MCInst &MI, unsigned Op,
unsigned RegOpcodeField,
- unsigned &CurByte,
+ uint64_t TSFlags, unsigned &CurByte,
raw_ostream &OS,
SmallVectorImpl<MCFixup> &Fixups) const{
const MCOperand &Disp = MI.getOperand(Op+3);
const MCOperand &Scale = MI.getOperand(Op+1);
const MCOperand &IndexReg = MI.getOperand(Op+2);
unsigned BaseReg = Base.getReg();
- unsigned BaseRegNo = -1U;
- if (BaseReg != 0 && BaseReg != X86::RIP)
- BaseRegNo = GetX86RegNum(Base);
+
+ // Handle %rip relative addressing.
+ if (BaseReg == X86::RIP) { // [disp32+RIP] in X86-64 mode
+ assert(Is64BitMode && "Rip-relative addressing requires 64-bit mode");
+ assert(IndexReg.getReg() == 0 && "Invalid rip-relative address");
+ EmitByte(ModRMByte(0, RegOpcodeField, 5), CurByte, OS);
+
+ unsigned FixupKind = X86::reloc_riprel_4byte;
+
+ // movq loads are handled with a special relocation form which allows the
+ // linker to eliminate some loads for GOT references which end up in the
+ // same linkage unit.
+ if (MI.getOpcode() == X86::MOV64rm ||
+ MI.getOpcode() == X86::MOV64rm_TC)
+ FixupKind = X86::reloc_riprel_4byte_movq_load;
+
+ // rip-relative addressing is actually relative to the *next* instruction.
+ // Since an immediate can follow the mod/rm byte for an instruction, this
+ // means that we need to bias the immediate field of the instruction with
+ // the size of the immediate field. If we have this case, add it into the
+ // expression to emit.
+ int ImmSize = X86II::hasImm(TSFlags) ? X86II::getSizeOfImm(TSFlags) : 0;
+
+ EmitImmediate(Disp, 4, MCFixupKind(FixupKind),
+ CurByte, OS, Fixups, -ImmSize);
+ return;
+ }
+
+ unsigned BaseRegNo = BaseReg ? GetX86RegNum(Base) : -1U;
// Determine whether a SIB byte is needed.
// If no BaseReg, issue a RIP relative instruction only if the MCE can
// byte to emit an addr that is just 'disp32' (the non-RIP relative form).
(!Is64BitMode || BaseReg != 0)) {
- if (BaseReg == 0 || // [disp32] in X86-32 mode
- BaseReg == X86::RIP) { // [disp32+RIP] in X86-64 mode
+ if (BaseReg == 0) { // [disp32] in X86-32 mode
EmitByte(ModRMByte(0, RegOpcodeField, 5), CurByte, OS);
EmitImmediate(Disp, 4, FK_Data_4, CurByte, OS, Fixups);
return;
// Emit the normal disp32 encoding.
EmitByte(ModRMByte(2, RegOpcodeField, 4), CurByte, OS);
ForceDisp32 = true;
- } else if (Disp.getImm() == 0 && BaseReg != X86::EBP) {
+ } else if (Disp.getImm() == 0 &&
+ // Base reg can't be anything that ends up with '5' as the base
+ // reg, it is the magic [*] nomenclature that indicates no base.
+ BaseRegNo != N86::EBP) {
// Emit no displacement ModR/M byte
EmitByte(ModRMByte(0, RegOpcodeField, 4), CurByte, OS);
} else if (isDisp8(Disp.getImm())) {
EmitImmediate(Disp, 4, FK_Data_4, CurByte, OS, Fixups);
}
+/// EmitVEXOpcodePrefix - AVX instructions are encoded using a opcode prefix
+/// called VEX.
+void X86MCCodeEmitter::EmitVEXOpcodePrefix(uint64_t TSFlags, unsigned &CurByte,
+ const MCInst &MI, const TargetInstrDesc &Desc,
+ raw_ostream &OS) const {
+
+ // Pseudo instructions never have a VEX prefix.
+ if ((TSFlags & X86II::FormMask) == X86II::Pseudo)
+ return;
+
+ // VEX_R: opcode externsion equivalent to REX.R in
+ // 1's complement (inverted) form
+ //
+ // 1: Same as REX_R=0 (must be 1 in 32-bit mode)
+ // 0: Same as REX_R=1 (64 bit mode only)
+ //
+ unsigned char VEX_R = 0x1;
+
+ // VEX_B:
+ //
+ // 1: Same as REX_B=0 (ignored in 32-bit mode)
+ // 0: Same as REX_B=1 (64 bit mode only)
+ //
+ unsigned char VEX_B = 0x1;
+
+ // VEX_W: opcode specific (use like REX.W, or used for
+ // opcode extension, or ignored, depending on the opcode byte)
+ unsigned char VEX_W = 0;
+
+ // VEX_5M (VEX m-mmmmm field):
+ //
+ // 0b00000: Reserved for future use
+ // 0b00001: implied 0F leading opcode
+ // 0b00010: implied 0F 38 leading opcode bytes
+ // 0b00011: implied 0F 3A leading opcode bytes
+ // 0b00100-0b11111: Reserved for future use
+ //
+ unsigned char VEX_5M = 0x1;
+
+ // VEX_4V (VEX vvvv field): a register specifier
+ // (in 1's complement form) or 1111 if unused.
+ unsigned char VEX_4V = 0xf;
+
+ // VEX_L (Vector Length):
+ //
+ // 0: scalar or 128-bit vector
+ // 1: 256-bit vector
+ //
+ unsigned char VEX_L = 0;
+
+ // VEX_PP: opcode extension providing equivalent
+ // functionality of a SIMD prefix
+ //
+ // 0b00: None
+ // 0b01: 66 (not handled yet)
+ // 0b10: F3
+ // 0b11: F2
+ //
+ unsigned char VEX_PP = 0;
+
+ switch (TSFlags & X86II::Op0Mask) {
+ default: assert(0 && "Invalid prefix!");
+ case 0: break; // No prefix!
+ case X86II::T8: // 0F 38
+ VEX_5M = 0x2;
+ break;
+ case X86II::TA: // 0F 3A
+ VEX_5M = 0x3;
+ break;
+ case X86II::TF: // F2 0F 38
+ VEX_PP = 0x3;
+ VEX_5M = 0x2;
+ break;
+ case X86II::XS: // F3 0F
+ VEX_PP = 0x2;
+ break;
+ case X86II::XD: // F2 0F
+ VEX_PP = 0x3;
+ break;
+ }
+
+ unsigned NumOps = MI.getNumOperands();
+ unsigned i = 0;
+ unsigned SrcReg = 0, SrcRegNum = 0;
+
+ switch (TSFlags & X86II::FormMask) {
+ case X86II::MRMInitReg: assert(0 && "FIXME: Remove this!");
+ case X86II::MRMSrcReg:
+ if (MI.getOperand(0).isReg() &&
+ X86InstrInfo::isX86_64ExtendedReg(MI.getOperand(0).getReg()))
+ VEX_R = 0x0;
+
+ // On regular x86, both XMM0-XMM7 and XMM8-XMM15 are encoded in the
+ // range 0-7 and the difference between the 2 groups is given by the
+ // REX prefix. In the VEX prefix, registers are seen sequencially
+ // from 0-15 and encoded in 1's complement form, example:
+ //
+ // ModRM field => XMM9 => 1
+ // VEX.VVVV => XMM9 => ~9
+ //
+ // See table 4-35 of Intel AVX Programming Reference for details.
+ SrcReg = MI.getOperand(1).getReg();
+ SrcRegNum = GetX86RegNum(MI.getOperand(1));
+ if (SrcReg >= X86::XMM8 && SrcReg <= X86::XMM15)
+ SrcRegNum += 8;
+
+ // The registers represented through VEX_VVVV should
+ // be encoded in 1's complement form.
+ if ((TSFlags >> 32) & X86II::VEX_4V)
+ VEX_4V = (~SrcRegNum) & 0xf;
+
+ i = 2; // Skip the VEX.VVVV operand.
+ for (; i != NumOps; ++i) {
+ const MCOperand &MO = MI.getOperand(i);
+ if (MO.isReg() && X86InstrInfo::isX86_64ExtendedReg(MO.getReg()))
+ VEX_B = 0x0;
+ }
+ break;
+ default:
+ assert(0 && "Not implemented!");
+ }
+
+ // VEX opcode prefix can have 2 or 3 bytes
+ //
+ // 3 bytes:
+ // +-----+ +--------------+ +-------------------+
+ // | C4h | | RXB | m-mmmm | | W | vvvv | L | pp |
+ // +-----+ +--------------+ +-------------------+
+ // 2 bytes:
+ // +-----+ +-------------------+
+ // | C5h | | R | vvvv | L | pp |
+ // +-----+ +-------------------+
+ //
+ // Note: VEX.X isn't used so far
+ //
+ unsigned char LastByte = VEX_PP | (VEX_L << 2) | (VEX_4V << 3);
+
+ if (VEX_B /* & VEX_X */) { // 2 byte VEX prefix
+ EmitByte(0xC5, CurByte, OS);
+ EmitByte(LastByte | (VEX_R << 7), CurByte, OS);
+ return;
+ }
+
+ // 3 byte VEX prefix
+ EmitByte(0xC4, CurByte, OS);
+ EmitByte(VEX_R << 7 | 1 << 6 /* VEX_X = 1 */ | VEX_5M, CurByte, OS);
+ EmitByte(LastByte | (VEX_W << 7), CurByte, OS);
+}
+
/// DetermineREXPrefix - Determine if the MCInst has to be encoded with a X86-64
/// REX prefix which specifies 1) 64-bit instructions, 2) non-default operand
/// size, and 3) use of X86-64 extended registers.
-static unsigned DetermineREXPrefix(const MCInst &MI, unsigned TSFlags,
+static unsigned DetermineREXPrefix(const MCInst &MI, uint64_t TSFlags,
const TargetInstrDesc &Desc) {
- // Pseudo instructions shouldn't get here.
- assert((TSFlags & X86II::FormMask) != X86II::Pseudo &&
- "Can't encode pseudo instrs");
+ // Pseudo instructions never have a rex byte.
+ if ((TSFlags & X86II::FormMask) == X86II::Pseudo)
+ return 0;
unsigned REX = 0;
if (TSFlags & X86II::REX_W)
return REX;
}
-void X86MCCodeEmitter::
-EncodeInstruction(const MCInst &MI, raw_ostream &OS,
- SmallVectorImpl<MCFixup> &Fixups) const {
- unsigned Opcode = MI.getOpcode();
- const TargetInstrDesc &Desc = TII.get(Opcode);
- unsigned TSFlags = Desc.TSFlags;
-
- // Keep track of the current byte being emitted.
- unsigned CurByte = 0;
-
- // FIXME: We should emit the prefixes in exactly the same order as GAS does,
- // in order to provide diffability.
+/// EmitOpcodePrefix - Emit all instruction prefixes prior to the opcode.
+void X86MCCodeEmitter::EmitOpcodePrefix(uint64_t TSFlags, unsigned &CurByte,
+ const MCInst &MI, const TargetInstrDesc &Desc,
+ raw_ostream &OS) const {
// Emit the lock opcode prefix as needed.
if (TSFlags & X86II::LOCK)
EmitByte(0x3A, CurByte, OS);
break;
}
+}
+
+void X86MCCodeEmitter::
+EncodeInstruction(const MCInst &MI, raw_ostream &OS,
+ SmallVectorImpl<MCFixup> &Fixups) const {
+ unsigned Opcode = MI.getOpcode();
+ const TargetInstrDesc &Desc = TII.get(Opcode);
+ uint64_t TSFlags = Desc.TSFlags;
+
+ // Keep track of the current byte being emitted.
+ unsigned CurByte = 0;
+
+ // Is this instruction encoded in AVX form?
+ bool IsAVXForm = false;
+ if ((TSFlags >> 32) & X86II::VEX_4V)
+ IsAVXForm = true;
+
+ // FIXME: We should emit the prefixes in exactly the same order as GAS does,
+ // in order to provide diffability.
+
+ if (!IsAVXForm)
+ EmitOpcodePrefix(TSFlags, CurByte, MI, Desc, OS);
+ else
+ EmitVEXOpcodePrefix(TSFlags, CurByte, MI, Desc, OS);
// If this is a two-address instruction, skip one of the register operands.
unsigned NumOps = Desc.getNumOperands();
--NumOps;
unsigned char BaseOpcode = X86II::getBaseOpcodeFor(TSFlags);
+ unsigned SrcRegNum = 0;
switch (TSFlags & X86II::FormMask) {
case X86II::MRMInitReg:
assert(0 && "FIXME: Remove this form when the JIT moves to MCCodeEmitter!");
default: errs() << "FORM: " << (TSFlags & X86II::FormMask) << "\n";
assert(0 && "Unknown FormMask value in X86MCCodeEmitter!");
+ case X86II::Pseudo: return; // Pseudo instructions encode to nothing.
case X86II::RawFrm:
EmitByte(BaseOpcode, CurByte, OS);
break;
EmitByte(BaseOpcode, CurByte, OS);
EmitMemModRMByte(MI, CurOp,
GetX86RegNum(MI.getOperand(CurOp + X86AddrNumOperands)),
- CurByte, OS, Fixups);
+ TSFlags, CurByte, OS, Fixups);
CurOp += X86AddrNumOperands + 1;
break;
case X86II::MRMSrcReg:
EmitByte(BaseOpcode, CurByte, OS);
- EmitRegModRMByte(MI.getOperand(CurOp+1), GetX86RegNum(MI.getOperand(CurOp)),
- CurByte, OS);
- CurOp += 2;
+ SrcRegNum = CurOp + 1;
+
+ if (IsAVXForm) // Skip 1st src (which is encoded in VEX_VVVV)
+ SrcRegNum++;
+
+ EmitRegModRMByte(MI.getOperand(SrcRegNum),
+ GetX86RegNum(MI.getOperand(CurOp)), CurByte, OS);
+ CurOp = SrcRegNum + 1;
break;
case X86II::MRMSrcMem: {
AddrOperands = X86AddrNumOperands;
EmitMemModRMByte(MI, CurOp+1, GetX86RegNum(MI.getOperand(CurOp)),
- CurByte, OS, Fixups);
+ TSFlags, CurByte, OS, Fixups);
CurOp += AddrOperands + 1;
break;
}
case X86II::MRM4r: case X86II::MRM5r:
case X86II::MRM6r: case X86II::MRM7r:
EmitByte(BaseOpcode, CurByte, OS);
-
- // Special handling of lfence, mfence, monitor, and mwait.
- // FIXME: This is terrible, they should get proper encoding bits in TSFlags.
- if (Opcode == X86::LFENCE || Opcode == X86::MFENCE ||
- Opcode == X86::MONITOR || Opcode == X86::MWAIT) {
- EmitByte(ModRMByte(3, (TSFlags & X86II::FormMask)-X86II::MRM0r,
- Opcode == X86::MWAIT),
- CurByte, OS);
- } else {
- EmitRegModRMByte(MI.getOperand(CurOp++),
- (TSFlags & X86II::FormMask)-X86II::MRM0r,
- CurByte, OS);
- }
+ EmitRegModRMByte(MI.getOperand(CurOp++),
+ (TSFlags & X86II::FormMask)-X86II::MRM0r,
+ CurByte, OS);
break;
case X86II::MRM0m: case X86II::MRM1m:
case X86II::MRM2m: case X86II::MRM3m:
case X86II::MRM6m: case X86II::MRM7m:
EmitByte(BaseOpcode, CurByte, OS);
EmitMemModRMByte(MI, CurOp, (TSFlags & X86II::FormMask)-X86II::MRM0m,
- CurByte, OS, Fixups);
+ TSFlags, CurByte, OS, Fixups);
CurOp += X86AddrNumOperands;
break;
case X86II::MRM_C1:
EmitByte(BaseOpcode, CurByte, OS);
EmitByte(0xC1, CurByte, OS);
break;
+ case X86II::MRM_C2:
+ EmitByte(BaseOpcode, CurByte, OS);
+ EmitByte(0xC2, CurByte, OS);
+ break;
+ case X86II::MRM_C3:
+ EmitByte(BaseOpcode, CurByte, OS);
+ EmitByte(0xC3, CurByte, OS);
+ break;
+ case X86II::MRM_C4:
+ EmitByte(BaseOpcode, CurByte, OS);
+ EmitByte(0xC4, CurByte, OS);
+ break;
case X86II::MRM_C8:
EmitByte(BaseOpcode, CurByte, OS);
EmitByte(0xC8, CurByte, OS);
EmitByte(BaseOpcode, CurByte, OS);
EmitByte(0xF0, CurByte, OS);
break;
+ case X86II::MRM_F8:
+ EmitByte(BaseOpcode, CurByte, OS);
+ EmitByte(0xF8, CurByte, OS);
+ break;
+ case X86II::MRM_F9:
+ EmitByte(BaseOpcode, CurByte, OS);
+ EmitByte(0xF9, CurByte, OS);
+ break;
}
// If there is a remaining operand, it must be a trailing immediate. Emit it
// according to the right size for the instruction.
- // FIXME: This should pass in whether the value is pc relative or not. This
- // information should be aquired from TSFlags as well.
if (CurOp != NumOps)
EmitImmediate(MI.getOperand(CurOp++),
X86II::getSizeOfImm(TSFlags), getImmFixupKind(TSFlags),