From 6dc139729882d5c363dda1e0994a71b88da4bd5e Mon Sep 17 00:00:00 2001 From: Douglas Katzman Date: Wed, 13 May 2015 22:44:52 +0000 Subject: [PATCH] [X86] Fix PR23271 - RIP-relative decoding bug in disassembler. Differential Revision: http://reviews.llvm.org/D9110 llvm-svn: 237310 --- .../Disassembler/X86DisassemblerDecoder.cpp | 17 ++++----- llvm/test/MC/Disassembler/X86/x86-64.txt | 38 +++++++++++++++++++ 2 files changed, 46 insertions(+), 9 deletions(-) diff --git a/llvm/lib/Target/X86/Disassembler/X86DisassemblerDecoder.cpp b/llvm/lib/Target/X86/Disassembler/X86DisassemblerDecoder.cpp index 7c9e01273887..d990bf3484bf 100644 --- a/llvm/lib/Target/X86/Disassembler/X86DisassemblerDecoder.cpp +++ b/llvm/lib/Target/X86/Disassembler/X86DisassemblerDecoder.cpp @@ -1366,16 +1366,17 @@ static int readModRM(struct InternalInstruction* insn) { switch (mod) { case 0x0: insn->eaDisplacement = EA_DISP_NONE; /* readSIB may override this */ - switch (rm) { - case 0x14: - case 0x4: - case 0xc: /* in case REXW.b is set */ + // In determining whether RIP-relative mode is used (rm=5), + // or whether a SIB byte is present (rm=4), + // the extension bits (REX.b and EVEX.x) are ignored. + switch (rm & 7) { + case 0x4: // SIB byte is present insn->eaBase = (insn->addressSize == 4 ? EA_BASE_sib : EA_BASE_sib64); if (readSIB(insn) || readDisplacement(insn)) return -1; break; - case 0x5: + case 0x5: // RIP-relative insn->eaBase = EA_BASE_NONE; insn->eaDisplacement = EA_DISP_32; if (readDisplacement(insn)) @@ -1391,10 +1392,8 @@ static int readModRM(struct InternalInstruction* insn) { /* FALLTHROUGH */ case 0x2: insn->eaDisplacement = (mod == 0x1 ? EA_DISP_8 : EA_DISP_32); - switch (rm) { - case 0x14: - case 0x4: - case 0xc: /* in case REXW.b is set */ + switch (rm & 7) { + case 0x4: // SIB byte is present insn->eaBase = EA_BASE_sib; if (readSIB(insn) || readDisplacement(insn)) return -1; diff --git a/llvm/test/MC/Disassembler/X86/x86-64.txt b/llvm/test/MC/Disassembler/X86/x86-64.txt index f000d154984b..5699f40d2d33 100644 --- a/llvm/test/MC/Disassembler/X86/x86-64.txt +++ b/llvm/test/MC/Disassembler/X86/x86-64.txt @@ -301,3 +301,41 @@ # CHECK: movq %rax, 1515870810 0x67, 0x48 0xa3 0x5a 0x5a 0x5a 0x5a + +# CHECK: addq 255(%rip), %rbx +0x49, 0x03, 0x1d, 0xff, 0x00, 0x00, 0x00 + +# The following 4 encodings are equivalent, as confirmed by the 'xed64' +# decoder tool provided by Intel, which we assume to be canonical even +# if the real silicon does something different. If that should happen, +# then we'll all have disassembler bugs to repair. + +# Try all combinations of EVEX.x and REX.b: +# CHECK: vaddps 287453952(%rip), %zmm20, %zmm15 +0x62 0x11 0x5c 0x40 0x58 0x3d 0x00 0x33 0x22 0x11 +# CHECK: vaddps 287453952(%rip), %zmm20, %zmm15 +0x62 0x31 0x5c 0x40 0x58 0x3d 0x00 0x33 0x22 0x11 +# CHECK: vaddps 287453952(%rip), %zmm20, %zmm15 +0x62 0x51 0x5c 0x40 0x58 0x3d 0x00 0x33 0x22 0x11 +# CHECK: vaddps 287453952(%rip), %zmm20, %zmm15 +0x62 0x71 0x5c 0x40 0x58 0x3d 0x00 0x33 0x22 0x11 + +# Known bugs: these use a SIB byte. The index register is incorrectly +# printed as an xmm register. Indeed there are "gather" load instructions +# taking a vector of indices, but ONLY those instructions can do that. +# The CHECK lines test the current incorrect output; FIXME is desired. +# CHECK: vaddps (%r10,%xmm9), %zmm20, %zmm15 +# FIXME: vaddps (%r10,%r9), %zmm20, %zmm15 +0x62 0x11 0x5c 0x40 0x58 0x3c 0x0a + +# CHECK: vaddps (%rdx,%xmm9), %zmm20, %zmm15 +# FIXME: vaddps (%rdx,%r9), %zmm20, %zmm15 +0x62 0x31 0x5c 0x40 0x58 0x3c 0x0a + +# CHECK: vaddps (%r10,%xmm1), %zmm20, %zmm15 +# FIXME: vaddps (%r10,%rcx), %zmm20, %zmm15 +0x62 0x51 0x5c 0x40 0x58 0x3c 0x0a + +# CHECK: vaddps (%rdx,%xmm1), %zmm20, %zmm15 +# FIXME: vaddps (%rdx,%rcx), %zmm20, %zmm15 +0x62 0x71 0x5c 0x40 0x58 0x3c 0x0a