From 7360e8caa397945de67a218d0d9abcee783573a9 Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Mon, 20 Jan 2014 12:02:35 +0000 Subject: [PATCH] [x86] Fix 16-bit handling of OpSize bit When disassembling in 16-bit mode the meaning of the OpSize bit is inverted. Instructions found in the IC_OPSIZE context will actually *not* have the 0x66 prefix, and instructions in the IC context will have the 0x66 prefix. Make use of the existing special-case handling for the 0x66 prefix being in the wrong place, to cope with this. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@199650 91177308-0d34-0410-b5e6-96231b3b80d8 --- .../X86/Disassembler/X86DisassemblerDecoder.c | 8 +- test/MC/Disassembler/X86/x86-16.txt | 788 ++++++++++++++++++ 2 files changed, 793 insertions(+), 3 deletions(-) create mode 100644 test/MC/Disassembler/X86/x86-16.txt diff --git a/lib/Target/X86/Disassembler/X86DisassemblerDecoder.c b/lib/Target/X86/Disassembler/X86DisassemblerDecoder.c index fc19650c7bc..66badd95c32 100644 --- a/lib/Target/X86/Disassembler/X86DisassemblerDecoder.c +++ b/lib/Target/X86/Disassembler/X86DisassemblerDecoder.c @@ -971,7 +971,7 @@ static int getID(struct InternalInstruction* insn, const void *miiArg) { } } else { - if (isPrefixAtLocation(insn, 0x66, insn->necessaryPrefixLocation)) + if (insn->mode != MODE_16BIT && isPrefixAtLocation(insn, 0x66, insn->necessaryPrefixLocation)) attrMask |= ATTR_OPSIZE; else if (isPrefixAtLocation(insn, 0x67, insn->necessaryPrefixLocation)) attrMask |= ATTR_ADSIZE; @@ -989,7 +989,8 @@ static int getID(struct InternalInstruction* insn, const void *miiArg) { /* The following clauses compensate for limitations of the tables. */ - if (insn->prefixPresent[0x66] && !(attrMask & ATTR_OPSIZE)) { + if ((insn->mode == MODE_16BIT || insn->prefixPresent[0x66]) && + !(attrMask & ATTR_OPSIZE)) { /* * The instruction tables make no distinction between instructions that * allow OpSize anywhere (i.e., 16-bit operations) and that need it in a @@ -1021,7 +1022,8 @@ static int getID(struct InternalInstruction* insn, const void *miiArg) { specWithOpSizeName = x86DisassemblerGetInstrName(instructionIDWithOpsize, miiArg); - if (is16BitEquivalent(specName, specWithOpSizeName)) { + if (is16BitEquivalent(specName, specWithOpSizeName) && + (insn->mode == MODE_16BIT) ^ insn->prefixPresent[0x66]) { insn->instructionID = instructionIDWithOpsize; insn->spec = specifierForUID(instructionIDWithOpsize); } else { diff --git a/test/MC/Disassembler/X86/x86-16.txt b/test/MC/Disassembler/X86/x86-16.txt new file mode 100644 index 00000000000..eef8723c9a2 --- /dev/null +++ b/test/MC/Disassembler/X86/x86-16.txt @@ -0,0 +1,788 @@ +# RUN: llvm-mc --disassemble %s -triple=i686-linux-gnu-code16 | FileCheck %s + +# CHECK: movl $305419896, %ebx +0x66 0xbb 0x78 0x56 0x34 0x12 + +# CHECK: pause +0xf3 0x90 + +# CHECK: sfence +0x0f 0xae 0xf8 + +# CHECK: lfence +0x0f 0xae 0xe8 + +# CHECK: mfence +0x0f 0xae 0xf0 + +# CHECK: stgi +0x0f 0x01 0xdc + +# CHECK: clgi +0x0f 0x01 0xdd + +# CHECK: rdtscp +0x0f 0x01 0xf9 + +# CHECK: movl %eax, 16(%ebp) +0x67 0x66 0x89 0x45 0x10 + +# CHECK: movl %eax, -16(%ebp) +0x67 0x66 0x89 0x45 0xf0 + +# CHECK: testb %bl, %cl +0x84 0xcb + +# CHECK: cmpl %eax, %ebx +0x66 0x39 0xc3 + +# CHECK: addw %ax, %ax +0x01 0xc0 + +# CHECK: shrl %eax +0x66 0xd1 0xe8 + +# CHECK: shll %eax +0x66 0xd1 0xe0 + +# CHECK: shll %eax +0x66 0xd1 0xe0 + +# CHECK: movb 0, %al +0xa0 0x00 0x00 + +# CHECK: movw 0, %ax +0xa1 0x00 0x00 + +# CHECK: movl 0, %eax +0x66 0xa1 0x00 0x00 + +# CHECK: into +0xce + +# CHECK: int3 +0xcc + +# CHECK: int $4 +0xcd 0x04 + +# CHECK: int $127 +0xcd 0x7f + +# CHECK: pushfw +0x9c + +# CHECK: pushfl +0x66 0x9c + +# CHECK: popfw +0x9d + +# CHECK: popfl +0x66 0x9d + +# CHECK: retl +0x66 0xc3 + +# CHECK: cmoval %eax, %edx +0x66 0x0f 0x47 0xd0 + +# CHECK: cmovael %eax, %edx +0x66 0x0f 0x43 0xd0 + +# CHECK: cmovbel %eax, %edx +0x66 0x0f 0x46 0xd0 + +# CHECK: cmovbl %eax, %edx +0x66 0x0f 0x42 0xd0 + +# CHECK: cmovbw %bx, %bx +0x0f 0x42 0xdb + +# CHECK: cmovbel %eax, %edx +0x66 0x0f 0x46 0xd0 + +# CHECK: cmovbl %eax, %edx +0x66 0x0f 0x42 0xd0 + +# CHECK: cmovel %eax, %edx +0x66 0x0f 0x44 0xd0 + +# CHECK: cmovgl %eax, %edx +0x66 0x0f 0x4f 0xd0 + +# CHECK: cmovgel %eax, %edx +0x66 0x0f 0x4d 0xd0 + +# CHECK: cmovll %eax, %edx +0x66 0x0f 0x4c 0xd0 + +# CHECK: cmovlel %eax, %edx +0x66 0x0f 0x4e 0xd0 + +# CHECK: cmovbel %eax, %edx +0x66 0x0f 0x46 0xd0 + +# CHECK: cmovnel %eax, %edx +0x66 0x0f 0x45 0xd0 + +# CHECK: cmovael %eax, %edx +0x66 0x0f 0x43 0xd0 + +# CHECK: cmoval %eax, %edx +0x66 0x0f 0x47 0xd0 + +# CHECK: cmovael %eax, %edx +0x66 0x0f 0x43 0xd0 + +# CHECK: cmovnel %eax, %edx +0x66 0x0f 0x45 0xd0 + +# CHECK: cmovlel %eax, %edx +0x66 0x0f 0x4e 0xd0 + +# CHECK: cmovgel %eax, %edx +0x66 0x0f 0x4d 0xd0 + +# CHECK: cmovnel %eax, %edx +0x66 0x0f 0x45 0xd0 + +# CHECK: cmovlel %eax, %edx +0x66 0x0f 0x4e 0xd0 + +# CHECK: cmovll %eax, %edx +0x66 0x0f 0x4c 0xd0 + +# CHECK: cmovgel %eax, %edx +0x66 0x0f 0x4d 0xd0 + +# CHECK: cmovgl %eax, %edx +0x66 0x0f 0x4f 0xd0 + +# CHECK: cmovnol %eax, %edx +0x66 0x0f 0x41 0xd0 + +# CHECK: cmovnpl %eax, %edx +0x66 0x0f 0x4b 0xd0 + +# CHECK: cmovnsl %eax, %edx +0x66 0x0f 0x49 0xd0 + +# CHECK: cmovnel %eax, %edx +0x66 0x0f 0x45 0xd0 + +# CHECK: cmovol %eax, %edx +0x66 0x0f 0x40 0xd0 + +# CHECK: cmovpl %eax, %edx +0x66 0x0f 0x4a 0xd0 + +# CHECK: cmovsl %eax, %edx +0x66 0x0f 0x48 0xd0 + +# CHECK: cmovel %eax, %edx +0x66 0x0f 0x44 0xd0 + +# CHECK: fmul %st(0) +0xd8 0xc8 + +# CHECK: fadd %st(0) +0xd8 0xc0 + +# CHECK: fsub %st(0) +0xd8 0xe0 + +# CHECK: fsubr %st(0) +0xd8 0xe8 + +# CHECK: fdivr %st(0) +0xd8 0xf8 + +# CHECK: fdiv %st(0) +0xd8 0xf0 + +# CHECK: movl %cs, %eax +0x66 0x8c 0xc8 + +# CHECK: movw %cs, %ax +0x8c 0xc8 + +# CHECK: movl %cs, (%eax) +0x67 0x66 0x8c 0x08 + +# CHECK: movw %cs, (%eax) +0x67 0x8c 0x08 + +# CHECK: movl %eax, %cs +0x66 0x8e 0xc8 + +# CHECK: movl (%eax), %cs +0x67 0x66 0x8e 0x08 + +# CHECK: movw (%eax), %cs +0x67 0x8e 0x08 + +# CHECKX: movl %cr0, %eax +0x0f 0x20 0xc0 + +# CHECKX: movl %cr1, %eax +0x0f 0x20 0xc8 + +# CHECKX: movl %cr2, %eax +0x0f 0x20 0xd0 + +# CHECKX: movl %cr3, %eax +0x0f 0x20 0xd8 + +# CHECKX: movl %cr4, %eax +0x0f 0x20 0xe0 + +# CHECKX: movl %dr0, %eax +0x0f 0x21 0xc0 + +# CHECKX: movl %dr1, %eax +0x0f 0x21 0xc8 + +# CHECKX: movl %dr1, %eax +0x0f 0x21 0xc8 + +# CHECKX: movl %dr2, %eax +0x0f 0x21 0xd0 + +# CHECKX: movl %dr3, %eax +0x0f 0x21 0xd8 + +# CHECKX: movl %dr4, %eax +0x0f 0x21 0xe0 + +# CHECKX: movl %dr5, %eax +0x0f 0x21 0xe8 + +# CHECKX: movl %dr6, %eax +0x0f 0x21 0xf0 + +# CHECKX: movl %dr7, %eax +0x0f 0x21 0xf8 + +# CHECK: wait +0x9b + +# CHECK: movl %gs:124, %eax +0x65 0x66 0x8b 0x06 0x7c 0x00 + +# CHECK: pushaw +0x60 + +# CHECK: popaw +0x61 + +# CHECK: pushaw +0x60 + +# CHECK: popaw +0x61 + +# CHECK: pushal +0x66 0x60 + +# CHECK: popal +0x66 0x61 + +# CHECK: jmpw *8(%eax) +0x67 0xff 0x60 0x08 + +# CHECK: jmpl *8(%eax) +0x67 0x66 0xff 0x60 0x08 + +# CHECK: lcalll $2, $4660 +0x66 0x9a 0x34 0x12 0x00 0x00 0x02 0x00 + +# CHECKX: jcxz +0xe3 0x00 + +# CHECKX: jecxz +0x67 0xe3 0x00 + +# CHECK: iretw +0xcf + +# CHECK: iretw +0xcf + +# CHECK: iretl +0x66 0xcf + +# CHECK: sysretl +0x0f 0x07 + +# CHECK: sysretl +0x0f 0x07 + +# CHECK: testl -24(%ebp), %ecx +0x67 0x66 0x85 0x4d 0xe8 + +# CHECK: testl -24(%ebp), %ecx +0x67 0x66 0x85 0x4d 0xe8 + +# CHECK: pushw %cs +0x0e + +# CHECK: pushw %ds +0x1e + +# CHECK: pushw %ss +0x16 + +# CHECK: pushw %es +0x06 + +# CHECK: pushw %fs +0x0f 0xa0 + +# CHECK: pushw %gs +0x0f 0xa8 + +# CHECK: pushw %cs +0x0e + +# CHECK: pushw %ds +0x1e + +# CHECK: pushw %ss +0x16 + +# CHECK: pushw %es +0x06 + +# CHECK: pushw %fs +0x0f 0xa0 + +# CHECK: pushw %gs +0x0f 0xa8 + +# CHECK: pushl %cs +0x66 0x0e + +# CHECK: pushl %ds +0x66 0x1e + +# CHECK: pushl %ss +0x66 0x16 + +# CHECK: pushl %es +0x66 0x06 + +# CHECK: pushl %fs +0x66 0x0f 0xa0 + +# CHECK: pushl %gs +0x66 0x0f 0xa8 + +# CHECK: popw %ss +0x17 + +# CHECK: popw %ds +0x1f + +# CHECK: popw %es +0x07 + +# CHECK: popl %ss +0x66 0x17 + +# CHECK: popl %ds +0x66 0x1f + +# CHECK: popl %es +0x66 0x07 + +# CHECK: pushfl +0x66 0x9c + +# CHECK: popfl +0x66 0x9d + +# CHECK: pushfl +0x66 0x9c + +# CHECK: popfl +0x66 0x9d + +# CHECK: setb %bl +0x0f 0x92 0xc3 + +# CHECK: setb %bl +0x0f 0x92 0xc3 + +# CHECK: setae %bl +0x0f 0x93 0xc3 + +# CHECK: setae %bl +0x0f 0x93 0xc3 + +# CHECK: setbe %bl +0x0f 0x96 0xc3 + +# CHECK: seta %bl +0x0f 0x97 0xc3 + +# CHECK: setp %bl +0x0f 0x9a 0xc3 + +# CHECK: setnp %bl +0x0f 0x9b 0xc3 + +# CHECK: setl %bl +0x0f 0x9c 0xc3 + +# CHECK: setge %bl +0x0f 0x9d 0xc3 + +# CHECK: setle %bl +0x0f 0x9e 0xc3 + +# CHECK: setg %bl +0x0f 0x9f 0xc3 + +# CHECK: setne %cl +0x0f 0x95 0xc1 + +# CHECK: setb %bl +0x0f 0x92 0xc3 + +# CHECK: setb %bl +0x0f 0x92 0xc3 + +# CHECK: lcalll $31438, $31438 +0x66 0x9a 0xce 0x7a 0x00 0x00 0xce 0x7a + +# CHECK: lcalll $31438, $31438 +0x66 0x9a 0xce 0x7a 0x00 0x00 0xce 0x7a + +# CHECK: ljmpl $31438, $31438 +0x66 0xea 0xce 0x7a 0x00 0x00 0xce 0x7a + +# CHECK: ljmpl $31438, $31438 +0x66 0xea 0xce 0x7a 0x00 0x00 0xce 0x7a + +# CHECK: lcallw $31438, $31438 +0x9a 0xce 0x7a 0xce 0x7a + +# CHECK: lcallw $31438, $31438 +0x9a 0xce 0x7a 0xce 0x7a + +# CHECK: ljmpw $31438, $31438 +0xea 0xce 0x7a 0xce 0x7a + +# CHECK: ljmpw $31438, $31438 +0xea 0xce 0x7a 0xce 0x7a + +# CHECK: lcallw $31438, $31438 +0x9a 0xce 0x7a 0xce 0x7a + +# CHECK: lcallw $31438, $31438 +0x9a 0xce 0x7a 0xce 0x7a + +# CHECK: ljmpw $31438, $31438 +0xea 0xce 0x7a 0xce 0x7a + +# CHECK: ljmpw $31438, $31438 +0xea 0xce 0x7a 0xce 0x7a + +# CHECK: calll +0x66 0xe8 0x00 0x00 0x00 0x00 + +# CHECKX: callw +#0xe8 0x00 0x00 + +# CHECK: incb %al +0xfe 0xc0 + +# CHECK: incw %ax +0x40 + +# CHECK: incl %eax +0x66 0x40 + +# CHECK: decb %al +0xfe 0xc8 + +# CHECK: decw %ax +0x48 + +# CHECK: decl %eax +0x66 0x48 + +# CHECK: pshufw $14, %mm4, %mm0 +0x0f 0x70 0xc4 0x0e + +# CHECK: pshufw $90, %mm4, %mm0 +0x0f 0x70 0xc4 0x5a + +# CHECK: aaa +0x37 + +# CHECK: aad $1 +0xd5 0x01 + +# CHECK: aad +0xd5 0x0a + +# CHECK: aad +0xd5 0x0a + +# CHECK: aam $2 +0xd4 0x02 + +# CHECK: aam +0xd4 0x0a + +# CHECK: aam +0xd4 0x0a + +# CHECK: aas +0x3f + +# CHECK: daa +0x27 + +# CHECK: das +0x2f + +# CHECK: retw $31438 +0xc2 0xce 0x7a + +# CHECK: lretw $31438 +0xca 0xce 0x7a + +# CHECK: retw $31438 +0xc2 0xce 0x7a + +# CHECK: lretw $31438 +0xca 0xce 0x7a + +# CHECK: retl $31438 +0x66 0xc2 0xce 0x7a + +# CHECK: lretl $31438 +0x66 0xca 0xce 0x7a + +# CHECK: bound 2(%eax), %bx +0x67 0x62 0x58 0x02 + +# CHECK: bound 4(%ebx), %ecx +0x67 0x66 0x62 0x4b 0x04 + +# CHECK: arpl %bx, %bx +0x63 0xdb + +# CHECK: arpl %bx, 6(%ecx) +0x67 0x63 0x59 0x06 + +# CHECK: lgdtw 4(%eax) +0x67 0x0f 0x01 0x50 0x04 + +# CHECK: lgdtw 4(%eax) +0x67 0x0f 0x01 0x50 0x04 + +# CHECK: lgdtl 4(%eax) +0x67 0x66 0x0f 0x01 0x50 0x04 + +# CHECK: lidtw 4(%eax) +0x67 0x0f 0x01 0x58 0x04 + +# CHECK: lidtw 4(%eax) +0x67 0x0f 0x01 0x58 0x04 + +# CHECK: lidtl 4(%eax) +0x67 0x66 0x0f 0x01 0x58 0x04 + +# CHECK: sgdtw 4(%eax) +0x67 0x0f 0x01 0x40 0x04 + +# CHECK: sgdtw 4(%eax) +0x67 0x0f 0x01 0x40 0x04 + +# CHECK: sgdtl 4(%eax) +0x67 0x66 0x0f 0x01 0x40 0x04 + +# CHECK: sidtw 4(%eax) +0x67 0x0f 0x01 0x48 0x04 + +# CHECK: sidtw 4(%eax) +0x67 0x0f 0x01 0x48 0x04 + +# CHECK: sidtl 4(%eax) +0x67 0x66 0x0f 0x01 0x48 0x04 + +# CHECK: fcompi %st(2) +0xdf 0xf2 + +# CHECK: fcompi %st(2) +0xdf 0xf2 + +# CHECK: fcompi %st(1) +0xdf 0xf1 + +# CHECK: fucompi %st(2) +0xdf 0xea + +# CHECK: fucompi %st(2) +0xdf 0xea + +# CHECK: fucompi %st(1) +0xdf 0xe9 + +# CHECK: fldcw 32493 +0xd9 0x2e 0xed 0x7e + +# CHECK: fldcw 32493 +0xd9 0x2e 0xed 0x7e + +# CHECK: fnstcw 32493 +0xd9 0x3e 0xed 0x7e + +# CHECK: fnstcw 32493 +0xd9 0x3e 0xed 0x7e + +# CHECK: wait +0x9b + +# CHECK: fnstcw 32493 +0xd9 0x3e 0xed 0x7e + +# CHECK: wait +0x9b + +# CHECK: fnstcw 32493 +0xd9 0x3e 0xed 0x7e + +# CHECK: fnstsw 32493 +0xdd 0x3e 0xed 0x7e + +# CHECK: fnstsw 32493 +0xdd 0x3e 0xed 0x7e + +# CHECK: wait +0x9b + +# CHECK: fnstsw 32493 +0xdd 0x3e 0xed 0x7e + +# CHECK: wait +0x9b + +# CHECK: fnstsw 32493 +0xdd 0x3e 0xed 0x7e + +# CHECK: verr 32493 +0x0f 0x00 0x26 0xed 0x7e + +# CHECK: verr 32493 +0x0f 0x00 0x26 0xed 0x7e + +# CHECK: wait +0x9b + +# CHECK: fnclex +0xdb 0xe2 + +# CHECK: fnclex +0xdb 0xe2 + +# CHECK: ud2 +0x0f 0x0b + +# CHECK: ud2 +0x0f 0x0b + +# CHECK: ud2b +0x0f 0xb9 + +# CHECK: loope +0xe1 0x00 + +# CHECK: loopne +0xe0 0x00 + +# CHECK: outsb +0x6e + +# CHECKX: outsw +0x6f + +# CHECKX: outsl +0x66 0x6f + +# CHECK: insb +0x6c + +# CHECK: insw +0x6d + +# CHECK: insl +0x66 0x6d + +# CHECK: movsb +0xa4 + +# CHECKX: movsw +0xa5 + +# CHECKX: movsl +0x66 0xa5 + +# CHECKX: lodsb +0xac + +# CHECKX: lodsw +0xad + +# CHECKX: lodsl +0x66 0xad + +# CHECK: stosb +0xaa + +# CHECKX: stosw +0xab + +# CHECKX: stosl +0x66 0xab + +# CHECK: strw %ax +0x0f 0x00 0xc8 + +# CHECK: strl %eax +0x66 0x0f 0x00 0xc8 + +# CHECK: fsubp %st(1) +0xde 0xe1 + +# CHECK: fsubp %st(2) +0xde 0xe2 + +# CHECKX: nop +0x66 0x90 + +# CHECKX: nop +0x90 + +# CHECK: xchgl %ecx, %eax +0x66 0x91 + +# CHECK: xchgl %ecx, %eax +0x66 0x91 + +# CHECK: retw +0xc3 + +# CHECK: retl +0x66 0xc3 + +# CHECK: lretw +0xcb + +# CHECK: lretl +0x66 0xcb +