Mercurial > hg > CbC > CbC_llvm
diff lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp @ 120:1172e4bd9c6f
update 4.0.0
author | mir3636 |
---|---|
date | Fri, 25 Nov 2016 19:14:25 +0900 |
parents | 7d135dc70f03 |
children | 803732b1fca8 |
line wrap: on
line diff
--- a/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp Tue Jan 26 22:56:36 2016 +0900 +++ b/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp Fri Nov 25 19:14:25 2016 +0900 @@ -76,36 +76,17 @@ return Ctx.getRegisterInfo()->getEncodingValue(MO.getReg()) & 0x7; } - // 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. - unsigned char getVEXRegisterEncoding(const MCInst &MI, - unsigned OpNum) const { - unsigned SrcReg = MI.getOperand(OpNum).getReg(); - unsigned SrcRegNum = GetX86RegNum(MI.getOperand(OpNum)); - if (X86II::isX86_64ExtendedReg(SrcReg)) - SrcRegNum |= 8; - - // The registers represented through VEX_VVVV should - // be encoded in 1's complement form. - return (~SrcRegNum) & 0xf; + unsigned getX86RegEncoding(const MCInst &MI, unsigned OpNum) const { + return Ctx.getRegisterInfo()->getEncodingValue( + MI.getOperand(OpNum).getReg()); } - unsigned char getWriteMaskRegisterEncoding(const MCInst &MI, - unsigned OpNum) const { - assert(X86::K0 != MI.getOperand(OpNum).getReg() && - "Invalid mask register as write-mask!"); - unsigned MaskRegNum = GetX86RegNum(MI.getOperand(OpNum)); - return MaskRegNum; + // Does this register require a bit to be set in REX prefix. + bool isREXExtendedReg(const MCInst &MI, unsigned OpNum) const { + return (getX86RegEncoding(MI, OpNum) >> 3) & 1; } - void EmitByte(unsigned char C, unsigned &CurByte, raw_ostream &OS) const { + void EmitByte(uint8_t C, unsigned &CurByte, raw_ostream &OS) const { OS << (char)C; ++CurByte; } @@ -125,8 +106,8 @@ SmallVectorImpl<MCFixup> &Fixups, int ImmOffset = 0) const; - inline static unsigned char ModRMByte(unsigned Mod, unsigned RegOpcode, - unsigned RM) { + inline static uint8_t ModRMByte(unsigned Mod, unsigned RegOpcode, + unsigned RM) { assert(Mod < 4 && RegOpcode < 8 && RM < 8 && "ModRM Fields out of range!"); return RM | (RegOpcode << 3) | (Mod << 6); } @@ -142,11 +123,9 @@ EmitByte(ModRMByte(SS, Index, Base), CurByte, OS); } - - void EmitMemModRMByte(const MCInst &MI, unsigned Op, - unsigned RegOpcodeField, - uint64_t TSFlags, unsigned &CurByte, raw_ostream &OS, - SmallVectorImpl<MCFixup> &Fixups, + void emitMemModRMByte(const MCInst &MI, unsigned Op, unsigned RegOpcodeField, + uint64_t TSFlags, bool Rex, unsigned &CurByte, + raw_ostream &OS, SmallVectorImpl<MCFixup> &Fixups, const MCSubtargetInfo &STI) const; void encodeInstruction(const MCInst &MI, raw_ostream &OS, @@ -160,10 +139,12 @@ void EmitSegmentOverridePrefix(unsigned &CurByte, unsigned SegOperand, const MCInst &MI, raw_ostream &OS) const; - void EmitOpcodePrefix(uint64_t TSFlags, unsigned &CurByte, int MemOperand, + bool emitOpcodePrefix(uint64_t TSFlags, unsigned &CurByte, int MemOperand, const MCInst &MI, const MCInstrDesc &Desc, - const MCSubtargetInfo &STI, - raw_ostream &OS) const; + const MCSubtargetInfo &STI, raw_ostream &OS) const; + + uint8_t DetermineREXPrefix(const MCInst &MI, uint64_t TSFlags, + int MemOperand, const MCInstrDesc &Desc) const; }; } // end anonymous namespace @@ -177,7 +158,7 @@ /// 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; + return Value == (int8_t)Value; } /// isCDisp8 - Return true if this signed displacement fits in a 8-bit @@ -198,7 +179,7 @@ if (Value & Mask) // Unaligned offset return false; Value /= (int)CD8_Scale; - bool Ret = (Value == (signed char)Value); + bool Ret = (Value == (int8_t)Value); if (Ret) CValue = Value; @@ -231,6 +212,10 @@ (IndexReg.getReg() != 0 && X86MCRegisterClasses[X86::GR32RegClassID].contains(IndexReg.getReg()))) return true; + if (BaseReg.getReg() == X86::EIP) { + assert(IndexReg.getReg() == 0 && "Invalid eip-based address."); + return true; + } return false; } @@ -343,7 +328,9 @@ // the start of the field, not the end of the field. if (FixupKind == FK_PCRel_4 || FixupKind == MCFixupKind(X86::reloc_riprel_4byte) || - FixupKind == MCFixupKind(X86::reloc_riprel_4byte_movq_load)) + FixupKind == MCFixupKind(X86::reloc_riprel_4byte_movq_load) || + FixupKind == MCFixupKind(X86::reloc_riprel_4byte_relax) || + FixupKind == MCFixupKind(X86::reloc_riprel_4byte_relax_rex)) ImmOffset -= 4; if (FixupKind == FK_PCRel_2) ImmOffset -= 2; @@ -359,12 +346,12 @@ EmitConstant(0, Size, CurByte, OS); } -void X86MCCodeEmitter::EmitMemModRMByte(const MCInst &MI, unsigned Op, +void X86MCCodeEmitter::emitMemModRMByte(const MCInst &MI, unsigned Op, unsigned RegOpcodeField, - uint64_t TSFlags, unsigned &CurByte, - raw_ostream &OS, + uint64_t TSFlags, bool Rex, + unsigned &CurByte, raw_ostream &OS, SmallVectorImpl<MCFixup> &Fixups, - const MCSubtargetInfo &STI) const{ + const MCSubtargetInfo &STI) const { const MCOperand &Disp = MI.getOperand(Op+X86::AddrDisp); const MCOperand &Base = MI.getOperand(Op+X86::AddrBaseReg); const MCOperand &Scale = MI.getOperand(Op+X86::AddrScaleAmt); @@ -373,18 +360,38 @@ bool HasEVEX = (TSFlags & X86II::EncodingMask) == X86II::EVEX; // Handle %rip relative addressing. - if (BaseReg == X86::RIP) { // [disp32+RIP] in X86-64 mode + if (BaseReg == X86::RIP || + BaseReg == X86::EIP) { // [disp32+rIP] in X86-64 mode assert(is64BitMode(STI) && "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; - + unsigned Opcode = MI.getOpcode(); // 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) - FixupKind = X86::reloc_riprel_4byte_movq_load; + unsigned FixupKind = [=]() { + switch (Opcode) { + default: + return X86::reloc_riprel_4byte; + case X86::MOV64rm: + assert(Rex); + return X86::reloc_riprel_4byte_movq_load; + case X86::CALL64m: + case X86::JMP64m: + case X86::TEST64rm: + case X86::ADC64rm: + case X86::ADD64rm: + case X86::AND64rm: + case X86::CMP64rm: + case X86::OR64rm: + case X86::SBB64rm: + case X86::SUB64rm: + case X86::XOR64rm: + return Rex ? X86::reloc_riprel_4byte_relax_rex + : X86::reloc_riprel_4byte_relax; + } + }(); // rip-relative addressing is actually relative to the *next* instruction. // Since an immediate can follow the mod/rm byte for an instruction, this @@ -510,8 +517,11 @@ // Otherwise, emit the most general non-SIB encoding: [REG+disp32] EmitByte(ModRMByte(2, RegOpcodeField, BaseRegNo), CurByte, OS); - EmitImmediate(Disp, MI.getLoc(), 4, MCFixupKind(X86::reloc_signed_4byte), - CurByte, OS, Fixups); + unsigned Opcode = MI.getOpcode(); + unsigned FixupKind = Opcode == X86::MOV32rm ? X86::reloc_signed_4byte_relax + : X86::reloc_signed_4byte; + EmitImmediate(Disp, MI.getLoc(), 4, MCFixupKind(FixupKind), CurByte, OS, + Fixups); return; } @@ -593,8 +603,6 @@ uint64_t Encoding = TSFlags & X86II::EncodingMask; bool HasEVEX_K = TSFlags & X86II::EVEX_K; bool HasVEX_4V = TSFlags & X86II::VEX_4V; - bool HasVEX_4VOp3 = TSFlags & X86II::VEX_4VOp3; - bool HasMemOp4 = TSFlags & X86II::MemOp4; bool HasEVEX_RC = TSFlags & X86II::EVEX_RC; // VEX_R: opcode externsion equivalent to REX.R in @@ -603,26 +611,26 @@ // 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; - unsigned char EVEX_R2 = 0x1; + uint8_t VEX_R = 0x1; + uint8_t EVEX_R2 = 0x1; // VEX_X: equivalent to REX.X, only used when a // register is used for index in SIB Byte. // // 1: Same as REX.X=0 (must be 1 in 32-bit mode) // 0: Same as REX.X=1 (64-bit mode only) - unsigned char VEX_X = 0x1; + uint8_t VEX_X = 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; + uint8_t 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; + uint8_t VEX_W = (TSFlags & X86II::VEX_W) ? 1 : 0; // VEX_5M (VEX m-mmmmm field): // @@ -634,20 +642,31 @@ // 0b01000: XOP map select - 08h instructions with imm byte // 0b01001: XOP map select - 09h instructions with no imm byte // 0b01010: XOP map select - 0Ah instructions with imm dword - unsigned char VEX_5M = 0; + uint8_t VEX_5M; + switch (TSFlags & X86II::OpMapMask) { + default: llvm_unreachable("Invalid prefix!"); + case X86II::TB: VEX_5M = 0x1; break; // 0F + case X86II::T8: VEX_5M = 0x2; break; // 0F 38 + case X86II::TA: VEX_5M = 0x3; break; // 0F 3A + case X86II::XOP8: VEX_5M = 0x8; break; + case X86II::XOP9: VEX_5M = 0x9; break; + case X86II::XOPA: VEX_5M = 0xA; break; + } // VEX_4V (VEX vvvv field): a register specifier // (in 1's complement form) or 1111 if unused. - unsigned char VEX_4V = 0xf; - unsigned char EVEX_V2 = 0x1; + uint8_t VEX_4V = 0xf; + uint8_t EVEX_V2 = 0x1; - // VEX_L (Vector Length): + // EVEX_L2/VEX_L (Vector Length): // - // 0: scalar or 128-bit vector - // 1: 256-bit vector + // L2 L + // 0 0: scalar or 128-bit vector + // 0 1: 256-bit vector + // 1 0: 512-bit vector // - unsigned char VEX_L = 0; - unsigned char EVEX_L2 = 0; + uint8_t VEX_L = (TSFlags & X86II::VEX_L) ? 1 : 0; + uint8_t EVEX_L2 = (TSFlags & X86II::EVEX_L2) ? 1 : 0; // VEX_PP: opcode extension providing equivalent // functionality of a SIMD prefix @@ -657,55 +676,31 @@ // 0b10: F3 // 0b11: F2 // - unsigned char VEX_PP = 0; - - // EVEX_U - unsigned char EVEX_U = 1; // Always '1' so far - - // EVEX_z - unsigned char EVEX_z = 0; - - // EVEX_b - unsigned char EVEX_b = 0; - - // EVEX_rc - unsigned char EVEX_rc = 0; - - // EVEX_aaa - unsigned char EVEX_aaa = 0; - - bool EncodeRC = false; - - if (TSFlags & X86II::VEX_W) - VEX_W = 1; - - if (TSFlags & X86II::VEX_L) - VEX_L = 1; - if (TSFlags & X86II::EVEX_L2) - EVEX_L2 = 1; - - if (HasEVEX_K && (TSFlags & X86II::EVEX_Z)) - EVEX_z = 1; - - if ((TSFlags & X86II::EVEX_B)) - EVEX_b = 1; - + uint8_t VEX_PP; switch (TSFlags & X86II::OpPrefixMask) { - default: break; // VEX_PP already correct + default: llvm_unreachable("Invalid op prefix!"); + case X86II::PS: VEX_PP = 0x0; break; // none case X86II::PD: VEX_PP = 0x1; break; // 66 case X86II::XS: VEX_PP = 0x2; break; // F3 case X86II::XD: VEX_PP = 0x3; break; // F2 } - switch (TSFlags & X86II::OpMapMask) { - default: llvm_unreachable("Invalid prefix!"); - case X86II::TB: VEX_5M = 0x1; break; // 0F - case X86II::T8: VEX_5M = 0x2; break; // 0F 38 - case X86II::TA: VEX_5M = 0x3; break; // 0F 3A - case X86II::XOP8: VEX_5M = 0x8; break; - case X86II::XOP9: VEX_5M = 0x9; break; - case X86II::XOPA: VEX_5M = 0xA; break; - } + // EVEX_U + uint8_t EVEX_U = 1; // Always '1' so far + + // EVEX_z + uint8_t EVEX_z = (HasEVEX_K && (TSFlags & X86II::EVEX_Z)) ? 1 : 0; + + // EVEX_b + uint8_t EVEX_b = (TSFlags & X86II::EVEX_B) ? 1 : 0; + + // EVEX_rc + uint8_t EVEX_rc = 0; + + // EVEX_aaa + uint8_t EVEX_aaa = 0; + + bool EncodeRC = false; // Classify VEX_B, VEX_4V, VEX_R, VEX_X unsigned NumOps = Desc.getNumOperands(); @@ -721,81 +716,88 @@ // MemAddr, src1(VEX_4V), src2(ModR/M) // MemAddr, src1(ModR/M), imm8 // - if (X86II::isX86_64ExtendedReg(MI.getOperand(MemOperand + - X86::AddrBaseReg).getReg())) - VEX_B = 0x0; - if (X86II::isX86_64ExtendedReg(MI.getOperand(MemOperand + - X86::AddrIndexReg).getReg())) - VEX_X = 0x0; - if (X86II::is32ExtendedReg(MI.getOperand(MemOperand + - X86::AddrIndexReg).getReg())) - EVEX_V2 = 0x0; + unsigned BaseRegEnc = getX86RegEncoding(MI, MemOperand + X86::AddrBaseReg); + VEX_B = ~(BaseRegEnc >> 3) & 1; + unsigned IndexRegEnc = getX86RegEncoding(MI, MemOperand+X86::AddrIndexReg); + VEX_X = ~(IndexRegEnc >> 3) & 1; + if (!HasVEX_4V) // Only needed with VSIB which don't use VVVV. + EVEX_V2 = ~(IndexRegEnc >> 4) & 1; CurOp += X86::AddrNumOperands; if (HasEVEX_K) - EVEX_aaa = getWriteMaskRegisterEncoding(MI, CurOp++); + EVEX_aaa = getX86RegEncoding(MI, CurOp++); if (HasVEX_4V) { - VEX_4V = getVEXRegisterEncoding(MI, CurOp); - if (X86II::is32ExtendedReg(MI.getOperand(CurOp).getReg())) - EVEX_V2 = 0x0; - CurOp++; + unsigned VRegEnc = getX86RegEncoding(MI, CurOp++); + VEX_4V = ~VRegEnc & 0xf; + EVEX_V2 = ~(VRegEnc >> 4) & 1; } - const MCOperand &MO = MI.getOperand(CurOp); - if (MO.isReg()) { - if (X86II::isX86_64ExtendedReg(MO.getReg())) - VEX_R = 0x0; - if (X86II::is32ExtendedReg(MO.getReg())) - EVEX_R2 = 0x0; - } + unsigned RegEnc = getX86RegEncoding(MI, CurOp++); + VEX_R = ~(RegEnc >> 3) & 1; + EVEX_R2 = ~(RegEnc >> 4) & 1; break; } - case X86II::MRMSrcMem: + case X86II::MRMSrcMem: { // MRMSrcMem instructions forms: // src1(ModR/M), MemAddr // src1(ModR/M), src2(VEX_4V), MemAddr // src1(ModR/M), MemAddr, imm8 - // src1(ModR/M), MemAddr, src2(VEX_I8IMM) + // src1(ModR/M), MemAddr, src2(Imm[7:4]) // // FMA4: - // dst(ModR/M.reg), src1(VEX_4V), src2(ModR/M), src3(VEX_I8IMM) - // dst(ModR/M.reg), src1(VEX_4V), src2(VEX_I8IMM), src3(ModR/M), - if (X86II::isX86_64ExtendedReg(MI.getOperand(CurOp).getReg())) - VEX_R = 0x0; - if (X86II::is32ExtendedReg(MI.getOperand(CurOp).getReg())) - EVEX_R2 = 0x0; - CurOp++; + // dst(ModR/M.reg), src1(VEX_4V), src2(ModR/M), src3(Imm[7:4]) + unsigned RegEnc = getX86RegEncoding(MI, CurOp++); + VEX_R = ~(RegEnc >> 3) & 1; + EVEX_R2 = ~(RegEnc >> 4) & 1; if (HasEVEX_K) - EVEX_aaa = getWriteMaskRegisterEncoding(MI, CurOp++); + EVEX_aaa = getX86RegEncoding(MI, CurOp++); if (HasVEX_4V) { - VEX_4V = getVEXRegisterEncoding(MI, CurOp); - if (X86II::is32ExtendedReg(MI.getOperand(CurOp).getReg())) - EVEX_V2 = 0x0; - CurOp++; + unsigned VRegEnc = getX86RegEncoding(MI, CurOp++); + VEX_4V = ~VRegEnc & 0xf; + EVEX_V2 = ~(VRegEnc >> 4) & 1; } - if (X86II::isX86_64ExtendedReg( - MI.getOperand(MemOperand+X86::AddrBaseReg).getReg())) - VEX_B = 0x0; - if (X86II::isX86_64ExtendedReg( - MI.getOperand(MemOperand+X86::AddrIndexReg).getReg())) - VEX_X = 0x0; - if (X86II::is32ExtendedReg(MI.getOperand(MemOperand + - X86::AddrIndexReg).getReg())) - EVEX_V2 = 0x0; + unsigned BaseRegEnc = getX86RegEncoding(MI, MemOperand + X86::AddrBaseReg); + VEX_B = ~(BaseRegEnc >> 3) & 1; + unsigned IndexRegEnc = getX86RegEncoding(MI, MemOperand+X86::AddrIndexReg); + VEX_X = ~(IndexRegEnc >> 3) & 1; + if (!HasVEX_4V) // Only needed with VSIB which don't use VVVV. + EVEX_V2 = ~(IndexRegEnc >> 4) & 1; + + break; + } + case X86II::MRMSrcMem4VOp3: { + // Instruction format for 4VOp3: + // src1(ModR/M), MemAddr, src3(VEX_4V) + unsigned RegEnc = getX86RegEncoding(MI, CurOp++); + VEX_R = ~(RegEnc >> 3) & 1; - if (HasVEX_4VOp3) - // Instruction format for 4VOp3: - // src1(ModR/M), MemAddr, src3(VEX_4V) - // CurOp points to start of the MemoryOperand, - // it skips TIED_TO operands if exist, then increments past src1. - // CurOp + X86::AddrNumOperands will point to src3. - VEX_4V = getVEXRegisterEncoding(MI, CurOp+X86::AddrNumOperands); + unsigned BaseRegEnc = getX86RegEncoding(MI, MemOperand + X86::AddrBaseReg); + VEX_B = ~(BaseRegEnc >> 3) & 1; + unsigned IndexRegEnc = getX86RegEncoding(MI, MemOperand+X86::AddrIndexReg); + VEX_X = ~(IndexRegEnc >> 3) & 1; + + VEX_4V = ~getX86RegEncoding(MI, CurOp + X86::AddrNumOperands) & 0xf; break; + } + case X86II::MRMSrcMemOp4: { + // dst(ModR/M.reg), src1(VEX_4V), src2(Imm[7:4]), src3(ModR/M), + unsigned RegEnc = getX86RegEncoding(MI, CurOp++); + VEX_R = ~(RegEnc >> 3) & 1; + + unsigned VRegEnc = getX86RegEncoding(MI, CurOp++); + VEX_4V = ~VRegEnc & 0xf; + + unsigned BaseRegEnc = getX86RegEncoding(MI, MemOperand + X86::AddrBaseReg); + VEX_B = ~(BaseRegEnc >> 3) & 1; + unsigned IndexRegEnc = getX86RegEncoding(MI, MemOperand+X86::AddrIndexReg); + VEX_X = ~(IndexRegEnc >> 3) & 1; + break; + } case X86II::MRM0m: case X86II::MRM1m: case X86II::MRM2m: case X86II::MRM3m: case X86II::MRM4m: case X86II::MRM5m: @@ -804,58 +806,45 @@ // MemAddr // src1(VEX_4V), MemAddr if (HasVEX_4V) { - VEX_4V = getVEXRegisterEncoding(MI, CurOp); - if (X86II::is32ExtendedReg(MI.getOperand(CurOp).getReg())) - EVEX_V2 = 0x0; - CurOp++; + unsigned VRegEnc = getX86RegEncoding(MI, CurOp++); + VEX_4V = ~VRegEnc & 0xf; + EVEX_V2 = ~(VRegEnc >> 4) & 1; } if (HasEVEX_K) - EVEX_aaa = getWriteMaskRegisterEncoding(MI, CurOp++); + EVEX_aaa = getX86RegEncoding(MI, CurOp++); - if (X86II::isX86_64ExtendedReg( - MI.getOperand(MemOperand+X86::AddrBaseReg).getReg())) - VEX_B = 0x0; - if (X86II::isX86_64ExtendedReg( - MI.getOperand(MemOperand+X86::AddrIndexReg).getReg())) - VEX_X = 0x0; + unsigned BaseRegEnc = getX86RegEncoding(MI, MemOperand + X86::AddrBaseReg); + VEX_B = ~(BaseRegEnc >> 3) & 1; + unsigned IndexRegEnc = getX86RegEncoding(MI, MemOperand+X86::AddrIndexReg); + VEX_X = ~(IndexRegEnc >> 3) & 1; break; } - case X86II::MRMSrcReg: + case X86II::MRMSrcReg: { // MRMSrcReg instructions forms: - // dst(ModR/M), src1(VEX_4V), src2(ModR/M), src3(VEX_I8IMM) + // dst(ModR/M), src1(VEX_4V), src2(ModR/M), src3(Imm[7:4]) // dst(ModR/M), src1(ModR/M) // dst(ModR/M), src1(ModR/M), imm8 // // FMA4: - // dst(ModR/M.reg), src1(VEX_4V), src2(ModR/M), src3(VEX_I8IMM) - // dst(ModR/M.reg), src1(VEX_4V), src2(VEX_I8IMM), src3(ModR/M), - if (X86II::isX86_64ExtendedReg(MI.getOperand(CurOp).getReg())) - VEX_R = 0x0; - if (X86II::is32ExtendedReg(MI.getOperand(CurOp).getReg())) - EVEX_R2 = 0x0; - CurOp++; + // dst(ModR/M.reg), src1(VEX_4V), src2(Imm[7:4]), src3(ModR/M), + unsigned RegEnc = getX86RegEncoding(MI, CurOp++); + VEX_R = ~(RegEnc >> 3) & 1; + EVEX_R2 = ~(RegEnc >> 4) & 1; if (HasEVEX_K) - EVEX_aaa = getWriteMaskRegisterEncoding(MI, CurOp++); + EVEX_aaa = getX86RegEncoding(MI, CurOp++); if (HasVEX_4V) { - VEX_4V = getVEXRegisterEncoding(MI, CurOp); - if (X86II::is32ExtendedReg(MI.getOperand(CurOp).getReg())) - EVEX_V2 = 0x0; - CurOp++; + unsigned VRegEnc = getX86RegEncoding(MI, CurOp++); + VEX_4V = ~VRegEnc & 0xf; + EVEX_V2 = ~(VRegEnc >> 4) & 1; } - if (HasMemOp4) // Skip second register source (encoded in I8IMM) - CurOp++; + RegEnc = getX86RegEncoding(MI, CurOp++); + VEX_B = ~(RegEnc >> 3) & 1; + VEX_X = ~(RegEnc >> 4) & 1; - if (X86II::isX86_64ExtendedReg(MI.getOperand(CurOp).getReg())) - VEX_B = 0x0; - if (X86II::is32ExtendedReg(MI.getOperand(CurOp).getReg())) - VEX_X = 0x0; - CurOp++; - if (HasVEX_4VOp3) - VEX_4V = getVEXRegisterEncoding(MI, CurOp++); if (EVEX_b) { if (HasEVEX_RC) { unsigned RcOperand = NumOps-1; @@ -865,55 +854,80 @@ EncodeRC = true; } break; - case X86II::MRMDestReg: + } + case X86II::MRMSrcReg4VOp3: { + // Instruction format for 4VOp3: + // src1(ModR/M), src2(ModR/M), src3(VEX_4V) + unsigned RegEnc = getX86RegEncoding(MI, CurOp++); + VEX_R = ~(RegEnc >> 3) & 1; + + RegEnc = getX86RegEncoding(MI, CurOp++); + VEX_B = ~(RegEnc >> 3) & 1; + + VEX_4V = ~getX86RegEncoding(MI, CurOp++) & 0xf; + break; + } + case X86II::MRMSrcRegOp4: { + // dst(ModR/M.reg), src1(VEX_4V), src2(Imm[7:4]), src3(ModR/M), + unsigned RegEnc = getX86RegEncoding(MI, CurOp++); + VEX_R = ~(RegEnc >> 3) & 1; + + unsigned VRegEnc = getX86RegEncoding(MI, CurOp++); + VEX_4V = ~VRegEnc & 0xf; + + // Skip second register source (encoded in Imm[7:4]) + ++CurOp; + + RegEnc = getX86RegEncoding(MI, CurOp++); + VEX_B = ~(RegEnc >> 3) & 1; + VEX_X = ~(RegEnc >> 4) & 1; + break; + } + case X86II::MRMDestReg: { // MRMDestReg instructions forms: // dst(ModR/M), src(ModR/M) // dst(ModR/M), src(ModR/M), imm8 // dst(ModR/M), src1(VEX_4V), src2(ModR/M) - if (X86II::isX86_64ExtendedReg(MI.getOperand(CurOp).getReg())) - VEX_B = 0x0; - if (X86II::is32ExtendedReg(MI.getOperand(CurOp).getReg())) - VEX_X = 0x0; - CurOp++; + unsigned RegEnc = getX86RegEncoding(MI, CurOp++); + VEX_B = ~(RegEnc >> 3) & 1; + VEX_X = ~(RegEnc >> 4) & 1; if (HasEVEX_K) - EVEX_aaa = getWriteMaskRegisterEncoding(MI, CurOp++); + EVEX_aaa = getX86RegEncoding(MI, CurOp++); if (HasVEX_4V) { - VEX_4V = getVEXRegisterEncoding(MI, CurOp); - if (X86II::is32ExtendedReg(MI.getOperand(CurOp).getReg())) - EVEX_V2 = 0x0; - CurOp++; + unsigned VRegEnc = getX86RegEncoding(MI, CurOp++); + VEX_4V = ~VRegEnc & 0xf; + EVEX_V2 = ~(VRegEnc >> 4) & 1; } - if (X86II::isX86_64ExtendedReg(MI.getOperand(CurOp).getReg())) - VEX_R = 0x0; - if (X86II::is32ExtendedReg(MI.getOperand(CurOp).getReg())) - EVEX_R2 = 0x0; + RegEnc = getX86RegEncoding(MI, CurOp++); + VEX_R = ~(RegEnc >> 3) & 1; + EVEX_R2 = ~(RegEnc >> 4) & 1; if (EVEX_b) EncodeRC = true; break; + } case X86II::MRM0r: case X86II::MRM1r: case X86II::MRM2r: case X86II::MRM3r: case X86II::MRM4r: case X86II::MRM5r: - case X86II::MRM6r: case X86II::MRM7r: + case X86II::MRM6r: case X86II::MRM7r: { // MRM0r-MRM7r instructions forms: // dst(VEX_4V), src(ModR/M), imm8 if (HasVEX_4V) { - VEX_4V = getVEXRegisterEncoding(MI, CurOp); - if (X86II::is32ExtendedReg(MI.getOperand(CurOp).getReg())) - EVEX_V2 = 0x0; - CurOp++; + unsigned VRegEnc = getX86RegEncoding(MI, CurOp++); + VEX_4V = ~VRegEnc & 0xf; + EVEX_V2 = ~(VRegEnc >> 4) & 1; } if (HasEVEX_K) - EVEX_aaa = getWriteMaskRegisterEncoding(MI, CurOp++); + EVEX_aaa = getX86RegEncoding(MI, CurOp++); - if (X86II::isX86_64ExtendedReg(MI.getOperand(CurOp).getReg())) - VEX_B = 0x0; - if (X86II::is32ExtendedReg(MI.getOperand(CurOp).getReg())) - VEX_X = 0x0; + unsigned RegEnc = getX86RegEncoding(MI, CurOp++); + VEX_B = ~(RegEnc >> 3) & 1; + VEX_X = ~(RegEnc >> 4) & 1; break; } + } if (Encoding == X86II::VEX || Encoding == X86II::XOP) { // VEX opcode prefix can have 2 or 3 bytes @@ -931,7 +945,7 @@ // +-----+ +--------------+ +-------------------+ // | 8Fh | | RXB | m-mmmm | | W | vvvv | L | pp | // +-----+ +--------------+ +-------------------+ - unsigned char LastByte = VEX_PP | (VEX_L << 2) | (VEX_4V << 3); + uint8_t LastByte = VEX_PP | (VEX_L << 2) | (VEX_4V << 3); // Can we use the 2 byte VEX prefix? if (Encoding == X86II::VEX && VEX_B && VEX_X && !VEX_W && (VEX_5M == 1)) { @@ -954,8 +968,6 @@ assert((VEX_5M & 0x3) == VEX_5M && "More than 2 significant bits in VEX.m-mmmm fields for EVEX!"); - VEX_5M &= 0x3; - EmitByte(0x62, CurByte, OS); EmitByte((VEX_R << 7) | (VEX_X << 6) | @@ -968,26 +980,27 @@ VEX_PP, CurByte, OS); if (EncodeRC) EmitByte((EVEX_z << 7) | - (EVEX_rc << 5) | - (EVEX_b << 4) | - (EVEX_V2 << 3) | - EVEX_aaa, CurByte, OS); + (EVEX_rc << 5) | + (EVEX_b << 4) | + (EVEX_V2 << 3) | + EVEX_aaa, CurByte, OS); else EmitByte((EVEX_z << 7) | - (EVEX_L2 << 6) | - (VEX_L << 5) | - (EVEX_b << 4) | - (EVEX_V2 << 3) | - EVEX_aaa, CurByte, OS); + (EVEX_L2 << 6) | + (VEX_L << 5) | + (EVEX_b << 4) | + (EVEX_V2 << 3) | + EVEX_aaa, 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, uint64_t TSFlags, - const MCInstrDesc &Desc) { - unsigned REX = 0; +uint8_t X86MCCodeEmitter::DetermineREXPrefix(const MCInst &MI, uint64_t TSFlags, + int MemOperand, + const MCInstrDesc &Desc) const { + uint8_t REX = 0; bool UsesHighByteReg = false; if (TSFlags & X86II::REX_W) @@ -996,85 +1009,60 @@ if (MI.getNumOperands() == 0) return REX; unsigned NumOps = MI.getNumOperands(); - // FIXME: MCInst should explicitize the two-addrness. - bool isTwoAddr = NumOps > 1 && - Desc.getOperandConstraint(1, MCOI::TIED_TO) != -1; + unsigned CurOp = X86II::getOperandBias(Desc); // If it accesses SPL, BPL, SIL, or DIL, then it requires a 0x40 REX prefix. - unsigned i = isTwoAddr ? 1 : 0; - for (; i != NumOps; ++i) { + for (unsigned i = CurOp; i != NumOps; ++i) { const MCOperand &MO = MI.getOperand(i); if (!MO.isReg()) continue; unsigned Reg = MO.getReg(); if (Reg == X86::AH || Reg == X86::BH || Reg == X86::CH || Reg == X86::DH) UsesHighByteReg = true; - if (!X86II::isX86_64NonExtLowByteReg(Reg)) continue; - // FIXME: The caller of DetermineREXPrefix slaps this prefix onto anything - // that returns non-zero. - REX |= 0x40; // REX fixed encoding prefix - break; + if (X86II::isX86_64NonExtLowByteReg(Reg)) + // FIXME: The caller of DetermineREXPrefix slaps this prefix onto anything + // that returns non-zero. + REX |= 0x40; // REX fixed encoding prefix } switch (TSFlags & X86II::FormMask) { + case X86II::AddRegFrm: + REX |= isREXExtendedReg(MI, CurOp++) << 0; // REX.B + break; case X86II::MRMSrcReg: - if (MI.getOperand(0).isReg() && - X86II::isX86_64ExtendedReg(MI.getOperand(0).getReg())) - REX |= 1 << 2; // set REX.R - i = isTwoAddr ? 2 : 1; - for (; i != NumOps; ++i) { - const MCOperand &MO = MI.getOperand(i); - if (MO.isReg() && X86II::isX86_64ExtendedReg(MO.getReg())) - REX |= 1 << 0; // set REX.B - } + REX |= isREXExtendedReg(MI, CurOp++) << 2; // REX.R + REX |= isREXExtendedReg(MI, CurOp++) << 0; // REX.B break; case X86II::MRMSrcMem: { - if (MI.getOperand(0).isReg() && - X86II::isX86_64ExtendedReg(MI.getOperand(0).getReg())) - REX |= 1 << 2; // set REX.R - unsigned Bit = 0; - i = isTwoAddr ? 2 : 1; - for (; i != NumOps; ++i) { - const MCOperand &MO = MI.getOperand(i); - if (MO.isReg()) { - if (X86II::isX86_64ExtendedReg(MO.getReg())) - REX |= 1 << Bit; // set REX.B (Bit=0) and REX.X (Bit=1) - Bit++; - } - } + REX |= isREXExtendedReg(MI, CurOp++) << 2; // REX.R + REX |= isREXExtendedReg(MI, MemOperand+X86::AddrBaseReg) << 0; // REX.B + REX |= isREXExtendedReg(MI, MemOperand+X86::AddrIndexReg) << 1; // REX.X + CurOp += X86::AddrNumOperands; break; } + case X86II::MRMDestReg: + REX |= isREXExtendedReg(MI, CurOp++) << 0; // REX.B + REX |= isREXExtendedReg(MI, CurOp++) << 2; // REX.R + break; + case X86II::MRMDestMem: + REX |= isREXExtendedReg(MI, MemOperand+X86::AddrBaseReg) << 0; // REX.B + REX |= isREXExtendedReg(MI, MemOperand+X86::AddrIndexReg) << 1; // REX.X + CurOp += X86::AddrNumOperands; + REX |= isREXExtendedReg(MI, CurOp++) << 2; // REX.R + break; case X86II::MRMXm: case X86II::MRM0m: case X86II::MRM1m: case X86II::MRM2m: case X86II::MRM3m: case X86II::MRM4m: case X86II::MRM5m: case X86II::MRM6m: case X86II::MRM7m: - case X86II::MRMDestMem: { - unsigned e = (isTwoAddr ? X86::AddrNumOperands+1 : X86::AddrNumOperands); - i = isTwoAddr ? 1 : 0; - if (NumOps > e && MI.getOperand(e).isReg() && - X86II::isX86_64ExtendedReg(MI.getOperand(e).getReg())) - REX |= 1 << 2; // set REX.R - unsigned Bit = 0; - for (; i != e; ++i) { - const MCOperand &MO = MI.getOperand(i); - if (MO.isReg()) { - if (X86II::isX86_64ExtendedReg(MO.getReg())) - REX |= 1 << Bit; // REX.B (Bit=0) and REX.X (Bit=1) - Bit++; - } - } + REX |= isREXExtendedReg(MI, MemOperand+X86::AddrBaseReg) << 0; // REX.B + REX |= isREXExtendedReg(MI, MemOperand+X86::AddrIndexReg) << 1; // REX.X break; - } - default: - if (MI.getOperand(0).isReg() && - X86II::isX86_64ExtendedReg(MI.getOperand(0).getReg())) - REX |= 1 << 0; // set REX.B - i = isTwoAddr ? 2 : 1; - for (unsigned e = NumOps; i != e; ++i) { - const MCOperand &MO = MI.getOperand(i); - if (MO.isReg() && X86II::isX86_64ExtendedReg(MO.getReg())) - REX |= 1 << 2; // set REX.R - } + case X86II::MRMXr: + case X86II::MRM0r: case X86II::MRM1r: + case X86II::MRM2r: case X86II::MRM3r: + case X86II::MRM4r: case X86II::MRM5r: + case X86II::MRM6r: case X86II::MRM7r: + REX |= isREXExtendedReg(MI, CurOp++) << 0; // REX.B break; } if (REX && UsesHighByteReg) @@ -1101,16 +1089,18 @@ } } -/// EmitOpcodePrefix - Emit all instruction prefixes prior to the opcode. +/// Emit all instruction prefixes prior to the opcode. /// /// MemOperand is the operand # of the start of a memory operand if present. If /// Not present, it is -1. -void X86MCCodeEmitter::EmitOpcodePrefix(uint64_t TSFlags, unsigned &CurByte, +/// +/// Returns true if a REX prefix was used. +bool X86MCCodeEmitter::emitOpcodePrefix(uint64_t TSFlags, unsigned &CurByte, int MemOperand, const MCInst &MI, const MCInstrDesc &Desc, const MCSubtargetInfo &STI, raw_ostream &OS) const { - + bool Ret = false; // Emit the operand size opcode prefix as needed. if ((TSFlags & X86II::OpSizeMask) == (is16BitMode(STI) ? X86II::OpSize32 : X86II::OpSize16)) @@ -1135,8 +1125,10 @@ // Handle REX prefix. // FIXME: Can this come before F2 etc to simplify emission? if (is64BitMode(STI)) { - if (unsigned REX = DetermineREXPrefix(MI, TSFlags, Desc)) + if (uint8_t REX = DetermineREXPrefix(MI, TSFlags, MemOperand, Desc)) { EmitByte(0x40 | REX, CurByte, OS); + Ret = true; + } } // 0x0F escape code must be emitted just before the opcode. @@ -1156,6 +1148,7 @@ EmitByte(0x3A, CurByte, OS); break; } + return Ret; } void X86MCCodeEmitter:: @@ -1181,16 +1174,17 @@ // It uses the VEX.VVVV field? bool HasVEX_4V = TSFlags & X86II::VEX_4V; - bool HasVEX_4VOp3 = TSFlags & X86II::VEX_4VOp3; - bool HasMemOp4 = TSFlags & X86II::MemOp4; - const unsigned MemOp4_I8IMMOperand = 2; + bool HasVEX_I8Reg = (TSFlags & X86II::ImmMask) == X86II::Imm8Reg; // It uses the EVEX.aaa field? bool HasEVEX_K = TSFlags & X86II::EVEX_K; bool HasEVEX_RC = TSFlags & X86II::EVEX_RC; + // Used if a register is encoded in 7:4 of immediate. + unsigned I8RegNum = 0; + // Determine where the memory operand starts, if present. - int MemoryOperand = X86II::getMemoryOperandNo(TSFlags, Opcode); + int MemoryOperand = X86II::getMemoryOperandNo(TSFlags); if (MemoryOperand != -1) MemoryOperand += CurOp; // Emit segment override opcode prefix as needed. @@ -1226,19 +1220,20 @@ if (need_address_override) EmitByte(0x67, CurByte, OS); + bool Rex = false; if (Encoding == 0) - EmitOpcodePrefix(TSFlags, CurByte, MemoryOperand, MI, Desc, STI, OS); + Rex = emitOpcodePrefix(TSFlags, CurByte, MemoryOperand, MI, Desc, STI, OS); else EmitVEXOpcodePrefix(TSFlags, CurByte, MemoryOperand, MI, Desc, OS); - unsigned char BaseOpcode = X86II::getBaseOpcodeFor(TSFlags); + uint8_t BaseOpcode = X86II::getBaseOpcodeFor(TSFlags); if (TSFlags & X86II::Has3DNow0F0FOpcode) BaseOpcode = 0x0F; // Weird 3DNow! encoding. - unsigned SrcRegNum = 0; - switch (TSFlags & X86II::FormMask) { - default: errs() << "FORM: " << (TSFlags & X86II::FormMask) << "\n"; + uint64_t Form = TSFlags & X86II::FormMask; + switch (Form) { + default: errs() << "FORM: " << Form << "\n"; llvm_unreachable("Unknown FormMask value in X86MCCodeEmitter!"); case X86II::Pseudo: llvm_unreachable("Pseudo instruction shouldn't be emitted"); @@ -1315,12 +1310,12 @@ EmitByte(BaseOpcode + GetX86RegNum(MI.getOperand(CurOp++)), CurByte, OS); break; - case X86II::MRMDestReg: + case X86II::MRMDestReg: { EmitByte(BaseOpcode, CurByte, OS); - SrcRegNum = CurOp + 1; + unsigned SrcRegNum = CurOp + 1; if (HasEVEX_K) // Skip writemask - SrcRegNum++; + ++SrcRegNum; if (HasVEX_4V) // Skip 1st src (which is encoded in VEX_VVVV) ++SrcRegNum; @@ -1329,71 +1324,111 @@ GetX86RegNum(MI.getOperand(SrcRegNum)), CurByte, OS); CurOp = SrcRegNum + 1; break; - - case X86II::MRMDestMem: + } + case X86II::MRMDestMem: { EmitByte(BaseOpcode, CurByte, OS); - SrcRegNum = CurOp + X86::AddrNumOperands; + unsigned SrcRegNum = CurOp + X86::AddrNumOperands; if (HasEVEX_K) // Skip writemask - SrcRegNum++; + ++SrcRegNum; if (HasVEX_4V) // Skip 1st src (which is encoded in VEX_VVVV) ++SrcRegNum; - EmitMemModRMByte(MI, CurOp, - GetX86RegNum(MI.getOperand(SrcRegNum)), - TSFlags, CurByte, OS, Fixups, STI); + emitMemModRMByte(MI, CurOp, GetX86RegNum(MI.getOperand(SrcRegNum)), TSFlags, + Rex, CurByte, OS, Fixups, STI); CurOp = SrcRegNum + 1; break; - - case X86II::MRMSrcReg: + } + case X86II::MRMSrcReg: { EmitByte(BaseOpcode, CurByte, OS); - SrcRegNum = CurOp + 1; + unsigned SrcRegNum = CurOp + 1; if (HasEVEX_K) // Skip writemask - SrcRegNum++; + ++SrcRegNum; if (HasVEX_4V) // Skip 1st src (which is encoded in VEX_VVVV) ++SrcRegNum; - if (HasMemOp4) // Skip 2nd src (which is encoded in I8IMM) - ++SrcRegNum; - EmitRegModRMByte(MI.getOperand(SrcRegNum), GetX86RegNum(MI.getOperand(CurOp)), CurByte, OS); - - // 2 operands skipped with HasMemOp4, compensate accordingly - CurOp = HasMemOp4 ? SrcRegNum : SrcRegNum + 1; - if (HasVEX_4VOp3) - ++CurOp; + CurOp = SrcRegNum + 1; + if (HasVEX_I8Reg) + I8RegNum = getX86RegEncoding(MI, CurOp++); // do not count the rounding control operand if (HasEVEX_RC) - NumOps--; + --NumOps; break; + } + case X86II::MRMSrcReg4VOp3: { + EmitByte(BaseOpcode, CurByte, OS); + unsigned SrcRegNum = CurOp + 1; + EmitRegModRMByte(MI.getOperand(SrcRegNum), + GetX86RegNum(MI.getOperand(CurOp)), CurByte, OS); + CurOp = SrcRegNum + 1; + ++CurOp; // Encoded in VEX.VVVV + break; + } + case X86II::MRMSrcRegOp4: { + EmitByte(BaseOpcode, CurByte, OS); + unsigned SrcRegNum = CurOp + 1; + + // Skip 1st src (which is encoded in VEX_VVVV) + ++SrcRegNum; + + // Capture 2nd src (which is encoded in Imm[7:4]) + assert(HasVEX_I8Reg && "MRMSrcRegOp4 should imply VEX_I8Reg"); + I8RegNum = getX86RegEncoding(MI, SrcRegNum++); + + EmitRegModRMByte(MI.getOperand(SrcRegNum), + GetX86RegNum(MI.getOperand(CurOp)), CurByte, OS); + CurOp = SrcRegNum + 1; + break; + } case X86II::MRMSrcMem: { - int AddrOperands = X86::AddrNumOperands; unsigned FirstMemOp = CurOp+1; - if (HasEVEX_K) { // Skip writemask - ++AddrOperands; + if (HasEVEX_K) // Skip writemask ++FirstMemOp; - } - if (HasVEX_4V) { - ++AddrOperands; + if (HasVEX_4V) ++FirstMemOp; // Skip the register source (which is encoded in VEX_VVVV). - } - if (HasMemOp4) // Skip second register source (encoded in I8IMM) - ++FirstMemOp; EmitByte(BaseOpcode, CurByte, OS); - EmitMemModRMByte(MI, FirstMemOp, GetX86RegNum(MI.getOperand(CurOp)), - TSFlags, CurByte, OS, Fixups, STI); - CurOp += AddrOperands + 1; - if (HasVEX_4VOp3) - ++CurOp; + emitMemModRMByte(MI, FirstMemOp, GetX86RegNum(MI.getOperand(CurOp)), + TSFlags, Rex, CurByte, OS, Fixups, STI); + CurOp = FirstMemOp + X86::AddrNumOperands; + if (HasVEX_I8Reg) + I8RegNum = getX86RegEncoding(MI, CurOp++); + break; + } + case X86II::MRMSrcMem4VOp3: { + unsigned FirstMemOp = CurOp+1; + + EmitByte(BaseOpcode, CurByte, OS); + + emitMemModRMByte(MI, FirstMemOp, GetX86RegNum(MI.getOperand(CurOp)), + TSFlags, Rex, CurByte, OS, Fixups, STI); + CurOp = FirstMemOp + X86::AddrNumOperands; + ++CurOp; // Encoded in VEX.VVVV. + break; + } + case X86II::MRMSrcMemOp4: { + unsigned FirstMemOp = CurOp+1; + + ++FirstMemOp; // Skip the register source (which is encoded in VEX_VVVV). + + // Capture second register source (encoded in Imm[7:4]) + assert(HasVEX_I8Reg && "MRMSrcRegOp4 should imply VEX_I8Reg"); + I8RegNum = getX86RegEncoding(MI, FirstMemOp++); + + EmitByte(BaseOpcode, CurByte, OS); + + emitMemModRMByte(MI, FirstMemOp, GetX86RegNum(MI.getOperand(CurOp)), + TSFlags, Rex, CurByte, OS, Fixups, STI); + CurOp = FirstMemOp + X86::AddrNumOperands; break; } @@ -1407,7 +1442,6 @@ if (HasEVEX_K) // Skip writemask ++CurOp; EmitByte(BaseOpcode, CurByte, OS); - uint64_t Form = TSFlags & X86II::FormMask; EmitRegModRMByte(MI.getOperand(CurOp++), (Form == X86II::MRMXr) ? 0 : Form-X86II::MRM0r, CurByte, OS); @@ -1424,9 +1458,9 @@ if (HasEVEX_K) // Skip writemask ++CurOp; EmitByte(BaseOpcode, CurByte, OS); - uint64_t Form = TSFlags & X86II::FormMask; - EmitMemModRMByte(MI, CurOp, (Form == X86II::MRMXm) ? 0 : Form-X86II::MRM0m, - TSFlags, CurByte, OS, Fixups, STI); + emitMemModRMByte(MI, CurOp, + (Form == X86II::MRMXm) ? 0 : Form - X86II::MRM0m, TSFlags, + Rex, CurByte, OS, Fixups, STI); CurOp += X86::AddrNumOperands; break; } @@ -1453,38 +1487,27 @@ case X86II::MRM_FC: case X86II::MRM_FD: case X86II::MRM_FE: case X86II::MRM_FF: EmitByte(BaseOpcode, CurByte, OS); - - uint64_t Form = TSFlags & X86II::FormMask; EmitByte(0xC0 + Form - X86II::MRM_C0, 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. Some instructions - // (SSE4a extrq and insertq) have two trailing immediates. - while (CurOp != NumOps && NumOps - CurOp <= 2) { + if (HasVEX_I8Reg) { // The last source register of a 4 operand instruction in AVX is encoded // in bits[7:4] of a immediate byte. - if (TSFlags & X86II::VEX_I8IMM) { - const MCOperand &MO = MI.getOperand(HasMemOp4 ? MemOp4_I8IMMOperand - : CurOp); - ++CurOp; - unsigned RegNum = GetX86RegNum(MO) << 4; - if (X86II::isX86_64ExtendedReg(MO.getReg())) - RegNum |= 1 << 7; - // If there is an additional 5th operand it must be an immediate, which - // is encoded in bits[3:0] - if (CurOp != NumOps) { - const MCOperand &MIMM = MI.getOperand(CurOp++); - if (MIMM.isImm()) { - unsigned Val = MIMM.getImm(); - assert(Val < 16 && "Immediate operand value out of range"); - RegNum |= Val; - } - } - EmitImmediate(MCOperand::createImm(RegNum), MI.getLoc(), 1, FK_Data_1, - CurByte, OS, Fixups); - } else { + assert(I8RegNum < 16 && "Register encoding out of range"); + I8RegNum <<= 4; + if (CurOp != NumOps) { + unsigned Val = MI.getOperand(CurOp++).getImm(); + assert(Val < 16 && "Immediate operand value out of range"); + I8RegNum |= Val; + } + EmitImmediate(MCOperand::createImm(I8RegNum), MI.getLoc(), 1, FK_Data_1, + CurByte, OS, Fixups); + } else { + // If there is a remaining operand, it must be a trailing immediate. Emit it + // according to the right size for the instruction. Some instructions + // (SSE4a extrq and insertq) have two trailing immediates. + while (CurOp != NumOps && NumOps - CurOp <= 2) { EmitImmediate(MI.getOperand(CurOp++), MI.getLoc(), X86II::getSizeOfImm(TSFlags), getImmFixupKind(TSFlags), CurByte, OS, Fixups);