[X86] Fix PR23271 - RIP-relative decoding bug in disassembler.
authorDouglas Katzman <dougk@google.com>
Wed, 13 May 2015 22:44:52 +0000 (22:44 +0000)
committerDouglas Katzman <dougk@google.com>
Wed, 13 May 2015 22:44:52 +0000 (22:44 +0000)
Differential Revision: http://reviews.llvm.org/D9110

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@237310 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Target/X86/Disassembler/X86DisassemblerDecoder.cpp
test/MC/Disassembler/X86/x86-64.txt

index 7c9e012738875d2d8ff60ca0fcdfa2e2c487565d..d990bf3484bf4479d7ae4810973ad2ab8ff81608 100644 (file)
@@ -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;
index f000d154984bc282145eabb4315afc894ca364ea..5699f40d2d331fe7b39082f9a9d9d3119b20673e 100644 (file)
 
 # 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