11a37d0a8f0f7110046e499bbe1117fec91f31f7eAnders Carlsson/* Copyright (c) 2007, Google Inc. 21a37d0a8f0f7110046e499bbe1117fec91f31f7eAnders Carlsson * All rights reserved. 31a37d0a8f0f7110046e499bbe1117fec91f31f7eAnders Carlsson * 41a37d0a8f0f7110046e499bbe1117fec91f31f7eAnders Carlsson * Redistribution and use in source and binary forms, with or without 51a37d0a8f0f7110046e499bbe1117fec91f31f7eAnders Carlsson * modification, are permitted provided that the following conditions are 61a37d0a8f0f7110046e499bbe1117fec91f31f7eAnders Carlsson * met: 71a37d0a8f0f7110046e499bbe1117fec91f31f7eAnders Carlsson * 81a37d0a8f0f7110046e499bbe1117fec91f31f7eAnders Carlsson * * Redistributions of source code must retain the above copyright 91a37d0a8f0f7110046e499bbe1117fec91f31f7eAnders Carlsson * notice, this list of conditions and the following disclaimer. 101a37d0a8f0f7110046e499bbe1117fec91f31f7eAnders Carlsson * * Redistributions in binary form must reproduce the above 111a37d0a8f0f7110046e499bbe1117fec91f31f7eAnders Carlsson * copyright notice, this list of conditions and the following disclaimer 121a37d0a8f0f7110046e499bbe1117fec91f31f7eAnders Carlsson * in the documentation and/or other materials provided with the 131a37d0a8f0f7110046e499bbe1117fec91f31f7eAnders Carlsson * distribution. 141a37d0a8f0f7110046e499bbe1117fec91f31f7eAnders Carlsson * * Neither the name of Google Inc. nor the names of its 151a37d0a8f0f7110046e499bbe1117fec91f31f7eAnders Carlsson * contributors may be used to endorse or promote products derived from 161a37d0a8f0f7110046e499bbe1117fec91f31f7eAnders Carlsson * this software without specific prior written permission. 171a37d0a8f0f7110046e499bbe1117fec91f31f7eAnders Carlsson * 181a37d0a8f0f7110046e499bbe1117fec91f31f7eAnders Carlsson * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 191a37d0a8f0f7110046e499bbe1117fec91f31f7eAnders Carlsson * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 201a37d0a8f0f7110046e499bbe1117fec91f31f7eAnders Carlsson * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 211a37d0a8f0f7110046e499bbe1117fec91f31f7eAnders Carlsson * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 221a37d0a8f0f7110046e499bbe1117fec91f31f7eAnders Carlsson * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23b71f95647189f3b0f7f5f5a39c8c3ab8130dcf1fEric Christopher * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24b71f95647189f3b0f7f5f5a39c8c3ab8130dcf1fEric Christopher * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25b71f95647189f3b0f7f5f5a39c8c3ab8130dcf1fEric Christopher * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26b71f95647189f3b0f7f5f5a39c8c3ab8130dcf1fEric Christopher * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27b71f95647189f3b0f7f5f5a39c8c3ab8130dcf1fEric Christopher * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28b71f95647189f3b0f7f5f5a39c8c3ab8130dcf1fEric Christopher * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29b71f95647189f3b0f7f5f5a39c8c3ab8130dcf1fEric Christopher * 30b71f95647189f3b0f7f5f5a39c8c3ab8130dcf1fEric Christopher * --- 31b71f95647189f3b0f7f5f5a39c8c3ab8130dcf1fEric Christopher * Author: Joi Sigurdsson 32b71f95647189f3b0f7f5f5a39c8c3ab8130dcf1fEric Christopher * 33b71f95647189f3b0f7f5f5a39c8c3ab8130dcf1fEric Christopher * Implementation of MiniDisassembler. 34b71f95647189f3b0f7f5f5a39c8c3ab8130dcf1fEric Christopher */ 35b71f95647189f3b0f7f5f5a39c8c3ab8130dcf1fEric Christopher 36b71f95647189f3b0f7f5f5a39c8c3ab8130dcf1fEric Christopher#include "mini_disassembler.h" 37b71f95647189f3b0f7f5f5a39c8c3ab8130dcf1fEric Christopher 38b71f95647189f3b0f7f5f5a39c8c3ab8130dcf1fEric Christophernamespace sidestep { 39b71f95647189f3b0f7f5f5a39c8c3ab8130dcf1fEric Christopher 40b71f95647189f3b0f7f5f5a39c8c3ab8130dcf1fEric ChristopherMiniDisassembler::MiniDisassembler(bool operand_default_is_32_bits, 41b71f95647189f3b0f7f5f5a39c8c3ab8130dcf1fEric Christopher bool address_default_is_32_bits) 42b71f95647189f3b0f7f5f5a39c8c3ab8130dcf1fEric Christopher : operand_default_is_32_bits_(operand_default_is_32_bits), 43b71f95647189f3b0f7f5f5a39c8c3ab8130dcf1fEric Christopher address_default_is_32_bits_(address_default_is_32_bits) { 44b71f95647189f3b0f7f5f5a39c8c3ab8130dcf1fEric Christopher Initialize(); 45b71f95647189f3b0f7f5f5a39c8c3ab8130dcf1fEric Christopher} 46b71f95647189f3b0f7f5f5a39c8c3ab8130dcf1fEric Christopher 47b71f95647189f3b0f7f5f5a39c8c3ab8130dcf1fEric ChristopherMiniDisassembler::MiniDisassembler() 489ce2116005d417f7a36fa99bba7e499a58650a9aEric Christopher : operand_default_is_32_bits_(true), 49b71f95647189f3b0f7f5f5a39c8c3ab8130dcf1fEric Christopher address_default_is_32_bits_(true) { 50b71f95647189f3b0f7f5f5a39c8c3ab8130dcf1fEric Christopher Initialize(); 51b71f95647189f3b0f7f5f5a39c8c3ab8130dcf1fEric Christopher} 52b71f95647189f3b0f7f5f5a39c8c3ab8130dcf1fEric Christopher 53b71f95647189f3b0f7f5f5a39c8c3ab8130dcf1fEric ChristopherInstructionType MiniDisassembler::Disassemble( 54b71f95647189f3b0f7f5f5a39c8c3ab8130dcf1fEric Christopher unsigned char* start_byte, 55b71f95647189f3b0f7f5f5a39c8c3ab8130dcf1fEric Christopher unsigned int& instruction_bytes) { 56b71f95647189f3b0f7f5f5a39c8c3ab8130dcf1fEric Christopher // Clean up any state from previous invocations. 57b71f95647189f3b0f7f5f5a39c8c3ab8130dcf1fEric Christopher Initialize(); 58b71f95647189f3b0f7f5f5a39c8c3ab8130dcf1fEric Christopher 59b71f95647189f3b0f7f5f5a39c8c3ab8130dcf1fEric Christopher // Start by processing any prefixes. 605aeaca3fa755cddba583842e7a0c3e168bf71b4dCraig Topper unsigned char* current_byte = start_byte; 615aeaca3fa755cddba583842e7a0c3e168bf71b4dCraig Topper unsigned int size = 0; 625aeaca3fa755cddba583842e7a0c3e168bf71b4dCraig Topper InstructionType instruction_type = ProcessPrefixes(current_byte, size); 635aeaca3fa755cddba583842e7a0c3e168bf71b4dCraig Topper 645aeaca3fa755cddba583842e7a0c3e168bf71b4dCraig Topper if (IT_UNKNOWN == instruction_type) 655aeaca3fa755cddba583842e7a0c3e168bf71b4dCraig Topper return instruction_type; 665aeaca3fa755cddba583842e7a0c3e168bf71b4dCraig Topper 675aeaca3fa755cddba583842e7a0c3e168bf71b4dCraig Topper current_byte += size; 685aeaca3fa755cddba583842e7a0c3e168bf71b4dCraig Topper size = 0; 695aeaca3fa755cddba583842e7a0c3e168bf71b4dCraig Topper 705aeaca3fa755cddba583842e7a0c3e168bf71b4dCraig Topper // Invariant: We have stripped all prefixes, and the operand_is_32_bits_ 715aeaca3fa755cddba583842e7a0c3e168bf71b4dCraig Topper // and address_is_32_bits_ flags are correctly set. 725aeaca3fa755cddba583842e7a0c3e168bf71b4dCraig Topper 735aeaca3fa755cddba583842e7a0c3e168bf71b4dCraig Topper instruction_type = ProcessOpcode(current_byte, 0, size); 745aeaca3fa755cddba583842e7a0c3e168bf71b4dCraig Topper 755aeaca3fa755cddba583842e7a0c3e168bf71b4dCraig Topper // Check for error processing instruction 765aeaca3fa755cddba583842e7a0c3e168bf71b4dCraig Topper if ((IT_UNKNOWN == instruction_type_) || (IT_UNUSED == instruction_type_)) { 77b71f95647189f3b0f7f5f5a39c8c3ab8130dcf1fEric Christopher return IT_UNKNOWN; 78b71f95647189f3b0f7f5f5a39c8c3ab8130dcf1fEric Christopher } 79347208968c303a9c11fe29012f6dc49680465182Eli Friedman 80347208968c303a9c11fe29012f6dc49680465182Eli Friedman current_byte += size; 81347208968c303a9c11fe29012f6dc49680465182Eli Friedman 826bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines // Invariant: operand_bytes_ indicates the total size of operands 836bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines // specified by the opcode and/or ModR/M byte and/or SIB byte. 846bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines // pCurrentByte points to the first byte after the ModR/M byte, or after 85b71f95647189f3b0f7f5f5a39c8c3ab8130dcf1fEric Christopher // the SIB byte if it is present (i.e. the first byte of any operands 86347208968c303a9c11fe29012f6dc49680465182Eli Friedman // encoded in the instruction). 87347208968c303a9c11fe29012f6dc49680465182Eli Friedman 88347208968c303a9c11fe29012f6dc49680465182Eli Friedman // We get the total length of any prefixes, the opcode, and the ModR/M and 896bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines // SIB bytes if present, by taking the difference of the original starting 906bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines // address and the current byte (which points to the first byte of the 916bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines // operands if present, or to the first byte of the next instruction if 926bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines // they are not). Adding the count of bytes in the operands encoded in 936bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines // the instruction gives us the full length of the instruction in bytes. 94b71f95647189f3b0f7f5f5a39c8c3ab8130dcf1fEric Christopher instruction_bytes += operand_bytes_ + (current_byte - start_byte); 951bddbcbd11de09c7bcb48c3d661c447967db73a7Chris Lattner 96b71f95647189f3b0f7f5f5a39c8c3ab8130dcf1fEric Christopher // Return the instruction type, which was set by ProcessOpcode(). 97b71f95647189f3b0f7f5f5a39c8c3ab8130dcf1fEric Christopher return instruction_type_; 98b71f95647189f3b0f7f5f5a39c8c3ab8130dcf1fEric Christopher} 99b71f95647189f3b0f7f5f5a39c8c3ab8130dcf1fEric Christopher 100b71f95647189f3b0f7f5f5a39c8c3ab8130dcf1fEric Christophervoid MiniDisassembler::Initialize() { 101b71f95647189f3b0f7f5f5a39c8c3ab8130dcf1fEric Christopher operand_is_32_bits_ = operand_default_is_32_bits_; 1021bddbcbd11de09c7bcb48c3d661c447967db73a7Chris Lattner address_is_32_bits_ = address_default_is_32_bits_; 103b71f95647189f3b0f7f5f5a39c8c3ab8130dcf1fEric Christopher#ifdef _M_X64 104b71f95647189f3b0f7f5f5a39c8c3ab8130dcf1fEric Christopher operand_default_support_64_bits_ = true; 105b71f95647189f3b0f7f5f5a39c8c3ab8130dcf1fEric Christopher#else 106b71f95647189f3b0f7f5f5a39c8c3ab8130dcf1fEric Christopher operand_default_support_64_bits_ = false; 107b71f95647189f3b0f7f5f5a39c8c3ab8130dcf1fEric Christopher#endif 108b71f95647189f3b0f7f5f5a39c8c3ab8130dcf1fEric Christopher operand_is_64_bits_ = false; 1091bddbcbd11de09c7bcb48c3d661c447967db73a7Chris Lattner operand_bytes_ = 0; 110b71f95647189f3b0f7f5f5a39c8c3ab8130dcf1fEric Christopher have_modrm_ = false; 111b71f95647189f3b0f7f5f5a39c8c3ab8130dcf1fEric Christopher should_decode_modrm_ = false; 112b71f95647189f3b0f7f5f5a39c8c3ab8130dcf1fEric Christopher instruction_type_ = IT_UNKNOWN; 113b71f95647189f3b0f7f5f5a39c8c3ab8130dcf1fEric Christopher got_f2_prefix_ = false; 114b71f95647189f3b0f7f5f5a39c8c3ab8130dcf1fEric Christopher got_f3_prefix_ = false; 115b71f95647189f3b0f7f5f5a39c8c3ab8130dcf1fEric Christopher got_66_prefix_ = false; 116347208968c303a9c11fe29012f6dc49680465182Eli Friedman} 117347208968c303a9c11fe29012f6dc49680465182Eli Friedman 118347208968c303a9c11fe29012f6dc49680465182Eli FriedmanInstructionType MiniDisassembler::ProcessPrefixes(unsigned char* start_byte, 1196bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines unsigned int& size) { 1206bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines InstructionType instruction_type = IT_GENERIC; 1216bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines const Opcode& opcode = s_ia32_opcode_map_[0].table_[*start_byte]; 1226bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines 1236bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines switch (opcode.type_) { 1246bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines case IT_PREFIX_ADDRESS: 1256bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines address_is_32_bits_ = !address_default_is_32_bits_; 1266bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines goto nochangeoperand; 1276bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines case IT_PREFIX_OPERAND: 128b71f95647189f3b0f7f5f5a39c8c3ab8130dcf1fEric Christopher operand_is_32_bits_ = !operand_default_is_32_bits_; 129c82ac95dbd68cbfa13bf8a93f7230fbe252931f7Eric Christopher nochangeoperand: 1301bddbcbd11de09c7bcb48c3d661c447967db73a7Chris Lattner case IT_PREFIX: 131c82ac95dbd68cbfa13bf8a93f7230fbe252931f7Eric Christopher 132c82ac95dbd68cbfa13bf8a93f7230fbe252931f7Eric Christopher if (0xF2 == (*start_byte)) 133054c27674efe41608eb5546fe16e43f4b3777407Eric Christopher got_f2_prefix_ = true; 134c82ac95dbd68cbfa13bf8a93f7230fbe252931f7Eric Christopher else if (0xF3 == (*start_byte)) 135c82ac95dbd68cbfa13bf8a93f7230fbe252931f7Eric Christopher got_f3_prefix_ = true; 1361bddbcbd11de09c7bcb48c3d661c447967db73a7Chris Lattner else if (0x66 == (*start_byte)) 137c82ac95dbd68cbfa13bf8a93f7230fbe252931f7Eric Christopher got_66_prefix_ = true; 138c82ac95dbd68cbfa13bf8a93f7230fbe252931f7Eric Christopher else if (operand_default_support_64_bits_ && (*start_byte) & 0x48) 139c82ac95dbd68cbfa13bf8a93f7230fbe252931f7Eric Christopher operand_is_64_bits_ = true; 140c82ac95dbd68cbfa13bf8a93f7230fbe252931f7Eric Christopher 141c82ac95dbd68cbfa13bf8a93f7230fbe252931f7Eric Christopher instruction_type = opcode.type_; 142c82ac95dbd68cbfa13bf8a93f7230fbe252931f7Eric Christopher size ++; 1435aeaca3fa755cddba583842e7a0c3e168bf71b4dCraig Topper // we got a prefix, so add one and check next byte 1445aeaca3fa755cddba583842e7a0c3e168bf71b4dCraig Topper ProcessPrefixes(start_byte + 1, size); 1455aeaca3fa755cddba583842e7a0c3e168bf71b4dCraig Topper default: 1465aeaca3fa755cddba583842e7a0c3e168bf71b4dCraig Topper break; // not a prefix byte 1475aeaca3fa755cddba583842e7a0c3e168bf71b4dCraig Topper } 1485aeaca3fa755cddba583842e7a0c3e168bf71b4dCraig Topper 1495aeaca3fa755cddba583842e7a0c3e168bf71b4dCraig Topper return instruction_type; 1505aeaca3fa755cddba583842e7a0c3e168bf71b4dCraig Topper} 1515aeaca3fa755cddba583842e7a0c3e168bf71b4dCraig Topper 152c82ac95dbd68cbfa13bf8a93f7230fbe252931f7Eric ChristopherInstructionType MiniDisassembler::ProcessOpcode(unsigned char* start_byte, 15303568487447d3d8240c36727120a6dd9c527ec5eEric Christopher unsigned int table_index, 1541bddbcbd11de09c7bcb48c3d661c447967db73a7Chris Lattner unsigned int& size) { 15503568487447d3d8240c36727120a6dd9c527ec5eEric Christopher const OpcodeTable& table = s_ia32_opcode_map_[table_index]; // Get our table 15603568487447d3d8240c36727120a6dd9c527ec5eEric Christopher unsigned char current_byte = (*start_byte) >> table.shift_; 15703568487447d3d8240c36727120a6dd9c527ec5eEric Christopher current_byte = current_byte & table.mask_; // Mask out the bits we will use 15803568487447d3d8240c36727120a6dd9c527ec5eEric Christopher 15903568487447d3d8240c36727120a6dd9c527ec5eEric Christopher // Check whether the byte we have is inside the table we have. 1603afda6037d0c96a1868fe9a5ab51b6cfe7fade1cEric Christopher if (current_byte < table.min_lim_ || current_byte > table.max_lim_) { 1611bddbcbd11de09c7bcb48c3d661c447967db73a7Chris Lattner instruction_type_ = IT_UNKNOWN; 1623afda6037d0c96a1868fe9a5ab51b6cfe7fade1cEric Christopher return instruction_type_; 1633afda6037d0c96a1868fe9a5ab51b6cfe7fade1cEric Christopher } 1643afda6037d0c96a1868fe9a5ab51b6cfe7fade1cEric Christopher 1653afda6037d0c96a1868fe9a5ab51b6cfe7fade1cEric Christopher const Opcode& opcode = table.table_[current_byte]; 1663afda6037d0c96a1868fe9a5ab51b6cfe7fade1cEric Christopher if (IT_UNUSED == opcode.type_) { 1671bddbcbd11de09c7bcb48c3d661c447967db73a7Chris Lattner // This instruction is not used by the IA-32 ISA, so we indicate 1683afda6037d0c96a1868fe9a5ab51b6cfe7fade1cEric Christopher // this to the user. Probably means that we were pointed to 1693afda6037d0c96a1868fe9a5ab51b6cfe7fade1cEric Christopher // a byte in memory that was not the start of an instruction. 1703afda6037d0c96a1868fe9a5ab51b6cfe7fade1cEric Christopher instruction_type_ = IT_UNUSED; 1713afda6037d0c96a1868fe9a5ab51b6cfe7fade1cEric Christopher return instruction_type_; 1723afda6037d0c96a1868fe9a5ab51b6cfe7fade1cEric Christopher } else if (IT_REFERENCE == opcode.type_) { 1731bddbcbd11de09c7bcb48c3d661c447967db73a7Chris Lattner // We are looking at an opcode that has more bytes (or is continued 1743afda6037d0c96a1868fe9a5ab51b6cfe7fade1cEric Christopher // in the ModR/M byte). Recursively find the opcode definition in 1753afda6037d0c96a1868fe9a5ab51b6cfe7fade1cEric Christopher // the table for the opcode's next byte. 1763afda6037d0c96a1868fe9a5ab51b6cfe7fade1cEric Christopher size++; 1773afda6037d0c96a1868fe9a5ab51b6cfe7fade1cEric Christopher ProcessOpcode(start_byte + 1, opcode.table_index_, size); 1783afda6037d0c96a1868fe9a5ab51b6cfe7fade1cEric Christopher return instruction_type_; 1791bddbcbd11de09c7bcb48c3d661c447967db73a7Chris Lattner } 1803afda6037d0c96a1868fe9a5ab51b6cfe7fade1cEric Christopher 1813afda6037d0c96a1868fe9a5ab51b6cfe7fade1cEric Christopher const SpecificOpcode* specific_opcode = (SpecificOpcode*)&opcode; 1823afda6037d0c96a1868fe9a5ab51b6cfe7fade1cEric Christopher if (opcode.is_prefix_dependent_) { 1833afda6037d0c96a1868fe9a5ab51b6cfe7fade1cEric Christopher if (got_f2_prefix_ && opcode.opcode_if_f2_prefix_.mnemonic_ != 0) { 1843afda6037d0c96a1868fe9a5ab51b6cfe7fade1cEric Christopher specific_opcode = &opcode.opcode_if_f2_prefix_; 1851bddbcbd11de09c7bcb48c3d661c447967db73a7Chris Lattner } else if (got_f3_prefix_ && opcode.opcode_if_f3_prefix_.mnemonic_ != 0) { 1863afda6037d0c96a1868fe9a5ab51b6cfe7fade1cEric Christopher specific_opcode = &opcode.opcode_if_f3_prefix_; 1873afda6037d0c96a1868fe9a5ab51b6cfe7fade1cEric Christopher } else if (got_66_prefix_ && opcode.opcode_if_66_prefix_.mnemonic_ != 0) { 1883afda6037d0c96a1868fe9a5ab51b6cfe7fade1cEric Christopher specific_opcode = &opcode.opcode_if_66_prefix_; 1893afda6037d0c96a1868fe9a5ab51b6cfe7fade1cEric Christopher } 1903afda6037d0c96a1868fe9a5ab51b6cfe7fade1cEric Christopher } 1911bddbcbd11de09c7bcb48c3d661c447967db73a7Chris Lattner 1923afda6037d0c96a1868fe9a5ab51b6cfe7fade1cEric Christopher // Inv: The opcode type is known. 1933afda6037d0c96a1868fe9a5ab51b6cfe7fade1cEric Christopher instruction_type_ = specific_opcode->type_; 1943afda6037d0c96a1868fe9a5ab51b6cfe7fade1cEric Christopher 1953afda6037d0c96a1868fe9a5ab51b6cfe7fade1cEric Christopher // Let's process the operand types to see if we have any immediate 1963afda6037d0c96a1868fe9a5ab51b6cfe7fade1cEric Christopher // operands, and/or a ModR/M byte. 1971bddbcbd11de09c7bcb48c3d661c447967db73a7Chris Lattner 1983afda6037d0c96a1868fe9a5ab51b6cfe7fade1cEric Christopher ProcessOperand(specific_opcode->flag_dest_); 1993afda6037d0c96a1868fe9a5ab51b6cfe7fade1cEric Christopher ProcessOperand(specific_opcode->flag_source_); 2003afda6037d0c96a1868fe9a5ab51b6cfe7fade1cEric Christopher ProcessOperand(specific_opcode->flag_aux_); 2013afda6037d0c96a1868fe9a5ab51b6cfe7fade1cEric Christopher 2023afda6037d0c96a1868fe9a5ab51b6cfe7fade1cEric Christopher // Inv: We have processed the opcode and incremented operand_bytes_ 2031bddbcbd11de09c7bcb48c3d661c447967db73a7Chris Lattner // by the number of bytes of any operands specified by the opcode 2043afda6037d0c96a1868fe9a5ab51b6cfe7fade1cEric Christopher // that are stored in the instruction (not registers etc.). Now 2053afda6037d0c96a1868fe9a5ab51b6cfe7fade1cEric Christopher // we need to return the total number of bytes for the opcode and 2063afda6037d0c96a1868fe9a5ab51b6cfe7fade1cEric Christopher // for the ModR/M or SIB bytes if they are present. 2073afda6037d0c96a1868fe9a5ab51b6cfe7fade1cEric Christopher 2083afda6037d0c96a1868fe9a5ab51b6cfe7fade1cEric Christopher if (table.mask_ != 0xff) { 2099a2a69f60898f771d44af0e40e7b4cf37b565d21Eric Christopher if (have_modrm_) { 2109a2a69f60898f771d44af0e40e7b4cf37b565d21Eric Christopher // we're looking at a ModR/M byte so we're not going to 2119a2a69f60898f771d44af0e40e7b4cf37b565d21Eric Christopher // count that into the opcode size 2124f918aed75d4927e88365541c7200f0b5fe5014bDavid Blaikie ProcessModrm(start_byte, size); 21379e5ab7a537987348a9ba01424d8bbe7080eac57Daniel Dunbar return IT_GENERIC; 2148484375b0fc442c704b3ec06e2e795d88591606fManman Ren } else { 2154f918aed75d4927e88365541c7200f0b5fe5014bDavid Blaikie // need to count the ModR/M byte even if it's just being 2169a2a69f60898f771d44af0e40e7b4cf37b565d21Eric Christopher // used for opcode extension 2179a2a69f60898f771d44af0e40e7b4cf37b565d21Eric Christopher size++; 2189a2a69f60898f771d44af0e40e7b4cf37b565d21Eric Christopher return IT_GENERIC; 21979e5ab7a537987348a9ba01424d8bbe7080eac57Daniel Dunbar } 2209a2a69f60898f771d44af0e40e7b4cf37b565d21Eric Christopher } else { 2219a2a69f60898f771d44af0e40e7b4cf37b565d21Eric Christopher if (have_modrm_) { 2229a2a69f60898f771d44af0e40e7b4cf37b565d21Eric Christopher // The ModR/M byte is the next byte. 2239a2a69f60898f771d44af0e40e7b4cf37b565d21Eric Christopher size++; 2249a2a69f60898f771d44af0e40e7b4cf37b565d21Eric Christopher ProcessModrm(start_byte + 1, size); 2259a2a69f60898f771d44af0e40e7b4cf37b565d21Eric Christopher return IT_GENERIC; 2269a2a69f60898f771d44af0e40e7b4cf37b565d21Eric Christopher } else { 2279a2a69f60898f771d44af0e40e7b4cf37b565d21Eric Christopher size++; 2289a2a69f60898f771d44af0e40e7b4cf37b565d21Eric Christopher return IT_GENERIC; 2296fa43e3aaf98afc3b337968429523e80f6e08d91Eric Christopher } 2306fa43e3aaf98afc3b337968429523e80f6e08d91Eric Christopher } 23179e5ab7a537987348a9ba01424d8bbe7080eac57Daniel Dunbar} 2328484375b0fc442c704b3ec06e2e795d88591606fManman Ren 2336fa43e3aaf98afc3b337968429523e80f6e08d91Eric Christopherbool MiniDisassembler::ProcessOperand(int flag_operand) { 23479e5ab7a537987348a9ba01424d8bbe7080eac57Daniel Dunbar bool succeeded = true; 2358484375b0fc442c704b3ec06e2e795d88591606fManman Ren if (AM_NOT_USED == flag_operand) 2366fa43e3aaf98afc3b337968429523e80f6e08d91Eric Christopher return succeeded; 2376fa43e3aaf98afc3b337968429523e80f6e08d91Eric Christopher 23879e5ab7a537987348a9ba01424d8bbe7080eac57Daniel Dunbar // Decide what to do based on the addressing mode. 2398484375b0fc442c704b3ec06e2e795d88591606fManman Ren switch (flag_operand & AM_MASK) { 2406fa43e3aaf98afc3b337968429523e80f6e08d91Eric Christopher // No ModR/M byte indicated by these addressing modes, and no 2416fa43e3aaf98afc3b337968429523e80f6e08d91Eric Christopher // additional (e.g. immediate) parameters. 2429a2a69f60898f771d44af0e40e7b4cf37b565d21Eric Christopher case AM_A: // Direct address 243d6b84b9455202c8a93a306c02770cdfecf13fda0Chris Lattner case AM_F: // EFLAGS register 244d6b84b9455202c8a93a306c02770cdfecf13fda0Chris Lattner case AM_X: // Memory addressed by the DS:SI register pair 245d6b84b9455202c8a93a306c02770cdfecf13fda0Chris Lattner case AM_Y: // Memory addressed by the ES:DI register pair 24679e5ab7a537987348a9ba01424d8bbe7080eac57Daniel Dunbar case AM_IMPLICIT: // Parameter is implicit, occupies no space in 247860c518c99f23e9c78c941627e91d0fa735a27c6Eli Friedman // instruction 2488484375b0fc442c704b3ec06e2e795d88591606fManman Ren break; 24979e5ab7a537987348a9ba01424d8bbe7080eac57Daniel Dunbar 2508484375b0fc442c704b3ec06e2e795d88591606fManman Ren // There is a ModR/M byte but it does not necessarily need 251ff8aeaa9827188f9fc360cb4e0a6c8b6331edc8aEric Christopher // to be decoded. 25279e5ab7a537987348a9ba01424d8bbe7080eac57Daniel Dunbar case AM_C: // reg field of ModR/M selects a control register 2538484375b0fc442c704b3ec06e2e795d88591606fManman Ren case AM_D: // reg field of ModR/M selects a debug register 254ff8aeaa9827188f9fc360cb4e0a6c8b6331edc8aEric Christopher case AM_G: // reg field of ModR/M selects a general register 255ff8aeaa9827188f9fc360cb4e0a6c8b6331edc8aEric Christopher case AM_P: // reg field of ModR/M selects an MMX register 2560c2b4f40ac17156a424d4faa20ba5d862ecc8416Eric Christopher case AM_R: // mod field of ModR/M may refer only to a general register 2571bddbcbd11de09c7bcb48c3d661c447967db73a7Chris Lattner case AM_S: // reg field of ModR/M selects a segment register 2580c2b4f40ac17156a424d4faa20ba5d862ecc8416Eric Christopher case AM_T: // reg field of ModR/M selects a test register 2590c2b4f40ac17156a424d4faa20ba5d862ecc8416Eric Christopher case AM_V: // reg field of ModR/M selects a 128-bit XMM register 2600c2b4f40ac17156a424d4faa20ba5d862ecc8416Eric Christopher have_modrm_ = true; 2610c2b4f40ac17156a424d4faa20ba5d862ecc8416Eric Christopher break; 2620c2b4f40ac17156a424d4faa20ba5d862ecc8416Eric Christopher 2631bddbcbd11de09c7bcb48c3d661c447967db73a7Chris Lattner // In these addressing modes, there is a ModR/M byte and it needs to be 2640c2b4f40ac17156a424d4faa20ba5d862ecc8416Eric Christopher // decoded. No other (e.g. immediate) params than indicated in ModR/M. 2650c2b4f40ac17156a424d4faa20ba5d862ecc8416Eric Christopher case AM_E: // Operand is either a general-purpose register or memory, 2660c2b4f40ac17156a424d4faa20ba5d862ecc8416Eric Christopher // specified by ModR/M byte 2670c2b4f40ac17156a424d4faa20ba5d862ecc8416Eric Christopher case AM_M: // ModR/M byte will refer only to memory 2680c2b4f40ac17156a424d4faa20ba5d862ecc8416Eric Christopher case AM_Q: // Operand is either an MMX register or memory (complex 2691bddbcbd11de09c7bcb48c3d661c447967db73a7Chris Lattner // evaluation), specified by ModR/M byte 2700c2b4f40ac17156a424d4faa20ba5d862ecc8416Eric Christopher case AM_W: // Operand is either a 128-bit XMM register or memory (complex 2710c2b4f40ac17156a424d4faa20ba5d862ecc8416Eric Christopher // eval), specified by ModR/M byte 2720c2b4f40ac17156a424d4faa20ba5d862ecc8416Eric Christopher have_modrm_ = true; 2730c2b4f40ac17156a424d4faa20ba5d862ecc8416Eric Christopher should_decode_modrm_ = true; 2740c2b4f40ac17156a424d4faa20ba5d862ecc8416Eric Christopher break; 2750c2b4f40ac17156a424d4faa20ba5d862ecc8416Eric Christopher 2760c2b4f40ac17156a424d4faa20ba5d862ecc8416Eric Christopher // These addressing modes specify an immediate or an offset value 2770d57ca1449d7a4d7afb927d4c3c1069dc6339372Bob Wilson // directly, so we need to look at the operand type to see how many 2780c2b4f40ac17156a424d4faa20ba5d862ecc8416Eric Christopher // bytes. 2797bd0dfd322d7a2d6a5461dcbdb2a83fd729dd8e2Eric Christopher case AM_I: // Immediate data. 2801bddbcbd11de09c7bcb48c3d661c447967db73a7Chris Lattner case AM_J: // Jump to offset. 2817bd0dfd322d7a2d6a5461dcbdb2a83fd729dd8e2Eric Christopher case AM_O: // Operand is at offset. 2827bd0dfd322d7a2d6a5461dcbdb2a83fd729dd8e2Eric Christopher switch (flag_operand & OT_MASK) { 2834c07c5dfebd270b2f0660e86f056eeafdb26a4fbCraig Topper case OT_B: // Byte regardless of operand-size attribute. 2847bd0dfd322d7a2d6a5461dcbdb2a83fd729dd8e2Eric Christopher operand_bytes_ += OS_BYTE; 2857bd0dfd322d7a2d6a5461dcbdb2a83fd729dd8e2Eric Christopher break; 2867bd0dfd322d7a2d6a5461dcbdb2a83fd729dd8e2Eric Christopher case OT_C: // Byte or word, depending on operand-size attribute. 2871bddbcbd11de09c7bcb48c3d661c447967db73a7Chris Lattner if (operand_is_32_bits_) 2887bd0dfd322d7a2d6a5461dcbdb2a83fd729dd8e2Eric Christopher operand_bytes_ += OS_WORD; 2897bd0dfd322d7a2d6a5461dcbdb2a83fd729dd8e2Eric Christopher else 2907bd0dfd322d7a2d6a5461dcbdb2a83fd729dd8e2Eric Christopher operand_bytes_ += OS_BYTE; 2917bd0dfd322d7a2d6a5461dcbdb2a83fd729dd8e2Eric Christopher break; 2927bd0dfd322d7a2d6a5461dcbdb2a83fd729dd8e2Eric Christopher case OT_D: // Doubleword, regardless of operand-size attribute. 2931bddbcbd11de09c7bcb48c3d661c447967db73a7Chris Lattner operand_bytes_ += OS_DOUBLE_WORD; 2947bd0dfd322d7a2d6a5461dcbdb2a83fd729dd8e2Eric Christopher break; 2957bd0dfd322d7a2d6a5461dcbdb2a83fd729dd8e2Eric Christopher case OT_DQ: // Double-quadword, regardless of operand-size attribute. 2967bd0dfd322d7a2d6a5461dcbdb2a83fd729dd8e2Eric Christopher operand_bytes_ += OS_DOUBLE_QUAD_WORD; 2977bd0dfd322d7a2d6a5461dcbdb2a83fd729dd8e2Eric Christopher break; 2987bd0dfd322d7a2d6a5461dcbdb2a83fd729dd8e2Eric Christopher case OT_P: // 32-bit or 48-bit pointer, depending on operand-size 2991bddbcbd11de09c7bcb48c3d661c447967db73a7Chris Lattner // attribute. 3007bd0dfd322d7a2d6a5461dcbdb2a83fd729dd8e2Eric Christopher if (operand_is_32_bits_) 3017bd0dfd322d7a2d6a5461dcbdb2a83fd729dd8e2Eric Christopher operand_bytes_ += OS_48_BIT_POINTER; 3027bd0dfd322d7a2d6a5461dcbdb2a83fd729dd8e2Eric Christopher else 3037bd0dfd322d7a2d6a5461dcbdb2a83fd729dd8e2Eric Christopher operand_bytes_ += OS_32_BIT_POINTER; 3047bd0dfd322d7a2d6a5461dcbdb2a83fd729dd8e2Eric Christopher break; 3051bddbcbd11de09c7bcb48c3d661c447967db73a7Chris Lattner case OT_PS: // 128-bit packed single-precision floating-point data. 3067bd0dfd322d7a2d6a5461dcbdb2a83fd729dd8e2Eric Christopher operand_bytes_ += OS_128_BIT_PACKED_SINGLE_PRECISION_FLOATING; 3077bd0dfd322d7a2d6a5461dcbdb2a83fd729dd8e2Eric Christopher break; 3087bd0dfd322d7a2d6a5461dcbdb2a83fd729dd8e2Eric Christopher case OT_Q: // Quadword, regardless of operand-size attribute. 3097bd0dfd322d7a2d6a5461dcbdb2a83fd729dd8e2Eric Christopher operand_bytes_ += OS_QUAD_WORD; 3107bd0dfd322d7a2d6a5461dcbdb2a83fd729dd8e2Eric Christopher break; 3111bddbcbd11de09c7bcb48c3d661c447967db73a7Chris Lattner case OT_S: // 6-byte pseudo-descriptor. 3127bd0dfd322d7a2d6a5461dcbdb2a83fd729dd8e2Eric Christopher operand_bytes_ += OS_PSEUDO_DESCRIPTOR; 3137bd0dfd322d7a2d6a5461dcbdb2a83fd729dd8e2Eric Christopher break; 3147bd0dfd322d7a2d6a5461dcbdb2a83fd729dd8e2Eric Christopher case OT_SD: // Scalar Double-Precision Floating-Point Value 3157bd0dfd322d7a2d6a5461dcbdb2a83fd729dd8e2Eric Christopher case OT_PD: // Unaligned packed double-precision floating point value 3167bd0dfd322d7a2d6a5461dcbdb2a83fd729dd8e2Eric Christopher operand_bytes_ += OS_DOUBLE_PRECISION_FLOATING; 3171bddbcbd11de09c7bcb48c3d661c447967db73a7Chris Lattner break; 3187bd0dfd322d7a2d6a5461dcbdb2a83fd729dd8e2Eric Christopher case OT_SS: 3197bd0dfd322d7a2d6a5461dcbdb2a83fd729dd8e2Eric Christopher // Scalar element of a 128-bit packed single-precision 3207bd0dfd322d7a2d6a5461dcbdb2a83fd729dd8e2Eric Christopher // floating data. 3217bd0dfd322d7a2d6a5461dcbdb2a83fd729dd8e2Eric Christopher // We simply return enItUnknown since we don't have to support 3227bd0dfd322d7a2d6a5461dcbdb2a83fd729dd8e2Eric Christopher // floating point 3237bd0dfd322d7a2d6a5461dcbdb2a83fd729dd8e2Eric Christopher succeeded = false; 3241bddbcbd11de09c7bcb48c3d661c447967db73a7Chris Lattner break; 3257bd0dfd322d7a2d6a5461dcbdb2a83fd729dd8e2Eric Christopher case OT_V: // Word, doubleword or quadword, depending on operand-size 3267bd0dfd322d7a2d6a5461dcbdb2a83fd729dd8e2Eric Christopher // attribute. 3277bd0dfd322d7a2d6a5461dcbdb2a83fd729dd8e2Eric Christopher if (operand_is_64_bits_ && flag_operand & AM_I && 3287bd0dfd322d7a2d6a5461dcbdb2a83fd729dd8e2Eric Christopher flag_operand & IOS_64) 3297bd0dfd322d7a2d6a5461dcbdb2a83fd729dd8e2Eric Christopher operand_bytes_ += OS_QUAD_WORD; 3301bddbcbd11de09c7bcb48c3d661c447967db73a7Chris Lattner else if (operand_is_32_bits_) 3317bd0dfd322d7a2d6a5461dcbdb2a83fd729dd8e2Eric Christopher operand_bytes_ += OS_DOUBLE_WORD; 3327bd0dfd322d7a2d6a5461dcbdb2a83fd729dd8e2Eric Christopher else 3337bd0dfd322d7a2d6a5461dcbdb2a83fd729dd8e2Eric Christopher operand_bytes_ += OS_WORD; 3347bd0dfd322d7a2d6a5461dcbdb2a83fd729dd8e2Eric Christopher break; 3357bd0dfd322d7a2d6a5461dcbdb2a83fd729dd8e2Eric Christopher case OT_W: // Word, regardless of operand-size attribute. 3361bddbcbd11de09c7bcb48c3d661c447967db73a7Chris Lattner operand_bytes_ += OS_WORD; 3377bd0dfd322d7a2d6a5461dcbdb2a83fd729dd8e2Eric Christopher break; 3387bd0dfd322d7a2d6a5461dcbdb2a83fd729dd8e2Eric Christopher 3397bd0dfd322d7a2d6a5461dcbdb2a83fd729dd8e2Eric Christopher // Can safely ignore these. 3407bd0dfd322d7a2d6a5461dcbdb2a83fd729dd8e2Eric Christopher case OT_A: // Two one-word operands in memory or two double-word 3417bd0dfd322d7a2d6a5461dcbdb2a83fd729dd8e2Eric Christopher // operands in memory 3421bddbcbd11de09c7bcb48c3d661c447967db73a7Chris Lattner case OT_PI: // Quadword MMX technology register (e.g. mm0) 3437bd0dfd322d7a2d6a5461dcbdb2a83fd729dd8e2Eric Christopher case OT_SI: // Doubleword integer register (e.g., eax) 3447bd0dfd322d7a2d6a5461dcbdb2a83fd729dd8e2Eric Christopher break; 3457bd0dfd322d7a2d6a5461dcbdb2a83fd729dd8e2Eric Christopher 3467bd0dfd322d7a2d6a5461dcbdb2a83fd729dd8e2Eric Christopher default: 3477bd0dfd322d7a2d6a5461dcbdb2a83fd729dd8e2Eric Christopher break; 3481bddbcbd11de09c7bcb48c3d661c447967db73a7Chris Lattner } 3497bd0dfd322d7a2d6a5461dcbdb2a83fd729dd8e2Eric Christopher break; 3507bd0dfd322d7a2d6a5461dcbdb2a83fd729dd8e2Eric Christopher 3517bd0dfd322d7a2d6a5461dcbdb2a83fd729dd8e2Eric Christopher default: 3527bd0dfd322d7a2d6a5461dcbdb2a83fd729dd8e2Eric Christopher break; 3537bd0dfd322d7a2d6a5461dcbdb2a83fd729dd8e2Eric Christopher } 3541bddbcbd11de09c7bcb48c3d661c447967db73a7Chris Lattner 3557bd0dfd322d7a2d6a5461dcbdb2a83fd729dd8e2Eric Christopher return succeeded; 3567bd0dfd322d7a2d6a5461dcbdb2a83fd729dd8e2Eric Christopher} 3577bd0dfd322d7a2d6a5461dcbdb2a83fd729dd8e2Eric Christopher 3587bd0dfd322d7a2d6a5461dcbdb2a83fd729dd8e2Eric Christopherbool MiniDisassembler::ProcessModrm(unsigned char* start_byte, 3597bd0dfd322d7a2d6a5461dcbdb2a83fd729dd8e2Eric Christopher unsigned int& size) { 3607bd0dfd322d7a2d6a5461dcbdb2a83fd729dd8e2Eric Christopher // If we don't need to decode, we just return the size of the ModR/M 3611bddbcbd11de09c7bcb48c3d661c447967db73a7Chris Lattner // byte (there is never a SIB byte in this case). 3627bd0dfd322d7a2d6a5461dcbdb2a83fd729dd8e2Eric Christopher if (!should_decode_modrm_) { 3637bd0dfd322d7a2d6a5461dcbdb2a83fd729dd8e2Eric Christopher size++; 3647bd0dfd322d7a2d6a5461dcbdb2a83fd729dd8e2Eric Christopher return true; 3657bd0dfd322d7a2d6a5461dcbdb2a83fd729dd8e2Eric Christopher } 3667bd0dfd322d7a2d6a5461dcbdb2a83fd729dd8e2Eric Christopher 3677bd0dfd322d7a2d6a5461dcbdb2a83fd729dd8e2Eric Christopher // We never care about the reg field, only the combination of the mod 3685aeaca3fa755cddba583842e7a0c3e168bf71b4dCraig Topper // and r/m fields, so let's start by packing those fields together into 3695aeaca3fa755cddba583842e7a0c3e168bf71b4dCraig Topper // 5 bits. 3705aeaca3fa755cddba583842e7a0c3e168bf71b4dCraig Topper unsigned char modrm = (*start_byte); 3715aeaca3fa755cddba583842e7a0c3e168bf71b4dCraig Topper unsigned char mod = modrm & 0xC0; // mask out top two bits to get mod field 3727bd0dfd322d7a2d6a5461dcbdb2a83fd729dd8e2Eric Christopher modrm = modrm & 0x07; // mask out bottom 3 bits to get r/m field 3735228982f07d3420672060b2429a797b0cd3e00d5Craig Topper mod = mod >> 3; // shift the mod field to the right place 3745228982f07d3420672060b2429a797b0cd3e00d5Craig Topper modrm = mod | modrm; // combine the r/m and mod fields as discussed 3755228982f07d3420672060b2429a797b0cd3e00d5Craig Topper mod = mod >> 3; // shift the mod field to bits 2..0 3765228982f07d3420672060b2429a797b0cd3e00d5Craig Topper 3775228982f07d3420672060b2429a797b0cd3e00d5Craig Topper // Invariant: modrm contains the mod field in bits 4..3 and the r/m field 3785228982f07d3420672060b2429a797b0cd3e00d5Craig Topper // in bits 2..0, and mod contains the mod field in bits 2..0 37967a5936a1d60fff1ec12441de63fd27ea50b0130Eric Christopher 38067a5936a1d60fff1ec12441de63fd27ea50b0130Eric Christopher const ModrmEntry* modrm_entry = 0; 38167a5936a1d60fff1ec12441de63fd27ea50b0130Eric Christopher if (address_is_32_bits_) 38267a5936a1d60fff1ec12441de63fd27ea50b0130Eric Christopher modrm_entry = &s_ia32_modrm_map_[modrm]; 38367a5936a1d60fff1ec12441de63fd27ea50b0130Eric Christopher else 38467a5936a1d60fff1ec12441de63fd27ea50b0130Eric Christopher modrm_entry = &s_ia16_modrm_map_[modrm]; 38567a5936a1d60fff1ec12441de63fd27ea50b0130Eric Christopher 38667a5936a1d60fff1ec12441de63fd27ea50b0130Eric Christopher // Invariant: modrm_entry points to information that we need to decode 38767a5936a1d60fff1ec12441de63fd27ea50b0130Eric Christopher // the ModR/M byte. 38867a5936a1d60fff1ec12441de63fd27ea50b0130Eric Christopher 38967a5936a1d60fff1ec12441de63fd27ea50b0130Eric Christopher // Add to the count of operand bytes, if the ModR/M byte indicates 39067a5936a1d60fff1ec12441de63fd27ea50b0130Eric Christopher // that some operands are encoded in the instruction. 39167a5936a1d60fff1ec12441de63fd27ea50b0130Eric Christopher if (modrm_entry->is_encoded_in_instruction_) 39267a5936a1d60fff1ec12441de63fd27ea50b0130Eric Christopher operand_bytes_ += modrm_entry->operand_size_; 39367a5936a1d60fff1ec12441de63fd27ea50b0130Eric Christopher 39467a5936a1d60fff1ec12441de63fd27ea50b0130Eric Christopher // Process the SIB byte if necessary, and return the count 39567a5936a1d60fff1ec12441de63fd27ea50b0130Eric Christopher // of ModR/M and SIB bytes. 39667a5936a1d60fff1ec12441de63fd27ea50b0130Eric Christopher if (modrm_entry->use_sib_byte_) { 39767a5936a1d60fff1ec12441de63fd27ea50b0130Eric Christopher size++; 39867a5936a1d60fff1ec12441de63fd27ea50b0130Eric Christopher return ProcessSib(start_byte + 1, mod, size); 39967a5936a1d60fff1ec12441de63fd27ea50b0130Eric Christopher } else { 40067a5936a1d60fff1ec12441de63fd27ea50b0130Eric Christopher size++; 40167a5936a1d60fff1ec12441de63fd27ea50b0130Eric Christopher return true; 40267a5936a1d60fff1ec12441de63fd27ea50b0130Eric Christopher } 40367a5936a1d60fff1ec12441de63fd27ea50b0130Eric Christopher} 40467a5936a1d60fff1ec12441de63fd27ea50b0130Eric Christopher 40567a5936a1d60fff1ec12441de63fd27ea50b0130Eric Christopherbool MiniDisassembler::ProcessSib(unsigned char* start_byte, 40667a5936a1d60fff1ec12441de63fd27ea50b0130Eric Christopher unsigned char mod, 40767a5936a1d60fff1ec12441de63fd27ea50b0130Eric Christopher unsigned int& size) { 40867a5936a1d60fff1ec12441de63fd27ea50b0130Eric Christopher // get the mod field from the 2..0 bits of the SIB byte 40967a5936a1d60fff1ec12441de63fd27ea50b0130Eric Christopher unsigned char sib_base = (*start_byte) & 0x07; 41067a5936a1d60fff1ec12441de63fd27ea50b0130Eric Christopher if (0x05 == sib_base) { 41167a5936a1d60fff1ec12441de63fd27ea50b0130Eric Christopher switch (mod) { 41267a5936a1d60fff1ec12441de63fd27ea50b0130Eric Christopher case 0x00: // mod == 00 41367a5936a1d60fff1ec12441de63fd27ea50b0130Eric Christopher case 0x02: // mod == 10 41467a5936a1d60fff1ec12441de63fd27ea50b0130Eric Christopher operand_bytes_ += OS_DOUBLE_WORD; 4154b45c111f0ac43441c475aca4ecc1d62499e0cb8Chandler Carruth break; 41667a5936a1d60fff1ec12441de63fd27ea50b0130Eric Christopher case 0x01: // mod == 01 41767a5936a1d60fff1ec12441de63fd27ea50b0130Eric Christopher operand_bytes_ += OS_BYTE; 41867a5936a1d60fff1ec12441de63fd27ea50b0130Eric Christopher break; 419355130fde923c7284d32cc61fc3a34673bf14852Eli Friedman case 0x03: // mod == 11 420355130fde923c7284d32cc61fc3a34673bf14852Eli Friedman // According to the IA-32 docs, there does not seem to be a disp 421355130fde923c7284d32cc61fc3a34673bf14852Eli Friedman // value for this value of mod 422355130fde923c7284d32cc61fc3a34673bf14852Eli Friedman default: 423355130fde923c7284d32cc61fc3a34673bf14852Eli Friedman break; 424355130fde923c7284d32cc61fc3a34673bf14852Eli Friedman } 425355130fde923c7284d32cc61fc3a34673bf14852Eli Friedman } 426355130fde923c7284d32cc61fc3a34673bf14852Eli Friedman 427355130fde923c7284d32cc61fc3a34673bf14852Eli Friedman size++; 428355130fde923c7284d32cc61fc3a34673bf14852Eli Friedman return true; 42967a5936a1d60fff1ec12441de63fd27ea50b0130Eric Christopher} 43067a5936a1d60fff1ec12441de63fd27ea50b0130Eric Christopher 43167a5936a1d60fff1ec12441de63fd27ea50b0130Eric Christopher}; // namespace sidestep 43267a5936a1d60fff1ec12441de63fd27ea50b0130Eric Christopher