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