diff --git a/llvm/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp b/llvm/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp --- a/llvm/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp +++ b/llvm/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp @@ -113,33 +113,28 @@ } } -/// \returns true if this signed displacement fits in a 8-bit sign-extended -/// field. -static bool isDisp8(int Value) { return Value == (int8_t)Value; } - -/// \returns true if this signed displacement fits in a 8-bit compressed -/// dispacement field. -static bool isCDisp8(uint64_t TSFlags, int Value, int &CValue) { - assert(((TSFlags & X86II::EncodingMask) == X86II::EVEX) && - "Compressed 8-bit displacement is only valid for EVEX inst."); +/// Determine if this immediate can fit in a disp8 or a compressed disp8 for +/// EVEX instructions. \p will be set to the value to pass to the ImmOffset +/// parameter of emitImmediate. +static bool isDispOrCDisp8(uint64_t TSFlags, int Value, int &ImmOffset) { + bool HasEVEX = (TSFlags & X86II::EncodingMask) == X86II::EVEX; - unsigned CD8_Scale = + int CD8_Scale = (TSFlags & X86II::CD8_Scale_Mask) >> X86II::CD8_Scale_Shift; - if (CD8_Scale == 0) { - CValue = Value; - return isDisp8(Value); - } + if (!HasEVEX || CD8_Scale == 0) + return isInt<8>(Value); - unsigned Mask = CD8_Scale - 1; - assert((CD8_Scale & Mask) == 0 && "Invalid memory object size."); - if (Value & Mask) // Unaligned offset + assert(isPowerOf2_32(CD8_Scale) && "Unexpected CD8 scale!"); + if (Value & (CD8_Scale - 1)) // Unaligned offset return false; - Value /= (int)CD8_Scale; - bool Ret = (Value == (int8_t)Value); - if (Ret) - CValue = Value; - return Ret; + int CDisp8 = Value / CD8_Scale; + if (!isInt<8>(CDisp8)) + return false; + + // ImmOffset will be added to Value in emitImmediate leaving just CDisp8. + ImmOffset = CDisp8 - Value; + return true; } /// \returns the appropriate fixup kind to use for an immediate in an @@ -393,7 +388,6 @@ const MCOperand &Scale = MI.getOperand(Op + X86::AddrScaleAmt); const MCOperand &IndexReg = MI.getOperand(Op + X86::AddrIndexReg); unsigned BaseReg = Base.getReg(); - bool HasEVEX = (TSFlags & X86II::EncodingMask) == X86II::EVEX; // Handle %rip relative addressing. if (BaseReg == X86::RIP || @@ -487,7 +481,7 @@ RMfield = (IndexReg16 & 1) | ((7 - RMfield) << 1); } - if (Disp.isImm() && isDisp8(Disp.getImm())) { + if (Disp.isImm() && isInt<8>(Disp.getImm())) { if (Disp.getImm() == 0 && RMfield != 6) { // There is no displacement; just the register. emitByte(modRMByte(0, RegOpcodeField, RMfield), OS); @@ -557,18 +551,11 @@ // Otherwise, if the displacement fits in a byte, encode as [REG+disp8]. if (Disp.isImm()) { - if (!HasEVEX && isDisp8(Disp.getImm())) { - emitByte(modRMByte(1, RegOpcodeField, BaseRegNo), OS); - emitImmediate(Disp, MI.getLoc(), 1, FK_Data_1, StartByte, OS, Fixups); - return; - } - // Try EVEX compressed 8-bit displacement first; if failed, fall back to - // 32-bit displacement. - int CDisp8 = 0; - if (HasEVEX && isCDisp8(TSFlags, Disp.getImm(), CDisp8)) { + int ImmOffset = 0; + if (isDispOrCDisp8(TSFlags, Disp.getImm(), ImmOffset)) { emitByte(modRMByte(1, RegOpcodeField, BaseRegNo), OS); emitImmediate(Disp, MI.getLoc(), 1, FK_Data_1, StartByte, OS, Fixups, - CDisp8 - Disp.getImm()); + ImmOffset); return; } } @@ -589,7 +576,6 @@ bool ForceDisp32 = false; bool ForceDisp8 = false; - int CDisp8 = 0; int ImmOffset = 0; if (BaseReg == 0) { // If there is no base register, we emit the special case SIB byte with @@ -606,15 +592,10 @@ BaseRegNo != N86::EBP) { // Emit no displacement ModR/M byte emitByte(modRMByte(0, RegOpcodeField, 4), OS); - } else if (!HasEVEX && isDisp8(Disp.getImm())) { - // Emit the disp8 encoding. - emitByte(modRMByte(1, RegOpcodeField, 4), OS); - ForceDisp8 = true; // Make sure to force 8 bit disp if Base=EBP - } else if (HasEVEX && isCDisp8(TSFlags, Disp.getImm(), CDisp8)) { + } else if (isDispOrCDisp8(TSFlags, Disp.getImm(), ImmOffset)) { // Emit the disp8 encoding. emitByte(modRMByte(1, RegOpcodeField, 4), OS); ForceDisp8 = true; // Make sure to force 8 bit disp if Base=EBP - ImmOffset = CDisp8 - Disp.getImm(); } else { // Emit the normal disp32 encoding. emitByte(modRMByte(2, RegOpcodeField, 4), OS);