From 1ac23b10384543fcc7343beeac542b2ab626eeec Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Fri, 5 Feb 2010 02:18:40 +0000 Subject: [PATCH] start adding MRMDestMem, which requires memory form mod/rm encoding to start limping. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@95350 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/X86/X86MCCodeEmitter.cpp | 159 +++++++++++++++++++++++++++- 1 file changed, 158 insertions(+), 1 deletion(-) diff --git a/lib/Target/X86/X86MCCodeEmitter.cpp b/lib/Target/X86/X86MCCodeEmitter.cpp index f9935b359f1..bfa02e838dc 100644 --- a/lib/Target/X86/X86MCCodeEmitter.cpp +++ b/lib/Target/X86/X86MCCodeEmitter.cpp @@ -25,9 +25,12 @@ class X86MCCodeEmitter : public MCCodeEmitter { void operator=(const X86MCCodeEmitter &); // DO NOT IMPLEMENT const TargetMachine &TM; const TargetInstrInfo &TII; + bool Is64BitMode; public: X86MCCodeEmitter(TargetMachine &tm) : TM(tm), TII(*TM.getInstrInfo()) { + // FIXME: Get this from the right place. + Is64BitMode = false; } ~X86MCCodeEmitter() {} @@ -59,6 +62,9 @@ public: EmitByte(ModRMByte(3, RegOpcodeFld, GetX86RegNum(ModRMReg)), OS); } + void EmitMemModRMByte(const MCInst &MI, unsigned Op, + unsigned RegOpcodeField, intptr_t PCAdj, + raw_ostream &OS) const; void EncodeInstruction(const MCInst &MI, raw_ostream &OS) const; @@ -73,6 +79,143 @@ MCCodeEmitter *llvm::createX86MCCodeEmitter(const Target &, } +/// isDisp8 - Return true if this signed displacement fits in a 8-bit +/// sign-extended field. +static bool isDisp8(int Value) { + return Value == (signed char)Value; +} + +void X86MCCodeEmitter::EmitMemModRMByte(const MCInst &MI, unsigned Op, + unsigned RegOpcodeField, + intptr_t PCAdj, + raw_ostream &OS) const { + const MCOperand &Op3 = MI.getOperand(Op+3); + int DispVal = 0; + const MCOperand *DispForReloc = 0; + + // Figure out what sort of displacement we have to handle here. + if (Op3.isImm()) { + DispVal = Op3.getImm(); + } else { +#if 0 + if (Op3.isGlobal()) { + DispForReloc = &Op3; + } else if (Op3.isSymbol()) { + DispForReloc = &Op3; + } else if (Op3.isCPI()) { + if (!MCE.earlyResolveAddresses() || Is64BitMode || IsPIC) { + DispForReloc = &Op3; + } else { + DispVal += MCE.getConstantPoolEntryAddress(Op3.getIndex()); + DispVal += Op3.getOffset(); + } + } else { + assert(Op3.isJTI()); + if (!MCE.earlyResolveAddresses() || Is64BitMode || IsPIC) { + DispForReloc = &Op3; + } else { + DispVal += MCE.getJumpTableEntryAddress(Op3.getIndex()); + } +#endif + } + + const MCOperand &Base = MI.getOperand(Op); + //const MCOperand &Scale = MI.getOperand(Op+1); + const MCOperand &IndexReg = MI.getOperand(Op+2); + unsigned BaseReg = Base.getReg(); + + // Is a SIB byte needed? + // If no BaseReg, issue a RIP relative instruction only if the MCE can + // resolve addresses on-the-fly, otherwise use SIB (Intel Manual 2A, table + // 2-7) and absolute references. + if ((!Is64BitMode || DispForReloc || BaseReg != 0) && + IndexReg.getReg() == 0 && + (BaseReg == X86::RIP || (BaseReg != 0 && BaseReg != X86::ESP))) { + if (BaseReg == 0 || BaseReg == X86::RIP) { // Just a displacement? + // Emit special case [disp32] encoding + EmitByte(ModRMByte(0, RegOpcodeField, 5), OS); +#if 0 + emitDisplacementField(DispForReloc, DispVal, PCAdj, true); +#endif + } else { + unsigned BaseRegNo = GetX86RegNum(Base); + if (!DispForReloc && DispVal == 0 && BaseRegNo != N86::EBP) { + // Emit simple indirect register encoding... [EAX] f.e. + EmitByte(ModRMByte(0, RegOpcodeField, BaseRegNo), OS); + } else if (!DispForReloc && isDisp8(DispVal)) { + // Emit the disp8 encoding... [REG+disp8] + EmitByte(ModRMByte(1, RegOpcodeField, BaseRegNo), OS); + EmitConstant(DispVal, 1, OS); + } else { + // Emit the most general non-SIB encoding: [REG+disp32] + EmitByte(ModRMByte(2, RegOpcodeField, BaseRegNo), OS); +#if 0 + emitDisplacementField(DispForReloc, DispVal, PCAdj, IsPCRel); +#endif + } + } + + } else { // We need a SIB byte, so start by outputting the ModR/M byte first + assert(IndexReg.getReg() != X86::ESP && + IndexReg.getReg() != X86::RSP && "Cannot use ESP as index reg!"); + + bool ForceDisp32 = false; + bool ForceDisp8 = false; + if (BaseReg == 0) { + // If there is no base register, we emit the special case SIB byte with + // MOD=0, BASE=5, to JUST get the index, scale, and displacement. + EmitByte(ModRMByte(0, RegOpcodeField, 4), OS); + ForceDisp32 = true; + } else if (DispForReloc) { + // Emit the normal disp32 encoding. + EmitByte(ModRMByte(2, RegOpcodeField, 4), OS); + ForceDisp32 = true; + } else if (DispVal == 0 && BaseReg != X86::EBP) { + // Emit no displacement ModR/M byte + EmitByte(ModRMByte(0, RegOpcodeField, 4), OS); + } else if (isDisp8(DispVal)) { + // Emit the disp8 encoding. + EmitByte(ModRMByte(1, RegOpcodeField, 4), OS); + ForceDisp8 = true; // Make sure to force 8 bit disp if Base=EBP + } else { + // Emit the normal disp32 encoding. + EmitByte(ModRMByte(2, RegOpcodeField, 4), OS); + } + +#if 0 + // Calculate what the SS field value should be... + static const unsigned SSTable[] = { ~0, 0, 1, ~0, 2, ~0, ~0, ~0, 3 }; + unsigned SS = SSTable[Scale.getImm()]; + + if (BaseReg == 0) { + // Handle the SIB byte for the case where there is no base, see Intel + // Manual 2A, table 2-7. The displacement has already been output. + unsigned IndexRegNo; + if (IndexReg.getReg()) + IndexRegNo = getX86RegNum(IndexReg.getReg()); + else // Examples: [ESP+1*+4] or [scaled idx]+disp32 (MOD=0,BASE=5) + IndexRegNo = 4; + emitSIBByte(SS, IndexRegNo, 5); + } else { + unsigned BaseRegNo = getX86RegNum(BaseReg); + unsigned IndexRegNo; + if (IndexReg.getReg()) + IndexRegNo = getX86RegNum(IndexReg.getReg()); + else + IndexRegNo = 4; // For example [ESP+1*+4] + emitSIBByte(SS, IndexRegNo, BaseRegNo); + } + + // Do we need to output a displacement? + if (ForceDisp8) { + emitConstant(DispVal, 1); + } else if (DispVal != 0 || ForceDisp32) { + emitDisplacementField(DispForReloc, DispVal, PCAdj, IsPCRel); + } +#endif + } +} + void X86MCCodeEmitter:: EncodeInstruction(const MCInst &MI, raw_ostream &OS) const { @@ -175,9 +318,12 @@ EncodeInstruction(const MCInst &MI, raw_ostream &OS) const { // Skip the last source operand that is tied_to the dest reg. e.g. LXADD32 --NumOps; + // FIXME: Can we kill off MRMInitReg?? + unsigned char BaseOpcode = X86InstrInfo::getBaseOpcodeFor(Desc); switch (TSFlags & X86II::FormMask) { - default: assert(0 && "Unknown FormMask value in X86MCCodeEmitter!"); + default: errs() << "FORM: " << (TSFlags & X86II::FormMask) << "\n"; + assert(0 && "Unknown FormMask value in X86MCCodeEmitter!"); case X86II::RawFrm: { EmitByte(BaseOpcode, OS); @@ -213,6 +359,17 @@ EncodeInstruction(const MCInst &MI, raw_ostream &OS) const { EmitConstant(MI.getOperand(CurOp++).getImm(), X86InstrInfo::sizeOfImm(&Desc), OS); break; + + case X86II::MRMDestMem: + EmitByte(BaseOpcode, OS); + EmitMemModRMByte(MI, CurOp, + GetX86RegNum(MI.getOperand(CurOp + X86AddrNumOperands)), + 0, OS); + CurOp += X86AddrNumOperands + 1; + if (CurOp != NumOps) + EmitConstant(MI.getOperand(CurOp++).getImm(), + X86InstrInfo::sizeOfImm(&Desc), OS); + break; } #ifndef NDEBUG