llvm.org GIT mirror llvm / 51f423f
[X86] Fix disassembly of absolute moves to work correctly in 16 and 32-bit modes with all 4 combinations of OpSize and AdSize prefixes being present or not. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@225036 91177308-0d34-0410-b5e6-96231b3b80d8 Craig Topper 4 years ago
4 changed file(s) with 53 addition(s) and 20 deletion(s). Raw diff Collapse all Expand all
10161016 return 0;
10171017 }
10181018 }
1019 }
1020
1021 /*
1022 * Absolute moves need special handling.
1023 * -For 16-bit mode because the meaning of the AdSize and OpSize prefixes are
1024 * inverted w.r.t.
1025 * -For 32-bit mode we need to ensure the ADSIZE prefix is observed in
1026 * any position.
1027 */
1028 if (insn->opcodeType == ONEBYTE && ((insn->opcode & 0xFC) == 0xA0)) {
1029 /* Make sure we observed the prefixes in any position. */
1030 if (insn->prefixPresent[0x67])
1031 attrMask |= ATTR_ADSIZE;
1032 if (insn->prefixPresent[0x66])
1033 attrMask |= ATTR_OPSIZE;
1034
1035 /* In 16-bit, invert the attributes. */
1036 if (insn->mode == MODE_16BIT)
1037 attrMask ^= ATTR_ADSIZE | ATTR_OPSIZE;
1038
1039 if (getIDWithAttrMask(&instructionID, insn, attrMask))
1040 return -1;
1041
1042 insn->instructionID = instructionID;
1043 insn->spec = specifierForUID(instructionID);
1044 return 0;
10191045 }
10201046
10211047 if ((insn->mode == MODE_16BIT || insn->prefixPresent[0x66]) &&
8181 "operands change width") \
8282 ENUM_ENTRY(IC_ADSIZE, 3, "requires an ADSIZE prefix, so " \
8383 "operands change width") \
84 ENUM_ENTRY(IC_OPSIZE_ADSIZE, 4, "requires ADSIZE and OPSIZE prefixes") \
8485 ENUM_ENTRY(IC_XD, 2, "may say something about the opcode " \
8586 "but not the operands") \
8687 ENUM_ENTRY(IC_XS, 2, "may say something about the opcode " \
8990 "operands change width") \
9091 ENUM_ENTRY(IC_XS_OPSIZE, 3, "requires an OPSIZE prefix, so " \
9192 "operands change width") \
92 ENUM_ENTRY(IC_64BIT_REXW, 4, "requires a REX.W prefix, so operands "\
93 ENUM_ENTRY(IC_64BIT_REXW, 5, "requires a REX.W prefix, so operands "\
9394 "change width; overrides IC_OPSIZE") \
9495 ENUM_ENTRY(IC_64BIT_OPSIZE, 3, "Just as meaningful as IC_OPSIZE") \
9596 ENUM_ENTRY(IC_64BIT_ADSIZE, 3, "Just as meaningful as IC_ADSIZE") \
96 ENUM_ENTRY(IC_64BIT_XD, 5, "XD instructions are SSE; REX.W is " \
97 ENUM_ENTRY(IC_64BIT_OPSIZE_ADSIZE, 4, "Just as meaningful as IC_OPSIZE/" \
98 "IC_ADSIZE") \
99 ENUM_ENTRY(IC_64BIT_XD, 6, "XD instructions are SSE; REX.W is " \
97100 "secondary") \
98 ENUM_ENTRY(IC_64BIT_XS, 5, "Just as meaningful as IC_64BIT_XD") \
101 ENUM_ENTRY(IC_64BIT_XS, 6, "Just as meaningful as IC_64BIT_XD") \
99102 ENUM_ENTRY(IC_64BIT_XD_OPSIZE, 3, "Just as meaningful as IC_XD_OPSIZE") \
100103 ENUM_ENTRY(IC_64BIT_XS_OPSIZE, 3, "Just as meaningful as IC_XS_OPSIZE") \
101 ENUM_ENTRY(IC_64BIT_REXW_XS, 6, "OPSIZE could mean a different " \
104 ENUM_ENTRY(IC_64BIT_REXW_XS, 7, "OPSIZE could mean a different " \
102105 "opcode") \
103 ENUM_ENTRY(IC_64BIT_REXW_XD, 6, "Just as meaningful as " \
106 ENUM_ENTRY(IC_64BIT_REXW_XD, 7, "Just as meaningful as " \
104107 "IC_64BIT_REXW_XS") \
105 ENUM_ENTRY(IC_64BIT_REXW_OPSIZE, 7, "The Dynamic Duo! Prefer over all " \
108 ENUM_ENTRY(IC_64BIT_REXW_OPSIZE, 8, "The Dynamic Duo! Prefer over all " \
106109 "else because this changes most " \
107110 "operands' meaning") \
108111 ENUM_ENTRY(IC_VEX, 1, "requires a VEX prefix") \
9292 inheritsFrom(child, IC_64BIT_XD) ||
9393 inheritsFrom(child, IC_64BIT_XS));
9494 case IC_OPSIZE:
95 return inheritsFrom(child, IC_64BIT_OPSIZE);
95 return inheritsFrom(child, IC_64BIT_OPSIZE) ||
96 inheritsFrom(child, IC_OPSIZE_ADSIZE);
9697 case IC_ADSIZE:
98 return inheritsFrom(child, IC_OPSIZE_ADSIZE);
99 case IC_OPSIZE_ADSIZE:
100 return false;
97101 case IC_64BIT_ADSIZE:
102 return inheritsFrom(child, IC_64BIT_OPSIZE_ADSIZE);
103 case IC_64BIT_OPSIZE_ADSIZE:
98104 return false;
99105 case IC_XD:
100106 return inheritsFrom(child, IC_64BIT_XD);
109115 inheritsFrom(child, IC_64BIT_REXW_XD) ||
110116 inheritsFrom(child, IC_64BIT_REXW_OPSIZE));
111117 case IC_64BIT_OPSIZE:
112 return(inheritsFrom(child, IC_64BIT_REXW_OPSIZE));
118 return inheritsFrom(child, IC_64BIT_REXW_OPSIZE) ||
119 inheritsFrom(child, IC_64BIT_OPSIZE_ADSIZE);
113120 case IC_64BIT_XD:
114121 return(inheritsFrom(child, IC_64BIT_REXW_XD));
115122 case IC_64BIT_XS:
720727 o << "IC_64BIT_XS";
721728 else if ((index & ATTR_64BIT) && (index & ATTR_XD))
722729 o << "IC_64BIT_XD";
730 else if ((index & ATTR_64BIT) && (index & ATTR_OPSIZE) &&
731 (index & ATTR_ADSIZE))
732 o << "IC_64BIT_OPSIZE_ADSIZE";
723733 else if ((index & ATTR_64BIT) && (index & ATTR_OPSIZE))
724734 o << "IC_64BIT_OPSIZE";
725735 else if ((index & ATTR_64BIT) && (index & ATTR_ADSIZE))
736746 o << "IC_XS";
737747 else if (index & ATTR_XD)
738748 o << "IC_XD";
749 else if ((index & ATTR_OPSIZE) && (index & ATTR_ADSIZE))
750 o << "IC_OPSIZE_ADSIZE";
739751 else if (index & ATTR_OPSIZE)
740752 o << "IC_OPSIZE";
741753 else if (index & ATTR_ADSIZE)
821833 InstructionSpecifier &previousInfo =
822834 InstructionSpecifiers[decision.instructionIDs[index]];
823835
824 // FIXME this doesn't actually work. The MCInsts the disassembler
825 // create don't encode re-encode correctly. They just manage to mostly
826 // print correctly.
827 // Instructions such as MOV8ao8 and MOV8ao8_16 differ only in the
828 // presence of the AdSize prefix. However, the disassembler doesn't
829 // care about that difference in the instruction definition; it
830 // handles 16-bit vs. 32-bit addressing for itself based purely
831 // on the 0x67 prefix and the CPU mode. So there's no need to
832 // disambiguate between them; just let them conflict/coexist.
833 if (previousInfo.name + "_16" == newInfo.name)
834 continue;
835
836836 if(previousInfo.name == "NOOP" && (newInfo.name == "XCHG16ar" ||
837837 newInfo.name == "XCHG32ar" ||
838838 newInfo.name == "XCHG32ar64" ||
411411 insnContext = IC_64BIT_XD_OPSIZE;
412412 else if (OpSize == X86Local::OpSize16 && OpPrefix == X86Local::XS)
413413 insnContext = IC_64BIT_XS_OPSIZE;
414 else if (OpSize == X86Local::OpSize16 && AdSize == X86Local::AdSize32)
415 insnContext = IC_64BIT_OPSIZE_ADSIZE;
414416 else if (OpSize == X86Local::OpSize16 || OpPrefix == X86Local::PD)
415417 insnContext = IC_64BIT_OPSIZE;
416418 else if (AdSize == X86Local::AdSize32)
432434 insnContext = IC_XD_OPSIZE;
433435 else if (OpSize == X86Local::OpSize16 && OpPrefix == X86Local::XS)
434436 insnContext = IC_XS_OPSIZE;
437 else if (OpSize == X86Local::OpSize16 && AdSize == X86Local::AdSize16)
438 insnContext = IC_OPSIZE_ADSIZE;
435439 else if (OpSize == X86Local::OpSize16 || OpPrefix == X86Local::PD)
436440 insnContext = IC_OPSIZE;
437441 else if (AdSize == X86Local::AdSize16)