[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
This commit is contained in:
David Woodhouse
2014-01-20 12:02:35 +00:00
parent e6f5bb99fc
commit 7360e8caa3
2 changed files with 793 additions and 3 deletions

View File

@@ -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 {