diff --git a/llvm/lib/Target/X86/X86CodeEmitter.cpp b/llvm/lib/Target/X86/X86CodeEmitter.cpp index 57af7bb43f68..6757043bc064 100644 --- a/llvm/lib/Target/X86/X86CodeEmitter.cpp +++ b/llvm/lib/Target/X86/X86CodeEmitter.cpp @@ -749,10 +749,6 @@ void Emitter::emitOpcodePrefix(uint64_t TSFlags, } } -static unsigned GetX86RegNum(const MachineOperand &MO) { - return X86_MC::getX86RegNum(MO.getReg()); -} - // 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 @@ -765,7 +761,7 @@ static unsigned GetX86RegNum(const MachineOperand &MO) { static unsigned char getVEXRegisterEncoding(const MachineInstr &MI, unsigned OpNum) { unsigned SrcReg = MI.getOperand(OpNum).getReg(); - unsigned SrcRegNum = GetX86RegNum(MI.getOperand(OpNum)); + unsigned SrcRegNum = X86_MC::getX86RegNum(MI.getOperand(OpNum).getReg()); if (X86II::isX86_64ExtendedReg(SrcReg)) SrcRegNum |= 8; @@ -1132,6 +1128,7 @@ void Emitter::emitInstruction(MachineInstr &MI, bool HasVEX_4V = (TSFlags >> X86II::VEXShift) & X86II::VEX_4V; bool HasVEX_4VOp3 = (TSFlags >> X86II::VEXShift) & X86II::VEX_4VOp3; bool HasMemOp4 = (TSFlags >> X86II::VEXShift) & X86II::MemOp4; + const unsigned MemOp4_I8IMMOperand = 2; // Determine where the memory operand starts, if present. int MemoryOperand = X86II::getMemoryOperandNo(TSFlags, Opcode); @@ -1273,9 +1270,6 @@ void Emitter::emitInstruction(MachineInstr &MI, emitRegModRMByte(MI.getOperand(CurOp).getReg(), X86_MC::getX86RegNum(MI.getOperand(CurOp+1).getReg())); CurOp += 2; - if (CurOp != NumOps) - emitConstant(MI.getOperand(CurOp++).getImm(), - X86II::getSizeOfImm(Desc->TSFlags)); break; } case X86II::MRMDestMem: { @@ -1287,9 +1281,6 @@ void Emitter::emitInstruction(MachineInstr &MI, emitMemModRMByte(MI, CurOp, X86_MC::getX86RegNum(MI.getOperand(SrcRegNum).getReg())); CurOp = SrcRegNum + 1; - if (CurOp != NumOps) - emitConstant(MI.getOperand(CurOp++).getImm(), - X86II::getSizeOfImm(Desc->TSFlags)); break; } @@ -1309,9 +1300,6 @@ void Emitter::emitInstruction(MachineInstr &MI, CurOp = HasMemOp4 ? SrcRegNum : SrcRegNum + 1; if (HasVEX_4VOp3) ++CurOp; - if (CurOp != NumOps) - emitConstant(MI.getOperand(CurOp++).getImm(), - X86II::getSizeOfImm(Desc->TSFlags)); break; } case X86II::MRMSrcMem: { @@ -1333,9 +1321,6 @@ void Emitter::emitInstruction(MachineInstr &MI, CurOp += AddrOperands + 1; if (HasVEX_4VOp3) ++CurOp; - if (CurOp != NumOps) - emitConstant(MI.getOperand(CurOp++).getImm(), - X86II::getSizeOfImm(Desc->TSFlags)); break; } @@ -1448,6 +1433,33 @@ void Emitter::emitInstruction(MachineInstr &MI, break; } + if (CurOp != NumOps) { + // The last source register of a 4 operand instruction in AVX is encoded + // in bits[7:4] of a immediate byte. + if ((TSFlags >> X86II::VEXShift) & X86II::VEX_I8IMM) { + const MachineOperand &MO = MI.getOperand(HasMemOp4 ? MemOp4_I8IMMOperand + : CurOp); + CurOp++; + bool IsExtReg = X86II::isX86_64ExtendedReg(MO.getReg()); + unsigned RegNum = (IsExtReg ? (1 << 7) : 0); + RegNum |= X86_MC::getX86RegNum(MO.getReg()) << 4; + // If there is an additional 5th operand it must be an immediate, which + // is encoded in bits[3:0] + if(CurOp != NumOps) { + const MachineOperand &MIMM = MI.getOperand(CurOp++); + if(MIMM.isImm()) { + unsigned Val = MIMM.getImm(); + assert(Val < 16 && "Immediate operand value out of range"); + RegNum |= Val; + } + } + emitConstant(RegNum, 1); + } else { + emitConstant(MI.getOperand(CurOp++).getImm(), + X86II::getSizeOfImm(Desc->TSFlags)); + } + } + if (!MI.isVariadic() && CurOp != NumOps) { #ifndef NDEBUG dbgs() << "Cannot encode all operands of: " << MI << "\n";