diff options
author | Craig Topper <craig.topper@gmail.com> | 2013-03-14 07:40:52 +0000 |
---|---|---|
committer | Craig Topper <craig.topper@gmail.com> | 2013-03-14 07:40:52 +0000 |
commit | 9d3f3c5f400578855f6f7b71670cb8514b4fac0f (patch) | |
tree | 6287e25763d71a4761cf532a02e5764266ffe912 | |
parent | 599521f1671d720a2c786058810537287920f44a (diff) | |
download | llvm-9d3f3c5f400578855f6f7b71670cb8514b4fac0f.tar.gz llvm-9d3f3c5f400578855f6f7b71670cb8514b4fac0f.tar.bz2 llvm-9d3f3c5f400578855f6f7b71670cb8514b4fac0f.tar.xz |
Fix a bug in the calculation of the VEX.B bit for FMA4 rr with the VEX.W bit set. The VEX.B was being calculated from the wrong operand. Fixes at least some portion of PR14185.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@177014 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp | 8 | ||||
-rw-r--r-- | lib/Target/X86/X86CodeEmitter.cpp | 5 | ||||
-rw-r--r-- | test/MC/X86/x86_64-fma4-encoding.s | 4 |
3 files changed, 17 insertions, 0 deletions
diff --git a/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp b/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp index 122204ae75..30c56061b9 100644 --- a/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp +++ b/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp @@ -446,6 +446,7 @@ void X86MCCodeEmitter::EmitVEXOpcodePrefix(uint64_t TSFlags, unsigned &CurByte, raw_ostream &OS) const { 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; // VEX_R: opcode externsion equivalent to REX.R in // 1's complement (inverted) form @@ -650,12 +651,19 @@ void X86MCCodeEmitter::EmitVEXOpcodePrefix(uint64_t TSFlags, unsigned &CurByte, // 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; CurOp++; if (HasVEX_4V) VEX_4V = getVEXRegisterEncoding(MI, CurOp++); + + if (HasMemOp4) // Skip second register source (encoded in I8IMM) + CurOp++; + if (X86II::isX86_64ExtendedReg(MI.getOperand(CurOp).getReg())) VEX_B = 0x0; CurOp++; diff --git a/lib/Target/X86/X86CodeEmitter.cpp b/lib/Target/X86/X86CodeEmitter.cpp index ece38aa346..a6bb2a7426 100644 --- a/lib/Target/X86/X86CodeEmitter.cpp +++ b/lib/Target/X86/X86CodeEmitter.cpp @@ -816,6 +816,7 @@ void Emitter<CodeEmitter>::emitVEXOpcodePrefix(uint64_t TSFlags, const MCInstrDesc *Desc) const { 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; // VEX_R: opcode externsion equivalent to REX.R in // 1's complement (inverted) form @@ -1032,6 +1033,10 @@ void Emitter<CodeEmitter>::emitVEXOpcodePrefix(uint64_t TSFlags, if (HasVEX_4V) VEX_4V = getVEXRegisterEncoding(MI, CurOp++); + + if (MemOp4) // Skip second register source (encoded in I8IMM) + CurOp++; + if (X86II::isX86_64ExtendedReg(MI.getOperand(CurOp).getReg())) VEX_B = 0x0; CurOp++; diff --git a/test/MC/X86/x86_64-fma4-encoding.s b/test/MC/X86/x86_64-fma4-encoding.s index f7ee351ab5..c9bd954e90 100644 --- a/test/MC/X86/x86_64-fma4-encoding.s +++ b/test/MC/X86/x86_64-fma4-encoding.s @@ -25,6 +25,10 @@ // CHECK: encoding: [0xc4,0xe3,0xf9,0x6b,0xc2,0x10] vfmaddsd %xmm2, %xmm1, %xmm0, %xmm0 +// CHECK: vfmaddsd %xmm10, %xmm1, %xmm0, %xmm0 +// CHECK: encoding: [0xc4,0xc3,0xf9,0x6b,0xc2,0x10] + vfmaddsd %xmm10, %xmm1, %xmm0, %xmm0 + // CHECK: vfmaddps (%rcx), %xmm1, %xmm0, %xmm0 // CHECK: encoding: [0xc4,0xe3,0xf9,0x68,0x01,0x10] vfmaddps (%rcx), %xmm1, %xmm0, %xmm0 |