diff options
4 files changed, 61 insertions, 1 deletions
diff --git a/llvm/lib/Target/X86/Disassembler/X86Disassembler.cpp b/llvm/lib/Target/X86/Disassembler/X86Disassembler.cpp index ca71c4f3519..f03068e0cdc 100644 --- a/llvm/lib/Target/X86/Disassembler/X86Disassembler.cpp +++ b/llvm/lib/Target/X86/Disassembler/X86Disassembler.cpp @@ -683,6 +683,15 @@ static bool translateInstruction(MCInst &mcInst, } mcInst.setOpcode(insn.instructionID); + // If when reading the prefix bytes we determined the overlapping 0xf2 or 0xf3 + // prefix bytes should be disassembled as xrelease and xacquire then set the + // opcode to those instead of the rep and repne opcodes. + if (insn.xAcquireRelease) { + if(mcInst.getOpcode() == X86::REP_PREFIX) + mcInst.setOpcode(X86::XRELEASE_PREFIX); + else if(mcInst.getOpcode() == X86::REPNE_PREFIX) + mcInst.setOpcode(X86::XACQUIRE_PREFIX); + } int index; diff --git a/llvm/lib/Target/X86/Disassembler/X86DisassemblerDecoder.c b/llvm/lib/Target/X86/Disassembler/X86DisassemblerDecoder.c index e40edba6d68..55ab8ebe7b0 100644 --- a/llvm/lib/Target/X86/Disassembler/X86DisassemblerDecoder.c +++ b/llvm/lib/Target/X86/Disassembler/X86DisassemblerDecoder.c @@ -328,6 +328,27 @@ static int readPrefixes(struct InternalInstruction* insn) { break; if (lookAtByte(insn, &nextByte)) return -1; + /* + * If the byte is 0xf2 or 0xf3, and any of the following conditions are + * met: + * - it is followed by a LOCK (0xf0) prefix + * - it is followed by an xchg instruction + * then it should be disassembled as a xacquire/xrelease not repne/rep. + */ + if ((byte == 0xf2 || byte == 0xf3) && + ((nextByte == 0xf0) | + ((nextByte & 0xfe) == 0x86 || (nextByte & 0xf8) == 0x90))) + insn->xAcquireRelease = TRUE; + /* + * Also if the byte is 0xf3, and the following condition is met: + * - it is followed by a "mov mem, reg" (opcode 0x88/0x89) or + * "mov mem, imm" (opcode 0xc6/0xc7) instructions. + * then it should be disassembled as an xrelease not rep. + */ + if (byte == 0xf3 && + (nextByte == 0x88 || nextByte == 0x89 || + nextByte == 0xc6 || nextByte == 0xc7)) + insn->xAcquireRelease = TRUE; if (insn->mode == MODE_64BIT && (nextByte & 0xf0) == 0x40) { if (consumeByte(insn, &nextByte)) return -1; diff --git a/llvm/lib/Target/X86/Disassembler/X86DisassemblerDecoder.h b/llvm/lib/Target/X86/Disassembler/X86DisassemblerDecoder.h index 407ead3cafa..04a0dc038bc 100644 --- a/llvm/lib/Target/X86/Disassembler/X86DisassemblerDecoder.h +++ b/llvm/lib/Target/X86/Disassembler/X86DisassemblerDecoder.h @@ -457,6 +457,8 @@ struct InternalInstruction { uint64_t necessaryPrefixLocation; /* The segment override type */ SegmentOverride segmentOverride; + /* 1 if the prefix byte, 0xf2 or 0xf3 is xacquire or xrelease */ + BOOL xAcquireRelease; /* Sizes of various critical pieces of data, in bytes */ uint8_t registerSize; diff --git a/llvm/test/MC/Disassembler/X86/simple-tests.txt b/llvm/test/MC/Disassembler/X86/simple-tests.txt index 9827a1809f1..d51f0a1c926 100644 --- a/llvm/test/MC/Disassembler/X86/simple-tests.txt +++ b/llvm/test/MC/Disassembler/X86/simple-tests.txt @@ -764,7 +764,35 @@ # CHECK: repne # CHECK-NEXT: movb $0, (%rax) 0xf2 0xc6 0x0 0x0 -# CHECK: rep + +# rdar://11019859 Support 2013 Haswell RTM instructions and HLE prefixes +# CHECK: xrelease # CHECK-NEXT: lock # CHECK-NEXT: incl (%rax) 0xf3 0xf0 0xff 0x00 + +# CHECK: xrelease +# CHECK-NEXT: xchgl %ebx, %eax +0xf3 0x93 +# CHECK: xrelease +# CHECK-NEXT: xchgl %ebx, (%rax) +0xf3 0x87 0x18 +# CHECK: xrelease +# CHECK-NEXT: movb %al, (%rbx) +0xf3 0x88 0x03 +# CHECK: xrelease +# CHECK-NEXT: movl %eax, (%rbx) +0xf3 0x89 0x03 +# CHECK: xrelease +# CHECK-NEXT: movb $1, (%rbx) +0xf3 0xc6 0x03 0x01 +# CHECK: xrelease +# CHECK-NEXT: movl $1, (%rbx) +0xf3 0xc7 0x03 0x01 0x00 0x00 0x00 + +# CHECK: xacquire +# CHECK-NEXT: xchgl %ebx, %eax +0xf2 0x93 +# CHECK: xacquire +# CHECK-NEXT: xchgl %ebx, (%rax) +0xf2 0x87 0x18 |