diff options
author | Lorry Tar Creator <lorry-tar-importer@lorry> | 2017-06-27 06:07:23 +0000 |
---|---|---|
committer | Lorry Tar Creator <lorry-tar-importer@lorry> | 2017-06-27 06:07:23 +0000 |
commit | 1bf1084f2b10c3b47fd1a588d85d21ed0eb41d0c (patch) | |
tree | 46dcd36c86e7fbc6e5df36deb463b33e9967a6f7 /Source/JavaScriptCore/disassembler | |
parent | 32761a6cee1d0dee366b885b7b9c777e67885688 (diff) | |
download | WebKitGtk-tarball-master.tar.gz |
webkitgtk-2.16.5HEADwebkitgtk-2.16.5master
Diffstat (limited to 'Source/JavaScriptCore/disassembler')
29 files changed, 17959 insertions, 276 deletions
diff --git a/Source/JavaScriptCore/disassembler/ARM64/A64DOpcode.cpp b/Source/JavaScriptCore/disassembler/ARM64/A64DOpcode.cpp index 0ea817a46..9584f4953 100644 --- a/Source/JavaScriptCore/disassembler/ARM64/A64DOpcode.cpp +++ b/Source/JavaScriptCore/disassembler/ARM64/A64DOpcode.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012 Apple Inc. All rights reserved. + * Copyright (C) 2012, 2016 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -24,6 +24,9 @@ */ #include "config.h" + +#if USE(ARM64_DISASSEMBLER) + #include "A64DOpcode.h" #include <stdarg.h> @@ -62,6 +65,8 @@ struct OpcodeGroupInitializer { { groupIndex, groupClass::mask, groupClass::pattern, groupClass::format } static OpcodeGroupInitializer opcodeGroupList[] = { + OPCODE_GROUP_ENTRY(0x08, A64DOpcodeLoadStoreRegisterPair), + OPCODE_GROUP_ENTRY(0x09, A64DOpcodeLoadStoreRegisterPair), OPCODE_GROUP_ENTRY(0x0a, A64DOpcodeLogicalShiftedRegister), OPCODE_GROUP_ENTRY(0x0b, A64DOpcodeAddSubtractExtendedRegister), OPCODE_GROUP_ENTRY(0x0b, A64DOpcodeAddSubtractShiftedRegister), @@ -78,6 +83,7 @@ static OpcodeGroupInitializer opcodeGroupList[] = { OPCODE_GROUP_ENTRY(0x15, A64DOpcodeConditionalBranchImmediate), OPCODE_GROUP_ENTRY(0x15, A64DOpcodeCompareAndBranchImmediate), OPCODE_GROUP_ENTRY(0x15, A64DOpcodeHint), + OPCODE_GROUP_ENTRY(0x15, A64DOpcodeDmb), OPCODE_GROUP_ENTRY(0x16, A64DOpcodeUnconditionalBranchImmediate), OPCODE_GROUP_ENTRY(0x16, A64DOpcodeUnconditionalBranchRegister), OPCODE_GROUP_ENTRY(0x16, A64DOpcodeTestAndBranchImmediate), @@ -88,12 +94,14 @@ static OpcodeGroupInitializer opcodeGroupList[] = { OPCODE_GROUP_ENTRY(0x18, A64DOpcodeLoadStoreRegisterOffset), OPCODE_GROUP_ENTRY(0x19, A64DOpcodeLoadStoreUnsignedImmediate), OPCODE_GROUP_ENTRY(0x1a, A64DOpcodeConditionalSelect), + OPCODE_GROUP_ENTRY(0x1a, A64DOpcodeDataProcessing1Source), OPCODE_GROUP_ENTRY(0x1a, A64DOpcodeDataProcessing2Source), OPCODE_GROUP_ENTRY(0x1b, A64DOpcodeDataProcessing3Source), OPCODE_GROUP_ENTRY(0x1c, A64DOpcodeLoadStoreImmediate), OPCODE_GROUP_ENTRY(0x1c, A64DOpcodeLoadStoreRegisterOffset), OPCODE_GROUP_ENTRY(0x1d, A64DOpcodeLoadStoreUnsignedImmediate), OPCODE_GROUP_ENTRY(0x1e, A64DOpcodeFloatingPointCompare), + OPCODE_GROUP_ENTRY(0x1e, A64DOpcodeFloatingPointConditionalSelect), OPCODE_GROUP_ENTRY(0x1e, A64DOpcodeFloatingPointDataProcessing2Source), OPCODE_GROUP_ENTRY(0x1e, A64DOpcodeFloatingPointDataProcessing1Source), OPCODE_GROUP_ENTRY(0x1e, A64DOpcodeFloatingFixedPointConversions), @@ -172,6 +180,11 @@ const char* A64DOpcode::format() void A64DOpcode::appendRegisterName(unsigned registerNumber, bool is64Bit) { + if (registerNumber == 29) { + bufferPrintf(is64Bit ? "fp" : "wfp"); + return; + } + if (registerNumber == 30) { bufferPrintf(is64Bit ? "lr" : "wlr"); return; @@ -276,7 +289,7 @@ const char* const A64DOpcodeBitfield::s_opNames[3] = { "sbfm", "bfm", "ubfm" }; const char* const A64DOpcodeBitfield::s_extendPseudoOpNames[3][3] = { { "sxtb", "sxth", "sxtw" }, { 0, 0, 0} , { "uxtb", "uxth", "uxtw" } }; const char* const A64DOpcodeBitfield::s_insertOpNames[3] = { "sbfiz", "bfi", "ubfiz" }; -const char* const A64DOpcodeBitfield::s_extractOpNames[3] = { "sbfx", "bf", "ubfx" }; +const char* const A64DOpcodeBitfield::s_extractOpNames[3] = { "sbfx", "bfxil", "ubfx" }; const char* A64DOpcodeBitfield::format() { @@ -298,7 +311,7 @@ const char* A64DOpcodeBitfield::format() } else if (immediateS() == 15) { appendInstructionName(extendPseudoOpNames(1)); isSTXType = true; - } else if (immediateS() == 31 && is64Bit()) { + } else if (immediateS() == 31 && is64Bit() && !opc()) { appendInstructionName(extendPseudoOpNames(2)); isSTXType = true; } @@ -312,19 +325,9 @@ const char* A64DOpcodeBitfield::format() } } - if (opc() == 0x2 && immediateS() == (immediateR() + 1)) { - // lsl - appendInstructionName("lsl"); - appendRegisterName(rd(), is64Bit()); - appendSeparator(); - appendRegisterName(rn(), is64Bit()); - appendSeparator(); - appendUnsignedImmediate((is64Bit() ? 63u : 31u) - immediateR()); - - return m_formatBuffer; - } else if (!(opc() & 0x1) && ((immediateS() & 0x1f) == 0x1f) && (is64Bit() == (immediateS() >> 5))) { + if (!(opc() & 0x1) && ((immediateS() & 0x1f) == 0x1f) && (is64Bit() == (immediateS() >> 5))) { // asr/lsr - appendInstructionName(!opc() ? "ars" : "lsr"); + appendInstructionName(!opc() ? "asr" : "lsr"); appendRegisterName(rd(), is64Bit()); appendSeparator(); @@ -333,42 +336,58 @@ const char* A64DOpcodeBitfield::format() appendUnsignedImmediate(immediateR()); return m_formatBuffer; - } else if (immediateS() < immediateR()) { - // bit field insert - appendInstructionName(insertOpNames()); + } + if (opc() == 0x2 && (immediateS() + 1) == immediateR()) { + // lsl + appendInstructionName("lsl"); appendRegisterName(rd(), is64Bit()); appendSeparator(); appendRegisterName(rn(), is64Bit()); appendSeparator(); appendUnsignedImmediate((is64Bit() ? 64u : 32u) - immediateR()); - appendSeparator(); - appendUnsignedImmediate(immediateS() + 1); - + return m_formatBuffer; - } else { - // bit field extract - appendInstructionName(extractOpNames()); + } + + if (immediateS() < immediateR()) { + if (opc() != 1 || rn() != 0x1f) { + // bit field insert + appendInstructionName(insertOpNames()); + appendRegisterName(rd(), is64Bit()); + appendSeparator(); + appendRegisterName(rn(), is64Bit()); + appendSeparator(); + appendUnsignedImmediate((is64Bit() ? 64u : 32u) - immediateR()); + appendSeparator(); + appendUnsignedImmediate(immediateS() + 1); + + return m_formatBuffer; + } + + appendInstructionName(opName()); appendRegisterName(rd(), is64Bit()); appendSeparator(); appendRegisterName(rn(), is64Bit()); appendSeparator(); appendUnsignedImmediate(immediateR()); appendSeparator(); - appendUnsignedImmediate(immediateS() - immediateR() + 1); - + appendUnsignedImmediate(immediateS()); + return m_formatBuffer; } + + // bit field extract + appendInstructionName(extractOpNames()); - appendInstructionName(opName()); appendRegisterName(rd(), is64Bit()); appendSeparator(); appendRegisterName(rn(), is64Bit()); appendSeparator(); appendUnsignedImmediate(immediateR()); appendSeparator(); - appendUnsignedImmediate(immediateS()); + appendUnsignedImmediate(immediateS() - immediateR() + 1); return m_formatBuffer; } @@ -430,6 +449,38 @@ const char* A64DOpcodeConditionalSelect::format() } +const char* const A64DOpcodeDataProcessing1Source::s_opNames[8] = { + "rbit", "rev16", "rev32", "rev", "clz", "cls", 0, 0 +}; + +const char* A64DOpcodeDataProcessing1Source::format() +{ + if (sBit()) + return A64DOpcode::format(); + + if (opCode2()) + return A64DOpcode::format(); + + if (opCode() & 0x38) + return A64DOpcode::format(); + + if ((opCode() & 0x3e) == 0x6) + return A64DOpcode::format(); + + if (is64Bit() && opCode() == 0x3) + return A64DOpcode::format(); + + if (!is64Bit() && opCode() == 0x2) + appendInstructionName("rev"); + else + appendInstructionName(opName()); + appendZROrRegisterName(rd(), is64Bit()); + appendSeparator(); + appendZROrRegisterName(rn(), is64Bit()); + + return m_formatBuffer; +} + const char* const A64DOpcodeDataProcessing2Source::s_opNames[8] = { 0, 0, "udiv", "sdiv", "lsl", "lsr", "asr", "ror" // We use the pseudo-op names for the shift/rotate instructions }; @@ -449,11 +500,11 @@ const char* A64DOpcodeDataProcessing2Source::format() return A64DOpcode::format(); appendInstructionName(opName()); - appendRegisterName(rd(), is64Bit()); + appendZROrRegisterName(rd(), is64Bit()); appendSeparator(); - appendRegisterName(rn(), is64Bit()); + appendZROrRegisterName(rn(), is64Bit()); appendSeparator(); - appendRegisterName(rm(), is64Bit()); + appendZROrRegisterName(rm(), is64Bit()); return m_formatBuffer; } @@ -482,15 +533,18 @@ const char* A64DOpcodeDataProcessing3Source::format() if (!opName()) return A64DOpcode::format(); + if ((opNum() & 0x4) && (ra() != 31)) + return A64DOpcode::format(); + appendInstructionName(opName()); - appendRegisterName(rd(), is64Bit()); + appendZROrRegisterName(rd(), is64Bit()); appendSeparator(); bool srcOneAndTwoAre64Bit = is64Bit() & !(opNum() & 0x2); - appendRegisterName(rn(), srcOneAndTwoAre64Bit); + appendZROrRegisterName(rn(), srcOneAndTwoAre64Bit); appendSeparator(); - appendRegisterName(rm(), srcOneAndTwoAre64Bit); + appendZROrRegisterName(rm(), srcOneAndTwoAre64Bit); - if ((ra() != 31) || !(opNum() & 0x4)) { + if (ra() != 31) { appendSeparator(); appendRegisterName(ra(), is64Bit()); } @@ -550,23 +604,26 @@ const char* A64OpcodeExceptionGeneration::format() const char* A64DOpcodeExtract::format() { - if (!op21() || !o0Bit()) + if (op21() || o0Bit()) return A64DOpcode::format(); if (is64Bit() != nBit()) return A64DOpcode::format(); - if (is64Bit() && (immediateS() & 0x20)) + if (!is64Bit() && (immediateS() & 0x20)) return A64DOpcode::format(); - const char* opName = (rn() == rm()) ? "ror" : "extr"; + bool isROR = rn() == rm(); + const char* opName = (isROR) ? "ror" : "extr"; appendInstructionName(opName); - appendRegisterName(rd(), is64Bit()); + appendZROrRegisterName(rd(), is64Bit()); appendSeparator(); - appendRegisterName(rn(), is64Bit()); - appendSeparator(); - appendRegisterName(rm(), is64Bit()); + appendZROrRegisterName(rn(), is64Bit()); + if (!isROR) { + appendSeparator(); + appendZROrRegisterName(rm(), is64Bit()); + } appendSeparator(); appendUnsignedImmediate(immediateS()); @@ -602,6 +659,30 @@ const char* A64DOpcodeFloatingPointCompare::format() return m_formatBuffer; } +const char* A64DOpcodeFloatingPointConditionalSelect::format() +{ + if (mBit()) + return A64DOpcode::format(); + + if (sBit()) + return A64DOpcode::format(); + + if (type() & 0x2) + return A64DOpcode::format(); + + appendInstructionName(opName()); + unsigned registerSize = type() + 2; + appendFPRegisterName(rd(), registerSize); + appendSeparator(); + appendFPRegisterName(rn(), registerSize); + appendSeparator(); + appendFPRegisterName(rm(), registerSize); + appendSeparator(); + appendString(conditionName(condition())); + + return m_formatBuffer; +} + const char* const A64DOpcodeFloatingPointDataProcessing1Source::s_opNames[16] = { "fmov", "fabs", "fneg", "fsqrt", "fcvt", "fcvt", 0, "fcvt", "frintn", "frintp", "frintm", "frintz", "frinta", 0, "frintx", "frinti" @@ -770,10 +851,10 @@ const char* A64DOpcodeFloatingPointIntegerConversions::format() // fmov Vd.D[1], Xn bufferPrintf("V%u.D[1]", rd()); appendSeparator(); - appendRegisterName(rn()); + appendZROrRegisterName(rn()); } else { // fmov Xd, Vn.D[1] - appendRegisterName(rd()); + appendZROrRegisterName(rd()); appendSeparator(); bufferPrintf("V%u.D[1]", rn()); } @@ -788,9 +869,9 @@ const char* A64DOpcodeFloatingPointIntegerConversions::format() if (destIsFP) { appendFPRegisterName(rd(), FPRegisterSize); appendSeparator(); - appendRegisterName(rn(), is64Bit()); + appendZROrRegisterName(rn(), is64Bit()); } else { - appendRegisterName(rd(), is64Bit()); + appendZROrRegisterName(rd(), is64Bit()); appendSeparator(); appendFPRegisterName(rn(), FPRegisterSize); } @@ -812,6 +893,23 @@ const char* A64DOpcodeHint::format() return m_formatBuffer; } +const char* const A64DOpcodeDmb::s_optionNames[16] = { + 0, "oshld", "oshst", "osh", 0, "nshld", "nshst", "nsh", + 0, "ishld", "ishst", "ish", 0, "ld", "st", "sy" +}; + +const char* A64DOpcodeDmb::format() +{ + appendInstructionName(opName()); + const char* thisOption = option(); + if (thisOption) + appendString(thisOption); + else + appendUnsignedImmediate(crM()); + + return m_formatBuffer; +} + // A zero in an entry of the table means the instruction is Unallocated const char* const A64DOpcodeLoadStore::s_opNames[32] = { "strb", "ldrb", "ldrsb", "ldrsb", "str", "ldr", "str", "ldr", @@ -853,6 +951,8 @@ const char* A64DOpcodeLoadStoreImmediate::format() appendInstructionName(thisOpName); if (vBit()) appendFPRegisterName(rt(), size()); + else if (!opc()) + appendZROrRegisterName(rt(), is64BitRT()); else appendRegisterName(rt(), is64BitRT()); appendSeparator(); @@ -910,31 +1010,99 @@ const char* A64DOpcodeLoadStoreRegisterOffset::format() appendFPRegisterName(rt(), size()); scale = ((opc() & 2)<<1) | size(); } else { - appendRegisterName(rt(), is64BitRT()); + if (!opc()) + appendZROrRegisterName(rt(), is64BitRT()); + else + appendRegisterName(rt(), is64BitRT()); scale = size(); } appendSeparator(); appendCharacter('['); appendSPOrRegisterName(rn()); - appendSeparator(); - appendZROrRegisterName(rm(), (option() & 0x3) == 0x3); + if (rm() != 31) { + appendSeparator(); + appendRegisterName(rm(), (option() & 0x3) == 0x3); - unsigned shift = sBit() ? scale : 0; + unsigned shift = sBit() ? scale : 0; - if (option() == 0x3) { - if (shift) { + if (option() == 0x3) { + if (shift) { + appendSeparator(); + appendString("lsl "); + appendUnsignedImmediate(shift); + } + } else { appendSeparator(); - appendString("lsl "); - appendUnsignedImmediate(shift); + appendString(optionName()); + if (shift) + appendUnsignedImmediate(shift); } + } + + appendCharacter(']'); + + return m_formatBuffer; +} + +const char* A64DOpcodeLoadStoreRegisterPair::opName() +{ + if (!vBit() && lBit() && size() == 0x1) + return "ldpsw"; + if (lBit()) + return "ldp"; + return "stp"; +} + +const char* A64DOpcodeLoadStoreRegisterPair::format() +{ + const char* thisOpName = opName(); + + if (size() == 0x3) + return A64DOpcode::format(); + + if ((offsetMode() < 0x1) || (offsetMode() > 0x3)) + return A64DOpcode::format(); + + if ((offsetMode() == 0x1) && !vBit() && !lBit()) + return A64DOpcode::format(); + + appendInstructionName(thisOpName); + unsigned offsetShift; + if (vBit()) { + appendFPRegisterName(rt(), size()); + appendSeparator(); + appendFPRegisterName(rt2(), size()); + offsetShift = size() + 2; } else { + if (!lBit()) + appendZROrRegisterName(rt(), is64Bit()); + else + appendRegisterName(rt(), is64Bit()); appendSeparator(); - appendString(optionName()); - if (shift) - appendUnsignedImmediate(shift); + if (!lBit()) + appendZROrRegisterName(rt2(), is64Bit()); + else + appendRegisterName(rt2(), is64Bit()); + offsetShift = (size() >> 1) + 2; } - appendCharacter(']'); + appendSeparator(); + appendCharacter('['); + appendSPOrRegisterName(rn()); + + int offset = immediate7() << offsetShift; + + if (offsetMode() == 1) { + appendCharacter(']'); + appendSeparator(); + appendSignedImmediate(offset); + } else { + appendSeparator(); + appendSignedImmediate(offset); + appendCharacter(']'); + if (offsetMode() == 0x3) + appendCharacter('!'); + } return m_formatBuffer; } @@ -952,7 +1120,10 @@ const char* A64DOpcodeLoadStoreUnsignedImmediate::format() appendFPRegisterName(rt(), size()); scale = ((opc() & 2)<<1) | size(); } else { - appendRegisterName(rt(), is64BitRT()); + if (!opc()) + appendZROrRegisterName(rt(), is64BitRT()); + else + appendRegisterName(rt(), is64BitRT()); scale = size(); } appendSeparator(); @@ -983,15 +1154,15 @@ const char* A64DOpcodeLogicalShiftedRegister::format() appendInstructionName("tst"); else { if (isMov()) - appendInstructionName("mov"); + appendInstructionName(nBit() ? "mvn" : "mov"); else appendInstructionName(opName(opNumber())); - appendSPOrRegisterName(rd(), is64Bit()); + appendZROrRegisterName(rd(), is64Bit()); appendSeparator(); } if (!isMov()) { - appendRegisterName(rn(), is64Bit()); + appendZROrRegisterName(rn(), is64Bit()); appendSeparator(); } @@ -1075,22 +1246,39 @@ const char* A64DOpcodeLogicalImmediate::format() return m_formatBuffer; } -const char* const A64DOpcodeMoveWide::s_opNames[4] = { "movn", "", "movz", "movk" }; +const char* const A64DOpcodeMoveWide::s_opNames[4] = { "movn", 0, "movz", "movk" }; const char* A64DOpcodeMoveWide::format() { if (opc() == 1) return A64DOpcode::format(); - if (!size() && hw() >= 2) + if (!is64Bit() && hw() >= 2) return A64DOpcode::format(); - appendInstructionName(opName()); - appendRegisterName(rd(), is64Bit()); - appendSeparator(); - appendUnsignedImmediate(immediate16()); - if (hw()) { + if (!opc() && (!immediate16() || !hw()) && (is64Bit() || immediate16() != 0xffff)) { + // MOV pseudo op for MOVN + appendInstructionName("mov"); + appendRegisterName(rd(), is64Bit()); appendSeparator(); - appendShiftAmount(hw()); + + if (is64Bit()) { + int64_t amount = immediate16() << (hw() * 16); + amount = ~amount; + appendSignedImmediate64(amount); + } else { + int32_t amount = immediate16() << (hw() * 16); + amount = ~amount; + appendSignedImmediate(amount); + } + } else { + appendInstructionName(opName()); + appendRegisterName(rd(), is64Bit()); + appendSeparator(); + appendUnsignedHexImmediate(immediate16()); + if (hw()) { + appendSeparator(); + appendShiftAmount(hw()); + } } return m_formatBuffer; @@ -1130,3 +1318,5 @@ const char* A64DOpcodeUnconditionalBranchRegister::format() } } } // namespace JSC::ARM64Disassembler + +#endif // USE(ARM64_DISASSEMBLER) diff --git a/Source/JavaScriptCore/disassembler/ARM64/A64DOpcode.h b/Source/JavaScriptCore/disassembler/ARM64/A64DOpcode.h index ed18d30df..89c00477d 100644 --- a/Source/JavaScriptCore/disassembler/ARM64/A64DOpcode.h +++ b/Source/JavaScriptCore/disassembler/ARM64/A64DOpcode.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012 Apple Inc. All rights reserved. + * Copyright (C) 2012, 2016 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -23,8 +23,7 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef A64DOpcode_h -#define A64DOpcode_h +#pragma once #include <wtf/Assertions.h> #include <stdint.h> @@ -165,19 +164,29 @@ protected: bufferPrintf("#%d", immediate); } + void appendSignedImmediate64(int64_t immediate) + { + bufferPrintf("#%" PRIi64, immediate); + } + void appendUnsignedImmediate(unsigned immediate) { bufferPrintf("#%u", immediate); } + void appendUnsignedHexImmediate(unsigned immediate) + { + bufferPrintf("#0x%x", immediate); + } + void appendUnsignedImmediate64(uint64_t immediate) { - bufferPrintf("#0x%llx", immediate); + bufferPrintf("#0x%" PRIx64, immediate); } void appendPCRelativeOffset(uint32_t* pc, int32_t immediate) { - bufferPrintf("0x%llx", reinterpret_cast<uint64_t>(pc + immediate)); + bufferPrintf("0x%" PRIx64, reinterpret_cast<uint64_t>(pc + immediate)); } void appendShiftAmount(unsigned amount) @@ -313,7 +322,7 @@ private: static const char* const s_opNames[4]; public: - static const uint32_t mask = 0x1fe00010; + static const uint32_t mask = 0x1fe00000; static const uint32_t pattern = 0x1a800000; DEFINE_STATIC_FORMAT(A64DOpcodeConditionalSelect, thisObj); @@ -328,6 +337,25 @@ public: unsigned op2() { return (m_opcode >> 10) & 0x3; } }; +class A64DOpcodeDataProcessing1Source : public A64DOpcode { +private: + static const char* const s_opNames[8]; + +public: + static const uint32_t mask = 0x5fe00000; + static const uint32_t pattern = 0x5ac00000; + + DEFINE_STATIC_FORMAT(A64DOpcodeDataProcessing1Source, thisObj); + + const char* format(); + + const char* opName() { return s_opNames[opNameIndex()]; } + unsigned sBit() { return (m_opcode >> 29) & 0x1; } + unsigned opCode() { return (m_opcode >> 10) & 0x3f; } + unsigned opCode2() { return (m_opcode >> 16) & 0x1f; } + unsigned opNameIndex() { return (opCode() & 0x7); } +}; + class A64DOpcodeDataProcessing2Source : public A64DOpcode { private: static const char* const s_opNames[8]; @@ -359,7 +387,7 @@ public: const char* format(); - const char* opName() { return ra() == 31 ? s_opNames[opNum() & 0xf] : s_pseudoOpNames[opNum() & 0xf]; } + const char* opName() { return ra() == 31 ? s_pseudoOpNames[opNum() & 0xf] : s_opNames[opNum() & 0xf]; } unsigned ra() { return (m_opcode >> 10) & 0x1f; } unsigned op54() { return (m_opcode >> 29) & 0x3; } unsigned op31() { return (m_opcode >> 21) & 0x7; } @@ -369,7 +397,7 @@ public: class A64OpcodeExceptionGeneration : public A64DOpcode { public: - static const uint32_t mask = 0xff000010; + static const uint32_t mask = 0xff000000; static const uint32_t pattern = 0xd4000000; DEFINE_STATIC_FORMAT(A64OpcodeExceptionGeneration, thisObj); @@ -423,6 +451,20 @@ public: unsigned opNum() { return (m_opcode >> 3) & 0x3; } }; +class A64DOpcodeFloatingPointConditionalSelect : public A64DOpcodeFloatingPointOps { +public: + static const uint32_t mask = 0x5f200c00; + static const uint32_t pattern = 0x1e200c00; + + DEFINE_STATIC_FORMAT(A64DOpcodeFloatingPointConditionalSelect, thisObj); + + const char* format(); + + const char* opName() { return "fcsel"; } + + unsigned condition() { return (m_opcode >> 12) & 0xf; } +}; + class A64DOpcodeFloatingPointDataProcessing1Source : public A64DOpcodeFloatingPointOps { private: static const char* const s_opNames[16]; @@ -510,6 +552,22 @@ public: unsigned immediate7() { return (m_opcode >> 5) & 0x7f; } }; +class A64DOpcodeDmb : public A64DOpcode { + static const char* const s_optionNames[16]; + +public: + static const uint32_t mask = 0xfffff0ff; + static const uint32_t pattern = 0xd50330bf; + + DEFINE_STATIC_FORMAT(A64DOpcodeDmb, thisObj); + + const char* format(); + + const char* opName() { return "dmb"; } + const char* option() { return s_optionNames[crM()]; } + unsigned crM() { return (m_opcode >> 8) & 0xf; } +}; + class A64DOpcodeLoadStore : public A64DOpcode { private: static const char* const s_opNames[32]; @@ -565,6 +623,22 @@ public: int sBit() { return (m_opcode >> 12) & 0x1; } }; +class A64DOpcodeLoadStoreRegisterPair : public A64DOpcodeLoadStore { +public: + static const uint32_t mask = 0x3a000000; + static const uint32_t pattern = 0x28000000; + + DEFINE_STATIC_FORMAT(A64DOpcodeLoadStoreRegisterPair, thisObj); + + const char* format(); + const char* opName(); + + unsigned rt2() { return (m_opcode >> 10) & 0x1f; } + int immediate7() { return (static_cast<int>((m_opcode >> 15) & 0x7f) << 25) >> 25; } + unsigned offsetMode() { return (m_opcode >> 23) & 0x7; } + int lBit() { return (m_opcode >> 22) & 0x1; } +}; + class A64DOpcodeLoadStoreUnsignedImmediate : public A64DOpcodeLoadStore { public: static const uint32_t mask = 0x3b000000; @@ -618,7 +692,7 @@ public: const char* format(); bool isTst() { return ((opNumber() == 6) && (rd() == 31)); } - bool isMov() { return ((opNumber() == 2) && (rn() == 31)); } + bool isMov() { return ((opc() == 1) && (rn() == 31)); } unsigned opNumber() { return (opc() << 1) | nBit(); } unsigned shift() { return (m_opcode >> 22) & 0x3; } int immediate6() { return (static_cast<int>((m_opcode >> 10) & 0x3f) << 26) >> 26; } @@ -688,5 +762,3 @@ public: } } // namespace JSC::ARM64Disassembler using JSC::ARM64Disassembler::A64DOpcode; - -#endif // A64DOpcode_h diff --git a/Source/JavaScriptCore/disassembler/ARM64Disassembler.cpp b/Source/JavaScriptCore/disassembler/ARM64Disassembler.cpp index 713c1a74c..ac52213df 100644 --- a/Source/JavaScriptCore/disassembler/ARM64Disassembler.cpp +++ b/Source/JavaScriptCore/disassembler/ARM64Disassembler.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012 Apple Inc. All rights reserved. + * Copyright (C) 2012, 2014 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -33,7 +33,7 @@ namespace JSC { -bool tryToDisassemble(const MacroAssemblerCodePtr& codePtr, size_t size, const char* prefix, PrintStream& out, InstructionSubsetHint) +bool tryToDisassemble(const MacroAssemblerCodePtr& codePtr, size_t size, const char* prefix, PrintStream& out) { A64DOpcode arm64Opcode; diff --git a/Source/JavaScriptCore/disassembler/ARMLLVMDisassembler.cpp b/Source/JavaScriptCore/disassembler/ARMLLVMDisassembler.cpp new file mode 100644 index 000000000..a349abbc6 --- /dev/null +++ b/Source/JavaScriptCore/disassembler/ARMLLVMDisassembler.cpp @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2013 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "Disassembler.h" + +#if USE(ARM_LLVM_DISASSEMBLER) + +#include "MacroAssemblerCodeRef.h" +#include <llvm-c/Disassembler.h> +#include <llvm-c/Target.h> + +namespace JSC { + +bool tryToDisassemble(const MacroAssemblerCodePtr& codePtr, size_t size, const char* prefix, PrintStream& out) +{ + LLVMInitializeAllTargetInfos(); + LLVMInitializeAllTargetMCs(); + LLVMInitializeAllDisassemblers(); + + const char* triple = "armv7-unknown-linux-gnueabihf"; + LLVMDisasmContextRef disassemblyContext = LLVMCreateDisasm(triple, 0, 0, 0, 0); + + RELEASE_ASSERT(disassemblyContext); + + char pcString[20]; + char instructionString[100]; + + uint8_t* pc = static_cast<uint8_t*>(codePtr.executableAddress()); + uint8_t* end = pc + size; + + while (pc < end) { + snprintf( + pcString, sizeof(pcString), "0x%lx", + static_cast<unsigned long>(bitwise_cast<uintptr_t>(pc))); + + size_t instructionSize = LLVMDisasmInstruction( + disassemblyContext, pc, end - pc, bitwise_cast<uintptr_t>(pc), + instructionString, sizeof(instructionString)); + + if (!instructionSize) + snprintf(instructionString, sizeof(instructionString), "unknown instruction"); + + out.printf("%s%16s: [0x%08lx] %s\n", prefix, pcString, *(reinterpret_cast<unsigned long*>(pc)), instructionString); + pc += 4; + } + + LLVMDisasmDispose(disassemblyContext); + return true; +} + +} // namespace JSC + +#endif // USE(ARM_LLVM_DISASSEMBLER) diff --git a/Source/JavaScriptCore/disassembler/ARMv7/ARMv7DOpcode.cpp b/Source/JavaScriptCore/disassembler/ARMv7/ARMv7DOpcode.cpp new file mode 100644 index 000000000..3175cccbd --- /dev/null +++ b/Source/JavaScriptCore/disassembler/ARMv7/ARMv7DOpcode.cpp @@ -0,0 +1,1733 @@ +/* + * Copyright (C) 2013 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" + +#if USE(ARMV7_DISASSEMBLER) + +#include "ARMv7DOpcode.h" + +#include <stdarg.h> +#include <stdint.h> +#include <stdio.h> +#include <string.h> + +namespace JSC { namespace ARMv7Disassembler { + +ARMv7D16BitOpcode::OpcodeGroup* ARMv7D16BitOpcode::opcodeTable[32]; +ARMv7D32BitOpcode::OpcodeGroup* ARMv7D32BitOpcode::opcodeTable[16]; + +const char* const ARMv7DOpcode::s_conditionNames[16] = { + "eq", "ne", "hs", "lo", "mi", "pl", "vs", "vc", + "hi", "ls", "ge", "lt", "gt", "le", "al", "al" +}; + +const char* const ARMv7DOpcode::s_optionName[8] = { + "uxtb", "uxth", "uxtw", "uxtx", "sxtb", "sxth", "sxtw", "sxtx" +}; + +const char* const ARMv7DOpcode::s_shiftNames[4] = { + "lsl", "lsr", "asr", "ror" +}; + +const char* const ARMv7DOpcode::s_specialRegisterNames[3] = { "sp", "lr", "pc" }; + +template <typename OpcodeType, typename InstructionType> +struct OpcodeGroupInitializer { + unsigned m_opcodeGroupNumber; + InstructionType m_mask; + InstructionType m_pattern; + const char* (*m_format)(OpcodeType*); +}; + +#define OPCODE_GROUP_ENTRY(groupIndex, groupClass) \ +{ groupIndex, groupClass::s_mask, groupClass::s_pattern, groupClass::format } + +typedef OpcodeGroupInitializer<ARMv7D16BitOpcode, uint16_t> Opcode16GroupInitializer; +typedef OpcodeGroupInitializer<ARMv7D32BitOpcode, uint32_t> Opcode32GroupInitializer; + +static Opcode16GroupInitializer opcode16BitGroupList[] = { + OPCODE_GROUP_ENTRY(0x0, ARMv7DOpcodeLogicalImmediateT1), + OPCODE_GROUP_ENTRY(0x1, ARMv7DOpcodeLogicalImmediateT1), + OPCODE_GROUP_ENTRY(0x2, ARMv7DOpcodeLogicalImmediateT1), + OPCODE_GROUP_ENTRY(0x3, ARMv7DOpcodeAddSubtractT1), + OPCODE_GROUP_ENTRY(0x3, ARMv7DOpcodeAddSubtractImmediate3), + OPCODE_GROUP_ENTRY(0x4, ARMv7DOpcodeMoveImmediateT1), + OPCODE_GROUP_ENTRY(0x5, ARMv7DOpcodeCompareImmediateT1), + OPCODE_GROUP_ENTRY(0x6, ARMv7DOpcodeAddSubtractImmediate8), + OPCODE_GROUP_ENTRY(0x7, ARMv7DOpcodeAddSubtractImmediate8), + OPCODE_GROUP_ENTRY(0x8, ARMv7DOpcodeDataProcessingRegisterT1), + OPCODE_GROUP_ENTRY(0x8, ARMv7DOpcodeAddRegisterT2), + OPCODE_GROUP_ENTRY(0x8, ARMv7DOpcodeCompareRegisterT2), + OPCODE_GROUP_ENTRY(0x8, ARMv7DOpcodeCompareRegisterT1), + OPCODE_GROUP_ENTRY(0x8, ARMv7DOpcodeMoveRegisterT1), + OPCODE_GROUP_ENTRY(0x8, ARMv7DOpcodeBranchExchangeT1), + OPCODE_GROUP_ENTRY(0x9, ARMv7DOpcodeLoadFromLiteralPool), + OPCODE_GROUP_ENTRY(0xa, ARMv7DOpcodeLoadStoreRegisterOffsetT1), + OPCODE_GROUP_ENTRY(0xb, ARMv7DOpcodeLoadStoreRegisterOffsetT1), + OPCODE_GROUP_ENTRY(0xc, ARMv7DOpcodeLoadStoreRegisterImmediateWordAndByte), + OPCODE_GROUP_ENTRY(0xd, ARMv7DOpcodeLoadStoreRegisterImmediateWordAndByte), + OPCODE_GROUP_ENTRY(0xe, ARMv7DOpcodeLoadStoreRegisterImmediateWordAndByte), + OPCODE_GROUP_ENTRY(0xf, ARMv7DOpcodeLoadStoreRegisterImmediateWordAndByte), + OPCODE_GROUP_ENTRY(0x10, ARMv7DOpcodeStoreRegisterImmediateHalfWord), + OPCODE_GROUP_ENTRY(0x11, ARMv7DOpcodeLoadRegisterImmediateHalfWord), + OPCODE_GROUP_ENTRY(0x12, ARMv7DOpcodeLoadStoreRegisterSPRelative), + OPCODE_GROUP_ENTRY(0x13, ARMv7DOpcodeLoadStoreRegisterSPRelative), + OPCODE_GROUP_ENTRY(0x14, ARMv7DOpcodeGeneratePCRelativeAddress), + OPCODE_GROUP_ENTRY(0x15, ARMv7DOpcodeAddSPPlusImmediate), + OPCODE_GROUP_ENTRY(0x16, ARMv7DOpcodeMiscCompareAndBranch), + OPCODE_GROUP_ENTRY(0x16, ARMv7DOpcodeMiscByteHalfwordOps), + OPCODE_GROUP_ENTRY(0x16, ARMv7DOpcodeMiscPushPop), + OPCODE_GROUP_ENTRY(0x16, ARMv7DOpcodeMiscAddSubSP), + OPCODE_GROUP_ENTRY(0x17, ARMv7DOpcodeMiscHint16), // Needs to be before IfThenT1 + OPCODE_GROUP_ENTRY(0x17, ARMv7DOpcodeMiscIfThenT1), + OPCODE_GROUP_ENTRY(0x17, ARMv7DOpcodeMiscByteHalfwordOps), + OPCODE_GROUP_ENTRY(0x17, ARMv7DOpcodeMiscCompareAndBranch), + OPCODE_GROUP_ENTRY(0x17, ARMv7DOpcodeMiscPushPop), + OPCODE_GROUP_ENTRY(0x17, ARMv7DOpcodeMiscBreakpointT1), + OPCODE_GROUP_ENTRY(0x1a, ARMv7DOpcodeBranchConditionalT1), + OPCODE_GROUP_ENTRY(0x1b, ARMv7DOpcodeBranchConditionalT1), + OPCODE_GROUP_ENTRY(0x1c, ARMv7DOpcodeBranchT2) +}; + +static Opcode32GroupInitializer opcode32BitGroupList[] = { + OPCODE_GROUP_ENTRY(0x4, ARMv7DOpcodeDataPopMultiple), + OPCODE_GROUP_ENTRY(0x4, ARMv7DOpcodeDataPushMultiple), + OPCODE_GROUP_ENTRY(0x5, ARMv7DOpcodeDataProcessingShiftedReg), + OPCODE_GROUP_ENTRY(0x6, ARMv7DOpcodeVLDR), + OPCODE_GROUP_ENTRY(0x6, ARMv7DOpcodeVMOVSinglePrecision), + OPCODE_GROUP_ENTRY(0x6, ARMv7DOpcodeVMOVDoublePrecision), + OPCODE_GROUP_ENTRY(0x7, ARMv7DOpcodeFPTransfer), + OPCODE_GROUP_ENTRY(0x7, ARMv7DOpcodeVMSR), + OPCODE_GROUP_ENTRY(0x7, ARMv7DOpcodeVCMP), + OPCODE_GROUP_ENTRY(0x7, ARMv7DOpcodeVCVTBetweenFPAndInt), + OPCODE_GROUP_ENTRY(0x8, ARMv7DOpcodeDataProcessingModifiedImmediate), + OPCODE_GROUP_ENTRY(0x8, ARMv7DOpcodeConditionalBranchT3), + OPCODE_GROUP_ENTRY(0x8, ARMv7DOpcodeBranchOrBranchLink), + OPCODE_GROUP_ENTRY(0x9, ARMv7DOpcodeUnmodifiedImmediate), + OPCODE_GROUP_ENTRY(0x9, ARMv7DOpcodeHint32), + OPCODE_GROUP_ENTRY(0x9, ARMv7DOpcodeConditionalBranchT3), + OPCODE_GROUP_ENTRY(0x9, ARMv7DOpcodeBranchOrBranchLink), + OPCODE_GROUP_ENTRY(0xa, ARMv7DOpcodeDataProcessingModifiedImmediate), + OPCODE_GROUP_ENTRY(0xa, ARMv7DOpcodeConditionalBranchT3), + OPCODE_GROUP_ENTRY(0xa, ARMv7DOpcodeBranchOrBranchLink), + OPCODE_GROUP_ENTRY(0xb, ARMv7DOpcodeUnmodifiedImmediate), + OPCODE_GROUP_ENTRY(0xb, ARMv7DOpcodeConditionalBranchT3), + OPCODE_GROUP_ENTRY(0xb, ARMv7DOpcodeBranchOrBranchLink), + OPCODE_GROUP_ENTRY(0xc, ARMv7DOpcodeLoadRegister), + OPCODE_GROUP_ENTRY(0xc, ARMv7DOpcodeDataPushPopSingle), // Should be before StoreSingle* + OPCODE_GROUP_ENTRY(0xc, ARMv7DOpcodeDataPopMultiple), + OPCODE_GROUP_ENTRY(0xc, ARMv7DOpcodeDataPushMultiple), + OPCODE_GROUP_ENTRY(0xc, ARMv7DOpcodeStoreSingleRegister), + OPCODE_GROUP_ENTRY(0xc, ARMv7DOpcodeStoreSingleImmediate12), + OPCODE_GROUP_ENTRY(0xc, ARMv7DOpcodeStoreSingleImmediate8), + OPCODE_GROUP_ENTRY(0xc, ARMv7DOpcodeLoadSignedImmediate), + OPCODE_GROUP_ENTRY(0xc, ARMv7DOpcodeLoadUnsignedImmediate), + OPCODE_GROUP_ENTRY(0xd, ARMv7DOpcodeLongMultipleDivide), + OPCODE_GROUP_ENTRY(0xd, ARMv7DOpcodeDataProcessingRegShift), + OPCODE_GROUP_ENTRY(0xd, ARMv7DOpcodeDataProcessingRegExtend), + OPCODE_GROUP_ENTRY(0xd, ARMv7DOpcodeDataProcessingRegParallel), + OPCODE_GROUP_ENTRY(0xd, ARMv7DOpcodeDataProcessingRegMisc), + OPCODE_GROUP_ENTRY(0xe, ARMv7DOpcodeVLDR), + OPCODE_GROUP_ENTRY(0xf, ARMv7DOpcodeVCMP), + OPCODE_GROUP_ENTRY(0xf, ARMv7DOpcodeVCVTBetweenFPAndInt), +}; + +bool ARMv7DOpcode::s_initialized = false; + +void ARMv7DOpcode::init() +{ + if (s_initialized) + return; + + ARMv7D16BitOpcode::init(); + ARMv7D32BitOpcode::init(); + + s_initialized = true; +} + +void ARMv7DOpcode::startITBlock(unsigned blocksize, unsigned firstCondition) +{ + ASSERT(blocksize > 0 && blocksize <= MaxITBlockSize); + m_ITBlocksize = blocksize; + m_ITConditionIndex = m_ITBlocksize + 1; + m_currentITCondition = 0; + m_ifThenConditions[0] = firstCondition; +} + +void ARMv7DOpcode::saveITConditionAt(unsigned blockPosition, unsigned condition) +{ + if (blockPosition < m_ITBlocksize) + m_ifThenConditions[blockPosition] = static_cast<unsigned char>(condition); +} + +void ARMv7DOpcode::fetchOpcode(uint16_t*& newPC) +{ + m_bufferOffset = 0; + m_formatBuffer[0] = '\0'; + m_currentPC = newPC; + + m_opcode = *newPC++; + + if (is32BitInstruction()) { + m_opcode <<= 16; + m_opcode |= *newPC++; + } + + if (m_ITConditionIndex < m_ITBlocksize) + m_currentITCondition = m_ifThenConditions[m_ITConditionIndex]; + else + m_currentITCondition = CondNone; +} + +const char* ARMv7DOpcode::disassemble(uint16_t*& currentPC) +{ + const char* result; + fetchOpcode(currentPC); + + if (is32BitInstruction()) + result = reinterpret_cast<ARMv7D32BitOpcode*>(this)->doDisassemble(); + else + result = reinterpret_cast<ARMv7D16BitOpcode*>(this)->doDisassemble(); + + if (startingITBlock()) + m_ITConditionIndex = 0; + else if (inITBlock() && (++m_ITConditionIndex >= m_ITBlocksize)) + endITBlock(); + + return result; +} + +void ARMv7DOpcode::bufferPrintf(const char* format, ...) +{ + if (m_bufferOffset >= bufferSize) + return; + + va_list argList; + va_start(argList, format); + + m_bufferOffset += vsnprintf(m_formatBuffer + m_bufferOffset, bufferSize - m_bufferOffset, format, argList); + + va_end(argList); +} + +void ARMv7DOpcode::appendInstructionName(const char* instructionName, bool addS) +{ + if (!inITBlock() && !addS) { + appendInstructionNameNoITBlock(instructionName); + + return; + } + + const char sevenSpaces[8] = " "; + + unsigned length = strlen(instructionName); + + bufferPrintf(" %s", instructionName); + if (inITBlock()) { + const char* condition = conditionName(m_currentITCondition); + length += strlen(condition); + appendString(condition); + } else if (addS) { + length++; + appendCharacter('s'); + } + + if (length >= 7) + length = 6; + + appendString(sevenSpaces + length); +} + +void ARMv7DOpcode::appendRegisterName(unsigned registerNumber) +{ + registerNumber &= 0xf; + + if (registerNumber > 12) { + appendString(s_specialRegisterNames[registerNumber - 13]); + return; + } + + bufferPrintf("r%u", registerNumber); +} + +void ARMv7DOpcode::appendRegisterList(unsigned registers) +{ + unsigned numberPrinted = 0; + + appendCharacter('{'); + + for (unsigned i = 0; i < 16; i++) { + if (registers & (1 << i)) { + if (numberPrinted++) + appendSeparator(); + appendRegisterName(i); + } + } + + appendCharacter('}'); +} + +void ARMv7DOpcode::appendFPRegisterName(char registerPrefix, unsigned registerNumber) +{ + bufferPrintf("%c%u", registerPrefix, registerNumber); +} + +// 16 Bit Instructions + +void ARMv7D16BitOpcode::init() +{ + OpcodeGroup* lastGroups[OpcodeGroup::opcodeTableSize]; + + for (unsigned i = 0; i < OpcodeGroup::opcodeTableSize; i++) { + opcodeTable[i] = 0; + lastGroups[i] = 0; + } + + for (unsigned i = 0; i < sizeof(opcode16BitGroupList) / sizeof(Opcode16GroupInitializer); i++) { + OpcodeGroup* newOpcodeGroup = new OpcodeGroup(opcode16BitGroupList[i].m_mask, opcode16BitGroupList[i].m_pattern, opcode16BitGroupList[i].m_format); + uint16_t opcodeGroupNumber = opcode16BitGroupList[i].m_opcodeGroupNumber; + + if (!opcodeTable[opcodeGroupNumber]) + opcodeTable[opcodeGroupNumber] = newOpcodeGroup; + else + lastGroups[opcodeGroupNumber]->setNext(newOpcodeGroup); + lastGroups[opcodeGroupNumber] = newOpcodeGroup; + } +} + +const char* ARMv7D16BitOpcode::doDisassemble() +{ + OpcodeGroup* opGroup = opcodeTable[opcodeGroupNumber(m_opcode)]; + + while (opGroup) { + if (opGroup->matches(static_cast<uint16_t>(m_opcode))) + return opGroup->format(this); + opGroup = opGroup->next(); + } + + return defaultFormat(); +} + +const char* ARMv7D16BitOpcode::defaultFormat() +{ + bufferPrintf(" .word %04x", m_opcode); + return m_formatBuffer; +} + +const char* ARMv7DOpcodeAddRegisterT2::format() +{ + appendInstructionName("add"); + appendRegisterName(rdn()); + appendSeparator(); + appendRegisterName(rm()); + + return m_formatBuffer; +} + +const char* ARMv7DOpcodeAddSPPlusImmediate::format() +{ + appendInstructionName("add"); + appendRegisterName(rd()); + appendSeparator(); + appendRegisterName(RegSP); + appendSeparator(); + appendUnsignedImmediate(immediate8()); + + return m_formatBuffer; +} + +const char* const ARMv7DOpcodeAddSubtract::s_opNames[2] = { "add", "sub" }; + +const char* ARMv7DOpcodeAddSubtractT1::format() +{ + appendInstructionName(opName(), !inITBlock()); + appendRegisterName(rd()); + appendSeparator(); + appendRegisterName(rn()); + appendSeparator(); + appendRegisterName(rm()); + + return m_formatBuffer; +} + +const char* ARMv7DOpcodeAddSubtractImmediate3::format() +{ + appendInstructionName(opName(), !inITBlock()); + appendRegisterName(rd()); + appendSeparator(); + appendRegisterName(rn()); + appendSeparator(); + appendUnsignedImmediate(immediate3()); + + return m_formatBuffer; +} + +const char* ARMv7DOpcodeAddSubtractImmediate8::format() +{ + appendInstructionName(opName(), !inITBlock()); + appendRegisterName(rdn()); + appendSeparator(); + appendUnsignedImmediate(immediate8()); + + return m_formatBuffer; +} + +const char* ARMv7DOpcodeBranchConditionalT1::format() +{ + if (condition() == 0xe) + return defaultFormat(); + + if (condition() == 0xf) { + appendInstructionName("svc"); + appendUnsignedImmediate(offset()); + + return m_formatBuffer; + } + + bufferPrintf(" b%-6.6s", conditionName(condition())); + appendPCRelativeOffset(static_cast<int32_t>(offset()) + 2); + + return m_formatBuffer; +} + +const char* ARMv7DOpcodeBranchExchangeT1::format() +{ + appendInstructionName(opName()); + appendRegisterName(rm()); + + return m_formatBuffer; +} + +const char* ARMv7DOpcodeBranchT2::format() +{ + appendInstructionName("b"); + appendPCRelativeOffset(static_cast<int32_t>(immediate11()) + 2); + + return m_formatBuffer; +} + +const char* ARMv7DOpcodeCompareImmediateT1::format() +{ + appendInstructionName("cmp"); + appendRegisterName(rn()); + appendSeparator(); + appendUnsignedImmediate(immediate8()); + + return m_formatBuffer; +} + +const char* ARMv7DOpcodeCompareRegisterT1::format() +{ + appendInstructionName("cmp"); + appendRegisterName(rn()); + appendSeparator(); + appendRegisterName(rm()); + + return m_formatBuffer; +} + +const char* ARMv7DOpcodeCompareRegisterT2::format() +{ + appendInstructionName("compare"); + appendRegisterName(rn()); + appendSeparator(); + appendRegisterName(rm()); + + return m_formatBuffer; +} + +const char* const ARMv7DOpcodeDataProcessingRegisterT1::s_opNames[16] = { + "and", "eor", "lsl", "lsr", "asr", "adc", "sbc", "ror", "tst", "rsb", "cmp", "cmn", "orr", "mul", "bic", "mvn" +}; + +const char* ARMv7DOpcodeDataProcessingRegisterT1::format() +{ + appendInstructionName(opName(), inITBlock() && (!(op() == 0x8) || (op() == 0xa) || (op() == 0xb))); + appendRegisterName(rdn()); + appendSeparator(); + appendRegisterName(rm()); + if (op() == 0x9) // rsb T1 + appendString(", #0"); + else if (op() == 0xd) { // mul T1 + appendSeparator(); + appendRegisterName(rdn()); + } + + return m_formatBuffer; +} + +const char* ARMv7DOpcodeGeneratePCRelativeAddress::format() +{ + appendInstructionName("adr"); + appendRegisterName(rd()); + appendSeparator(); + appendPCRelativeOffset(static_cast<int32_t>(immediate8())); + + return m_formatBuffer; +} + +const char* ARMv7DOpcodeLoadFromLiteralPool::format() +{ + appendInstructionName("ldr"); + appendRegisterName(rt()); + appendSeparator(); + appendPCRelativeOffset(static_cast<int32_t>(immediate8())); + + return m_formatBuffer; +} + +const char* const ARMv7DOpcodeLoadStoreRegisterImmediate::s_opNames[6] = { + "str", "ldr", "strb", "ldrb", "strh", "ldrh" +}; + +const char* ARMv7DOpcodeLoadStoreRegisterImmediate::format() +{ + const char* instructionName = opName(); + + if (!instructionName) + return defaultFormat(); + + appendInstructionName(opName()); + appendRegisterName(rt()); + appendSeparator(); + appendCharacter('['); + appendRegisterName(rn()); + if (immediate5()) { + appendSeparator(); + appendUnsignedImmediate(immediate5() << scale()); + } + appendCharacter(']'); + + return m_formatBuffer; +} + +unsigned ARMv7DOpcodeLoadStoreRegisterImmediate::scale() +{ + switch (op()) { + case 0: + case 1: + return 2; + case 2: + case 3: + return 0; + case 4: + case 5: + return 1; + default: + break; + } + ASSERT_NOT_REACHED(); + return 0; +} + +const char* const ARMv7DOpcodeLoadStoreRegisterOffsetT1::s_opNames[8] = { + "str", "strh", "strb", "ldrsb", "ldr", "ldrh", "ldrb", "ldrsh" +}; + +const char* ARMv7DOpcodeLoadStoreRegisterOffsetT1::format() +{ + appendInstructionName(opName()); + appendRegisterName(rt()); + appendSeparator(); + appendCharacter('['); + appendRegisterName(rn()); + appendSeparator(); + appendRegisterName(rm()); + appendCharacter(']'); + + return m_formatBuffer; +} + +const char* ARMv7DOpcodeLoadStoreRegisterSPRelative::format() +{ + appendInstructionName(opName()); + appendRegisterName(rt()); + appendSeparator(); + appendCharacter('['); + appendRegisterName(RegSP); + if (immediate8()) { + appendSeparator(); + appendUnsignedImmediate(immediate8() << 2); + } + appendCharacter(']'); + + return m_formatBuffer; +} + +const char* ARMv7DOpcodeLogicalImmediateT1::format() +{ + if (!op() && !immediate5()) { + // mov T2 + appendInstructionName("movs"); + appendRegisterName(rd()); + appendSeparator(); + appendRegisterName(rm()); + + return m_formatBuffer; + } + + appendInstructionName(opName(), !inITBlock()); + appendRegisterName(rd()); + appendSeparator(); + appendRegisterName(rm()); + appendSeparator(); + appendUnsignedImmediate((op() && !immediate5()) ? 32 : immediate5()); + + return m_formatBuffer; +} + +const char* ARMv7DOpcodeMiscAddSubSP::format() +{ + appendInstructionName(opName()); + appendRegisterName(RegSP); + appendSeparator(); + appendRegisterName(RegSP); + appendSeparator(); + appendUnsignedImmediate(immediate7()); + + return m_formatBuffer; +} + +const char* ARMv7DOpcodeMiscBreakpointT1::format() +{ + appendInstructionNameNoITBlock("bkpt"); + appendUnsignedImmediate(immediate8()); + + return m_formatBuffer; +} + +const char* const ARMv7DOpcodeMiscByteHalfwordOps::s_opNames[8] = { + "sxth", "sxb", "uxth", "uxtb", "rev", "rev16", "revsh" +}; + +const char* ARMv7DOpcodeMiscByteHalfwordOps::format() +{ + const char* instructionName = opName(); + + if (!instructionName) + return defaultFormat(); + + appendInstructionName(instructionName); + appendRegisterName(rd()); + appendSeparator(); + appendRegisterName(rm()); + + return m_formatBuffer; +} + +const char* ARMv7DOpcodeMiscCompareAndBranch::format() +{ + appendInstructionName(opName()); + appendPCRelativeOffset(immediate6() + 2); + + return m_formatBuffer; +} + +const char* const ARMv7DOpcodeMiscHint16::s_opNames[16] = { + "nop", "yield", "wfe", "wfi", "sev" +}; + +const char* ARMv7DOpcodeMiscHint16::format() +{ + if (opA() > 4) + return defaultFormat(); + + appendInstructionName(opName()); + + return m_formatBuffer; +} + +const char* ARMv7DOpcodeMiscIfThenT1::format() +{ + char opName[6]; + opName[0] = 'i'; + opName[1] = 't'; + + unsigned condition = firstCondition(); + unsigned maskBits = mask(); + unsigned blockLength = 0; + + for (unsigned i = 0; i < 4; ++i) { + if (maskBits & (1 << i)) { + blockLength = 4 - i; + break; + } + } + + startITBlock(blockLength, condition); + + for (unsigned i = 1; i < blockLength; ++i) { + unsigned currMaskBit = (maskBits >> (4-i)) & 0x1; + opName[i + 1] = (currMaskBit ^ (condition & 1)) ? 'e' : 't'; + saveITConditionAt(i, (condition & ~1) | currMaskBit); + } + opName[blockLength + 1] = '\0'; + + appendInstructionNameNoITBlock(opName); + appendString(conditionName(condition)); + + return m_formatBuffer; +} + +const char* ARMv7DOpcodeMiscPushPop::format() +{ + appendInstructionName(opName()); + appendRegisterList(registerMask()); + + return m_formatBuffer; +} + +const char* ARMv7DOpcodeMoveImmediateT1::format() +{ + appendInstructionName("mov", !inITBlock()); + appendRegisterName(rd()); + appendSeparator(); + appendUnsignedImmediate(immediate8()); + + return m_formatBuffer; +} + +const char* ARMv7DOpcodeMoveRegisterT1::format() +{ + appendInstructionName("mov"); + appendRegisterName(rd()); + appendSeparator(); + appendRegisterName(rm()); + + return m_formatBuffer; +} + +// 32 bit Intructions + +void ARMv7D32BitOpcode::init() +{ + OpcodeGroup* lastGroups[OpcodeGroup::opcodeTableSize]; + + for (unsigned i = 0; i < OpcodeGroup::opcodeTableSize; i++) { + opcodeTable[i] = 0; + lastGroups[i] = 0; + } + + for (unsigned i = 0; i < sizeof(opcode32BitGroupList) / sizeof(Opcode32GroupInitializer); i++) { + OpcodeGroup* newOpcodeGroup = new OpcodeGroup(opcode32BitGroupList[i].m_mask, opcode32BitGroupList[i].m_pattern, opcode32BitGroupList[i].m_format); + uint16_t opcodeGroupNumber = opcode32BitGroupList[i].m_opcodeGroupNumber; + + if (!opcodeTable[opcodeGroupNumber]) + opcodeTable[opcodeGroupNumber] = newOpcodeGroup; + else + lastGroups[opcodeGroupNumber]->setNext(newOpcodeGroup); + lastGroups[opcodeGroupNumber] = newOpcodeGroup; + } +} + +const char* ARMv7D32BitOpcode::doDisassemble() +{ + OpcodeGroup* opGroup = opcodeTable[opcodeGroupNumber(m_opcode)]; + + while (opGroup) { + if (opGroup->matches(m_opcode)) + return opGroup->format(this); + opGroup = opGroup->next(); + } + + return defaultFormat(); +} + +const char* ARMv7D32BitOpcode::defaultFormat() +{ + bufferPrintf(" .long %08x", m_opcode); + return m_formatBuffer; +} + +const char* ARMv7DOpcodeConditionalBranchT3::format() +{ + if (condition() < 0xe) + bufferPrintf(" b%-6.6s", conditionName(condition())); + else + appendInstructionName("b"); + appendPCRelativeOffset(offset() + 2); + + return m_formatBuffer; +} + +const char* ARMv7DOpcodeBranchOrBranchLink::format() +{ + appendInstructionName(isBL() ? "bl" : "b"); + appendPCRelativeOffset(offset() + 2); + + return m_formatBuffer; +} + +const char* const ARMv7DOpcodeDataProcessingLogicalAndRithmetic::s_opNames[16] = { + "and", "bic", "orr", "orn", "eor", 0, "pkh", 0, "add", 0, "adc", "sbc", 0, "sub", "rsb", 0 +}; + +void ARMv7DOpcodeDataProcessingModifiedImmediate::appendModifiedImmediate(unsigned immediate12) +{ + if (!(immediate12 & 0xc00)) { + unsigned immediate = 0; + unsigned lower8Bits = immediate12 & 0xff; + + switch ((immediate12 >> 8) & 3) { + case 0: + immediate = lower8Bits; + break; + case 1: + immediate = (lower8Bits << 16) | lower8Bits; + break; + case 2: + immediate = (lower8Bits << 24) | (lower8Bits << 8); + break; + case 3: + immediate = (lower8Bits << 24) | (lower8Bits << 16) | (lower8Bits << 8) | lower8Bits; + break; + } + appendUnsignedImmediate(immediate); + return; + } + + unsigned immediate8 = 0x80 | (immediate12 & 0x7f); + unsigned shiftAmount = 32 - ((immediate12 >> 7) & 0x1f); + + appendUnsignedImmediate(immediate8 << shiftAmount); +} + +const char* ARMv7DOpcodeDataProcessingModifiedImmediate::format() +{ + if ((op() == 0x5) || (op() == 0x6) || (op() == 0x7) || (op() == 0x9) || (op() == 0xc) || (op() == 0xf)) + return defaultFormat(); + + const char* instructionName = opName(); + + if (rn() == 15) { + if (op() == 2) { + // MOV T2 + instructionName = sBit() ? "movs" : "mov"; + appendInstructionName(instructionName); + appendRegisterName(rd()); + appendSeparator(); + appendModifiedImmediate(immediate12()); + + return m_formatBuffer; + } + + if (op() == 3) { + // MVN T1 + instructionName = sBit() ? "mvns" : "mvn"; + appendInstructionName(instructionName); + appendRegisterName(rd()); + appendSeparator(); + appendModifiedImmediate(immediate12()); + + return m_formatBuffer; + } + } + + if (rd() == 15) { + if (sBit()) { + bool testOrCmpInstruction = false; + + switch (op()) { + case 0x0: + instructionName = "tst"; + testOrCmpInstruction = true; + break; + case 0x4: + instructionName = "teq"; + testOrCmpInstruction = true; + break; + case 0x8: + instructionName = "cmn"; + testOrCmpInstruction = true; + break; + case 0xd: + instructionName = "cmp"; + testOrCmpInstruction = true; + break; + } + + if (testOrCmpInstruction) { + appendInstructionName(instructionName); + appendRegisterName(rn()); + appendSeparator(); + appendModifiedImmediate(immediate12()); + + return m_formatBuffer; + } + } + } + + appendInstructionName(instructionName); + appendRegisterName(rd()); + appendSeparator(); + appendRegisterName(rn()); + appendSeparator(); + appendModifiedImmediate(immediate12()); + + return m_formatBuffer; +} + +void ARMv7DOpcodeDataProcessingShiftedReg::appendImmShift(unsigned type, unsigned immediate) +{ + if (type || immediate) { + appendSeparator(); + + if (!immediate) { + switch (type) { + case 1: + case 2: + immediate = 32; + break; + case 3: + appendString("rrx"); + return; + } + } + + appendShiftType(type); + appendUnsignedImmediate(immediate); + } +} + +const char* ARMv7DOpcodeDataProcessingShiftedReg::format() +{ + if ((op() == 0x5) || (op() == 0x7) || (op() == 0x9) || (op() == 0xc) || (op() == 0xf)) + return defaultFormat(); + + if (op() == 6) { + // pkhbt or pkhtb + if (sBit() || tBit()) + return defaultFormat(); + + if (tbBit()) + appendInstructionName("pkhtb"); + else + appendInstructionName("pkhbt"); + appendRegisterName(rd()); + appendSeparator(); + appendRegisterName(rn()); + appendSeparator(); + appendRegisterName(rm()); + appendImmShift(tbBit() << 1, immediate5()); + + return m_formatBuffer; + } + + const char* instructionName = opName(); + + if (rn() == 15) { + if (op() == 2) { + if (!type() && !immediate5()) { + // MOV T3 + instructionName = sBit() ? "movs" : "mov"; + appendInstructionName(instructionName); + appendRegisterName(rd()); + appendSeparator(); + appendRegisterName(rm()); + + return m_formatBuffer; + } + + if (type() == 3 && !immediate5()) { + // RRX T1 + instructionName = sBit() ? "rrx" : "rrx"; + appendInstructionName(instructionName); + appendRegisterName(rd()); + appendSeparator(); + appendRegisterName(rm()); + + return m_formatBuffer; + } + + // Logical + if (sBit()) + bufferPrintf("%ss ", shiftName(type())); + else + appendInstructionName(shiftName(type())); + appendRegisterName(rd()); + appendSeparator(); + appendRegisterName(rm()); + appendSeparator(); + appendUnsignedImmediate(immediate5()); + + return m_formatBuffer; + } + + if (op() == 3) { + // MVN T2 + instructionName = sBit() ? "mvns" : "mvn"; + appendInstructionName(instructionName); + appendRegisterName(rd()); + appendSeparator(); + appendRegisterName(rm()); + appendImmShift(type(), immediate5()); + + return m_formatBuffer; + } + } + + if (rd() == 15) { + if (sBit()) { + bool testOrCmpInstruction = false; + + switch (op()) { + case 0x0: + instructionName = "tst"; + testOrCmpInstruction = true; + break; + case 0x4: + instructionName = "teq"; + testOrCmpInstruction = true; + break; + case 0x8: + instructionName = "cmn"; + testOrCmpInstruction = true; + break; + case 0xd: + instructionName = "cmp"; + testOrCmpInstruction = true; + break; + } + + if (testOrCmpInstruction) { + appendInstructionName(instructionName); + appendRegisterName(rn()); + appendSeparator(); + appendRegisterName(rm()); + appendImmShift(type(), immediate5()); + + return m_formatBuffer; + } + } + } + + appendInstructionName(instructionName); + appendRegisterName(rd()); + appendSeparator(); + appendRegisterName(rn()); + appendSeparator(); + appendRegisterName(rm()); + appendImmShift(type(), immediate5()); + + return m_formatBuffer; +} + +const char* ARMv7DOpcodeFPTransfer::format() +{ + appendInstructionName("vmov"); + + if (opL()) { + appendFPRegister(); + appendSeparator(); + } + + appendRegisterName(rt()); + + if (!opL()) { + appendSeparator(); + appendFPRegister(); + } + + return m_formatBuffer; +} + +void ARMv7DOpcodeFPTransfer::appendFPRegister() +{ + if (opC()) { + appendFPRegisterName('d', vd()); + bufferPrintf("[%u]", opH()); + } else + appendFPRegisterName('s', vn()); +} + +const char* ARMv7DOpcodeDataProcessingRegShift::format() +{ + appendInstructionName(opName()); + appendRegisterName(rd()); + appendSeparator(); + appendRegisterName(rn()); + appendSeparator(); + appendRegisterName(rm()); + + return m_formatBuffer; +} + +const char* const ARMv7DOpcodeDataProcessingRegExtend::s_opExtendNames[8] = { + "sxth", "uxth", "sxtb16", "uxtb16", "sxtb", "uxtb" +}; + +const char* const ARMv7DOpcodeDataProcessingRegExtend::s_opExtendAndAddNames[8] = { + "sxtah", "uxtah", "sxtab16", "uxtab16", "sxtab", "uxtab" +}; + +const char* ARMv7DOpcodeDataProcessingRegExtend::format() +{ + const char* instructionName; + + if (rn() == 0xf) + instructionName = opExtendName(); + else + instructionName = opExtendAndAddName(); + + if (!instructionName) + return defaultFormat(); + + appendInstructionName(instructionName); + appendRegisterName(rd()); + appendSeparator(); + appendRegisterName(rn()); + appendSeparator(); + appendRegisterName(rm()); + + if (rotate()) { + appendSeparator(); + appendString("ror "); + appendUnsignedImmediate(rotate() * 8); + } + + return m_formatBuffer; +} + +const char* const ARMv7DOpcodeDataProcessingRegParallel::s_opNames[16] = { + "sadd8", "sadd16", "sasx", 0, "ssub8", "ssub16", "ssax", 0, + "qadd8", "qadd16", "qasx", 0, "qsub8", "qsub16", "qsax", 0 +}; + +const char* ARMv7DOpcodeDataProcessingRegParallel::format() +{ + const char* instructionName; + + instructionName = opName(); + + if (!instructionName) + return defaultFormat(); + + appendInstructionName(instructionName); + appendRegisterName(rd()); + appendSeparator(); + appendRegisterName(rn()); + appendSeparator(); + appendRegisterName(rm()); + + return m_formatBuffer; +} + +const char* const ARMv7DOpcodeDataProcessingRegMisc::s_opNames[16] = { + "qadd", "qdadd", "qsub", "qdsub", "rev", "rev16", "rbit", "revsh", + "sel", 0, 0, 0, "clz" +}; + +const char* ARMv7DOpcodeDataProcessingRegMisc::format() +{ + const char* instructionName; + + instructionName = opName(); + + if (!instructionName) + return defaultFormat(); + + if ((op1() & 0x1) && (rn() != rm())) + return defaultFormat(); + + appendInstructionName(instructionName); + appendRegisterName(rd()); + appendSeparator(); + + if (op1() == 0x2) { // sel + appendRegisterName(rn()); + appendSeparator(); + appendRegisterName(rm()); + + return m_formatBuffer; + } + + appendRegisterName(rm()); + + if (!(op1() & 0x1)) { + appendSeparator(); + appendRegisterName(rn()); + } + + return m_formatBuffer; +} + +const char* const ARMv7DOpcodeHint32::s_opNames[8] = { + "nop", "yield", "wfe", "wfi", "sev" +}; + +const char* ARMv7DOpcodeHint32::format() +{ + if (isDebugHint()) { + appendInstructionName("debug"); + appendUnsignedImmediate(debugOption()); + + return m_formatBuffer; + } + + if (op() > 0x4) + return defaultFormat(); + + appendInstructionName(opName()); + + return m_formatBuffer; +} + +const char* const ARMv7DOpcodeDataLoad::s_opNames[8] = { + "ldrb", "ldrh", "ldr", 0, "ldrsb", "ldrsh" +}; + +const char* ARMv7DOpcodeLoadRegister::format() +{ + appendInstructionName(opName()); + appendRegisterName(rt()); + appendSeparator(); + appendCharacter('['); + appendRegisterName(rn()); + appendSeparator(); + appendRegisterName(rm()); + if (immediate2()) { + appendSeparator(); + appendUnsignedImmediate(immediate2()); + } + appendCharacter(']'); + + return m_formatBuffer; +} + +const char* ARMv7DOpcodeLoadSignedImmediate::format() +{ + appendInstructionName(opName()); + appendRegisterName(rt()); + appendSeparator(); + appendCharacter('['); + appendRegisterName(rn()); + if (pBit()) { + if (wBit() || immediate8()) { + appendSeparator(); + if (uBit()) + appendUnsignedImmediate(immediate8()); + else + appendSignedImmediate(0 - static_cast<int>(immediate8())); + } + appendCharacter(']'); + if (wBit()) + appendCharacter('!'); + } else { + appendCharacter(']'); + appendSeparator(); + if (uBit()) + appendUnsignedImmediate(immediate8()); + else + appendSignedImmediate(0 - static_cast<int>(immediate8())); + } + + return m_formatBuffer; +} + +const char* ARMv7DOpcodeLoadUnsignedImmediate::format() +{ + appendInstructionName(opName()); + appendRegisterName(rt()); + appendSeparator(); + appendCharacter('['); + appendRegisterName(rn()); + if (immediate12()) { + appendSeparator(); + appendUnsignedImmediate(immediate12()); + } + appendCharacter(']'); + + return m_formatBuffer; +} + +const char* const ARMv7DOpcodeLongMultipleDivide::s_opNames[8] = { + "smull", "sdiv", "umull", "udiv", "smlal", "smlsld", "umlal", 0 +}; + +const char* const ARMv7DOpcodeLongMultipleDivide::s_smlalOpNames[4] = { + "smlalbb", "smlalbt", "smlaltb", "smlaltt" +}; + +const char* const ARMv7DOpcodeLongMultipleDivide::s_smlaldOpNames[2] = { + "smlald", "smlaldx" +}; + +const char* const ARMv7DOpcodeLongMultipleDivide::s_smlsldOpNames[2] = { + "smlsld", "smlsldx" +}; + +const char* ARMv7DOpcodeLongMultipleDivide::format() +{ + const char* instructionName = opName(); + + switch (op1()) { + case 0x0: + case 0x2: + if (op2()) + return defaultFormat(); + break; + case 0x1: + case 0x3: + if (op2() != 0xf) + return defaultFormat(); + break; + case 0x4: + if ((op2() & 0xc) == 0x8) + instructionName = smlalOpName(); + else if ((op2() & 0xe) == 0xc) + instructionName = smlaldOpName(); + else if (op2()) + return defaultFormat(); + break; + case 0x5: + if ((op2() & 0xe) == 0xc) + instructionName = smlaldOpName(); + else + return defaultFormat(); + break; + case 0x6: + if (op2() == 0x5) + instructionName = "umaal"; + else if (op2()) + return defaultFormat(); + break; + case 0x7: + return defaultFormat(); + break; + } + + appendInstructionName(instructionName); + if ((op1() & 0x5) == 0x1) { // sdiv and udiv + if (rt() != 0xf) + return defaultFormat(); + } else { + appendRegisterName(rdLo()); + appendSeparator(); + } + appendRegisterName(rdHi()); + appendSeparator(); + appendRegisterName(rn()); + appendSeparator(); + appendRegisterName(rm()); + + return m_formatBuffer; +} + +const char* const ARMv7DOpcodeUnmodifiedImmediate::s_opNames[16] = { + "addw", 0, "movw", 0, 0, "subw", "movt", 0, + "ssat", "ssat16", "sbfx", "bfi", "usat" , "usat16", "ubfx", 0 +}; + +const char* ARMv7DOpcodeUnmodifiedImmediate::format() +{ + const char* instructionName = opName(); + + switch (op() >> 1) { + case 0x0: + case 0x5: + if (rn() == 0xf) + instructionName = "adr"; + break; + case 0x9: + if (immediate5()) + instructionName = "ssat"; + break; + case 0xb: + if (rn() == 0xf) + instructionName = "bfc"; + break; + case 0xd: + if (immediate5()) + instructionName = "usat"; + break; + } + + if (!instructionName) + return defaultFormat(); + + appendInstructionName(instructionName); + appendRegisterName(rd()); + appendSeparator(); + + if ((op() & 0x17) == 0x4) { // movw or movt + appendUnsignedImmediate(immediate16()); + + return m_formatBuffer; + } + + if (!op() || (op() == 0xa)) { // addw, subw and adr + if (rn() == 0xf) { + int32_t offset; + + if ((op() == 0xa) && (rn() == 0xf)) + offset = 0 - static_cast<int32_t>(immediate12()); + else + offset = static_cast<int32_t>(immediate12()); + + appendPCRelativeOffset(offset); + + return m_formatBuffer; + } + + appendRegisterName(rn()); + appendSeparator(); + appendUnsignedImmediate(immediate12()); + + return m_formatBuffer; + } + + if (((op() & 0x15) == 0x10) || (((op() & 0x17) == 0x12) && immediate5())) { // ssat, usat, ssat16 & usat16 + appendSeparator(); + appendUnsignedImmediate(bitNumOrSatImmediate() + 1); + appendSeparator(); + appendRegisterName(rn()); + if (shBit() || immediate5()) { + appendSeparator(); + appendShiftType(shBit() << 1); + appendUnsignedImmediate(immediate5()); + } + + return m_formatBuffer; + } + + if (op() == 0x16) { // bfi or bfc + int width = static_cast<int>(bitNumOrSatImmediate()) - static_cast<int>(immediate5()) + 1; + + if (width < 0) + return defaultFormat(); + + if (rn() != 0xf) { + appendSeparator(); + appendRegisterName(rn()); + } + appendSeparator(); + appendUnsignedImmediate(immediate5()); + appendSeparator(); + appendSignedImmediate(width); + + return m_formatBuffer; + } + + // Must be sbfx or ubfx + appendSeparator(); + appendRegisterName(rn()); + appendSeparator(); + appendUnsignedImmediate(immediate5()); + appendSeparator(); + appendUnsignedImmediate(bitNumOrSatImmediate() + 1); + + return m_formatBuffer; +} + +const char* const ARMv7DOpcodeDataStoreSingle::s_opNames[4] = { + "strb", "strh", "str", 0 +}; + +const char* ARMv7DOpcodeDataPushPopSingle::format() +{ + appendInstructionName(opName()); + appendRegisterName(rt()); + + return m_formatBuffer; +} + +void ARMv7DOpcodeDataPushPopMultiple::appendRegisterList() +{ + unsigned registers = registerList(); + + appendCharacter('{'); + bool needSeparator = false; + + for (unsigned i = 0; i < 16; i++) { + if (registers & (1 << i)) { + if (needSeparator) + appendSeparator(); + appendRegisterName(i); + needSeparator = true; + } + } + appendCharacter('}'); +} + +const char* ARMv7DOpcodeDataPopMultiple::format() +{ + if (condition() != 0xe) + bufferPrintf(" pop%-4.4s", conditionName(condition())); + else + appendInstructionName("pop"); + appendRegisterList(); + + return m_formatBuffer; +} + +const char* ARMv7DOpcodeDataPushMultiple::format() +{ + if (condition() != 0xe) + bufferPrintf(" push%-3.3s", conditionName(condition())); + else + appendInstructionName("push"); + appendRegisterList(); + + return m_formatBuffer; +} + +const char* ARMv7DOpcodeStoreSingleImmediate12::format() +{ + appendInstructionName(opName()); + appendRegisterName(rt()); + appendSeparator(); + appendCharacter('['); + appendRegisterName(rn()); + if (immediate12()) { + appendSeparator(); + appendUnsignedImmediate(immediate12()); + } + appendCharacter(']'); + + return m_formatBuffer; +} + +const char* ARMv7DOpcodeStoreSingleImmediate8::format() +{ + if (pBit() && uBit() && !wBit()) // Really undecoded strt + return defaultFormat(); + + if ((rn() == 0xf) || (!pBit() && !wBit())) + return defaultFormat(); + + appendInstructionName(opName()); + appendRegisterName(rt()); + appendSeparator(); + appendCharacter('['); + appendRegisterName(rn()); + + if (!pBit()) { + appendCharacter(']'); + appendSeparator(); + appendSignedImmediate(uBit() ? static_cast<int32_t>(immediate8()) : (0 - static_cast<int32_t>(immediate8()))); + + return m_formatBuffer; + } + + if (immediate8()) { + appendSeparator(); + appendSignedImmediate(uBit() ? static_cast<int32_t>(immediate8()) : (0 - static_cast<int32_t>(immediate8()))); + } + appendCharacter(']'); + + if (wBit()) + appendCharacter('!'); + + return m_formatBuffer; +} + +const char* ARMv7DOpcodeStoreSingleRegister::format() +{ + appendInstructionName(opName()); + appendRegisterName(rt()); + appendSeparator(); + appendCharacter('['); + appendRegisterName(rn()); + appendSeparator(); + appendRegisterName(rm()); + if (immediate2()) { + appendSeparator(); + appendString("lsl "); + appendUnsignedImmediate(immediate2()); + } + appendCharacter(']'); + + return m_formatBuffer; +} + +const char* ARMv7DOpcodeVCMP::format() +{ + bufferPrintf(" vcmp"); + + if (eBit()) + appendCharacter('e'); // Raise exception on qNaN + + if (condition() != 0xe) + appendString(conditionName(condition())); + + appendCharacter('.'); + appendString(szBit() ? "f64" : "f32"); + appendCharacter(' '); + if (szBit()) { + appendFPRegisterName('d', (dBit() << 4) | vd()); + appendSeparator(); + appendFPRegisterName('d', (mBit() << 4) | vm()); + } else { + appendFPRegisterName('s', (vd() << 1) | dBit()); + appendSeparator(); + appendFPRegisterName('s', (vm() << 1) | mBit()); + } + + return m_formatBuffer; +} + +const char* ARMv7DOpcodeVCVTBetweenFPAndInt::format() +{ + bufferPrintf(" vcvt"); + bool convertToInteger = op2() & 0x4; + + if (convertToInteger) { + if (!op()) + appendCharacter('r'); // Round using mode in FPSCR + if (condition() != 0xe) + appendString(conditionName(condition())); + appendCharacter('.'); + appendCharacter((op2() & 1) ? 's' : 'u'); + appendString("32.f"); + appendString(szBit() ? "64" : "32"); + appendCharacter(' '); + appendFPRegisterName('s', (vd() << 1) | dBit()); + appendSeparator(); + if (szBit()) + appendFPRegisterName('d', (mBit() << 4) | vm()); + else + appendFPRegisterName('s', (vm() << 1) | mBit()); + } else { + if (condition() != 0xe) + appendString(conditionName(condition())); + appendCharacter('.'); + appendString(szBit() ? "f64." : "f32."); + appendString(op() ? "s32" : "u32"); + appendCharacter(' '); + if (szBit()) + appendFPRegisterName('d', (dBit() << 4) | vd()); + else + appendFPRegisterName('s', (vd() << 1) | dBit()); + appendSeparator(); + appendFPRegisterName('s', (vm() << 1) | mBit()); + } + + return m_formatBuffer; +} + +const char* ARMv7DOpcodeVLDR::format() +{ + if (condition() != 0xe) + bufferPrintf(" vldr%-3.3s", conditionName(condition())); + else + appendInstructionName("vldr"); + + appendFPRegisterName(doubleReg() ? 'd' : 's', vd()); + appendSeparator(); + + int immediate = immediate8() * 4; + + if (!uBit()) + immediate = -immediate; + + appendCharacter('['); + + if (rn() == RegPC) + appendPCRelativeOffset(immediate); + else { + appendRegisterName(rn()); + + if (immediate) { + appendSeparator(); + appendSignedImmediate(immediate); + } + } + + appendCharacter(']'); + + return m_formatBuffer; +} + +const char* ARMv7DOpcodeVMOVDoublePrecision::format() +{ + appendInstructionName("vmov"); + if (op()) { + appendRegisterName(rt()); + appendSeparator(); + appendRegisterName(rt2()); + appendSeparator(); + } + + appendFPRegisterName('d', vm()); + + if (!op()) { + appendSeparator(); + appendRegisterName(rt()); + appendSeparator(); + appendRegisterName(rt2()); + } + + return m_formatBuffer; +} + +const char* ARMv7DOpcodeVMOVSinglePrecision::format() +{ + appendInstructionName("vmov"); + if (op()) { + appendRegisterName(rt()); + appendSeparator(); + appendRegisterName(rt2()); + appendSeparator(); + } + + appendFPRegisterName('s', vm()); + appendSeparator(); + appendFPRegisterName('s', (vm() + 1) % 32); + + if (!op()) { + appendSeparator(); + appendRegisterName(rt()); + appendSeparator(); + appendRegisterName(rt2()); + } + + return m_formatBuffer; +} + +const char* ARMv7DOpcodeVMSR::format() +{ + appendInstructionName("vmrs"); + if (opL()) { + if (rt() == 0xf) + appendString("apsr_nzcv"); + else + appendRegisterName(rt()); + appendSeparator(); + } + + appendString("fpscr"); + + if (!opL()) { + appendSeparator(); + appendRegisterName(rt()); + } + + return m_formatBuffer; +} + +} } // namespace JSC::ARMv7Disassembler + +#endif // #if USE(ARMV7_DISASSEMBLER) diff --git a/Source/JavaScriptCore/disassembler/ARMv7/ARMv7DOpcode.h b/Source/JavaScriptCore/disassembler/ARMv7/ARMv7DOpcode.h new file mode 100644 index 000000000..e00ff9c36 --- /dev/null +++ b/Source/JavaScriptCore/disassembler/ARMv7/ARMv7DOpcode.h @@ -0,0 +1,1234 @@ +/* + * Copyright (C) 2013 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#if USE(ARMV7_DISASSEMBLER) + +#include <stdint.h> +#include <wtf/Assertions.h> + +namespace JSC { namespace ARMv7Disassembler { + +class ARMv7DOpcode { +public: + static void init(); + + ARMv7DOpcode() + : m_opcode(0) + , m_bufferOffset(0) + { + init(); + + for (unsigned i = 0; i < 4; i++) + m_ifThenConditions[i] = CondNone; + + endITBlock(); + + m_formatBuffer[0] = '\0'; + } + + const char* disassemble(uint16_t*& currentPC); + +protected: + const unsigned RegSP = 0xd; + const unsigned RegLR = 0xe; + const unsigned RegPC = 0xf; + + void fetchOpcode(uint16_t*&); + bool is32BitInstruction() { return (m_opcode & 0xfffff800) > 0xe000; } + bool isFPInstruction() { return (m_opcode & 0xfc000e00) == 0xec000a00; } + + static const char* const s_conditionNames[16]; + static const char* const s_shiftNames[4]; + static const char* const s_optionName[8]; + static const char* const s_specialRegisterNames[3]; + + static const char* conditionName(unsigned condition) { return s_conditionNames[condition & 0xf]; } + static const char* shiftName(unsigned shiftValue) { return s_shiftNames[shiftValue & 0x3]; } + + bool inITBlock() { return m_ITConditionIndex < m_ITBlocksize; } + bool startingITBlock() { return m_ITConditionIndex == m_ITBlocksize + 1; } + + void startITBlock(unsigned, unsigned); + void saveITConditionAt(unsigned, unsigned); + void endITBlock() + { + m_currentITCondition = CondNone; + m_ITConditionIndex = 0; + m_ITBlocksize = 0; + } + + void bufferPrintf(const char* format, ...) WTF_ATTRIBUTE_PRINTF(2, 3); + void appendInstructionName(const char*, bool addS = false); + + void appendInstructionNameNoITBlock(const char* instructionName) + { + bufferPrintf(" %-7.7s", instructionName); + } + + void appendRegisterName(unsigned); + void appendRegisterList(unsigned); + void appendFPRegisterName(char, unsigned); + + void appendSeparator() + { + bufferPrintf(", "); + } + + void appendCharacter(const char c) + { + bufferPrintf("%c", c); + } + + void appendString(const char* string) + { + bufferPrintf("%s", string); + } + + void appendShiftType(unsigned shiftValue) + { + bufferPrintf("%s ", shiftName(shiftValue)); + } + + void appendSignedImmediate(int immediate) + { + bufferPrintf("#%d", immediate); + } + + void appendUnsignedImmediate(unsigned immediate) + { + bufferPrintf("#%u", immediate); + } + + void appendPCRelativeOffset(int32_t immediate) + { + bufferPrintf("0x%x", reinterpret_cast<uint32_t>(m_currentPC + immediate)); + } + + void appendShiftAmount(unsigned amount) + { + bufferPrintf("lsl #%u", 16 * amount); + } + + static const int bufferSize = 81; + static const unsigned char CondNone = 0xe; + static const unsigned MaxITBlockSize = 4; + + char m_formatBuffer[bufferSize]; + unsigned char m_ifThenConditions[MaxITBlockSize]; + uint16_t* m_currentPC; + uint32_t m_opcode; + int m_bufferOffset; + int m_currentITCondition; + unsigned m_ITConditionIndex; + unsigned m_ITBlocksize; + +private: + static bool s_initialized; +}; + +#define DEFINE_STATIC_FORMAT16(klass, thisObj) \ + static const char* format(ARMv7D16BitOpcode* thisObj) { return reinterpret_cast< klass *>(thisObj)->format(); } + +class ARMv7D16BitOpcode : public ARMv7DOpcode { +private: + class OpcodeGroup { + public: + OpcodeGroup(uint16_t opcodeMask, uint16_t opcodePattern, const char* (*format)(ARMv7D16BitOpcode*)) + : m_opcodeMask(opcodeMask) + , m_opcodePattern(opcodePattern) + , m_format(format) + , m_next(0) + { + } + + void setNext(OpcodeGroup* next) + { + m_next = next; + } + + OpcodeGroup* next() + { + return m_next; + } + + bool matches(uint16_t opcode) + { + return (opcode & m_opcodeMask) == m_opcodePattern; + } + + const char* format(ARMv7D16BitOpcode* thisObj) + { + return m_format(thisObj); + } + + public: + static const unsigned opcodeTableSize = 32; + static const unsigned opcodeTableMask = opcodeTableSize-1; + + // private: + uint16_t m_opcodeMask; + uint16_t m_opcodePattern; + const char* (*m_format)(ARMv7D16BitOpcode*); + OpcodeGroup* m_next; + }; + +public: + static void init(); + + const char* defaultFormat(); + const char* doDisassemble(); + +protected: + unsigned rm() { return (m_opcode >> 3) & 0x7; } + unsigned rd() { return m_opcode & 0x7; } + unsigned opcodeGroupNumber(unsigned opcode) { return (opcode >> 11) & OpcodeGroup::opcodeTableMask; } + +private: + static OpcodeGroup* opcodeTable[OpcodeGroup::opcodeTableSize]; +}; + +class ARMv7DOpcodeAddRegisterT2 : public ARMv7D16BitOpcode { +public: + static const uint16_t s_mask = 0xff00; + static const uint16_t s_pattern = 0x4400; + + DEFINE_STATIC_FORMAT16(ARMv7DOpcodeAddRegisterT2, thisObj); + +protected: + const char* format(); + + unsigned rdn() { return ((m_opcode >> 4) & 0x8) | (m_opcode & 0x7); } + unsigned rm() { return ((m_opcode >> 3) & 0xf); } +}; + +class ARMv7DOpcodeAddSPPlusImmediate : public ARMv7D16BitOpcode { +public: + static const uint16_t s_mask = 0xf800; + static const uint16_t s_pattern = 0xc800; + + DEFINE_STATIC_FORMAT16(ARMv7DOpcodeAddSPPlusImmediate, thisObj); + +protected: + const char* format(); + + unsigned rd() { return (m_opcode >> 8) & 0x7; } + unsigned immediate8() { return m_opcode & 0x0ff; } +}; + +class ARMv7DOpcodeAddSubtract : public ARMv7D16BitOpcode { +protected: + static const char* const s_opNames[2]; +}; + +class ARMv7DOpcodeAddSubtractT1 : public ARMv7DOpcodeAddSubtract { +public: + static const uint16_t s_mask = 0xfc00; + static const uint16_t s_pattern = 0x1800; + + DEFINE_STATIC_FORMAT16(ARMv7DOpcodeAddSubtractT1, thisObj); + +protected: + const char* format(); + + const char* opName() { return s_opNames[op()]; } + + unsigned op() { return (m_opcode >> 9) & 0x1; } + unsigned rm() { return (m_opcode >> 6) & 0x7; } + unsigned rn() { return (m_opcode >> 3) & 0x7; } +}; + +class ARMv7DOpcodeAddSubtractImmediate3 : public ARMv7DOpcodeAddSubtract { +public: + static const uint16_t s_mask = 0xfc00; + static const uint16_t s_pattern = 0x1c00; + + DEFINE_STATIC_FORMAT16(ARMv7DOpcodeAddSubtractImmediate3, thisObj); + +protected: + const char* format(); + + const char* opName() { return s_opNames[op()]; } + + unsigned op() { return (m_opcode >> 9) & 0x1; } + unsigned immediate3() { return (m_opcode >> 6) & 0x7; } + unsigned rn() { return (m_opcode >> 3) & 0x7; } +}; + +class ARMv7DOpcodeAddSubtractImmediate8 : public ARMv7DOpcodeAddSubtract { +public: + static const uint16_t s_mask = 0xf000; + static const uint16_t s_pattern = 0x3000; + + DEFINE_STATIC_FORMAT16(ARMv7DOpcodeAddSubtractImmediate8, thisObj); + +protected: + const char* format(); + + const char* opName() { return s_opNames[op()]; } + + unsigned op() { return (m_opcode >> 11) & 0x1; } + unsigned rdn() { return (m_opcode >> 8) & 0x7; } + unsigned immediate8() { return m_opcode & 0xff; } +}; + +class ARMv7DOpcodeBranchConditionalT1 : public ARMv7D16BitOpcode { +public: + static const uint16_t s_mask = 0xf000; + static const uint16_t s_pattern = 0xd000; + + DEFINE_STATIC_FORMAT16(ARMv7DOpcodeBranchConditionalT1, thisObj); + +protected: + const char* format(); + + unsigned condition() { return (m_opcode >> 8) & 0xf; } + int offset() { return static_cast<int>(m_opcode & 0xff); } +}; + +class ARMv7DOpcodeBranchExchangeT1 : public ARMv7D16BitOpcode { +public: + static const uint16_t s_mask = 0xff00; + static const uint16_t s_pattern = 0x4700; + + DEFINE_STATIC_FORMAT16(ARMv7DOpcodeBranchExchangeT1, thisObj); + +protected: + const char* format(); + + const char* opName() { return (m_opcode & 0x80) ? "blx" : "bx"; } + unsigned rm() { return ((m_opcode >> 3) & 0xf); } +}; + +class ARMv7DOpcodeBranchT2 : public ARMv7D16BitOpcode { +public: + static const uint16_t s_mask = 0xf800; + static const uint16_t s_pattern = 0xe000; + + DEFINE_STATIC_FORMAT16(ARMv7DOpcodeBranchT2, thisObj); + +protected: + const char* format(); + + int immediate11() { return static_cast<int>(m_opcode & 0x7ff); } +}; + +class ARMv7DOpcodeCompareImmediateT1 : public ARMv7D16BitOpcode { +public: + static const uint16_t s_mask = 0xf800; + static const uint16_t s_pattern = 0x2800; + + DEFINE_STATIC_FORMAT16(ARMv7DOpcodeCompareImmediateT1, thisObj); + +protected: + const char* format(); + + unsigned rn() { return (m_opcode >> 8) & 0x3; } + unsigned immediate8() { return m_opcode & 0xff; } +}; + +class ARMv7DOpcodeCompareRegisterT1 : public ARMv7D16BitOpcode { +public: + static const uint16_t s_mask = 0xffc0; + static const uint16_t s_pattern = 0x4280; + + DEFINE_STATIC_FORMAT16(ARMv7DOpcodeCompareRegisterT1, thisObj); + +protected: + const char* format(); + + unsigned rn() { return m_opcode & 0x7; } +}; + +class ARMv7DOpcodeCompareRegisterT2 : public ARMv7D16BitOpcode { +public: + static const uint16_t s_mask = 0xff00; + static const uint16_t s_pattern = 0x4500; + + DEFINE_STATIC_FORMAT16(ARMv7DOpcodeCompareRegisterT2, thisObj); + +protected: + const char* format(); + + unsigned rn() { return ((m_opcode >> 4) & 0x8) | (m_opcode & 0x7); } + unsigned rm() { return ((m_opcode >> 3) & 0xf); } +}; + +class ARMv7DOpcodeDataProcessingRegisterT1 : public ARMv7D16BitOpcode { +private: + static const char* const s_opNames[16]; + +public: + static const uint16_t s_mask = 0xfc00; + static const uint16_t s_pattern = 0x4000; + + DEFINE_STATIC_FORMAT16(ARMv7DOpcodeDataProcessingRegisterT1, thisObj); + +protected: + const char* format(); + + const char* opName() { return s_opNames[op()]; } + + unsigned op() { return (m_opcode >> 6) & 0xf; } + + unsigned rm() { return (m_opcode >> 3) & 0x7; } + unsigned rdn() { return m_opcode & 0x7; } +}; + +class ARMv7DOpcodeGeneratePCRelativeAddress : public ARMv7D16BitOpcode { +public: + static const uint16_t s_mask = 0xf800; + static const uint16_t s_pattern = 0xa000; + + DEFINE_STATIC_FORMAT16(ARMv7DOpcodeGeneratePCRelativeAddress, thisObj); + +protected: + const char* format(); + + unsigned rd() { return (m_opcode >> 8) & 0x7; } + unsigned immediate8() { return m_opcode & 0x0ff; } +}; + +class ARMv7DOpcodeLoadFromLiteralPool : public ARMv7D16BitOpcode { +public: + static const uint16_t s_mask = 0xf800; + static const uint16_t s_pattern = 0x4800; + + DEFINE_STATIC_FORMAT16(ARMv7DOpcodeLoadFromLiteralPool, thisObj); + +protected: + const char* format(); + + unsigned rt() { return (m_opcode >> 8) & 0x7; } + unsigned immediate8() { return m_opcode & 0x0ff; } +}; + +class ARMv7DOpcodeLoadStoreRegisterImmediate : public ARMv7D16BitOpcode { +private: + static const char* const s_opNames[6]; + +public: + const char* format(); + +protected: + const char* opName() { return s_opNames[op()]; } + + unsigned op() { return ((m_opcode >> 11) & 0x1f) - 0xc; } + unsigned immediate5() { return (m_opcode >> 6) & 0x01f; } + unsigned rn() { return (m_opcode >> 3) & 0x7; } + unsigned rt() { return m_opcode & 0x7; } + unsigned scale(); +}; + +class ARMv7DOpcodeLoadStoreRegisterImmediateWordAndByte : public ARMv7DOpcodeLoadStoreRegisterImmediate { +public: + static const uint16_t s_mask = 0xe000; + static const uint16_t s_pattern = 0x6000; + + DEFINE_STATIC_FORMAT16(ARMv7DOpcodeLoadStoreRegisterImmediate, thisObj); +}; + +class ARMv7DOpcodeStoreRegisterImmediateHalfWord : public ARMv7DOpcodeLoadStoreRegisterImmediate { +public: + static const uint16_t s_mask = 0xf800; + static const uint16_t s_pattern = 0x8000; + + DEFINE_STATIC_FORMAT16(ARMv7DOpcodeLoadStoreRegisterImmediate, thisObj); +}; + +class ARMv7DOpcodeLoadRegisterImmediateHalfWord : public ARMv7DOpcodeLoadStoreRegisterImmediate { +public: + static const uint16_t s_mask = 0xf800; + static const uint16_t s_pattern = 0x8800; + + DEFINE_STATIC_FORMAT16(ARMv7DOpcodeLoadStoreRegisterImmediate, thisObj); +}; + +class ARMv7DOpcodeLoadStoreRegisterOffsetT1 : public ARMv7D16BitOpcode { +private: + static const char* const s_opNames[8]; + +public: + static const uint16_t s_mask = 0xf000; + static const uint16_t s_pattern = 0x5000; + + DEFINE_STATIC_FORMAT16(ARMv7DOpcodeLoadStoreRegisterOffsetT1, thisObj); + +protected: + const char* format(); + + const char* opName() { return s_opNames[opB()]; } + + unsigned opB() { return (m_opcode >> 9) & 0x7; } + unsigned rm() { return (m_opcode >> 6) & 0x7; } + unsigned rn() { return (m_opcode >> 3) & 0x7; } + unsigned rt() { return m_opcode & 0x7; } +}; + +class ARMv7DOpcodeLoadStoreRegisterSPRelative : public ARMv7D16BitOpcode { +private: + static const char* const s_opNames[8]; + +public: + static const uint16_t s_mask = 0xf000; + static const uint16_t s_pattern = 0x9000; + + DEFINE_STATIC_FORMAT16(ARMv7DOpcodeLoadStoreRegisterSPRelative, thisObj); + +protected: + const char* format(); + + const char* opName() { return op() ? "ldr" : "str"; } + + unsigned op() { return (m_opcode >> 11) & 0x1; } + unsigned rt() { return (m_opcode >> 8) & 0x7; } + unsigned immediate8() { return m_opcode & 0xff; } +}; + +class ARMv7DOpcodeLogicalImmediateT1 : public ARMv7D16BitOpcode { +public: + static const uint16_t s_mask = 0xe000; + static const uint16_t s_pattern = 0x0000; + + DEFINE_STATIC_FORMAT16(ARMv7DOpcodeLogicalImmediateT1, thisObj); + +protected: + const char* format(); + + const char* opName() { return shiftName(op()); } + + unsigned op() { return (m_opcode >> 12) & 0x3; } + unsigned immediate5() { return (m_opcode >> 6) & 0x1f; } +}; + +class ARMv7DOpcodeMiscAddSubSP : public ARMv7D16BitOpcode { +public: + static const uint16_t s_mask = 0xff00; + static const uint16_t s_pattern = 0xb000; + + DEFINE_STATIC_FORMAT16(ARMv7DOpcodeMiscAddSubSP, thisObj); + +protected: + const char* format(); + + const char* opName() { return op() ? "sub" : "add"; } + unsigned op() { return (m_opcode >> 7) & 0x1; } + unsigned immediate7() { return m_opcode & 0x7f; } +}; + +class ARMv7DOpcodeMiscByteHalfwordOps : public ARMv7D16BitOpcode { +private: + static const char* const s_opNames[8]; + +public: + static const uint16_t s_mask = 0xf700; + static const uint16_t s_pattern = 0xb200; + + DEFINE_STATIC_FORMAT16(ARMv7DOpcodeMiscByteHalfwordOps, thisObj); + +protected: + const char* format(); + + const char* opName() { return s_opNames[op()]; } + unsigned op() { return ((m_opcode >> 9) & 0x4) || ((m_opcode >> 6) & 0x3); } +}; + +class ARMv7DOpcodeMiscBreakpointT1 : public ARMv7D16BitOpcode { +public: + static const uint16_t s_mask = 0xff00; + static const uint16_t s_pattern = 0xbe00; + + DEFINE_STATIC_FORMAT16(ARMv7DOpcodeMiscBreakpointT1, thisObj); + +protected: + const char* format(); + + unsigned immediate8() { return m_opcode & 0xff; } +}; + +class ARMv7DOpcodeMiscCompareAndBranch : public ARMv7D16BitOpcode { +public: + static const uint16_t s_mask = 0xf500; + static const uint16_t s_pattern = 0xb100; + + DEFINE_STATIC_FORMAT16(ARMv7DOpcodeMiscCompareAndBranch, thisObj); + +protected: + const char* format(); + + const char* opName() { return op() ? "cbnz" : "cbz"; } + unsigned op() { return (m_opcode >> 11) & 0x1; } + int32_t immediate6() { return ((m_opcode >> 4) & 0x20) | ((m_opcode >> 3) & 0x1f); } + unsigned rn() { return m_opcode & 0x7; } +}; + +class ARMv7DOpcodeMiscHint16 : public ARMv7D16BitOpcode { +private: + static const char* const s_opNames[16]; + +public: + static const uint16_t s_mask = 0xff0f; + static const uint16_t s_pattern = 0xbf00; + + DEFINE_STATIC_FORMAT16(ARMv7DOpcodeMiscHint16, thisObj); + +protected: + const char* format(); + + const char* opName() { return s_opNames[opA()]; } + unsigned opA() { return (m_opcode >> 4) & 0xf; } +}; + +class ARMv7DOpcodeMiscIfThenT1 : public ARMv7D16BitOpcode { +public: + static const uint16_t s_mask = 0xff00; + static const uint16_t s_pattern = 0xbf00; + + DEFINE_STATIC_FORMAT16(ARMv7DOpcodeMiscIfThenT1, thisObj); + +protected: + const char* format(); + + unsigned firstCondition() { return (m_opcode >> 4) & 0xf; } + unsigned mask() { return m_opcode & 0xf; } +}; + +class ARMv7DOpcodeMiscPushPop : public ARMv7D16BitOpcode { +public: + static const uint16_t s_mask = 0xf600; + static const uint16_t s_pattern = 0xb400; + + DEFINE_STATIC_FORMAT16(ARMv7DOpcodeMiscPushPop, thisObj); + +protected: + const char* format(); + + const char* opName() { return op() ? "pop" : "push"; } + unsigned op() { return (m_opcode >> 11) & 0x1; } + unsigned registerMask() { return ((m_opcode << 6) & 0x4000) | (m_opcode & 0xff); } +}; + +class ARMv7DOpcodeMoveImmediateT1 : public ARMv7D16BitOpcode { +public: + static const uint16_t s_mask = 0xf800; + static const uint16_t s_pattern = 0x2000; + + DEFINE_STATIC_FORMAT16(ARMv7DOpcodeMoveImmediateT1, thisObj); + +protected: + const char* format(); + + unsigned rd() { return (m_opcode >> 8) & 0x3; } + unsigned immediate8() { return m_opcode & 0xff; } +}; + +class ARMv7DOpcodeMoveRegisterT1 : public ARMv7D16BitOpcode { +public: + static const uint16_t s_mask = 0xff00; + static const uint16_t s_pattern = 0x4600; + + DEFINE_STATIC_FORMAT16(ARMv7DOpcodeMoveRegisterT1, thisObj); + +protected: + const char* format(); + + unsigned rd() { return ((m_opcode >> 4) & 0x8) | (m_opcode & 0x7); } + unsigned rm() { return ((m_opcode >> 3) & 0xf); } +}; + +// 32 Bit instructions + +#define DEFINE_STATIC_FORMAT32(klass, thisObj) \ + static const char* format(ARMv7D32BitOpcode* thisObj) { return reinterpret_cast< klass *>(thisObj)->format(); } + +class ARMv7D32BitOpcode : public ARMv7DOpcode { +private: + class OpcodeGroup { + public: + OpcodeGroup(uint32_t opcodeMask, uint32_t opcodePattern, const char* (*format)(ARMv7D32BitOpcode*)) + : m_opcodeMask(opcodeMask) + , m_opcodePattern(opcodePattern) + , m_format(format) + , m_next(0) + { + } + + void setNext(OpcodeGroup* next) + { + m_next = next; + } + + OpcodeGroup* next() + { + return m_next; + } + + bool matches(uint32_t opcode) + { + return (opcode & m_opcodeMask) == m_opcodePattern; + } + + const char* format(ARMv7D32BitOpcode* thisObj) + { + return m_format(thisObj); + } + + public: + static const unsigned opcodeTableSize = 16; + static const unsigned opcodeTableMask = opcodeTableSize-1; + + private: + uint32_t m_opcodeMask; + uint32_t m_opcodePattern; + const char* (*m_format)(ARMv7D32BitOpcode*); + OpcodeGroup* m_next; + }; + +public: + static void init(); + + const char* defaultFormat(); + const char* doDisassemble(); + +protected: + unsigned rd() { return (m_opcode >> 8) & 0xf; } + unsigned rm() { return m_opcode & 0xf; } + unsigned rn() { return (m_opcode >> 16) & 0xf; } + unsigned rt() { return (m_opcode >> 12) & 0xf; } + + unsigned opcodeGroupNumber(unsigned opcode) { return (opcode >> 25) & OpcodeGroup::opcodeTableMask; } + +private: + static OpcodeGroup* opcodeTable[OpcodeGroup::opcodeTableSize]; +}; + +class ARMv7DOpcodeBranchRelative : public ARMv7D32BitOpcode { +protected: + unsigned sBit() { return (m_opcode >> 26) & 0x1; } + unsigned j1() { return (m_opcode >> 13) & 0x1; } + unsigned j2() { return (m_opcode >> 11) & 0x1; } + unsigned immediate11() { return m_opcode & 0x7ff; } +}; + +class ARMv7DOpcodeConditionalBranchT3 : public ARMv7DOpcodeBranchRelative { +public: + static const uint32_t s_mask = 0xf800d000; + static const uint32_t s_pattern = 0xf0008000; + + DEFINE_STATIC_FORMAT32(ARMv7DOpcodeConditionalBranchT3, thisObj); + +protected: + const char* format(); + + int32_t offset() { return ((static_cast<int32_t>(sBit() << 31)) >> 12) | static_cast<int32_t>((j1() << 18) | (j2() << 17) | (immediate6() << 11) | immediate11()); } + unsigned condition() { return (m_opcode >> 22) & 0xf; } + unsigned immediate6() { return (m_opcode >> 16) & 0x3f; } +}; + +class ARMv7DOpcodeBranchOrBranchLink : public ARMv7DOpcodeBranchRelative { +public: + static const uint32_t s_mask = 0xf8009000; + static const uint32_t s_pattern = 0xf0009000; + + DEFINE_STATIC_FORMAT32(ARMv7DOpcodeBranchOrBranchLink, thisObj); + +protected: + const char* format(); + + int32_t offset() { return ((static_cast<int32_t>(sBit() << 31)) >> 8) | static_cast<int32_t>((~(j1() ^ sBit()) << 22) | (~(j2() ^ sBit()) << 21) | (immediate10() << 11) | immediate11()); } + unsigned immediate10() { return (m_opcode >> 16) & 0x3ff; } + bool isBL() { return !!((m_opcode >> 14) & 0x1); } +}; + +class ARMv7DOpcodeDataProcessingLogicalAndRithmetic : public ARMv7D32BitOpcode { +protected: + static const char* const s_opNames[16]; +}; + +class ARMv7DOpcodeDataProcessingModifiedImmediate : public ARMv7DOpcodeDataProcessingLogicalAndRithmetic { +private: + void appendImmShift(unsigned, unsigned); + +public: + static const uint32_t s_mask = 0xfa008000; + static const uint32_t s_pattern = 0xf0000000; + + DEFINE_STATIC_FORMAT32(ARMv7DOpcodeDataProcessingModifiedImmediate, thisObj); + +protected: + const char* format(); + void appendModifiedImmediate(unsigned); + + const char* opName() { return s_opNames[op()]; } + + unsigned op() { return (m_opcode >> 21) & 0xf; } + unsigned sBit() { return (m_opcode >> 20) & 0x1; } + unsigned immediate12() { return ((m_opcode >> 15) & 0x0800) | ((m_opcode >> 4) & 0x0700) | (m_opcode & 0x00ff); } +}; + +class ARMv7DOpcodeDataProcessingShiftedReg : public ARMv7DOpcodeDataProcessingLogicalAndRithmetic { +private: + void appendImmShift(unsigned, unsigned); + +public: + static const uint32_t s_mask = 0xfe000000; + static const uint32_t s_pattern = 0xea000000; + + DEFINE_STATIC_FORMAT32(ARMv7DOpcodeDataProcessingShiftedReg, thisObj); + +protected: + const char* format(); + + const char* opName() { return s_opNames[op()]; } + + unsigned sBit() { return (m_opcode >> 20) & 0x1; } + unsigned op() { return (m_opcode >> 21) & 0xf; } + unsigned immediate5() { return ((m_opcode >> 10) & 0x1c) | ((m_opcode >> 6) & 0x3); } + unsigned type() { return (m_opcode >> 4) & 0x3; } + unsigned tbBit() { return (m_opcode >> 5) & 0x1; } + unsigned tBit() { return (m_opcode >> 4) & 0x1; } +}; + +class ARMv7DOpcodeDataProcessingReg : public ARMv7D32BitOpcode { +protected: + unsigned op1() { return (m_opcode >> 20) & 0xf; } + unsigned op2() { return (m_opcode >> 4) & 0xf; } +}; + +class ARMv7DOpcodeDataProcessingRegShift : public ARMv7DOpcodeDataProcessingReg { +public: + static const uint32_t s_mask = 0xffe0f0f0; + static const uint32_t s_pattern = 0xfa00f000; + + DEFINE_STATIC_FORMAT32(ARMv7DOpcodeDataProcessingRegShift, thisObj); + +protected: + const char* format(); + + const char* opName() { return shiftName((op1() >> 1) & 0x3); } +}; + +class ARMv7DOpcodeDataProcessingRegExtend : public ARMv7DOpcodeDataProcessingReg { +private: + static const char* const s_opExtendNames[8]; + static const char* const s_opExtendAndAddNames[8]; + +public: + static const uint32_t s_mask = 0xff80f0c0; + static const uint32_t s_pattern = 0xfa00f080; + + DEFINE_STATIC_FORMAT32(ARMv7DOpcodeDataProcessingRegExtend, thisObj); + +protected: + const char* format(); + + const char* opExtendName() { return s_opExtendNames[op1()]; } + const char* opExtendAndAddName() { return s_opExtendAndAddNames[op1()]; } + unsigned rotate() { return (m_opcode >> 4) & 0x3; } +}; + +class ARMv7DOpcodeDataProcessingRegParallel : public ARMv7DOpcodeDataProcessingReg { +private: + static const char* const s_opNames[16]; + +public: + static const uint32_t s_mask = 0xff80f0e0; + static const uint32_t s_pattern = 0xfa00f000; + + DEFINE_STATIC_FORMAT32(ARMv7DOpcodeDataProcessingRegParallel, thisObj); + +protected: + const char* format(); + + const char* opName() { return s_opNames[((op1() & 0x7) << 1) | (op2() & 0x1)]; } +}; + +class ARMv7DOpcodeDataProcessingRegMisc : public ARMv7DOpcodeDataProcessingReg { +private: + static const char* const s_opNames[16]; + +public: + static const uint32_t s_mask = 0xffc0f0c0; + static const uint32_t s_pattern = 0xfa80f080; + + DEFINE_STATIC_FORMAT32(ARMv7DOpcodeDataProcessingRegMisc, thisObj); + +protected: + const char* format(); + + const char* opName() { return s_opNames[((op1() & 0x3) << 2) | (op2() & 0x3)]; } +}; + +class ARMv7DOpcodeHint32 : public ARMv7D32BitOpcode { +private: + static const char* const s_opNames[8]; + +public: + static const uint32_t s_mask = 0xfff0d000; + static const uint32_t s_pattern = 0xf3a08000; + + DEFINE_STATIC_FORMAT32(ARMv7DOpcodeHint32, thisObj); + +protected: + const char* format(); + + const char* opName() { return s_opNames[op()]; } + + bool isDebugHint() { return (m_opcode & 0xf0) == 0xf0; } + unsigned debugOption() { return m_opcode & 0xf; } + unsigned op() { return m_opcode & 0x7; } +}; + +class ARMv7DOpcodeFPTransfer : public ARMv7D32BitOpcode { +public: + static const uint32_t s_mask = 0xffc00e7f; + static const uint32_t s_pattern = 0xee000a10; + + DEFINE_STATIC_FORMAT32(ARMv7DOpcodeFPTransfer, thisObj); + +protected: + const char* format(); + + void appendFPRegister(); + + unsigned opH() { return (m_opcode >> 21) & 0x1; } + unsigned opL() { return (m_opcode >> 20) & 0x1; } + unsigned rt() { return (m_opcode >> 12) & 0xf; } + unsigned opC() { return (m_opcode >> 8) & 0x1; } + unsigned opB() { return (m_opcode >> 5) & 0x3; } + unsigned vd() { return ((m_opcode >> 3) & 0x10) | ((m_opcode >> 16) & 0xf); } + unsigned vn() { return ((m_opcode >> 7) & 0x1) | ((m_opcode >> 15) & 0x1e); } +}; + +class ARMv7DOpcodeDataLoad : public ARMv7D32BitOpcode { +protected: + static const char* const s_opNames[8]; + +protected: + const char* opName() { return s_opNames[op()]; } + + unsigned op() { return ((m_opcode >> 22) & 0x4) | ((m_opcode >> 21) & 0x3); } +}; + +class ARMv7DOpcodeLoadRegister : public ARMv7DOpcodeDataLoad { +public: + static const uint32_t s_mask = 0xfe900800; + static const uint32_t s_pattern = 0xf8100000; + + DEFINE_STATIC_FORMAT32(ARMv7DOpcodeLoadRegister, thisObj); + +protected: + const char* format(); + + unsigned immediate2() { return (m_opcode >> 4) & 0x3; } +}; + +class ARMv7DOpcodeLoadSignedImmediate : public ARMv7DOpcodeDataLoad { +public: + static const uint32_t s_mask = 0xfe900800; + static const uint32_t s_pattern = 0xf8100800; + + DEFINE_STATIC_FORMAT32(ARMv7DOpcodeLoadSignedImmediate, thisObj); + +protected: + const char* format(); + + unsigned pBit() { return (m_opcode >> 10) & 0x1; } + unsigned uBit() { return (m_opcode >> 9) & 0x1; } + unsigned wBit() { return (m_opcode >> 8) & 0x1; } + unsigned immediate8() { return m_opcode & 0xff; } +}; + +class ARMv7DOpcodeLoadUnsignedImmediate : public ARMv7DOpcodeDataLoad { +public: + static const uint32_t s_mask = 0xfe900000; + static const uint32_t s_pattern = 0xf8900000; + + DEFINE_STATIC_FORMAT32(ARMv7DOpcodeLoadUnsignedImmediate, thisObj); + +protected: + const char* format(); + + unsigned immediate12() { return m_opcode & 0xfff; } +}; + +class ARMv7DOpcodeLongMultipleDivide : public ARMv7D32BitOpcode { +protected: + static const char* const s_opNames[8]; + static const char* const s_smlalOpNames[4]; + static const char* const s_smlaldOpNames[2]; + static const char* const s_smlsldOpNames[2]; + +public: + static const uint32_t s_mask = 0xff800000; + static const uint32_t s_pattern = 0xfb800000; + + DEFINE_STATIC_FORMAT32(ARMv7DOpcodeLongMultipleDivide, thisObj); + +protected: + const char* format(); + + const char* opName() { return s_opNames[op1()]; } + const char* smlalOpName() { return s_smlalOpNames[(nBit() << 1) | mBit()]; } + const char* smlaldOpName() { return s_smlaldOpNames[mBit()]; } + const char* smlsldOpName() { return s_smlsldOpNames[mBit()]; } + + unsigned rdLo() { return rt(); } + unsigned rdHi() { return rd(); } + unsigned op1() { return (m_opcode >> 20) & 0x7; } + unsigned op2() { return (m_opcode >> 4) & 0xf; } + unsigned nBit() { return (m_opcode >> 5) & 0x1; } + unsigned mBit() { return (m_opcode >> 4) & 0x1; } +}; + +class ARMv7DOpcodeDataPushPopSingle : public ARMv7D32BitOpcode { +public: + static const uint32_t s_mask = 0xffef0fff; + static const uint32_t s_pattern = 0xf84d0d04; + + DEFINE_STATIC_FORMAT32(ARMv7DOpcodeDataPushPopSingle, thisObj); + +protected: + const char* format(); + + const char* opName() { return op() ? "pop" : "push"; } + unsigned op() { return (m_opcode >> 20) & 0x1; } +}; + +class ARMv7DOpcodeDataPushPopMultiple : public ARMv7D32BitOpcode { +protected: + void appendRegisterList(); + + unsigned registerList() { return m_opcode & 0xffff; } + unsigned condition() { return m_opcode >> 28; } +}; + +class ARMv7DOpcodeDataPopMultiple : public ARMv7DOpcodeDataPushPopMultiple { +public: + static const uint32_t s_mask = 0x0fff0000; + static const uint32_t s_pattern = 0x08bd0000; + + DEFINE_STATIC_FORMAT32(ARMv7DOpcodeDataPopMultiple, thisObj); + +protected: + const char* format(); +}; + +class ARMv7DOpcodeDataPushMultiple : public ARMv7DOpcodeDataPushPopMultiple { +public: + static const uint32_t s_mask = 0xfe7f0000; + static const uint32_t s_pattern = 0xe82d0000; + + DEFINE_STATIC_FORMAT32(ARMv7DOpcodeDataPushMultiple, thisObj); + +protected: + const char* format(); +}; + +class ARMv7DOpcodeDataStoreSingle : public ARMv7D32BitOpcode { +protected: + static const char* const s_opNames[4]; + +protected: + const char* opName() { return s_opNames[op()]; } + + unsigned op() { return (m_opcode >> 21) & 0x3; } +}; + +class ARMv7DOpcodeStoreSingleImmediate12 : public ARMv7DOpcodeDataStoreSingle { +public: + static const uint32_t s_mask = 0xfff00000; + static const uint32_t s_pattern = 0xf8c00000; + + DEFINE_STATIC_FORMAT32(ARMv7DOpcodeStoreSingleImmediate12, thisObj); + + const char* format(); + +protected: + unsigned immediate12() { return m_opcode & 0xfff; } +}; + +class ARMv7DOpcodeStoreSingleImmediate8 : public ARMv7DOpcodeDataStoreSingle { +public: + static const uint32_t s_mask = 0xfff00800; + static const uint32_t s_pattern = 0xf8400800; + + DEFINE_STATIC_FORMAT32(ARMv7DOpcodeStoreSingleImmediate8, thisObj); + + const char* format(); + +protected: + unsigned pBit() { return (m_opcode >> 10) & 0x1; } + unsigned uBit() { return (m_opcode >> 9) & 0x1; } + unsigned wBit() { return (m_opcode >> 8) & 0x1; } + unsigned immediate8() { return m_opcode & 0xff; } +}; + +class ARMv7DOpcodeStoreSingleRegister : public ARMv7DOpcodeDataStoreSingle { +public: + static const uint32_t s_mask = 0xfff00fc0; + static const uint32_t s_pattern = 0xf8400000; + + DEFINE_STATIC_FORMAT32(ARMv7DOpcodeStoreSingleRegister, thisObj); + +protected: + const char* format(); + + unsigned immediate2() { return (m_opcode >> 4) & 0x3; } +}; + +class ARMv7DOpcodeUnmodifiedImmediate : public ARMv7D32BitOpcode { +protected: + static const char* const s_opNames[16]; + +public: + static const uint32_t s_mask = 0xfa008000; + static const uint32_t s_pattern = 0xf2000000; + + DEFINE_STATIC_FORMAT32(ARMv7DOpcodeUnmodifiedImmediate, thisObj); + +protected: + const char* format(); + + const char* opName() { return s_opNames[op() >> 1]; } + + unsigned op() { return (m_opcode >> 20) & 0x1f; } + unsigned shBit() { return (m_opcode >> 21) & 0x1; } + unsigned bitNumOrSatImmediate() { return m_opcode & 0x1f; } + unsigned immediate5() { return ((m_opcode >> 9) & 0x1c) | ((m_opcode >> 6) & 0x3); } + unsigned immediate12() { return ((m_opcode >> 15) & 0x0800) | ((m_opcode >> 4) & 0x0700) | (m_opcode & 0x00ff); } + unsigned immediate16() { return ((m_opcode >> 4) & 0xf000) | ((m_opcode >> 15) & 0x0800) | ((m_opcode >> 4) & 0x0700) | (m_opcode & 0x00ff); } +}; + +class ARMv7DOpcodeVCMP : public ARMv7D32BitOpcode { +public: + static const uint32_t s_mask = 0x0fbf0e50; + static const uint32_t s_pattern = 0x0eb40a40; + + DEFINE_STATIC_FORMAT32(ARMv7DOpcodeVCMP, thisObj); + +protected: + const char* format(); + + unsigned condition() { return m_opcode >> 28; } + unsigned dBit() { return (m_opcode >> 22) & 0x1; } + unsigned vd() { return (m_opcode >> 12) & 0xf; } + unsigned szBit() { return (m_opcode >> 8) & 0x1; } + unsigned eBit() { return (m_opcode >> 7) & 0x1; } + unsigned mBit() { return (m_opcode >> 5) & 0x1; } + unsigned vm() { return m_opcode & 0xf; } +}; + +class ARMv7DOpcodeVCVTBetweenFPAndInt : public ARMv7D32BitOpcode { +public: + static const uint32_t s_mask = 0x0fb80e50; + static const uint32_t s_pattern = 0x0eb80a40; + + DEFINE_STATIC_FORMAT32(ARMv7DOpcodeVCVTBetweenFPAndInt, thisObj); + +protected: + const char* format(); + + unsigned condition() { return m_opcode >> 28; } + unsigned dBit() { return (m_opcode >> 22) & 0x1; } + unsigned op2() { return (m_opcode >> 16) & 0x7; } + unsigned vd() { return (m_opcode >> 12) & 0xf; } + unsigned szBit() { return (m_opcode >> 8) & 0x1; } + unsigned op() { return (m_opcode >> 7) & 0x1; } + unsigned mBit() { return (m_opcode >> 5) & 0x1; } + unsigned vm() { return m_opcode & 0xf; } +}; + +class ARMv7DOpcodeVLDR : public ARMv7D32BitOpcode { +public: + static const uint32_t s_mask = 0x0f300e00; + static const uint32_t s_pattern = 0x0d100a00; + + DEFINE_STATIC_FORMAT32(ARMv7DOpcodeVLDR, thisObj); + +protected: + const char* format(); + + unsigned condition() { return m_opcode >> 28; } + unsigned uBit() { return (m_opcode >> 23) & 0x1; } + unsigned rn() { return (m_opcode >> 16) & 0xf; } + unsigned vd() { return ((m_opcode >> 18) & 0x10) | ((m_opcode >> 12) & 0xf); } + bool doubleReg() { return !!(m_opcode & 0x100); } + unsigned immediate8() { return m_opcode & 0xff; } +}; + +class ARMv7DOpcodeVMOVDoublePrecision : public ARMv7D32BitOpcode { +public: + static const uint32_t s_mask = 0xffe00fd0; + static const uint32_t s_pattern = 0xec400b10; + + DEFINE_STATIC_FORMAT32(ARMv7DOpcodeVMOVDoublePrecision, thisObj); + +protected: + const char* format(); + + unsigned op() { return (m_opcode >> 20) & 0x1; } + unsigned rt2() { return (m_opcode >> 16) & 0xf; } + unsigned rt() { return (m_opcode >> 16) & 0xf; } + unsigned vm() { return (m_opcode & 0xf) | ((m_opcode >> 1) & 0x10); } +}; + +class ARMv7DOpcodeVMOVSinglePrecision : public ARMv7D32BitOpcode { +public: + static const uint32_t s_mask = 0xffe00fd0; + static const uint32_t s_pattern = 0xec400a10; + + DEFINE_STATIC_FORMAT32(ARMv7DOpcodeVMOVSinglePrecision, thisObj); + +protected: + const char* format(); + + unsigned op() { return (m_opcode >> 20) & 0x1; } + unsigned rt2() { return (m_opcode >> 16) & 0xf; } + unsigned rt() { return (m_opcode >> 16) & 0xf; } + unsigned vm() { return ((m_opcode << 1) & 0x1e) | ((m_opcode >> 5) & 0x1); } +}; + +class ARMv7DOpcodeVMSR : public ARMv7D32BitOpcode { +public: + static const uint32_t s_mask = 0xffef0fff; + static const uint32_t s_pattern = 0xeee10a10; + + DEFINE_STATIC_FORMAT32(ARMv7DOpcodeVMSR, thisObj); + +protected: + const char* format(); + + unsigned opL() { return (m_opcode >> 20) & 0x1; } + unsigned rt() { return (m_opcode >> 12) & 0xf; } +}; + + +} } // namespace JSC::ARMv7Disassembler + +using JSC::ARMv7Disassembler::ARMv7DOpcode; + +#endif // #if USE(ARMV7_DISASSEMBLER) diff --git a/Source/JavaScriptCore/disassembler/ARMv7Disassembler.cpp b/Source/JavaScriptCore/disassembler/ARMv7Disassembler.cpp new file mode 100644 index 000000000..bfb48953c --- /dev/null +++ b/Source/JavaScriptCore/disassembler/ARMv7Disassembler.cpp @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2013 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "Disassembler.h" + +#if USE(ARMV7_DISASSEMBLER) + +#include "ARMv7/ARMv7DOpcode.h" +#include "MacroAssemblerCodeRef.h" + +namespace JSC { + +bool tryToDisassemble(const MacroAssemblerCodePtr& codePtr, size_t size, const char* prefix, PrintStream& out) +{ + ARMv7DOpcode armOpcode; + + uint16_t* currentPC = reinterpret_cast<uint16_t*>(reinterpret_cast<uintptr_t>(codePtr.executableAddress())&~1); + uint16_t* endPC = currentPC + (size / sizeof(uint16_t)); + + while (currentPC < endPC) { + char pcString[12]; + snprintf(pcString, sizeof(pcString), "0x%x", reinterpret_cast<unsigned>(currentPC)); + out.printf("%s%10s: %s\n", prefix, pcString, armOpcode.disassemble(currentPC)); + } + + return true; +} + +} // namespace JSC + +#endif // USE(ARMV7_DISASSEMBLER) + diff --git a/Source/JavaScriptCore/disassembler/Disassembler.cpp b/Source/JavaScriptCore/disassembler/Disassembler.cpp index a72e22a9e..788a6c362 100644 --- a/Source/JavaScriptCore/disassembler/Disassembler.cpp +++ b/Source/JavaScriptCore/disassembler/Disassembler.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012, 2013 Apple Inc. All rights reserved. + * Copyright (C) 2012, 2013, 2015 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -26,21 +26,126 @@ #include "config.h" #include "Disassembler.h" -#if ENABLE(DISASSEMBLER) - #include "MacroAssemblerCodeRef.h" +#include <wtf/Condition.h> #include <wtf/DataLog.h> +#include <wtf/Deque.h> +#include <wtf/Lock.h> +#include <wtf/NeverDestroyed.h> +#include <wtf/StringPrintStream.h> +#include <wtf/Threading.h> namespace JSC { -void disassemble(const MacroAssemblerCodePtr& codePtr, size_t size, const char* prefix, PrintStream& out, InstructionSubsetHint subsetHint) +void disassemble(const MacroAssemblerCodePtr& codePtr, size_t size, const char* prefix, PrintStream& out) { - if (tryToDisassemble(codePtr, size, prefix, out, subsetHint)) + if (tryToDisassemble(codePtr, size, prefix, out)) return; out.printf("%sdisassembly not available for range %p...%p\n", prefix, codePtr.executableAddress(), static_cast<char*>(codePtr.executableAddress()) + size); } +namespace { + +// This is really a struct, except that it should be a class because that's what the WTF_* macros +// expect. +class DisassemblyTask { + WTF_MAKE_NONCOPYABLE(DisassemblyTask); + WTF_MAKE_FAST_ALLOCATED; +public: + DisassemblyTask() + { + } + + ~DisassemblyTask() + { + if (header) + free(header); // free() because it would have been copied by strdup. + } + + char* header { nullptr }; + MacroAssemblerCodeRef codeRef; + size_t size { 0 }; + const char* prefix { nullptr }; +}; + +class AsynchronousDisassembler { +public: + AsynchronousDisassembler() + { + createThread("Asynchronous Disassembler", [&] () { run(); }); + } + + void enqueue(std::unique_ptr<DisassemblyTask> task) + { + LockHolder locker(m_lock); + m_queue.append(WTFMove(task)); + m_condition.notifyAll(); + } + + void waitUntilEmpty() + { + LockHolder locker(m_lock); + while (!m_queue.isEmpty() || m_working) + m_condition.wait(m_lock); + } + +private: + NO_RETURN void run() + { + for (;;) { + std::unique_ptr<DisassemblyTask> task; + { + LockHolder locker(m_lock); + m_working = false; + m_condition.notifyAll(); + while (m_queue.isEmpty()) + m_condition.wait(m_lock); + task = m_queue.takeFirst(); + m_working = true; + } + + dataLog(task->header); + disassemble(task->codeRef.code(), task->size, task->prefix, WTF::dataFile()); + } + } + + Lock m_lock; + Condition m_condition; + Deque<std::unique_ptr<DisassemblyTask>> m_queue; + bool m_working { false }; +}; + +bool hadAnyAsynchronousDisassembly = false; + +AsynchronousDisassembler& asynchronousDisassembler() +{ + static NeverDestroyed<AsynchronousDisassembler> disassembler; + hadAnyAsynchronousDisassembly = true; + return disassembler.get(); +} + +} // anonymous namespace + +void disassembleAsynchronously( + const CString& header, const MacroAssemblerCodeRef& codeRef, size_t size, const char* prefix) +{ + std::unique_ptr<DisassemblyTask> task = std::make_unique<DisassemblyTask>(); + task->header = strdup(header.data()); // Yuck! We need this because CString does racy refcounting. + task->codeRef = codeRef; + task->size = size; + task->prefix = prefix; + + asynchronousDisassembler().enqueue(WTFMove(task)); +} + +void waitForAsynchronousDisassembly() +{ + if (!hadAnyAsynchronousDisassembly) + return; + + asynchronousDisassembler().waitUntilEmpty(); +} + } // namespace JSC -#endif // ENABLE(DISASSEMBLER) diff --git a/Source/JavaScriptCore/disassembler/Disassembler.h b/Source/JavaScriptCore/disassembler/Disassembler.h index 7088fc46a..9317449ee 100644 --- a/Source/JavaScriptCore/disassembler/Disassembler.h +++ b/Source/JavaScriptCore/disassembler/Disassembler.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012, 2013 Apple Inc. All rights reserved. + * Copyright (C) 2012, 2013, 2015 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -23,22 +23,22 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef Disassembler_h -#define Disassembler_h +#pragma once -#include <wtf/Platform.h> +#include "JSExportMacros.h" +#include <functional> #include <wtf/PrintStream.h> +#include <wtf/text/CString.h> namespace JSC { class MacroAssemblerCodePtr; - -enum InstructionSubsetHint { MacroAssemblerSubset, LLVMSubset }; +class MacroAssemblerCodeRef; #if ENABLE(DISASSEMBLER) -bool tryToDisassemble(const MacroAssemblerCodePtr&, size_t, const char* prefix, PrintStream&, InstructionSubsetHint = MacroAssemblerSubset); +bool tryToDisassemble(const MacroAssemblerCodePtr&, size_t, const char* prefix, PrintStream&); #else -inline bool tryToDisassemble(const MacroAssemblerCodePtr&, size_t, const char*, PrintStream&, InstructionSubsetHint = MacroAssemblerSubset) +inline bool tryToDisassemble(const MacroAssemblerCodePtr&, size_t, const char*, PrintStream&) { return false; } @@ -46,9 +46,13 @@ inline bool tryToDisassemble(const MacroAssemblerCodePtr&, size_t, const char*, // Prints either the disassembly, or a line of text indicating that disassembly failed and // the range of machine code addresses. -void disassemble(const MacroAssemblerCodePtr&, size_t, const char* prefix, PrintStream& out, InstructionSubsetHint = MacroAssemblerSubset); +void disassemble(const MacroAssemblerCodePtr&, size_t, const char* prefix, PrintStream& out); -} // namespace JSC +// Asynchronous disassembly. This happens on another thread, and calls the provided +// callback when the disassembly is done. +void disassembleAsynchronously( + const CString& header, const MacroAssemblerCodeRef&, size_t, const char* prefix); -#endif // Disassembler_h +JS_EXPORT_PRIVATE void waitForAsynchronousDisassembly(); +} // namespace JSC diff --git a/Source/JavaScriptCore/disassembler/LLVMDisassembler.cpp b/Source/JavaScriptCore/disassembler/LLVMDisassembler.cpp deleted file mode 100644 index a117bfa28..000000000 --- a/Source/JavaScriptCore/disassembler/LLVMDisassembler.cpp +++ /dev/null @@ -1,131 +0,0 @@ -/* - * Copyright (C) 2013 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" -#include "LLVMDisassembler.h" - -#if USE(LLVM_DISASSEMBLER) - -#include "InitializeLLVM.h" -#include "LLVMAPI.h" -#include "MacroAssemblerCodeRef.h" - -namespace JSC { - -static const unsigned symbolStringSize = 40; - -static const char *symbolLookupCallback( - void* opaque, uint64_t referenceValue, uint64_t* referenceType, uint64_t referencePC, - const char** referenceName) -{ - // Set this if you want to debug an unexpected reference type. Currently we only encounter these - // if we try to disassemble garbage, since our code generator never uses them. These include things - // like PC-relative references. - static const bool crashOnUnexpected = false; - - char* symbolString = static_cast<char*>(opaque); - - switch (*referenceType) { - case LLVMDisassembler_ReferenceType_InOut_None: - return 0; - case LLVMDisassembler_ReferenceType_In_Branch: - *referenceName = 0; - *referenceType = LLVMDisassembler_ReferenceType_InOut_None; - snprintf( - symbolString, symbolStringSize, "0x%lx", - static_cast<unsigned long>(referenceValue)); - return symbolString; - default: - if (crashOnUnexpected) { - dataLog("referenceValue = ", referenceValue, "\n"); - dataLog("referenceType = ", RawPointer(referenceType), ", *referenceType = ", *referenceType, "\n"); - dataLog("referencePC = ", referencePC, "\n"); - dataLog("referenceName = ", RawPointer(referenceName), "\n"); - - RELEASE_ASSERT_NOT_REACHED(); - } - - *referenceName = "unimplemented reference type!"; - *referenceType = LLVMDisassembler_ReferenceType_InOut_None; - snprintf( - symbolString, symbolStringSize, "unimplemented:0x%lx", - static_cast<unsigned long>(referenceValue)); - return symbolString; - } -} - -bool tryToDisassembleWithLLVM( - const MacroAssemblerCodePtr& codePtr, size_t size, const char* prefix, PrintStream& out, - InstructionSubsetHint) -{ - initializeLLVM(); - - const char* triple; -#if CPU(X86_64) - triple = "x86_64-apple-darwin"; -#elif CPU(X86) - triple = "x86-apple-darwin"; -#else -#error "LLVM disassembler currently not supported on this CPU." -#endif - - char symbolString[symbolStringSize]; - - LLVMDisasmContextRef disassemblyContext = - llvm->CreateDisasm(triple, symbolString, 0, 0, symbolLookupCallback); - RELEASE_ASSERT(disassemblyContext); - - char pcString[20]; - char instructionString[1000]; - - uint8_t* pc = static_cast<uint8_t*>(codePtr.executableAddress()); - uint8_t* end = pc + size; - - while (pc < end) { - snprintf( - pcString, sizeof(pcString), "0x%lx", - static_cast<unsigned long>(bitwise_cast<uintptr_t>(pc))); - - size_t instructionSize = llvm->DisasmInstruction( - disassemblyContext, pc, end - pc, bitwise_cast<uintptr_t>(pc), - instructionString, sizeof(instructionString)); - - if (!instructionSize) - snprintf(instructionString, sizeof(instructionString), ".byte 0x%02x", *pc++); - else - pc += instructionSize; - - out.printf("%s%16s: %s\n", prefix, pcString, instructionString); - } - - llvm->DisasmDispose(disassemblyContext); - - return true; -} - -} // namespace JSC - -#endif // USE(LLVM_DISASSEMBLER) - diff --git a/Source/JavaScriptCore/disassembler/UDis86Disassembler.cpp b/Source/JavaScriptCore/disassembler/UDis86Disassembler.cpp new file mode 100644 index 000000000..4093f13e4 --- /dev/null +++ b/Source/JavaScriptCore/disassembler/UDis86Disassembler.cpp @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2012, 2013, 2016 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "UDis86Disassembler.h" + +#if USE(UDIS86) + +#include "MacroAssemblerCodeRef.h" +#include "udis86.h" + +namespace JSC { + +bool tryToDisassembleWithUDis86(const MacroAssemblerCodePtr& codePtr, size_t size, const char* prefix, PrintStream& out) +{ + ud_t disassembler; + ud_init(&disassembler); + ud_set_input_buffer(&disassembler, static_cast<unsigned char*>(codePtr.executableAddress()), size); +#if CPU(X86_64) + ud_set_mode(&disassembler, 64); +#else + ud_set_mode(&disassembler, 32); +#endif + ud_set_pc(&disassembler, bitwise_cast<uintptr_t>(codePtr.executableAddress())); + ud_set_syntax(&disassembler, UD_SYN_ATT); + + uint64_t currentPC = disassembler.pc; + while (ud_disassemble(&disassembler)) { + char pcString[20]; + snprintf(pcString, sizeof(pcString), "0x%lx", static_cast<unsigned long>(currentPC)); + out.printf("%s%16s: %s\n", prefix, pcString, ud_insn_asm(&disassembler)); + currentPC = disassembler.pc; + } + + return true; +} + +} // namespace JSC + +#endif // USE(UDIS86) + diff --git a/Source/JavaScriptCore/disassembler/LLVMDisassembler.h b/Source/JavaScriptCore/disassembler/UDis86Disassembler.h index 745912f27..8de53ea3e 100644 --- a/Source/JavaScriptCore/disassembler/LLVMDisassembler.h +++ b/Source/JavaScriptCore/disassembler/UDis86Disassembler.h @@ -23,24 +23,20 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef LLVMDisassembler_h -#define LLVMDisassembler_h +#pragma once #include "Disassembler.h" namespace JSC { -#if USE(LLVM_DISASSEMBLER) +#if USE(UDIS86) -bool tryToDisassembleWithLLVM(const MacroAssemblerCodePtr& codePtr, size_t size, const char* prefix, PrintStream& out, InstructionSubsetHint); +bool tryToDisassembleWithUDis86(const MacroAssemblerCodePtr& codePtr, size_t size, const char* prefix, PrintStream& out); -#else // USE(LLVM_DISASSEMBLER) +#else // USE(UDIS86) -inline bool tryToDisassembleWithLLVM(const MacroAssemblerCodePtr&, size_t, const char*, PrintStream&, InstructionSubsetHint) { return false; } +inline bool tryToDisassembleWithUDis86(const MacroAssemblerCodePtr&, size_t, const char*, PrintStream&) { return false; } -#endif // USE(LLVM_DISASSEMBLER) +#endif // USE(UDIS86) } // namespace JSC - -#endif // LLVMDisassembler_h - diff --git a/Source/JavaScriptCore/disassembler/X86Disassembler.cpp b/Source/JavaScriptCore/disassembler/X86Disassembler.cpp index 5cce4a93f..247b2274d 100644 --- a/Source/JavaScriptCore/disassembler/X86Disassembler.cpp +++ b/Source/JavaScriptCore/disassembler/X86Disassembler.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2013 Apple Inc. All rights reserved. + * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -26,49 +26,19 @@ #include "config.h" #include "Disassembler.h" -#if ENABLE(DISASSEMBLER) -#if USE(UDIS86) || USE(LLVM_DISASSEMBLER) +#if USE(UDIS86) #include "MacroAssemblerCodeRef.h" #include "Options.h" #include "UDis86Disassembler.h" -#include "LLVMDisassembler.h" namespace JSC { -// This horrifying monster is needed because neither of our disassemblers supports -// all of x86, and using them together to disassemble the same instruction stream -// would result in a fairly jarring print-out since they print in different -// styles. Maybe we can do better in the future, but for now the caller hints -// whether he's using the subset of the architecture that our MacroAssembler -// supports (in which case we go with UDis86) or if he's using the LLVM subset. - -bool tryToDisassemble(const MacroAssemblerCodePtr& codePtr, size_t size, const char* prefix, PrintStream& out, InstructionSubsetHint subsetHint) +bool tryToDisassemble(const MacroAssemblerCodePtr& codePtr, size_t size, const char* prefix, PrintStream& out) { - if (Options::forceUDis86Disassembler()) - return tryToDisassembleWithUDis86(codePtr, size, prefix, out, subsetHint); - - if (Options::forceLLVMDisassembler()) - return tryToDisassembleWithLLVM(codePtr, size, prefix, out, subsetHint); - - if (subsetHint == MacroAssemblerSubset - && tryToDisassembleWithUDis86(codePtr, size, prefix, out, MacroAssemblerSubset)) - return true; - - if (subsetHint == LLVMSubset - && tryToDisassembleWithLLVM(codePtr, size, prefix, out, LLVMSubset)) - return true; - - if (tryToDisassembleWithUDis86(codePtr, size, prefix, out, subsetHint)) - return true; - if (tryToDisassembleWithLLVM(codePtr, size, prefix, out, subsetHint)) - return true; - - RELEASE_ASSERT_NOT_REACHED(); - return false; + return tryToDisassembleWithUDis86(codePtr, size, prefix, out); } } // namespace JSC -#endif // USE(UDIS86) || USE(LLVM_DISASSEMBLER) -#endif // ENABLE(DISASSEMBLER) +#endif // USE(UDIS86) diff --git a/Source/JavaScriptCore/disassembler/udis86/differences.txt b/Source/JavaScriptCore/disassembler/udis86/differences.txt new file mode 100644 index 000000000..c3dabf6f0 --- /dev/null +++ b/Source/JavaScriptCore/disassembler/udis86/differences.txt @@ -0,0 +1,9 @@ +This documents the differences between the stock version of udis86 and the one found +here: + +- All files not named "udis86" were prefixed with "udis86". + +- assert() has been changed to ASSERT() + +- Fixed udis86_syn-att.c's jump destination printing to work correctly in 64-bit mode. + diff --git a/Source/JavaScriptCore/disassembler/udis86/optable.xml b/Source/JavaScriptCore/disassembler/udis86/optable.xml new file mode 100644 index 000000000..3bda8587e --- /dev/null +++ b/Source/JavaScriptCore/disassembler/udis86/optable.xml @@ -0,0 +1,10099 @@ +<?xml version="1.0"?> +<?xml-stylesheet href="optable.xsl" type="text/xsl"?> +<x86optable> + + <!-- + The most important elements of each instruction definition are the + pfx (prefix), opc (opcode), and opr (operand) elements. Each is a + CDATA element consisting of blank-separated words. Upper and lower + case are equivalent. + + <pfx></pfx> + + pfx describes the set of valid prefixes that can precede the main + opcode without turning it into a different instruction. These may + be: + + aso accepts address size override + oso accepts operand size override + seg accepts a segment override + rexw, rexr, rexx, rexb + uses the indicated REX bit + vexl accepts the vex.L prefix bit, in other words, the vexl + bit can be used in the decoding of the avx instruction. + + <opr></opr> + + [T][s] + + Size Suffix + =========== + + x - If vex.L = 1 => m256/YMM + vex.L = 0 => m128/XMM + + opc words may be actual byte values (two hex digits), or may be one of + the following: + /sse=66,f3,f2 - required prefix (always first, and always + followed by 0f) + /3dnow=00-ff - this is a 3DNow opcode (only in a definition of the + form 0f 0f 3dnow=<byte>) + /a=16,32,64 - has this address size + /m=16,32,64,!64 - applicable only when the CPU is in this mode + /o=16,32,64 - has this operand size + /mod=11,!11 - has ModR/M with 11 or not-11 in the Mod field + /reg=0-7 - has ModR/M with this value in the reg field + /rm=0-7 - has ModR/M with this value in the R/M field (only with + /mod=11) + /x87=00-3f - X87 opcode with this value in the low 6 bits of the + following "ModR/M" byte (only with /mod=11 and no other modifiers) + + opr words follow the Intel documentation somewhat, and specify the + location and the size of the operand. The OperandDict table in + ud_itab.py maps these words to named OP_ and SZ_ constants for the + location and size respectively. These constants are defined in + decode.h, q.v. for details. + + The mode element affects instruction semantics but not decoding: + inv64 - invalid in 64-bit mode + def64 - default operand size is 64 bits in 64-bit mode + + cpuid + + The cpuid element maybe applied to an instruction or a specific + definition of the instruction. One ore more strings define the + cpuid features that the instruction (or a definition belongs to) + + Values are: sse, sse2, sse3, sse4, sse4.1, sse4.2, avx + + AVX Instructions + + AVX instructions can be described in two ways. One, the explicit + form, and the other that promotes an existing sse instruction + definition to its avx form. + + If an instruction is defined to be in cpuid=avx, but is defined in + the legacy form (using /sse= extensions), then the opcode generator + will infer that as two definitions, one the see instruction and the + other, an inferred avx instruction. + + In generating the sse definition from the above, the following + transformations happen, + + - /vexw and /vexl extensions (if any) are removed + - The operands H and L are removed. Operands specified on + the right to removed operands are shifted to the left + position. + - The vexl prefix is removed. + - "avx" is removed form the cpuid definition. + + In generating the avx definition from the above, the following + transformations happen, + + - c4 is inserted in the 0th position of the opcode string + - /sse extension is removed + - A new /vex extension is constructed using /sse, 0f, 38 and + 3a opcodes (if any). + - Operands V, W, H, and U are marked explicitly to have the + size suffix "x" + + If the above transformations do not generate the required + definitions, the instructions will need to be defined separately. + --> + + <instruction> + <mnemonic>aaa</mnemonic> + <def> + <opc>37 /m=!64</opc> + </def> + </instruction> + + <instruction> + <mnemonic>aad</mnemonic> + <def> + <opc>d5 /m=!64</opc> + <opr>Ib</opr> + </def> + </instruction> + + <instruction> + <mnemonic>aam</mnemonic> + <def> + <opc>d4 /m=!64</opc> + <opr>Ib</opr> + </def> + </instruction> + + <instruction> + <mnemonic>aas</mnemonic> + <def> + <opc>3f /m=!64</opc> + </def> + </instruction> + + <instruction> + <mnemonic>adc</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>10</opc> + <opr>Eb Gb</opr> + </def> + <def> + <pfx>aso oso rexw rexr rexx rexb</pfx> + <opc>11</opc> + <opr>Ev Gv</opr> + </def> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>12</opc> + <opr>Gb Eb</opr> + </def> + <def> + <pfx>aso oso rexw rexr rexx rexb</pfx> + <opc>13</opc> + <opr>Gv Ev</opr> + </def> + <def> + <opc>14</opc> + <opr>AL Ib</opr> + </def> + <def> + <pfx>oso rexw</pfx> + <opc>15</opc> + <opr>rAX sIz</opr> + </def> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>80 /reg=2</opc> + <opr>Eb Ib</opr> + </def> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>82 /reg=2 /m=!64</opc> + <opr>Eb Ib</opr> + <mode>inv64</mode> + </def> + <def> + <pfx>aso oso rexw rexr rexx rexb</pfx> + <opc>81 /reg=2</opc> + <opr>Ev sIz</opr> + </def> + <def> + <pfx>aso oso rexw rexr rexx rexb</pfx> + <opc>83 /reg=2</opc> + <opr>Ev sIb</opr> + </def> + </instruction> + + <instruction> + <mnemonic>add</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>00</opc> + <opr>Eb Gb</opr> + </def> + <def> + <pfx>aso oso rexw rexr rexx rexb</pfx> + <opc>01</opc> + <opr>Ev Gv</opr> + </def> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>02</opc> + <opr>Gb Eb</opr> + </def> + <def> + <pfx>aso oso rexw rexr rexx rexb</pfx> + <opc>03</opc> + <opr>Gv Ev</opr> + </def> + <def> + <opc>04</opc> + <opr>AL Ib</opr> + </def> + <def> + <pfx>oso rexw</pfx> + <opc>05</opc> + <opr>rAX sIz</opr> + </def> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>80 /reg=0</opc> + <opr>Eb Ib</opr> + </def> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>82 /reg=0 /m=!64</opc> + <opr>Eb Ib</opr> + <mode>inv64</mode> + </def> + <def> + <pfx>aso oso rexw rexr rexx rexb</pfx> + <opc>81 /reg=0</opc> + <opr>Ev sIz</opr> + </def> + <def> + <pfx>aso oso rexw rexr rexx rexb</pfx> + <opc>83 /reg=0</opc> + <opr>Ev sIb</opr> + </def> + </instruction> + + <instruction> + <mnemonic>addpd</mnemonic> + <def> + <pfx>aso rexr rexx rexb vexl</pfx> + <opc>/sse=66 0f 58</opc> + <opr>V H W</opr> + <cpuid>sse2 avx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>addps</mnemonic> + <def> + <pfx>aso rexr rexx rexb vexl</pfx> + <opc>0f 58</opc> + <opr>V H W</opr> + <cpuid>sse avx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>addsd</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>/sse=f2 0f 58</opc> + <opr>V H W</opr> + <cpuid>sse2 avx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>addss</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>/sse=f3 0f 58</opc> + <opr>V H W</opr> + <cpuid>sse avx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>addsubpd</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>/sse=66 0f d0</opc> + <opr>V H W</opr> + <cpuid>sse3 avx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>addsubps</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>/sse=f2 0f d0</opc> + <opr>V H W</opr> + <cpuid>sse3 avx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>aesdec</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>/sse=66 0f 38 de</opc> + <opr>V H W</opr> + <cpuid>aesni avx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>aesdeclast</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>/sse=66 0f 38 df</opc> + <opr>V W</opr> + <cpuid>aesni avx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>aesenc</mnemonic> + <cpuid>aesni</cpuid> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>/sse=66 0f 38 dc</opc> + <opr>V W</opr> + <cpuid>aesni avx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>aesenclast</mnemonic> + <cpuid>aesni avx</cpuid> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>/sse=66 0f 38 dd</opc> + <opr>V H W</opr> + </def> + </instruction> + + <instruction> + <mnemonic>aesimc</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>/sse=66 0f 38 db</opc> + <opr>V W</opr> + <cpuid>aesni avx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>aeskeygenassist</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>/sse=66 0f 3a df</opc> + <opr>V W Ib</opr> + <cpuid>aesni avx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>and</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>20</opc> + <opr>Eb Gb</opr> + </def> + <def> + <pfx>aso oso rexw rexr rexx rexb</pfx> + <opc>21</opc> + <opr>Ev Gv</opr> + </def> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>22</opc> + <opr>Gb Eb</opr> + </def> + <def> + <pfx>aso oso rexw rexr rexx rexb</pfx> + <opc>23</opc> + <opr>Gv Ev</opr> + </def> + <def> + <opc>24</opc> + <opr>AL Ib</opr> + </def> + <def> + <pfx>oso rexw</pfx> + <opc>25</opc> + <opr>rAX sIz</opr> + </def> + <def> + <pfx>aso rexw rexr rexx rexb</pfx> + <opc>80 /reg=4</opc> + <opr>Eb Ib</opr> + </def> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>82 /reg=4 /m=!64</opc> + <opr>Eb Ib</opr> + <mode>inv64</mode> + </def> + <def> + <pfx>aso oso rexw rexr rexx rexb</pfx> + <opc>81 /reg=4</opc> + <opr>Ev sIz</opr> + </def> + <def> + <pfx>aso oso rexw rexr rexx rexb</pfx> + <opc>83 /reg=4</opc> + <opr>Ev sIb</opr> + </def> + </instruction> + + <instruction> + <mnemonic>andpd</mnemonic> + <def> + <pfx>aso rexr rexx rexb vexl</pfx> + <opc>/sse=66 0f 54</opc> + <opr>V H W</opr> + <cpuid>sse2 avx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>andps</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>0f 54</opc> + <opr>V H W</opr> + <cpuid>sse avx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>andnpd</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>/sse=66 0f 55</opc> + <opr>V H W</opr> + <cpuid>sse2 avx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>andnps</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>0f 55</opc> + <opr>V H W</opr> + <cpuid>sse2 avx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>arpl</mnemonic> + <def> + <pfx>aso</pfx> + <opc>63 /m=!64</opc> + <opr>Ew Gw</opr> + </def> + </instruction> + + <instruction> + <mnemonic>movsxd</mnemonic> + <def> + <pfx>aso oso rexw rexx rexr rexb</pfx> + <opc>63 /m=64</opc> + <opr>Gq Ed</opr> + </def> + </instruction> + + <instruction> + <mnemonic>call</mnemonic> + <def> + <pfx>aso oso rexw rexr rexx rexb</pfx> + <opc>ff /reg=2 /m=!64</opc> + <opr>Ev</opr> + </def> + <def> + <pfx>aso oso rexw rexr rexx rexb</pfx> + <opc>ff /reg=2 /m=64</opc> + <opr>Eq</opr> + <mode>def64</mode> + </def> + <def> + <pfx>aso oso rexw rexr rexx rexb</pfx> + <opc>ff /reg=3</opc> + <opr>Fv</opr> + </def> + <def> + <pfx>oso</pfx> + <opc>e8</opc> + <opr>Jz</opr> + <mode>def64</mode> + </def> + <def> + <pfx>oso</pfx> + <opc>9a /m=!64</opc> + <opr>Av</opr> + </def> + </instruction> + + <instruction> + <mnemonic>cbw</mnemonic> + <def> + <pfx>oso rexw</pfx> + <opc>98 /o=16</opc> + </def> + </instruction> + + <instruction> + <mnemonic>cwde</mnemonic> + <def> + <pfx>oso rexw</pfx> + <opc>98 /o=32</opc> + </def> + </instruction> + + <instruction> + <mnemonic>cdqe</mnemonic> + <def> + <pfx>oso rexw</pfx> + <opc>98 /o=64</opc> + </def> + </instruction> + + <instruction> + <mnemonic>clc</mnemonic> + <def> + <opc>f8</opc> + </def> + </instruction> + + <instruction> + <mnemonic>cld</mnemonic> + <def> + <opc>fc</opc> + </def> + </instruction> + + <instruction> + <mnemonic>clflush</mnemonic> + <def> + <pfx>aso rexw rexr rexx rexb</pfx> + <opc>0f ae /reg=7 /mod=!11</opc> + <opr>M</opr> + </def> + </instruction> + + <instruction> + <mnemonic>clgi</mnemonic> + <vendor>amd</vendor> + <def> + <opc>0f 01 /reg=3 /mod=11 /rm=5</opc> + </def> + </instruction> + + <instruction> + <mnemonic>cli</mnemonic> + <def> + <opc>fa</opc> + </def> + </instruction> + + <instruction> + <mnemonic>clts</mnemonic> + <def> + <opc>0f 06</opc> + </def> + </instruction> + + <instruction> + <mnemonic>cmc</mnemonic> + <def> + <opc>f5</opc> + </def> + </instruction> + + <instruction> + <mnemonic>cmovo</mnemonic> + <def> + <pfx>aso oso rexw rexr rexx rexb</pfx> + <opc>0f 40</opc> + <opr>Gv Ev</opr> + </def> + </instruction> + + <instruction> + <mnemonic>cmovno</mnemonic> + <def> + <pfx>aso oso rexw rexr rexx rexb</pfx> + <opc>0f 41</opc> + <opr>Gv Ev</opr> + </def> + </instruction> + + <instruction> + <mnemonic>cmovb</mnemonic> + <def> + <pfx>aso oso rexw rexr rexx rexb</pfx> + <opc>0f 42</opc> + <opr>Gv Ev</opr> + </def> + </instruction> + + <instruction> + <mnemonic>cmovae</mnemonic> + <def> + <pfx>aso oso rexw rexr rexx rexb</pfx> + <opc>0f 43</opc> + <opr>Gv Ev</opr> + </def> + </instruction> + + <instruction> + <mnemonic>cmovz</mnemonic> + <def> + <pfx>aso oso rexw rexr rexx rexb</pfx> + <opc>0f 44</opc> + <opr>Gv Ev</opr> + </def> + </instruction> + + <instruction> + <mnemonic>cmovnz</mnemonic> + <def> + <pfx>aso oso rexw rexr rexx rexb</pfx> + <opc>0f 45</opc> + <opr>Gv Ev</opr> + </def> + </instruction> + + <instruction> + <mnemonic>cmovbe</mnemonic> + <def> + <pfx>aso oso rexw rexr rexx rexb</pfx> + <opc>0f 46</opc> + <opr>Gv Ev</opr> + </def> + </instruction> + + <instruction> + <mnemonic>cmova</mnemonic> + <def> + <pfx>aso oso rexw rexr rexx rexb</pfx> + <opc>0f 47</opc> + <opr>Gv Ev</opr> + </def> + </instruction> + + <instruction> + <mnemonic>cmovs</mnemonic> + <def> + <pfx>aso oso rexw rexr rexx rexb</pfx> + <opc>0f 48</opc> + <opr>Gv Ev</opr> + </def> + </instruction> + + <instruction> + <mnemonic>cmovns</mnemonic> + <def> + <pfx>aso oso rexw rexr rexx rexb</pfx> + <opc>0f 49</opc> + <opr>Gv Ev</opr> + </def> + </instruction> + + <instruction> + <mnemonic>cmovp</mnemonic> + <def> + <pfx>aso oso rexw rexr rexx rexb</pfx> + <opc>0f 4a</opc> + <opr>Gv Ev</opr> + </def> + </instruction> + + <instruction> + <mnemonic>cmovnp</mnemonic> + <def> + <pfx>aso oso rexw rexr rexx rexb</pfx> + <opc>0f 4b</opc> + <opr>Gv Ev</opr> + </def> + </instruction> + + <instruction> + <mnemonic>cmovl</mnemonic> + <def> + <pfx>aso oso rexw rexr rexx rexb</pfx> + <opc>0f 4c</opc> + <opr>Gv Ev</opr> + </def> + </instruction> + + <instruction> + <mnemonic>cmovge</mnemonic> + <def> + <pfx>aso oso rexw rexr rexx rexb</pfx> + <opc>0f 4d</opc> + <opr>Gv Ev</opr> + </def> + </instruction> + + <instruction> + <mnemonic>cmovle</mnemonic> + <def> + <pfx>aso oso rexw rexr rexx rexb</pfx> + <opc>0f 4e</opc> + <opr>Gv Ev</opr> + </def> + </instruction> + + <instruction> + <mnemonic>cmovg</mnemonic> + <def> + <pfx>aso oso rexw rexr rexx rexb</pfx> + <opc>0f 4f</opc> + <opr>Gv Ev</opr> + </def> + </instruction> + + <instruction> + <mnemonic>cmp</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>38</opc> + <opr>Eb Gb</opr> + </def> + <def> + <pfx>aso oso rexw rexr rexx rexb</pfx> + <opc>39</opc> + <opr>Ev Gv</opr> + </def> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>3a</opc> + <opr>Gb Eb</opr> + </def> + <def> + <pfx>aso oso rexw rexr rexx rexb</pfx> + <opc>3b</opc> + <opr>Gv Ev</opr> + </def> + <def> + <opc>3c</opc> + <opr>AL Ib</opr> + </def> + <def> + <pfx>oso rexw</pfx> + <opc>3d</opc> + <opr>rAX sIz</opr> + </def> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>80 /reg=7</opc> + <opr>Eb Ib</opr> + </def> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>82 /reg=7 /m=!64</opc> + <opr>Eb Ib</opr> + <mode>inv64</mode> + </def> + <def> + <pfx>aso oso rexw rexr rexx rexb</pfx> + <opc>81 /reg=7</opc> + <opr>Ev sIz</opr> + </def> + <def> + <pfx>aso oso rexw rexr rexx rexb</pfx> + <opc>83 /reg=7</opc> + <opr>Ev sIb</opr> + </def> + </instruction> + + <instruction> + <mnemonic>cmppd</mnemonic> + <def> + <pfx>aso rexr rexx rexb vexl</pfx> + <opc>/sse=66 0f c2</opc> + <opr>V H W Ib</opr> + <cpuid>sse2 avx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>cmpps</mnemonic> + <def> + <pfx>aso rexr rexx rexb vexl</pfx> + <opc>0f c2</opc> + <opr>V H W Ib</opr> + <cpuid>sse2 avx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>cmpsb</mnemonic> + <def> + <pfx>repz seg</pfx> + <opc>a6</opc> + </def> + </instruction> + + <instruction> + <mnemonic>cmpsw</mnemonic> + <def> + <pfx>repz oso rexw seg</pfx> + <opc>a7 /o=16</opc> + </def> + </instruction> + + <instruction> + <mnemonic>cmpsd</mnemonic> + <def> + <pfx>repz oso rexw seg</pfx> + <opc>a7 /o=32</opc> + </def> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>/sse=f2 0f c2</opc> + <opr>V H W Ib</opr> + <cpuid>sse2 avx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>cmpsq</mnemonic> + <def> + <pfx>repz oso rexw seg</pfx> + <opc>a7 /o=64</opc> + </def> + </instruction> + + <instruction> + <mnemonic>cmpss</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>/sse=f3 0f c2</opc> + <opr>V H W Ib</opr> + <cpuid>sse2 avx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>cmpxchg</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>0f b0</opc> + <opr>Eb Gb</opr> + </def> + <def> + <pfx>aso oso rexw rexr rexx rexb</pfx> + <opc>0f b1</opc> + <opr>Ev Gv</opr> + </def> + </instruction> + + <instruction> + <mnemonic>cmpxchg8b</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>0f c7 /mod=!11 /reg=1 /o=16</opc> + <opr>M</opr> + </def> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>0f c7 /mod=!11 /reg=1 /o=32</opc> + <opr>M</opr> + </def> + </instruction> + + <instruction> + <mnemonic>cmpxchg16b</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>0f c7 /mod=!11 /reg=1 /o=64</opc> + <opr>M</opr> + </def> + </instruction> + + <instruction> + <mnemonic>comisd</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>/sse=66 0f 2f</opc> + <opr>Vsd Wsd</opr> + <cpuid>sse2 avx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>comiss</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>0f 2f</opc> + <opr>V W</opr> + <cpuid>sse2 avx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>cpuid</mnemonic> + <def> + <opc>0f a2</opc> + </def> + </instruction> + + <instruction> + <mnemonic>cvtdq2pd</mnemonic> + <def> + <pfx>aso rexr rexx rexb vexl</pfx> + <opc>/sse=f3 0f e6</opc> + <opr>V Wdq</opr> + <cpuid>sse2 avx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>cvtdq2ps</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>0f 5b</opc> + <opr>V W</opr> + <cpuid>sse2 avx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>cvtpd2dq</mnemonic> + <def> + <pfx>aso rexr rexx rexb vexl</pfx> + <opc>/sse=f2 0f e6</opc> + <opr>Vdq W</opr> + <cpuid>sse2 avx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>cvtpd2pi</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>/sse=66 0f 2d</opc> + <opr>P W</opr> + </def> + </instruction> + + <instruction> + <mnemonic>cvtpd2ps</mnemonic> + <def> + <pfx>aso rexr rexx rexb vexl</pfx> + <opc>/sse=66 0f 5a</opc> + <opr>Vdq W</opr> + <cpuid>sse2 avx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>cvtpi2ps</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>0f 2a</opc> + <opr>V Q</opr> + </def> + </instruction> + + <instruction> + <mnemonic>cvtpi2pd</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>/sse=66 0f 2a</opc> + <opr>V Q</opr> + </def> + </instruction> + + <instruction> + <mnemonic>cvtps2dq</mnemonic> + <def> + <pfx>aso rexr rexx rexb vexl</pfx> + <opc>/sse=66 0f 5b</opc> + <opr>V W</opr> + <cpuid>sse2 avx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>cvtps2pd</mnemonic> + <def> + <pfx>aso rexr rexx rexb vexl</pfx> + <opc>0f 5a</opc> + <opr>V Wdq</opr> + <cpuid>sse2 avx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>cvtps2pi</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>0f 2d</opc> + <opr>P MqU</opr> + </def> + </instruction> + + <instruction> + <mnemonic>cvtsd2si</mnemonic> + <def> + <pfx>aso rexw rexr rexx rexb</pfx> + <opc>/sse=f2 0f 2d</opc> + <opr>Gy MqU</opr> + <cpuid>sse2 avx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>cvtsd2ss</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>/sse=f2 0f 5a</opc> + <opr>V H W</opr> + <cpuid>sse2 avx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>cvtsi2sd</mnemonic> + <def> + <pfx>aso rexw rexr rexx rexb</pfx> + <opc>/sse=f2 0f 2a</opc> + <opr>V H Ey</opr> + <cpuid>sse2 avx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>cvtsi2ss</mnemonic> + <def> + <pfx>aso rexw rexr rexx rexb</pfx> + <opc>/sse=f3 0f 2a</opc> + <opr>V H Ey</opr> + <cpuid>sse avx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>cvtss2sd</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>/sse=f3 0f 5a</opc> + <opr>V H W</opr> + <cpuid>sse2 avx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>cvtss2si</mnemonic> + <def> + <pfx>aso rexw rexr rexx rexb</pfx> + <opc>/sse=f3 0f 2d</opc> + <opr>Gy MdU</opr> + <cpuid>sse avx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>cvttpd2dq</mnemonic> + <def> + <pfx>aso rexr rexx rexb vexl</pfx> + <opc>/sse=66 0f e6</opc> + <opr>Vdq W</opr> + <cpuid>sse2 avx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>cvttpd2pi</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>/sse=66 0f 2c</opc> + <opr>P W</opr> + </def> + </instruction> + + <instruction> + <mnemonic>cvttps2dq</mnemonic> + <def> + <pfx>aso rexr rexx rexb vexl</pfx> + <opc>/sse=f3 0f 5b</opc> + <opr>V W</opr> + <cpuid>sse2 avx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>cvttps2pi</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>0f 2c</opc> + <opr>P W</opr> + </def> + </instruction> + + <instruction> + <mnemonic>cvttsd2si</mnemonic> + <def> + <pfx>aso rexw rexr rexx rexb</pfx> + <opc>/sse=f2 0f 2c</opc> + <opr>Gy MqU</opr> + <cpuid>sse2 avx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>cvttss2si</mnemonic> + <def> + <pfx>aso rexw rexr rexx rexb</pfx> + <opc>/sse=f3 0f 2c</opc> + <opr>Gy MdU</opr> + <cpuid>sse2 avx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>cwd</mnemonic> + <def> + <pfx>oso rexw</pfx> + <opc>99 /o=16</opc> + </def> + </instruction> + + <instruction> + <mnemonic>cdq</mnemonic> + <def> + <pfx>oso rexw</pfx> + <opc>99 /o=32</opc> + </def> + </instruction> + + <instruction> + <mnemonic>cqo</mnemonic> + <def> + <pfx>oso rexw</pfx> + <opc>99 /o=64</opc> + </def> + </instruction> + + <instruction> + <mnemonic>daa</mnemonic> + <def> + <opc>27 /m=!64</opc> + <mode>inv64</mode> + </def> + </instruction> + + <instruction> + <mnemonic>das</mnemonic> + <def> + <opc>2f /m=!64</opc> + <mode>inv64</mode> + </def> + </instruction> + + <instruction> + <mnemonic>dec</mnemonic> + <def> + <pfx>oso</pfx> + <opc>48</opc> + <opr>R0z</opr> + </def> + <def> + <pfx>oso</pfx> + <opc>49</opc> + <opr>R1z</opr> + </def> + <def> + <pfx>oso</pfx> + <opc>4a</opc> + <opr>R2z</opr> + </def> + <def> + <pfx>oso</pfx> + <opc>4b</opc> + <opr>R3z</opr> + </def> + <def> + <pfx>oso</pfx> + <opc>4c</opc> + <opr>R4z</opr> + </def> + <def> + <pfx>oso</pfx> + <opc>4d</opc> + <opr>R5z</opr> + </def> + <def> + <pfx>oso</pfx> + <opc>4e</opc> + <opr>R6z</opr> + </def> + <def> + <pfx>oso</pfx> + <opc>4f</opc> + <opr>R7z</opr> + </def> + <def> + <pfx>aso rexw rexr rexx rexb</pfx> + <opc>fe /reg=1</opc> + <opr>Eb</opr> + </def> + <def> + <pfx>aso oso rexw rexr rexx rexb</pfx> + <opc>ff /reg=1</opc> + <opr>Ev</opr> + </def> + </instruction> + + <instruction> + <mnemonic>div</mnemonic> + <def> + <pfx>aso oso rexw rexr rexx rexb</pfx> + <opc>f7 /reg=6</opc> + <opr>Ev</opr> + </def> + <def> + <pfx>aso rexw rexr rexx rexb</pfx> + <opc>f6 /reg=6</opc> + <opr>Eb</opr> + </def> + </instruction> + + <instruction> + <mnemonic>divpd</mnemonic> + <def> + <pfx>aso rexr rexx rexb vexl</pfx> + <opc>/sse=66 0f 5e</opc> + <opr>V H W</opr> + <cpuid>sse2 avx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>divps</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>0f 5e</opc> + <opr>V H W</opr> + <cpuid>sse avx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>divsd</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>/sse=f2 0f 5e</opc> + <opr>V H MqU</opr> + <cpuid>sse2 avx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>divss</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>/sse=f3 0f 5e</opc> + <opr>V H MdU</opr> + <cpuid>sse avx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>dppd</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>/sse=66 0f 3a 41</opc> + <opr>V H W Ib</opr> + <cpuid>sse4.1 avx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>dpps</mnemonic> + <def> + <pfx>aso rexr rexx rexb vexl</pfx> + <opc>/sse=66 0f 3a 40</opc> + <opr>V H W Ib</opr> + <cpuid>sse4.1 avx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>emms</mnemonic> + <def> + <opc>0f 77</opc> + </def> + </instruction> + + <instruction> + <mnemonic>enter</mnemonic> + <def> + <opc>c8</opc> + <opr>Iw Ib</opr> + <mode>def64</mode> + </def> + </instruction> + + <instruction> + <mnemonic>extractps</mnemonic> + <def> + <pfx>aso rexr rexw rexx rexb</pfx> + <opc>/sse=66 0f 3a 17</opc> + <opr>MdRy V Ib</opr> + <cpuid>sse4.1 avx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>f2xm1</mnemonic> + <cpuid>X87</cpuid> + <def> + <opc>d9 /mod=11 /x87=30</opc> + </def> + </instruction> + + <instruction> + <mnemonic>fabs</mnemonic> + <cpuid>X87</cpuid> + <def> + <opc>d9 /mod=11 /x87=21</opc> + </def> + </instruction> + + <instruction> + <mnemonic>fadd</mnemonic> + <cpuid>X87</cpuid> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>dc /mod=!11 /reg=0</opc> + <opr>Mq</opr> + </def> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>d8 /mod=!11 /reg=0</opc> + <opr>Md</opr> + </def> + <def> + <opc>dc /mod=11 /x87=00</opc> + <opr>ST0 ST0</opr> + </def> + <def> + <opc>dc /mod=11 /x87=01</opc> + <opr>ST1 ST0</opr> + </def> + <def> + <opc>dc /mod=11 /x87=02</opc> + <opr>ST2 ST0</opr> + </def> + <def> + <opc>dc /mod=11 /x87=03</opc> + <opr>ST3 ST0</opr> + </def> + <def> + <opc>dc /mod=11 /x87=04</opc> + <opr>ST4 ST0</opr> + </def> + <def> + <opc>dc /mod=11 /x87=05</opc> + <opr>ST5 ST0</opr> + </def> + <def> + <opc>dc /mod=11 /x87=06</opc> + <opr>ST6 ST0</opr> + </def> + <def> + <opc>dc /mod=11 /x87=07</opc> + <opr>ST7 ST0</opr> + </def> + <def> + <opc>d8 /mod=11 /x87=00</opc> + <opr>ST0 ST0</opr> + </def> + <def> + <opc>d8 /mod=11 /x87=01</opc> + <opr>ST0 ST1</opr> + </def> + <def> + <opc>d8 /mod=11 /x87=02</opc> + <opr>ST0 ST2</opr> + </def> + <def> + <opc>d8 /mod=11 /x87=03</opc> + <opr>ST0 ST3</opr> + </def> + <def> + <opc>d8 /mod=11 /x87=04</opc> + <opr>ST0 ST4</opr> + </def> + <def> + <opc>d8 /mod=11 /x87=05</opc> + <opr>ST0 ST5</opr> + </def> + <def> + <opc>d8 /mod=11 /x87=06</opc> + <opr>ST0 ST6</opr> + </def> + <def> + <opc>d8 /mod=11 /x87=07</opc> + <opr>ST0 ST7</opr> + </def> + </instruction> + + <instruction> + <mnemonic>faddp</mnemonic> + <cpuid>X87</cpuid> + <def> + <opc>de /mod=11 /x87=00</opc> + <opr>ST0 ST0</opr> + </def> + <def> + <opc>de /mod=11 /x87=01</opc> + <opr>ST1 ST0</opr> + </def> + <def> + <opc>de /mod=11 /x87=02</opc> + <opr>ST2 ST0</opr> + </def> + <def> + <opc>de /mod=11 /x87=03</opc> + <opr>ST3 ST0</opr> + </def> + <def> + <opc>de /mod=11 /x87=04</opc> + <opr>ST4 ST0</opr> + </def> + <def> + <opc>de /mod=11 /x87=05</opc> + <opr>ST5 ST0</opr> + </def> + <def> + <opc>de /mod=11 /x87=06</opc> + <opr>ST6 ST0</opr> + </def> + <def> + <opc>de /mod=11 /x87=07</opc> + <opr>ST7 ST0</opr> + </def> + </instruction> + + <instruction> + <mnemonic>fbld</mnemonic> + <cpuid>X87</cpuid> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>df /mod=!11 /reg=4</opc> + <opr>Mt</opr> + </def> + </instruction> + + <instruction> + <mnemonic>fbstp</mnemonic> + <cpuid>X87</cpuid> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>df /mod=!11 /reg=6</opc> + <opr>Mt</opr> + </def> + </instruction> + + <instruction> + <mnemonic>fchs</mnemonic> + <cpuid>X87</cpuid> + <def> + <opc>d9 /mod=11 /x87=20</opc> + </def> + </instruction> + + <instruction> + <mnemonic>fclex</mnemonic> + <cpuid>X87</cpuid> + <def> + <opc>db /mod=11 /x87=22</opc> + </def> + </instruction> + + <instruction> + <mnemonic>fcmovb</mnemonic> + <cpuid>X87</cpuid> + <def> + <opc>da /mod=11 /x87=00</opc> + <opr>ST0 ST0</opr> + </def> + <def> + <opc>da /mod=11 /x87=01</opc> + <opr>ST0 ST1</opr> + </def> + <def> + <opc>da /mod=11 /x87=02</opc> + <opr>ST0 ST2</opr> + </def> + <def> + <opc>da /mod=11 /x87=03</opc> + <opr>ST0 ST3</opr> + </def> + <def> + <opc>da /mod=11 /x87=04</opc> + <opr>ST0 ST4</opr> + </def> + <def> + <opc>da /mod=11 /x87=05</opc> + <opr>ST0 ST5</opr> + </def> + <def> + <opc>da /mod=11 /x87=06</opc> + <opr>ST0 ST6</opr> + </def> + <def> + <opc>da /mod=11 /x87=07</opc> + <opr>ST0 ST7</opr> + </def> + </instruction> + + <instruction> + <mnemonic>fcmove</mnemonic> + <cpuid>X87</cpuid> + <def> + <opc>da /mod=11 /x87=08</opc> + <opr>ST0 ST0</opr> + </def> + <def> + <opc>da /mod=11 /x87=09</opc> + <opr>ST0 ST1</opr> + </def> + <def> + <opc>da /mod=11 /x87=0a</opc> + <opr>ST0 ST2</opr> + </def> + <def> + <opc>da /mod=11 /x87=0b</opc> + <opr>ST0 ST3</opr> + </def> + <def> + <opc>da /mod=11 /x87=0c</opc> + <opr>ST0 ST4</opr> + </def> + <def> + <opc>da /mod=11 /x87=0d</opc> + <opr>ST0 ST5</opr> + </def> + <def> + <opc>da /mod=11 /x87=0e</opc> + <opr>ST0 ST6</opr> + </def> + <def> + <opc>da /mod=11 /x87=0f</opc> + <opr>ST0 ST7</opr> + </def> + </instruction> + + <instruction> + <mnemonic>fcmovbe</mnemonic> + <cpuid>X87</cpuid> + <def> + <opc>da /mod=11 /x87=10</opc> + <opr>ST0 ST0</opr> + </def> + <def> + <opc>da /mod=11 /x87=11</opc> + <opr>ST0 ST1</opr> + </def> + <def> + <opc>da /mod=11 /x87=12</opc> + <opr>ST0 ST2</opr> + </def> + <def> + <opc>da /mod=11 /x87=13</opc> + <opr>ST0 ST3</opr> + </def> + <def> + <opc>da /mod=11 /x87=14</opc> + <opr>ST0 ST4</opr> + </def> + <def> + <opc>da /mod=11 /x87=15</opc> + <opr>ST0 ST5</opr> + </def> + <def> + <opc>da /mod=11 /x87=16</opc> + <opr>ST0 ST6</opr> + </def> + <def> + <opc>da /mod=11 /x87=17</opc> + <opr>ST0 ST7</opr> + </def> + </instruction> + + <instruction> + <mnemonic>fcmovu</mnemonic> + <cpuid>X87</cpuid> + <def> + <opc>da /mod=11 /x87=18</opc> + <opr>ST0 ST0</opr> + </def> + <def> + <opc>da /mod=11 /x87=19</opc> + <opr>ST0 ST1</opr> + </def> + <def> + <opc>da /mod=11 /x87=1a</opc> + <opr>ST0 ST2</opr> + </def> + <def> + <opc>da /mod=11 /x87=1b</opc> + <opr>ST0 ST3</opr> + </def> + <def> + <opc>da /mod=11 /x87=1c</opc> + <opr>ST0 ST4</opr> + </def> + <def> + <opc>da /mod=11 /x87=1d</opc> + <opr>ST0 ST5</opr> + </def> + <def> + <opc>da /mod=11 /x87=1e</opc> + <opr>ST0 ST6</opr> + </def> + <def> + <opc>da /mod=11 /x87=1f</opc> + <opr>ST0 ST7</opr> + </def> + </instruction> + + <instruction> + <mnemonic>fcmovnb</mnemonic> + <cpuid>X87</cpuid> + <def> + <opc>db /mod=11 /x87=00</opc> + <opr>ST0 ST0</opr> + </def> + <def> + <opc>db /mod=11 /x87=01</opc> + <opr>ST0 ST1</opr> + </def> + <def> + <opc>db /mod=11 /x87=02</opc> + <opr>ST0 ST2</opr> + </def> + <def> + <opc>db /mod=11 /x87=03</opc> + <opr>ST0 ST3</opr> + </def> + <def> + <opc>db /mod=11 /x87=04</opc> + <opr>ST0 ST4</opr> + </def> + <def> + <opc>db /mod=11 /x87=05</opc> + <opr>ST0 ST5</opr> + </def> + <def> + <opc>db /mod=11 /x87=06</opc> + <opr>ST0 ST6</opr> + </def> + <def> + <opc>db /mod=11 /x87=07</opc> + <opr>ST0 ST7</opr> + </def> + </instruction> + + <instruction> + <mnemonic>fcmovne</mnemonic> + <cpuid>X87</cpuid> + <def> + <opc>db /mod=11 /x87=08</opc> + <opr>ST0 ST0</opr> + </def> + <def> + <opc>db /mod=11 /x87=09</opc> + <opr>ST0 ST1</opr> + </def> + <def> + <opc>db /mod=11 /x87=0a</opc> + <opr>ST0 ST2</opr> + </def> + <def> + <opc>db /mod=11 /x87=0b</opc> + <opr>ST0 ST3</opr> + </def> + <def> + <opc>db /mod=11 /x87=0c</opc> + <opr>ST0 ST4</opr> + </def> + <def> + <opc>db /mod=11 /x87=0d</opc> + <opr>ST0 ST5</opr> + </def> + <def> + <opc>db /mod=11 /x87=0e</opc> + <opr>ST0 ST6</opr> + </def> + <def> + <opc>db /mod=11 /x87=0f</opc> + <opr>ST0 ST7</opr> + </def> + </instruction> + + <instruction> + <mnemonic>fcmovnbe</mnemonic> + <cpuid>X87</cpuid> + <def> + <opc>db /mod=11 /x87=10</opc> + <opr>ST0 ST0</opr> + </def> + <def> + <opc>db /mod=11 /x87=11</opc> + <opr>ST0 ST1</opr> + </def> + <def> + <opc>db /mod=11 /x87=12</opc> + <opr>ST0 ST2</opr> + </def> + <def> + <opc>db /mod=11 /x87=13</opc> + <opr>ST0 ST3</opr> + </def> + <def> + <opc>db /mod=11 /x87=14</opc> + <opr>ST0 ST4</opr> + </def> + <def> + <opc>db /mod=11 /x87=15</opc> + <opr>ST0 ST5</opr> + </def> + <def> + <opc>db /mod=11 /x87=16</opc> + <opr>ST0 ST6</opr> + </def> + <def> + <opc>db /mod=11 /x87=17</opc> + <opr>ST0 ST7</opr> + </def> + </instruction> + + <instruction> + <mnemonic>fcmovnu</mnemonic> + <cpuid>X87</cpuid> + <def> + <opc>db /mod=11 /x87=18</opc> + <opr>ST0 ST0</opr> + </def> + <def> + <opc>db /mod=11 /x87=19</opc> + <opr>ST0 ST1</opr> + </def> + <def> + <opc>db /mod=11 /x87=1a</opc> + <opr>ST0 ST2</opr> + </def> + <def> + <opc>db /mod=11 /x87=1b</opc> + <opr>ST0 ST3</opr> + </def> + <def> + <opc>db /mod=11 /x87=1c</opc> + <opr>ST0 ST4</opr> + </def> + <def> + <opc>db /mod=11 /x87=1d</opc> + <opr>ST0 ST5</opr> + </def> + <def> + <opc>db /mod=11 /x87=1e</opc> + <opr>ST0 ST6</opr> + </def> + <def> + <opc>db /mod=11 /x87=1f</opc> + <opr>ST0 ST7</opr> + </def> + </instruction> + + <instruction> + <mnemonic>fucomi</mnemonic> + <cpuid>X87</cpuid> + <def> + <opc>db /mod=11 /x87=28</opc> + <opr>ST0 ST0</opr> + </def> + <def> + <opc>db /mod=11 /x87=29</opc> + <opr>ST0 ST1</opr> + </def> + <def> + <opc>db /mod=11 /x87=2a</opc> + <opr>ST0 ST2</opr> + </def> + <def> + <opc>db /mod=11 /x87=2b</opc> + <opr>ST0 ST3</opr> + </def> + <def> + <opc>db /mod=11 /x87=2c</opc> + <opr>ST0 ST4</opr> + </def> + <def> + <opc>db /mod=11 /x87=2d</opc> + <opr>ST0 ST5</opr> + </def> + <def> + <opc>db /mod=11 /x87=2e</opc> + <opr>ST0 ST6</opr> + </def> + <def> + <opc>db /mod=11 /x87=2f</opc> + <opr>ST0 ST7</opr> + </def> + </instruction> + + <instruction> + <mnemonic>fcom</mnemonic> + <cpuid>X87</cpuid> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>d8 /mod=!11 /reg=2</opc> + <opr>Md</opr> + </def> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>dc /mod=!11 /reg=2</opc> + <opr>Mq</opr> + </def> + <def> + <opc>d8 /mod=11 /x87=10</opc> + <opr>ST0 ST0</opr> + </def> + <def> + <opc>d8 /mod=11 /x87=11</opc> + <opr>ST0 ST1</opr> + </def> + <def> + <opc>d8 /mod=11 /x87=12</opc> + <opr>ST0 ST2</opr> + </def> + <def> + <opc>d8 /mod=11 /x87=13</opc> + <opr>ST0 ST3</opr> + </def> + <def> + <opc>d8 /mod=11 /x87=14</opc> + <opr>ST0 ST4</opr> + </def> + <def> + <opc>d8 /mod=11 /x87=15</opc> + <opr>ST0 ST5</opr> + </def> + <def> + <opc>d8 /mod=11 /x87=16</opc> + <opr>ST0 ST6</opr> + </def> + <def> + <opc>d8 /mod=11 /x87=17</opc> + <opr>ST0 ST7</opr> + </def> + </instruction> + + <instruction> + <mnemonic>fcom2</mnemonic> + <cpuid>X87 UNDOC</cpuid> + <def> + <opc>dc /mod=11 /x87=10</opc> + <opr>ST0</opr> + </def> + <def> + <opc>dc /mod=11 /x87=11</opc> + <opr>ST1</opr> + </def> + <def> + <opc>dc /mod=11 /x87=12</opc> + <opr>ST2</opr> + </def> + <def> + <opc>dc /mod=11 /x87=13</opc> + <opr>ST3</opr> + </def> + <def> + <opc>dc /mod=11 /x87=14</opc> + <opr>ST4</opr> + </def> + <def> + <opc>dc /mod=11 /x87=15</opc> + <opr>ST5</opr> + </def> + <def> + <opc>dc /mod=11 /x87=16</opc> + <opr>ST6</opr> + </def> + <def> + <opc>dc /mod=11 /x87=17</opc> + <opr>ST7</opr> + </def> + </instruction> + + <instruction> + <mnemonic>fcomp3</mnemonic> + <cpuid>X87 UNDOC</cpuid> + <def> + <opc>dc /mod=11 /x87=18</opc> + <opr>ST0</opr> + </def> + <def> + <opc>dc /mod=11 /x87=19</opc> + <opr>ST1</opr> + </def> + <def> + <opc>dc /mod=11 /x87=1a</opc> + <opr>ST2</opr> + </def> + <def> + <opc>dc /mod=11 /x87=1b</opc> + <opr>ST3</opr> + </def> + <def> + <opc>dc /mod=11 /x87=1c</opc> + <opr>ST4</opr> + </def> + <def> + <opc>dc /mod=11 /x87=1d</opc> + <opr>ST5</opr> + </def> + <def> + <opc>dc /mod=11 /x87=1e</opc> + <opr>ST6</opr> + </def> + <def> + <opc>dc /mod=11 /x87=1f</opc> + <opr>ST7</opr> + </def> + </instruction> + + <instruction> + <mnemonic>fcomi</mnemonic> + <cpuid>X87</cpuid> + <def> + <opc>db /mod=11 /x87=30</opc> + <opr>ST0 ST0</opr> + </def> + <def> + <opc>db /mod=11 /x87=31</opc> + <opr>ST0 ST1</opr> + </def> + <def> + <opc>db /mod=11 /x87=32</opc> + <opr>ST0 ST2</opr> + </def> + <def> + <opc>db /mod=11 /x87=33</opc> + <opr>ST0 ST3</opr> + </def> + <def> + <opc>db /mod=11 /x87=34</opc> + <opr>ST0 ST4</opr> + </def> + <def> + <opc>db /mod=11 /x87=35</opc> + <opr>ST0 ST5</opr> + </def> + <def> + <opc>db /mod=11 /x87=36</opc> + <opr>ST0 ST6</opr> + </def> + <def> + <opc>db /mod=11 /x87=37</opc> + <opr>ST0 ST7</opr> + </def> + </instruction> + + <instruction> + <mnemonic>fucomip</mnemonic> + <cpuid>X87</cpuid> + <def> + <opc>df /mod=11 /x87=28</opc> + <opr>ST0 ST0</opr> + </def> + <def> + <opc>df /mod=11 /x87=29</opc> + <opr>ST0 ST1</opr> + </def> + <def> + <opc>df /mod=11 /x87=2a</opc> + <opr>ST0 ST2</opr> + </def> + <def> + <opc>df /mod=11 /x87=2b</opc> + <opr>ST0 ST3</opr> + </def> + <def> + <opc>df /mod=11 /x87=2c</opc> + <opr>ST0 ST4</opr> + </def> + <def> + <opc>df /mod=11 /x87=2d</opc> + <opr>ST0 ST5</opr> + </def> + <def> + <opc>df /mod=11 /x87=2e</opc> + <opr>ST0 ST6</opr> + </def> + <def> + <opc>df /mod=11 /x87=2f</opc> + <opr>ST0 ST7</opr> + </def> + </instruction> + + <instruction> + <mnemonic>fcomip</mnemonic> + <cpuid>X87</cpuid> + <def> + <opc>df /mod=11 /x87=30</opc> + <opr>ST0 ST0</opr> + </def> + <def> + <opc>df /mod=11 /x87=31</opc> + <opr>ST0 ST1</opr> + </def> + <def> + <opc>df /mod=11 /x87=32</opc> + <opr>ST0 ST2</opr> + </def> + <def> + <opc>df /mod=11 /x87=33</opc> + <opr>ST0 ST3</opr> + </def> + <def> + <opc>df /mod=11 /x87=34</opc> + <opr>ST0 ST4</opr> + </def> + <def> + <opc>df /mod=11 /x87=35</opc> + <opr>ST0 ST5</opr> + </def> + <def> + <opc>df /mod=11 /x87=36</opc> + <opr>ST0 ST6</opr> + </def> + <def> + <opc>df /mod=11 /x87=37</opc> + <opr>ST0 ST7</opr> + </def> + </instruction> + + <instruction> + <mnemonic>fcomp</mnemonic> + <cpuid>X87</cpuid> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>d8 /mod=!11 /reg=3</opc> + <opr>Md</opr> + </def> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>dc /mod=!11 /reg=3</opc> + <opr>Mq</opr> + </def> + <def> + <opc>d8 /mod=11 /x87=18</opc> + <opr>ST0 ST0</opr> + </def> + <def> + <opc>d8 /mod=11 /x87=19</opc> + <opr>ST0 ST1</opr> + </def> + <def> + <opc>d8 /mod=11 /x87=1a</opc> + <opr>ST0 ST2</opr> + </def> + <def> + <opc>d8 /mod=11 /x87=1b</opc> + <opr>ST0 ST3</opr> + </def> + <def> + <opc>d8 /mod=11 /x87=1c</opc> + <opr>ST0 ST4</opr> + </def> + <def> + <opc>d8 /mod=11 /x87=1d</opc> + <opr>ST0 ST5</opr> + </def> + <def> + <opc>d8 /mod=11 /x87=1e</opc> + <opr>ST0 ST6</opr> + </def> + <def> + <opc>d8 /mod=11 /x87=1f</opc> + <opr>ST0 ST7</opr> + </def> + </instruction> + + <instruction> + <mnemonic>fcomp5</mnemonic> + <cpuid>X87 UNDOC</cpuid> + <def> + <opc>de /mod=11 /x87=10</opc> + <opr>ST0</opr> + </def> + <def> + <opc>de /mod=11 /x87=11</opc> + <opr>ST1</opr> + </def> + <def> + <opc>de /mod=11 /x87=12</opc> + <opr>ST2</opr> + </def> + <def> + <opc>de /mod=11 /x87=13</opc> + <opr>ST3</opr> + </def> + <def> + <opc>de /mod=11 /x87=14</opc> + <opr>ST4</opr> + </def> + <def> + <opc>de /mod=11 /x87=15</opc> + <opr>ST5</opr> + </def> + <def> + <opc>de /mod=11 /x87=16</opc> + <opr>ST6</opr> + </def> + <def> + <opc>de /mod=11 /x87=17</opc> + <opr>ST7</opr> + </def> + </instruction> + + <instruction> + <mnemonic>fcompp</mnemonic> + <cpuid>X87</cpuid> + <def> + <opc>de /mod=11 /x87=19</opc> + </def> + </instruction> + + <instruction> + <mnemonic>fcos</mnemonic> + <cpuid>X87</cpuid> + <def> + <opc>d9 /mod=11 /x87=3f</opc> + </def> + </instruction> + + <instruction> + <mnemonic>fdecstp</mnemonic> + <cpuid>X87</cpuid> + <def> + <opc>d9 /mod=11 /x87=36</opc> + </def> + </instruction> + + <instruction> + <mnemonic>fdiv</mnemonic> + <cpuid>X87</cpuid> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>dc /mod=!11 /reg=6</opc> + <opr>Mq</opr> + </def> + <def> + <opc>dc /mod=11 /x87=38</opc> + <opr>ST0 ST0</opr> + </def> + <def> + <opc>dc /mod=11 /x87=39</opc> + <opr>ST1 ST0</opr> + </def> + <def> + <opc>dc /mod=11 /x87=3a</opc> + <opr>ST2 ST0</opr> + </def> + <def> + <opc>dc /mod=11 /x87=3b</opc> + <opr>ST3 ST0</opr> + </def> + <def> + <opc>dc /mod=11 /x87=3c</opc> + <opr>ST4 ST0</opr> + </def> + <def> + <opc>dc /mod=11 /x87=3d</opc> + <opr>ST5 ST0</opr> + </def> + <def> + <opc>dc /mod=11 /x87=3e</opc> + <opr>ST6 ST0</opr> + </def> + <def> + <opc>dc /mod=11 /x87=3f</opc> + <opr>ST7 ST0</opr> + </def> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>d8 /mod=!11 /reg=6</opc> + <opr>Md</opr> + </def> + <def> + <opc>d8 /mod=11 /x87=30</opc> + <opr>ST0 ST0</opr> + </def> + <def> + <opc>d8 /mod=11 /x87=31</opc> + <opr>ST0 ST1</opr> + </def> + <def> + <opc>d8 /mod=11 /x87=32</opc> + <opr>ST0 ST2</opr> + </def> + <def> + <opc>d8 /mod=11 /x87=33</opc> + <opr>ST0 ST3</opr> + </def> + <def> + <opc>d8 /mod=11 /x87=34</opc> + <opr>ST0 ST4</opr> + </def> + <def> + <opc>d8 /mod=11 /x87=35</opc> + <opr>ST0 ST5</opr> + </def> + <def> + <opc>d8 /mod=11 /x87=36</opc> + <opr>ST0 ST6</opr> + </def> + <def> + <opc>d8 /mod=11 /x87=37</opc> + <opr>ST0 ST7</opr> + </def> + </instruction> + + <instruction> + <mnemonic>fdivp</mnemonic> + <cpuid>X87</cpuid> + <def> + <opc>de /mod=11 /x87=38</opc> + <opr>ST0 ST0</opr> + </def> + <def> + <opc>de /mod=11 /x87=39</opc> + <opr>ST1 ST0</opr> + </def> + <def> + <opc>de /mod=11 /x87=3a</opc> + <opr>ST2 ST0</opr> + </def> + <def> + <opc>de /mod=11 /x87=3b</opc> + <opr>ST3 ST0</opr> + </def> + <def> + <opc>de /mod=11 /x87=3c</opc> + <opr>ST4 ST0</opr> + </def> + <def> + <opc>de /mod=11 /x87=3d</opc> + <opr>ST5 ST0</opr> + </def> + <def> + <opc>de /mod=11 /x87=3e</opc> + <opr>ST6 ST0</opr> + </def> + <def> + <opc>de /mod=11 /x87=3f</opc> + <opr>ST7 ST0</opr> + </def> + </instruction> + + <instruction> + <mnemonic>fdivr</mnemonic> + <cpuid>X87</cpuid> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>dc /mod=!11 /reg=7</opc> + <opr>Mq</opr> + </def> + <def> + <opc>dc /mod=11 /x87=30</opc> + <opr>ST0 ST0</opr> + </def> + <def> + <opc>dc /mod=11 /x87=31</opc> + <opr>ST1 ST0</opr> + </def> + <def> + <opc>dc /mod=11 /x87=32</opc> + <opr>ST2 ST0</opr> + </def> + <def> + <opc>dc /mod=11 /x87=33</opc> + <opr>ST3 ST0</opr> + </def> + <def> + <opc>dc /mod=11 /x87=34</opc> + <opr>ST4 ST0</opr> + </def> + <def> + <opc>dc /mod=11 /x87=35</opc> + <opr>ST5 ST0</opr> + </def> + <def> + <opc>dc /mod=11 /x87=36</opc> + <opr>ST6 ST0</opr> + </def> + <def> + <opc>dc /mod=11 /x87=37</opc> + <opr>ST7 ST0</opr> + </def> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>d8 /mod=!11 /reg=7</opc> + <opr>Md</opr> + </def> + <def> + <opc>d8 /mod=11 /x87=38</opc> + <opr>ST0 ST0</opr> + </def> + <def> + <opc>d8 /mod=11 /x87=39</opc> + <opr>ST0 ST1</opr> + </def> + <def> + <opc>d8 /mod=11 /x87=3a</opc> + <opr>ST0 ST2</opr> + </def> + <def> + <opc>d8 /mod=11 /x87=3b</opc> + <opr>ST0 ST3</opr> + </def> + <def> + <opc>d8 /mod=11 /x87=3c</opc> + <opr>ST0 ST4</opr> + </def> + <def> + <opc>d8 /mod=11 /x87=3d</opc> + <opr>ST0 ST5</opr> + </def> + <def> + <opc>d8 /mod=11 /x87=3e</opc> + <opr>ST0 ST6</opr> + </def> + <def> + <opc>d8 /mod=11 /x87=3f</opc> + <opr>ST0 ST7</opr> + </def> + </instruction> + + <instruction> + <mnemonic>fdivrp</mnemonic> + <cpuid>X87</cpuid> + <def> + <opc>de /mod=11 /x87=30</opc> + <opr>ST0 ST0</opr> + </def> + <def> + <opc>de /mod=11 /x87=31</opc> + <opr>ST1 ST0</opr> + </def> + <def> + <opc>de /mod=11 /x87=32</opc> + <opr>ST2 ST0</opr> + </def> + <def> + <opc>de /mod=11 /x87=33</opc> + <opr>ST3 ST0</opr> + </def> + <def> + <opc>de /mod=11 /x87=34</opc> + <opr>ST4 ST0</opr> + </def> + <def> + <opc>de /mod=11 /x87=35</opc> + <opr>ST5 ST0</opr> + </def> + <def> + <opc>de /mod=11 /x87=36</opc> + <opr>ST6 ST0</opr> + </def> + <def> + <opc>de /mod=11 /x87=37</opc> + <opr>ST7 ST0</opr> + </def> + </instruction> + + <instruction> + <mnemonic>femms</mnemonic> + <def> + <opc>0f 0e</opc> + </def> + </instruction> + + <instruction> + <mnemonic>ffree</mnemonic> + <cpuid>X87</cpuid> + <def> + <opc>dd /mod=11 /x87=00</opc> + <opr>ST0</opr> + </def> + <def> + <opc>dd /mod=11 /x87=01</opc> + <opr>ST1</opr> + </def> + <def> + <opc>dd /mod=11 /x87=02</opc> + <opr>ST2</opr> + </def> + <def> + <opc>dd /mod=11 /x87=03</opc> + <opr>ST3</opr> + </def> + <def> + <opc>dd /mod=11 /x87=04</opc> + <opr>ST4</opr> + </def> + <def> + <opc>dd /mod=11 /x87=05</opc> + <opr>ST5</opr> + </def> + <def> + <opc>dd /mod=11 /x87=06</opc> + <opr>ST6</opr> + </def> + <def> + <opc>dd /mod=11 /x87=07</opc> + <opr>ST7</opr> + </def> + </instruction> + + <instruction> + <mnemonic>ffreep</mnemonic> + <cpuid>X87</cpuid> + <def> + <opc>df /mod=11 /x87=00</opc> + <opr>ST0</opr> + </def> + <def> + <opc>df /mod=11 /x87=01</opc> + <opr>ST1</opr> + </def> + <def> + <opc>df /mod=11 /x87=02</opc> + <opr>ST2</opr> + </def> + <def> + <opc>df /mod=11 /x87=03</opc> + <opr>ST3</opr> + </def> + <def> + <opc>df /mod=11 /x87=04</opc> + <opr>ST4</opr> + </def> + <def> + <opc>df /mod=11 /x87=05</opc> + <opr>ST5</opr> + </def> + <def> + <opc>df /mod=11 /x87=06</opc> + <opr>ST6</opr> + </def> + <def> + <opc>df /mod=11 /x87=07</opc> + <opr>ST7</opr> + </def> + </instruction> + + <instruction> + <mnemonic>ficom</mnemonic> + <cpuid>X87</cpuid> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>de /mod=!11 /reg=2</opc> + <opr>Mw</opr> + </def> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>da /mod=!11 /reg=2</opc> + <opr>Md</opr> + </def> + </instruction> + + <instruction> + <mnemonic>ficomp</mnemonic> + <cpuid>X87</cpuid> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>de /mod=!11 /reg=3</opc> + <opr>Mw</opr> + </def> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>da /mod=!11 /reg=3</opc> + <opr>Md</opr> + </def> + </instruction> + + <instruction> + <mnemonic>fild</mnemonic> + <cpuid>X87</cpuid> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>df /mod=!11 /reg=0</opc> + <opr>Mw</opr> + </def> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>df /mod=!11 /reg=5</opc> + <opr>Mq</opr> + </def> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>db /mod=!11 /reg=0</opc> + <opr>Md</opr> + </def> + </instruction> + + <instruction> + <mnemonic>fincstp</mnemonic> + <cpuid>X87</cpuid> + <def> + <opc>d9 /mod=11 /x87=37</opc> + </def> + </instruction> + + <instruction> + <mnemonic>fninit</mnemonic> + <cpuid>X87</cpuid> + <def> + <opc>db /mod=11 /x87=23</opc> + </def> + </instruction> + + <instruction> + <mnemonic>fiadd</mnemonic> + <cpuid>X87</cpuid> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>da /mod=!11 /reg=0</opc> + <opr>Md</opr> + </def> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>de /mod=!11 /reg=0</opc> + <opr>Mw</opr> + </def> + </instruction> + + <instruction> + <mnemonic>fidivr</mnemonic> + <cpuid>X87</cpuid> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>da /mod=!11 /reg=7</opc> + <opr>Md</opr> + </def> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>de /mod=!11 /reg=7</opc> + <opr>Mw</opr> + </def> + </instruction> + + <instruction> + <mnemonic>fidiv</mnemonic> + <cpuid>X87</cpuid> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>da /mod=!11 /reg=6</opc> + <opr>Md</opr> + </def> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>de /mod=!11 /reg=6</opc> + <opr>Mw</opr> + </def> + </instruction> + + <instruction> + <mnemonic>fisub</mnemonic> + <cpuid>X87</cpuid> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>da /mod=!11 /reg=4</opc> + <opr>Md</opr> + </def> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>de /mod=!11 /reg=4</opc> + <opr>Mw</opr> + </def> + </instruction> + + <instruction> + <mnemonic>fisubr</mnemonic> + <cpuid>X87</cpuid> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>da /mod=!11 /reg=5</opc> + <opr>Md</opr> + </def> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>de /mod=!11 /reg=5</opc> + <opr>Mw</opr> + </def> + </instruction> + + <instruction> + <mnemonic>fist</mnemonic> + <cpuid>X87</cpuid> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>df /mod=!11 /reg=2</opc> + <opr>Mw</opr> + </def> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>db /mod=!11 /reg=2</opc> + <opr>Md</opr> + </def> + </instruction> + + <instruction> + <mnemonic>fistp</mnemonic> + <cpuid>X87</cpuid> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>df /mod=!11 /reg=3</opc> + <opr>Mw</opr> + </def> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>df /mod=!11 /reg=7</opc> + <opr>Mq</opr> + </def> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>db /mod=!11 /reg=3</opc> + <opr>Md</opr> + </def> + </instruction> + + <instruction> + <mnemonic>fisttp</mnemonic> + <cpuid>X87</cpuid> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>db /mod=!11 /reg=1</opc> + <opr>Md</opr> + </def> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>dd /mod=!11 /reg=1</opc> + <opr>Mq</opr> + </def> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>df /mod=!11 /reg=1</opc> + <opr>Mw</opr> + </def> + </instruction> + + <instruction> + <mnemonic>fld</mnemonic> + <cpuid>X87</cpuid> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>db /mod=!11 /reg=5</opc> + <opr>Mt</opr> + </def> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>dd /mod=!11 /reg=0</opc> + <opr>Mq</opr> + </def> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>d9 /mod=!11 /reg=0</opc> + <opr>Md</opr> + </def> + <def> + <opc>d9 /mod=11 /x87=00</opc> + <opr>ST0</opr> + </def> + <def> + <opc>d9 /mod=11 /x87=01</opc> + <opr>ST1</opr> + </def> + <def> + <opc>d9 /mod=11 /x87=02</opc> + <opr>ST2</opr> + </def> + <def> + <opc>d9 /mod=11 /x87=03</opc> + <opr>ST3</opr> + </def> + <def> + <opc>d9 /mod=11 /x87=04</opc> + <opr>ST4</opr> + </def> + <def> + <opc>d9 /mod=11 /x87=05</opc> + <opr>ST5</opr> + </def> + <def> + <opc>d9 /mod=11 /x87=06</opc> + <opr>ST6</opr> + </def> + <def> + <opc>d9 /mod=11 /x87=07</opc> + <opr>ST7</opr> + </def> + </instruction> + + <instruction> + <mnemonic>fld1</mnemonic> + <cpuid>X87</cpuid> + <def> + <opc>d9 /mod=11 /x87=28</opc> + </def> + </instruction> + + <instruction> + <mnemonic>fldl2t</mnemonic> + <cpuid>X87</cpuid> + <def> + <opc>d9 /mod=11 /x87=29</opc> + </def> + </instruction> + + <instruction> + <mnemonic>fldl2e</mnemonic> + <cpuid>X87</cpuid> + <def> + <opc>d9 /mod=11 /x87=2a</opc> + </def> + </instruction> + + <instruction> + <mnemonic>fldpi</mnemonic> + <cpuid>X87</cpuid> + <def> + <opc>d9 /mod=11 /x87=2b</opc> + </def> + </instruction> + + <instruction> + <mnemonic>fldlg2</mnemonic> + <cpuid>X87</cpuid> + <def> + <opc>d9 /mod=11 /x87=2c</opc> + </def> + </instruction> + + <instruction> + <mnemonic>fldln2</mnemonic> + <cpuid>X87</cpuid> + <def> + <opc>d9 /mod=11 /x87=2d</opc> + </def> + </instruction> + + <instruction> + <mnemonic>fldz</mnemonic> + <cpuid>X87</cpuid> + <def> + <opc>d9 /mod=11 /x87=2e</opc> + </def> + </instruction> + + <instruction> + <mnemonic>fldcw</mnemonic> + <cpuid>X87</cpuid> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>d9 /mod=!11 /reg=5</opc> + <opr>Mw</opr> + </def> + </instruction> + + <instruction> + <mnemonic>fldenv</mnemonic> + <cpuid>X87</cpuid> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>d9 /mod=!11 /reg=4</opc> + <opr>M</opr> + </def> + </instruction> + + <instruction> + <mnemonic>fmul</mnemonic> + <cpuid>X87</cpuid> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>dc /mod=!11 /reg=1</opc> + <opr>Mq</opr> + </def> + <def> + <opc>dc /mod=11 /x87=08</opc> + <opr>ST0 ST0</opr> + </def> + <def> + <opc>dc /mod=11 /x87=09</opc> + <opr>ST1 ST0</opr> + </def> + <def> + <opc>dc /mod=11 /x87=0a</opc> + <opr>ST2 ST0</opr> + </def> + <def> + <opc>dc /mod=11 /x87=0b</opc> + <opr>ST3 ST0</opr> + </def> + <def> + <opc>dc /mod=11 /x87=0c</opc> + <opr>ST4 ST0</opr> + </def> + <def> + <opc>dc /mod=11 /x87=0d</opc> + <opr>ST5 ST0</opr> + </def> + <def> + <opc>dc /mod=11 /x87=0e</opc> + <opr>ST6 ST0</opr> + </def> + <def> + <opc>dc /mod=11 /x87=0f</opc> + <opr>ST7 ST0</opr> + </def> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>d8 /mod=!11 /reg=1</opc> + <opr>Md</opr> + </def> + <def> + <opc>d8 /mod=11 /x87=08</opc> + <opr>ST0 ST0</opr> + </def> + <def> + <opc>d8 /mod=11 /x87=09</opc> + <opr>ST0 ST1</opr> + </def> + <def> + <opc>d8 /mod=11 /x87=0a</opc> + <opr>ST0 ST2</opr> + </def> + <def> + <opc>d8 /mod=11 /x87=0b</opc> + <opr>ST0 ST3</opr> + </def> + <def> + <opc>d8 /mod=11 /x87=0c</opc> + <opr>ST0 ST4</opr> + </def> + <def> + <opc>d8 /mod=11 /x87=0d</opc> + <opr>ST0 ST5</opr> + </def> + <def> + <opc>d8 /mod=11 /x87=0e</opc> + <opr>ST0 ST6</opr> + </def> + <def> + <opc>d8 /mod=11 /x87=0f</opc> + <opr>ST0 ST7</opr> + </def> + </instruction> + + <instruction> + <mnemonic>fmulp</mnemonic> + <cpuid>X87</cpuid> + <def> + <opc>de /mod=11 /x87=08</opc> + <opr>ST0 ST0</opr> + </def> + <def> + <opc>de /mod=11 /x87=09</opc> + <opr>ST1 ST0</opr> + </def> + <def> + <opc>de /mod=11 /x87=0a</opc> + <opr>ST2 ST0</opr> + </def> + <def> + <opc>de /mod=11 /x87=0b</opc> + <opr>ST3 ST0</opr> + </def> + <def> + <opc>de /mod=11 /x87=0c</opc> + <opr>ST4 ST0</opr> + </def> + <def> + <opc>de /mod=11 /x87=0d</opc> + <opr>ST5 ST0</opr> + </def> + <def> + <opc>de /mod=11 /x87=0e</opc> + <opr>ST6 ST0</opr> + </def> + <def> + <opc>de /mod=11 /x87=0f</opc> + <opr>ST7 ST0</opr> + </def> + </instruction> + + <instruction> + <mnemonic>fimul</mnemonic> + <cpuid>X87</cpuid> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>da /mod=!11 /reg=1</opc> + <opr>Md</opr> + </def> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>de /mod=!11 /reg=1</opc> + <opr>Mw</opr> + </def> + </instruction> + + <instruction> + <mnemonic>fnop</mnemonic> + <cpuid>X87</cpuid> + <def> + <opc>d9 /mod=11 /x87=10</opc> + </def> + </instruction> + + <instruction> + <mnemonic>fndisi</mnemonic> + <cpuid>X87</cpuid> + <def> + <opc>db /mod=11 /x87=21</opc> + </def> + </instruction> + + <instruction> + <mnemonic>fneni</mnemonic> + <cpuid>X87</cpuid> + <def> + <opc>db /mod=11 /x87=20</opc> + </def> + </instruction> + + <instruction> + <mnemonic>fnsetpm</mnemonic> + <cpuid>X87</cpuid> + <def> + <opc>db /mod=11 /x87=24</opc> + </def> + </instruction> + + <instruction> + <mnemonic>fpatan</mnemonic> + <cpuid>X87</cpuid> + <def> + <opc>d9 /mod=11 /x87=33</opc> + </def> + </instruction> + + <instruction> + <mnemonic>fprem</mnemonic> + <cpuid>X87</cpuid> + <def> + <opc>d9 /mod=11 /x87=38</opc> + </def> + </instruction> + + <instruction> + <mnemonic>fprem1</mnemonic> + <cpuid>X87</cpuid> + <def> + <opc>d9 /mod=11 /x87=35</opc> + </def> + </instruction> + + <instruction> + <mnemonic>fptan</mnemonic> + <cpuid>X87</cpuid> + <def> + <opc>d9 /mod=11 /x87=32</opc> + </def> + </instruction> + + <instruction> + <mnemonic>frndint</mnemonic> + <cpuid>X87</cpuid> + <def> + <opc>d9 /mod=11 /x87=3c</opc> + </def> + </instruction> + + <instruction> + <mnemonic>frstor</mnemonic> + <cpuid>X87</cpuid> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>dd /mod=!11 /reg=4</opc> + <opr>M</opr> + </def> + </instruction> + + <instruction> + <mnemonic>frstpm</mnemonic> + <cpuid>X87</cpuid> + <def> + <opc>db /mod=11 /x87=25</opc> + </def> + </instruction> + + <instruction> + <mnemonic>fnsave</mnemonic> + <cpuid>X87</cpuid> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>dd /mod=!11 /reg=6</opc> + <opr>M</opr> + </def> + </instruction> + + <instruction> + <mnemonic>fscale</mnemonic> + <cpuid>X87</cpuid> + <def> + <opc>d9 /mod=11 /x87=3d</opc> + </def> + </instruction> + + <instruction> + <mnemonic>fsin</mnemonic> + <cpuid>X87</cpuid> + <def> + <opc>d9 /mod=11 /x87=3e</opc> + </def> + </instruction> + + <instruction> + <mnemonic>fsincos</mnemonic> + <cpuid>X87</cpuid> + <def> + <opc>d9 /mod=11 /x87=3b</opc> + </def> + </instruction> + + <instruction> + <mnemonic>fsqrt</mnemonic> + <cpuid>X87</cpuid> + <def> + <opc>d9 /mod=11 /x87=3a</opc> + </def> + </instruction> + + <instruction> + <mnemonic>fstp</mnemonic> + <cpuid>X87</cpuid> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>db /mod=!11 /reg=7</opc> + <opr>Mt</opr> + </def> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>dd /mod=!11 /reg=3</opc> + <opr>Mq</opr> + </def> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>d9 /mod=!11 /reg=3</opc> + <opr>Md</opr> + </def> + <def> + <opc>dd /mod=11 /x87=18</opc> + <opr>ST0</opr> + </def> + <def> + <opc>dd /mod=11 /x87=19</opc> + <opr>ST1</opr> + </def> + <def> + <opc>dd /mod=11 /x87=1a</opc> + <opr>ST2</opr> + </def> + <def> + <opc>dd /mod=11 /x87=1b</opc> + <opr>ST3</opr> + </def> + <def> + <opc>dd /mod=11 /x87=1c</opc> + <opr>ST4</opr> + </def> + <def> + <opc>dd /mod=11 /x87=1d</opc> + <opr>ST5</opr> + </def> + <def> + <opc>dd /mod=11 /x87=1e</opc> + <opr>ST6</opr> + </def> + <def> + <opc>dd /mod=11 /x87=1f</opc> + <opr>ST7</opr> + </def> + </instruction> + + <instruction> + <mnemonic>fstp1</mnemonic> + <def> + <opc>d9 /mod=11 /x87=18</opc> + <opr>ST0</opr> + </def> + <def> + <opc>d9 /mod=11 /x87=19</opc> + <opr>ST1</opr> + </def> + <def> + <opc>d9 /mod=11 /x87=1a</opc> + <opr>ST2</opr> + </def> + <def> + <opc>d9 /mod=11 /x87=1b</opc> + <opr>ST3</opr> + </def> + <def> + <opc>d9 /mod=11 /x87=1c</opc> + <opr>ST4</opr> + </def> + <def> + <opc>d9 /mod=11 /x87=1d</opc> + <opr>ST5</opr> + </def> + <def> + <opc>d9 /mod=11 /x87=1e</opc> + <opr>ST6</opr> + </def> + <def> + <opc>d9 /mod=11 /x87=1f</opc> + <opr>ST7</opr> + </def> + </instruction> + + <instruction> + <mnemonic>fstp8</mnemonic> + <def> + <opc>df /mod=11 /x87=10</opc> + <opr>ST0</opr> + </def> + <def> + <opc>df /mod=11 /x87=11</opc> + <opr>ST1</opr> + </def> + <def> + <opc>df /mod=11 /x87=12</opc> + <opr>ST2</opr> + </def> + <def> + <opc>df /mod=11 /x87=13</opc> + <opr>ST3</opr> + </def> + <def> + <opc>df /mod=11 /x87=14</opc> + <opr>ST4</opr> + </def> + <def> + <opc>df /mod=11 /x87=15</opc> + <opr>ST5</opr> + </def> + <def> + <opc>df /mod=11 /x87=16</opc> + <opr>ST6</opr> + </def> + <def> + <opc>df /mod=11 /x87=17</opc> + <opr>ST7</opr> + </def> + </instruction> + + <instruction> + <mnemonic>fstp9</mnemonic> + <def> + <opc>df /mod=11 /x87=18</opc> + <opr>ST0</opr> + </def> + <def> + <opc>df /mod=11 /x87=19</opc> + <opr>ST1</opr> + </def> + <def> + <opc>df /mod=11 /x87=1a</opc> + <opr>ST2</opr> + </def> + <def> + <opc>df /mod=11 /x87=1b</opc> + <opr>ST3</opr> + </def> + <def> + <opc>df /mod=11 /x87=1c</opc> + <opr>ST4</opr> + </def> + <def> + <opc>df /mod=11 /x87=1d</opc> + <opr>ST5</opr> + </def> + <def> + <opc>df /mod=11 /x87=1e</opc> + <opr>ST6</opr> + </def> + <def> + <opc>df /mod=11 /x87=1f</opc> + <opr>ST7</opr> + </def> + </instruction> + + <instruction> + <mnemonic>fst</mnemonic> + <cpuid>X87</cpuid> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>d9 /mod=!11 /reg=2</opc> + <opr>Md</opr> + </def> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>dd /mod=!11 /reg=2</opc> + <opr>Mq</opr> + </def> + <def> + <opc>dd /mod=11 /x87=10</opc> + <opr>ST0</opr> + </def> + <def> + <opc>dd /mod=11 /x87=11</opc> + <opr>ST1</opr> + </def> + <def> + <opc>dd /mod=11 /x87=12</opc> + <opr>ST2</opr> + </def> + <def> + <opc>dd /mod=11 /x87=13</opc> + <opr>ST3</opr> + </def> + <def> + <opc>dd /mod=11 /x87=14</opc> + <opr>ST4</opr> + </def> + <def> + <opc>dd /mod=11 /x87=15</opc> + <opr>ST5</opr> + </def> + <def> + <opc>dd /mod=11 /x87=16</opc> + <opr>ST6</opr> + </def> + <def> + <opc>dd /mod=11 /x87=17</opc> + <opr>ST7</opr> + </def> + </instruction> + + <instruction> + <mnemonic>fnstcw</mnemonic> + <cpuid>X87</cpuid> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>d9 /mod=!11 /reg=7</opc> + <opr>Mw</opr> + </def> + </instruction> + + <instruction> + <mnemonic>fnstenv</mnemonic> + <cpuid>X87</cpuid> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>d9 /mod=!11 /reg=6</opc> + <opr>M</opr> + </def> + </instruction> + + <instruction> + <mnemonic>fnstsw</mnemonic> + <cpuid>X87</cpuid> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>dd /mod=!11 /reg=7</opc> + <opr>Mw</opr> + </def> + <def> + <opc>df /mod=11 /x87=20</opc> + <opr>AX</opr> + </def> + </instruction> + + <instruction> + <mnemonic>fsub</mnemonic> + <cpuid>X87</cpuid> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>d8 /mod=!11 /reg=4</opc> + <opr>Md</opr> + </def> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>dc /mod=!11 /reg=4</opc> + <opr>Mq</opr> + </def> + <def> + <opc>d8 /mod=11 /x87=20</opc> + <opr>ST0 ST0</opr> + </def> + <def> + <opc>d8 /mod=11 /x87=21</opc> + <opr>ST0 ST1</opr> + </def> + <def> + <opc>d8 /mod=11 /x87=22</opc> + <opr>ST0 ST2</opr> + </def> + <def> + <opc>d8 /mod=11 /x87=23</opc> + <opr>ST0 ST3</opr> + </def> + <def> + <opc>d8 /mod=11 /x87=24</opc> + <opr>ST0 ST4</opr> + </def> + <def> + <opc>d8 /mod=11 /x87=25</opc> + <opr>ST0 ST5</opr> + </def> + <def> + <opc>d8 /mod=11 /x87=26</opc> + <opr>ST0 ST6</opr> + </def> + <def> + <opc>d8 /mod=11 /x87=27</opc> + <opr>ST0 ST7</opr> + </def> + <def> + <opc>dc /mod=11 /x87=28</opc> + <opr>ST0 ST0</opr> + </def> + <def> + <opc>dc /mod=11 /x87=29</opc> + <opr>ST1 ST0</opr> + </def> + <def> + <opc>dc /mod=11 /x87=2a</opc> + <opr>ST2 ST0</opr> + </def> + <def> + <opc>dc /mod=11 /x87=2b</opc> + <opr>ST3 ST0</opr> + </def> + <def> + <opc>dc /mod=11 /x87=2c</opc> + <opr>ST4 ST0</opr> + </def> + <def> + <opc>dc /mod=11 /x87=2d</opc> + <opr>ST5 ST0</opr> + </def> + <def> + <opc>dc /mod=11 /x87=2e</opc> + <opr>ST6 ST0</opr> + </def> + <def> + <opc>dc /mod=11 /x87=2f</opc> + <opr>ST7 ST0</opr> + </def> + </instruction> + + <instruction> + <mnemonic>fsubp</mnemonic> + <cpuid>X87</cpuid> + <def> + <opc>de /mod=11 /x87=28</opc> + <opr>ST0 ST0</opr> + </def> + <def> + <opc>de /mod=11 /x87=29</opc> + <opr>ST1 ST0</opr> + </def> + <def> + <opc>de /mod=11 /x87=2a</opc> + <opr>ST2 ST0</opr> + </def> + <def> + <opc>de /mod=11 /x87=2b</opc> + <opr>ST3 ST0</opr> + </def> + <def> + <opc>de /mod=11 /x87=2c</opc> + <opr>ST4 ST0</opr> + </def> + <def> + <opc>de /mod=11 /x87=2d</opc> + <opr>ST5 ST0</opr> + </def> + <def> + <opc>de /mod=11 /x87=2e</opc> + <opr>ST6 ST0</opr> + </def> + <def> + <opc>de /mod=11 /x87=2f</opc> + <opr>ST7 ST0</opr> + </def> + </instruction> + + <instruction> + <mnemonic>fsubr</mnemonic> + <cpuid>X87</cpuid> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>dc /mod=!11 /reg=5</opc> + <opr>Mq</opr> + </def> + <def> + <opc>d8 /mod=11 /x87=28</opc> + <opr>ST0 ST0</opr> + </def> + <def> + <opc>d8 /mod=11 /x87=29</opc> + <opr>ST0 ST1</opr> + </def> + <def> + <opc>d8 /mod=11 /x87=2a</opc> + <opr>ST0 ST2</opr> + </def> + <def> + <opc>d8 /mod=11 /x87=2b</opc> + <opr>ST0 ST3</opr> + </def> + <def> + <opc>d8 /mod=11 /x87=2c</opc> + <opr>ST0 ST4</opr> + </def> + <def> + <opc>d8 /mod=11 /x87=2d</opc> + <opr>ST0 ST5</opr> + </def> + <def> + <opc>d8 /mod=11 /x87=2e</opc> + <opr>ST0 ST6</opr> + </def> + <def> + <opc>d8 /mod=11 /x87=2f</opc> + <opr>ST0 ST7</opr> + </def> + <def> + <opc>dc /mod=11 /x87=20</opc> + <opr>ST0 ST0</opr> + </def> + <def> + <opc>dc /mod=11 /x87=21</opc> + <opr>ST1 ST0</opr> + </def> + <def> + <opc>dc /mod=11 /x87=22</opc> + <opr>ST2 ST0</opr> + </def> + <def> + <opc>dc /mod=11 /x87=23</opc> + <opr>ST3 ST0</opr> + </def> + <def> + <opc>dc /mod=11 /x87=24</opc> + <opr>ST4 ST0</opr> + </def> + <def> + <opc>dc /mod=11 /x87=25</opc> + <opr>ST5 ST0</opr> + </def> + <def> + <opc>dc /mod=11 /x87=26</opc> + <opr>ST6 ST0</opr> + </def> + <def> + <opc>dc /mod=11 /x87=27</opc> + <opr>ST7 ST0</opr> + </def> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>d8 /mod=!11 /reg=5</opc> + <opr>Md</opr> + </def> + </instruction> + + <instruction> + <mnemonic>fsubrp</mnemonic> + <cpuid>X87</cpuid> + <def> + <opc>de /mod=11 /x87=20</opc> + <opr>ST0 ST0</opr> + </def> + <def> + <opc>de /mod=11 /x87=21</opc> + <opr>ST1 ST0</opr> + </def> + <def> + <opc>de /mod=11 /x87=22</opc> + <opr>ST2 ST0</opr> + </def> + <def> + <opc>de /mod=11 /x87=23</opc> + <opr>ST3 ST0</opr> + </def> + <def> + <opc>de /mod=11 /x87=24</opc> + <opr>ST4 ST0</opr> + </def> + <def> + <opc>de /mod=11 /x87=25</opc> + <opr>ST5 ST0</opr> + </def> + <def> + <opc>de /mod=11 /x87=26</opc> + <opr>ST6 ST0</opr> + </def> + <def> + <opc>de /mod=11 /x87=27</opc> + <opr>ST7 ST0</opr> + </def> + </instruction> + + <instruction> + <mnemonic>ftst</mnemonic> + <cpuid>X87</cpuid> + <def> + <opc>d9 /mod=11 /x87=24</opc> + </def> + </instruction> + + <instruction> + <mnemonic>fucom</mnemonic> + <cpuid>X87</cpuid> + <def> + <opc>dd /mod=11 /x87=20</opc> + <opr>ST0</opr> + </def> + <def> + <opc>dd /mod=11 /x87=21</opc> + <opr>ST1</opr> + </def> + <def> + <opc>dd /mod=11 /x87=22</opc> + <opr>ST2</opr> + </def> + <def> + <opc>dd /mod=11 /x87=23</opc> + <opr>ST3</opr> + </def> + <def> + <opc>dd /mod=11 /x87=24</opc> + <opr>ST4</opr> + </def> + <def> + <opc>dd /mod=11 /x87=25</opc> + <opr>ST5</opr> + </def> + <def> + <opc>dd /mod=11 /x87=26</opc> + <opr>ST6</opr> + </def> + <def> + <opc>dd /mod=11 /x87=27</opc> + <opr>ST7</opr> + </def> + </instruction> + + <instruction> + <mnemonic>fucomp</mnemonic> + <cpuid>X87</cpuid> + <def> + <opc>dd /mod=11 /x87=28</opc> + <opr>ST0</opr> + </def> + <def> + <opc>dd /mod=11 /x87=29</opc> + <opr>ST1</opr> + </def> + <def> + <opc>dd /mod=11 /x87=2a</opc> + <opr>ST2</opr> + </def> + <def> + <opc>dd /mod=11 /x87=2b</opc> + <opr>ST3</opr> + </def> + <def> + <opc>dd /mod=11 /x87=2c</opc> + <opr>ST4</opr> + </def> + <def> + <opc>dd /mod=11 /x87=2d</opc> + <opr>ST5</opr> + </def> + <def> + <opc>dd /mod=11 /x87=2e</opc> + <opr>ST6</opr> + </def> + <def> + <opc>dd /mod=11 /x87=2f</opc> + <opr>ST7</opr> + </def> + </instruction> + + <instruction> + <mnemonic>fucompp</mnemonic> + <cpuid>X87</cpuid> + <def> + <opc>da /mod=11 /x87=29</opc> + </def> + </instruction> + + <instruction> + <mnemonic>fxam</mnemonic> + <cpuid>X87</cpuid> + <def> + <opc>d9 /mod=11 /x87=25</opc> + </def> + </instruction> + + <instruction> + <mnemonic>fxch</mnemonic> + <cpuid>X87</cpuid> + <def> + <opc>d9 /mod=11 /x87=08</opc> + <opr>ST0 ST0</opr> + </def> + <def> + <opc>d9 /mod=11 /x87=09</opc> + <opr>ST0 ST1</opr> + </def> + <def> + <opc>d9 /mod=11 /x87=0a</opc> + <opr>ST0 ST2</opr> + </def> + <def> + <opc>d9 /mod=11 /x87=0b</opc> + <opr>ST0 ST3</opr> + </def> + <def> + <opc>d9 /mod=11 /x87=0c</opc> + <opr>ST0 ST4</opr> + </def> + <def> + <opc>d9 /mod=11 /x87=0d</opc> + <opr>ST0 ST5</opr> + </def> + <def> + <opc>d9 /mod=11 /x87=0e</opc> + <opr>ST0 ST6</opr> + </def> + <def> + <opc>d9 /mod=11 /x87=0f</opc> + <opr>ST0 ST7</opr> + </def> + </instruction> + + <instruction> + <mnemonic>fxch4</mnemonic> + <cpuid>X87</cpuid> + <def> + <opc>dd /mod=11 /x87=08</opc> + <opr>ST0</opr> + </def> + <def> + <opc>dd /mod=11 /x87=09</opc> + <opr>ST1</opr> + </def> + <def> + <opc>dd /mod=11 /x87=0a</opc> + <opr>ST2</opr> + </def> + <def> + <opc>dd /mod=11 /x87=0b</opc> + <opr>ST3</opr> + </def> + <def> + <opc>dd /mod=11 /x87=0c</opc> + <opr>ST4</opr> + </def> + <def> + <opc>dd /mod=11 /x87=0d</opc> + <opr>ST5</opr> + </def> + <def> + <opc>dd /mod=11 /x87=0e</opc> + <opr>ST6</opr> + </def> + <def> + <opc>dd /mod=11 /x87=0f</opc> + <opr>ST7</opr> + </def> + </instruction> + + <instruction> + <mnemonic>fxch7</mnemonic> + <cpuid>X87</cpuid> + <def> + <opc>df /mod=11 /x87=08</opc> + <opr>ST0</opr> + </def> + <def> + <opc>df /mod=11 /x87=09</opc> + <opr>ST1</opr> + </def> + <def> + <opc>df /mod=11 /x87=0a</opc> + <opr>ST2</opr> + </def> + <def> + <opc>df /mod=11 /x87=0b</opc> + <opr>ST3</opr> + </def> + <def> + <opc>df /mod=11 /x87=0c</opc> + <opr>ST4</opr> + </def> + <def> + <opc>df /mod=11 /x87=0d</opc> + <opr>ST5</opr> + </def> + <def> + <opc>df /mod=11 /x87=0e</opc> + <opr>ST6</opr> + </def> + <def> + <opc>df /mod=11 /x87=0f</opc> + <opr>ST7</opr> + </def> + </instruction> + + <instruction> + <mnemonic>fxrstor</mnemonic> + <def> + <pfx>aso rexw rexr rexx rexb</pfx> + <opc>0f ae /mod=!11 /reg=1</opc> + <opr>M</opr> + </def> + </instruction> + + <instruction> + <mnemonic>fxsave</mnemonic> + <def> + <pfx>aso rexw rexr rexx rexb</pfx> + <opc>0f ae /mod=!11 /reg=0</opc> + <opr>M</opr> + </def> + </instruction> + + <instruction> + <mnemonic>fxtract</mnemonic> + <cpuid>X87</cpuid> + <def> + <opc>d9 /mod=11 /x87=34</opc> + </def> + </instruction> + + <instruction> + <mnemonic>fyl2x</mnemonic> + <cpuid>X87</cpuid> + <def> + <opc>d9 /mod=11 /x87=31</opc> + </def> + </instruction> + + <instruction> + <mnemonic>fyl2xp1</mnemonic> + <cpuid>X87</cpuid> + <def> + <opc>d9 /mod=11 /x87=39</opc> + </def> + </instruction> + + <instruction> + <mnemonic>hlt</mnemonic> + <def> + <opc>f4</opc> + </def> + </instruction> + + <instruction> + <mnemonic>idiv</mnemonic> + <def> + <pfx>aso oso rexw rexr rexx rexb</pfx> + <opc>f7 /reg=7</opc> + <opr>Ev</opr> + </def> + <def> + <pfx>aso rexw rexr rexx rexb</pfx> + <opc>f6 /reg=7</opc> + <opr>Eb</opr> + </def> + </instruction> + + <instruction> + <mnemonic>in</mnemonic> + <def> + <opc>e4</opc> + <opr>AL Ib</opr> + </def> + <def> + <pfx>oso</pfx> + <opc>e5</opc> + <opr>eAX Ib</opr> + </def> + <def> + <opc>ec</opc> + <opr>AL DX</opr> + </def> + <def> + <pfx>oso</pfx> + <opc>ed</opc> + <opr>eAX DX</opr> + </def> + </instruction> + + <instruction> + <mnemonic>imul</mnemonic> + <def> + <pfx>aso oso rexw rexr rexx rexb</pfx> + <opc>0f af</opc> + <opr>Gv Ev</opr> + </def> + <def> + <pfx>aso rexw rexr rexx rexb</pfx> + <opc>f6 /reg=5</opc> + <opr>Eb</opr> + </def> + <def> + <pfx>aso oso rexw rexr rexx rexb</pfx> + <opc>f7 /reg=5</opc> + <opr>Ev</opr> + </def> + <def> + <pfx>aso oso rexw rexr rexx rexb</pfx> + <opc>69</opc> + <opr>Gv Ev Iz</opr> + </def> + <def> + <pfx>aso oso rexw rexr rexx rexb</pfx> + <opc>6b</opc> + <opr>Gv Ev sIb</opr> + </def> + </instruction> + + <instruction> + <mnemonic>inc</mnemonic> + <def> + <pfx>oso</pfx> + <opc>40</opc> + <opr>R0z</opr> + </def> + <def> + <pfx>oso</pfx> + <opc>41</opc> + <opr>R1z</opr> + </def> + <def> + <pfx>oso</pfx> + <opc>42</opc> + <opr>R2z</opr> + </def> + <def> + <pfx>oso</pfx> + <opc>43</opc> + <opr>R3z</opr> + </def> + <def> + <pfx>oso</pfx> + <opc>44</opc> + <opr>R4z</opr> + </def> + <def> + <pfx>oso</pfx> + <opc>45</opc> + <opr>R5z</opr> + </def> + <def> + <pfx>oso</pfx> + <opc>46</opc> + <opr>R6z</opr> + </def> + <def> + <pfx>oso</pfx> + <opc>47</opc> + <opr>R7z</opr> + </def> + <def> + <pfx>aso oso rexw rexr rexx rexb</pfx> + <opc>ff /reg=0</opc> + <opr>Ev</opr> + </def> + <def> + <pfx>aso rexw rexr rexx rexb</pfx> + <opc>fe /reg=0</opc> + <opr>Eb</opr> + </def> + </instruction> + + <instruction> + <mnemonic>insb</mnemonic> + <def> + <pfx>rep seg</pfx> + <opc>6c</opc> + </def> + </instruction> + + <instruction> + <mnemonic>insw</mnemonic> + <def> + <pfx>rep oso seg</pfx> + <opc>6d /o=16</opc> + </def> + </instruction> + + <instruction> + <mnemonic>insd</mnemonic> + <def> + <pfx>rep oso seg</pfx> + <opc>6d /o=32</opc> + </def> + </instruction> + + <instruction> + <mnemonic>int1</mnemonic> + <def> + <opc>f1</opc> + </def> + </instruction> + + <instruction> + <mnemonic>int3</mnemonic> + <def> + <opc>cc</opc> + </def> + </instruction> + + <instruction> + <mnemonic>int</mnemonic> + <def> + <opc>cd</opc> + <opr>Ib</opr> + </def> + </instruction> + + <instruction> + <mnemonic>into</mnemonic> + <def> + <opc>ce /m=!64</opc> + <mode>inv64</mode> + </def> + </instruction> + + <instruction> + <mnemonic>invd</mnemonic> + <def> + <opc>0f 08</opc> + </def> + </instruction> + + <instruction> + <mnemonic>invept</mnemonic> + <vendor>intel</vendor> + <def> + <opc>/sse=66 0f 38 80 /m=32</opc> + <opr>Gd Mo</opr> + </def> + <def> + <opc>/sse=66 0f 38 80 /m=64</opc> + <opr>Gq Mo</opr> + </def> + </instruction> + + <instruction> + <mnemonic>invlpg</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>0f 01 /reg=7 /mod=!11</opc> + <opr>M</opr> + </def> + </instruction> + + <instruction> + <mnemonic>invlpga</mnemonic> + <vendor>amd</vendor> + <def> + <opc>0f 01 /reg=3 /mod=11 /rm=7</opc> + </def> + </instruction> + + <instruction> + <mnemonic>invvpid</mnemonic> + <vendor>intel</vendor> + <def> + <opc>/sse=66 0f 38 81 /m=32</opc> + <opr>Gd Mo</opr> + </def> + <def> + <opc>/sse=66 0f 38 81 /m=64</opc> + <opr>Gq Mo</opr> + </def> + </instruction> + + <instruction> + <mnemonic>iretw</mnemonic> + <def> + <pfx>oso rexw</pfx> + <opc>cf /o=16</opc> + </def> + </instruction> + + <instruction> + <mnemonic>iretd</mnemonic> + <def> + <pfx>oso rexw</pfx> + <opc>cf /o=32</opc> + </def> + </instruction> + + <instruction> + <mnemonic>iretq</mnemonic> + <def> + <pfx>oso rexw</pfx> + <opc>cf /o=64</opc> + </def> + </instruction> + + <instruction> + <mnemonic>jo</mnemonic> + <def> + <opc>70</opc> + <opr>Jb</opr> + </def> + <def> + <pfx>oso</pfx> + <opc>0f 80</opc> + <opr>Jz</opr> + <mode>def64</mode> + </def> + </instruction> + + <instruction> + <mnemonic>jno</mnemonic> + <def> + <opc>71</opc> + <opr>Jb</opr> + </def> + <def> + <pfx>oso</pfx> + <opc>0f 81</opc> + <opr>Jz</opr> + <mode>def64</mode> + </def> + </instruction> + + <instruction> + <mnemonic>jb</mnemonic> + <def> + <opc>72</opc> + <opr>Jb</opr> + </def> + <def> + <pfx>oso</pfx> + <opc>0f 82</opc> + <opr>Jz</opr> + <mode>def64</mode> + </def> + </instruction> + + <instruction> + <mnemonic>jae</mnemonic> + <def> + <opc>73</opc> + <opr>Jb</opr> + </def> + <def> + <pfx>oso</pfx> + <opc>0f 83</opc> + <opr>Jz</opr> + <mode>def64</mode> + </def> + </instruction> + + <instruction> + <mnemonic>jz</mnemonic> + <def> + <opc>74</opc> + <opr>Jb</opr> + </def> + <def> + <pfx>oso</pfx> + <opc>0f 84</opc> + <opr>Jz</opr> + <mode>def64</mode> + </def> + </instruction> + + <instruction> + <mnemonic>jnz</mnemonic> + <def> + <opc>75</opc> + <opr>Jb</opr> + </def> + <def> + <pfx>oso</pfx> + <opc>0f 85</opc> + <opr>Jz</opr> + <mode>def64</mode> + </def> + </instruction> + + <instruction> + <mnemonic>jbe</mnemonic> + <def> + <opc>76</opc> + <opr>Jb</opr> + </def> + <def> + <pfx>oso</pfx> + <opc>0f 86</opc> + <opr>Jz</opr> + <mode>def64</mode> + </def> + </instruction> + + <instruction> + <mnemonic>ja</mnemonic> + <def> + <opc>77</opc> + <opr>Jb</opr> + </def> + <def> + <pfx>oso</pfx> + <opc>0f 87</opc> + <opr>Jz</opr> + <mode>def64</mode> + </def> + </instruction> + + <instruction> + <mnemonic>js</mnemonic> + <def> + <opc>78</opc> + <opr>Jb</opr> + </def> + <def> + <pfx>oso</pfx> + <opc>0f 88</opc> + <opr>Jz</opr> + <mode>def64</mode> + </def> + </instruction> + + <instruction> + <mnemonic>jns</mnemonic> + <def> + <opc>79</opc> + <opr>Jb</opr> + </def> + <def> + <pfx>oso</pfx> + <opc>0f 89</opc> + <opr>Jz</opr> + <mode>def64</mode> + </def> + </instruction> + + <instruction> + <mnemonic>jp</mnemonic> + <def> + <opc>7a</opc> + <opr>Jb</opr> + </def> + <def> + <pfx>oso</pfx> + <opc>0f 8a</opc> + <opr>Jz</opr> + <mode>def64</mode> + </def> + </instruction> + + <instruction> + <mnemonic>jnp</mnemonic> + <def> + <opc>7b</opc> + <opr>Jb</opr> + </def> + <def> + <pfx>oso</pfx> + <opc>0f 8b</opc> + <opr>Jz</opr> + <mode>def64</mode> + </def> + </instruction> + + <instruction> + <mnemonic>jl</mnemonic> + <def> + <opc>7c</opc> + <opr>Jb</opr> + </def> + <def> + <pfx>oso</pfx> + <opc>0f 8c</opc> + <opr>Jz</opr> + <mode>def64</mode> + </def> + </instruction> + + <instruction> + <mnemonic>jge</mnemonic> + <def> + <opc>7d</opc> + <opr>Jb</opr> + </def> + <def> + <pfx>oso</pfx> + <opc>0f 8d</opc> + <opr>Jz</opr> + <mode>def64</mode> + </def> + </instruction> + + <instruction> + <mnemonic>jle</mnemonic> + <def> + <opc>7e</opc> + <opr>Jb</opr> + </def> + <def> + <pfx>oso</pfx> + <opc>0f 8e</opc> + <opr>Jz</opr> + <mode>def64</mode> + </def> + </instruction> + + <instruction> + <mnemonic>jg</mnemonic> + <def> + <opc>7f</opc> + <opr>Jb</opr> + </def> + <def> + <pfx>oso</pfx> + <opc>0f 8f</opc> + <opr>Jz</opr> + <mode>def64</mode> + </def> + </instruction> + + <instruction> + <mnemonic>jcxz</mnemonic> + <def> + <pfx>aso</pfx> + <opc>e3 /a=16</opc> + <opr>Jb</opr> + </def> + </instruction> + + <instruction> + <mnemonic>jecxz</mnemonic> + <def> + <pfx>aso</pfx> + <opc>e3 /a=32</opc> + <opr>Jb</opr> + </def> + </instruction> + + <instruction> + <mnemonic>jrcxz</mnemonic> + <def> + <pfx>aso</pfx> + <opc>e3 /a=64</opc> + <opr>Jb</opr> + </def> + </instruction> + + <instruction> + <mnemonic>jmp</mnemonic> + <def> + <pfx>aso oso rexw rexr rexx rexb</pfx> + <opc>ff /reg=4</opc> + <opr>Ev</opr> + <mode>def64</mode> + </def> + <def> + <pfx>aso oso rexw rexr rexx rexb</pfx> + <opc>ff /reg=5</opc> + <opr>Fv</opr> + </def> + <def> + <pfx>oso</pfx> + <opc>e9</opc> + <opr>Jz</opr> + <mode>def64</mode> + </def> + <def> + <pfx>oso</pfx> + <opc>ea /m=!64</opc> + <opr>Av</opr> + </def> + <def> + <opc>eb</opc> + <opr>Jb</opr> + <mode>def64</mode> + </def> + </instruction> + + <instruction> + <mnemonic>lahf</mnemonic> + <def> + <opc>9f</opc> + </def> + </instruction> + + <instruction> + <mnemonic>lar</mnemonic> + <def> + <pfx>aso oso rexw rexr rexx rexb</pfx> + <opc>0f 02</opc> + <opr>Gv Ew</opr> + </def> + </instruction> + + <instruction> + <mnemonic>ldmxcsr</mnemonic> + <def> + <pfx>aso rexw rexr rexx rexb</pfx> + <opc>0f ae /reg=2 /mod=!11</opc> + <opr>Md</opr> + </def> + </instruction> + + <instruction> + <mnemonic>lds</mnemonic> + <def> + <pfx>aso oso</pfx> + <opc>c5 /vex=none /m=!64</opc> + <opr>Gv M</opr> + </def> + </instruction> + + <instruction> + <mnemonic>lea</mnemonic> + <def> + <pfx>aso oso rexw rexr rexx rexb</pfx> + <opc>8d</opc> + <opr>Gv M</opr> + </def> + </instruction> + + <instruction> + <mnemonic>les</mnemonic> + <def> + <pfx>aso oso</pfx> + <opc>c4 /m=!64</opc> + <opr>Gv M</opr> + </def> + </instruction> + + <instruction> + <mnemonic>lfs</mnemonic> + <def> + <pfx>aso oso rexw rexr rexx rexb</pfx> + <opc>0f b4</opc> + <opr>Gz M</opr> + </def> + </instruction> + + <instruction> + <mnemonic>lgs</mnemonic> + <def> + <pfx>aso oso rexw rexr rexx rexb</pfx> + <opc>0f b5</opc> + <opr>Gz M</opr> + </def> + </instruction> + + <instruction> + <mnemonic>lidt</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>0f 01 /reg=3 /mod=!11</opc> + <opr>M</opr> + </def> + </instruction> + + <instruction> + <mnemonic>lss</mnemonic> + <def> + <pfx>aso oso rexw rexr rexx rexb</pfx> + <opc>0f b2</opc> + <opr>Gv M</opr> + </def> + </instruction> + + <instruction> + <mnemonic>leave</mnemonic> + <def> + <opc>c9</opc> + </def> + </instruction> + + <instruction> + <mnemonic>lfence</mnemonic> + <def> + <opc>0f ae /reg=5 /mod=11 /rm=0</opc> + </def> + <def> + <opc>0f ae /reg=5 /mod=11 /rm=1</opc> + </def> + <def> + <opc>0f ae /reg=5 /mod=11 /rm=2</opc> + </def> + <def> + <opc>0f ae /reg=5 /mod=11 /rm=3</opc> + </def> + <def> + <opc>0f ae /reg=5 /mod=11 /rm=4</opc> + </def> + <def> + <opc>0f ae /reg=5 /mod=11 /rm=5</opc> + </def> + <def> + <opc>0f ae /reg=5 /mod=11 /rm=6</opc> + </def> + <def> + <opc>0f ae /reg=5 /mod=11 /rm=7</opc> + </def> + </instruction> + + <instruction> + <mnemonic>lgdt</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>0f 01 /reg=2 /mod=!11</opc> + <opr>M</opr> + </def> + </instruction> + + <instruction> + <mnemonic>lldt</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>0f 00 /reg=2</opc> + <opr>Ew</opr> + </def> + </instruction> + + <instruction> + <mnemonic>lmsw</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>0f 01 /reg=6 /mod=!11</opc> + <opr>Ew</opr> + </def> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>0f 01 /reg=6 /mod=11</opc> + <opr>Ew</opr> + </def> + </instruction> + + <instruction> + <mnemonic>lock</mnemonic> + <def> + <opc>f0</opc> + </def> + </instruction> + + <instruction> + <mnemonic>lodsb</mnemonic> + <def> + <pfx>rep seg</pfx> + <opc>ac</opc> + </def> + </instruction> + + <instruction> + <mnemonic>lodsw</mnemonic> + <def> + <pfx>rep seg oso rexw</pfx> + <opc>ad /o=16</opc> + </def> + </instruction> + + <instruction> + <mnemonic>lodsd</mnemonic> + <def> + <pfx>rep seg oso rexw</pfx> + <opc>ad /o=32</opc> + </def> + </instruction> + + <instruction> + <mnemonic>lodsq</mnemonic> + <def> + <pfx>rep seg oso rexw</pfx> + <opc>ad /o=64</opc> + </def> + </instruction> + + <instruction> + <mnemonic>loopne</mnemonic> + <def> + <opc>e0</opc> + <opr>Jb</opr> + </def> + </instruction> + + <instruction> + <mnemonic>loope</mnemonic> + <def> + <opc>e1</opc> + <opr>Jb</opr> + </def> + </instruction> + + <instruction> + <mnemonic>loop</mnemonic> + <def> + <opc>e2</opc> + <opr>Jb</opr> + </def> + </instruction> + + <instruction> + <mnemonic>lsl</mnemonic> + <def> + <pfx>aso oso rexw rexr rexx rexb</pfx> + <opc>0f 03</opc> + <opr>Gv Ew</opr> + </def> + </instruction> + + <instruction> + <mnemonic>ltr</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>0f 00 /reg=3</opc> + <opr>Ew</opr> + </def> + </instruction> + + <instruction> + <mnemonic>maskmovq</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>0f f7 /mod=11</opc> + <opr>P N</opr> + </def> + </instruction> + + <instruction> + <mnemonic>maxpd</mnemonic> + <def> + <pfx>aso rexr rexx rexb vexl</pfx> + <opc>/sse=66 0f 5f</opc> + <opr>V H W</opr> + <cpuid>sse2 avx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>maxps</mnemonic> + <def> + <pfx>aso rexr rexx rexb vexl</pfx> + <opc>0f 5f</opc> + <opr>V H W</opr> + <cpuid>sse avx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>maxsd</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>/sse=f2 0f 5f</opc> + <opr>V H W</opr> + <cpuid>sse2 avx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>maxss</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>/sse=f3 0f 5f</opc> + <opr>V H W</opr> + <cpuid>sse avx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>mfence</mnemonic> + <def> + <opc>0f ae /reg=6 /mod=11 /rm=0</opc> + </def> + <def> + <opc>0f ae /reg=6 /mod=11 /rm=1</opc> + </def> + <def> + <opc>0f ae /reg=6 /mod=11 /rm=2</opc> + </def> + <def> + <opc>0f ae /reg=6 /mod=11 /rm=3</opc> + </def> + <def> + <opc>0f ae /reg=6 /mod=11 /rm=4</opc> + </def> + <def> + <opc>0f ae /reg=6 /mod=11 /rm=5</opc> + </def> + <def> + <opc>0f ae /reg=6 /mod=11 /rm=6</opc> + </def> + <def> + <opc>0f ae /reg=6 /mod=11 /rm=7</opc> + </def> + </instruction> + + <instruction> + <mnemonic>minpd</mnemonic> + <def> + <pfx>aso rexr rexx rexb vexl</pfx> + <opc>/sse=66 0f 5d</opc> + <opr>V H W</opr> + <cpuid>sse2 avx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>minps</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>0f 5d</opc> + <opr>V H W</opr> + <cpuid>sse2 avx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>minsd</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>/sse=f2 0f 5d</opc> + <opr>V H MqU</opr> + <cpuid>sse2 avx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>minss</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>/sse=f3 0f 5d</opc> + <opr>V H MdU</opr> + <cpuid>sse avx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>monitor</mnemonic> + <def> + <opc>0f 01 /reg=1 /mod=11 /rm=0</opc> + </def> + </instruction> + + <instruction> + <mnemonic>montmul</mnemonic> + <def> + <opc>0f a6 /mod=11 /rm=0 /reg=0</opc> + </def> + </instruction> + + <instruction> + <mnemonic>mov</mnemonic> + <def> + <pfx>aso rexw rexr rexx rexb</pfx> + <opc>c6 /reg=0</opc> + <opr>Eb Ib</opr> + </def> + <def> + <pfx>aso oso rexw rexr rexx rexb</pfx> + <opc>c7 /reg=0</opc> + <opr>Ev sIz</opr> + </def> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>88</opc> + <opr>Eb Gb</opr> + </def> + <def> + <pfx>aso oso rexw rexr rexx rexb</pfx> + <opc>89</opc> + <opr>Ev Gv</opr> + </def> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>8a</opc> + <opr>Gb Eb</opr> + </def> + <def> + <pfx>aso oso rexw rexr rexx rexb</pfx> + <opc>8b</opc> + <opr>Gv Ev</opr> + </def> + <def> + <pfx>aso oso rexw rexr rexx rexb</pfx> + <opc>8c</opc> + <opr>MwRv S</opr> + </def> + <def> + <pfx>aso oso rexw rexr rexx rexb</pfx> + <opc>8e</opc> + <opr>S MwRv</opr> + </def> + <def> + <opc>a0</opc> + <opr>AL Ob</opr> + </def> + <def> + <pfx>aso oso rexw</pfx> + <opc>a1</opc> + <opr>rAX Ov</opr> + </def> + <def> + <opc>a2</opc> + <opr>Ob AL</opr> + </def> + <def> + <pfx>aso oso rexw</pfx> + <opc>a3</opc> + <opr>Ov rAX</opr> + </def> + <def> + <pfx>rexb</pfx> + <opc>b0</opc> + <opr>R0b Ib</opr> + </def> + <def> + <pfx>rexb</pfx> + <opc>b1</opc> + <opr>R1b Ib</opr> + </def> + <def> + <pfx>rexb</pfx> + <opc>b2</opc> + <opr>R2b Ib</opr> + </def> + <def> + <pfx>rexb</pfx> + <opc>b3</opc> + <opr>R3b Ib</opr> + </def> + <def> + <pfx>rexb</pfx> + <opc>b4</opc> + <opr>R4b Ib</opr> + </def> + <def> + <pfx>rexb</pfx> + <opc>b5</opc> + <opr>R5b Ib</opr> + </def> + <def> + <pfx>rexb</pfx> + <opc>b6</opc> + <opr>R6b Ib</opr> + </def> + <def> + <pfx>rexb</pfx> + <opc>b7</opc> + <opr>R7b Ib</opr> + </def> + <def> + <pfx>oso rexw rexb</pfx> + <opc>b8</opc> + <opr>R0v Iv</opr> + </def> + <def> + <pfx>oso rexw rexb</pfx> + <opc>b9</opc> + <opr>R1v Iv</opr> + </def> + <def> + <pfx>oso rexw rexb</pfx> + <opc>ba</opc> + <opr>R2v Iv</opr> + </def> + <def> + <pfx>oso rexw rexb</pfx> + <opc>bb</opc> + <opr>R3v Iv</opr> + </def> + <def> + <pfx>oso rexw rexb</pfx> + <opc>bc</opc> + <opr>R4v Iv</opr> + </def> + <def> + <pfx>oso rexw rexb</pfx> + <opc>bd</opc> + <opr>R5v Iv</opr> + </def> + <def> + <pfx>oso rexw rexb</pfx> + <opc>be</opc> + <opr>R6v Iv</opr> + </def> + <def> + <pfx>oso rexw rexb</pfx> + <opc>bf</opc> + <opr>R7v Iv</opr> + </def> + <def> + <pfx>rexr rexw rexb</pfx> + <opc>0f 20</opc> + <opr>R C</opr> + </def> + <def> + <pfx>rexr rexw rexb</pfx> + <opc>0f 21</opc> + <opr>R D</opr> + </def> + <def> + <pfx>rexr rexw rexb</pfx> + <opc>0f 22</opc> + <opr>C R</opr> + </def> + <def> + <pfx>rexr rexw rexb</pfx> + <opc>0f 23</opc> + <opr>D R</opr> + </def> + </instruction> + + <instruction> + <mnemonic>movapd</mnemonic> + <def> + <pfx>aso rexr rexx rexb vexl</pfx> + <opc>/sse=66 0f 28</opc> + <opr>V W</opr> + <cpuid>sse2 avx</cpuid> + </def> + <def> + <pfx>aso rexr rexx rexb vexl</pfx> + <opc>/sse=66 0f 29</opc> + <opr>W V</opr> + <cpuid>sse2 avx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>movaps</mnemonic> + <def> + <pfx>aso rexr rexx rexb vexl</pfx> + <opc>0f 28</opc> + <opr>V W</opr> + <cpuid>sse avx</cpuid> + </def> + <def> + <pfx>aso rexr rexx rexb vexl</pfx> + <opc>0f 29</opc> + <opr>W V</opr> + <cpuid>sse avx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>movd</mnemonic> + <def> + <pfx>aso rexw rexr rexx rexb</pfx> + <opc>0f 6e /o=16</opc> + <opr>P Ey</opr> + <cpuid>mmx</cpuid> + </def> + <def> + <pfx>aso rexw rexr rexx rexb</pfx> + <opc>0f 6e /o=32</opc> + <opr>P Ey</opr> + <cpuid>mmx</cpuid> + </def> + + <def> + <pfx>aso rexw rexr rexx rexb</pfx> + <opc>/sse=66 0f 6e /o=16</opc> + <opr>V Ey</opr> + <cpuid>sse2 avx</cpuid> + </def> + <def> + <pfx>aso rexw rexr rexx rexb</pfx> + <opc>/sse=66 0f 6e /o=32</opc> + <opr>V Ey</opr> + <cpuid>sse2 avx</cpuid> + </def> + <def> + <pfx>aso rexw rexr rexx rexb</pfx> + <opc>0f 7e /o=16</opc> + <opr>Ey P</opr> + <cpuid>mmx</cpuid> + </def> + <def> + <pfx>aso rexw rexr rexx rexb</pfx> + <opc>0f 7e /o=32</opc> + <opr>Ey P</opr> + <cpuid>mmx</cpuid> + </def> + <def> + <pfx>aso rexw rexr rexx rexb</pfx> + <opc>/sse=66 0f 7e /o=16</opc> + <opr>Ey V</opr> + <cpuid>sse2 avx</cpuid> + </def> + <def> + <pfx>aso rexw rexr rexx rexb</pfx> + <opc>/sse=66 0f 7e /o=32</opc> + <opr>Ey V</opr> + <cpuid>sse2 avx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>movhpd</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>/sse=66 0f 16 /mod=!11</opc> + <opr>V H M</opr> + <cpuid>sse2 avx</cpuid> + </def> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>/sse=66 0f 17</opc> + <opr>M V</opr> + <cpuid>sse2 avx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>movhps</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>0f 16 /mod=!11</opc> + <opr>V H M</opr> + <cpuid>sse avx</cpuid> + </def> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>0f 17</opc> + <opr>M V</opr> + <cpuid>sse avx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>movlhps</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>0f 16 /mod=11</opc> + <opr>V H U</opr> + <cpuid>sse avx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>movlpd</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>/sse=66 0f 12 /mod=!11</opc> + <opr>V M</opr> + </def> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>/sse=66 0f 13</opc> + <opr>M V</opr> + </def> + <cpuid>sse2 avx</cpuid> + </instruction> + + <instruction> + <mnemonic>movlps</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>0f 12 /mod=!11</opc> + <opr>V M</opr> + </def> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>0f 13</opc> + <opr>M V</opr> + </def> + <cpuid>sse avx</cpuid> + </instruction> + + <instruction> + <mnemonic>movhlps</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>0f 12 /mod=11</opc> + <opr>V U</opr> + <cpuid>sse avx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>movmskpd</mnemonic> + <def> + <pfx>oso rexr rexb vexl</pfx> + <opc>/sse=66 0f 50</opc> + <opr>Gd U</opr> + <cpuid>sse2 avx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>movmskps</mnemonic> + <def> + <pfx>oso rexr rexb</pfx> + <opc>0f 50</opc> + <opr>Gd U</opr> + <cpuid>sse2 avx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>movntdq</mnemonic> + <def> + <pfx>aso rexr rexx rexb vexl</pfx> + <opc>/sse=66 0f e7</opc> + <opr>M V</opr> + <cpuid>sse2 avx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>movnti</mnemonic> + <def> + <pfx>aso rexw rexr rexx rexb</pfx> + <opc>0f c3</opc> + <opr>M Gy</opr> + </def> + </instruction> + + <instruction> + <mnemonic>movntpd</mnemonic> + <def> + <pfx>aso rexr rexx rexb vexl</pfx> + <opc>/sse=66 0f 2b</opc> + <opr>M V</opr> + <cpuid>sse2 avx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>movntps</mnemonic> + <def> + <pfx>aso rexr rexx rexb vexl</pfx> + <opc>0f 2b</opc> + <opr>M V</opr> + <cpuid>sse2 avx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>movntq</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>0f e7</opc> + <opr>M P</opr> + </def> + </instruction> + + <instruction> + <mnemonic>movq</mnemonic> + <def> + <pfx>aso rexw rexr rexx rexb</pfx> + <opc>0f 6e /o=64</opc> + <opr>P Eq</opr> + <cpuid>mmx</cpuid> + </def> + <def> + <pfx>aso rexw rexr rexx rexb</pfx> + <opc>/sse=66 0f 6e /o=64</opc> + <opr>V Eq</opr> + <cpuid>sse2 avx</cpuid> + </def> + <def> + <pfx>aso rexw rexr rexx rexb</pfx> + <opc>0f 7e /o=64</opc> + <opr>Eq P</opr> + <cpuid>mmx</cpuid> + </def> + <def> + <pfx>aso rexw rexr rexx rexb</pfx> + <opc>/sse=66 0f 7e /o=64</opc> + <opr>Eq V</opr> + <cpuid>sse2 avx</cpuid> + </def> + <def> + <pfx>aso rexw rexr rexx rexb</pfx> + <opc>/sse=f3 0f 7e</opc> + <opr>V W</opr> + <cpuid>sse2 avx</cpuid> + </def> + <def> + <pfx>aso rexw rexr rexx rexb</pfx> + <opc>/sse=66 0f d6</opc> + <opr>W V</opr> + <cpuid>sse2 avx</cpuid> + </def> + <def> + <pfx>aso rexw rexr rexx rexb</pfx> + <opc>0f 6f</opc> + <opr>P Q</opr> + <cpuid>mmx</cpuid> + </def> + <def> + <pfx>aso rexw rexr rexx rexb</pfx> + <opc>0f 7f</opc> + <opr>Q P</opr> + <cpuid>mmx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>movsb</mnemonic> + <def> + <pfx>rep seg</pfx> + <opc>a4</opc> + </def> + </instruction> + + <instruction> + <mnemonic>movsw</mnemonic> + <def> + <pfx>rep seg oso rexw</pfx> + <opc>a5 /o=16</opc> + </def> + </instruction> + + <instruction> + <mnemonic>movsd</mnemonic> + <def> + <pfx>rep seg oso rexw</pfx> + <opc>a5 /o=32</opc> + </def> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>/sse=f2 0f 10</opc> + <opr>V MqU</opr> + <cpuid>sse2</cpuid> + </def> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>/sse=f2 0f 11</opc> + <opr>W V</opr> + <cpuid>sse2</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>movsq</mnemonic> + <def> + <pfx>rep seg oso rexw</pfx> + <opc>a5 /o=64</opc> + </def> + </instruction> + + <instruction> + <mnemonic>movss</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>/sse=f3 0f 10</opc> + <opr>V MdU</opr> + <cpuid>sse</cpuid> + </def> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>/sse=f3 0f 11</opc> + <opr>W V</opr> + <cpuid>sse</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>movsx</mnemonic> + <def> + <pfx>aso oso rexw rexr rexx rexb</pfx> + <opc>0f be</opc> + <opr>Gv Eb</opr> + </def> + <def> + <pfx>aso oso rexw rexr rexx rexb</pfx> + <opc>0f bf</opc> + <opr>Gy Ew</opr> + </def> + </instruction> + + <instruction> + <mnemonic>movupd</mnemonic> + <def> + <pfx>aso rexr rexx rexb vexl</pfx> + <opc>/sse=66 0f 10</opc> + <opr>V W</opr> + <cpuid>sse2 avx</cpuid> + </def> + <def> + <pfx>aso rexr rexx rexb vexl</pfx> + <opc>/sse=66 0f 11</opc> + <opr>W V</opr> + <cpuid>sse2 avx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>movups</mnemonic> + <def> + <pfx>aso rexr rexx rexb vexl</pfx> + <opc>0f 10</opc> + <opr>V W</opr> + <cpuid>sse2 avx</cpuid> + </def> + <def> + <pfx>aso rexr rexx rexb vexl</pfx> + <opc>0f 11</opc> + <opr>W V</opr> + <cpuid>sse2 avx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>movzx</mnemonic> + <def> + <pfx>aso oso rexw rexr rexx rexb</pfx> + <opc>0f b6</opc> + <opr>Gv Eb</opr> + </def> + <def> + <pfx>aso oso rexw rexr rexx rexb</pfx> + <opc>0f b7</opc> + <opr>Gy Ew</opr> + </def> + </instruction> + + <instruction> + <mnemonic>mul</mnemonic> + <def> + <pfx>aso rexw rexr rexx rexb</pfx> + <opc>f6 /reg=4</opc> + <opr>Eb</opr> + </def> + <def> + <pfx>aso oso rexw rexr rexx rexb</pfx> + <opc>f7 /reg=4</opc> + <opr>Ev</opr> + </def> + </instruction> + + <instruction> + <mnemonic>mulpd</mnemonic> + <def> + <pfx>aso rexr rexx rexb vexl</pfx> + <opc>/sse=66 0f 59</opc> + <opr>V H W</opr> + <cpuid>sse2 avx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>mulps</mnemonic> + <def> + <pfx>aso rexr rexx rexb vexl</pfx> + <opc>0f 59</opc> + <opr>V H W</opr> + <cpuid>sse2 avx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>mulsd</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>/sse=f2 0f 59</opc> + <opr>V H W</opr> + <cpuid>sse2 avx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>mulss</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>/sse=f3 0f 59</opc> + <opr>V H W</opr> + <cpuid>sse avx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>mwait</mnemonic> + <def> + <opc>0f 01 /reg=1 /mod=11 /rm=1</opc> + </def> + </instruction> + + <instruction> + <mnemonic>neg</mnemonic> + <def> + <pfx>aso rexw rexr rexx rexb</pfx> + <opc>f6 /reg=3</opc> + <opr>Eb</opr> + </def> + <def> + <pfx>aso oso rexw rexr rexx rexb</pfx> + <opc>f7 /reg=3</opc> + <opr>Ev</opr> + </def> + </instruction> + + <instruction> + <mnemonic>nop</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>0f 19</opc> + <opr>M</opr> + </def> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>0f 1a</opc> + <opr>M</opr> + </def> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>0f 1b</opc> + <opr>M</opr> + </def> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>0f 1c</opc> + <opr>M</opr> + </def> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>0f 1d</opc> + <opr>M</opr> + </def> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>0f 1e</opc> + <opr>M</opr> + </def> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>0f 1f</opc> + <opr>M</opr> + </def> + </instruction> + + <instruction> + <mnemonic>not</mnemonic> + <def> + <pfx>aso rexw rexr rexx rexb</pfx> + <opc>f6 /reg=2</opc> + <opr>Eb</opr> + </def> + <def> + <pfx>aso oso rexw rexr rexx rexb</pfx> + <opc>f7 /reg=2</opc> + <opr>Ev</opr> + </def> + </instruction> + + <instruction> + <mnemonic>or</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>08</opc> + <opr>Eb Gb</opr> + </def> + <def> + <pfx>aso oso rexw rexr rexx rexb</pfx> + <opc>09</opc> + <opr>Ev Gv</opr> + </def> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>0a</opc> + <opr>Gb Eb</opr> + </def> + <def> + <pfx>aso oso rexw rexr rexx rexb</pfx> + <opc>0b</opc> + <opr>Gv Ev</opr> + </def> + <def> + <opc>0c</opc> + <opr>AL Ib</opr> + </def> + <def> + <pfx>oso rexw</pfx> + <opc>0d</opc> + <opr>rAX sIz</opr> + </def> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>80 /reg=1</opc> + <opr>Eb Ib</opr> + </def> + <def> + <pfx>aso oso rexw rexr rexx rexb</pfx> + <opc>81 /reg=1</opc> + <opr>Ev sIz</opr> + </def> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>82 /reg=1 /m=!64</opc> + <opr>Eb Ib</opr> + </def> + <def> + <pfx>aso oso rexw rexr rexx rexb</pfx> + <opc>83 /reg=1</opc> + <opr>Ev sIb</opr> + </def> + </instruction> + + <instruction> + <mnemonic>orpd</mnemonic> + <def> + <pfx>aso rexr rexx rexb vexl</pfx> + <opc>/sse=66 0f 56</opc> + <opr>V H W</opr> + <cpuid>sse2 avx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>orps</mnemonic> + <def> + <pfx>aso rexr rexx rexb vexl</pfx> + <opc>0f 56</opc> + <opr>V H W</opr> + <cpuid>sse avx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>out</mnemonic> + <def> + <opc>e6</opc> + <opr>Ib AL</opr> + </def> + <def> + <pfx>oso</pfx> + <opc>e7</opc> + <opr>Ib eAX</opr> + </def> + <def> + <opc>ee</opc> + <opr>DX AL</opr> + </def> + <def> + <pfx>oso</pfx> + <opc>ef</opc> + <opr>DX eAX</opr> + </def> + </instruction> + + <instruction> + <mnemonic>outsb</mnemonic> + <def> + <pfx>rep seg</pfx> + <opc>6e</opc> + </def> + </instruction> + + <instruction> + <mnemonic>outsw</mnemonic> + <def> + <pfx>rep oso seg</pfx> + <opc>6f /o=16</opc> + </def> + </instruction> + + <instruction> + <mnemonic>outsd</mnemonic> + <def> + <pfx>rep oso seg</pfx> + <opc>6f /o=32</opc> + </def> + </instruction> + + <instruction> + <mnemonic>packsswb</mnemonic> + <def> + <pfx>aso rexr rexx rexb vexl</pfx> + <opc>/sse=66 0f 63</opc> + <opr>V H W</opr> + <cpuid>sse2 avx</cpuid> + </def> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>0f 63</opc> + <opr>P Q</opr> + <cpuid>mmx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>packssdw</mnemonic> + <def> + <pfx>aso rexr rexx rexb vexl</pfx> + <opc>/sse=66 0f 6b</opc> + <opr>V H W</opr> + <cpuid>sse2 avx</cpuid> + </def> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>0f 6b</opc> + <opr>P Q</opr> + <cpuid>mmx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>packuswb</mnemonic> + <def> + <pfx>aso rexr rexx rexb vexl</pfx> + <opc>/sse=66 0f 67</opc> + <opr>V H W</opr> + <cpuid>sse2 avx</cpuid> + </def> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>0f 67</opc> + <opr>P Q</opr> + <cpuid>mmx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>paddb</mnemonic> + <def> + <pfx>aso rexr rexx rexb vexl</pfx> + <opc>/sse=66 0f fc</opc> + <opr>V H W</opr> + <cpuid>sse2 avx</cpuid> + </def> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>0f fc</opc> + <opr>P Q</opr> + <cpuid>mmx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>paddw</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>0f fd</opc> + <opr>P Q</opr> + <cpuid>mmx</cpuid> + </def> + <def> + <pfx>aso rexr rexx rexb vexl</pfx> + <opc>/sse=66 0f fd</opc> + <opr>V H W</opr> + <cpuid>sse2 avx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>paddd</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>0f fe</opc> + <opr>P Q</opr> + <cpuid>mmx</cpuid> + </def> + <def> + <pfx>aso rexr rexx rexb vexl</pfx> + <opc>/sse=66 0f fe</opc> + <opr>V H W</opr> + <cpuid>sse2 avx</cpuid> + </def> + </instruction> + + + <instruction> + <mnemonic>paddsb</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>0f ec</opc> + <opr>P Q</opr> + </def> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>/sse=66 0f ec</opc> + <opr>V H W</opr> + <cpuid>sse2 avx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>paddsw</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>0f ed</opc> + <opr>P Q</opr> + </def> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>/sse=66 0f ed</opc> + <opr>V H W</opr> + <cpuid>sse2 avx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>paddusb</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>0f dc</opc> + <opr>P Q</opr> + </def> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>/sse=66 0f dc</opc> + <opr>V H W</opr> + <cpuid>sse2 avx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>paddusw</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>0f dd</opc> + <opr>P Q</opr> + </def> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>/sse=66 0f dd</opc> + <opr>V H W</opr> + <cpuid>sse2 avx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>pand</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>/sse=66 0f db</opc> + <opr>V H W</opr> + <cpuid>sse2 avx</cpuid> + </def> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>0f db</opc> + <opr>P Q</opr> + </def> + </instruction> + + <instruction> + <mnemonic>pandn</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>/sse=66 0f df</opc> + <opr>V H W</opr> + <cpuid>sse2 avx</cpuid> + </def> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>0f df</opc> + <opr>P Q</opr> + </def> + </instruction> + + <instruction> + <mnemonic>pavgb</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>/sse=66 0f e0</opc> + <opr>V H W</opr> + <cpuid>sse2 avx</cpuid> + </def> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>0f e0</opc> + <opr>P Q</opr> + </def> + </instruction> + + <instruction> + <mnemonic>pavgw</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>/sse=66 0f e3</opc> + <opr>V H W</opr> + <cpuid>sse2 avx</cpuid> + </def> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>0f e3</opc> + <opr>P Q</opr> + </def> + </instruction> + + <instruction> + <mnemonic>pcmpeqb</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>0f 74</opc> + <opr>P Q</opr> + </def> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>/sse=66 0f 74</opc> + <opr>V H W</opr> + <cpuid>sse2 avx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>pcmpeqw</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>0f 75</opc> + <opr>P Q</opr> + </def> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>/sse=66 0f 75</opc> + <opr>V H W</opr> + <cpuid>sse2 avx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>pcmpeqd</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>0f 76</opc> + <opr>P Q</opr> + </def> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>/sse=66 0f 76</opc> + <opr>V H W</opr> + <cpuid>sse2 avx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>pcmpgtb</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>/sse=66 0f 64</opc> + <opr>V H W</opr> + <cpuid>sse2 avx</cpuid> + </def> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>0f 64</opc> + <opr>P Q</opr> + </def> + </instruction> + + <instruction> + <mnemonic>pcmpgtw</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>/sse=66 0f 65</opc> + <opr>V H W</opr> + <cpuid>sse2 avx</cpuid> + </def> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>0f 65</opc> + <opr>P Q</opr> + </def> + </instruction> + + <instruction> + <mnemonic>pcmpgtd</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>/sse=66 0f 66</opc> + <opr>V H W</opr> + <cpuid>sse2 avx</cpuid> + </def> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>0f 66</opc> + <opr>P Q</opr> + </def> + </instruction> + + <instruction> + <mnemonic>pextrb</mnemonic> + <def> + <pfx>aso rexx rexr rexb</pfx> + <opc>/sse=66 0f 3a 14 /vexw=0</opc> + <opr>MbRv V Ib</opr> + <mode>def64</mode> + <cpuid>sse4.1 avx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>pextrd</mnemonic> + <def> + <pfx>aso rexr rexx rexw rexb</pfx> + <opc>/sse=66 0f 3a 16 /o=16 /vexw=0</opc> + <opr>Ed V Ib</opr> + <cpuid>sse4.1 avx</cpuid> + </def> + <def> + <pfx>aso rexr rexx rexw rexb</pfx> + <opc>/sse=66 0f 3a 16 /o=32 /vexw=0</opc> + <opr>Ed V Ib</opr> + <cpuid>sse4.1 avx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>pextrq</mnemonic> + <def> + <pfx>aso rexr rexw rexb</pfx> + <opc>/sse=66 0f 3a 16 /o=64 /vexw=1</opc> + <opr>Eq V Ib</opr> + <mode>def64</mode> + <cpuid>sse4.1 avx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>pextrw</mnemonic> + <def> + <pfx>aso rexw rexr rexb</pfx> + <opc>/sse=66 0f c5</opc> + <opr>Gd U Ib</opr> + <cpuid>sse avx</cpuid> + </def> + <def> + <pfx>aso rexw rexr rexx rexb</pfx> + <opc>0f c5</opc> + <opr>Gd N Ib</opr> + </def> + <def> + <pfx>aso rexw rexx rexr rexb</pfx> + <opc>/sse=66 0f 3a 15</opc> + <opr>MwRd V Ib</opr> + <cpuid>sse4.1 avx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>pinsrb</mnemonic> + <def> + <pfx>aso rexw rexr rexx rexb</pfx> + <opc>/sse=66 0f 3a 20</opc> + <opr>V MbRd Ib</opr> + <cpuid>sse4.1</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>pinsrw</mnemonic> + <def> + <pfx>aso rexw rexr rexx rexb</pfx> + <opc>0f c4</opc> + <opr>P MwRy Ib</opr> + <mode>def64</mode> + </def> + <def> + <pfx>aso rexw rexr rexx rexb</pfx> + <opc>/sse=66 0f c4</opc> + <opr>V MwRy Ib</opr> + <mode>def64</mode> + <cpuid>sse2 avx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>pinsrd</mnemonic> + <def> + <pfx>aso rexw rexr rexx rexb</pfx> + <opc>/sse=66 0f 3a 22 /o=16</opc> + <opr>V Ed Ib</opr> + <cpuid>sse4.1</cpuid> + </def> + + <def> + <pfx>aso rexw rexr rexx rexb</pfx> + <opc>/sse=66 0f 3a 22 /o=32</opc> + <opr>V Ed Ib</opr> + <cpuid>sse4.1</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>pinsrq</mnemonic> + <def> + <pfx>aso oso rexw rexr rexx rexb</pfx> + <opc>/sse=66 0f 3a 22 /o=64</opc> + <opr>V Eq Ib</opr> + <cpuid>sse4.1</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>vpinsrb</mnemonic> + <def> + <pfx>aso rexw rexr rexx rexb</pfx> + <opc>/vex=66_0f3a 20 /vexw=0 /vexl=0</opc> + <opr>V H MbRd Ib</opr> + <cpuid>avx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>vpinsrd</mnemonic> + <def> + <pfx>aso oso rexw rexr rexx rexb</pfx> + <opc>/vex=66_0f3a 22 /m=!64 /vexw=0 /vexl=0</opc> + <opr>V H Ed Ib</opr> + <cpuid>avx</cpuid> + </def> + <def> + <pfx>aso oso rexw rexr rexx rexb</pfx> + <opc>/vex=66_0f3a 22 /m=64 /vexw=0 /vexl=0</opc> + <opr>V H Ed Ib</opr> + <cpuid>avx</cpuid> + </def> + </instruction> + + + <instruction> + <mnemonic>vpinsrq</mnemonic> + <def> + <pfx>aso oso rexw rexr rexx rexb</pfx> + <opc>/vex=66_0f3a 22 /m=64 /vexw=1 /vexl=0</opc> + <opr>V H Eq Ib</opr> + <cpuid>avx</cpuid> + </def> + </instruction> + + + <instruction> + <mnemonic>pmaddwd</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>0f f5</opc> + <opr>P Q</opr> + </def> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>/sse=66 0f f5</opc> + <opr>V H W</opr> + <cpuid>sse4.1 avx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>pmaxsw</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>/sse=66 0f ee</opc> + <opr>V H W</opr> + <cpuid>sse4.1 avx</cpuid> + </def> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>0f ee</opc> + <opr>P Q</opr> + </def> + </instruction> + + <instruction> + <mnemonic>pmaxub</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>0f de</opc> + <opr>P Q</opr> + </def> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>/sse=66 0f de</opc> + <opr>V H W</opr> + <cpuid>sse2 avx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>pminsw</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>/sse=66 0f ea</opc> + <opr>V H W</opr> + <cpuid>sse2 avx</cpuid> + </def> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>0f ea</opc> + <opr>P Q</opr> + </def> + </instruction> + + <instruction> + <mnemonic>pminub</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>/sse=66 0f da</opc> + <opr>V H W</opr> + <cpuid>sse2 avx</cpuid> + </def> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>0f da</opc> + <opr>P Q</opr> + </def> + </instruction> + + <instruction> + <mnemonic>pmovmskb</mnemonic> + <def> + <pfx>oso rexr rexw rexb</pfx> + <opc>/sse=66 0f d7 /vexl=0</opc> + <opr>Gd U</opr> + <cpuid>sse2 avx</cpuid> + </def> + <def> + <pfx>oso rexr rexw rexb</pfx> + <opc>0f d7</opc> + <opr>Gd N</opr> + </def> + </instruction> + + <instruction> + <mnemonic>pmulhuw</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>0f e4</opc> + <opr>P Q</opr> + </def> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>/sse=66 0f e4</opc> + <opr>V H W</opr> + <cpuid>sse2 avx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>pmulhw</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>/sse=66 0f e5</opc> + <opr>V H W</opr> + <cpuid>sse2 avx</cpuid> + </def> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>0f e5</opc> + <opr>P Q</opr> + </def> + </instruction> + + <instruction> + <mnemonic>pmullw</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>0f d5</opc> + <opr>P Q</opr> + </def> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>/sse=66 0f d5</opc> + <opr>V H W</opr> + <cpuid>sse2 avx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>pop</mnemonic> + <def> + <opc>07 /m=!64</opc> + <opr>ES</opr> + <mode>inv64</mode> + </def> + <def> + <opc>17 /m=!64</opc> + <opr>SS</opr> + <mode>inv64</mode> + </def> + <def> + <opc>1f /m=!64</opc> + <opr>DS</opr> + <mode>inv64</mode> + </def> + <def> + <opc>0f a9</opc> + <opr>GS</opr> + </def> + <def> + <opc>0f a1</opc> + <opr>FS</opr> + </def> + <def> + <pfx>oso rexb</pfx> + <opc>58</opc> + <opr>R0v</opr> + <mode>def64</mode> + </def> + <def> + <pfx>oso rexb</pfx> + <opc>59</opc> + <opr>R1v</opr> + <mode>def64</mode> + </def> + <def> + <pfx>oso rexb</pfx> + <opc>5a</opc> + <opr>R2v</opr> + <mode>def64</mode> + </def> + <def> + <pfx>oso rexb</pfx> + <opc>5b</opc> + <opr>R3v</opr> + <mode>def64</mode> + </def> + <def> + <pfx>oso rexb</pfx> + <opc>5c</opc> + <opr>R4v</opr> + <mode>def64</mode> + </def> + <def> + <pfx>oso rexb</pfx> + <opc>5d</opc> + <opr>R5v</opr> + <mode>def64</mode> + </def> + <def> + <pfx>oso rexb</pfx> + <opc>5e</opc> + <opr>R6v</opr> + <mode>def64</mode> + </def> + <def> + <pfx>oso rexb</pfx> + <opc>5f</opc> + <opr>R7v</opr> + <mode>def64</mode> + </def> + <def> + <pfx>aso oso rexw rexr rexx rexb</pfx> + <opc>8f /reg=0</opc> + <opr>Ev</opr> + <mode>def64</mode> + </def> + </instruction> + + <instruction> + <mnemonic>popa</mnemonic> + <def> + <pfx>oso</pfx> + <opc>61 /o=16 /m=!64</opc> + <mode>inv64</mode> + </def> + </instruction> + + <instruction> + <mnemonic>popad</mnemonic> + <def> + <pfx>oso</pfx> + <opc>61 /o=32 /m=!64</opc> + <mode>inv64</mode> + </def> + </instruction> + + <instruction> + <mnemonic>popfw</mnemonic> + <def> + <pfx>oso</pfx> + <opc>9d /m=!64 /o=16</opc> + </def> + </instruction> + + <instruction> + <mnemonic>popfd</mnemonic> + <def> + <pfx>oso</pfx> + <opc>9d /m=!64 /o=32</opc> + </def> + </instruction> + + <instruction> + <mnemonic>popfq</mnemonic> + <def> + <pfx>oso</pfx> + <opc>9d /m=64 /o=32</opc> + <mode>def64</mode> + </def> + <def> + <pfx>oso</pfx> + <opc>9d /m=64 /o=64</opc> + <mode>def64</mode> + </def> + </instruction> + + <instruction> + <mnemonic>por</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>/sse=66 0f eb</opc> + <opr>V H W</opr> + <cpuid>sse2 avx</cpuid> + </def> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>0f eb</opc> + <opr>P Q</opr> + </def> + </instruction> + + <instruction> + <mnemonic>prefetch</mnemonic> + <def> + <pfx>aso rexw rexr rexx rexb</pfx> + <opc>0f 0d /reg=0</opc> + <opr>M</opr> + </def> + <def> + <pfx>aso rexw rexr rexx rexb</pfx> + <opc>0f 0d /reg=1</opc> + <opr>M</opr> + </def> + <def> + <pfx>aso rexw rexr rexx rexb</pfx> + <opc>0f 0d /reg=2</opc> + <opr>M</opr> + </def> + <def> + <pfx>aso rexw rexr rexx rexb</pfx> + <opc>0f 0d /reg=3</opc> + <opr>M</opr> + </def> + <def> + <pfx>aso rexw rexr rexx rexb</pfx> + <opc>0f 0d /reg=4</opc> + <opr>M</opr> + </def> + <def> + <pfx>aso rexw rexr rexx rexb</pfx> + <opc>0f 0d /reg=5</opc> + <opr>M</opr> + </def> + <def> + <pfx>aso rexw rexr rexx rexb</pfx> + <opc>0f 0d /reg=6</opc> + <opr>M</opr> + </def> + <def> + <pfx>aso rexw rexr rexx rexb</pfx> + <opc>0f 0d /reg=7</opc> + <opr>M</opr> + </def> + </instruction> + + <instruction> + <mnemonic>prefetchnta</mnemonic> + <def> + <pfx>aso rexw rexr rexx rexb</pfx> + <opc>0f 18 /reg=0</opc> + <opr>M</opr> + </def> + </instruction> + + <instruction> + <mnemonic>prefetcht0</mnemonic> + <def> + <pfx>aso rexw rexr rexx rexb</pfx> + <opc>0f 18 /reg=1</opc> + <opr>M</opr> + </def> + </instruction> + + <instruction> + <mnemonic>prefetcht1</mnemonic> + <def> + <pfx>aso rexw rexr rexx rexb</pfx> + <opc>0f 18 /reg=2</opc> + <opr>M</opr> + </def> + </instruction> + + <instruction> + <mnemonic>prefetcht2</mnemonic> + <def> + <pfx>aso rexw rexr rexx rexb</pfx> + <opc>0f 18 /reg=3</opc> + <opr>M</opr> + </def> + </instruction> + + <instruction> + <mnemonic>psadbw</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>/sse=66 0f f6</opc> + <opr>V H W</opr> + <cpuid>sse2 avx</cpuid> + </def> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>0f f6</opc> + <opr>P Q</opr> + </def> + </instruction> + + <instruction> + <mnemonic>pshufw</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>0f 70</opc> + <opr>P Q Ib</opr> + </def> + </instruction> + + <instruction> + <mnemonic>psllw</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>/sse=66 0f f1</opc> + <opr>V W</opr> + <cpuid>sse2</cpuid> + </def> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>0f f1</opc> + <opr>P Q</opr> + </def> + <def> + <pfx>rexb</pfx> + <opc>/sse=66 0f 71 /reg=6</opc> + <opr>U Ib</opr> + <cpuid>sse2</cpuid> + </def> + <def> + <opc>0f 71 /reg=6</opc> + <opr>N Ib</opr> + </def> + </instruction> + + <instruction> + <mnemonic>pslld</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>/sse=66 0f f2</opc> + <opr>V W</opr> + <cpuid>sse2</cpuid> + </def> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>0f f2</opc> + <opr>P Q</opr> + </def> + <def> + <pfx>rexb</pfx> + <opc>/sse=66 0f 72 /reg=6</opc> + <opr>U Ib</opr> + <cpuid>sse2</cpuid> + </def> + <def> + <opc>0f 72 /reg=6</opc> + <opr>N Ib</opr> + </def> + </instruction> + + <instruction> + <mnemonic>psllq</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>/sse=66 0f f3</opc> + <opr>V W</opr> + <cpuid>sse2</cpuid> + </def> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>0f f3</opc> + <opr>P Q</opr> + </def> + <def> + <pfx>rexb</pfx> + <opc>/sse=66 0f 73 /reg=6</opc> + <opr>U Ib</opr> + <cpuid>sse2</cpuid> + </def> + <def> + <opc>0f 73 /reg=6</opc> + <opr>N Ib</opr> + </def> + </instruction> + + <instruction> + <mnemonic>psraw</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>0f e1</opc> + <opr>P Q</opr> + </def> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>/sse=66 0f e1</opc> + <opr>V H W</opr> + <cpuid>sse2 avx</cpuid> + </def> + <def> + <pfx>rexb</pfx> + <opc>/sse=66 0f 71 /reg=4</opc> + <opr>H U Ib</opr> + <cpuid>sse2 avx</cpuid> + </def> + <def> + <opc>0f 71 /reg=4</opc> + <opr>N Ib</opr> + </def> + </instruction> + + <instruction> + <mnemonic>psrad</mnemonic> + <def> + <opc>0f 72 /reg=4</opc> + <opr>N Ib</opr> + </def> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>/sse=66 0f e2</opc> + <opr>V H W</opr> + <cpuid>sse2 avx</cpuid> + </def> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>0f e2</opc> + <opr>P Q</opr> + </def> + <def> + <pfx>rexb</pfx> + <opc>/sse=66 0f 72 /reg=4</opc> + <opr>H U Ib</opr> + <cpuid>sse2 avx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>psrlw</mnemonic> + <def> + <opc>0f 71 /reg=2</opc> + <opr>N Ib</opr> + </def> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>0f d1</opc> + <opr>P Q</opr> + </def> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>/sse=66 0f d1</opc> + <opr>V H W</opr> + <cpuid>sse2 avx</cpuid> + </def> + <def> + <pfx>rexb</pfx> + <opc>/sse=66 0f 71 /reg=2</opc> + <opr>H U Ib</opr> + <cpuid>sse2 avx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>psrld</mnemonic> + <def> + <opc>0f 72 /reg=2</opc> + <opr>N Ib</opr> + </def> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>0f d2</opc> + <opr>P Q</opr> + </def> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>/sse=66 0f d2</opc> + <opr>V H W</opr> + <cpuid>sse2 avx</cpuid> + </def> + <def> + <pfx>rexb</pfx> + <opc>/sse=66 0f 72 /reg=2</opc> + <opr>H U Ib</opr> + <cpuid>sse2 avx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>psrlq</mnemonic> + <def> + <opc>0f 73 /reg=2</opc> + <opr>N Ib</opr> + </def> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>0f d3</opc> + <opr>P Q</opr> + </def> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>/sse=66 0f d3</opc> + <opr>V H W</opr> + <cpuid>sse2 avx</cpuid> + </def> + <def> + <pfx>rexb</pfx> + <opc>/sse=66 0f 73 /reg=2</opc> + <opr>H U Ib</opr> + <cpuid>sse2 avx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>psubb</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>/sse=66 0f f8</opc> + <opr>V H W</opr> + <cpuid>sse2 avx</cpuid> + </def> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>0f f8</opc> + <opr>P Q</opr> + </def> + </instruction> + + <instruction> + <mnemonic>psubw</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>/sse=66 0f f9</opc> + <opr>V H W</opr> + <cpuid>sse2 avx</cpuid> + </def> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>0f f9</opc> + <opr>P Q</opr> + </def> + </instruction> + + <instruction> + <mnemonic>psubd</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>0f fa</opc> + <opr>P Q</opr> + </def> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>/sse=66 0f fa</opc> + <opr>V H W</opr> + <cpuid>sse2 avx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>psubsb</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>0f e8</opc> + <opr>P Q</opr> + </def> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>/sse=66 0f e8</opc> + <opr>V H W</opr> + <cpuid>sse2 avx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>psubsw</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>0f e9</opc> + <opr>P Q</opr> + </def> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>/sse=66 0f e9</opc> + <opr>V H W</opr> + <cpuid>sse2 avx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>psubusb</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>0f d8</opc> + <opr>P Q</opr> + </def> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>/sse=66 0f d8</opc> + <opr>V H W</opr> + <cpuid>sse2 avx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>psubusw</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>0f d9</opc> + <opr>P Q</opr> + </def> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>/sse=66 0f d9</opc> + <opr>V H W</opr> + <cpuid>sse2 avx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>punpckhbw</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>/sse=66 0f 68</opc> + <opr>V H W</opr> + <cpuid>sse2 avx</cpuid> + </def> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>0f 68</opc> + <opr>P Q</opr> + </def> + </instruction> + + <instruction> + <mnemonic>punpckhwd</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>/sse=66 0f 69</opc> + <opr>V H W</opr> + <cpuid>sse2 avx</cpuid> + </def> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>0f 69</opc> + <opr>P Q</opr> + </def> + </instruction> + + <instruction> + <mnemonic>punpckhdq</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>/sse=66 0f 6a</opc> + <opr>V H W</opr> + <cpuid>sse2 avx</cpuid> + </def> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>0f 6a</opc> + <opr>P Q</opr> + </def> + </instruction> + + <instruction> + <mnemonic>punpcklbw</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>/sse=66 0f 60</opc> + <opr>V H W</opr> + <cpuid>sse2 avx</cpuid> + </def> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>0f 60</opc> + <opr>P Q</opr> + </def> + </instruction> + + <instruction> + <mnemonic>punpcklwd</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>/sse=66 0f 61</opc> + <opr>V H W</opr> + <cpuid>sse2 avx</cpuid> + </def> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>0f 61</opc> + <opr>P Q</opr> + </def> + </instruction> + + <instruction> + <mnemonic>punpckldq</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>/sse=66 0f 62</opc> + <opr>V H W</opr> + <cpuid>sse2 avx</cpuid> + </def> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>0f 62</opc> + <opr>P Q</opr> + </def> + </instruction> + + <instruction> + <mnemonic>pi2fw</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>0f 0f /3dnow=0c</opc> + <opr>P Q</opr> + </def> + </instruction> + + <instruction> + <mnemonic>pi2fd</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>0f 0f /3dnow=0d</opc> + <opr>P Q</opr> + </def> + </instruction> + + <instruction> + <mnemonic>pf2iw</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>0f 0f /3dnow=1c</opc> + <opr>P Q</opr> + </def> + </instruction> + + <instruction> + <mnemonic>pf2id</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>0f 0f /3dnow=1d</opc> + <opr>P Q</opr> + </def> + </instruction> + + <instruction> + <mnemonic>pfnacc</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>0f 0f /3dnow=8a</opc> + <opr>P Q</opr> + </def> + </instruction> + + <instruction> + <mnemonic>pfpnacc</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>0f 0f /3dnow=8e</opc> + <opr>P Q</opr> + </def> + </instruction> + + <instruction> + <mnemonic>pfcmpge</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>0f 0f /3dnow=90</opc> + <opr>P Q</opr> + </def> + </instruction> + + <instruction> + <mnemonic>pfmin</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>0f 0f /3dnow=94</opc> + <opr>P Q</opr> + </def> + </instruction> + + <instruction> + <mnemonic>pfrcp</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>0f 0f /3dnow=96</opc> + <opr>P Q</opr> + </def> + </instruction> + + <instruction> + <mnemonic>pfrsqrt</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>0f 0f /3dnow=97</opc> + <opr>P Q</opr> + </def> + </instruction> + + <instruction> + <mnemonic>pfsub</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>0f 0f /3dnow=9a</opc> + <opr>P Q</opr> + </def> + </instruction> + + <instruction> + <mnemonic>pfadd</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>0f 0f /3dnow=9e</opc> + <opr>P Q</opr> + </def> + </instruction> + + <instruction> + <mnemonic>pfcmpgt</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>0f 0f /3dnow=a0</opc> + <opr>P Q</opr> + </def> + </instruction> + + <instruction> + <mnemonic>pfmax</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>0f 0f /3dnow=a4</opc> + <opr>P Q</opr> + </def> + </instruction> + + <instruction> + <mnemonic>pfrcpit1</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>0f 0f /3dnow=a6</opc> + <opr>P Q</opr> + </def> + </instruction> + + <instruction> + <mnemonic>pfrsqit1</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>0f 0f /3dnow=a7</opc> + <opr>P Q</opr> + </def> + </instruction> + + <instruction> + <mnemonic>pfsubr</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>0f 0f /3dnow=aa</opc> + <opr>P Q</opr> + </def> + </instruction> + + <instruction> + <mnemonic>pfacc</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>0f 0f /3dnow=ae</opc> + <opr>P Q</opr> + </def> + </instruction> + + <instruction> + <mnemonic>pfcmpeq</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>0f 0f /3dnow=b0</opc> + <opr>P Q</opr> + </def> + </instruction> + + <instruction> + <mnemonic>pfmul</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>0f 0f /3dnow=b4</opc> + <opr>P Q</opr> + </def> + </instruction> + + <instruction> + <mnemonic>pfrcpit2</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>0f 0f /3dnow=b6</opc> + <opr>P Q</opr> + </def> + </instruction> + + <instruction> + <mnemonic>pmulhrw</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>0f 0f /3dnow=b7</opc> + <opr>P Q</opr> + </def> + </instruction> + + <instruction> + <mnemonic>pswapd</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>0f 0f /3dnow=bb</opc> + <opr>P Q</opr> + </def> + </instruction> + + <instruction> + <mnemonic>pavgusb</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>0f 0f /3dnow=bf</opc> + <opr>P Q</opr> + </def> + </instruction> + + <instruction> + <mnemonic>push</mnemonic> + <def> + <opc>06 /m=!64</opc> + <opr>ES</opr> + <mode>inv64</mode> + </def> + <def> + <opc>0e /m=!64</opc> + <opr>CS</opr> + <mode>inv64</mode> + </def> + <def> + <opc>16 /m=!64</opc> + <opr>SS</opr> + <mode>inv64</mode> + </def> + <def> + <opc>1e /m=!64</opc> + <opr>DS</opr> + <mode>inv64</mode> + </def> + <def> + <opc>0f a8</opc> + <opr>GS</opr> + </def> + <def> + <opc>0f a0</opc> + <opr>FS</opr> + </def> + <def> + <pfx>oso rexb</pfx> + <opc>50</opc> + <opr>R0v</opr> + <mode>def64</mode> + </def> + <def> + <pfx>oso rexb</pfx> + <opc>51</opc> + <opr>R1v</opr> + <mode>def64</mode> + </def> + <def> + <pfx>oso rexb</pfx> + <opc>52</opc> + <opr>R2v</opr> + <mode>def64</mode> + </def> + <def> + <pfx>oso rexb</pfx> + <opc>53</opc> + <opr>R3v</opr> + <mode>def64</mode> + </def> + <def> + <pfx>oso rexb</pfx> + <opc>54</opc> + <opr>R4v</opr> + <mode>def64</mode> + </def> + <def> + <pfx>oso rexb</pfx> + <opc>55</opc> + <opr>R5v</opr> + <mode>def64</mode> + </def> + <def> + <pfx>oso rexb</pfx> + <opc>56</opc> + <opr>R6v</opr> + <mode>def64</mode> + </def> + <def> + <pfx>oso rexb</pfx> + <opc>57</opc> + <opr>R7v</opr> + <mode>def64</mode> + </def> + <def> + <pfx>oso</pfx> + <opc>68</opc> + <opr>sIz</opr> + <mode>def64</mode> + </def> + <def> + <pfx>aso oso rexw rexr rexx rexb</pfx> + <opc>ff /reg=6</opc> + <opr>Ev</opr> + <mode>def64</mode> + </def> + <def> + <pfx>oso</pfx> + <opc>6a</opc> + <opr>sIb</opr> + <mode>def64</mode> + </def> + </instruction> + + <instruction> + <mnemonic>pusha</mnemonic> + <def> + <pfx>oso</pfx> + <opc>60 /o=16 /m=!64</opc> + <mode>inv64</mode> + </def> + </instruction> + + <instruction> + <mnemonic>pushad</mnemonic> + <def> + <pfx>oso</pfx> + <opc>60 /o=32 /m=!64</opc> + <mode>inv64</mode> + </def> + </instruction> + + <instruction> + <mnemonic>pushfw</mnemonic> + <def> + <pfx>oso</pfx> + <opc>9c /m=!64 /o=16</opc> + </def> + <def> + <pfx>oso rexw</pfx> + <opc>9c /m=64 /o=16</opc> + <mode>def64</mode> + </def> + </instruction> + + <instruction> + <mnemonic>pushfd</mnemonic> + <def> + <pfx>oso</pfx> + <opc>9c /m=!64 /o=32</opc> + </def> + </instruction> + + <instruction> + <mnemonic>pushfq</mnemonic> + <def> + <pfx>oso rexw</pfx> + <opc>9c /m=64 /o=32</opc> + <mode>def64</mode> + </def> + <def> + <pfx>oso rexw</pfx> + <opc>9c /m=64 /o=64</opc> + <mode>def64</mode> + </def> + </instruction> + + <instruction> + <mnemonic>pxor</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>/sse=66 0f ef</opc> + <opr>V H W</opr> + <cpuid>sse2 avx</cpuid> + </def> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>0f ef</opc> + <opr>P Q</opr> + </def> + </instruction> + + <instruction> + <mnemonic>rcl</mnemonic> + <def> + <pfx>aso rexw rexr rexx rexb</pfx> + <opc>c0 /reg=2</opc> + <opr>Eb Ib</opr> + </def> + <def> + <pfx>aso oso rexw rexr rexx rexb</pfx> + <opc>c1 /reg=2</opc> + <opr>Ev Ib</opr> + </def> + <def> + <pfx>aso rexw rexr rexx rexb</pfx> + <opc>d0 /reg=2</opc> + <opr>Eb I1</opr> + </def> + <def> + <pfx>aso rexw rexr rexx rexb</pfx> + <opc>d2 /reg=2</opc> + <opr>Eb CL</opr> + </def> + <def> + <pfx>aso oso rexw rexr rexx rexb</pfx> + <opc>d3 /reg=2</opc> + <opr>Ev CL</opr> + </def> + <def> + <pfx>aso oso rexw rexr rexx rexb</pfx> + <opc>d1 /reg=2</opc> + <opr>Ev I1</opr> + </def> + </instruction> + + <instruction> + <mnemonic>rcr</mnemonic> + <def> + <pfx>aso rexw rexr rexx rexb</pfx> + <opc>d0 /reg=3</opc> + <opr>Eb I1</opr> + </def> + <def> + <pfx>aso oso rexw rexr rexx rexb</pfx> + <opc>c1 /reg=3</opc> + <opr>Ev Ib</opr> + </def> + <def> + <pfx>aso rexw rexr rexx rexb</pfx> + <opc>c0 /reg=3</opc> + <opr>Eb Ib</opr> + </def> + <def> + <pfx>aso oso rexw rexr rexx rexb</pfx> + <opc>d1 /reg=3</opc> + <opr>Ev I1</opr> + </def> + <def> + <pfx>aso rexw rexr rexx rexb</pfx> + <opc>d2 /reg=3</opc> + <opr>Eb CL</opr> + </def> + <def> + <pfx>aso oso rexw rexr rexx rexb</pfx> + <opc>d3 /reg=3</opc> + <opr>Ev CL</opr> + </def> + </instruction> + + <instruction> + <mnemonic>rol</mnemonic> + <def> + <pfx>aso rexw rexr rexx rexb</pfx> + <opc>c0 /reg=0</opc> + <opr>Eb Ib</opr> + </def> + <def> + <pfx>aso rexw rexr rexx rexb</pfx> + <opc>d0 /reg=0</opc> + <opr>Eb I1</opr> + </def> + <def> + <pfx>aso oso rexw rexr rexx rexb</pfx> + <opc>d1 /reg=0</opc> + <opr>Ev I1</opr> + </def> + <def> + <pfx>aso rexw rexr rexx rexb</pfx> + <opc>d2 /reg=0</opc> + <opr>Eb CL</opr> + </def> + <def> + <pfx>aso oso rexw rexr rexx rexb</pfx> + <opc>d3 /reg=0</opc> + <opr>Ev CL</opr> + </def> + <def> + <pfx>aso oso rexw rexr rexx rexb</pfx> + <opc>c1 /reg=0</opc> + <opr>Ev Ib</opr> + </def> + </instruction> + + <instruction> + <mnemonic>ror</mnemonic> + <def> + <pfx>aso rexw rexr rexx rexb</pfx> + <opc>d0 /reg=1</opc> + <opr>Eb I1</opr> + </def> + <def> + <pfx>aso rexw rexr rexx rexb</pfx> + <opc>c0 /reg=1</opc> + <opr>Eb Ib</opr> + </def> + <def> + <pfx>aso oso rexw rexr rexx rexb</pfx> + <opc>c1 /reg=1</opc> + <opr>Ev Ib</opr> + </def> + <def> + <pfx>aso oso rexw rexr rexx rexb</pfx> + <opc>d1 /reg=1</opc> + <opr>Ev I1</opr> + </def> + <def> + <pfx>aso rexw rexr rexx rexb</pfx> + <opc>d2 /reg=1</opc> + <opr>Eb CL</opr> + </def> + <def> + <pfx>aso oso rexw rexr rexx rexb</pfx> + <opc>d3 /reg=1</opc> + <opr>Ev CL</opr> + </def> + </instruction> + + <instruction> + <mnemonic>rcpps</mnemonic> + <def> + <pfx>aso rexr rexx rexb vexl</pfx> + <opc>0f 53</opc> + <opr>V W</opr> + <cpuid>sse avx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>rcpss</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>/sse=f3 0f 53</opc> + <opr>V W</opr> + <cpuid>sse avx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>rdmsr</mnemonic> + <def> + <opc>0f 32</opc> + </def> + </instruction> + + <instruction> + <mnemonic>rdpmc</mnemonic> + <def> + <opc>0f 33</opc> + </def> + </instruction> + + <instruction> + <mnemonic>rdtsc</mnemonic> + <def> + <opc>0f 31</opc> + </def> + </instruction> + + <instruction> + <mnemonic>rdtscp</mnemonic> + <vendor>amd</vendor> + <def> + <opc>0f 01 /reg=7 /mod=11 /rm=1</opc> + </def> + </instruction> + + <instruction> + <mnemonic>repne</mnemonic> + <def> + <opc>f2</opc> + </def> + </instruction> + + <instruction> + <mnemonic>rep</mnemonic> + <def> + <opc>f3</opc> + </def> + </instruction> + + <instruction> + <mnemonic>ret</mnemonic> + <def> + <opc>c2</opc> + <opr>Iw</opr> + </def> + <def> + <opc>c3</opc> + </def> + </instruction> + + <instruction> + <mnemonic>retf</mnemonic> + <def> + <opc>ca</opc> + <opr>Iw</opr> + </def> + <def> + <opc>cb</opc> + </def> + </instruction> + + <instruction> + <mnemonic>rsm</mnemonic> + <def> + <opc>0f aa</opc> + </def> + </instruction> + + <instruction> + <mnemonic>rsqrtps</mnemonic> + <def> + <pfx>aso rexr rexx rexb vexl</pfx> + <opc>0f 52</opc> + <opr>V W</opr> + <cpuid>sse avx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>rsqrtss</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>/sse=f3 0f 52</opc> + <opr>V W</opr> + <cpuid>sse avx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>sahf</mnemonic> + <def> + <opc>9e</opc> + </def> + </instruction> + + <instruction> + <mnemonic>sal</mnemonic> + </instruction> + + <instruction> + <mnemonic>salc</mnemonic> + <def> + <opc>d6 /m=!64</opc> + <mode>inv64</mode> + </def> + </instruction> + + <instruction> + <mnemonic>sar</mnemonic> + <def> + <pfx>aso oso rexw rexr rexx rexb</pfx> + <opc>d1 /reg=7</opc> + <opr>Ev I1</opr> + </def> + <def> + <pfx>aso rexw rexr rexx rexb</pfx> + <opc>c0 /reg=7</opc> + <opr>Eb Ib</opr> + </def> + <def> + <pfx>aso rexw rexr rexx rexb</pfx> + <opc>d0 /reg=7</opc> + <opr>Eb I1</opr> + </def> + <def> + <pfx>aso oso rexw rexr rexx rexb</pfx> + <opc>c1 /reg=7</opc> + <opr>Ev Ib</opr> + </def> + <def> + <pfx>aso rexw rexr rexx rexb</pfx> + <opc>d2 /reg=7</opc> + <opr>Eb CL</opr> + </def> + <def> + <pfx>aso oso rexw rexr rexx rexb</pfx> + <opc>d3 /reg=7</opc> + <opr>Ev CL</opr> + </def> + </instruction> + + <instruction> + <mnemonic>shl</mnemonic> + <def> + <pfx>aso rexw rexr rexx rexb</pfx> + <opc>c0 /reg=6</opc> + <opr>Eb Ib</opr> + </def> + <def> + <pfx>aso oso rexw rexr rexx rexb</pfx> + <opc>c1 /reg=6</opc> + <opr>Ev Ib</opr> + </def> + <def> + <pfx>aso rexw rexr rexx rexb</pfx> + <opc>d0 /reg=6</opc> + <opr>Eb I1</opr> + </def> + <def> + <pfx>aso rexw rexr rexx rexb</pfx> + <opc>d2 /reg=6</opc> + <opr>Eb CL</opr> + </def> + <def> + <pfx>aso oso rexw rexr rexx rexb</pfx> + <opc>d3 /reg=6</opc> + <opr>Ev CL</opr> + </def> + <def> + <pfx>aso oso rexw rexr rexx rexb</pfx> + <opc>c1 /reg=4</opc> + <opr>Ev Ib</opr> + </def> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>d2 /reg=4</opc> + <opr>Eb CL</opr> + </def> + <def> + <pfx>aso oso rexw rexr rexx rexb</pfx> + <opc>d1 /reg=4</opc> + <opr>Ev I1</opr> + </def> + <def> + <pfx>aso rexw rexr rexx rexb</pfx> + <opc>d0 /reg=4</opc> + <opr>Eb I1</opr> + </def> + <def> + <pfx>aso rexw rexr rexx rexb</pfx> + <opc>c0 /reg=4</opc> + <opr>Eb Ib</opr> + </def> + <def> + <pfx>aso oso rexw rexr rexx rexb</pfx> + <opc>d3 /reg=4</opc> + <opr>Ev CL</opr> + </def> + <def> + <pfx>aso oso rexw rexr rexx rexb</pfx> + <opc>d1 /reg=6</opc> + <opr>Ev I1</opr> + </def> + </instruction> + + <instruction> + <mnemonic>shr</mnemonic> + <def> + <pfx>aso oso rexw rexr rexx rexb</pfx> + <opc>c1 /reg=5</opc> + <opr>Ev Ib</opr> + </def> + <def> + <pfx>aso rexw rexr rexx rexb</pfx> + <opc>d2 /reg=5</opc> + <opr>Eb CL</opr> + </def> + <def> + <pfx>aso oso rexw rexr rexx rexb</pfx> + <opc>d1 /reg=5</opc> + <opr>Ev I1</opr> + </def> + <def> + <pfx>aso rexw rexr rexx rexb</pfx> + <opc>d0 /reg=5</opc> + <opr>Eb I1</opr> + </def> + <def> + <pfx>aso rexw rexr rexx rexb</pfx> + <opc>c0 /reg=5</opc> + <opr>Eb Ib</opr> + </def> + <def> + <pfx>aso oso rexw rexr rexx rexb</pfx> + <opc>d3 /reg=5</opc> + <opr>Ev CL</opr> + </def> + </instruction> + + <instruction> + <mnemonic>sbb</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>18</opc> + <opr>Eb Gb</opr> + </def> + <def> + <pfx>aso oso rexw rexr rexx rexb</pfx> + <opc>19</opc> + <opr>Ev Gv</opr> + </def> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>1a</opc> + <opr>Gb Eb</opr> + </def> + <def> + <pfx>aso oso rexw rexr rexx rexb</pfx> + <opc>1b</opc> + <opr>Gv Ev</opr> + </def> + <def> + <opc>1c</opc> + <opr>AL Ib</opr> + </def> + <def> + <pfx>oso rexw</pfx> + <opc>1d</opc> + <opr>rAX sIz</opr> + </def> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>80 /reg=3</opc> + <opr>Eb Ib</opr> + </def> + <def> + <pfx>aso oso rexw rexr rexx rexb</pfx> + <opc>81 /reg=3</opc> + <opr>Ev sIz</opr> + </def> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>82 /reg=3 /m=!64</opc> + <opr>Eb Ib</opr> + <mode>inv64</mode> + </def> + <def> + <pfx>aso oso rexw rexr rexx rexb</pfx> + <opc>83 /reg=3</opc> + <opr>Ev sIb</opr> + </def> + </instruction> + + <instruction> + <mnemonic>scasb</mnemonic> + <def> + <pfx>repz</pfx> + <opc>ae</opc> + </def> + </instruction> + + <instruction> + <mnemonic>scasw</mnemonic> + <def> + <pfx>repz oso rexw</pfx> + <opc>af /o=16</opc> + </def> + </instruction> + + <instruction> + <mnemonic>scasd</mnemonic> + <def> + <pfx>repz oso rexw</pfx> + <opc>af /o=32</opc> + </def> + </instruction> + + <instruction> + <mnemonic>scasq</mnemonic> + <def> + <pfx>repz oso rexw</pfx> + <opc>af /o=64</opc> + </def> + </instruction> + + <instruction> + <mnemonic>seto</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>0f 90</opc> + <opr>Eb</opr> + </def> + </instruction> + + <instruction> + <mnemonic>setno</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>0f 91</opc> + <opr>Eb</opr> + </def> + </instruction> + + <instruction> + <mnemonic>setb</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>0f 92</opc> + <opr>Eb</opr> + </def> + </instruction> + + <instruction> + <mnemonic>setae</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>0f 93</opc> + <opr>Eb</opr> + </def> + </instruction> + + <instruction> + <mnemonic>setz</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>0f 94</opc> + <opr>Eb</opr> + </def> + </instruction> + + <instruction> + <mnemonic>setnz</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>0f 95</opc> + <opr>Eb</opr> + </def> + </instruction> + + <instruction> + <mnemonic>setbe</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>0f 96</opc> + <opr>Eb</opr> + </def> + </instruction> + + <instruction> + <mnemonic>seta</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>0f 97</opc> + <opr>Eb</opr> + </def> + </instruction> + + <instruction> + <mnemonic>sets</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>0f 98</opc> + <opr>Eb</opr> + </def> + </instruction> + + <instruction> + <mnemonic>setns</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>0f 99</opc> + <opr>Eb</opr> + </def> + </instruction> + + <instruction> + <mnemonic>setp</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>0f 9a</opc> + <opr>Eb</opr> + </def> + </instruction> + + <instruction> + <mnemonic>setnp</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>0f 9b</opc> + <opr>Eb</opr> + </def> + </instruction> + + <instruction> + <mnemonic>setl</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>0f 9c</opc> + <opr>Eb</opr> + </def> + </instruction> + + <instruction> + <mnemonic>setge</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>0f 9d</opc> + <opr>Eb</opr> + </def> + </instruction> + + <instruction> + <mnemonic>setle</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>0f 9e</opc> + <opr>Eb</opr> + </def> + </instruction> + + <instruction> + <mnemonic>setg</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>0f 9f</opc> + <opr>Eb</opr> + </def> + </instruction> + + <instruction> + <mnemonic>sfence</mnemonic> + <def> + <opc>0f ae /reg=7 /mod=11 /rm=0</opc> + </def> + <def> + <opc>0f ae /reg=7 /mod=11 /rm=1</opc> + </def> + <def> + <opc>0f ae /reg=7 /mod=11 /rm=2</opc> + </def> + <def> + <opc>0f ae /reg=7 /mod=11 /rm=3</opc> + </def> + <def> + <opc>0f ae /reg=7 /mod=11 /rm=4</opc> + </def> + <def> + <opc>0f ae /reg=7 /mod=11 /rm=5</opc> + </def> + <def> + <opc>0f ae /reg=7 /mod=11 /rm=6</opc> + </def> + <def> + <opc>0f ae /reg=7 /mod=11 /rm=7</opc> + </def> + </instruction> + + <instruction> + <mnemonic>sgdt</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>0f 01 /reg=0 /mod=!11</opc> + <opr>M</opr> + </def> + </instruction> + + <instruction> + <mnemonic>shld</mnemonic> + <def> + <pfx>aso oso rexw rexr rexx rexb</pfx> + <opc>0f a4</opc> + <opr>Ev Gv Ib</opr> + </def> + <def> + <pfx>aso oso rexw rexr rexx rexb</pfx> + <opc>0f a5</opc> + <opr>Ev Gv CL</opr> + </def> + </instruction> + + <instruction> + <mnemonic>shrd</mnemonic> + <def> + <pfx>aso oso rexw rexr rexx rexb</pfx> + <opc>0f ac</opc> + <opr>Ev Gv Ib</opr> + </def> + <def> + <pfx>aso oso rexw rexr rexx rexb</pfx> + <opc>0f ad</opc> + <opr>Ev Gv CL</opr> + </def> + </instruction> + + <instruction> + <mnemonic>shufpd</mnemonic> + <def> + <pfx>aso rexr rexx rexb vexl</pfx> + <opc>/sse=66 0f c6</opc> + <opr>V H W Ib</opr> + <cpuid>sse2 avx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>shufps</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>0f c6</opc> + <opr>V H W Ib</opr> + <cpuid>sse2 avx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>sidt</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>0f 01 /reg=1 /mod=!11</opc> + <opr>M</opr> + </def> + </instruction> + + <instruction> + <mnemonic>sldt</mnemonic> + <def> + <pfx>aso oso rexr rexw rexx rexb</pfx> + <opc>0f 00 /reg=0</opc> + <opr>MwRv</opr> + </def> + </instruction> + + <instruction> + <mnemonic>smsw</mnemonic> + <def> + <pfx>aso oso rexr rexw rexx rexb</pfx> + <opc>0f 01 /reg=4 /mod=!11</opc> + <opr>MwRv</opr> + </def> + <def> + <pfx>aso oso rexr rexw rexx rexb</pfx> + <opc>0f 01 /reg=4 /mod=11</opc> + <opr>MwRv</opr> + </def> + </instruction> + + <instruction> + <mnemonic>sqrtps</mnemonic> + <def> + <pfx>aso rexr rexx rexb vexl</pfx> + <opc>0f 51</opc> + <opr>V W</opr> + <cpuid>sse avx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>sqrtpd</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>/sse=66 0f 51</opc> + <opr>V W</opr> + <cpuid>sse2 avx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>sqrtsd</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>/sse=f2 0f 51</opc> + <opr>V H W</opr> + <cpuid>sse2 avx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>sqrtss</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>/sse=f3 0f 51</opc> + <opr>V H W</opr> + <cpuid>sse avx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>stc</mnemonic> + <def> + <opc>f9</opc> + </def> + </instruction> + + <instruction> + <mnemonic>std</mnemonic> + <def> + <opc>fd</opc> + </def> + </instruction> + + <instruction> + <mnemonic>stgi</mnemonic> + <vendor>amd</vendor> + <def> + <opc>0f 01 /reg=3 /mod=11 /rm=4</opc> + </def> + </instruction> + + <instruction> + <mnemonic>sti</mnemonic> + <def> + <opc>fb</opc> + </def> + </instruction> + + <instruction> + <mnemonic>skinit</mnemonic> + <vendor>amd</vendor> + <def> + <opc>0f 01 /reg=3 /mod=11 /rm=6</opc> + </def> + </instruction> + + <instruction> + <mnemonic>stmxcsr</mnemonic> + <def> + <pfx>aso rexw rexr rexx rexb</pfx> + <opc>0f ae /mod=!11 /reg=3</opc> + <opr>Md</opr> + <cpuid>sse avx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>stosb</mnemonic> + <def> + <pfx>rep seg</pfx> + <opc>aa</opc> + </def> + </instruction> + + <instruction> + <mnemonic>stosw</mnemonic> + <def> + <pfx>rep seg oso rexw</pfx> + <opc>ab /o=16</opc> + </def> + </instruction> + + <instruction> + <mnemonic>stosd</mnemonic> + <def> + <pfx>rep seg oso rexw</pfx> + <opc>ab /o=32</opc> + </def> + </instruction> + + <instruction> + <mnemonic>stosq</mnemonic> + <def> + <pfx>rep seg oso rexw</pfx> + <opc>ab /o=64</opc> + </def> + </instruction> + + <instruction> + <mnemonic>str</mnemonic> + <def> + <pfx>aso oso rexr rexw rexx rexb</pfx> + <opc>0f 00 /reg=1</opc> + <opr>MwRv</opr> + </def> + </instruction> + + <instruction> + <mnemonic>sub</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>28</opc> + <opr>Eb Gb</opr> + </def> + <def> + <pfx>aso oso rexw rexr rexx rexb</pfx> + <opc>29</opc> + <opr>Ev Gv</opr> + </def> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>2a</opc> + <opr>Gb Eb</opr> + </def> + <def> + <pfx>aso oso rexw rexr rexx rexb</pfx> + <opc>2b</opc> + <opr>Gv Ev</opr> + </def> + <def> + <opc>2c</opc> + <opr>AL Ib</opr> + </def> + <def> + <pfx>oso rexw</pfx> + <opc>2d</opc> + <opr>rAX sIz</opr> + </def> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>80 /reg=5</opc> + <opr>Eb Ib</opr> + </def> + <def> + <pfx>aso oso rexw rexr rexx rexb</pfx> + <opc>81 /reg=5</opc> + <opr>Ev sIz</opr> + </def> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>82 /reg=5 /m=!64</opc> + <opr>Eb Ib</opr> + <mode>inv64</mode> + </def> + <def> + <pfx>aso oso rexw rexr rexx rexb</pfx> + <opc>83 /reg=5</opc> + <opr>Ev sIb</opr> + </def> + </instruction> + + <instruction> + <mnemonic>subpd</mnemonic> + <def> + <pfx>aso rexr rexx rexb vexl</pfx> + <opc>/sse=66 0f 5c</opc> + <opr>V H W</opr> + <cpuid>sse2 avx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>subps</mnemonic> + <def> + <pfx>aso rexr rexx rexb vexl</pfx> + <opc>0f 5c</opc> + <opr>V H W</opr> + <cpuid>sse avx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>subsd</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>/sse=f2 0f 5c</opc> + <opr>V H W</opr> + <cpuid>sse2 avx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>subss</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>/sse=f3 0f 5c</opc> + <opr>V H W</opr> + <cpuid>sse avx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>swapgs</mnemonic> + <def> + <opc>0f 01 /reg=7 /mod=11 /rm=0</opc> + </def> + </instruction> + + <instruction> + <mnemonic>syscall</mnemonic> + <def> + <opc>0f 05</opc> + </def> + </instruction> + + <instruction> + <mnemonic>sysenter</mnemonic> + <def> + <opc>0f 34 /m=!64</opc> + </def> + <def> + <opc>0f 34 /m=64</opc> + <vendor>intel</vendor> + </def> + </instruction> + + <instruction> + <mnemonic>sysexit</mnemonic> + <def> + <opc>0f 35 /m=!64</opc> + </def> + <def> + <opc>0f 35 /m=64</opc> + <vendor>intel</vendor> + </def> + </instruction> + + <instruction> + <mnemonic>sysret</mnemonic> + <def> + <opc>0f 07</opc> + </def> + </instruction> + + <instruction> + <mnemonic>test</mnemonic> + <def> + <pfx>aso rexw rexr rexx rexb</pfx> + <opc>f6 /reg=0</opc> + <opr>Eb Ib</opr> + </def> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>84</opc> + <opr>Eb Gb</opr> + </def> + <def> + <pfx>aso oso rexw rexr rexx rexb</pfx> + <opc>85</opc> + <opr>Ev Gv</opr> + </def> + <def> + <opc>a8</opc> + <opr>AL Ib</opr> + </def> + <def> + <pfx>oso rexw</pfx> + <opc>a9</opc> + <opr>rAX sIz</opr> + </def> + <def> + <pfx>aso rexw rexr rexx rexb</pfx> + <opc>f6 /reg=1</opc> + <opr>Eb Ib</opr> + </def> + <def> + <pfx>aso oso rexw rexr rexx rexb</pfx> + <opc>f7 /reg=0</opc> + <opr>Ev sIz</opr> + </def> + <def> + <pfx>aso oso rexw rexr rexx rexb</pfx> + <opc>f7 /reg=1</opc> + <opr>Ev Iz</opr> + </def> + </instruction> + + <instruction> + <mnemonic>ucomisd</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>/sse=66 0f 2e</opc> + <opr>V W</opr> + <cpuid>sse2 avx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>ucomiss</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>0f 2e</opc> + <opr>V W</opr> + <cpuid>sse avx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>ud2</mnemonic> + <def> + <opc>0f 0b</opc> + </def> + </instruction> + + <instruction> + <mnemonic>unpckhpd</mnemonic> + <def> + <pfx>aso rexr rexx rexb vexl</pfx> + <opc>/sse=66 0f 15</opc> + <opr>V H W</opr> + <cpuid>sse2 avx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>unpckhps</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>0f 15</opc> + <opr>V H W</opr> + <cpuid>sse avx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>unpcklps</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>0f 14</opc> + <opr>V H W</opr> + <cpuid>sse avx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>unpcklpd</mnemonic> + <def> + <pfx>aso rexr rexx rexb vexl</pfx> + <opc>/sse=66 0f 14</opc> + <opr>V H W</opr> + <cpuid>sse2 avx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>verr</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>0f 00 /reg=4</opc> + <opr>Ew</opr> + </def> + </instruction> + + <instruction> + <mnemonic>verw</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>0f 00 /reg=5</opc> + <opr>Ew</opr> + </def> + </instruction> + + <instruction> + <mnemonic>vmcall</mnemonic> + <vendor>intel</vendor> + <def> + <opc>0f 01 /reg=0 /mod=11 /rm=1</opc> + </def> + </instruction> + + <instruction> + <mnemonic>rdrand</mnemonic> + <def> + <pfx>oso rexr rexw rexx rexb</pfx> + <opc>0f c7 /mod=11 /reg=6</opc> + <opr>R</opr> + </def> + <cpuid>rdrand</cpuid> + </instruction> + + <instruction> + <mnemonic>vmclear</mnemonic> + <vendor>intel</vendor> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>/sse=66 0f c7 /mod=!11 /reg=6</opc> + <opr>Mq</opr> + </def> + </instruction> + + <instruction> + <mnemonic>vmxon</mnemonic> + <vendor>intel</vendor> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>/sse=f3 0f c7 /mod=!11 /reg=6</opc> + <opr>Mq</opr> + </def> + </instruction> + + <instruction> + <mnemonic>vmptrld</mnemonic> + <vendor>intel</vendor> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>0f c7 /mod=!11 /reg=6</opc> + <opr>Mq</opr> + </def> + </instruction> + + <instruction> + <mnemonic>vmptrst</mnemonic> + <vendor>intel</vendor> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>0f c7 /mod=!11 /reg=7</opc> + <opr>Mq</opr> + </def> + </instruction> + + <instruction> + <mnemonic>vmlaunch</mnemonic> + <vendor>intel</vendor> + <def> + <opc>0f 01 /reg=0 /mod=11 /rm=2</opc> + </def> + </instruction> + + <instruction> + <mnemonic>vmresume</mnemonic> + <vendor>intel</vendor> + <def> + <opc>0f 01 /reg=0 /mod=11 /rm=3</opc> + </def> + </instruction> + + <instruction> + <mnemonic>vmxoff</mnemonic> + <vendor>intel</vendor> + <def> + <opc>0f 01 /reg=0 /mod=11 /rm=4</opc> + </def> + </instruction> + + <instruction> + <mnemonic>vmread</mnemonic> + <vendor>intel</vendor> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>0f 78</opc> + <opr>Ey Gy</opr> + <mode>def64</mode> + </def> + </instruction> + + <instruction> + <mnemonic>vmwrite</mnemonic> + <vendor>intel</vendor> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>0f 79</opc> + <opr>Gy Ey</opr> + <mode>def64</mode> + </def> + </instruction> + + <instruction> + <mnemonic>vmrun</mnemonic> + <vendor>amd</vendor> + <def> + <opc>0f 01 /reg=3 /mod=11 /rm=0</opc> + </def> + </instruction> + + <instruction> + <mnemonic>vmmcall</mnemonic> + <vendor>amd</vendor> + <def> + <opc>0f 01 /reg=3 /mod=11 /rm=1</opc> + </def> + </instruction> + + <instruction> + <mnemonic>vmload</mnemonic> + <vendor>amd</vendor> + <def> + <opc>0f 01 /reg=3 /mod=11 /rm=2</opc> + </def> + </instruction> + + <instruction> + <mnemonic>vmsave</mnemonic> + <vendor>amd</vendor> + <def> + <opc>0f 01 /reg=3 /mod=11 /rm=3</opc> + </def> + </instruction> + + <instruction> + <mnemonic>wait</mnemonic> + <def> + <opc>9b</opc> + </def> + </instruction> + + <instruction> + <mnemonic>wbinvd</mnemonic> + <def> + <opc>0f 09</opc> + </def> + </instruction> + + <instruction> + <mnemonic>wrmsr</mnemonic> + <def> + <opc>0f 30</opc> + </def> + </instruction> + + <instruction> + <mnemonic>xadd</mnemonic> + <def> + <pfx>aso oso rexr rexx rexb</pfx> + <opc>0f c0</opc> + <opr>Eb Gb</opr> + </def> + <def> + <pfx>aso oso rexw rexr rexx rexb</pfx> + <opc>0f c1</opc> + <opr>Ev Gv</opr> + </def> + </instruction> + + <instruction> + <mnemonic>xchg</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>86</opc> + <opr>Eb Gb</opr> + </def> + <def> + <pfx>aso oso rexw rexr rexx rexb</pfx> + <opc>87</opc> + <opr>Ev Gv</opr> + </def> + <def> + <pfx>oso rexw rexb</pfx> + <opc>90</opc> + <opr>R0v rAX</opr> + </def> + <def> + <pfx>oso rexw rexb</pfx> + <opc>91</opc> + <opr>R1v rAX</opr> + </def> + <def> + <pfx>oso rexw rexb</pfx> + <opc>92</opc> + <opr>R2v rAX</opr> + </def> + <def> + <pfx>oso rexw rexb</pfx> + <opc>93</opc> + <opr>R3v rAX</opr> + </def> + <def> + <pfx>oso rexw rexb</pfx> + <opc>94</opc> + <opr>R4v rAX</opr> + </def> + <def> + <pfx>oso rexw rexb</pfx> + <opc>95</opc> + <opr>R5v rAX</opr> + </def> + <def> + <pfx>oso rexw rexb</pfx> + <opc>96</opc> + <opr>R6v rAX</opr> + </def> + <def> + <pfx>oso rexw rexb</pfx> + <opc>97</opc> + <opr>R7v rAX</opr> + </def> + </instruction> + + <instruction> + <mnemonic>xgetbv</mnemonic> + <def> + <opc>0f 01 /mod=11 /reg=2 /rm=0</opc> + </def> + </instruction> + + <instruction> + <mnemonic>xlatb</mnemonic> + <def> + <pfx>rexw seg</pfx> + <opc>d7</opc> + </def> + </instruction> + + <instruction> + <mnemonic>xor</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>30</opc> + <opr>Eb Gb</opr> + </def> + <def> + <pfx>aso oso rexw rexr rexx rexb</pfx> + <opc>31</opc> + <opr>Ev Gv</opr> + </def> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>32</opc> + <opr>Gb Eb</opr> + </def> + <def> + <pfx>aso oso rexw rexr rexx rexb</pfx> + <opc>33</opc> + <opr>Gv Ev</opr> + </def> + <def> + <opc>34</opc> + <opr>AL Ib</opr> + </def> + <def> + <pfx>oso rexw</pfx> + <opc>35</opc> + <opr>rAX sIz</opr> + </def> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>80 /reg=6</opc> + <opr>Eb Ib</opr> + </def> + <def> + <pfx>aso oso rexw rexr rexx rexb</pfx> + <opc>81 /reg=6</opc> + <opr>Ev sIz</opr> + </def> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>82 /reg=6 /m=!64</opc> + <opr>Eb Ib</opr> + <mode>inv64</mode> + </def> + <def> + <pfx>aso oso rexw rexr rexx rexb</pfx> + <opc>83 /reg=6</opc> + <opr>Ev sIb</opr> + </def> + </instruction> + + <instruction> + <mnemonic>xorpd</mnemonic> + <def> + <pfx>aso rexr rexx rexb vexl</pfx> + <opc>/sse=66 0f 57</opc> + <opr>V H W</opr> + <cpuid>sse2 avx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>xorps</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>0f 57</opc> + <opr>V H W</opr> + <cpuid>sse2 avx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>xcryptecb</mnemonic> + <def> + <opc>0f a7 /mod=11 /rm=0 /reg=1</opc> + </def> + </instruction> + + <instruction> + <mnemonic>xcryptcbc</mnemonic> + <def> + <opc>0f a7 /mod=11 /rm=0 /reg=2</opc> + </def> + </instruction> + + <instruction> + <mnemonic>xcryptctr</mnemonic> + <def> + <opc>0f a7 /mod=11 /rm=0 /reg=3</opc> + </def> + </instruction> + + <instruction> + <mnemonic>xcryptcfb</mnemonic> + <def> + <opc>0f a7 /mod=11 /rm=0 /reg=4</opc> + </def> + </instruction> + + <instruction> + <mnemonic>xcryptofb</mnemonic> + <def> + <opc>0f a7 /mod=11 /rm=0 /reg=5</opc> + </def> + </instruction> + + <instruction> + <mnemonic>xrstor</mnemonic> + <def> + <pfx>aso rexw rexr rexx rexb</pfx> + <opc>0f ae /reg=5 /mod=!11</opc> + <opr>M</opr> + </def> + </instruction> + + <instruction> + <mnemonic>xsave</mnemonic> + <def> + <pfx>aso rexw rexr rexx rexb</pfx> + <opc>0f ae /reg=4 /mod=!11</opc> + <opr>M</opr> + </def> + </instruction> + + <instruction> + <mnemonic>xsetbv</mnemonic> + <def> + <opc>0f 01 /mod=11 /reg=2 /rm=1</opc> + </def> + </instruction> + + <instruction> + <mnemonic>xsha1</mnemonic> + <def> + <opc>0f a6 /mod=11 /rm=0 /reg=1</opc> + </def> + </instruction> + + <instruction> + <mnemonic>xsha256</mnemonic> + <def> + <opc>0f a6 /mod=11 /rm=0 /reg=2</opc> + </def> + </instruction> + + <instruction> + <mnemonic>xstore</mnemonic> + <def> + <opc>0f a7 /mod=11 /rm=0 /reg=0</opc> + </def> + </instruction> + + <instruction> + <mnemonic>pclmulqdq</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>/sse=66 0f 3a 44</opc> + <opr>V H W Ib</opr> + <cpuid>aesni avx</cpuid> + </def> + </instruction> + + <!-- + SMX + --> + + <instruction> + <mnemonic>getsec</mnemonic> + <cpuid>smx</cpuid> + <def> + <opc>0f 37</opc> + </def> + </instruction> + + <!-- + SSE 2 + --> + + <instruction> + <mnemonic>movdqa</mnemonic> + <def> + <pfx>aso rexr rexx rexb vexl</pfx> + <opc>/sse=66 0f 7f</opc> + <opr>W V</opr> + </def> + <def> + <pfx>aso rexr rexx rexb vexl</pfx> + <opc>/sse=66 0f 6f</opc> + <opr>V W</opr> + </def> + <cpuid>sse2 avx</cpuid> + </instruction> + + <instruction> + <mnemonic>maskmovdqu</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>/sse=66 0f f7 /mod=11</opc> + <opr>V U</opr> + <cpuid>sse2 avx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>movdq2q</mnemonic> + <def> + <pfx>aso rexb</pfx> + <opc>/sse=f2 0f d6</opc> + <opr>P U</opr> + </def> + </instruction> + + <instruction> + <mnemonic>movdqu</mnemonic> + <def> + <pfx>aso rexr rexx rexb vexl</pfx> + <opc>/sse=f3 0f 6f</opc> + <opr>V W</opr> + </def> + <def> + <pfx>aso rexr rexx rexb vexl</pfx> + <opc>/sse=f3 0f 7f</opc> + <opr>W V</opr> + </def> + <cpuid>sse2 avx</cpuid> + </instruction> + + <instruction> + <mnemonic>movq2dq</mnemonic> + <def> + <pfx>aso rexr</pfx> + <opc>/sse=f3 0f d6</opc> + <opr>V N</opr> + </def> + </instruction> + + <instruction> + <mnemonic>paddq</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>0f d4</opc> + <opr>P Q</opr> + </def> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>/sse=66 0f d4</opc> + <opr>V H W</opr> + <cpuid>sse2 avx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>psubq</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>/sse=66 0f fb</opc> + <opr>V H W</opr> + <cpuid>sse2 avx</cpuid> + </def> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>0f fb</opc> + <opr>P Q</opr> + </def> + </instruction> + + <instruction> + <mnemonic>pmuludq</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>0f f4</opc> + <opr>P Q</opr> + </def> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>/sse=66 0f f4</opc> + <opr>V W</opr> + </def> + </instruction> + + <instruction> + <mnemonic>pshufhw</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>/sse=f3 0f 70</opc> + <opr>V W Ib</opr> + <cpuid>sse2 avx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>pshuflw</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>/sse=f2 0f 70</opc> + <opr>V W Ib</opr> + <cpuid>sse2 avx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>pshufd</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>/sse=66 0f 70</opc> + <opr>V W Ib</opr> + <cpuid>sse2 avx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>pslldq</mnemonic> + <def> + <pfx>rexb</pfx> + <opc>/sse=66 0f 73 /reg=7</opc> + <opr>H U Ib</opr> + <cpuid>sse2 avx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>psrldq</mnemonic> + <def> + <pfx>rexb</pfx> + <opc>/sse=66 0f 73 /reg=3</opc> + <opr>H U Ib</opr> + <cpuid>sse2 avx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>punpckhqdq</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>/sse=66 0f 6d</opc> + <opr>V H W</opr> + <cpuid>sse2 avx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>punpcklqdq</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>/sse=66 0f 6c</opc> + <opr>V H W</opr> + <cpuid>sse2 avx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>haddpd</mnemonic> + <def> + <pfx>aso rexr rexx rexb vexl</pfx> + <opc>/sse=66 0f 7c</opc> + <opr>V H W</opr> + <cpuid>sse3 avx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>haddps</mnemonic> + <def> + <pfx>aso rexr rexx rexb vexl</pfx> + <opc>/sse=f2 0f 7c</opc> + <opr>V H W</opr> + <cpuid>sse3 avx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>hsubpd</mnemonic> + <def> + <pfx>aso rexr rexx rexb vexl</pfx> + <opc>/sse=66 0f 7d</opc> + <opr>V H W</opr> + <cpuid>sse3 avx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>hsubps</mnemonic> + <def> + <pfx>aso rexr rexx rexb vexl</pfx> + <opc>/sse=f2 0f 7d</opc> + <opr>V H W</opr> + <cpuid>sse3 avx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>insertps</mnemonic> + <def> + <pfx>aso rexr rexw rexx rexb</pfx> + <opc>/sse=66 0f 3a 21</opc> + <opr>V H Md Ib</opr> + <cpuid>sse4.1 avx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>lddqu</mnemonic> + <def> + <pfx>aso rexr rexx rexb vexl</pfx> + <opc>/sse=f2 0f f0</opc> + <opr>V M</opr> + <cpuid>sse3 avx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>movddup</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>/sse=f2 0f 12 /mod=11</opc> + <opr>V W</opr> + </def> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>/sse=f2 0f 12 /mod=!11</opc> + <opr>V W</opr> + </def> + <cpuid>sse3 avx</cpuid> + </instruction> + + <instruction> + <mnemonic>movshdup</mnemonic> + <def> + <pfx>aso rexr rexx rexb vexl</pfx> + <opc>/sse=f3 0f 16 /mod=11</opc> + <opr>V W</opr> + <cpuid>sse3 avx</cpuid> + </def> + <def> + <pfx>aso rexr rexx rexb vexl</pfx> + <opc>/sse=f3 0f 16 /mod=!11</opc> + <opr>V W</opr> + <cpuid>sse3 avx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>movsldup</mnemonic> + <def> + <pfx>aso rexr rexx rexb vexl</pfx> + <opc>/sse=f3 0f 12 /mod=11</opc> + <opr>V W</opr> + <cpuid>sse3 avx</cpuid> + </def> + <def> + <pfx>aso rexr rexx rexb vexl</pfx> + <opc>/sse=f3 0f 12 /mod=!11</opc> + <opr>V W</opr> + <cpuid>sse3 avx</cpuid> + </def> + </instruction> + + <!-- + SSSE 3 + --> + + <instruction> + <mnemonic>pabsb</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>0f 38 1c</opc> + <opr>P Q</opr> + <cpuid>ssse3</cpuid> + </def> + <def> + <pfx>aso rexr rexx rexb vexl</pfx> + <opc>/sse=66 0f 38 1c</opc> + <opr>V W</opr> + <cpuid>ssse3 avx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>pabsw</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>0f 38 1d</opc> + <opr>P Q</opr> + <cpuid>ssse3</cpuid> + </def> + <def> + <pfx>aso rexr rexx rexb vexl</pfx> + <opc>/sse=66 0f 38 1d</opc> + <opr>V W</opr> + <cpuid>ssse3 avx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>pabsd</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>0f 38 1e</opc> + <opr>P Q</opr> + <cpuid>ssse3</cpuid> + </def> + <def> + <pfx>aso rexr rexx rexb vexl</pfx> + <opc>/sse=66 0f 38 1e</opc> + <opr>V W</opr> + <cpuid>ssse3 avx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>pshufb</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>0f 38 00</opc> + <opr>P Q</opr> + </def> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>/sse=66 0f 38 00</opc> + <opr>V H W</opr> + <cpuid>ssse3 avx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>phaddw</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>0f 38 01</opc> + <opr>P Q</opr> + </def> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>/sse=66 0f 38 01</opc> + <opr>V H W</opr> + <cpuid>ssse3 avx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>phaddd</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>0f 38 02</opc> + <opr>P Q</opr> + </def> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>/sse=66 0f 38 02</opc> + <opr>V H W</opr> + <cpuid>ssse3 avx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>phaddsw</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>0f 38 03</opc> + <opr>P Q</opr> + </def> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>/sse=66 0f 38 03</opc> + <opr>V H W</opr> + <cpuid>ssse3 avx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>pmaddubsw</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>0f 38 04</opc> + <opr>P Q</opr> + </def> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>/sse=66 0f 38 04</opc> + <opr>V H W</opr> + <cpuid>ssse3 avx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>phsubw</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>0f 38 05</opc> + <opr>P Q</opr> + </def> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>/sse=66 0f 38 05</opc> + <opr>V H W</opr> + <cpuid>ssse3 avx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>phsubd</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>0f 38 06</opc> + <opr>P Q</opr> + </def> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>/sse=66 0f 38 06</opc> + <opr>V H W</opr> + <cpuid>ssse3 avx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>phsubsw</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>0f 38 07</opc> + <opr>P Q</opr> + </def> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>/sse=66 0f 38 07</opc> + <opr>V H W</opr> + <cpuid>ssse3 avx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>psignb</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>0f 38 08</opc> + <opr>P Q</opr> + </def> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>/sse=66 0f 38 08</opc> + <opr>V H W</opr> + <cpuid>ssse3 avx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>psignd</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>0f 38 0a</opc> + <opr>P Q</opr> + </def> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>/sse=66 0f 38 0a</opc> + <opr>V H W</opr> + <cpuid>ssse3 avx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>psignw</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>0f 38 09</opc> + <opr>P Q</opr> + </def> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>/sse=66 0f 38 09</opc> + <opr>V H W</opr> + <cpuid>ssse3 avx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>pmulhrsw</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>0f 38 0b</opc> + <opr>P Q</opr> + </def> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>/sse=66 0f 38 0b</opc> + <opr>V H W</opr> + <cpuid>ssse3 avx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>palignr</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>0f 3a 0f</opc> + <opr>P Q Ib</opr> + </def> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>/sse=66 0f 3a 0f</opc> + <opr>V H W Ib</opr> + <cpuid>ssse3 avx</cpuid> + </def> + </instruction> + + <!-- + SSE 4.1 + --> + + <instruction> + <mnemonic>pblendvb</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>/sse=66 0f 38 10</opc> + <opr>V W</opr> + <cpuid>sse4.1</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>pmuldq</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>/sse=66 0f 38 28</opc> + <opr>V H W</opr> + <cpuid>sse4.1 avx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>pminsb</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>/sse=66 0f 38 38</opc> + <opr>V H W</opr> + <cpuid>sse4.1 avx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>pminsd</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>/sse=66 0f 38 39</opc> + <opr>V H W</opr> + <cpuid>sse4.1 avx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>pminuw</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>/sse=66 0f 38 3a</opc> + <opr>V H W</opr> + <cpuid>sse4.1 avx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>pminud</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>/sse=66 0f 38 3b</opc> + <opr>V H W</opr> + <cpuid>sse4.1 avx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>pmaxsb</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>/sse=66 0f 38 3c</opc> + <opr>V H W</opr> + <cpuid>sse4.1 avx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>pmaxsd</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>/sse=66 0f 38 3d</opc> + <opr>V H W</opr> + <cpuid>sse4.1 avx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>pmaxud</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>/sse=66 0f 38 3f</opc> + <opr>V H W</opr> + <cpuid>sse4.1 avx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>pmaxuw</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>/sse=66 0f 38 3e</opc> + <opr>V H W</opr> + <cpuid>sse4.1 avx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>pmulld</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>/sse=66 0f 38 40</opc> + <opr>V H W</opr> + <cpuid>sse4.1 avx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>phminposuw</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>/sse=66 0f 38 41</opc> + <opr>V W</opr> + <cpuid>sse4.1 avx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>roundps</mnemonic> + <def> + <pfx>aso rexr rexx rexb vexl</pfx> + <opc>/sse=66 0f 3a 08</opc> + <opr>V W Ib</opr> + <cpuid>sse avx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>roundpd</mnemonic> + <def> + <pfx>aso rexr rexx rexb vexl</pfx> + <opc>/sse=66 0f 3a 09</opc> + <opr>V W Ib</opr> + <cpuid>sse4.1 avx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>roundss</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>/sse=66 0f 3a 0a</opc> + <opr>V H W Ib</opr> + <cpuid>sse4.1 avx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>roundsd</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>/sse=66 0f 3a 0b</opc> + <opr>V H W Ib</opr> + <cpuid>sse4.1 avx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>blendpd</mnemonic> + <def> + <pfx>aso rexr rexx rexb vexl</pfx> + <opc>/sse=66 0f 3a 0d</opc> + <opr>V H W Ib</opr> + <cpuid>sse4.1 avx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>blendps</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>/sse=66 0f 3a 0c</opc> + <opr>V H W Ib</opr> + <cpuid>sse4.1 avx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>blendvpd</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>/sse=66 0f 38 15</opc> + <opr>V W</opr> + <cpuid>sse4.1</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>blendvps</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>/sse=66 0f 38 14</opc> + <opr>V W</opr> + <cpuid>sse4.1</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>bound</mnemonic> + <def> + <pfx>aso oso</pfx> + <opc>62 /m=!64</opc> + <opr>Gv M</opr> + </def> + </instruction> + + <instruction> + <mnemonic>bsf</mnemonic> + <def> + <pfx>aso oso rexw rexr rexx rexb</pfx> + <opc>0f bc</opc> + <opr>Gv Ev</opr> + </def> + </instruction> + + <instruction> + <mnemonic>bsr</mnemonic> + <def> + <pfx>aso oso rexw rexr rexx rexb</pfx> + <opc>0f bd</opc> + <opr>Gv Ev</opr> + </def> + </instruction> + + <instruction> + <mnemonic>bswap</mnemonic> + <def> + <pfx>oso rexw rexb</pfx> + <opc>0f c8</opc> + <opr>R0y</opr> + </def> + <def> + <pfx>oso rexw rexb</pfx> + <opc>0f c9</opc> + <opr>R1y</opr> + </def> + <def> + <pfx>oso rexw rexb</pfx> + <opc>0f ca</opc> + <opr>R2y</opr> + </def> + <def> + <pfx>oso rexw rexb</pfx> + <opc>0f cb</opc> + <opr>R3y</opr> + </def> + <def> + <pfx>oso rexw rexb</pfx> + <opc>0f cc</opc> + <opr>R4y</opr> + </def> + <def> + <pfx>oso rexw rexb</pfx> + <opc>0f cd</opc> + <opr>R5y</opr> + </def> + <def> + <pfx>oso rexw rexb</pfx> + <opc>0f ce</opc> + <opr>R6y</opr> + </def> + <def> + <pfx>oso rexw rexb</pfx> + <opc>0f cf</opc> + <opr>R7y</opr> + </def> + </instruction> + + <instruction> + <mnemonic>bt</mnemonic> + <def> + <pfx>aso oso rexw rexr rexx rexb</pfx> + <opc>0f ba /reg=4</opc> + <opr>Ev Ib</opr> + </def> + <def> + <pfx>aso oso rexw rexr rexx rexb</pfx> + <opc>0f a3</opc> + <opr>Ev Gv</opr> + </def> + </instruction> + + <instruction> + <mnemonic>btc</mnemonic> + <def> + <pfx>aso oso rexw rexr rexx rexb</pfx> + <opc>0f bb</opc> + <opr>Ev Gv</opr> + </def> + <def> + <pfx>aso oso rexw rexr rexx rexb</pfx> + <opc>0f ba /reg=7</opc> + <opr>Ev Ib</opr> + </def> + </instruction> + + <instruction> + <mnemonic>btr</mnemonic> + <def> + <pfx>aso oso rexw rexr rexx rexb</pfx> + <opc>0f b3</opc> + <opr>Ev Gv</opr> + </def> + <def> + <pfx>aso oso rexw rexr rexx rexb</pfx> + <opc>0f ba /reg=6</opc> + <opr>Ev Ib</opr> + </def> + </instruction> + + <instruction> + <mnemonic>bts</mnemonic> + <def> + <pfx>aso oso rexw rexr rexx rexb</pfx> + <opc>0f ab</opc> + <opr>Ev Gv</opr> + </def> + <def> + <pfx>aso oso rexw rexr rexx rexb</pfx> + <opc>0f ba /reg=5</opc> + <opr>Ev Ib</opr> + </def> + </instruction> + + <instruction> + <mnemonic>pblendw</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>/sse=66 0f 3a 0e</opc> + <opr>V H W Ib</opr> + <cpuid>sse4.1 avx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>mpsadbw</mnemonic> + <def> + <pfx>aso rexr rexx rexb vexl</pfx> + <opc>/sse=66 0f 3a 42</opc> + <opr>V H W Ib</opr> + <cpuid>sse4.1 avx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>movntdqa</mnemonic> + <def> + <pfx>aso rexr rexw rexx rexb vexl</pfx> + <opc>/sse=66 0f 38 2a</opc> + <opr>V M</opr> + <cpuid>sse4.1 avx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>packusdw</mnemonic> + <def> + <pfx>aso rexr rexw rexx rexb vexl</pfx> + <opc>/sse=66 0f 38 2b</opc> + <opr>V H W</opr> + <cpuid>sse2 avx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>pmovsxbw</mnemonic> + <def> + <pfx>aso rexr rexw rexx rexb</pfx> + <opc>/sse=66 0f 38 20</opc> + <opr>V MqU</opr> + <cpuid>sse4.1 avx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>pmovsxbd</mnemonic> + <def> + <pfx>aso rexr rexw rexx rexb</pfx> + <opc>/sse=66 0f 38 21</opc> + <opr>V MdU</opr> + <cpuid>sse4.1 avx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>pmovsxbq</mnemonic> + <def> + <pfx>aso rexr rexw rexx rexb</pfx> + <opc>/sse=66 0f 38 22</opc> + <opr>V MwU</opr> + <cpuid>sse4.1 avx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>pmovsxwd</mnemonic> + <def> + <pfx>aso rexr rexw rexx rexb</pfx> + <opc>/sse=66 0f 38 23</opc> + <opr>V MqU</opr> + <cpuid>sse4.1 avx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>pmovsxwq</mnemonic> + <def> + <pfx>aso rexr rexw rexx rexb</pfx> + <opc>/sse=66 0f 38 24</opc> + <opr>V MdU</opr> + <cpuid>sse4.1 avx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>pmovsxdq</mnemonic> + <def> + <pfx>aso rexr rexw rexx rexb</pfx> + <opc>/sse=66 0f 38 25</opc> + <opr>V MqU</opr> + <cpuid>sse4.1</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>pmovzxbw</mnemonic> + <def> + <pfx>aso rexr rexw rexx rexb</pfx> + <opc>/sse=66 0f 38 30</opc> + <opr>V MqU</opr> + <cpuid>sse4.1 avx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>pmovzxbd</mnemonic> + <def> + <pfx>aso rexr rexw rexx rexb</pfx> + <opc>/sse=66 0f 38 31</opc> + <opr>V MdU</opr> + <cpuid>sse4.1 avx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>pmovzxbq</mnemonic> + <def> + <pfx>aso rexr rexw rexx rexb</pfx> + <opc>/sse=66 0f 38 32</opc> + <opr>V MwU</opr> + <cpuid>sse4.1 avx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>pmovzxwd</mnemonic> + <def> + <pfx>aso rexr rexw rexx rexb</pfx> + <opc>/sse=66 0f 38 33</opc> + <opr>V MqU</opr> + <cpuid>sse4.1 avx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>pmovzxwq</mnemonic> + <def> + <pfx>aso rexr rexw rexx rexb</pfx> + <opc>/sse=66 0f 38 34</opc> + <opr>V MdU</opr> + <cpuid>sse4.1 avx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>pmovzxdq</mnemonic> + <def> + <pfx>aso rexr rexw rexx rexb</pfx> + <opc>/sse=66 0f 38 35</opc> + <opr>V MqU</opr> + <cpuid>sse4.1 avx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>pcmpeqq</mnemonic> + <def> + <pfx>aso rexr rexw rexx rexb</pfx> + <opc>/sse=66 0f 38 29</opc> + <opr>V H W</opr> + <cpuid>sse4.1 avx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>popcnt</mnemonic> + <def> + <pfx>aso oso rexr rexw rexx rexb</pfx> + <opc>/sse=f3 0f b8</opc> + <opr>Gv Ev</opr> + </def> + <cpuid>sse4.2</cpuid> + </instruction> + + <instruction> + <mnemonic>ptest</mnemonic> + <def> + <pfx>aso rexr rexw rexx rexb vexl</pfx> + <opc>/sse=66 0f 38 17</opc> + <opr>V W</opr> + <cpuid>sse4.1 avx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>pcmpestri</mnemonic> + <def> + <pfx>aso rexr rexw rexx rexb</pfx> + <opc>/sse=66 0f 3a 61</opc> + <opr>V W Ib</opr> + <cpuid>sse4.2 avx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>pcmpestrm</mnemonic> + <def> + <pfx>aso rexr rexw rexx rexb</pfx> + <opc>/sse=66 0f 3a 60</opc> + <opr>V W Ib</opr> + <cpuid>sse4.2 avx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>pcmpgtq</mnemonic> + <def> + <pfx>aso rexr rexw rexx rexb</pfx> + <opc>/sse=66 0f 38 37</opc> + <opr>V H W</opr> + <cpuid>sse4.2 avx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>pcmpistri</mnemonic> + <def> + <pfx>aso rexr rexw rexx rexb</pfx> + <opc>/sse=66 0f 3a 63</opc> + <opr>V W Ib</opr> + <cpuid>sse4.2 avx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>pcmpistrm</mnemonic> + <def> + <pfx>aso rexr rexw rexx rexb</pfx> + <opc>/sse=66 0f 3a 62</opc> + <opr>V W Ib</opr> + <cpuid>sse4.2 avx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>movbe</mnemonic> + <def> + <pfx>aso oso rexr rexw rexx rexb</pfx> + <opc>0f 38 f0</opc> + <opr>Gv Mv</opr> + <cpuid>sse3 atom</cpuid> + </def> + <def> + <pfx>aso oso rexr rexw rexx rexb</pfx> + <opc>0f 38 f1</opc> + <opr>Mv Gv</opr> + <cpuid>sse3 atom</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>crc32</mnemonic> + <def> + <pfx>aso oso rexr rexw rexx rexb</pfx> + <opc>/sse=f2 0f 38 f0</opc> + <opr>Gy Eb</opr> + <cpuid>sse4.2</cpuid> + </def> + <def> + <pfx>aso oso rexr rexw rexx rexb</pfx> + <opc>/sse=f2 0f 38 f1</opc> + <opr>Gy Ev</opr> + <cpuid>sse4.2</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>invalid</mnemonic> + </instruction> + + <instruction> + <mnemonic>vbroadcastss</mnemonic> + <def> + <pfx>aso rexr rexx rexb vexl</pfx> + <opc>/vex=66_0f38 18 /vexw=0</opc> + <opr>V Md</opr> + <cpuid>avx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>vbroadcastsd</mnemonic> + <def> + <pfx>aso rexr rexx rexb vexl</pfx> + <opc>/vex=66_0f38 19 /vexw=0 /vexl=1</opc> + <opr>Vqq Mq</opr> + <cpuid>avx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>vextractf128</mnemonic> + <def> + <pfx>aso rexr rexx rexb vexl</pfx> + <opc>/vex=66_0f3a 19 /vexw=0 /vexl=1</opc> + <opr>Wdq Vqq Ib</opr> + <cpuid>avx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>vinsertf128</mnemonic> + <def> + <pfx>aso rexr rexx rexb vexl</pfx> + <opc>/vex=66_0f3a 18 /vexw=0 /vexl=1</opc> + <opr>Vqq Hqq Wdq Ib</opr> + <cpuid>avx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>vmaskmovps</mnemonic> + <def> + <pfx>aso rexr rexx rexb vexl</pfx> + <opc>/vex=66_0f38 2c /vexw=0</opc> + <opr>V H M</opr> + <cpuid>avx</cpuid> + </def> + <def> + <pfx>aso rexr rexx rexb vexl</pfx> + <opc>/vex=66_0f38 2e /vexw=0</opc> + <opr>M H V</opr> + <cpuid>avx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>vmaskmovpd</mnemonic> + <def> + <pfx>aso rexr rexx rexb vexl</pfx> + <opc>/vex=66_0f38 2d /vexw=0</opc> + <opr>V H M</opr> + <cpuid>avx</cpuid> + </def> + <def> + <pfx>aso rexr rexx rexb vexl</pfx> + <opc>/vex=66_0f38 2f /vexw=0</opc> + <opr>M H V</opr> + <cpuid>avx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>vpermilpd</mnemonic> + <def> + <pfx>aso rexr rexx rexb vexl</pfx> + <opc>/vex=66_0f38 0d /vexw=0</opc> + <opr>Vx Hx Wx</opr> + <cpuid>avx</cpuid> + </def> + <def> + <pfx>aso rexr rexx rexb vexl</pfx> + <opc>/vex=66_0f3a 05 /vexw=0</opc> + <opr>V W Ib</opr> + <cpuid>avx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>vpermilps</mnemonic> + <def> + <pfx>aso rexr rexx rexb vexl</pfx> + <opc>/vex=66_0f38 0c /vexw=0</opc> + <opr>Vx Hx Wx</opr> + <cpuid>avx</cpuid> + </def> + <def> + <pfx>aso rexr rexx rexb vexl</pfx> + <opc>/vex=66_0f3a 04 /vexw=0</opc> + <opr>Vx Wx Ib</opr> + <cpuid>avx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>vperm2f128</mnemonic> + <def> + <pfx>aso rexr rexx rexb vexl</pfx> + <opc>/vex=66_0f3a 06 /vexw=0 /vexl=1</opc> + <opr>Vqq Hqq Wqq Ib</opr> + <cpuid>avx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>vtestps</mnemonic> + <def> + <pfx>aso rexr rexx rexb vexl</pfx> + <opc>/vex=66_0f38 0e /vexw=0</opc> + <opr>Vx Wx</opr> + <cpuid>avx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>vtestpd</mnemonic> + <def> + <pfx>aso rexr rexx rexb vexl</pfx> + <opc>/vex=66_0f38 0f /vexw=0</opc> + <opr>Vx Wx</opr> + <cpuid>avx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>vzeroupper</mnemonic> + <def> + <opc>/vex=0f 77 /vexl=0</opc> + <cpuid>avx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>vzeroall</mnemonic> + <def> + <opc>/vex=0f 77 /vexl=1</opc> + <cpuid>avx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>vblendvpd</mnemonic> + <def> + <pfx>aso rexr rexx rexb vexl</pfx> + <opc>/vex=66_0f3a 4b /vexw=0</opc> + <opr>Vx Hx Wx Lx</opr> + <cpuid>avx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>vblendvps</mnemonic> + <def> + <pfx>aso rexr rexx rexb vexl</pfx> + <opc>/vex=66_0f3a 4a /vexw=0</opc> + <opr>Vx Hx Wx Lx</opr> + <cpuid>avx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>vmovsd</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>/vex=f2_0f 10 /mod=11</opc> + <opr>V H U</opr> + <cpuid>avx</cpuid> + </def> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>/vex=f2_0f 10 /mod=!11</opc> + <opr>V Mq</opr> + <cpuid>avx</cpuid> + </def> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>/vex=f2_0f 11 /mod=11</opc> + <opr>U H V</opr> + <cpuid>avx</cpuid> + </def> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>/vex=f2_0f 11 /mod=!11</opc> + <opr>Mq V</opr> + <cpuid>avx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>vmovss</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>/vex=f3_0f 10 /mod=11</opc> + <opr>V H U</opr> + <cpuid>avx</cpuid> + </def> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>/vex=f3_0f 10 /mod=!11</opc> + <opr>V Md</opr> + <cpuid>avx</cpuid> + </def> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>/vex=f3_0f 11 /mod=11</opc> + <opr>U H V</opr> + <cpuid>avx</cpuid> + </def> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>/vex=f3_0f 11 /mod=!11</opc> + <opr>Md V</opr> + <cpuid>avx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>vpblendvb</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>/vex=66_0f3a 4c /vexw=0</opc> + <opr>V H W L</opr> + <cpuid>avx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>vpsllw</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>/vex=66_0f f1 /vexl=0</opc> + <opr>V H W</opr> + <cpuid>avx</cpuid> + </def> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>/vex=66_0f 71 /reg=6 /vexl=0</opc> + <opr>H V W</opr> + <cpuid>avx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>vpslld</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>/vex=66_0f f2 /vexl=0</opc> + <opr>V H W</opr> + <cpuid>avx</cpuid> + </def> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>/vex=66_0f 72 /reg=6 /vexl=0</opc> + <opr>H V W</opr> + <cpuid>avx</cpuid> + </def> + </instruction> + + <instruction> + <mnemonic>vpsllq</mnemonic> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>/vex=66_0f f3 /vexl=0</opc> + <opr>V H W</opr> + <cpuid>avx</cpuid> + </def> + <def> + <pfx>aso rexr rexx rexb</pfx> + <opc>/vex=66_0f 73 /reg=6 /vexl=0</opc> + <opr>H V W</opr> + <cpuid>avx</cpuid> + </def> + </instruction> + +</x86optable> diff --git a/Source/JavaScriptCore/disassembler/udis86/ud_itab.py b/Source/JavaScriptCore/disassembler/udis86/ud_itab.py new file mode 100644 index 000000000..ef011d2ec --- /dev/null +++ b/Source/JavaScriptCore/disassembler/udis86/ud_itab.py @@ -0,0 +1,379 @@ +# udis86 - scripts/ud_itab.py +# +# Copyright (c) 2009, 2013 Vivek Thampi +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without modification, +# are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +# ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +import os +import sys +from ud_opcode import UdOpcodeTable, UdOpcodeTables, UdInsnDef + +class UdItabGenerator: + + OperandDict = { + "Av" : [ "OP_A" , "SZ_V" ], + "E" : [ "OP_E" , "SZ_NA" ], + "Eb" : [ "OP_E" , "SZ_B" ], + "Ew" : [ "OP_E" , "SZ_W" ], + "Ev" : [ "OP_E" , "SZ_V" ], + "Ed" : [ "OP_E" , "SZ_D" ], + "Ey" : [ "OP_E" , "SZ_Y" ], + "Eq" : [ "OP_E" , "SZ_Q" ], + "Ez" : [ "OP_E" , "SZ_Z" ], + "Fv" : [ "OP_F" , "SZ_V" ], + "G" : [ "OP_G" , "SZ_NA" ], + "Gb" : [ "OP_G" , "SZ_B" ], + "Gw" : [ "OP_G" , "SZ_W" ], + "Gv" : [ "OP_G" , "SZ_V" ], + "Gy" : [ "OP_G" , "SZ_Y" ], + "Gd" : [ "OP_G" , "SZ_D" ], + "Gq" : [ "OP_G" , "SZ_Q" ], + "Gz" : [ "OP_G" , "SZ_Z" ], + "M" : [ "OP_M" , "SZ_NA" ], + "Mb" : [ "OP_M" , "SZ_B" ], + "Mw" : [ "OP_M" , "SZ_W" ], + "Ms" : [ "OP_M" , "SZ_W" ], + "Md" : [ "OP_M" , "SZ_D" ], + "Mq" : [ "OP_M" , "SZ_Q" ], + "Mdq" : [ "OP_M" , "SZ_DQ" ], + "Mv" : [ "OP_M" , "SZ_V" ], + "Mt" : [ "OP_M" , "SZ_T" ], + "Mo" : [ "OP_M" , "SZ_O" ], + "MbRd" : [ "OP_MR" , "SZ_BD" ], + "MbRv" : [ "OP_MR" , "SZ_BV" ], + "MwRv" : [ "OP_MR" , "SZ_WV" ], + "MwRd" : [ "OP_MR" , "SZ_WD" ], + "MwRy" : [ "OP_MR" , "SZ_WY" ], + "MdRy" : [ "OP_MR" , "SZ_DY" ], + "I1" : [ "OP_I1" , "SZ_NA" ], + "I3" : [ "OP_I3" , "SZ_NA" ], + "Ib" : [ "OP_I" , "SZ_B" ], + "Iw" : [ "OP_I" , "SZ_W" ], + "Iv" : [ "OP_I" , "SZ_V" ], + "Iz" : [ "OP_I" , "SZ_Z" ], + "sIb" : [ "OP_sI" , "SZ_B" ], + "sIz" : [ "OP_sI" , "SZ_Z" ], + "sIv" : [ "OP_sI" , "SZ_V" ], + "Jv" : [ "OP_J" , "SZ_V" ], + "Jz" : [ "OP_J" , "SZ_Z" ], + "Jb" : [ "OP_J" , "SZ_B" ], + "R" : [ "OP_R" , "SZ_RDQ" ], + "C" : [ "OP_C" , "SZ_NA" ], + "D" : [ "OP_D" , "SZ_NA" ], + "S" : [ "OP_S" , "SZ_W" ], + "Ob" : [ "OP_O" , "SZ_B" ], + "Ow" : [ "OP_O" , "SZ_W" ], + "Ov" : [ "OP_O" , "SZ_V" ], + "U" : [ "OP_U" , "SZ_O" ], + "Ux" : [ "OP_U" , "SZ_X" ], + "V" : [ "OP_V" , "SZ_DQ" ], + "Vdq" : [ "OP_V" , "SZ_DQ" ], + "Vqq" : [ "OP_V" , "SZ_QQ" ], + "Vsd" : [ "OP_V" , "SZ_Q" ], + "Vx" : [ "OP_V" , "SZ_X" ], + "H" : [ "OP_H" , "SZ_X" ], + "Hx" : [ "OP_H" , "SZ_X" ], + "Hqq" : [ "OP_H" , "SZ_QQ" ], + "W" : [ "OP_W" , "SZ_DQ" ], + "Wdq" : [ "OP_W" , "SZ_DQ" ], + "Wqq" : [ "OP_W" , "SZ_QQ" ], + "Wsd" : [ "OP_W" , "SZ_Q" ], + "Wx" : [ "OP_W" , "SZ_X" ], + "L" : [ "OP_L" , "SZ_O" ], + "Lx" : [ "OP_L" , "SZ_X" ], + "MwU" : [ "OP_MU" , "SZ_WO" ], + "MdU" : [ "OP_MU" , "SZ_DO" ], + "MqU" : [ "OP_MU" , "SZ_QO" ], + "N" : [ "OP_N" , "SZ_Q" ], + "P" : [ "OP_P" , "SZ_Q" ], + "Q" : [ "OP_Q" , "SZ_Q" ], + "AL" : [ "OP_AL" , "SZ_B" ], + "AX" : [ "OP_AX" , "SZ_W" ], + "eAX" : [ "OP_eAX" , "SZ_Z" ], + "rAX" : [ "OP_rAX" , "SZ_V" ], + "CL" : [ "OP_CL" , "SZ_B" ], + "CX" : [ "OP_CX" , "SZ_W" ], + "eCX" : [ "OP_eCX" , "SZ_Z" ], + "rCX" : [ "OP_rCX" , "SZ_V" ], + "DL" : [ "OP_DL" , "SZ_B" ], + "DX" : [ "OP_DX" , "SZ_W" ], + "eDX" : [ "OP_eDX" , "SZ_Z" ], + "rDX" : [ "OP_rDX" , "SZ_V" ], + "R0b" : [ "OP_R0" , "SZ_B" ], + "R1b" : [ "OP_R1" , "SZ_B" ], + "R2b" : [ "OP_R2" , "SZ_B" ], + "R3b" : [ "OP_R3" , "SZ_B" ], + "R4b" : [ "OP_R4" , "SZ_B" ], + "R5b" : [ "OP_R5" , "SZ_B" ], + "R6b" : [ "OP_R6" , "SZ_B" ], + "R7b" : [ "OP_R7" , "SZ_B" ], + "R0w" : [ "OP_R0" , "SZ_W" ], + "R1w" : [ "OP_R1" , "SZ_W" ], + "R2w" : [ "OP_R2" , "SZ_W" ], + "R3w" : [ "OP_R3" , "SZ_W" ], + "R4w" : [ "OP_R4" , "SZ_W" ], + "R5w" : [ "OP_R5" , "SZ_W" ], + "R6w" : [ "OP_R6" , "SZ_W" ], + "R7w" : [ "OP_R7" , "SZ_W" ], + "R0v" : [ "OP_R0" , "SZ_V" ], + "R1v" : [ "OP_R1" , "SZ_V" ], + "R2v" : [ "OP_R2" , "SZ_V" ], + "R3v" : [ "OP_R3" , "SZ_V" ], + "R4v" : [ "OP_R4" , "SZ_V" ], + "R5v" : [ "OP_R5" , "SZ_V" ], + "R6v" : [ "OP_R6" , "SZ_V" ], + "R7v" : [ "OP_R7" , "SZ_V" ], + "R0z" : [ "OP_R0" , "SZ_Z" ], + "R1z" : [ "OP_R1" , "SZ_Z" ], + "R2z" : [ "OP_R2" , "SZ_Z" ], + "R3z" : [ "OP_R3" , "SZ_Z" ], + "R4z" : [ "OP_R4" , "SZ_Z" ], + "R5z" : [ "OP_R5" , "SZ_Z" ], + "R6z" : [ "OP_R6" , "SZ_Z" ], + "R7z" : [ "OP_R7" , "SZ_Z" ], + "R0y" : [ "OP_R0" , "SZ_Y" ], + "R1y" : [ "OP_R1" , "SZ_Y" ], + "R2y" : [ "OP_R2" , "SZ_Y" ], + "R3y" : [ "OP_R3" , "SZ_Y" ], + "R4y" : [ "OP_R4" , "SZ_Y" ], + "R5y" : [ "OP_R5" , "SZ_Y" ], + "R6y" : [ "OP_R6" , "SZ_Y" ], + "R7y" : [ "OP_R7" , "SZ_Y" ], + "ES" : [ "OP_ES" , "SZ_NA" ], + "CS" : [ "OP_CS" , "SZ_NA" ], + "DS" : [ "OP_DS" , "SZ_NA" ], + "SS" : [ "OP_SS" , "SZ_NA" ], + "GS" : [ "OP_GS" , "SZ_NA" ], + "FS" : [ "OP_FS" , "SZ_NA" ], + "ST0" : [ "OP_ST0" , "SZ_NA" ], + "ST1" : [ "OP_ST1" , "SZ_NA" ], + "ST2" : [ "OP_ST2" , "SZ_NA" ], + "ST3" : [ "OP_ST3" , "SZ_NA" ], + "ST4" : [ "OP_ST4" , "SZ_NA" ], + "ST5" : [ "OP_ST5" , "SZ_NA" ], + "ST6" : [ "OP_ST6" , "SZ_NA" ], + "ST7" : [ "OP_ST7" , "SZ_NA" ], + "NONE" : [ "OP_NONE" , "SZ_NA" ], + } + + # + # opcode prefix dictionary + # + PrefixDict = { + "rep" : "P_str", + "repz" : "P_strz", + "aso" : "P_aso", + "oso" : "P_oso", + "rexw" : "P_rexw", + "rexb" : "P_rexb", + "rexx" : "P_rexx", + "rexr" : "P_rexr", + "vexl" : "P_vexl", + "vexw" : "P_vexw", + "seg" : "P_seg", + "inv64" : "P_inv64", + "def64" : "P_def64", + "cast" : "P_cast", + } + + MnemonicAliases = ( "invalid", "3dnow", "none", "db", "pause" ) + + def __init__(self, tables): + self.tables = tables + self._insnIndexMap, i = {}, 0 + for insn in tables.getInsnList(): + self._insnIndexMap[insn], i = i, i + 1 + + self._tableIndexMap, i = {}, 0 + for table in tables.getTableList(): + self._tableIndexMap[table], i = i, i + 1 + + def getInsnIndex(self, insn): + assert isinstance(insn, UdInsnDef) + return self._insnIndexMap[insn] + + def getTableIndex(self, table): + assert isinstance(table, UdOpcodeTable) + return self._tableIndexMap[table] + + def getTableName(self, table): + return "ud_itab__%d" % self.getTableIndex(table) + + def genOpcodeTable(self, table, isGlobal=False): + """Emit Opcode Table in C. + """ + self.ItabC.write( "\n" ); + if not isGlobal: + self.ItabC.write('static ') + self.ItabC.write( "const uint16_t %s[] = {\n" % self.getTableName(table)) + for i in range(table.size()): + if i > 0 and i % 4 == 0: + self.ItabC.write( "\n" ) + if i % 4 == 0: + self.ItabC.write( " /* %2x */" % i) + e = table.entryAt(i) + if e is None: + self.ItabC.write("%12s," % "INVALID") + elif isinstance(e, UdOpcodeTable): + self.ItabC.write("%12s," % ("GROUP(%d)" % self.getTableIndex(e))) + elif isinstance(e, UdInsnDef): + self.ItabC.write("%12s," % self.getInsnIndex(e)) + self.ItabC.write( "\n" ) + self.ItabC.write( "};\n" ) + + + def genOpcodeTables(self): + tables = self.tables.getTableList() + for table in tables: + self.genOpcodeTable(table, table is self.tables.root) + + + def genOpcodeTablesLookupIndex(self): + self.ItabC.write( "\n\n" ); + self.ItabC.write( "struct ud_lookup_table_list_entry ud_lookup_table_list[] = {\n" ) + for table in self.tables.getTableList(): + f0 = self.getTableName(table) + "," + f1 = table.label() + "," + f2 = "\"%s\"" % table.meta() + self.ItabC.write(" /* %03d */ { %s %s %s },\n" % + (self.getTableIndex(table), f0, f1, f2)) + self.ItabC.write( "};" ) + + + def genInsnTable( self ): + self.ItabC.write( "struct ud_itab_entry ud_itab[] = {\n" ); + for insn in self.tables.getInsnList(): + opr_c = [ "O_NONE", "O_NONE", "O_NONE", "O_NONE" ] + pfx_c = [] + opr = insn.operands + for i in range(len(opr)): + if not (opr[i] in self.OperandDict.keys()): + print("error: invalid operand declaration: %s\n" % opr[i]) + opr_c[i] = "O_" + opr[i] + opr = "%s %s %s %s" % (opr_c[0] + ",", opr_c[1] + ",", + opr_c[2] + ",", opr_c[3]) + + for p in insn.prefixes: + if not ( p in self.PrefixDict.keys() ): + print("error: invalid prefix specification: %s \n" % pfx) + pfx_c.append( self.PrefixDict[p] ) + if len(insn.prefixes) == 0: + pfx_c.append( "P_none" ) + pfx = "|".join( pfx_c ) + + self.ItabC.write( " /* %04d */ { UD_I%s %s, %s },\n" \ + % ( self.getInsnIndex(insn), insn.mnemonic + ',', opr, pfx ) ) + self.ItabC.write( "};\n" ) + + + def getMnemonicsList(self): + mnemonics = self.tables.getMnemonicsList() + mnemonics.extend(self.MnemonicAliases) + return mnemonics + + def genMnemonicsList(self): + mnemonics = self.getMnemonicsList() + self.ItabC.write( "\n\n" ); + self.ItabC.write( "const char* ud_mnemonics_str[] = {\n " ) + self.ItabC.write( ",\n ".join( [ "\"%s\"" % m for m in mnemonics ] ) ) + self.ItabC.write( "\n};\n" ) + + + def genItabH( self, filePath ): + self.ItabH = open( filePath, "w" ) + + # Generate Table Type Enumeration + self.ItabH.write( "#ifndef UD_ITAB_H\n" ) + self.ItabH.write( "#define UD_ITAB_H\n\n" ) + + self.ItabH.write("/* itab.h -- generated by udis86:scripts/ud_itab.py, do no edit */\n\n") + + # table type enumeration + self.ItabH.write( "/* ud_table_type -- lookup table types (see decode.c) */\n" ) + self.ItabH.write( "enum ud_table_type {\n " ) + enum = UdOpcodeTable.getLabels() + self.ItabH.write( ",\n ".join( enum ) ) + self.ItabH.write( "\n};\n\n" ); + + # mnemonic enumeration + self.ItabH.write( "/* ud_mnemonic -- mnemonic constants */\n" ) + enum = "enum ud_mnemonic_code {\n " + enum += ",\n ".join( [ "UD_I%s" % m for m in self.getMnemonicsList() ] ) + enum += ",\n UD_MAX_MNEMONIC_CODE" + enum += "\n};\n" + self.ItabH.write( enum ) + self.ItabH.write( "\n" ) + + self.ItabH.write( "extern const char * ud_mnemonics_str[];\n" ) + + self.ItabH.write( "\n#endif /* UD_ITAB_H */\n" ) + + self.ItabH.close() + + + def genItabC(self, filePath): + self.ItabC = open(filePath, "w") + self.ItabC.write("/* itab.c -- generated by udis86:scripts/ud_itab.py, do no edit") + self.ItabC.write(" */\n"); + self.ItabC.write("#include \"udis86_decode.h\"\n\n"); + + self.ItabC.write("#define GROUP(n) (0x8000 | (n))\n") + self.ItabC.write("#define INVALID %d\n\n" % self.getInsnIndex(self.tables.invalidInsn)) + + self.genOpcodeTables() + self.genOpcodeTablesLookupIndex() + + # + # Macros defining short-names for operands + # + self.ItabC.write("\n\n/* itab entry operand definitions (for readability) */\n"); + operands = self.OperandDict.keys() + operands = sorted(operands) + for o in operands: + self.ItabC.write("#define O_%-7s { %-12s %-8s }\n" % + (o, self.OperandDict[o][0] + ",", self.OperandDict[o][1])); + self.ItabC.write("\n"); + + self.genInsnTable() + self.genMnemonicsList() + + self.ItabC.close() + + def genItab( self, location ): + self.genItabC(os.path.join(location, "udis86_itab.c")) + self.genItabH(os.path.join(location, "udis86_itab.h")) + +def usage(): + print("usage: ud_itab.py <optable.xml> <output-path>") + +def main(): + + if len(sys.argv) != 3: + usage() + sys.exit(1) + + tables = UdOpcodeTables(xml=sys.argv[1]) + itab = UdItabGenerator(tables) + itab.genItab(sys.argv[2]) + +if __name__ == '__main__': + main() diff --git a/Source/JavaScriptCore/disassembler/udis86/ud_opcode.py b/Source/JavaScriptCore/disassembler/udis86/ud_opcode.py new file mode 100644 index 000000000..fe1833dc7 --- /dev/null +++ b/Source/JavaScriptCore/disassembler/udis86/ud_opcode.py @@ -0,0 +1,622 @@ +# udis86 - scripts/ud_opcode.py +# +# Copyright (c) 2009, 2013 Vivek Thampi +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without modification, +# are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +# ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +import os + +# Some compatibility stuff for supporting python 2.x as well as python 3.x +def itemslist(dict): + try: + return dict.iteritems() # python 2.x + except AttributeError: + return list(dict.items()) # python 3.x + +class UdInsnDef: + """An x86 instruction definition + """ + def __init__(self, **insnDef): + self.mnemonic = insnDef['mnemonic'] + self.prefixes = insnDef['prefixes'] + self.opcodes = insnDef['opcodes'] + self.operands = insnDef['operands'] + self._cpuid = insnDef['cpuid'] + self._opcexts = {} + + for opc in self.opcodes: + if opc.startswith('/'): + e, v = opc.split('=') + self._opcexts[e] = v + + def lookupPrefix(self, pfx): + """Lookup prefix (if any, None otherwise), by name""" + return True if pfx in self.prefixes else None + + + @property + def vendor(self): + return self._opcexts.get('/vendor', None) + + @property + def mode(self): + return self._opcexts.get('/m', None) + + @property + def osize(self): + return self._opcexts.get('/o', None) + + def isDef64(self): + return 'def64' in self.prefixes + + def __str__(self): + return self.mnemonic + " " + ', '.join(self.operands) + \ + " " + ' '.join(self.opcodes) + + +class UdOpcodeTable: + """A single table of instruction definitions, indexed by + a decode field. + """ + + class CollisionError(Exception): + pass + + class IndexError(Exception): + """Invalid Index Error""" + pass + + @classmethod + def vendor2idx(cls, v): + return (0 if v == 'amd' + else (1 if v == 'intel' + else 2)) + + @classmethod + def vex2idx(cls, v): + if v.startswith("none_"): + v = v[5:] + vexOpcExtMap = { + 'none' : 0x0, + '0f' : 0x1, + '0f38' : 0x2, + '0f3a' : 0x3, + '66' : 0x4, + '66_0f' : 0x5, + '66_0f38' : 0x6, + '66_0f3a' : 0x7, + 'f3' : 0x8, + 'f3_0f' : 0x9, + 'f3_0f38' : 0xa, + 'f3_0f3a' : 0xb, + 'f2' : 0xc, + 'f2_0f' : 0xd, + 'f2_0f38' : 0xe, + 'f2_0f3a' : 0xf, + } + return vexOpcExtMap[v] + + + # A mapping of opcode extensions to their representational + # values used in the opcode map. + OpcExtMap = { + '/rm' : lambda v: int(v, 16), + '/x87' : lambda v: int(v, 16), + '/3dnow' : lambda v: int(v, 16), + '/reg' : lambda v: int(v, 16), + # modrm.mod + # (!11, 11) => (00b, 01b) + '/mod' : lambda v: 0 if v == '!11' else 1, + # Mode extensions: + # (16, 32, 64) => (00, 01, 02) + '/o' : lambda v: (int(v) / 32), + '/a' : lambda v: (int(v) / 32), + # Disassembly mode + # (!64, 64) => (00b, 01b) + '/m' : lambda v: 1 if v == '64' else 0, + # SSE + # none => 0 + # f2 => 1 + # f3 => 2 + # 66 => 3 + '/sse' : lambda v: (0 if v == 'none' + else (((int(v, 16) & 0xf) + 1) / 2)), + # AVX + '/vex' : lambda v: UdOpcodeTable.vex2idx(v), + '/vexw' : lambda v: 0 if v == '0' else 1, + '/vexl' : lambda v: 0 if v == '0' else 1, + # Vendor + '/vendor': lambda v: UdOpcodeTable.vendor2idx(v) + } + + + _TableInfo = { + 'opctbl' : { 'label' : 'UD_TAB__OPC_TABLE', 'size' : 256 }, + '/sse' : { 'label' : 'UD_TAB__OPC_SSE', 'size' : 4 }, + '/reg' : { 'label' : 'UD_TAB__OPC_REG', 'size' : 8 }, + '/rm' : { 'label' : 'UD_TAB__OPC_RM', 'size' : 8 }, + '/mod' : { 'label' : 'UD_TAB__OPC_MOD', 'size' : 2 }, + '/m' : { 'label' : 'UD_TAB__OPC_MODE', 'size' : 2 }, + '/x87' : { 'label' : 'UD_TAB__OPC_X87', 'size' : 64 }, + '/a' : { 'label' : 'UD_TAB__OPC_ASIZE', 'size' : 3 }, + '/o' : { 'label' : 'UD_TAB__OPC_OSIZE', 'size' : 3 }, + '/3dnow' : { 'label' : 'UD_TAB__OPC_3DNOW', 'size' : 256 }, + '/vendor' : { 'label' : 'UD_TAB__OPC_VENDOR', 'size' : 3 }, + '/vex' : { 'label' : 'UD_TAB__OPC_VEX', 'size' : 16 }, + '/vexw' : { 'label' : 'UD_TAB__OPC_VEX_W', 'size' : 2 }, + '/vexl' : { 'label' : 'UD_TAB__OPC_VEX_L', 'size' : 2 }, + } + + + def __init__(self, typ): + assert typ in self._TableInfo + self._typ = typ + self._entries = {} + + + def size(self): + return self._TableInfo[self._typ]['size'] + + def entries(self): + return itemslist(self._entries) + + def numEntries(self): + return len(self._entries.keys()) + + def label(self): + return self._TableInfo[self._typ]['label'] + + def typ(self): + return self._typ + + def meta(self): + return self._typ + + + def __str__(self): + return "table-%s" % self._typ + + + def add(self, opc, obj): + typ = UdOpcodeTable.getOpcodeTyp(opc) + idx = UdOpcodeTable.getOpcodeIdx(opc) + if self._typ != typ or idx in self._entries: + raise CollisionError() + self._entries[idx] = obj + + + def lookup(self, opc): + typ = UdOpcodeTable.getOpcodeTyp(opc) + idx = UdOpcodeTable.getOpcodeIdx(opc) + if self._typ != typ: + raise UdOpcodeTable.CollisionError("%s <-> %s" % (self._typ, typ)) + return self._entries.get(idx, None) + + + def entryAt(self, index): + """Returns the entry at a given index of the table, + None if there is none. Raises an exception if the + index is out of bounds. + """ + if index < self.size(): + return self._entries.get(index, None) + raise self.IndexError("index out of bounds: %s" % index) + + def setEntryAt(self, index, obj): + if index < self.size(): + self._entries[index] = obj + else: + raise self.IndexError("index out of bounds: %s" % index) + + @classmethod + def getOpcodeTyp(cls, opc): + if opc.startswith('/'): + return opc.split('=')[0] + else: + return 'opctbl' + + + @classmethod + def getOpcodeIdx(cls, opc): + if opc.startswith('/'): + typ, v = opc.split('=') + return cls.OpcExtMap[typ](v) + else: + # plain opctbl opcode + return int(opc, 16) + + + @classmethod + def getLabels(cls): + """Returns a list of all labels""" + return [cls._TableInfo[k]['label'] for k in cls._TableInfo.keys()] + + +class UdOpcodeTables(object): + """Collection of opcode tables + """ + + class CollisionError(Exception): + def __init__(self, obj1, obj2): + self.obj1, self.obj2 = obj1, obj2 + + def newTable(self, typ): + """Create a new opcode table of a give type `typ`. """ + tbl = UdOpcodeTable(typ) + self._tables.append(tbl) + return tbl + + def mkTrie(self, opcodes, obj): + """Recursively contruct a trie entry mapping a string of + opcodes to an object. + """ + if len(opcodes) == 0: + return obj + opc = opcodes[0] + tbl = self.newTable(UdOpcodeTable.getOpcodeTyp(opc)) + tbl.add(opc, self.mkTrie(opcodes[1:], obj)) + return tbl + + def walk(self, tbl, opcodes): + """Walk down the opcode trie, starting at a given opcode + table, given a string of opcodes. Return None if unable + to walk, the object at the leaf otherwise. + """ + opc = opcodes[0] + e = tbl.lookup(opc) + if e is None: + return None + elif isinstance(e, UdOpcodeTable) and len(opcodes[1:]): + return self.walk(e, opcodes[1:]) + return e + + def map(self, tbl, opcodes, obj): + """Create a mapping from a given string of opcodes to an + object in the opcode trie. Constructs trie branches as + needed. + """ + opc = opcodes[0] + e = tbl.lookup(opc) + if e is None: + tbl.add(opc, self.mkTrie(opcodes[1:], obj)) + else: + if len(opcodes[1:]) == 0: + raise self.CollisionError(e, obj) + self.map(e, opcodes[1:], obj) + + def __init__(self, xml): + self._tables = [] + self._insns = [] + self._mnemonics = {} + + # The root table is always a 256 entry opctbl, indexed + # by a plain opcode byte + self.root = self.newTable('opctbl') + + if os.getenv("UD_OPCODE_DEBUG"): + self._logFh = open("opcodeTables.log", "w") + + # add an invalid instruction entry without any mapping + # in the opcode tables. + self.invalidInsn = UdInsnDef(mnemonic="invalid", opcodes=[], cpuid=[], + operands=[], prefixes=[]) + self._insns.append(self.invalidInsn) + + # Construct UdOpcodeTables object from the given + # udis86 optable.xml + for insn in self.__class__.parseOptableXML(xml): + self.addInsnDef(insn) + self.patchAvx2byte() + self.mergeSSENONE() + self.printStats() + + def log(self, s): + if os.getenv("UD_OPCODE_DEBUG"): + self._logFh.write(s + "\n") + + + def mergeSSENONE(self): + """Merge sse tables with only one entry for /sse=none + """ + for table in self._tables: + for k, e in table.entries(): + if isinstance(e, UdOpcodeTable) and e.typ() == '/sse': + if e.numEntries() == 1: + sse = e.lookup("/sse=none") + if sse: + table.setEntryAt(k, sse) + uniqTables = {} + def genTableList(tbl): + if tbl not in uniqTables: + self._tables.append(tbl) + uniqTables[tbl] = 1 + for k, e in tbl.entries(): + if isinstance(e, UdOpcodeTable): + genTableList(e) + self._tables = [] + genTableList(self.root) + + + def patchAvx2byte(self): + # create avx tables + for pp in (None, 'f2', 'f3', '66'): + for m in (None, '0f', '0f38', '0f3a'): + if pp is None and m is None: + continue + if pp is None: + vex = m + elif m is None: + vex = pp + else: + vex = pp + '_' + m + table = self.walk(self.root, ('c4', '/vex=' + vex)) + self.map(self.root, ('c5', '/vex=' + vex), table) + + + def addInsn(self, **insnDef): + + # Canonicalize opcode list + opcexts = insnDef['opcexts'] + opcodes = list(insnDef['opcodes']) + + # Re-order vex + if '/vex' in opcexts: + assert opcodes[0] == 'c4' or opcodes[0] == 'c5' + opcodes.insert(1, '/vex=' + opcexts['/vex']) + + # Add extensions. The order is important, and determines how + # well the opcode table is packed. Also note, /sse must be + # before /o, because /sse may consume operand size prefix + # affect the outcome of /o. + for ext in ('/mod', '/x87', '/reg', '/rm', '/sse', '/o', '/a', '/m', + '/vexw', '/vexl', '/3dnow', '/vendor'): + if ext in opcexts: + opcodes.append(ext + '=' + opcexts[ext]) + + insn = UdInsnDef(mnemonic = insnDef['mnemonic'], + prefixes = insnDef['prefixes'], + operands = insnDef['operands'], + opcodes = opcodes, + cpuid = insnDef['cpuid']) + try: + self.map(self.root, opcodes, insn) + except self.CollisionError as e: + self.pprint() + print(opcodes, insn, str(e.obj1), str(e.obj2)) + raise + except Exception as e: + self.pprint() + raise + self._insns.append(insn) + # add to lookup by mnemonic structure + if insn.mnemonic not in self._mnemonics: + self._mnemonics[insn.mnemonic] = [ insn ] + else: + self._mnemonics[insn.mnemonic].append(insn) + + + def addInsnDef(self, insnDef): + opcodes = [] + opcexts = {} + + # pack plain opcodes first, and collect opcode + # extensions + for opc in insnDef['opcodes']: + if not opc.startswith('/'): + opcodes.append(opc) + else: + e, v = opc.split('=') + opcexts[e] = v + + # treat vendor as an opcode extension + if len(insnDef['vendor']): + opcexts['/vendor'] = insnDef['vendor'][0] + + if insnDef['mnemonic'] in ('lds', 'les'): + # + # Massage lds and les, which share the same prefix as AVX + # instructions, to work well with the opcode tree. + # + opcexts['/vex'] = 'none' + elif '/vex' in opcexts: + # A proper avx instruction definition; make sure there are + # no legacy opcode extensions + assert '/sse' not in opcodes + + # make sure the opcode definitions don't already include + # the avx prefixes. + assert opcodes[0] not in ('c4', 'c5') + + # An avx only instruction is defined by the /vex= opcode + # extension. They do not include the c4 (long form) or + # c5 (short form) prefix. As part of opcode table generate, + # here we create the long form definition, and then patch + # the table for c5 in a later stage. + # Construct a long-form definition of the avx instruction + opcodes.insert(0, 'c4') + elif (opcodes[0] == '0f' and opcodes[1] != '0f' and + '/sse' not in opcexts): + # Make all 2-byte opcode form isntructions play nice with sse + # opcode maps. + opcexts['/sse'] = 'none' + + # legacy sse defs that get promoted to avx + fn = self.addInsn + if 'avx' in insnDef['cpuid'] and '/sse' in opcexts: + fn = self.addSSE2AVXInsn + + fn(mnemonic = insnDef['mnemonic'], + prefixes = insnDef['prefixes'], + opcodes = opcodes, + opcexts = opcexts, + operands = insnDef['operands'], + cpuid = insnDef['cpuid']) + + + def addSSE2AVXInsn(self, **insnDef): + """Add an instruction definition containing an avx cpuid bit, but + declared in its legacy SSE form. The function splits the + definition to create two new definitions, one for SSE and one + promoted to an AVX form. + """ + + # SSE + ssemnemonic = insnDef['mnemonic'] + sseopcodes = insnDef['opcodes'] + # remove vex opcode extensions + sseopcexts = dict([(e, v) for e, v in itemslist(insnDef['opcexts']) + if not e.startswith('/vex')]) + # strip out avx operands, preserving relative ordering + # of remaining operands + sseoperands = [opr for opr in insnDef['operands'] + if opr not in ('H', 'L')] + # strip out avx prefixes + sseprefixes = [pfx for pfx in insnDef['prefixes'] + if not pfx.startswith('vex')] + # strip out avx bits from cpuid + ssecpuid = [flag for flag in insnDef['cpuid'] + if not flag.startswith('avx')] + + self.addInsn(mnemonic = ssemnemonic, + prefixes = sseprefixes, + opcodes = sseopcodes, + opcexts = sseopcexts, + operands = sseoperands, + cpuid = ssecpuid) + + # AVX + vexmnemonic = 'v' + insnDef['mnemonic'] + vexprefixes = insnDef['prefixes'] + vexopcodes = ['c4'] + vexopcexts = dict([(e, insnDef['opcexts'][e]) + for e in insnDef['opcexts'] if e != '/sse']) + vexopcexts['/vex'] = insnDef['opcexts']['/sse'] + '_' + '0f' + if insnDef['opcodes'][1] == '38' or insnDef['opcodes'][1] == '3a': + vexopcexts['/vex'] += insnDef['opcodes'][1] + vexopcodes.extend(insnDef['opcodes'][2:]) + else: + vexopcodes.extend(insnDef['opcodes'][1:]) + vexoperands = [] + for o in insnDef['operands']: + # make the operand size explicit: x + if o in ('V', 'W', 'H', 'U'): + o = o + 'x' + vexoperands.append(o) + vexcpuid = [flag for flag in insnDef['cpuid'] + if not flag.startswith('sse')] + + self.addInsn(mnemonic = vexmnemonic, + prefixes = vexprefixes, + opcodes = vexopcodes, + opcexts = vexopcexts, + operands = vexoperands, + cpuid = vexcpuid) + + def getInsnList(self): + """Returns a list of all instructions in the collection""" + return self._insns + + + def getTableList(self): + """Returns a list of all tables in the collection""" + return self._tables + + def getMnemonicsList(self): + """Returns a sorted list of mnemonics""" + return sorted(self._mnemonics.keys()) + + + def pprint(self): + def printWalk(tbl, indent=""): + entries = tbl.entries() + for k, e in entries: + if isinstance(e, UdOpcodeTable): + self.log("%s |-<%02x> %s" % (indent, k, e)) + printWalk(e, indent + " |") + elif isinstance(e, UdInsnDef): + self.log("%s |-<%02x> %s" % (indent, k, e)) + printWalk(self.root) + + + def printStats(self): + tables = self.getTableList() + self.log("stats: ") + self.log(" Num tables = %d" % len(tables)) + self.log(" Num insnDefs = %d" % len(self.getInsnList())) + self.log(" Num insns = %d" % len(self.getMnemonicsList())) + + totalSize = 0 + totalEntries = 0 + for table in tables: + totalSize += table.size() + totalEntries += table.numEntries() + self.log(" Packing Ratio = %d%%" % ((totalEntries * 100) / totalSize)) + self.log("--------------------") + + self.pprint() + + + @staticmethod + def parseOptableXML(xml): + """Parse udis86 optable.xml file and return list of + instruction definitions. + """ + from xml.dom import minidom + + xmlDoc = minidom.parse(xml) + tlNode = xmlDoc.firstChild + insns = [] + + while tlNode and tlNode.localName != "x86optable": + tlNode = tlNode.nextSibling + + for insnNode in tlNode.childNodes: + if not insnNode.localName: + continue + if insnNode.localName != "instruction": + raise Exception("warning: invalid insn node - %s" % insnNode.localName) + mnemonic = insnNode.getElementsByTagName('mnemonic')[0].firstChild.data + vendor, cpuid = '', [] + + for node in insnNode.childNodes: + if node.localName == 'vendor': + vendor = node.firstChild.data.split() + elif node.localName == 'cpuid': + cpuid = node.firstChild.data.split() + + for node in insnNode.childNodes: + if node.localName == 'def': + insnDef = { 'pfx' : [] } + for node in node.childNodes: + if not node.localName: + continue + if node.localName in ('pfx', 'opc', 'opr', 'vendor', 'cpuid'): + insnDef[node.localName] = node.firstChild.data.split() + elif node.localName == 'mode': + insnDef['pfx'].extend(node.firstChild.data.split()) + insns.append({'prefixes' : insnDef.get('pfx', []), + 'mnemonic' : mnemonic, + 'opcodes' : insnDef.get('opc', []), + 'operands' : insnDef.get('opr', []), + 'vendor' : insnDef.get('vendor', vendor), + 'cpuid' : insnDef.get('cpuid', cpuid)}) + return insns diff --git a/Source/JavaScriptCore/disassembler/udis86/udis86.c b/Source/JavaScriptCore/disassembler/udis86/udis86.c new file mode 100644 index 000000000..56ab1a79b --- /dev/null +++ b/Source/JavaScriptCore/disassembler/udis86/udis86.c @@ -0,0 +1,462 @@ +/* udis86 - libudis86/udis86.c + * + * Copyright (c) 2002-2013 Vivek Thampi + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" + +#if USE(UDIS86) + +#include "udis86_udint.h" +#include "udis86_extern.h" +#include "udis86_decode.h" + +#if !defined(__UD_STANDALONE__) +#include <string.h> +#endif /* !__UD_STANDALONE__ */ + +static void ud_inp_init(struct ud *u); + +/* ============================================================================= + * ud_init + * Initializes ud_t object. + * ============================================================================= + */ +extern void +ud_init(struct ud* u) +{ + memset((void*)u, 0, sizeof(struct ud)); + ud_set_mode(u, 16); + u->mnemonic = UD_Iinvalid; + ud_set_pc(u, 0); +#ifndef __UD_STANDALONE__ + ud_set_input_file(u, stdin); +#endif /* __UD_STANDALONE__ */ + + ud_set_asm_buffer(u, u->asm_buf_int, sizeof(u->asm_buf_int)); +} + + +/* ============================================================================= + * ud_disassemble + * Disassembles one instruction and returns the number of + * bytes disassembled. A zero means end of disassembly. + * ============================================================================= + */ +extern unsigned int +ud_disassemble(struct ud* u) +{ + int len; + if (u->inp_end) { + return 0; + } + if ((len = ud_decode(u)) > 0) { + if (u->translator != NULL) { + u->asm_buf[0] = '\0'; + u->translator(u); + } + } + return len; +} + + +/* ============================================================================= + * ud_set_mode() - Set Disassemly Mode. + * ============================================================================= + */ +extern void +ud_set_mode(struct ud* u, uint8_t m) +{ + switch(m) { + case 16: + case 32: + case 64: u->dis_mode = m ; return; + default: u->dis_mode = 16; return; + } +} + +/* ============================================================================= + * ud_set_vendor() - Set vendor. + * ============================================================================= + */ +extern void +ud_set_vendor(struct ud* u, unsigned v) +{ + switch(v) { + case UD_VENDOR_INTEL: + u->vendor = v; + break; + case UD_VENDOR_ANY: + u->vendor = v; + break; + default: + u->vendor = UD_VENDOR_AMD; + } +} + +/* ============================================================================= + * ud_set_pc() - Sets code origin. + * ============================================================================= + */ +extern void +ud_set_pc(struct ud* u, uint64_t o) +{ + u->pc = o; +} + +/* ============================================================================= + * ud_set_syntax() - Sets the output syntax. + * ============================================================================= + */ +extern void +ud_set_syntax(struct ud* u, void (*t)(struct ud*)) +{ + u->translator = t; +} + +/* ============================================================================= + * ud_insn() - returns the disassembled instruction + * ============================================================================= + */ +const char* +ud_insn_asm(const struct ud* u) +{ + return u->asm_buf; +} + +/* ============================================================================= + * ud_insn_offset() - Returns the offset. + * ============================================================================= + */ +uint64_t +ud_insn_off(const struct ud* u) +{ + return u->insn_offset; +} + + +/* ============================================================================= + * ud_insn_hex() - Returns hex form of disassembled instruction. + * ============================================================================= + */ +const char* +ud_insn_hex(struct ud* u) +{ + u->insn_hexcode[0] = 0; + if (!u->error) { + unsigned int i; + const unsigned char *src_ptr = ud_insn_ptr(u); + char* src_hex; + src_hex = (char*) u->insn_hexcode; + /* for each byte used to decode instruction */ + for (i = 0; i < ud_insn_len(u) && i < sizeof(u->insn_hexcode) / 2; + ++i, ++src_ptr) { + sprintf(src_hex, "%02x", *src_ptr & 0xFF); + src_hex += 2; + } + } + return u->insn_hexcode; +} + + +/* ============================================================================= + * ud_insn_ptr + * Returns a pointer to buffer containing the bytes that were + * disassembled. + * ============================================================================= + */ +extern const uint8_t* +ud_insn_ptr(const struct ud* u) +{ + return (u->inp_buf == NULL) ? + u->inp_sess : u->inp_buf + (u->inp_buf_index - u->inp_ctr); +} + + +/* ============================================================================= + * ud_insn_len + * Returns the count of bytes disassembled. + * ============================================================================= + */ +extern unsigned int +ud_insn_len(const struct ud* u) +{ + return u->inp_ctr; +} + + +/* ============================================================================= + * ud_insn_get_opr + * Return the operand struct representing the nth operand of + * the currently disassembled instruction. Returns NULL if + * there's no such operand. + * ============================================================================= + */ +const struct ud_operand* +ud_insn_opr(const struct ud *u, unsigned int n) +{ + if (n > 3 || u->operand[n].type == UD_NONE) { + return NULL; + } else { + return &u->operand[n]; + } +} + + +/* ============================================================================= + * ud_opr_is_sreg + * Returns non-zero if the given operand is of a segment register type. + * ============================================================================= + */ +int +ud_opr_is_sreg(const struct ud_operand *opr) +{ + return opr->type == UD_OP_REG && + opr->base >= UD_R_ES && + opr->base <= UD_R_GS; +} + + +/* ============================================================================= + * ud_opr_is_sreg + * Returns non-zero if the given operand is of a general purpose + * register type. + * ============================================================================= + */ +int +ud_opr_is_gpr(const struct ud_operand *opr) +{ + return opr->type == UD_OP_REG && + opr->base >= UD_R_AL && + opr->base <= UD_R_R15; +} + + +/* ============================================================================= + * ud_set_user_opaque_data + * ud_get_user_opaque_data + * Get/set user opaqute data pointer + * ============================================================================= + */ +void +ud_set_user_opaque_data(struct ud * u, void* opaque) +{ + u->user_opaque_data = opaque; +} + +void* +ud_get_user_opaque_data(const struct ud *u) +{ + return u->user_opaque_data; +} + + +/* ============================================================================= + * ud_set_asm_buffer + * Allow the user to set an assembler output buffer. If `buf` is NULL, + * we switch back to the internal buffer. + * ============================================================================= + */ +void +ud_set_asm_buffer(struct ud *u, char *buf, size_t size) +{ + if (buf == NULL) { + ud_set_asm_buffer(u, u->asm_buf_int, sizeof(u->asm_buf_int)); + } else { + u->asm_buf = buf; + u->asm_buf_size = size; + } +} + + +/* ============================================================================= + * ud_set_sym_resolver + * Set symbol resolver for relative targets used in the translation + * phase. + * + * The resolver is a function that takes a uint64_t address and returns a + * symbolic name for the that address. The function also takes a second + * argument pointing to an integer that the client can optionally set to a + * non-zero value for offsetted targets. (symbol+offset) The function may + * also return NULL, in which case the translator only prints the target + * address. + * + * The function pointer maybe NULL which resets symbol resolution. + * ============================================================================= + */ +void +ud_set_sym_resolver(struct ud *u, const char* (*resolver)(struct ud*, + uint64_t addr, + int64_t *offset)) +{ + u->sym_resolver = resolver; +} + + +/* ============================================================================= + * ud_insn_mnemonic + * Return the current instruction mnemonic. + * ============================================================================= + */ +enum ud_mnemonic_code +ud_insn_mnemonic(const struct ud *u) +{ + return u->mnemonic; +} + + +/* ============================================================================= + * ud_lookup_mnemonic + * Looks up mnemonic code in the mnemonic string table. + * Returns NULL if the mnemonic code is invalid. + * ============================================================================= + */ +const char* +ud_lookup_mnemonic(enum ud_mnemonic_code c) +{ + if (c < UD_MAX_MNEMONIC_CODE) { + return ud_mnemonics_str[c]; + } else { + return NULL; + } +} + + +/* + * ud_inp_init + * Initializes the input system. + */ +static void +ud_inp_init(struct ud *u) +{ + u->inp_hook = NULL; + u->inp_buf = NULL; + u->inp_buf_size = 0; + u->inp_buf_index = 0; + u->inp_curr = 0; + u->inp_ctr = 0; + u->inp_end = 0; + u->inp_peek = UD_EOI; + UD_NON_STANDALONE(u->inp_file = NULL); +} + + +/* ============================================================================= + * ud_inp_set_hook + * Sets input hook. + * ============================================================================= + */ +void +ud_set_input_hook(register struct ud* u, int (*hook)(struct ud*)) +{ + ud_inp_init(u); + u->inp_hook = hook; +} + +/* ============================================================================= + * ud_inp_set_buffer + * Set buffer as input. + * ============================================================================= + */ +void +ud_set_input_buffer(register struct ud* u, const uint8_t* buf, size_t len) +{ + ud_inp_init(u); + u->inp_buf = buf; + u->inp_buf_size = len; + u->inp_buf_index = 0; +} + + +#ifndef __UD_STANDALONE__ +/* ============================================================================= + * ud_input_set_file + * Set FILE as input. + * ============================================================================= + */ +static int +inp_file_hook(struct ud* u) +{ + return fgetc(u->inp_file); +} + +void +ud_set_input_file(register struct ud* u, FILE* f) +{ + ud_inp_init(u); + u->inp_hook = inp_file_hook; + u->inp_file = f; +} +#endif /* __UD_STANDALONE__ */ + + +/* ============================================================================= + * ud_input_skip + * Skip n input bytes. + * ============================================================================ + */ +void +ud_input_skip(struct ud* u, size_t n) +{ + if (u->inp_end) { + return; + } + if (u->inp_buf == NULL) { + while (n--) { + int c = u->inp_hook(u); + if (c == UD_EOI) { + goto eoi; + } + } + return; + } else { + if (n > u->inp_buf_size || + u->inp_buf_index > u->inp_buf_size - n) { + u->inp_buf_index = u->inp_buf_size; + goto eoi; + } + u->inp_buf_index += n; + return; + } +eoi: + u->inp_end = 1; + UDERR(u, "cannot skip, eoi received\b"); + return; +} + + +/* ============================================================================= + * ud_input_end + * Returns non-zero on end-of-input. + * ============================================================================= + */ +int +ud_input_end(const struct ud *u) +{ + return u->inp_end; +} + +#endif // USE(UDIS86) + +/* vim:set ts=2 sw=2 expandtab */ diff --git a/Source/JavaScriptCore/disassembler/udis86/udis86.h b/Source/JavaScriptCore/disassembler/udis86/udis86.h new file mode 100644 index 000000000..baaf495e0 --- /dev/null +++ b/Source/JavaScriptCore/disassembler/udis86/udis86.h @@ -0,0 +1,33 @@ +/* udis86 - udis86.h + * + * Copyright (c) 2002-2009 Vivek Thampi + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef UDIS86_H +#define UDIS86_H + +#include "udis86_types.h" +#include "udis86_extern.h" +#include "udis86_itab.h" + +#endif diff --git a/Source/JavaScriptCore/disassembler/udis86/udis86_decode.c b/Source/JavaScriptCore/disassembler/udis86/udis86_decode.c new file mode 100644 index 000000000..c0ea28362 --- /dev/null +++ b/Source/JavaScriptCore/disassembler/udis86/udis86_decode.c @@ -0,0 +1,1273 @@ +/* udis86 - libudis86/decode.c + * + * Copyright (c) 2002-2009 Vivek Thampi + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" + +#if USE(UDIS86) + +#include "udis86_udint.h" +#include "udis86_types.h" +#include "udis86_extern.h" +#include "udis86_decode.h" + +#ifndef __UD_STANDALONE__ +# include <string.h> +#endif /* __UD_STANDALONE__ */ + +/* The max number of prefixes to an instruction */ +#define MAX_PREFIXES 15 + +/* rex prefix bits */ +#define REX_W(r) ( ( 0xF & ( r ) ) >> 3 ) +#define REX_R(r) ( ( 0x7 & ( r ) ) >> 2 ) +#define REX_X(r) ( ( 0x3 & ( r ) ) >> 1 ) +#define REX_B(r) ( ( 0x1 & ( r ) ) >> 0 ) +#define REX_PFX_MASK(n) ( ( P_REXW(n) << 3 ) | \ + ( P_REXR(n) << 2 ) | \ + ( P_REXX(n) << 1 ) | \ + ( P_REXB(n) << 0 ) ) + +/* scable-index-base bits */ +#define SIB_S(b) ( ( b ) >> 6 ) +#define SIB_I(b) ( ( ( b ) >> 3 ) & 7 ) +#define SIB_B(b) ( ( b ) & 7 ) + +/* modrm bits */ +#define MODRM_REG(b) ( ( ( b ) >> 3 ) & 7 ) +#define MODRM_NNN(b) ( ( ( b ) >> 3 ) & 7 ) +#define MODRM_MOD(b) ( ( ( b ) >> 6 ) & 3 ) +#define MODRM_RM(b) ( ( b ) & 7 ) + +static int decode_ext(struct ud *u, uint16_t ptr); +static int decode_opcode(struct ud *u); + +enum reg_class { /* register classes */ + REGCLASS_GPR, + REGCLASS_MMX, + REGCLASS_CR, + REGCLASS_DB, + REGCLASS_SEG, + REGCLASS_XMM +}; + + /* + * inp_start + * Should be called before each de-code operation. + */ +static void +inp_start(struct ud *u) +{ + u->inp_ctr = 0; +} + +static uint8_t +inp_peek(struct ud *u) +{ + if (u->inp_end == 0) { + if (u->inp_buf != NULL) { + if (u->inp_buf_index < u->inp_buf_size) { + return u->inp_buf[u->inp_buf_index]; + } + } else if (u->inp_peek != UD_EOI) { + return u->inp_peek; + } else { + int c; + if ((c = u->inp_hook(u)) != UD_EOI) { + u->inp_peek = c; + return u->inp_peek; + } + } + } + u->inp_end = 1; + UDERR(u, "byte expected, eoi received\n"); + return 0; +} + +static uint8_t +inp_next(struct ud *u) +{ + if (u->inp_end == 0) { + if (u->inp_buf != NULL) { + if (u->inp_buf_index < u->inp_buf_size) { + u->inp_ctr++; + return (u->inp_curr = u->inp_buf[u->inp_buf_index++]); + } + } else { + int c = u->inp_peek; + if (c != UD_EOI || (c = u->inp_hook(u)) != UD_EOI) { + u->inp_peek = UD_EOI; + u->inp_curr = c; + u->inp_sess[u->inp_ctr++] = u->inp_curr; + return u->inp_curr; + } + } + } + u->inp_end = 1; + UDERR(u, "byte expected, eoi received\n"); + return 0; +} + +static uint8_t +inp_curr(struct ud *u) +{ + return u->inp_curr; +} + + +/* + * inp_uint8 + * int_uint16 + * int_uint32 + * int_uint64 + * Load little-endian values from input + */ +static uint8_t +inp_uint8(struct ud* u) +{ + return inp_next(u); +} + +static uint16_t +inp_uint16(struct ud* u) +{ + uint16_t r, ret; + + ret = inp_next(u); + r = inp_next(u); + return ret | (r << 8); +} + +static uint32_t +inp_uint32(struct ud* u) +{ + uint32_t r, ret; + + ret = inp_next(u); + r = inp_next(u); + ret = ret | (r << 8); + r = inp_next(u); + ret = ret | (r << 16); + r = inp_next(u); + return ret | (r << 24); +} + +static uint64_t +inp_uint64(struct ud* u) +{ + uint64_t r, ret; + + ret = inp_next(u); + r = inp_next(u); + ret = ret | (r << 8); + r = inp_next(u); + ret = ret | (r << 16); + r = inp_next(u); + ret = ret | (r << 24); + r = inp_next(u); + ret = ret | (r << 32); + r = inp_next(u); + ret = ret | (r << 40); + r = inp_next(u); + ret = ret | (r << 48); + r = inp_next(u); + return ret | (r << 56); +} + + +static UD_INLINE int +eff_opr_mode(int dis_mode, int rex_w, int pfx_opr) +{ + if (dis_mode == 64) { + return rex_w ? 64 : (pfx_opr ? 16 : 32); + } else if (dis_mode == 32) { + return pfx_opr ? 16 : 32; + } else { + UD_ASSERT(dis_mode == 16); + return pfx_opr ? 32 : 16; + } +} + + +static UD_INLINE int +eff_adr_mode(int dis_mode, int pfx_adr) +{ + if (dis_mode == 64) { + return pfx_adr ? 32 : 64; + } else if (dis_mode == 32) { + return pfx_adr ? 16 : 32; + } else { + UD_ASSERT(dis_mode == 16); + return pfx_adr ? 32 : 16; + } +} + + +/* + * decode_prefixes + * + * Extracts instruction prefixes. + */ +static int +decode_prefixes(struct ud *u) +{ + int done = 0; + uint8_t curr = 0, last = 0; + UD_RETURN_ON_ERROR(u); + + do { + last = curr; + curr = inp_next(u); + UD_RETURN_ON_ERROR(u); + if (u->inp_ctr == MAX_INSN_LENGTH) { + UD_RETURN_WITH_ERROR(u, "max instruction length"); + } + + switch (curr) + { + case 0x2E: + u->pfx_seg = UD_R_CS; + break; + case 0x36: + u->pfx_seg = UD_R_SS; + break; + case 0x3E: + u->pfx_seg = UD_R_DS; + break; + case 0x26: + u->pfx_seg = UD_R_ES; + break; + case 0x64: + u->pfx_seg = UD_R_FS; + break; + case 0x65: + u->pfx_seg = UD_R_GS; + break; + case 0x67: /* adress-size override prefix */ + u->pfx_adr = 0x67; + break; + case 0xF0: + u->pfx_lock = 0xF0; + break; + case 0x66: + u->pfx_opr = 0x66; + break; + case 0xF2: + u->pfx_str = 0xf2; + break; + case 0xF3: + u->pfx_str = 0xf3; + break; + default: + /* consume if rex */ + done = (u->dis_mode == 64 && (curr & 0xF0) == 0x40) ? 0 : 1; + break; + } + } while (!done); + /* rex prefixes in 64bit mode, must be the last prefix */ + if (u->dis_mode == 64 && (last & 0xF0) == 0x40) { + u->pfx_rex = last; + } + return 0; +} + + +/* + * vex_l, vex_w + * Return the vex.L and vex.W bits + */ +static UD_INLINE uint8_t +vex_l(const struct ud *u) +{ + UD_ASSERT(u->vex_op != 0); + return ((u->vex_op == 0xc4 ? u->vex_b2 : u->vex_b1) >> 2) & 1; +} + +static UD_INLINE uint8_t +vex_w(const struct ud *u) +{ + UD_ASSERT(u->vex_op != 0); + return u->vex_op == 0xc4 ? ((u->vex_b2 >> 7) & 1) : 0; +} + + +static UD_INLINE uint8_t +modrm(struct ud * u) +{ + if ( !u->have_modrm ) { + u->modrm = inp_next( u ); + u->modrm_offset = (uint8_t) (u->inp_ctr - 1); + u->have_modrm = 1; + } + return u->modrm; +} + + +static unsigned int +resolve_operand_size(const struct ud* u, ud_operand_size_t osize) +{ + switch (osize) { + case SZ_V: + return u->opr_mode; + case SZ_Z: + return u->opr_mode == 16 ? 16 : 32; + case SZ_Y: + return u->opr_mode == 16 ? 32 : u->opr_mode; + case SZ_RDQ: + return u->dis_mode == 64 ? 64 : 32; + case SZ_X: + UD_ASSERT(u->vex_op != 0); + return (P_VEXL(u->itab_entry->prefix) && vex_l(u)) ? SZ_QQ : SZ_DQ; + default: + return osize; + } +} + + +static int resolve_mnemonic( struct ud* u ) +{ + /* resolve 3dnow weirdness. */ + if ( u->mnemonic == UD_I3dnow ) { + u->mnemonic = ud_itab[ u->le->table[ inp_curr( u ) ] ].mnemonic; + } + /* SWAPGS is only valid in 64bits mode */ + if ( u->mnemonic == UD_Iswapgs && u->dis_mode != 64 ) { + UDERR(u, "swapgs invalid in 64bits mode\n"); + return -1; + } + + if (u->mnemonic == UD_Ixchg) { + if ((u->operand[0].type == UD_OP_REG && u->operand[0].base == UD_R_AX && + u->operand[1].type == UD_OP_REG && u->operand[1].base == UD_R_AX) || + (u->operand[0].type == UD_OP_REG && u->operand[0].base == UD_R_EAX && + u->operand[1].type == UD_OP_REG && u->operand[1].base == UD_R_EAX)) { + u->operand[0].type = UD_NONE; + u->operand[1].type = UD_NONE; + u->mnemonic = UD_Inop; + } + } + + if (u->mnemonic == UD_Inop && u->pfx_repe) { + u->pfx_repe = 0; + u->mnemonic = UD_Ipause; + } + return 0; +} + + +/* ----------------------------------------------------------------------------- + * decode_a()- Decodes operands of the type seg:offset + * ----------------------------------------------------------------------------- + */ +static void +decode_a(struct ud* u, struct ud_operand *op) +{ + if (u->opr_mode == 16) { + /* seg16:off16 */ + op->type = UD_OP_PTR; + op->size = 32; + op->lval.ptr.off = inp_uint16(u); + op->lval.ptr.seg = inp_uint16(u); + } else { + /* seg16:off32 */ + op->type = UD_OP_PTR; + op->size = 48; + op->lval.ptr.off = inp_uint32(u); + op->lval.ptr.seg = inp_uint16(u); + } +} + +/* ----------------------------------------------------------------------------- + * decode_gpr() - Returns decoded General Purpose Register + * ----------------------------------------------------------------------------- + */ +static enum ud_type +decode_gpr(register struct ud* u, unsigned int s, unsigned char rm) +{ + switch (s) { + case 64: + return UD_R_RAX + rm; + case 32: + return UD_R_EAX + rm; + case 16: + return UD_R_AX + rm; + case 8: + if (u->dis_mode == 64 && u->pfx_rex) { + if (rm >= 4) + return UD_R_SPL + (rm-4); + return UD_R_AL + rm; + } else return UD_R_AL + rm; + case 0: + /* invalid size in case of a decode error */ + UD_ASSERT(u->error); + return UD_NONE; + default: + UD_ASSERT(!"invalid operand size"); + return UD_NONE; + } +} + +static void +decode_reg(struct ud *u, + struct ud_operand *opr, + int type, + int num, + int size) +{ + int reg; + size = resolve_operand_size(u, size); + switch (type) { + case REGCLASS_GPR : reg = decode_gpr(u, size, num); break; + case REGCLASS_MMX : reg = UD_R_MM0 + (num & 7); break; + case REGCLASS_XMM : + reg = num + (size == SZ_QQ ? UD_R_YMM0 : UD_R_XMM0); + break; + case REGCLASS_CR : reg = UD_R_CR0 + num; break; + case REGCLASS_DB : reg = UD_R_DR0 + num; break; + case REGCLASS_SEG : { + /* + * Only 6 segment registers, anything else is an error. + */ + if ((num & 7) > 5) { + UDERR(u, "invalid segment register value\n"); + return; + } else { + reg = UD_R_ES + (num & 7); + } + break; + } + default: + UD_ASSERT(!"invalid register type"); + return; + } + opr->type = UD_OP_REG; + opr->base = reg; + opr->size = size; +} + + +/* + * decode_imm + * + * Decode Immediate values. + */ +static void +decode_imm(struct ud* u, unsigned int size, struct ud_operand *op) +{ + op->size = resolve_operand_size(u, size); + op->type = UD_OP_IMM; + + switch (op->size) { + case 8: op->lval.sbyte = inp_uint8(u); break; + case 16: op->lval.uword = inp_uint16(u); break; + case 32: op->lval.udword = inp_uint32(u); break; + case 64: op->lval.uqword = inp_uint64(u); break; + default: return; + } +} + + +/* + * decode_mem_disp + * + * Decode mem address displacement. + */ +static void +decode_mem_disp(struct ud* u, unsigned int size, struct ud_operand *op) +{ + switch (size) { + case 8: + op->offset = 8; + op->lval.ubyte = inp_uint8(u); + break; + case 16: + op->offset = 16; + op->lval.uword = inp_uint16(u); + break; + case 32: + op->offset = 32; + op->lval.udword = inp_uint32(u); + break; + case 64: + op->offset = 64; + op->lval.uqword = inp_uint64(u); + break; + default: + return; + } +} + + +/* + * decode_modrm_reg + * + * Decodes reg field of mod/rm byte + * + */ +static UD_INLINE void +decode_modrm_reg(struct ud *u, + struct ud_operand *operand, + unsigned int type, + unsigned int size) +{ + uint8_t reg = (REX_R(u->_rex) << 3) | MODRM_REG(modrm(u)); + decode_reg(u, operand, type, reg, size); +} + + +/* + * decode_modrm_rm + * + * Decodes rm field of mod/rm byte + * + */ +static void +decode_modrm_rm(struct ud *u, + struct ud_operand *op, + unsigned char type, /* register type */ + unsigned int size) /* operand size */ + +{ + size_t offset = 0; + unsigned char mod, rm; + + /* get mod, r/m and reg fields */ + mod = MODRM_MOD(modrm(u)); + rm = (REX_B(u->_rex) << 3) | MODRM_RM(modrm(u)); + + /* + * If mod is 11b, then the modrm.rm specifies a register. + * + */ + if (mod == 3) { + decode_reg(u, op, type, rm, size); + return; + } + + /* + * !11b => Memory Address + */ + op->type = UD_OP_MEM; + op->size = resolve_operand_size(u, size); + + if (u->adr_mode == 64) { + op->base = UD_R_RAX + rm; + if (mod == 1) { + offset = 8; + } else if (mod == 2) { + offset = 32; + } else if (mod == 0 && (rm & 7) == 5) { + op->base = UD_R_RIP; + offset = 32; + } else { + offset = 0; + } + /* + * Scale-Index-Base (SIB) + */ + if ((rm & 7) == 4) { + inp_next(u); + + op->base = UD_R_RAX + (SIB_B(inp_curr(u)) | (REX_B(u->_rex) << 3)); + op->index = UD_R_RAX + (SIB_I(inp_curr(u)) | (REX_X(u->_rex) << 3)); + /* special conditions for base reference */ + if (op->index == UD_R_RSP) { + op->index = UD_NONE; + op->scale = UD_NONE; + } else { + op->scale = (1 << SIB_S(inp_curr(u))) & ~1; + } + + if (op->base == UD_R_RBP || op->base == UD_R_R13) { + if (mod == 0) { + op->base = UD_NONE; + } + if (mod == 1) { + offset = 8; + } else { + offset = 32; + } + } + } else { + op->scale = UD_NONE; + op->index = UD_NONE; + } + } else if (u->adr_mode == 32) { + op->base = UD_R_EAX + rm; + if (mod == 1) { + offset = 8; + } else if (mod == 2) { + offset = 32; + } else if (mod == 0 && rm == 5) { + op->base = UD_NONE; + offset = 32; + } else { + offset = 0; + } + + /* Scale-Index-Base (SIB) */ + if ((rm & 7) == 4) { + inp_next(u); + + op->scale = (1 << SIB_S(inp_curr(u))) & ~1; + op->index = UD_R_EAX + (SIB_I(inp_curr(u)) | (REX_X(u->pfx_rex) << 3)); + op->base = UD_R_EAX + (SIB_B(inp_curr(u)) | (REX_B(u->pfx_rex) << 3)); + + if (op->index == UD_R_ESP) { + op->index = UD_NONE; + op->scale = UD_NONE; + } + + /* special condition for base reference */ + if (op->base == UD_R_EBP) { + if (mod == 0) { + op->base = UD_NONE; + } + if (mod == 1) { + offset = 8; + } else { + offset = 32; + } + } + } else { + op->scale = UD_NONE; + op->index = UD_NONE; + } + } else { + const unsigned int bases[] = { UD_R_BX, UD_R_BX, UD_R_BP, UD_R_BP, + UD_R_SI, UD_R_DI, UD_R_BP, UD_R_BX }; + const unsigned int indices[] = { UD_R_SI, UD_R_DI, UD_R_SI, UD_R_DI, + UD_NONE, UD_NONE, UD_NONE, UD_NONE }; + op->base = bases[rm & 7]; + op->index = indices[rm & 7]; + op->scale = UD_NONE; + if (mod == 0 && rm == 6) { + offset = 16; + op->base = UD_NONE; + } else if (mod == 1) { + offset = 8; + } else if (mod == 2) { + offset = 16; + } + } + + if (offset) { + decode_mem_disp(u, offset, op); + } else { + op->offset = 0; + } +} + + +/* + * decode_moffset + * Decode offset-only memory operand + */ +static void +decode_moffset(struct ud *u, unsigned int size, struct ud_operand *opr) +{ + opr->type = UD_OP_MEM; + opr->base = UD_NONE; + opr->index = UD_NONE; + opr->scale = UD_NONE; + opr->size = resolve_operand_size(u, size); + decode_mem_disp(u, u->adr_mode, opr); +} + + +static void +decode_vex_vvvv(struct ud *u, struct ud_operand *opr, unsigned size) +{ + uint8_t vvvv; + UD_ASSERT(u->vex_op != 0); + vvvv = ((u->vex_op == 0xc4 ? u->vex_b2 : u->vex_b1) >> 3) & 0xf; + decode_reg(u, opr, REGCLASS_XMM, (0xf & ~vvvv), size); +} + + +/* + * decode_vex_immreg + * Decode source operand encoded in immediate byte [7:4] + */ +static int +decode_vex_immreg(struct ud *u, struct ud_operand *opr, unsigned size) +{ + uint8_t imm = inp_next(u); + uint8_t mask = u->dis_mode == 64 ? 0xf : 0x7; + UD_RETURN_ON_ERROR(u); + UD_ASSERT(u->vex_op != 0); + decode_reg(u, opr, REGCLASS_XMM, mask & (imm >> 4), size); + return 0; +} + + +/* + * decode_operand + * + * Decodes a single operand. + * Returns the type of the operand (UD_NONE if none) + */ +static int +decode_operand(struct ud *u, + struct ud_operand *operand, + enum ud_operand_code type, + unsigned int size) +{ + operand->type = UD_NONE; + operand->_oprcode = type; + + switch (type) { + case OP_A : + decode_a(u, operand); + break; + case OP_MR: + decode_modrm_rm(u, operand, REGCLASS_GPR, + MODRM_MOD(modrm(u)) == 3 ? + Mx_reg_size(size) : Mx_mem_size(size)); + break; + case OP_F: + u->br_far = 1; + /* intended fall through */ + case OP_M: + if (MODRM_MOD(modrm(u)) == 3) { + UDERR(u, "expected modrm.mod != 3\n"); + } + /* intended fall through */ + case OP_E: + decode_modrm_rm(u, operand, REGCLASS_GPR, size); + break; + case OP_G: + decode_modrm_reg(u, operand, REGCLASS_GPR, size); + break; + case OP_sI: + case OP_I: + decode_imm(u, size, operand); + break; + case OP_I1: + operand->type = UD_OP_CONST; + operand->lval.udword = 1; + break; + case OP_N: + if (MODRM_MOD(modrm(u)) != 3) { + UDERR(u, "expected modrm.mod == 3\n"); + } + /* intended fall through */ + case OP_Q: + decode_modrm_rm(u, operand, REGCLASS_MMX, size); + break; + case OP_P: + decode_modrm_reg(u, operand, REGCLASS_MMX, size); + break; + case OP_U: + if (MODRM_MOD(modrm(u)) != 3) { + UDERR(u, "expected modrm.mod == 3\n"); + } + /* intended fall through */ + case OP_W: + decode_modrm_rm(u, operand, REGCLASS_XMM, size); + break; + case OP_V: + decode_modrm_reg(u, operand, REGCLASS_XMM, size); + break; + case OP_H: + decode_vex_vvvv(u, operand, size); + break; + case OP_MU: + decode_modrm_rm(u, operand, REGCLASS_XMM, + MODRM_MOD(modrm(u)) == 3 ? + Mx_reg_size(size) : Mx_mem_size(size)); + break; + case OP_S: + decode_modrm_reg(u, operand, REGCLASS_SEG, size); + break; + case OP_O: + decode_moffset(u, size, operand); + break; + case OP_R0: + case OP_R1: + case OP_R2: + case OP_R3: + case OP_R4: + case OP_R5: + case OP_R6: + case OP_R7: + decode_reg(u, operand, REGCLASS_GPR, + (REX_B(u->_rex) << 3) | (type - OP_R0), size); + break; + case OP_AL: + case OP_AX: + case OP_eAX: + case OP_rAX: + decode_reg(u, operand, REGCLASS_GPR, 0, size); + break; + case OP_CL: + case OP_CX: + case OP_eCX: + decode_reg(u, operand, REGCLASS_GPR, 1, size); + break; + case OP_DL: + case OP_DX: + case OP_eDX: + decode_reg(u, operand, REGCLASS_GPR, 2, size); + break; + case OP_ES: + case OP_CS: + case OP_DS: + case OP_SS: + case OP_FS: + case OP_GS: + /* in 64bits mode, only fs and gs are allowed */ + if (u->dis_mode == 64) { + if (type != OP_FS && type != OP_GS) { + UDERR(u, "invalid segment register in 64bits\n"); + } + } + operand->type = UD_OP_REG; + operand->base = (type - OP_ES) + UD_R_ES; + operand->size = 16; + break; + case OP_J : + decode_imm(u, size, operand); + operand->type = UD_OP_JIMM; + break ; + case OP_R : + if (MODRM_MOD(modrm(u)) != 3) { + UDERR(u, "expected modrm.mod == 3\n"); + } + decode_modrm_rm(u, operand, REGCLASS_GPR, size); + break; + case OP_C: + decode_modrm_reg(u, operand, REGCLASS_CR, size); + break; + case OP_D: + decode_modrm_reg(u, operand, REGCLASS_DB, size); + break; + case OP_I3 : + operand->type = UD_OP_CONST; + operand->lval.sbyte = 3; + break; + case OP_ST0: + case OP_ST1: + case OP_ST2: + case OP_ST3: + case OP_ST4: + case OP_ST5: + case OP_ST6: + case OP_ST7: + operand->type = UD_OP_REG; + operand->base = (type - OP_ST0) + UD_R_ST0; + operand->size = 80; + break; + case OP_L: + decode_vex_immreg(u, operand, size); + break; + default : + operand->type = UD_NONE; + break; + } + return operand->type; +} + + +/* + * decode_operands + * + * Disassemble upto 3 operands of the current instruction being + * disassembled. By the end of the function, the operand fields + * of the ud structure will have been filled. + */ +static int +decode_operands(struct ud* u) +{ + decode_operand(u, &u->operand[0], + u->itab_entry->operand1.type, + u->itab_entry->operand1.size); + if (u->operand[0].type != UD_NONE) { + decode_operand(u, &u->operand[1], + u->itab_entry->operand2.type, + u->itab_entry->operand2.size); + } + if (u->operand[1].type != UD_NONE) { + decode_operand(u, &u->operand[2], + u->itab_entry->operand3.type, + u->itab_entry->operand3.size); + } + if (u->operand[2].type != UD_NONE) { + decode_operand(u, &u->operand[3], + u->itab_entry->operand4.type, + u->itab_entry->operand4.size); + } + return 0; +} + +/* ----------------------------------------------------------------------------- + * clear_insn() - clear instruction structure + * ----------------------------------------------------------------------------- + */ +static void +clear_insn(register struct ud* u) +{ + u->error = 0; + u->pfx_seg = 0; + u->pfx_opr = 0; + u->pfx_adr = 0; + u->pfx_lock = 0; + u->pfx_repne = 0; + u->pfx_rep = 0; + u->pfx_repe = 0; + u->pfx_rex = 0; + u->pfx_str = 0; + u->mnemonic = UD_Inone; + u->itab_entry = NULL; + u->have_modrm = 0; + u->br_far = 0; + u->vex_op = 0; + u->_rex = 0; + u->operand[0].type = UD_NONE; + u->operand[1].type = UD_NONE; + u->operand[2].type = UD_NONE; + u->operand[3].type = UD_NONE; +} + + +static UD_INLINE int +resolve_pfx_str(struct ud* u) +{ + if (u->pfx_str == 0xf3) { + if (P_STR(u->itab_entry->prefix)) { + u->pfx_rep = 0xf3; + } else { + u->pfx_repe = 0xf3; + } + } else if (u->pfx_str == 0xf2) { + u->pfx_repne = 0xf3; + } + return 0; +} + + +static int +resolve_mode( struct ud* u ) +{ + int default64; + /* if in error state, bail out */ + if ( u->error ) return -1; + + /* propagate prefix effects */ + if ( u->dis_mode == 64 ) { /* set 64bit-mode flags */ + + /* Check validity of instruction m64 */ + if ( P_INV64( u->itab_entry->prefix ) ) { + UDERR(u, "instruction invalid in 64bits\n"); + return -1; + } + + /* compute effective rex based on, + * - vex prefix (if any) + * - rex prefix (if any, and not vex) + * - allowed prefixes specified by the opcode map + */ + if (u->vex_op == 0xc4) { + /* vex has rex.rxb in 1's complement */ + u->_rex = ((~(u->vex_b1 >> 5) & 0x7) /* rex.0rxb */ | + ((u->vex_b2 >> 4) & 0x8) /* rex.w000 */); + } else if (u->vex_op == 0xc5) { + /* vex has rex.r in 1's complement */ + u->_rex = (~(u->vex_b1 >> 5)) & 4; + } else { + UD_ASSERT(u->vex_op == 0); + u->_rex = u->pfx_rex; + } + u->_rex &= REX_PFX_MASK(u->itab_entry->prefix); + + /* whether this instruction has a default operand size of + * 64bit, also hardcoded into the opcode map. + */ + default64 = P_DEF64( u->itab_entry->prefix ); + /* calculate effective operand size */ + if (REX_W(u->_rex)) { + u->opr_mode = 64; + } else if ( u->pfx_opr ) { + u->opr_mode = 16; + } else { + /* unless the default opr size of instruction is 64, + * the effective operand size in the absence of rex.w + * prefix is 32. + */ + u->opr_mode = default64 ? 64 : 32; + } + + /* calculate effective address size */ + u->adr_mode = (u->pfx_adr) ? 32 : 64; + } else if ( u->dis_mode == 32 ) { /* set 32bit-mode flags */ + u->opr_mode = ( u->pfx_opr ) ? 16 : 32; + u->adr_mode = ( u->pfx_adr ) ? 16 : 32; + } else if ( u->dis_mode == 16 ) { /* set 16bit-mode flags */ + u->opr_mode = ( u->pfx_opr ) ? 32 : 16; + u->adr_mode = ( u->pfx_adr ) ? 32 : 16; + } + + return 0; +} + + +static UD_INLINE int +decode_insn(struct ud *u, uint16_t ptr) +{ + UD_ASSERT((ptr & 0x8000) == 0); + u->itab_entry = &ud_itab[ ptr ]; + u->mnemonic = u->itab_entry->mnemonic; + return (resolve_pfx_str(u) == 0 && + resolve_mode(u) == 0 && + decode_operands(u) == 0 && + resolve_mnemonic(u) == 0) ? 0 : -1; +} + + +/* + * decode_3dnow() + * + * Decoding 3dnow is a little tricky because of its strange opcode + * structure. The final opcode disambiguation depends on the last + * byte that comes after the operands have been decoded. Fortunately, + * all 3dnow instructions have the same set of operand types. So we + * go ahead and decode the instruction by picking an arbitrarily chosen + * valid entry in the table, decode the operands, and read the final + * byte to resolve the menmonic. + */ +static UD_INLINE int +decode_3dnow(struct ud* u) +{ + uint16_t ptr; + UD_ASSERT(u->le->type == UD_TAB__OPC_3DNOW); + UD_ASSERT(u->le->table[0xc] != 0); + decode_insn(u, u->le->table[0xc]); + inp_next(u); + if (u->error) { + return -1; + } + ptr = u->le->table[inp_curr(u)]; + UD_ASSERT((ptr & 0x8000) == 0); + u->mnemonic = ud_itab[ptr].mnemonic; + return 0; +} + + +static int +decode_ssepfx(struct ud *u) +{ + uint8_t idx; + uint8_t pfx; + + /* + * String prefixes (f2, f3) take precedence over operand + * size prefix (66). + */ + pfx = u->pfx_str; + if (pfx == 0) { + pfx = u->pfx_opr; + } + idx = ((pfx & 0xf) + 1) / 2; + if (u->le->table[idx] == 0) { + idx = 0; + } + if (idx && u->le->table[idx] != 0) { + /* + * "Consume" the prefix as a part of the opcode, so it is no + * longer exported as an instruction prefix. + */ + u->pfx_str = 0; + if (pfx == 0x66) { + /* + * consume "66" only if it was used for decoding, leaving + * it to be used as an operands size override for some + * simd instructions. + */ + u->pfx_opr = 0; + } + } + return decode_ext(u, u->le->table[idx]); +} + + +static int +decode_vex(struct ud *u) +{ + uint8_t index; + if (u->dis_mode != 64 && MODRM_MOD(inp_peek(u)) != 0x3) { + index = 0; + } else { + u->vex_op = inp_curr(u); + u->vex_b1 = inp_next(u); + if (u->vex_op == 0xc4) { + uint8_t pp, m; + /* 3-byte vex */ + u->vex_b2 = inp_next(u); + UD_RETURN_ON_ERROR(u); + m = u->vex_b1 & 0x1f; + if (m == 0 || m > 3) { + UD_RETURN_WITH_ERROR(u, "reserved vex.m-mmmm value"); + } + pp = u->vex_b2 & 0x3; + index = (pp << 2) | m; + } else { + /* 2-byte vex */ + UD_ASSERT(u->vex_op == 0xc5); + index = 0x1 | ((u->vex_b1 & 0x3) << 2); + } + } + return decode_ext(u, u->le->table[index]); +} + + +/* + * decode_ext() + * + * Decode opcode extensions (if any) + */ +static int +decode_ext(struct ud *u, uint16_t ptr) +{ + uint8_t idx = 0; + if ((ptr & 0x8000) == 0) { + return decode_insn(u, ptr); + } + u->le = &ud_lookup_table_list[(~0x8000 & ptr)]; + if (u->le->type == UD_TAB__OPC_3DNOW) { + return decode_3dnow(u); + } + + switch (u->le->type) { + case UD_TAB__OPC_MOD: + /* !11 = 0, 11 = 1 */ + idx = (MODRM_MOD(modrm(u)) + 1) / 4; + break; + /* disassembly mode/operand size/address size based tables. + * 16 = 0,, 32 = 1, 64 = 2 + */ + case UD_TAB__OPC_MODE: + idx = u->dis_mode != 64 ? 0 : 1; + break; + case UD_TAB__OPC_OSIZE: + idx = eff_opr_mode(u->dis_mode, REX_W(u->pfx_rex), u->pfx_opr) / 32; + break; + case UD_TAB__OPC_ASIZE: + idx = eff_adr_mode(u->dis_mode, u->pfx_adr) / 32; + break; + case UD_TAB__OPC_X87: + idx = modrm(u) - 0xC0; + break; + case UD_TAB__OPC_VENDOR: + if (u->vendor == UD_VENDOR_ANY) { + /* choose a valid entry */ + idx = (u->le->table[idx] != 0) ? 0 : 1; + } else if (u->vendor == UD_VENDOR_AMD) { + idx = 0; + } else { + idx = 1; + } + break; + case UD_TAB__OPC_RM: + idx = MODRM_RM(modrm(u)); + break; + case UD_TAB__OPC_REG: + idx = MODRM_REG(modrm(u)); + break; + case UD_TAB__OPC_SSE: + return decode_ssepfx(u); + case UD_TAB__OPC_VEX: + return decode_vex(u); + case UD_TAB__OPC_VEX_W: + idx = vex_w(u); + break; + case UD_TAB__OPC_VEX_L: + idx = vex_l(u); + break; + case UD_TAB__OPC_TABLE: + inp_next(u); + return decode_opcode(u); + default: + UD_ASSERT(!"not reached"); + break; + } + + return decode_ext(u, u->le->table[idx]); +} + + +static int +decode_opcode(struct ud *u) +{ + uint16_t ptr; + UD_ASSERT(u->le->type == UD_TAB__OPC_TABLE); + UD_RETURN_ON_ERROR(u); + ptr = u->le->table[inp_curr(u)]; + return decode_ext(u, ptr); +} + + +/* ============================================================================= + * ud_decode() - Instruction decoder. Returns the number of bytes decoded. + * ============================================================================= + */ +unsigned int +ud_decode(struct ud *u) +{ + inp_start(u); + clear_insn(u); + u->le = &ud_lookup_table_list[0]; + u->error = decode_prefixes(u) == -1 || + decode_opcode(u) == -1 || + u->error; + /* Handle decode error. */ + if (u->error) { + /* clear out the decode data. */ + clear_insn(u); + /* mark the sequence of bytes as invalid. */ + u->itab_entry = &ud_itab[0]; /* entry 0 is invalid */ + u->mnemonic = u->itab_entry->mnemonic; + } + + /* maybe this stray segment override byte + * should be spewed out? + */ + if ( !P_SEG( u->itab_entry->prefix ) && + u->operand[0].type != UD_OP_MEM && + u->operand[1].type != UD_OP_MEM ) + u->pfx_seg = 0; + + u->insn_offset = u->pc; /* set offset of instruction */ + u->asm_buf_fill = 0; /* set translation buffer index to 0 */ + u->pc += u->inp_ctr; /* move program counter by bytes decoded */ + + /* return number of bytes disassembled. */ + return u->inp_ctr; +} + +#endif // USE(UDIS86) + +/* +vim: set ts=2 sw=2 expandtab +*/ diff --git a/Source/JavaScriptCore/disassembler/udis86/udis86_decode.h b/Source/JavaScriptCore/disassembler/udis86/udis86_decode.h new file mode 100644 index 000000000..411c8830e --- /dev/null +++ b/Source/JavaScriptCore/disassembler/udis86/udis86_decode.h @@ -0,0 +1,197 @@ +/* udis86 - libudis86/decode.h + * + * Copyright (c) 2002-2009 Vivek Thampi + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef UD_DECODE_H +#define UD_DECODE_H + +#include "udis86_types.h" +#include "udis86_udint.h" +#include "udis86_itab.h" + +#define MAX_INSN_LENGTH 15 + +/* itab prefix bits */ +#define P_none ( 0 ) + +#define P_inv64 ( 1 << 0 ) +#define P_INV64(n) ( ( n >> 0 ) & 1 ) +#define P_def64 ( 1 << 1 ) +#define P_DEF64(n) ( ( n >> 1 ) & 1 ) + +#define P_oso ( 1 << 2 ) +#define P_OSO(n) ( ( n >> 2 ) & 1 ) +#define P_aso ( 1 << 3 ) +#define P_ASO(n) ( ( n >> 3 ) & 1 ) + +#define P_rexb ( 1 << 4 ) +#define P_REXB(n) ( ( n >> 4 ) & 1 ) +#define P_rexw ( 1 << 5 ) +#define P_REXW(n) ( ( n >> 5 ) & 1 ) +#define P_rexr ( 1 << 6 ) +#define P_REXR(n) ( ( n >> 6 ) & 1 ) +#define P_rexx ( 1 << 7 ) +#define P_REXX(n) ( ( n >> 7 ) & 1 ) + +#define P_seg ( 1 << 8 ) +#define P_SEG(n) ( ( n >> 8 ) & 1 ) + +#define P_vexl ( 1 << 9 ) +#define P_VEXL(n) ( ( n >> 9 ) & 1 ) +#define P_vexw ( 1 << 10 ) +#define P_VEXW(n) ( ( n >> 10 ) & 1 ) + +#define P_str ( 1 << 11 ) +#define P_STR(n) ( ( n >> 11 ) & 1 ) +#define P_strz ( 1 << 12 ) +#define P_STR_ZF(n) ( ( n >> 12 ) & 1 ) + +/* operand type constants -- order is important! */ + +enum ud_operand_code { + OP_NONE, + + OP_A, OP_E, OP_M, OP_G, + OP_I, OP_F, + + OP_R0, OP_R1, OP_R2, OP_R3, + OP_R4, OP_R5, OP_R6, OP_R7, + + OP_AL, OP_CL, OP_DL, + OP_AX, OP_CX, OP_DX, + OP_eAX, OP_eCX, OP_eDX, + OP_rAX, OP_rCX, OP_rDX, + + OP_ES, OP_CS, OP_SS, OP_DS, + OP_FS, OP_GS, + + OP_ST0, OP_ST1, OP_ST2, OP_ST3, + OP_ST4, OP_ST5, OP_ST6, OP_ST7, + + OP_J, OP_S, OP_O, + OP_I1, OP_I3, OP_sI, + + OP_V, OP_W, OP_Q, OP_P, + OP_U, OP_N, OP_MU, OP_H, + OP_L, + + OP_R, OP_C, OP_D, + + OP_MR +} UD_ATTR_PACKED; + + +/* + * Operand size constants + * + * Symbolic constants for various operand sizes. Some of these constants + * are given a value equal to the width of the data (SZ_B == 8), such + * that they maybe used interchangeably in the internals. Modifying them + * will most certainly break things! + */ +typedef uint16_t ud_operand_size_t; + +#define SZ_NA 0 +#define SZ_Z 1 +#define SZ_V 2 +#define SZ_Y 3 +#define SZ_X 4 +#define SZ_RDQ 7 +#define SZ_B 8 +#define SZ_W 16 +#define SZ_D 32 +#define SZ_Q 64 +#define SZ_T 80 +#define SZ_O 12 +#define SZ_DQ 128 /* double quad */ +#define SZ_QQ 256 /* quad quad */ + +/* + * Complex size types; that encode sizes for operands of type MR (memory or + * register); for internal use only. Id space above 256. + */ +#define SZ_BD ((SZ_B << 8) | SZ_D) +#define SZ_BV ((SZ_B << 8) | SZ_V) +#define SZ_WD ((SZ_W << 8) | SZ_D) +#define SZ_WV ((SZ_W << 8) | SZ_V) +#define SZ_WY ((SZ_W << 8) | SZ_Y) +#define SZ_DY ((SZ_D << 8) | SZ_Y) +#define SZ_WO ((SZ_W << 8) | SZ_O) +#define SZ_DO ((SZ_D << 8) | SZ_O) +#define SZ_QO ((SZ_Q << 8) | SZ_O) + + +/* resolve complex size type. + */ +static UD_INLINE ud_operand_size_t +Mx_mem_size(ud_operand_size_t size) +{ + return (size >> 8) & 0xff; +} + +static UD_INLINE ud_operand_size_t +Mx_reg_size(ud_operand_size_t size) +{ + return size & 0xff; +} + +/* A single operand of an entry in the instruction table. + * (internal use only) + */ +struct ud_itab_entry_operand +{ + enum ud_operand_code type; + ud_operand_size_t size; +}; + + +/* A single entry in an instruction table. + *(internal use only) + */ +struct ud_itab_entry +{ + enum ud_mnemonic_code mnemonic; + struct ud_itab_entry_operand operand1; + struct ud_itab_entry_operand operand2; + struct ud_itab_entry_operand operand3; + struct ud_itab_entry_operand operand4; + uint32_t prefix; +}; + +struct ud_lookup_table_list_entry { + const uint16_t *table; + enum ud_table_type type; + const char *meta; +}; + +extern struct ud_itab_entry ud_itab[]; +extern struct ud_lookup_table_list_entry ud_lookup_table_list[]; + +#endif /* UD_DECODE_H */ + +/* vim:cindent + * vim:expandtab + * vim:ts=4 + * vim:sw=4 + */ diff --git a/Source/JavaScriptCore/disassembler/udis86/udis86_extern.h b/Source/JavaScriptCore/disassembler/udis86/udis86_extern.h new file mode 100644 index 000000000..bf3314d09 --- /dev/null +++ b/Source/JavaScriptCore/disassembler/udis86/udis86_extern.h @@ -0,0 +1,113 @@ +/* udis86 - libudis86/extern.h + * + * Copyright (c) 2002-2009, 2013 Vivek Thampi + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef UD_EXTERN_H +#define UD_EXTERN_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "udis86_types.h" + +#if defined(_MSC_VER) && defined(_USRDLL) +# ifdef LIBUDIS86_EXPORTS +# define LIBUDIS86_DLLEXTERN __declspec(dllexport) +# else +# define LIBUDIS86_DLLEXTERN __declspec(dllimport) +# endif +#else +# define LIBUDIS86_DLLEXTERN +#endif + +/* ============================= PUBLIC API ================================= */ + +extern LIBUDIS86_DLLEXTERN void ud_init(struct ud*); + +extern LIBUDIS86_DLLEXTERN void ud_set_mode(struct ud*, uint8_t); + +extern LIBUDIS86_DLLEXTERN void ud_set_pc(struct ud*, uint64_t); + +extern LIBUDIS86_DLLEXTERN void ud_set_input_hook(struct ud*, int (*)(struct ud*)); + +extern LIBUDIS86_DLLEXTERN void ud_set_input_buffer(struct ud*, const uint8_t*, size_t); + +#ifndef __UD_STANDALONE__ +extern LIBUDIS86_DLLEXTERN void ud_set_input_file(struct ud*, FILE*); +#endif /* __UD_STANDALONE__ */ + +extern LIBUDIS86_DLLEXTERN void ud_set_vendor(struct ud*, unsigned); + +extern LIBUDIS86_DLLEXTERN void ud_set_syntax(struct ud*, void (*)(struct ud*)); + +extern LIBUDIS86_DLLEXTERN void ud_input_skip(struct ud*, size_t); + +extern LIBUDIS86_DLLEXTERN int ud_input_end(const struct ud*); + +extern LIBUDIS86_DLLEXTERN unsigned int ud_decode(struct ud*); + +extern LIBUDIS86_DLLEXTERN unsigned int ud_disassemble(struct ud*); + +extern LIBUDIS86_DLLEXTERN void ud_translate_intel(struct ud*); + +extern LIBUDIS86_DLLEXTERN void ud_translate_att(struct ud*); + +extern LIBUDIS86_DLLEXTERN const char* ud_insn_asm(const struct ud* u); + +extern LIBUDIS86_DLLEXTERN const uint8_t* ud_insn_ptr(const struct ud* u); + +extern LIBUDIS86_DLLEXTERN uint64_t ud_insn_off(const struct ud*); + +extern LIBUDIS86_DLLEXTERN const char* ud_insn_hex(struct ud*); + +extern LIBUDIS86_DLLEXTERN unsigned int ud_insn_len(const struct ud* u); + +extern LIBUDIS86_DLLEXTERN const struct ud_operand* ud_insn_opr(const struct ud *u, unsigned int n); + +extern LIBUDIS86_DLLEXTERN int ud_opr_is_sreg(const struct ud_operand *opr); + +extern LIBUDIS86_DLLEXTERN int ud_opr_is_gpr(const struct ud_operand *opr); + +extern LIBUDIS86_DLLEXTERN enum ud_mnemonic_code ud_insn_mnemonic(const struct ud *u); + +extern LIBUDIS86_DLLEXTERN const char* ud_lookup_mnemonic(enum ud_mnemonic_code c); + +extern LIBUDIS86_DLLEXTERN void ud_set_user_opaque_data(struct ud*, void*); + +extern LIBUDIS86_DLLEXTERN void* ud_get_user_opaque_data(const struct ud*); + +extern LIBUDIS86_DLLEXTERN void ud_set_asm_buffer(struct ud *u, char *buf, size_t size); + +extern LIBUDIS86_DLLEXTERN void ud_set_sym_resolver(struct ud *u, + const char* (*resolver)(struct ud*, + uint64_t addr, + int64_t *offset)); + +/* ========================================================================== */ + +#ifdef __cplusplus +} +#endif +#endif /* UD_EXTERN_H */ diff --git a/Source/JavaScriptCore/disassembler/udis86/udis86_itab_holder.c b/Source/JavaScriptCore/disassembler/udis86/udis86_itab_holder.c new file mode 100644 index 000000000..80dda3a19 --- /dev/null +++ b/Source/JavaScriptCore/disassembler/udis86/udis86_itab_holder.c @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2012 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" + +#if USE(UDIS86) + +#include "udis86_itab.c" + +#endif + diff --git a/Source/JavaScriptCore/disassembler/udis86/udis86_syn-att.c b/Source/JavaScriptCore/disassembler/udis86/udis86_syn-att.c new file mode 100644 index 000000000..7d5646e4a --- /dev/null +++ b/Source/JavaScriptCore/disassembler/udis86/udis86_syn-att.c @@ -0,0 +1,235 @@ +/* udis86 - libudis86/syn-att.c + * + * Copyright (c) 2002-2009 Vivek Thampi + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" + +#if USE(UDIS86) + +#include "udis86_types.h" +#include "udis86_extern.h" +#include "udis86_decode.h" +#include "udis86_itab.h" +#include "udis86_syn.h" +#include "udis86_udint.h" + +/* ----------------------------------------------------------------------------- + * opr_cast() - Prints an operand cast. + * ----------------------------------------------------------------------------- + */ +static void +opr_cast(struct ud* u, struct ud_operand* op) +{ + switch(op->size) { + case 16 : case 32 : + ud_asmprintf(u, "*"); break; + default: break; + } +} + +/* ----------------------------------------------------------------------------- + * gen_operand() - Generates assembly output for each operand. + * ----------------------------------------------------------------------------- + */ +static void +gen_operand(struct ud* u, struct ud_operand* op) +{ + switch(op->type) { + case UD_OP_CONST: + ud_asmprintf(u, "$0x%x", op->lval.udword); + break; + + case UD_OP_REG: + ud_asmprintf(u, "%%%s", ud_reg_tab[op->base - UD_R_AL]); + break; + + case UD_OP_MEM: + if (u->br_far) { + opr_cast(u, op); + } + if (u->pfx_seg) { + ud_asmprintf(u, "%%%s:", ud_reg_tab[u->pfx_seg - UD_R_AL]); + } + if (op->offset != 0) { + ud_syn_print_mem_disp(u, op, 0); + } + if (op->base) { + ud_asmprintf(u, "(%%%s", ud_reg_tab[op->base - UD_R_AL]); + } + if (op->index) { + if (op->base) { + ud_asmprintf(u, ","); + } else { + ud_asmprintf(u, "("); + } + ud_asmprintf(u, "%%%s", ud_reg_tab[op->index - UD_R_AL]); + } + if (op->scale) { + ud_asmprintf(u, ",%d", op->scale); + } + if (op->base || op->index) { + ud_asmprintf(u, ")"); + } + break; + + case UD_OP_IMM: + ud_asmprintf(u, "$"); + ud_syn_print_imm(u, op); + break; + + case UD_OP_JIMM: + ud_syn_print_addr(u, ud_syn_rel_target(u, op)); + break; + + case UD_OP_PTR: + switch (op->size) { + case 32: + ud_asmprintf(u, "$0x%x, $0x%x", op->lval.ptr.seg, + op->lval.ptr.off & 0xFFFF); + break; + case 48: + ud_asmprintf(u, "$0x%x, $0x%x", op->lval.ptr.seg, + op->lval.ptr.off); + break; + } + break; + + default: return; + } +} + +/* ============================================================================= + * translates to AT&T syntax + * ============================================================================= + */ +extern void +ud_translate_att(struct ud *u) +{ + int size = 0; + int star = 0; + + /* check if P_OSO prefix is used */ + if (! P_OSO(u->itab_entry->prefix) && u->pfx_opr) { + switch (u->dis_mode) { + case 16: + ud_asmprintf(u, "o32 "); + break; + case 32: + case 64: + ud_asmprintf(u, "o16 "); + break; + } + } + + /* check if P_ASO prefix was used */ + if (! P_ASO(u->itab_entry->prefix) && u->pfx_adr) { + switch (u->dis_mode) { + case 16: + ud_asmprintf(u, "a32 "); + break; + case 32: + ud_asmprintf(u, "a16 "); + break; + case 64: + ud_asmprintf(u, "a32 "); + break; + } + } + + if (u->pfx_lock) + ud_asmprintf(u, "lock "); + if (u->pfx_rep) { + ud_asmprintf(u, "rep "); + } else if (u->pfx_repe) { + ud_asmprintf(u, "repe "); + } else if (u->pfx_repne) { + ud_asmprintf(u, "repne "); + } + + /* special instructions */ + switch (u->mnemonic) { + case UD_Iretf: + ud_asmprintf(u, "lret "); + break; + case UD_Idb: + ud_asmprintf(u, ".byte 0x%x", u->operand[0].lval.ubyte); + return; + case UD_Ijmp: + case UD_Icall: + if (u->br_far) ud_asmprintf(u, "l"); + if (u->operand[0].type == UD_OP_REG) { + star = 1; + } + ud_asmprintf(u, "%s", ud_lookup_mnemonic(u->mnemonic)); + break; + case UD_Ibound: + case UD_Ienter: + if (u->operand[0].type != UD_NONE) + gen_operand(u, &u->operand[0]); + if (u->operand[1].type != UD_NONE) { + ud_asmprintf(u, ","); + gen_operand(u, &u->operand[1]); + } + return; + default: + ud_asmprintf(u, "%s", ud_lookup_mnemonic(u->mnemonic)); + } + + if (size == 8) { + ud_asmprintf(u, "b"); + } else if (size == 16) { + ud_asmprintf(u, "w"); + } else if (size == 64) { + ud_asmprintf(u, "q"); + } + + if (star) { + ud_asmprintf(u, " *"); + } else { + ud_asmprintf(u, " "); + } + + if (u->operand[3].type != UD_NONE) { + gen_operand(u, &u->operand[3]); + ud_asmprintf(u, ", "); + } + if (u->operand[2].type != UD_NONE) { + gen_operand(u, &u->operand[2]); + ud_asmprintf(u, ", "); + } + if (u->operand[1].type != UD_NONE) { + gen_operand(u, &u->operand[1]); + ud_asmprintf(u, ", "); + } + if (u->operand[0].type != UD_NONE) { + gen_operand(u, &u->operand[0]); + } +} + +#endif // USE(UDIS86) + +/* +vim: set ts=2 sw=2 expandtab +*/ diff --git a/Source/JavaScriptCore/disassembler/udis86/udis86_syn-intel.c b/Source/JavaScriptCore/disassembler/udis86/udis86_syn-intel.c new file mode 100644 index 000000000..769df8901 --- /dev/null +++ b/Source/JavaScriptCore/disassembler/udis86/udis86_syn-intel.c @@ -0,0 +1,231 @@ +/* udis86 - libudis86/syn-intel.c + * + * Copyright (c) 2002-2013 Vivek Thampi + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" + +#if USE(UDIS86) + +#include "udis86_types.h" +#include "udis86_extern.h" +#include "udis86_decode.h" +#include "udis86_itab.h" +#include "udis86_syn.h" +#include "udis86_udint.h" + +/* ----------------------------------------------------------------------------- + * opr_cast() - Prints an operand cast. + * ----------------------------------------------------------------------------- + */ +static void +opr_cast(struct ud* u, struct ud_operand* op) +{ + if (u->br_far) { + ud_asmprintf(u, "far "); + } + switch(op->size) { + case 8: ud_asmprintf(u, "byte " ); break; + case 16: ud_asmprintf(u, "word " ); break; + case 32: ud_asmprintf(u, "dword "); break; + case 64: ud_asmprintf(u, "qword "); break; + case 80: ud_asmprintf(u, "tword "); break; + case 128: ud_asmprintf(u, "oword "); break; + case 256: ud_asmprintf(u, "yword "); break; + default: break; + } +} + +/* ----------------------------------------------------------------------------- + * gen_operand() - Generates assembly output for each operand. + * ----------------------------------------------------------------------------- + */ +static void gen_operand(struct ud* u, struct ud_operand* op, int syn_cast) +{ + switch(op->type) { + case UD_OP_REG: + ud_asmprintf(u, "%s", ud_reg_tab[op->base - UD_R_AL]); + break; + + case UD_OP_MEM: + if (syn_cast) { + opr_cast(u, op); + } + ud_asmprintf(u, "["); + if (u->pfx_seg) { + ud_asmprintf(u, "%s:", ud_reg_tab[u->pfx_seg - UD_R_AL]); + } + if (op->base) { + ud_asmprintf(u, "%s", ud_reg_tab[op->base - UD_R_AL]); + } + if (op->index) { + ud_asmprintf(u, "%s%s", op->base != UD_NONE? "+" : "", + ud_reg_tab[op->index - UD_R_AL]); + if (op->scale) { + ud_asmprintf(u, "*%d", op->scale); + } + } + if (op->offset != 0) { + ud_syn_print_mem_disp(u, op, (op->base != UD_NONE || + op->index != UD_NONE) ? 1 : 0); + } + ud_asmprintf(u, "]"); + break; + + case UD_OP_IMM: + ud_syn_print_imm(u, op); + break; + + + case UD_OP_JIMM: + ud_syn_print_addr(u, ud_syn_rel_target(u, op)); + break; + + case UD_OP_PTR: + switch (op->size) { + case 32: + ud_asmprintf(u, "word 0x%x:0x%x", op->lval.ptr.seg, + op->lval.ptr.off & 0xFFFF); + break; + case 48: + ud_asmprintf(u, "dword 0x%x:0x%x", op->lval.ptr.seg, + op->lval.ptr.off); + break; + } + break; + + case UD_OP_CONST: + if (syn_cast) opr_cast(u, op); + ud_asmprintf(u, "%d", op->lval.udword); + break; + + default: return; + } +} + +/* ============================================================================= + * translates to intel syntax + * ============================================================================= + */ +extern void +ud_translate_intel(struct ud* u) +{ + /* check if P_OSO prefix is used */ + if (!P_OSO(u->itab_entry->prefix) && u->pfx_opr) { + switch (u->dis_mode) { + case 16: ud_asmprintf(u, "o32 "); break; + case 32: + case 64: ud_asmprintf(u, "o16 "); break; + } + } + + /* check if P_ASO prefix was used */ + if (!P_ASO(u->itab_entry->prefix) && u->pfx_adr) { + switch (u->dis_mode) { + case 16: ud_asmprintf(u, "a32 "); break; + case 32: ud_asmprintf(u, "a16 "); break; + case 64: ud_asmprintf(u, "a32 "); break; + } + } + + if (u->pfx_seg && + u->operand[0].type != UD_OP_MEM && + u->operand[1].type != UD_OP_MEM ) { + ud_asmprintf(u, "%s ", ud_reg_tab[u->pfx_seg - UD_R_AL]); + } + + if (u->pfx_lock) { + ud_asmprintf(u, "lock "); + } + if (u->pfx_rep) { + ud_asmprintf(u, "rep "); + } else if (u->pfx_repe) { + ud_asmprintf(u, "repe "); + } else if (u->pfx_repne) { + ud_asmprintf(u, "repne "); + } + + /* print the instruction mnemonic */ + ud_asmprintf(u, "%s", ud_lookup_mnemonic(u->mnemonic)); + + if (u->operand[0].type != UD_NONE) { + int cast = 0; + ud_asmprintf(u, " "); + if (u->operand[0].type == UD_OP_MEM) { + if (u->operand[1].type == UD_OP_IMM || + u->operand[1].type == UD_OP_CONST || + u->operand[1].type == UD_NONE || + (u->operand[0].size != u->operand[1].size)) { + cast = 1; + } else if (u->operand[1].type == UD_OP_REG && + u->operand[1].base == UD_R_CL) { + switch (u->mnemonic) { + case UD_Ircl: + case UD_Irol: + case UD_Iror: + case UD_Ircr: + case UD_Ishl: + case UD_Ishr: + case UD_Isar: + cast = 1; + break; + default: break; + } + } + } + gen_operand(u, &u->operand[0], cast); + } + + if (u->operand[1].type != UD_NONE) { + int cast = 0; + ud_asmprintf(u, ", "); + if (u->operand[1].type == UD_OP_MEM && + u->operand[0].size != u->operand[1].size && + !ud_opr_is_sreg(&u->operand[0])) { + cast = 1; + } + gen_operand(u, &u->operand[1], cast); + } + + if (u->operand[2].type != UD_NONE) { + int cast = 0; + ud_asmprintf(u, ", "); + if (u->operand[2].type == UD_OP_MEM && + u->operand[2].size != u->operand[1].size) { + cast = 1; + } + gen_operand(u, &u->operand[2], cast); + } + + if (u->operand[3].type != UD_NONE) { + ud_asmprintf(u, ", "); + gen_operand(u, &u->operand[3], 0); + } +} + +#endif // USE(UDIS86) + +/* +vim: set ts=2 sw=2 expandtab +*/ diff --git a/Source/JavaScriptCore/disassembler/udis86/udis86_syn.c b/Source/JavaScriptCore/disassembler/udis86/udis86_syn.c new file mode 100644 index 000000000..4417d9997 --- /dev/null +++ b/Source/JavaScriptCore/disassembler/udis86/udis86_syn.c @@ -0,0 +1,219 @@ +/* udis86 - libudis86/syn.c + * + * Copyright (c) 2002-2013 Vivek Thampi + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" + +#if USE(UDIS86) + +#include "udis86_types.h" +#include "udis86_decode.h" +#include "udis86_syn.h" +#include "udis86_udint.h" + +/* + * Register Table - Order Matters (types.h)! + * + */ +const char* ud_reg_tab[] = +{ + "al", "cl", "dl", "bl", + "ah", "ch", "dh", "bh", + "spl", "bpl", "sil", "dil", + "r8b", "r9b", "r10b", "r11b", + "r12b", "r13b", "r14b", "r15b", + + "ax", "cx", "dx", "bx", + "sp", "bp", "si", "di", + "r8w", "r9w", "r10w", "r11w", + "r12w", "r13w", "r14w", "r15w", + + "eax", "ecx", "edx", "ebx", + "esp", "ebp", "esi", "edi", + "r8d", "r9d", "r10d", "r11d", + "r12d", "r13d", "r14d", "r15d", + + "rax", "rcx", "rdx", "rbx", + "rsp", "rbp", "rsi", "rdi", + "r8", "r9", "r10", "r11", + "r12", "r13", "r14", "r15", + + "es", "cs", "ss", "ds", + "fs", "gs", + + "cr0", "cr1", "cr2", "cr3", + "cr4", "cr5", "cr6", "cr7", + "cr8", "cr9", "cr10", "cr11", + "cr12", "cr13", "cr14", "cr15", + + "dr0", "dr1", "dr2", "dr3", + "dr4", "dr5", "dr6", "dr7", + "dr8", "dr9", "dr10", "dr11", + "dr12", "dr13", "dr14", "dr15", + + "mm0", "mm1", "mm2", "mm3", + "mm4", "mm5", "mm6", "mm7", + + "st0", "st1", "st2", "st3", + "st4", "st5", "st6", "st7", + + "xmm0", "xmm1", "xmm2", "xmm3", + "xmm4", "xmm5", "xmm6", "xmm7", + "xmm8", "xmm9", "xmm10", "xmm11", + "xmm12", "xmm13", "xmm14", "xmm15", + + "ymm0", "ymm1", "ymm2", "ymm3", + "ymm4", "ymm5", "ymm6", "ymm7", + "ymm8", "ymm9", "ymm10", "ymm11", + "ymm12", "ymm13", "ymm14", "ymm15", + + "rip" +}; + + +uint64_t +ud_syn_rel_target(struct ud *u, struct ud_operand *opr) +{ + const uint64_t trunc_mask = 0xffffffffffffffffull >> (64 - u->opr_mode); + switch (opr->size) { + case 8 : return (u->pc + opr->lval.sbyte) & trunc_mask; + case 16: return (u->pc + opr->lval.sword) & trunc_mask; + case 32: return (u->pc + opr->lval.sdword) & trunc_mask; + default: UD_ASSERT(!"invalid relative offset size."); + return 0ull; + } +} + + +/* + * asmprintf + * Printf style function for printing translated assembly + * output. Returns the number of characters written and + * moves the buffer pointer forward. On an overflow, + * returns a negative number and truncates the output. + */ +int +ud_asmprintf(struct ud *u, const char *fmt, ...) +{ + int ret; + int avail; + va_list ap; + va_start(ap, fmt); + avail = u->asm_buf_size - u->asm_buf_fill - 1 /* nullchar */; + ret = vsnprintf((char*) u->asm_buf + u->asm_buf_fill, avail, fmt, ap); + if (ret < 0 || ret > avail) { + u->asm_buf_fill = u->asm_buf_size - 1; + } else { + u->asm_buf_fill += ret; + } + va_end(ap); + return ret; +} + + +void +ud_syn_print_addr(struct ud *u, uint64_t addr) +{ + const char *name = NULL; + if (u->sym_resolver) { + int64_t offset = 0; + name = u->sym_resolver(u, addr, &offset); + if (name) { + if (offset) { + ud_asmprintf(u, "%s%+" FMT64 "d", name, offset); + } else { + ud_asmprintf(u, "%s", name); + } + return; + } + } + ud_asmprintf(u, "0x%" FMT64 "x", addr); +} + + +void +ud_syn_print_imm(struct ud* u, const struct ud_operand *op) +{ + uint64_t v; + if (op->_oprcode == OP_sI && op->size != u->opr_mode) { + if (op->size == 8) { + v = (int64_t)op->lval.sbyte; + } else { + UD_ASSERT(op->size == 32); + v = (int64_t)op->lval.sdword; + } + if (u->opr_mode < 64) { + v = v & ((1ull << u->opr_mode) - 1ull); + } + } else { + switch (op->size) { + case 8 : v = op->lval.ubyte; break; + case 16: v = op->lval.uword; break; + case 32: v = op->lval.udword; break; + case 64: v = op->lval.uqword; break; + default: UD_ASSERT(!"invalid offset"); v = 0; /* keep cc happy */ + } + } + ud_asmprintf(u, "0x%" FMT64 "x", v); +} + + +void +ud_syn_print_mem_disp(struct ud* u, const struct ud_operand *op, int sign) +{ + UD_ASSERT(op->offset != 0); + if (op->base == UD_NONE && op->index == UD_NONE) { + uint64_t v; + UD_ASSERT(op->scale == UD_NONE && op->offset != 8); + /* unsigned mem-offset */ + switch (op->offset) { + case 16: v = op->lval.uword; break; + case 32: v = op->lval.udword; break; + case 64: v = op->lval.uqword; break; + default: UD_ASSERT(!"invalid offset"); v = 0; /* keep cc happy */ + } + ud_asmprintf(u, "0x%" FMT64 "x", v); + } else { + int64_t v; + UD_ASSERT(op->offset != 64); + switch (op->offset) { + case 8 : v = op->lval.sbyte; break; + case 16: v = op->lval.sword; break; + case 32: v = op->lval.sdword; break; + default: UD_ASSERT(!"invalid offset"); v = 0; /* keep cc happy */ + } + if (v < 0) { + ud_asmprintf(u, "-0x%" FMT64 "x", -v); + } else if (v > 0) { + ud_asmprintf(u, "%s0x%" FMT64 "x", sign? "+" : "", v); + } + } +} + +#endif // USE(UDIS86) + +/* +vim: set ts=2 sw=2 expandtab +*/ diff --git a/Source/JavaScriptCore/disassembler/udis86/udis86_syn.h b/Source/JavaScriptCore/disassembler/udis86/udis86_syn.h new file mode 100644 index 000000000..712ec37ae --- /dev/null +++ b/Source/JavaScriptCore/disassembler/udis86/udis86_syn.h @@ -0,0 +1,53 @@ +/* udis86 - libudis86/syn.h + * + * Copyright (c) 2002-2009 + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef UD_SYN_H +#define UD_SYN_H + +#include "udis86_types.h" +#ifndef __UD_STANDALONE__ +# include <stdarg.h> +#endif /* __UD_STANDALONE__ */ + +extern const char* ud_reg_tab[]; + +uint64_t ud_syn_rel_target(struct ud*, struct ud_operand*); + +#ifdef __GNUC__ +int ud_asmprintf(struct ud *u, const char *fmt, ...) + __attribute__ ((format (printf, 2, 3))); +#else +int ud_asmprintf(struct ud *u, const char *fmt, ...); +#endif + +void ud_syn_print_addr(struct ud *u, uint64_t addr); +void ud_syn_print_imm(struct ud* u, const struct ud_operand *op); +void ud_syn_print_mem_disp(struct ud* u, const struct ud_operand *, int sign); + +#endif /* UD_SYN_H */ + +/* +vim: set ts=2 sw=2 expandtab +*/ diff --git a/Source/JavaScriptCore/disassembler/udis86/udis86_types.h b/Source/JavaScriptCore/disassembler/udis86/udis86_types.h new file mode 100644 index 000000000..604f08e51 --- /dev/null +++ b/Source/JavaScriptCore/disassembler/udis86/udis86_types.h @@ -0,0 +1,260 @@ +/* udis86 - libudis86/types.h + * + * Copyright (c) 2002-2013 Vivek Thampi + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef UD_TYPES_H +#define UD_TYPES_H + +#ifdef __KERNEL__ + /* + * -D__KERNEL__ is automatically passed on the command line when + * building something as part of the Linux kernel. Assume standalone + * mode. + */ +# include <linux/kernel.h> +# include <linux/string.h> +# ifndef __UD_STANDALONE__ +# define __UD_STANDALONE__ 1 +# endif +#endif /* __KERNEL__ */ + +#if !defined(__UD_STANDALONE__) +# include <stdint.h> +# include <stdio.h> +#endif + +/* gcc specific extensions */ +#ifdef __GNUC__ +# define UD_ATTR_PACKED __attribute__((packed)) +#else +# define UD_ATTR_PACKED +#endif /* UD_ATTR_PACKED */ + + +/* ----------------------------------------------------------------------------- + * All possible "types" of objects in udis86. Order is Important! + * ----------------------------------------------------------------------------- + */ +enum ud_type +{ + UD_NONE, + + /* 8 bit GPRs */ + UD_R_AL, UD_R_CL, UD_R_DL, UD_R_BL, + UD_R_AH, UD_R_CH, UD_R_DH, UD_R_BH, + UD_R_SPL, UD_R_BPL, UD_R_SIL, UD_R_DIL, + UD_R_R8B, UD_R_R9B, UD_R_R10B, UD_R_R11B, + UD_R_R12B, UD_R_R13B, UD_R_R14B, UD_R_R15B, + + /* 16 bit GPRs */ + UD_R_AX, UD_R_CX, UD_R_DX, UD_R_BX, + UD_R_SP, UD_R_BP, UD_R_SI, UD_R_DI, + UD_R_R8W, UD_R_R9W, UD_R_R10W, UD_R_R11W, + UD_R_R12W, UD_R_R13W, UD_R_R14W, UD_R_R15W, + + /* 32 bit GPRs */ + UD_R_EAX, UD_R_ECX, UD_R_EDX, UD_R_EBX, + UD_R_ESP, UD_R_EBP, UD_R_ESI, UD_R_EDI, + UD_R_R8D, UD_R_R9D, UD_R_R10D, UD_R_R11D, + UD_R_R12D, UD_R_R13D, UD_R_R14D, UD_R_R15D, + + /* 64 bit GPRs */ + UD_R_RAX, UD_R_RCX, UD_R_RDX, UD_R_RBX, + UD_R_RSP, UD_R_RBP, UD_R_RSI, UD_R_RDI, + UD_R_R8, UD_R_R9, UD_R_R10, UD_R_R11, + UD_R_R12, UD_R_R13, UD_R_R14, UD_R_R15, + + /* segment registers */ + UD_R_ES, UD_R_CS, UD_R_SS, UD_R_DS, + UD_R_FS, UD_R_GS, + + /* control registers*/ + UD_R_CR0, UD_R_CR1, UD_R_CR2, UD_R_CR3, + UD_R_CR4, UD_R_CR5, UD_R_CR6, UD_R_CR7, + UD_R_CR8, UD_R_CR9, UD_R_CR10, UD_R_CR11, + UD_R_CR12, UD_R_CR13, UD_R_CR14, UD_R_CR15, + + /* debug registers */ + UD_R_DR0, UD_R_DR1, UD_R_DR2, UD_R_DR3, + UD_R_DR4, UD_R_DR5, UD_R_DR6, UD_R_DR7, + UD_R_DR8, UD_R_DR9, UD_R_DR10, UD_R_DR11, + UD_R_DR12, UD_R_DR13, UD_R_DR14, UD_R_DR15, + + /* mmx registers */ + UD_R_MM0, UD_R_MM1, UD_R_MM2, UD_R_MM3, + UD_R_MM4, UD_R_MM5, UD_R_MM6, UD_R_MM7, + + /* x87 registers */ + UD_R_ST0, UD_R_ST1, UD_R_ST2, UD_R_ST3, + UD_R_ST4, UD_R_ST5, UD_R_ST6, UD_R_ST7, + + /* extended multimedia registers */ + UD_R_XMM0, UD_R_XMM1, UD_R_XMM2, UD_R_XMM3, + UD_R_XMM4, UD_R_XMM5, UD_R_XMM6, UD_R_XMM7, + UD_R_XMM8, UD_R_XMM9, UD_R_XMM10, UD_R_XMM11, + UD_R_XMM12, UD_R_XMM13, UD_R_XMM14, UD_R_XMM15, + + /* 256B multimedia registers */ + UD_R_YMM0, UD_R_YMM1, UD_R_YMM2, UD_R_YMM3, + UD_R_YMM4, UD_R_YMM5, UD_R_YMM6, UD_R_YMM7, + UD_R_YMM8, UD_R_YMM9, UD_R_YMM10, UD_R_YMM11, + UD_R_YMM12, UD_R_YMM13, UD_R_YMM14, UD_R_YMM15, + + UD_R_RIP, + + /* Operand Types */ + UD_OP_REG, UD_OP_MEM, UD_OP_PTR, UD_OP_IMM, + UD_OP_JIMM, UD_OP_CONST +}; + +#include "udis86_itab.h" + +union ud_lval { + int8_t sbyte; + uint8_t ubyte; + int16_t sword; + uint16_t uword; + int32_t sdword; + uint32_t udword; + int64_t sqword; + uint64_t uqword; + struct { + uint16_t seg; + uint32_t off; + } ptr; +}; + +/* ----------------------------------------------------------------------------- + * struct ud_operand - Disassembled instruction Operand. + * ----------------------------------------------------------------------------- + */ +struct ud_operand { + enum ud_type type; + uint16_t size; + enum ud_type base; + enum ud_type index; + uint8_t scale; + uint8_t offset; + union ud_lval lval; + /* + * internal use only + */ + uint64_t _legacy; /* this will be removed in 1.8 */ + uint8_t _oprcode; +}; + +/* ----------------------------------------------------------------------------- + * struct ud - The udis86 object. + * ----------------------------------------------------------------------------- + */ +struct ud +{ + /* + * input buffering + */ + int (*inp_hook) (struct ud*); +#ifndef __UD_STANDALONE__ + FILE* inp_file; +#endif + const uint8_t* inp_buf; + size_t inp_buf_size; + size_t inp_buf_index; + uint8_t inp_curr; + size_t inp_ctr; + uint8_t inp_sess[64]; + int inp_end; + int inp_peek; + + void (*translator)(struct ud*); + uint64_t insn_offset; + char insn_hexcode[64]; + + /* + * Assembly output buffer + */ + char *asm_buf; + size_t asm_buf_size; + size_t asm_buf_fill; + char asm_buf_int[128]; + + /* + * Symbol resolver for use in the translation phase. + */ + const char* (*sym_resolver)(struct ud*, uint64_t addr, int64_t *offset); + + uint8_t dis_mode; + uint64_t pc; + uint8_t vendor; + enum ud_mnemonic_code mnemonic; + struct ud_operand operand[4]; + uint8_t error; + uint8_t _rex; + uint8_t pfx_rex; + uint8_t pfx_seg; + uint8_t pfx_opr; + uint8_t pfx_adr; + uint8_t pfx_lock; + uint8_t pfx_str; + uint8_t pfx_rep; + uint8_t pfx_repe; + uint8_t pfx_repne; + uint8_t opr_mode; + uint8_t adr_mode; + uint8_t br_far; + uint8_t br_near; + uint8_t have_modrm; + uint8_t modrm; + uint8_t modrm_offset; + uint8_t vex_op; + uint8_t vex_b1; + uint8_t vex_b2; + uint8_t primary_opcode; + void * user_opaque_data; + struct ud_itab_entry * itab_entry; + struct ud_lookup_table_list_entry *le; +}; + +/* ----------------------------------------------------------------------------- + * Type-definitions + * ----------------------------------------------------------------------------- + */ +typedef enum ud_type ud_type_t; +typedef enum ud_mnemonic_code ud_mnemonic_code_t; + +typedef struct ud ud_t; +typedef struct ud_operand ud_operand_t; + +#define UD_SYN_INTEL ud_translate_intel +#define UD_SYN_ATT ud_translate_att +#define UD_EOI (-1) +#define UD_INP_CACHE_SZ 32 +#define UD_VENDOR_AMD 0 +#define UD_VENDOR_INTEL 1 +#define UD_VENDOR_ANY 2 + +#endif + +/* +vim: set ts=2 sw=2 expandtab +*/ diff --git a/Source/JavaScriptCore/disassembler/udis86/udis86_udint.h b/Source/JavaScriptCore/disassembler/udis86/udis86_udint.h new file mode 100644 index 000000000..d166b9173 --- /dev/null +++ b/Source/JavaScriptCore/disassembler/udis86/udis86_udint.h @@ -0,0 +1,98 @@ +/* udis86 - libudis86/udint.h -- definitions for internal use only + * + * Copyright (c) 2002-2009 Vivek Thampi + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef _UDINT_H_ +#define _UDINT_H_ + +#include "udis86_types.h" + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif /* HAVE_CONFIG_H */ + +#if defined(UD_DEBUG) && HAVE_ASSERT_H +# define UD_ASSERT(_x) ASSERT(_x) +#else +# define UD_ASSERT(_x) +#endif /* !HAVE_ASSERT_H */ + +#if defined(UD_DEBUG) + #define UDERR(u, msg) \ + do { \ + (u)->error = 1; \ + fprintf(stderr, "decode-error: %s:%d: %s", \ + __FILE__, __LINE__, (msg)); \ + } while (0) +#else + #define UDERR(u, m) \ + do { \ + (u)->error = 1; \ + } while (0) +#endif /* !LOGERR */ + +#define UD_RETURN_ON_ERROR(u) \ + do { \ + if ((u)->error != 0) { \ + return (u)->error; \ + } \ + } while (0) + +#define UD_RETURN_WITH_ERROR(u, m) \ + do { \ + UDERR(u, m); \ + return (u)->error; \ + } while (0) + +#ifndef __UD_STANDALONE__ +# define UD_NON_STANDALONE(x) x +#else +# define UD_NON_STANDALONE(x) +#endif + +/* printf formatting int64 specifier */ +#ifdef FMT64 +# undef FMT64 +#endif +#if defined(_MSC_VER) || defined(__BORLANDC__) +# define FMT64 "I64" +#else +# if defined(__APPLE__) +# define FMT64 "ll" +# elif defined(__amd64__) || defined(__x86_64__) +# define FMT64 "l" +# else +# define FMT64 "ll" +# endif /* !x64 */ +#endif + +/* define an inline macro */ +#if defined(_MSC_VER) || defined(__BORLANDC__) +# define UD_INLINE __inline /* MS Visual Studio requires __inline + instead of inline for C code */ +#else +# define UD_INLINE inline +#endif + +#endif /* _UDINT_H_ */ |