summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorKevin Enderby <enderby@apple.com>2013-06-20 22:32:18 +0000
committerKevin Enderby <enderby@apple.com>2013-06-20 22:32:18 +0000
commit46d7de7a192f43eb568c26c88e2dc2b804c09614 (patch)
treea1e06e5fe54de1f0c2bcc67026036dd06837e99e /lib
parent1c97082f53f15cca7f7db3a14663ef1f928c4bef (diff)
downloadllvm-46d7de7a192f43eb568c26c88e2dc2b804c09614.tar.gz
llvm-46d7de7a192f43eb568c26c88e2dc2b804c09614.tar.bz2
llvm-46d7de7a192f43eb568c26c88e2dc2b804c09614.tar.xz
Update the X86 disassembler to use xacquire and xrelease when appropriate.
This is a bit tricky as the xacquire and xrelease hints use the same bytes, 0xf2 and 0xf3, as the repne and rep prefixes. Fortunately llvm has different llvm MCInst Opcode enums for rep/xrelease and repne/xacquire. So to make this work a boolean was added the InternalInstruction struct as part of the Prefix state which is set with the added logic in readPrefixes() when decoding an instruction to determine if these prefix bytes are to be disassembled as xacquire or xrelease. Then we let the matcher pick the normal prefix instructionID and we change the Opcode after that when it is set into the MCInst being created. rdar://11019859 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@184490 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib')
-rw-r--r--lib/Target/X86/Disassembler/X86Disassembler.cpp9
-rw-r--r--lib/Target/X86/Disassembler/X86DisassemblerDecoder.c21
-rw-r--r--lib/Target/X86/Disassembler/X86DisassemblerDecoder.h2
3 files changed, 32 insertions, 0 deletions
diff --git a/lib/Target/X86/Disassembler/X86Disassembler.cpp b/lib/Target/X86/Disassembler/X86Disassembler.cpp
index ca71c4f351..f03068e0cd 100644
--- a/lib/Target/X86/Disassembler/X86Disassembler.cpp
+++ b/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/lib/Target/X86/Disassembler/X86DisassemblerDecoder.c b/lib/Target/X86/Disassembler/X86DisassemblerDecoder.c
index e40edba6d6..55ab8ebe7b 100644
--- a/lib/Target/X86/Disassembler/X86DisassemblerDecoder.c
+++ b/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/lib/Target/X86/Disassembler/X86DisassemblerDecoder.h b/lib/Target/X86/Disassembler/X86DisassemblerDecoder.h
index 407ead3caf..04a0dc038b 100644
--- a/lib/Target/X86/Disassembler/X86DisassemblerDecoder.h
+++ b/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;