1fb144a0716afe7ab8bf245f2391a9e53b3db3c89fschneider@chromium.org// Copyright 2011 the V8 project authors. All rights reserved.
243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// Redistribution and use in source and binary forms, with or without
343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// modification, are permitted provided that the following conditions are
443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// met:
543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen//
643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen//     * Redistributions of source code must retain the above copyright
743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen//       notice, this list of conditions and the following disclaimer.
843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen//     * Redistributions in binary form must reproduce the above
943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen//       copyright notice, this list of conditions and the following
1043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen//       disclaimer in the documentation and/or other materials provided
1143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen//       with the distribution.
1243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen//     * Neither the name of Google Inc. nor the names of its
1343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen//       contributors may be used to endorse or promote products derived
1443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen//       from this software without specific prior written permission.
1543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen//
1643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
1743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
1843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
1943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
2043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
2143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
2243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
2643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
2843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen#include <assert.h>
2943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen#include <stdio.h>
3043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen#include <stdarg.h>
317276f14ca716596e0a0d17539516370c1f453847kasper.lund
327276f14ca716596e0a0d17539516370c1f453847kasper.lund#include "v8.h"
339dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
3493a47f4837f2137c8d8349250fd8e91da3108126jkummerow@chromium.org#if V8_TARGET_ARCH_IA32
359dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
3643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen#include "disasm.h"
3743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
3843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansennamespace disasm {
3943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
4043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansenenum OperandOrder {
4143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  UNSET_OP_ORDER = 0,
4243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  REG_OPER_OP_ORDER,
4343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  OPER_REG_OP_ORDER
4443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen};
4543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
4643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
4743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen//------------------------------------------------------------------
4843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// Tables
4943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen//------------------------------------------------------------------
5043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansenstruct ByteMnemonic {
5143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  int b;  // -1 terminates, otherwise must be in range (0..255)
5243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  const char* mnem;
5343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  OperandOrder op_order_;
5443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen};
5543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
5643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
577c2628c3f0353f0558760c3ca442f934263ea766kmillikin@chromium.orgstatic const ByteMnemonic two_operands_instr[] = {
58c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  {0x01, "add", OPER_REG_OP_ORDER},
5943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  {0x03, "add", REG_OPER_OP_ORDER},
6043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  {0x09, "or", OPER_REG_OP_ORDER},
6143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  {0x0B, "or", REG_OPER_OP_ORDER},
6243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  {0x1B, "sbb", REG_OPER_OP_ORDER},
63b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  {0x21, "and", OPER_REG_OP_ORDER},
64b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  {0x23, "and", REG_OPER_OP_ORDER},
6543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  {0x29, "sub", OPER_REG_OP_ORDER},
660c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org  {0x2A, "subb", REG_OPER_OP_ORDER},
6743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  {0x2B, "sub", REG_OPER_OP_ORDER},
6843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  {0x31, "xor", OPER_REG_OP_ORDER},
6943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  {0x33, "xor", REG_OPER_OP_ORDER},
70b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  {0x38, "cmpb", OPER_REG_OP_ORDER},
71b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  {0x3A, "cmpb", REG_OPER_OP_ORDER},
72b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  {0x3B, "cmp", REG_OPER_OP_ORDER},
73b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  {0x84, "test_b", REG_OPER_OP_ORDER},
74b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  {0x85, "test", REG_OPER_OP_ORDER},
757be3c996bea370e151c9fe4ecf7f779cdc5f87adkasperl@chromium.org  {0x87, "xchg", REG_OPER_OP_ORDER},
7643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  {0x8A, "mov_b", REG_OPER_OP_ORDER},
7743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  {0x8B, "mov", REG_OPER_OP_ORDER},
78b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  {0x8D, "lea", REG_OPER_OP_ORDER},
7943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  {-1, "", UNSET_OP_ORDER}
8043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen};
8143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
8243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
837c2628c3f0353f0558760c3ca442f934263ea766kmillikin@chromium.orgstatic const ByteMnemonic zero_operands_instr[] = {
8443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  {0xC3, "ret", UNSET_OP_ORDER},
8543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  {0xC9, "leave", UNSET_OP_ORDER},
8643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  {0x90, "nop", UNSET_OP_ORDER},
8743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  {0xF4, "hlt", UNSET_OP_ORDER},
8843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  {0xCC, "int3", UNSET_OP_ORDER},
8943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  {0x60, "pushad", UNSET_OP_ORDER},
9043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  {0x61, "popad", UNSET_OP_ORDER},
9143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  {0x9C, "pushfd", UNSET_OP_ORDER},
9243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  {0x9D, "popfd", UNSET_OP_ORDER},
9343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  {0x9E, "sahf", UNSET_OP_ORDER},
9443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  {0x99, "cdq", UNSET_OP_ORDER},
9543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  {0x9B, "fwait", UNSET_OP_ORDER},
96ce5e87bd905d592a8bd612b3dedf7a994177c13aager@chromium.org  {0xFC, "cld", UNSET_OP_ORDER},
979dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  {0xAB, "stos", UNSET_OP_ORDER},
9843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  {-1, "", UNSET_OP_ORDER}
9943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen};
10043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
10143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
1027c2628c3f0353f0558760c3ca442f934263ea766kmillikin@chromium.orgstatic const ByteMnemonic call_jump_instr[] = {
10343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  {0xE8, "call", UNSET_OP_ORDER},
10443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  {0xE9, "jmp", UNSET_OP_ORDER},
10543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  {-1, "", UNSET_OP_ORDER}
10643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen};
10743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
10843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
1097c2628c3f0353f0558760c3ca442f934263ea766kmillikin@chromium.orgstatic const ByteMnemonic short_immediate_instr[] = {
11043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  {0x05, "add", UNSET_OP_ORDER},
11143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  {0x0D, "or", UNSET_OP_ORDER},
11243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  {0x15, "adc", UNSET_OP_ORDER},
11343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  {0x25, "and", UNSET_OP_ORDER},
11443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  {0x2D, "sub", UNSET_OP_ORDER},
11543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  {0x35, "xor", UNSET_OP_ORDER},
11643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  {0x3D, "cmp", UNSET_OP_ORDER},
11743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  {-1, "", UNSET_OP_ORDER}
11843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen};
11943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
12043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
121c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com// Generally we don't want to generate these because they are subject to partial
122c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com// register stalls.  They are included for completeness and because the cmp
123c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com// variant is used by the RecordWrite stub.  Because it does not update the
124c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com// register it is not subject to partial register stalls.
125c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.comstatic ByteMnemonic byte_immediate_instr[] = {
126c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  {0x0c, "or", UNSET_OP_ORDER},
127c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  {0x24, "and", UNSET_OP_ORDER},
128c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  {0x34, "xor", UNSET_OP_ORDER},
129c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  {0x3c, "cmp", UNSET_OP_ORDER},
130c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  {-1, "", UNSET_OP_ORDER}
131c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com};
132c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
133c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
1347c2628c3f0353f0558760c3ca442f934263ea766kmillikin@chromium.orgstatic const char* const jump_conditional_mnem[] = {
13543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  /*0*/ "jo", "jno", "jc", "jnc",
13643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  /*4*/ "jz", "jnz", "jna", "ja",
13743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  /*8*/ "js", "jns", "jpe", "jpo",
13843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  /*12*/ "jl", "jnl", "jng", "jg"
13943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen};
14043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
14143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
1427c2628c3f0353f0558760c3ca442f934263ea766kmillikin@chromium.orgstatic const char* const set_conditional_mnem[] = {
1437be3c996bea370e151c9fe4ecf7f779cdc5f87adkasperl@chromium.org  /*0*/ "seto", "setno", "setc", "setnc",
1447be3c996bea370e151c9fe4ecf7f779cdc5f87adkasperl@chromium.org  /*4*/ "setz", "setnz", "setna", "seta",
1457be3c996bea370e151c9fe4ecf7f779cdc5f87adkasperl@chromium.org  /*8*/ "sets", "setns", "setpe", "setpo",
1467be3c996bea370e151c9fe4ecf7f779cdc5f87adkasperl@chromium.org  /*12*/ "setl", "setnl", "setng", "setg"
1477be3c996bea370e151c9fe4ecf7f779cdc5f87adkasperl@chromium.org};
1487be3c996bea370e151c9fe4ecf7f779cdc5f87adkasperl@chromium.org
1497be3c996bea370e151c9fe4ecf7f779cdc5f87adkasperl@chromium.org
1507c2628c3f0353f0558760c3ca442f934263ea766kmillikin@chromium.orgstatic const char* const conditional_move_mnem[] = {
1519d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com  /*0*/ "cmovo", "cmovno", "cmovc", "cmovnc",
1529d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com  /*4*/ "cmovz", "cmovnz", "cmovna", "cmova",
1539d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com  /*8*/ "cmovs", "cmovns", "cmovpe", "cmovpo",
1549d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com  /*12*/ "cmovl", "cmovnl", "cmovng", "cmovg"
1559d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com};
1569d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com
1579d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com
15843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansenenum InstructionType {
15943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  NO_INSTR,
16043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  ZERO_OPERANDS_INSTR,
16143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  TWO_OPERANDS_INSTR,
16243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  JUMP_CONDITIONAL_SHORT_INSTR,
16343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  REGISTER_INSTR,
16443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  MOVE_REG_INSTR,
16543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  CALL_JUMP_INSTR,
166c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  SHORT_IMMEDIATE_INSTR,
167c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  BYTE_IMMEDIATE_INSTR
16843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen};
16943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
17043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
17143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansenstruct InstructionDesc {
17243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  const char* mnem;
17343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  InstructionType type;
17443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  OperandOrder op_order_;
17543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen};
17643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
17743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
17843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansenclass InstructionTable {
17943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen public:
18043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  InstructionTable();
18143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  const InstructionDesc& Get(byte x) const { return instructions_[x]; }
182394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  static InstructionTable* get_instance() {
183394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com    static InstructionTable table;
184394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com    return &table;
185394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  }
18643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
18743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen private:
18843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  InstructionDesc instructions_[256];
18943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  void Clear();
19043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  void Init();
1917c2628c3f0353f0558760c3ca442f934263ea766kmillikin@chromium.org  void CopyTable(const ByteMnemonic bm[], InstructionType type);
19243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  void SetTableRange(InstructionType type,
19343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen                     byte start,
19443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen                     byte end,
19543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen                     const char* mnem);
19643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  void AddJumpConditionalShort();
19743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen};
19843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
19943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
20043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansenInstructionTable::InstructionTable() {
20143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  Clear();
20243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  Init();
20343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen}
20443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
20543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
20643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansenvoid InstructionTable::Clear() {
20743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  for (int i = 0; i < 256; i++) {
20843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    instructions_[i].mnem = "";
20943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    instructions_[i].type = NO_INSTR;
21043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    instructions_[i].op_order_ = UNSET_OP_ORDER;
21143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  }
21243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen}
21343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
21443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
21543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansenvoid InstructionTable::Init() {
21643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  CopyTable(two_operands_instr, TWO_OPERANDS_INSTR);
21743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  CopyTable(zero_operands_instr, ZERO_OPERANDS_INSTR);
21843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  CopyTable(call_jump_instr, CALL_JUMP_INSTR);
21943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  CopyTable(short_immediate_instr, SHORT_IMMEDIATE_INSTR);
220c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  CopyTable(byte_immediate_instr, BYTE_IMMEDIATE_INSTR);
22143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  AddJumpConditionalShort();
22243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  SetTableRange(REGISTER_INSTR, 0x40, 0x47, "inc");
22343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  SetTableRange(REGISTER_INSTR, 0x48, 0x4F, "dec");
22443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  SetTableRange(REGISTER_INSTR, 0x50, 0x57, "push");
22543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  SetTableRange(REGISTER_INSTR, 0x58, 0x5F, "pop");
2267be3c996bea370e151c9fe4ecf7f779cdc5f87adkasperl@chromium.org  SetTableRange(REGISTER_INSTR, 0x91, 0x97, "xchg eax,");  // 0x90 is nop.
22743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  SetTableRange(MOVE_REG_INSTR, 0xB8, 0xBF, "mov");
22843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen}
22943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
23043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
2317c2628c3f0353f0558760c3ca442f934263ea766kmillikin@chromium.orgvoid InstructionTable::CopyTable(const ByteMnemonic bm[],
2327c2628c3f0353f0558760c3ca442f934263ea766kmillikin@chromium.org                                 InstructionType type) {
23343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  for (int i = 0; bm[i].b >= 0; i++) {
23443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    InstructionDesc* id = &instructions_[bm[i].b];
23543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    id->mnem = bm[i].mnem;
23643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    id->op_order_ = bm[i].op_order_;
2373811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org    ASSERT_EQ(NO_INSTR, id->type);  // Information not already entered.
23843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    id->type = type;
23943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  }
24043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen}
24143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
24243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
24343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansenvoid InstructionTable::SetTableRange(InstructionType type,
24443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen                                     byte start,
24543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen                                     byte end,
24643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen                                     const char* mnem) {
24743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  for (byte b = start; b <= end; b++) {
24843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    InstructionDesc* id = &instructions_[b];
2493811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org    ASSERT_EQ(NO_INSTR, id->type);  // Information not already entered.
25043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    id->mnem = mnem;
25143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    id->type = type;
25243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  }
25343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen}
25443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
25543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
25643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansenvoid InstructionTable::AddJumpConditionalShort() {
25743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  for (byte b = 0x70; b <= 0x7F; b++) {
25843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    InstructionDesc* id = &instructions_[b];
2593811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org    ASSERT_EQ(NO_INSTR, id->type);  // Information not already entered.
26043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    id->mnem = jump_conditional_mnem[b & 0x0F];
26143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    id->type = JUMP_CONDITIONAL_SHORT_INSTR;
26243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  }
26343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen}
26443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
26543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
26643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// The IA32 disassembler implementation.
26743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansenclass DisassemblerIA32 {
26843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen public:
26943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  DisassemblerIA32(const NameConverter& converter,
27043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen                   bool abort_on_unimplemented = true)
27143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      : converter_(converter),
272394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com        instruction_table_(InstructionTable::get_instance()),
27343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen        tmp_buffer_pos_(0),
27443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen        abort_on_unimplemented_(abort_on_unimplemented) {
27543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    tmp_buffer_[0] = '\0';
27643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  }
27743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
27843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  virtual ~DisassemblerIA32() {}
27943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
28043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // Writes one disassembled instruction into 'buffer' (0-terminated).
28143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // Returns the length of the disassembled machine instruction in bytes.
282b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org  int InstructionDecode(v8::internal::Vector<char> buffer, byte* instruction);
28343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
28443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen private:
28543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  const NameConverter& converter_;
286394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  InstructionTable* instruction_table_;
287b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org  v8::internal::EmbeddedVector<char, 128> tmp_buffer_;
28843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  unsigned int tmp_buffer_pos_;
28943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  bool abort_on_unimplemented_;
29043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
29143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  enum {
29243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    eax = 0,
29343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    ecx = 1,
29443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    edx = 2,
29543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    ebx = 3,
29643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    esp = 4,
29743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    ebp = 5,
29843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    esi = 6,
29943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    edi = 7
30043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  };
30143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
30243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
303c4c927273ae2b690c4a015b4640a2a469c9a1a69ager@chromium.org  enum ShiftOpcodeExtension {
304c4c927273ae2b690c4a015b4640a2a469c9a1a69ager@chromium.org    kROL = 0,
305c4c927273ae2b690c4a015b4640a2a469c9a1a69ager@chromium.org    kROR = 1,
306c4c927273ae2b690c4a015b4640a2a469c9a1a69ager@chromium.org    kRCL = 2,
307c4c927273ae2b690c4a015b4640a2a469c9a1a69ager@chromium.org    kRCR = 3,
308c4c927273ae2b690c4a015b4640a2a469c9a1a69ager@chromium.org    kSHL = 4,
309c4c927273ae2b690c4a015b4640a2a469c9a1a69ager@chromium.org    KSHR = 5,
310c4c927273ae2b690c4a015b4640a2a469c9a1a69ager@chromium.org    kSAR = 7
311c4c927273ae2b690c4a015b4640a2a469c9a1a69ager@chromium.org  };
312c4c927273ae2b690c4a015b4640a2a469c9a1a69ager@chromium.org
313c4c927273ae2b690c4a015b4640a2a469c9a1a69ager@chromium.org
31443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  const char* NameOfCPURegister(int reg) const {
31543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    return converter_.NameOfCPURegister(reg);
31643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  }
31743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
31843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
3197be3c996bea370e151c9fe4ecf7f779cdc5f87adkasperl@chromium.org  const char* NameOfByteCPURegister(int reg) const {
3207be3c996bea370e151c9fe4ecf7f779cdc5f87adkasperl@chromium.org    return converter_.NameOfByteCPURegister(reg);
3217be3c996bea370e151c9fe4ecf7f779cdc5f87adkasperl@chromium.org  }
3227be3c996bea370e151c9fe4ecf7f779cdc5f87adkasperl@chromium.org
3237be3c996bea370e151c9fe4ecf7f779cdc5f87adkasperl@chromium.org
32443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  const char* NameOfXMMRegister(int reg) const {
32543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    return converter_.NameOfXMMRegister(reg);
32643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  }
32743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
32843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
32943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  const char* NameOfAddress(byte* addr) const {
33043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    return converter_.NameOfAddress(addr);
33143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  }
33243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
33343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
33443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // Disassembler helper functions.
33543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  static void get_modrm(byte data, int* mod, int* regop, int* rm) {
33643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    *mod = (data >> 6) & 3;
33743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    *regop = (data & 0x38) >> 3;
33843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    *rm = data & 7;
33943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  }
34043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
34143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
34243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  static void get_sib(byte data, int* scale, int* index, int* base) {
34343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    *scale = (data >> 6) & 3;
34443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    *index = (data >> 3) & 7;
34543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    *base = data & 7;
34643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  }
34743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
3487be3c996bea370e151c9fe4ecf7f779cdc5f87adkasperl@chromium.org  typedef const char* (DisassemblerIA32::*RegisterNameMapping)(int reg) const;
34943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
3507be3c996bea370e151c9fe4ecf7f779cdc5f87adkasperl@chromium.org  int PrintRightOperandHelper(byte* modrmp, RegisterNameMapping register_name);
35143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  int PrintRightOperand(byte* modrmp);
3527be3c996bea370e151c9fe4ecf7f779cdc5f87adkasperl@chromium.org  int PrintRightByteOperand(byte* modrmp);
353badaffc570baec00166b0ad3bdc96995751a7e13ricow@chromium.org  int PrintRightXMMOperand(byte* modrmp);
35443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  int PrintOperands(const char* mnem, OperandOrder op_order, byte* data);
35543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  int PrintImmediateOp(byte* data);
35643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  int F7Instruction(byte* data);
35743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  int D1D3C1Instruction(byte* data);
35843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  int JumpShort(byte* data);
35943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  int JumpConditional(byte* data, const char* comment);
36043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  int JumpConditionalShort(byte* data, const char* comment);
3617be3c996bea370e151c9fe4ecf7f779cdc5f87adkasperl@chromium.org  int SetCC(byte* data);
3629d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com  int CMov(byte* data);
36343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  int FPUInstruction(byte* data);
3643811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org  int MemoryFPUInstruction(int escape_opcode, int regop, byte* modrm_start);
3653811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org  int RegisterFPUInstruction(int escape_opcode, byte modrm_byte);
36643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  void AppendToBuffer(const char* format, ...);
36743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
36843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
36943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  void UnimplementedInstruction() {
37043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    if (abort_on_unimplemented_) {
37143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      UNIMPLEMENTED();
37243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    } else {
37343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      AppendToBuffer("'Unimplemented Instruction'");
37443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    }
37543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  }
37643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen};
37743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
37843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
37943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansenvoid DisassemblerIA32::AppendToBuffer(const char* format, ...) {
380b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org  v8::internal::Vector<char> buf = tmp_buffer_ + tmp_buffer_pos_;
38143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  va_list args;
38243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  va_start(args, format);
383b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org  int result = v8::internal::OS::VSNPrintF(buf, format, args);
38443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  va_end(args);
38543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  tmp_buffer_pos_ += result;
38643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen}
38743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
3887be3c996bea370e151c9fe4ecf7f779cdc5f87adkasperl@chromium.orgint DisassemblerIA32::PrintRightOperandHelper(
3897be3c996bea370e151c9fe4ecf7f779cdc5f87adkasperl@chromium.org    byte* modrmp,
390badaffc570baec00166b0ad3bdc96995751a7e13ricow@chromium.org    RegisterNameMapping direct_register_name) {
39143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  int mod, regop, rm;
39243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  get_modrm(*modrmp, &mod, &regop, &rm);
393badaffc570baec00166b0ad3bdc96995751a7e13ricow@chromium.org  RegisterNameMapping register_name = (mod == 3) ? direct_register_name :
394badaffc570baec00166b0ad3bdc96995751a7e13ricow@chromium.org      &DisassemblerIA32::NameOfCPURegister;
39543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  switch (mod) {
39643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    case 0:
39743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      if (rm == ebp) {
39843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen        int32_t disp = *reinterpret_cast<int32_t*>(modrmp+1);
39943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen        AppendToBuffer("[0x%x]", disp);
40043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen        return 5;
40143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      } else if (rm == esp) {
40243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen        byte sib = *(modrmp + 1);
40343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen        int scale, index, base;
40443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen        get_sib(sib, &scale, &index, &base);
40543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen        if (index == esp && base == esp && scale == 0 /*times_1*/) {
4067be3c996bea370e151c9fe4ecf7f779cdc5f87adkasperl@chromium.org          AppendToBuffer("[%s]", (this->*register_name)(rm));
40743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen          return 2;
40843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen        } else if (base == ebp) {
40943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen          int32_t disp = *reinterpret_cast<int32_t*>(modrmp + 2);
41043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen          AppendToBuffer("[%s*%d+0x%x]",
4117be3c996bea370e151c9fe4ecf7f779cdc5f87adkasperl@chromium.org                         (this->*register_name)(index),
41243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen                         1 << scale,
41343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen                         disp);
41443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen          return 6;
41543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen        } else if (index != esp && base != ebp) {
41643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen          // [base+index*scale]
41743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen          AppendToBuffer("[%s+%s*%d]",
4187be3c996bea370e151c9fe4ecf7f779cdc5f87adkasperl@chromium.org                         (this->*register_name)(base),
4197be3c996bea370e151c9fe4ecf7f779cdc5f87adkasperl@chromium.org                         (this->*register_name)(index),
42043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen                         1 << scale);
42143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen          return 2;
42243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen        } else {
42343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen          UnimplementedInstruction();
42443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen          return 1;
42543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen        }
42643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      } else {
4277be3c996bea370e151c9fe4ecf7f779cdc5f87adkasperl@chromium.org        AppendToBuffer("[%s]", (this->*register_name)(rm));
42843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen        return 1;
42943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      }
43043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      break;
43143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    case 1:  // fall through
43243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    case 2:
43343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      if (rm == esp) {
43443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen        byte sib = *(modrmp + 1);
43543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen        int scale, index, base;
43643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen        get_sib(sib, &scale, &index, &base);
43743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen        int disp =
43843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen            mod == 2 ? *reinterpret_cast<int32_t*>(modrmp + 2) : *(modrmp + 2);
43943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen        if (index == base && index == rm /*esp*/ && scale == 0 /*times_1*/) {
4407be3c996bea370e151c9fe4ecf7f779cdc5f87adkasperl@chromium.org          AppendToBuffer("[%s+0x%x]", (this->*register_name)(rm), disp);
44143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen        } else {
44243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen          AppendToBuffer("[%s+%s*%d+0x%x]",
4437be3c996bea370e151c9fe4ecf7f779cdc5f87adkasperl@chromium.org                         (this->*register_name)(base),
4447be3c996bea370e151c9fe4ecf7f779cdc5f87adkasperl@chromium.org                         (this->*register_name)(index),
44543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen                         1 << scale,
44643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen                         disp);
44743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen        }
44843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen        return mod == 2 ? 6 : 3;
44943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      } else {
45043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen        // No sib.
45143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen        int disp =
45243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen            mod == 2 ? *reinterpret_cast<int32_t*>(modrmp + 1) : *(modrmp + 1);
4537be3c996bea370e151c9fe4ecf7f779cdc5f87adkasperl@chromium.org        AppendToBuffer("[%s+0x%x]", (this->*register_name)(rm), disp);
45443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen        return mod == 2 ? 5 : 2;
45543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      }
45643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      break;
45743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    case 3:
4587be3c996bea370e151c9fe4ecf7f779cdc5f87adkasperl@chromium.org      AppendToBuffer("%s", (this->*register_name)(rm));
45943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      return 1;
46043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    default:
46143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      UnimplementedInstruction();
46243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      return 1;
46343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  }
46443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  UNREACHABLE();
46543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen}
46643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
46743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
4687be3c996bea370e151c9fe4ecf7f779cdc5f87adkasperl@chromium.orgint DisassemblerIA32::PrintRightOperand(byte* modrmp) {
4697be3c996bea370e151c9fe4ecf7f779cdc5f87adkasperl@chromium.org  return PrintRightOperandHelper(modrmp, &DisassemblerIA32::NameOfCPURegister);
4707be3c996bea370e151c9fe4ecf7f779cdc5f87adkasperl@chromium.org}
4717be3c996bea370e151c9fe4ecf7f779cdc5f87adkasperl@chromium.org
4727be3c996bea370e151c9fe4ecf7f779cdc5f87adkasperl@chromium.org
4737be3c996bea370e151c9fe4ecf7f779cdc5f87adkasperl@chromium.orgint DisassemblerIA32::PrintRightByteOperand(byte* modrmp) {
4747be3c996bea370e151c9fe4ecf7f779cdc5f87adkasperl@chromium.org  return PrintRightOperandHelper(modrmp,
4757be3c996bea370e151c9fe4ecf7f779cdc5f87adkasperl@chromium.org                                 &DisassemblerIA32::NameOfByteCPURegister);
4767be3c996bea370e151c9fe4ecf7f779cdc5f87adkasperl@chromium.org}
4777be3c996bea370e151c9fe4ecf7f779cdc5f87adkasperl@chromium.org
4787be3c996bea370e151c9fe4ecf7f779cdc5f87adkasperl@chromium.org
479badaffc570baec00166b0ad3bdc96995751a7e13ricow@chromium.orgint DisassemblerIA32::PrintRightXMMOperand(byte* modrmp) {
480badaffc570baec00166b0ad3bdc96995751a7e13ricow@chromium.org  return PrintRightOperandHelper(modrmp,
481badaffc570baec00166b0ad3bdc96995751a7e13ricow@chromium.org                                 &DisassemblerIA32::NameOfXMMRegister);
482badaffc570baec00166b0ad3bdc96995751a7e13ricow@chromium.org}
483badaffc570baec00166b0ad3bdc96995751a7e13ricow@chromium.org
484badaffc570baec00166b0ad3bdc96995751a7e13ricow@chromium.org
48543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// Returns number of bytes used including the current *data.
48643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// Writes instruction's mnemonic, left and right operands to 'tmp_buffer_'.
48743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansenint DisassemblerIA32::PrintOperands(const char* mnem,
48843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen                                    OperandOrder op_order,
48943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen                                    byte* data) {
49043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  byte modrm = *data;
49143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  int mod, regop, rm;
49243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  get_modrm(modrm, &mod, &regop, &rm);
49343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  int advance = 0;
49443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  switch (op_order) {
49543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    case REG_OPER_OP_ORDER: {
49643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      AppendToBuffer("%s %s,", mnem, NameOfCPURegister(regop));
49743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      advance = PrintRightOperand(data);
49843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      break;
49943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    }
50043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    case OPER_REG_OP_ORDER: {
50143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      AppendToBuffer("%s ", mnem);
50243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      advance = PrintRightOperand(data);
50343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      AppendToBuffer(",%s", NameOfCPURegister(regop));
50443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      break;
50543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    }
50643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    default:
50743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      UNREACHABLE();
50843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      break;
50943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  }
51043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  return advance;
51143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen}
51243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
51343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
51443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// Returns number of bytes used by machine instruction, including *data byte.
51543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// Writes immediate instructions to 'tmp_buffer_'.
51643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansenint DisassemblerIA32::PrintImmediateOp(byte* data) {
51743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  bool sign_extension_bit = (*data & 0x02) != 0;
51843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  byte modrm = *(data+1);
51943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  int mod, regop, rm;
52043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  get_modrm(modrm, &mod, &regop, &rm);
52143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  const char* mnem = "Imm???";
52243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  switch (regop) {
52343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    case 0: mnem = "add"; break;
52443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    case 1: mnem = "or"; break;
52543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    case 2: mnem = "adc"; break;
52643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    case 4: mnem = "and"; break;
52743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    case 5: mnem = "sub"; break;
52843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    case 6: mnem = "xor"; break;
52943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    case 7: mnem = "cmp"; break;
53043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    default: UnimplementedInstruction();
53143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  }
53243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  AppendToBuffer("%s ", mnem);
53343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  int count = PrintRightOperand(data+1);
53443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  if (sign_extension_bit) {
53543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    AppendToBuffer(",0x%x", *(data + 1 + count));
53643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    return 1 + count + 1 /*int8*/;
53743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  } else {
53843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    AppendToBuffer(",0x%x", *reinterpret_cast<int32_t*>(data + 1 + count));
53943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    return 1 + count + 4 /*int32_t*/;
54043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  }
54143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen}
54243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
54343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
54443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// Returns number of bytes used, including *data.
54543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansenint DisassemblerIA32::F7Instruction(byte* data) {
5463811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org  ASSERT_EQ(0xF7, *data);
54743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  byte modrm = *(data+1);
54843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  int mod, regop, rm;
54943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  get_modrm(modrm, &mod, &regop, &rm);
55043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  if (mod == 3 && regop != 0) {
55143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    const char* mnem = NULL;
55243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    switch (regop) {
55343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      case 2: mnem = "not"; break;
55443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      case 3: mnem = "neg"; break;
55543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      case 4: mnem = "mul"; break;
556d2899aa30a5af82205029034f7a491d49c48fc68yangguo@chromium.org      case 5: mnem = "imul"; break;
55743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      case 7: mnem = "idiv"; break;
55843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      default: UnimplementedInstruction();
55943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    }
56043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    AppendToBuffer("%s %s", mnem, NameOfCPURegister(rm));
56143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    return 2;
56243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  } else if (mod == 3 && regop == eax) {
56343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    int32_t imm = *reinterpret_cast<int32_t*>(data+2);
56443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    AppendToBuffer("test %s,0x%x", NameOfCPURegister(rm), imm);
56543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    return 6;
56643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  } else if (regop == eax) {
56743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    AppendToBuffer("test ");
56843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    int count = PrintRightOperand(data+1);
56943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    int32_t imm = *reinterpret_cast<int32_t*>(data+1+count);
57043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    AppendToBuffer(",0x%x", imm);
57143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    return 1+count+4 /*int32_t*/;
57243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  } else {
57343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    UnimplementedInstruction();
57443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    return 2;
57543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  }
57643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen}
57743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
578e0e1b0d3e70c933d36ed381d511e9fda39f2a751mstarzinger@chromium.org
57943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansenint DisassemblerIA32::D1D3C1Instruction(byte* data) {
58043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  byte op = *data;
5813811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org  ASSERT(op == 0xD1 || op == 0xD3 || op == 0xC1);
58243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  byte modrm = *(data+1);
58343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  int mod, regop, rm;
58443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  get_modrm(modrm, &mod, &regop, &rm);
58543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  int imm8 = -1;
58643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  int num_bytes = 2;
58743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  if (mod == 3) {
58843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    const char* mnem = NULL;
589c4c927273ae2b690c4a015b4640a2a469c9a1a69ager@chromium.org    switch (regop) {
590c4c927273ae2b690c4a015b4640a2a469c9a1a69ager@chromium.org      case kROL: mnem = "rol"; break;
591c4c927273ae2b690c4a015b4640a2a469c9a1a69ager@chromium.org      case kROR: mnem = "ror"; break;
592c4c927273ae2b690c4a015b4640a2a469c9a1a69ager@chromium.org      case kRCL: mnem = "rcl"; break;
593ea4f62e1df22417fc8dc2c2425485dca98b13d07ager@chromium.org      case kRCR: mnem = "rcr"; break;
594c4c927273ae2b690c4a015b4640a2a469c9a1a69ager@chromium.org      case kSHL: mnem = "shl"; break;
595c4c927273ae2b690c4a015b4640a2a469c9a1a69ager@chromium.org      case KSHR: mnem = "shr"; break;
596c4c927273ae2b690c4a015b4640a2a469c9a1a69ager@chromium.org      case kSAR: mnem = "sar"; break;
597c4c927273ae2b690c4a015b4640a2a469c9a1a69ager@chromium.org      default: UnimplementedInstruction();
598c4c927273ae2b690c4a015b4640a2a469c9a1a69ager@chromium.org    }
59943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    if (op == 0xD1) {
60043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      imm8 = 1;
60143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    } else if (op == 0xC1) {
60243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      imm8 = *(data+2);
60343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      num_bytes = 3;
60443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    } else if (op == 0xD3) {
605c4c927273ae2b690c4a015b4640a2a469c9a1a69ager@chromium.org      // Shift/rotate by cl.
60643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    }
6073811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org    ASSERT_NE(NULL, mnem);
60843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    AppendToBuffer("%s %s,", mnem, NameOfCPURegister(rm));
60943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    if (imm8 > 0) {
61043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      AppendToBuffer("%d", imm8);
61143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    } else {
61243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      AppendToBuffer("cl");
61343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    }
61443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  } else {
61543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    UnimplementedInstruction();
61643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  }
61743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  return num_bytes;
61843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen}
61943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
62043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
62143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// Returns number of bytes used, including *data.
62243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansenint DisassemblerIA32::JumpShort(byte* data) {
6233811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org  ASSERT_EQ(0xEB, *data);
62443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  byte b = *(data+1);
62543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  byte* dest = data + static_cast<int8_t>(b) + 2;
62643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  AppendToBuffer("jmp %s", NameOfAddress(dest));
62743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  return 2;
62843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen}
62943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
63043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
63143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// Returns number of bytes used, including *data.
63243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansenint DisassemblerIA32::JumpConditional(byte* data, const char* comment) {
6333811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org  ASSERT_EQ(0x0F, *data);
63443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  byte cond = *(data+1) & 0x0F;
63543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  byte* dest = data + *reinterpret_cast<int32_t*>(data+2) + 6;
63643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  const char* mnem = jump_conditional_mnem[cond];
63743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  AppendToBuffer("%s %s", mnem, NameOfAddress(dest));
63843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  if (comment != NULL) {
63943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    AppendToBuffer(", %s", comment);
64043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  }
64143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  return 6;  // includes 0x0F
64243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen}
64343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
64443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
64543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// Returns number of bytes used, including *data.
64643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansenint DisassemblerIA32::JumpConditionalShort(byte* data, const char* comment) {
64743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  byte cond = *data & 0x0F;
64843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  byte b = *(data+1);
64943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  byte* dest = data + static_cast<int8_t>(b) + 2;
65043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  const char* mnem = jump_conditional_mnem[cond];
65143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  AppendToBuffer("%s %s", mnem, NameOfAddress(dest));
65243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  if (comment != NULL) {
65343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    AppendToBuffer(", %s", comment);
65443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  }
65543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  return 2;
65643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen}
65743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
65843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
65943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// Returns number of bytes used, including *data.
6607be3c996bea370e151c9fe4ecf7f779cdc5f87adkasperl@chromium.orgint DisassemblerIA32::SetCC(byte* data) {
6613811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org  ASSERT_EQ(0x0F, *data);
6627be3c996bea370e151c9fe4ecf7f779cdc5f87adkasperl@chromium.org  byte cond = *(data+1) & 0x0F;
6637be3c996bea370e151c9fe4ecf7f779cdc5f87adkasperl@chromium.org  const char* mnem = set_conditional_mnem[cond];
6647be3c996bea370e151c9fe4ecf7f779cdc5f87adkasperl@chromium.org  AppendToBuffer("%s ", mnem);
6657be3c996bea370e151c9fe4ecf7f779cdc5f87adkasperl@chromium.org  PrintRightByteOperand(data+2);
6663811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org  return 3;  // Includes 0x0F.
6677be3c996bea370e151c9fe4ecf7f779cdc5f87adkasperl@chromium.org}
6687be3c996bea370e151c9fe4ecf7f779cdc5f87adkasperl@chromium.org
6697be3c996bea370e151c9fe4ecf7f779cdc5f87adkasperl@chromium.org
6707be3c996bea370e151c9fe4ecf7f779cdc5f87adkasperl@chromium.org// Returns number of bytes used, including *data.
6719d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.comint DisassemblerIA32::CMov(byte* data) {
6723811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org  ASSERT_EQ(0x0F, *data);
6739d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com  byte cond = *(data + 1) & 0x0F;
6749d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com  const char* mnem = conditional_move_mnem[cond];
6759d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com  int op_size = PrintOperands(mnem, REG_OPER_OP_ORDER, data + 2);
6769d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com  return 2 + op_size;  // includes 0x0F
6779d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com}
6789d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com
6799d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com
6809d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com// Returns number of bytes used, including *data.
68143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansenint DisassemblerIA32::FPUInstruction(byte* data) {
6823811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org  byte escape_opcode = *data;
6833811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org  ASSERT_EQ(0xD8, escape_opcode & 0xF8);
6843811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org  byte modrm_byte = *(data+1);
6853811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org
6863811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org  if (modrm_byte >= 0xC0) {
6873811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org    return RegisterFPUInstruction(escape_opcode, modrm_byte);
6883811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org  } else {
6893811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org    return MemoryFPUInstruction(escape_opcode, modrm_byte, data+1);
6903811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org  }
6913811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org}
6923811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org
6933811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.orgint DisassemblerIA32::MemoryFPUInstruction(int escape_opcode,
6943811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org                                           int modrm_byte,
6953811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org                                           byte* modrm_start) {
6963811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org  const char* mnem = "?";
6973811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org  int regop = (modrm_byte >> 3) & 0x7;  // reg/op field of modrm byte.
6983811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org  switch (escape_opcode) {
6993811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org    case 0xD9: switch (regop) {
7003811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org        case 0: mnem = "fld_s"; break;
7013811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org        case 3: mnem = "fstp_s"; break;
7023811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org        case 7: mnem = "fstcw"; break;
70343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen        default: UnimplementedInstruction();
70443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      }
7053811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org      break;
7063811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org
7073811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org    case 0xDB: switch (regop) {
7083811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org        case 0: mnem = "fild_s"; break;
7093811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org        case 1: mnem = "fisttp_s"; break;
7103811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org        case 2: mnem = "fist_s"; break;
7113811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org        case 3: mnem = "fistp_s"; break;
71243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen        default: UnimplementedInstruction();
71343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      }
7143811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org      break;
7153811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org
7163811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org    case 0xDD: switch (regop) {
7173811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org        case 0: mnem = "fld_d"; break;
718c20610af4f0ca150977ca140a1174f98ee46f5aafschneider@chromium.org        case 1: mnem = "fisttp_d"; break;
719c20610af4f0ca150977ca140a1174f98ee46f5aafschneider@chromium.org        case 2: mnem = "fst_d"; break;
7203811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org        case 3: mnem = "fstp_d"; break;
7213811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org        default: UnimplementedInstruction();
7223811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org      }
7233811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org      break;
7243811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org
7253811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org    case 0xDF: switch (regop) {
7263811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org        case 5: mnem = "fild_d"; break;
7273811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org        case 7: mnem = "fistp_d"; break;
7283811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org        default: UnimplementedInstruction();
7293811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org      }
7303811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org      break;
7313811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org
7323811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org    default: UnimplementedInstruction();
7333811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org  }
7343811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org  AppendToBuffer("%s ", mnem);
7353811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org  int count = PrintRightOperand(modrm_start);
7363811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org  return count + 1;
7373811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org}
7383811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org
7393811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.orgint DisassemblerIA32::RegisterFPUInstruction(int escape_opcode,
7403811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org                                             byte modrm_byte) {
7413811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org  bool has_register = false;  // Is the FPU register encoded in modrm_byte?
7423811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org  const char* mnem = "?";
7433811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org
7443811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org  switch (escape_opcode) {
7453811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org    case 0xD8:
7463811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org      UnimplementedInstruction();
7473811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org      break;
7483811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org
7493811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org    case 0xD9:
7503811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org      switch (modrm_byte & 0xF8) {
7514a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org        case 0xC0:
7524a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org          mnem = "fld";
7534a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org          has_register = true;
7544a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org          break;
7553811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org        case 0xC8:
7563811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org          mnem = "fxch";
7573811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org          has_register = true;
7583811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org          break;
7593811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org        default:
7603811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org          switch (modrm_byte) {
7613811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org            case 0xE0: mnem = "fchs"; break;
7623811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org            case 0xE1: mnem = "fabs"; break;
7633811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org            case 0xE4: mnem = "ftst"; break;
7643811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org            case 0xE8: mnem = "fld1"; break;
765ce5e87bd905d592a8bd612b3dedf7a994177c13aager@chromium.org            case 0xEB: mnem = "fldpi"; break;
766a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org            case 0xED: mnem = "fldln2"; break;
7673811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org            case 0xEE: mnem = "fldz"; break;
76864e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org            case 0xF0: mnem = "f2xm1"; break;
769a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org            case 0xF1: mnem = "fyl2x"; break;
7703811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org            case 0xF5: mnem = "fprem1"; break;
7713811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org            case 0xF7: mnem = "fincstp"; break;
7723811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org            case 0xF8: mnem = "fprem"; break;
77364e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org            case 0xFC: mnem = "frndint"; break;
77464e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org            case 0xFD: mnem = "fscale"; break;
7753811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org            case 0xFE: mnem = "fsin"; break;
7763811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org            case 0xFF: mnem = "fcos"; break;
7773811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org            default: UnimplementedInstruction();
7783811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org          }
7793811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org      }
7803811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org      break;
7813811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org
7823811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org    case 0xDA:
7833811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org      if (modrm_byte == 0xE9) {
7843811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org        mnem = "fucompp";
7853811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org      } else {
7863811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org        UnimplementedInstruction();
7873811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org      }
7883811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org      break;
7893811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org
7903811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org    case 0xDB:
7913811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org      if ((modrm_byte & 0xF8) == 0xE8) {
7923811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org        mnem = "fucomi";
7933811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org        has_register = true;
7943811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org      } else if (modrm_byte  == 0xE2) {
7953811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org        mnem = "fclex";
79664e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org      } else if (modrm_byte == 0xE3) {
79764e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org        mnem = "fninit";
7983811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org      } else {
7993811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org        UnimplementedInstruction();
8003811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org      }
8013811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org      break;
8023811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org
8033811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org    case 0xDC:
8043811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org      has_register = true;
8053811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org      switch (modrm_byte & 0xF8) {
8063811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org        case 0xC0: mnem = "fadd"; break;
8073811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org        case 0xE8: mnem = "fsub"; break;
8083811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org        case 0xC8: mnem = "fmul"; break;
8093811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org        case 0xF8: mnem = "fdiv"; break;
8103811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org        default: UnimplementedInstruction();
8113811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org      }
8123811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org      break;
8133811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org
8143811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org    case 0xDD:
8153811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org      has_register = true;
8163811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org      switch (modrm_byte & 0xF8) {
8173811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org        case 0xC0: mnem = "ffree"; break;
8183811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org        case 0xD8: mnem = "fstp"; break;
8193811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org        default: UnimplementedInstruction();
8203811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org      }
8213811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org      break;
8223811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org
8233811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org    case 0xDE:
8243811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org      if (modrm_byte  == 0xD9) {
8253811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org        mnem = "fcompp";
8263811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org      } else {
8273811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org        has_register = true;
8283811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org        switch (modrm_byte & 0xF8) {
8293811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org          case 0xC0: mnem = "faddp"; break;
8303811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org          case 0xE8: mnem = "fsubp"; break;
8313811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org          case 0xC8: mnem = "fmulp"; break;
8323811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org          case 0xF8: mnem = "fdivp"; break;
8333811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org          default: UnimplementedInstruction();
8343811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org        }
8353811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org      }
8363811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org      break;
8373811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org
8383811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org    case 0xDF:
8393811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org      if (modrm_byte == 0xE0) {
8403811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org        mnem = "fnstsw_ax";
8413811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org      } else if ((modrm_byte & 0xF8) == 0xE8) {
8423811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org        mnem = "fucomip";
8433811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org        has_register = true;
8443811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org      }
8453811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org      break;
8463811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org
8473811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org    default: UnimplementedInstruction();
8483811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org  }
8493811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org
8503811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org  if (has_register) {
8513811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org    AppendToBuffer("%s st%d", mnem, modrm_byte & 0x7);
8523811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org  } else {
8537276f14ca716596e0a0d17539516370c1f453847kasper.lund    AppendToBuffer("%s", mnem);
85443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  }
85543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  return 2;
85643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen}
85743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
85843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
85943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// Mnemonics for instructions 0xF0 byte.
86043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// Returns NULL if the instruction is not handled here.
86143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansenstatic const char* F0Mnem(byte f0byte) {
86243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  switch (f0byte) {
8631af7e1b5f676e5556c041fe09a5c4f5a906f27a0lrn@chromium.org    case 0x18: return "prefetch";
86443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    case 0xA2: return "cpuid";
86543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    case 0x31: return "rdtsc";
86643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    case 0xBE: return "movsx_b";
86743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    case 0xBF: return "movsx_w";
86843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    case 0xB6: return "movzx_b";
86943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    case 0xB7: return "movzx_w";
87043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    case 0xAF: return "imul";
87143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    case 0xA5: return "shld";
87243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    case 0xAD: return "shrd";
8731f34ad3eadf9b0e6b8ed415817d276f54dd6d06bdanno@chromium.org    case 0xAC: return "shrd";  // 3-operand version.
87443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    case 0xAB: return "bts";
87543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    default: return NULL;
87643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  }
87743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen}
87843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
87943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
8806f10e41fef1524c70846d970268de222e41c594cager@chromium.org// Disassembled instruction '*instr' and writes it into 'out_buffer'.
881b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.orgint DisassemblerIA32::InstructionDecode(v8::internal::Vector<char> out_buffer,
88243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen                                        byte* instr) {
88343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  tmp_buffer_pos_ = 0;  // starting to write as position 0
88443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  byte* data = instr;
88543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // Check for hints.
88643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  const char* branch_hint = NULL;
8876f10e41fef1524c70846d970268de222e41c594cager@chromium.org  // We use these two prefixes only with branch prediction
88843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  if (*data == 0x3E /*ds*/) {
88943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    branch_hint = "predicted taken";
89043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    data++;
89143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  } else if (*data == 0x2E /*cs*/) {
89243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    branch_hint = "predicted not taken";
89343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    data++;
89443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  }
89543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  bool processed = true;  // Will be set to false if the current instruction
89643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen                          // is not in 'instructions' table.
897394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  const InstructionDesc& idesc = instruction_table_->Get(*data);
89843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  switch (idesc.type) {
89943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    case ZERO_OPERANDS_INSTR:
90043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      AppendToBuffer(idesc.mnem);
90143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      data++;
90243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      break;
90343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
90443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    case TWO_OPERANDS_INSTR:
90543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      data++;
90643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      data += PrintOperands(idesc.mnem, idesc.op_order_, data);
90743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      break;
90843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
90943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    case JUMP_CONDITIONAL_SHORT_INSTR:
91043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      data += JumpConditionalShort(data, branch_hint);
91143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      break;
91243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
91343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    case REGISTER_INSTR:
91443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      AppendToBuffer("%s %s", idesc.mnem, NameOfCPURegister(*data & 0x07));
91543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      data++;
91643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      break;
91743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
91843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    case MOVE_REG_INSTR: {
91943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      byte* addr = reinterpret_cast<byte*>(*reinterpret_cast<int32_t*>(data+1));
92043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      AppendToBuffer("mov %s,%s",
92143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen                     NameOfCPURegister(*data & 0x07),
92243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen                     NameOfAddress(addr));
92343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      data += 5;
92443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      break;
92543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    }
92643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
92743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    case CALL_JUMP_INSTR: {
92843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      byte* addr = data + *reinterpret_cast<int32_t*>(data+1) + 5;
92943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      AppendToBuffer("%s %s", idesc.mnem, NameOfAddress(addr));
93043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      data += 5;
93143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      break;
93243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    }
93343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
93443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    case SHORT_IMMEDIATE_INSTR: {
93543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      byte* addr = reinterpret_cast<byte*>(*reinterpret_cast<int32_t*>(data+1));
93643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      AppendToBuffer("%s eax, %s", idesc.mnem, NameOfAddress(addr));
93743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      data += 5;
93843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      break;
93943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    }
94043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
941c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    case BYTE_IMMEDIATE_INSTR: {
942c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      AppendToBuffer("%s al, 0x%x", idesc.mnem, data[1]);
943c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      data += 2;
944c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      break;
945c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    }
946c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
94743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    case NO_INSTR:
94843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      processed = false;
94943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      break;
95043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
95143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    default:
95243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      UNIMPLEMENTED();  // This type is not implemented.
95343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  }
95443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  //----------------------------
95543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  if (!processed) {
95643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    switch (*data) {
95743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      case 0xC2:
95843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen        AppendToBuffer("ret 0x%x", *reinterpret_cast<uint16_t*>(data+1));
95943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen        data += 3;
96043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen        break;
96143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
96243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      case 0x69:  // fall through
96343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      case 0x6B:
96443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen        { int mod, regop, rm;
96543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen          get_modrm(*(data+1), &mod, &regop, &rm);
96643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen          int32_t imm =
96743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen              *data == 0x6B ? *(data+2) : *reinterpret_cast<int32_t*>(data+2);
96843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen          AppendToBuffer("imul %s,%s,0x%x",
96943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen                         NameOfCPURegister(regop),
97043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen                         NameOfCPURegister(rm),
97143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen                         imm);
97243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen          data += 2 + (*data == 0x6B ? 1 : 4);
97343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen        }
97443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen        break;
97543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
97643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      case 0xF6:
9772356e6fbe66ac3aa027b61cb43a3c3619b3c3a5evegorov@chromium.org        { data++;
9782356e6fbe66ac3aa027b61cb43a3c3619b3c3a5evegorov@chromium.org          int mod, regop, rm;
9792356e6fbe66ac3aa027b61cb43a3c3619b3c3a5evegorov@chromium.org          get_modrm(*data, &mod, &regop, &rm);
9802356e6fbe66ac3aa027b61cb43a3c3619b3c3a5evegorov@chromium.org          if (regop == eax) {
9812356e6fbe66ac3aa027b61cb43a3c3619b3c3a5evegorov@chromium.org            AppendToBuffer("test_b ");
982badaffc570baec00166b0ad3bdc96995751a7e13ricow@chromium.org            data += PrintRightByteOperand(data);
9832356e6fbe66ac3aa027b61cb43a3c3619b3c3a5evegorov@chromium.org            int32_t imm = *data;
9842356e6fbe66ac3aa027b61cb43a3c3619b3c3a5evegorov@chromium.org            AppendToBuffer(",0x%x", imm);
9852356e6fbe66ac3aa027b61cb43a3c3619b3c3a5evegorov@chromium.org            data++;
98643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen          } else {
98743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen            UnimplementedInstruction();
98843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen          }
98943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen        }
99043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen        break;
99143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
99243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      case 0x81:  // fall through
99343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      case 0x83:  // 0x81 with sign extension bit set
99443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen        data += PrintImmediateOp(data);
99543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen        break;
99643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
99743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      case 0x0F:
99864e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org        { byte f0byte = data[1];
99943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen          const char* f0mnem = F0Mnem(f0byte);
10001af7e1b5f676e5556c041fe09a5c4f5a906f27a0lrn@chromium.org          if (f0byte == 0x18) {
10011af7e1b5f676e5556c041fe09a5c4f5a906f27a0lrn@chromium.org            int mod, regop, rm;
10021af7e1b5f676e5556c041fe09a5c4f5a906f27a0lrn@chromium.org            get_modrm(*data, &mod, &regop, &rm);
10031af7e1b5f676e5556c041fe09a5c4f5a906f27a0lrn@chromium.org            const char* suffix[] = {"nta", "1", "2", "3"};
10041af7e1b5f676e5556c041fe09a5c4f5a906f27a0lrn@chromium.org            AppendToBuffer("%s%s ", f0mnem, suffix[regop & 0x03]);
10051af7e1b5f676e5556c041fe09a5c4f5a906f27a0lrn@chromium.org            data += PrintRightOperand(data);
100664e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org          } else if (f0byte == 0x1F && data[2] == 0) {
100764e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org            AppendToBuffer("nop");  // 3 byte nop.
100864e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org            data += 3;
100964e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org          } else if (f0byte == 0x1F && data[2] == 0x40 && data[3] == 0) {
101064e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org            AppendToBuffer("nop");  // 4 byte nop.
101164e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org            data += 4;
101264e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org          } else if (f0byte == 0x1F && data[2] == 0x44 && data[3] == 0 &&
101364e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org                     data[4] == 0) {
101464e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org            AppendToBuffer("nop");  // 5 byte nop.
101564e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org            data += 5;
101664e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org          } else if (f0byte == 0x1F && data[2] == 0x80 && data[3] == 0 &&
101764e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org                     data[4] == 0 && data[5] == 0 && data[6] == 0) {
101864e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org            AppendToBuffer("nop");  // 7 byte nop.
101964e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org            data += 7;
102064e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org          } else if (f0byte == 0x1F && data[2] == 0x84 && data[3] == 0 &&
102164e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org                     data[4] == 0 && data[5] == 0 && data[6] == 0 &&
102264e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org                     data[7] == 0) {
102364e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org            AppendToBuffer("nop");  // 8 byte nop.
102464e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org            data += 8;
10251af7e1b5f676e5556c041fe09a5c4f5a906f27a0lrn@chromium.org          } else if (f0byte == 0xA2 || f0byte == 0x31) {
102643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen            AppendToBuffer("%s", f0mnem);
102743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen            data += 2;
1028c20610af4f0ca150977ca140a1174f98ee46f5aafschneider@chromium.org          } else if (f0byte == 0x28) {
1029c20610af4f0ca150977ca140a1174f98ee46f5aafschneider@chromium.org            data += 2;
1030c20610af4f0ca150977ca140a1174f98ee46f5aafschneider@chromium.org            int mod, regop, rm;
1031c20610af4f0ca150977ca140a1174f98ee46f5aafschneider@chromium.org            get_modrm(*data, &mod, &regop, &rm);
1032c20610af4f0ca150977ca140a1174f98ee46f5aafschneider@chromium.org            AppendToBuffer("movaps %s,%s",
1033c20610af4f0ca150977ca140a1174f98ee46f5aafschneider@chromium.org                           NameOfXMMRegister(regop),
1034c20610af4f0ca150977ca140a1174f98ee46f5aafschneider@chromium.org                           NameOfXMMRegister(rm));
1035c20610af4f0ca150977ca140a1174f98ee46f5aafschneider@chromium.org            data++;
1036fb144a0716afe7ab8bf245f2391a9e53b3db3c89fschneider@chromium.org          } else if (f0byte == 0x57) {
1037fb144a0716afe7ab8bf245f2391a9e53b3db3c89fschneider@chromium.org            data += 2;
1038fb144a0716afe7ab8bf245f2391a9e53b3db3c89fschneider@chromium.org            int mod, regop, rm;
1039fb144a0716afe7ab8bf245f2391a9e53b3db3c89fschneider@chromium.org            get_modrm(*data, &mod, &regop, &rm);
1040fb144a0716afe7ab8bf245f2391a9e53b3db3c89fschneider@chromium.org            AppendToBuffer("xorps %s,%s",
1041fb144a0716afe7ab8bf245f2391a9e53b3db3c89fschneider@chromium.org                           NameOfXMMRegister(regop),
1042fb144a0716afe7ab8bf245f2391a9e53b3db3c89fschneider@chromium.org                           NameOfXMMRegister(rm));
1043fb144a0716afe7ab8bf245f2391a9e53b3db3c89fschneider@chromium.org            data++;
10444121f23c2a08f8ef03858df1477b81a0450b94a0ulan@chromium.org          } else if (f0byte == 0x50) {
10454121f23c2a08f8ef03858df1477b81a0450b94a0ulan@chromium.org            data += 2;
10464121f23c2a08f8ef03858df1477b81a0450b94a0ulan@chromium.org            int mod, regop, rm;
10474121f23c2a08f8ef03858df1477b81a0450b94a0ulan@chromium.org            get_modrm(*data, &mod, &regop, &rm);
10484121f23c2a08f8ef03858df1477b81a0450b94a0ulan@chromium.org            AppendToBuffer("movmskps %s,%s",
10494121f23c2a08f8ef03858df1477b81a0450b94a0ulan@chromium.org                           NameOfCPURegister(regop),
10504121f23c2a08f8ef03858df1477b81a0450b94a0ulan@chromium.org                           NameOfXMMRegister(rm));
10514121f23c2a08f8ef03858df1477b81a0450b94a0ulan@chromium.org            data++;
105243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen          } else if ((f0byte & 0xF0) == 0x80) {
105343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen            data += JumpConditional(data, branch_hint);
105443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen          } else if (f0byte == 0xBE || f0byte == 0xBF || f0byte == 0xB6 ||
105543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen                     f0byte == 0xB7 || f0byte == 0xAF) {
105643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen            data += 2;
105743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen            data += PrintOperands(f0mnem, REG_OPER_OP_ORDER, data);
10587be3c996bea370e151c9fe4ecf7f779cdc5f87adkasperl@chromium.org          } else if ((f0byte & 0xF0) == 0x90) {
10597be3c996bea370e151c9fe4ecf7f779cdc5f87adkasperl@chromium.org            data += SetCC(data);
10609d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com          } else if ((f0byte & 0xF0) == 0x40) {
10619d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com            data += CMov(data);
106243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen          } else {
106343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen            data += 2;
106443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen            if (f0byte == 0xAB || f0byte == 0xA5 || f0byte == 0xAD) {
106543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen              // shrd, shld, bts
106643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen              AppendToBuffer("%s ", f0mnem);
106743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen              int mod, regop, rm;
106843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen              get_modrm(*data, &mod, &regop, &rm);
106943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen              data += PrintRightOperand(data);
107043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen              if (f0byte == 0xAB) {
107143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen                AppendToBuffer(",%s", NameOfCPURegister(regop));
107243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen              } else {
107343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen                AppendToBuffer(",%s,cl", NameOfCPURegister(regop));
107443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen              }
107543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen            } else {
107643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen              UnimplementedInstruction();
107743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen            }
107843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen          }
107943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen        }
108043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen        break;
108143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
108243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      case 0x8F:
108343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen        { data++;
108443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen          int mod, regop, rm;
108543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen          get_modrm(*data, &mod, &regop, &rm);
108643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen          if (regop == eax) {
108743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen            AppendToBuffer("pop ");
108843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen            data += PrintRightOperand(data);
108943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen          }
109043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen        }
109143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen        break;
109243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
109343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      case 0xFF:
109443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen        { data++;
109543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen          int mod, regop, rm;
109643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen          get_modrm(*data, &mod, &regop, &rm);
109743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen          const char* mnem = NULL;
109843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen          switch (regop) {
109943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen            case esi: mnem = "push"; break;
110043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen            case eax: mnem = "inc"; break;
11016f10e41fef1524c70846d970268de222e41c594cager@chromium.org            case ecx: mnem = "dec"; break;
110243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen            case edx: mnem = "call"; break;
110343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen            case esp: mnem = "jmp"; break;
110443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen            default: mnem = "???";
110543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen          }
110643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen          AppendToBuffer("%s ", mnem);
110743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen          data += PrintRightOperand(data);
110843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen        }
110943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen        break;
111043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
111143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      case 0xC7:  // imm32, fall through
111243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      case 0xC6:  // imm8
111343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen        { bool is_byte = *data == 0xC6;
111443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen          data++;
1115badaffc570baec00166b0ad3bdc96995751a7e13ricow@chromium.org          if (is_byte) {
1116badaffc570baec00166b0ad3bdc96995751a7e13ricow@chromium.org            AppendToBuffer("%s ", "mov_b");
1117badaffc570baec00166b0ad3bdc96995751a7e13ricow@chromium.org            data += PrintRightByteOperand(data);
1118badaffc570baec00166b0ad3bdc96995751a7e13ricow@chromium.org            int32_t imm = *data;
1119badaffc570baec00166b0ad3bdc96995751a7e13ricow@chromium.org            AppendToBuffer(",0x%x", imm);
1120badaffc570baec00166b0ad3bdc96995751a7e13ricow@chromium.org            data++;
1121badaffc570baec00166b0ad3bdc96995751a7e13ricow@chromium.org          } else {
1122badaffc570baec00166b0ad3bdc96995751a7e13ricow@chromium.org            AppendToBuffer("%s ", "mov");
1123badaffc570baec00166b0ad3bdc96995751a7e13ricow@chromium.org            data += PrintRightOperand(data);
1124badaffc570baec00166b0ad3bdc96995751a7e13ricow@chromium.org            int32_t imm = *reinterpret_cast<int32_t*>(data);
1125badaffc570baec00166b0ad3bdc96995751a7e13ricow@chromium.org            AppendToBuffer(",0x%x", imm);
1126badaffc570baec00166b0ad3bdc96995751a7e13ricow@chromium.org            data += 4;
1127badaffc570baec00166b0ad3bdc96995751a7e13ricow@chromium.org          }
112843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen        }
112943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen        break;
113043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
11317be3c996bea370e151c9fe4ecf7f779cdc5f87adkasperl@chromium.org      case 0x80:
11327be3c996bea370e151c9fe4ecf7f779cdc5f87adkasperl@chromium.org        { data++;
11330c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org          int mod, regop, rm;
11340c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org          get_modrm(*data, &mod, &regop, &rm);
11350c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org          const char* mnem = NULL;
11360c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org          switch (regop) {
11370c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org            case 5:  mnem = "subb"; break;
11380c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org            case 7:  mnem = "cmpb"; break;
11390c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org            default: UnimplementedInstruction();
11400c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org          }
11410c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org          AppendToBuffer("%s ", mnem);
1142badaffc570baec00166b0ad3bdc96995751a7e13ricow@chromium.org          data += PrintRightByteOperand(data);
11437be3c996bea370e151c9fe4ecf7f779cdc5f87adkasperl@chromium.org          int32_t imm = *data;
11447be3c996bea370e151c9fe4ecf7f779cdc5f87adkasperl@chromium.org          AppendToBuffer(",0x%x", imm);
11457be3c996bea370e151c9fe4ecf7f779cdc5f87adkasperl@chromium.org          data++;
11467be3c996bea370e151c9fe4ecf7f779cdc5f87adkasperl@chromium.org        }
11477be3c996bea370e151c9fe4ecf7f779cdc5f87adkasperl@chromium.org        break;
11487be3c996bea370e151c9fe4ecf7f779cdc5f87adkasperl@chromium.org
114943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      case 0x88:  // 8bit, fall through
115043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      case 0x89:  // 32bit
115143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen        { bool is_byte = *data == 0x88;
115243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen          int mod, regop, rm;
115343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen          data++;
115443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen          get_modrm(*data, &mod, &regop, &rm);
1155badaffc570baec00166b0ad3bdc96995751a7e13ricow@chromium.org          if (is_byte) {
1156badaffc570baec00166b0ad3bdc96995751a7e13ricow@chromium.org            AppendToBuffer("%s ", "mov_b");
1157badaffc570baec00166b0ad3bdc96995751a7e13ricow@chromium.org            data += PrintRightByteOperand(data);
1158badaffc570baec00166b0ad3bdc96995751a7e13ricow@chromium.org            AppendToBuffer(",%s", NameOfByteCPURegister(regop));
1159badaffc570baec00166b0ad3bdc96995751a7e13ricow@chromium.org          } else {
1160badaffc570baec00166b0ad3bdc96995751a7e13ricow@chromium.org            AppendToBuffer("%s ", "mov");
1161badaffc570baec00166b0ad3bdc96995751a7e13ricow@chromium.org            data += PrintRightOperand(data);
1162badaffc570baec00166b0ad3bdc96995751a7e13ricow@chromium.org            AppendToBuffer(",%s", NameOfCPURegister(regop));
1163badaffc570baec00166b0ad3bdc96995751a7e13ricow@chromium.org          }
116443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen        }
116543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen        break;
116643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
116743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      case 0x66:  // prefix
116864e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org        while (*data == 0x66) data++;
116964e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org        if (*data == 0xf && data[1] == 0x1f) {
117064e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org          AppendToBuffer("nop");  // 0x66 prefix
117164e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org        } else if (*data == 0x90) {
117264e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org          AppendToBuffer("nop");  // 0x66 prefix
117364e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org        } else if (*data == 0x8B) {
117443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen          data++;
117543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen          data += PrintOperands("mov_w", REG_OPER_OP_ORDER, data);
117643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen        } else if (*data == 0x89) {
117743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen          data++;
117843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen          int mod, regop, rm;
117943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen          get_modrm(*data, &mod, &regop, &rm);
118043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen          AppendToBuffer("mov_w ");
118143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen          data += PrintRightOperand(data);
118243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen          AppendToBuffer(",%s", NameOfCPURegister(regop));
11839d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com        } else if (*data == 0x0F) {
11849d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com          data++;
1185ce5e87bd905d592a8bd612b3dedf7a994177c13aager@chromium.org          if (*data == 0x38) {
1186ce5e87bd905d592a8bd612b3dedf7a994177c13aager@chromium.org            data++;
1187ce5e87bd905d592a8bd612b3dedf7a994177c13aager@chromium.org            if (*data == 0x17) {
1188ce5e87bd905d592a8bd612b3dedf7a994177c13aager@chromium.org              data++;
1189ce5e87bd905d592a8bd612b3dedf7a994177c13aager@chromium.org              int mod, regop, rm;
1190ce5e87bd905d592a8bd612b3dedf7a994177c13aager@chromium.org              get_modrm(*data, &mod, &regop, &rm);
1191ce5e87bd905d592a8bd612b3dedf7a994177c13aager@chromium.org              AppendToBuffer("ptest %s,%s",
1192ce5e87bd905d592a8bd612b3dedf7a994177c13aager@chromium.org                             NameOfXMMRegister(regop),
1193ce5e87bd905d592a8bd612b3dedf7a994177c13aager@chromium.org                             NameOfXMMRegister(rm));
1194ce5e87bd905d592a8bd612b3dedf7a994177c13aager@chromium.org              data++;
11951af7e1b5f676e5556c041fe09a5c4f5a906f27a0lrn@chromium.org            } else if (*data == 0x2A) {
11961af7e1b5f676e5556c041fe09a5c4f5a906f27a0lrn@chromium.org              // movntdqa
11971af7e1b5f676e5556c041fe09a5c4f5a906f27a0lrn@chromium.org              data++;
11981af7e1b5f676e5556c041fe09a5c4f5a906f27a0lrn@chromium.org              int mod, regop, rm;
11991af7e1b5f676e5556c041fe09a5c4f5a906f27a0lrn@chromium.org              get_modrm(*data, &mod, &regop, &rm);
12001af7e1b5f676e5556c041fe09a5c4f5a906f27a0lrn@chromium.org              AppendToBuffer("movntdqa %s,", NameOfXMMRegister(regop));
12011af7e1b5f676e5556c041fe09a5c4f5a906f27a0lrn@chromium.org              data += PrintRightOperand(data);
1202ce5e87bd905d592a8bd612b3dedf7a994177c13aager@chromium.org            } else {
1203ce5e87bd905d592a8bd612b3dedf7a994177c13aager@chromium.org              UnimplementedInstruction();
1204ce5e87bd905d592a8bd612b3dedf7a994177c13aager@chromium.org            }
12055f0c45f2cacb31d36a8f80c31f17bda7751a3644ager@chromium.org          } else if (*data == 0x3A) {
12065f0c45f2cacb31d36a8f80c31f17bda7751a3644ager@chromium.org            data++;
12074acdc2c8d4caecf7606db8af710366c1d6e28fe5whesse@chromium.org            if (*data == 0x0B) {
12084acdc2c8d4caecf7606db8af710366c1d6e28fe5whesse@chromium.org              data++;
12094acdc2c8d4caecf7606db8af710366c1d6e28fe5whesse@chromium.org              int mod, regop, rm;
12104acdc2c8d4caecf7606db8af710366c1d6e28fe5whesse@chromium.org              get_modrm(*data, &mod, &regop, &rm);
12114acdc2c8d4caecf7606db8af710366c1d6e28fe5whesse@chromium.org              int8_t imm8 = static_cast<int8_t>(data[1]);
12124acdc2c8d4caecf7606db8af710366c1d6e28fe5whesse@chromium.org              AppendToBuffer("roundsd %s,%s,%d",
12134acdc2c8d4caecf7606db8af710366c1d6e28fe5whesse@chromium.org                             NameOfXMMRegister(regop),
12144acdc2c8d4caecf7606db8af710366c1d6e28fe5whesse@chromium.org                             NameOfXMMRegister(rm),
12154acdc2c8d4caecf7606db8af710366c1d6e28fe5whesse@chromium.org                             static_cast<int>(imm8));
12164acdc2c8d4caecf7606db8af710366c1d6e28fe5whesse@chromium.org              data += 2;
12174acdc2c8d4caecf7606db8af710366c1d6e28fe5whesse@chromium.org            } else if (*data == 0x16) {
12185f0c45f2cacb31d36a8f80c31f17bda7751a3644ager@chromium.org              data++;
12195f0c45f2cacb31d36a8f80c31f17bda7751a3644ager@chromium.org              int mod, regop, rm;
12205f0c45f2cacb31d36a8f80c31f17bda7751a3644ager@chromium.org              get_modrm(*data, &mod, &regop, &rm);
12215f0c45f2cacb31d36a8f80c31f17bda7751a3644ager@chromium.org              int8_t imm8 = static_cast<int8_t>(data[1]);
12225f0c45f2cacb31d36a8f80c31f17bda7751a3644ager@chromium.org              AppendToBuffer("pextrd %s,%s,%d",
1223d91075f76b836c2cfa4f4e4cc0fb31170df864ccerik.corry@gmail.com                             NameOfCPURegister(regop),
12245f0c45f2cacb31d36a8f80c31f17bda7751a3644ager@chromium.org                             NameOfXMMRegister(rm),
12255f0c45f2cacb31d36a8f80c31f17bda7751a3644ager@chromium.org                             static_cast<int>(imm8));
12265f0c45f2cacb31d36a8f80c31f17bda7751a3644ager@chromium.org              data += 2;
122764e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org            } else if (*data == 0x17) {
122864e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org              data++;
122964e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org              int mod, regop, rm;
123064e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org              get_modrm(*data, &mod, &regop, &rm);
123164e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org              int8_t imm8 = static_cast<int8_t>(data[1]);
123264e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org              AppendToBuffer("extractps %s,%s,%d",
123364e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org                             NameOfCPURegister(regop),
123464e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org                             NameOfXMMRegister(rm),
123564e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org                             static_cast<int>(imm8));
123664e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org              data += 2;
1237d91075f76b836c2cfa4f4e4cc0fb31170df864ccerik.corry@gmail.com            } else if (*data == 0x22) {
1238d91075f76b836c2cfa4f4e4cc0fb31170df864ccerik.corry@gmail.com              data++;
1239d91075f76b836c2cfa4f4e4cc0fb31170df864ccerik.corry@gmail.com              int mod, regop, rm;
1240d91075f76b836c2cfa4f4e4cc0fb31170df864ccerik.corry@gmail.com              get_modrm(*data, &mod, &regop, &rm);
1241d91075f76b836c2cfa4f4e4cc0fb31170df864ccerik.corry@gmail.com              int8_t imm8 = static_cast<int8_t>(data[1]);
1242d91075f76b836c2cfa4f4e4cc0fb31170df864ccerik.corry@gmail.com              AppendToBuffer("pinsrd %s,%s,%d",
1243d91075f76b836c2cfa4f4e4cc0fb31170df864ccerik.corry@gmail.com                             NameOfXMMRegister(regop),
1244d91075f76b836c2cfa4f4e4cc0fb31170df864ccerik.corry@gmail.com                             NameOfCPURegister(rm),
1245d91075f76b836c2cfa4f4e4cc0fb31170df864ccerik.corry@gmail.com                             static_cast<int>(imm8));
1246d91075f76b836c2cfa4f4e4cc0fb31170df864ccerik.corry@gmail.com              data += 2;
12475f0c45f2cacb31d36a8f80c31f17bda7751a3644ager@chromium.org            } else {
12485f0c45f2cacb31d36a8f80c31f17bda7751a3644ager@chromium.org              UnimplementedInstruction();
12495f0c45f2cacb31d36a8f80c31f17bda7751a3644ager@chromium.org            }
1250f837290e142d49c9e1332841ec2c49ee2f09584avegorov@chromium.org          } else if (*data == 0x2E || *data == 0x2F) {
1251f837290e142d49c9e1332841ec2c49ee2f09584avegorov@chromium.org            const char* mnem = (*data == 0x2E) ? "ucomisd" : "comisd";
12529d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com            data++;
12539d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com            int mod, regop, rm;
12549d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com            get_modrm(*data, &mod, &regop, &rm);
1255f837290e142d49c9e1332841ec2c49ee2f09584avegorov@chromium.org            if (mod == 0x3) {
1256f837290e142d49c9e1332841ec2c49ee2f09584avegorov@chromium.org              AppendToBuffer("%s %s,%s", mnem,
1257f837290e142d49c9e1332841ec2c49ee2f09584avegorov@chromium.org                             NameOfXMMRegister(regop),
1258f837290e142d49c9e1332841ec2c49ee2f09584avegorov@chromium.org                             NameOfXMMRegister(rm));
1259f837290e142d49c9e1332841ec2c49ee2f09584avegorov@chromium.org              data++;
1260f837290e142d49c9e1332841ec2c49ee2f09584avegorov@chromium.org            } else {
1261f837290e142d49c9e1332841ec2c49ee2f09584avegorov@chromium.org              AppendToBuffer("%s %s,", mnem, NameOfXMMRegister(regop));
1262f837290e142d49c9e1332841ec2c49ee2f09584avegorov@chromium.org              data += PrintRightOperand(data);
1263f837290e142d49c9e1332841ec2c49ee2f09584avegorov@chromium.org            }
1264f837290e142d49c9e1332841ec2c49ee2f09584avegorov@chromium.org          } else if (*data == 0x50) {
1265f837290e142d49c9e1332841ec2c49ee2f09584avegorov@chromium.org            data++;
1266f837290e142d49c9e1332841ec2c49ee2f09584avegorov@chromium.org            int mod, regop, rm;
1267f837290e142d49c9e1332841ec2c49ee2f09584avegorov@chromium.org            get_modrm(*data, &mod, &regop, &rm);
1268f837290e142d49c9e1332841ec2c49ee2f09584avegorov@chromium.org            AppendToBuffer("movmskpd %s,%s",
1269f837290e142d49c9e1332841ec2c49ee2f09584avegorov@chromium.org                           NameOfCPURegister(regop),
12709d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com                           NameOfXMMRegister(rm));
12719d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com            data++;
12725f0c45f2cacb31d36a8f80c31f17bda7751a3644ager@chromium.org          } else if (*data == 0x54) {
12735f0c45f2cacb31d36a8f80c31f17bda7751a3644ager@chromium.org            data++;
12745f0c45f2cacb31d36a8f80c31f17bda7751a3644ager@chromium.org            int mod, regop, rm;
12755f0c45f2cacb31d36a8f80c31f17bda7751a3644ager@chromium.org            get_modrm(*data, &mod, &regop, &rm);
12765f0c45f2cacb31d36a8f80c31f17bda7751a3644ager@chromium.org            AppendToBuffer("andpd %s,%s",
12775f0c45f2cacb31d36a8f80c31f17bda7751a3644ager@chromium.org                           NameOfXMMRegister(regop),
12785f0c45f2cacb31d36a8f80c31f17bda7751a3644ager@chromium.org                           NameOfXMMRegister(rm));
12795f0c45f2cacb31d36a8f80c31f17bda7751a3644ager@chromium.org            data++;
1280471f2f1d24adb4bad1edc3bf0ee35092486de187mstarzinger@chromium.org          } else if (*data == 0x56) {
1281471f2f1d24adb4bad1edc3bf0ee35092486de187mstarzinger@chromium.org            data++;
1282471f2f1d24adb4bad1edc3bf0ee35092486de187mstarzinger@chromium.org            int mod, regop, rm;
1283471f2f1d24adb4bad1edc3bf0ee35092486de187mstarzinger@chromium.org            get_modrm(*data, &mod, &regop, &rm);
1284471f2f1d24adb4bad1edc3bf0ee35092486de187mstarzinger@chromium.org            AppendToBuffer("orpd %s,%s",
1285471f2f1d24adb4bad1edc3bf0ee35092486de187mstarzinger@chromium.org                           NameOfXMMRegister(regop),
1286471f2f1d24adb4bad1edc3bf0ee35092486de187mstarzinger@chromium.org                           NameOfXMMRegister(rm));
1287471f2f1d24adb4bad1edc3bf0ee35092486de187mstarzinger@chromium.org            data++;
1288846fb74ad58083497b91fc4668a56fddb36fbd2esgjesse@chromium.org          } else if (*data == 0x57) {
1289846fb74ad58083497b91fc4668a56fddb36fbd2esgjesse@chromium.org            data++;
1290846fb74ad58083497b91fc4668a56fddb36fbd2esgjesse@chromium.org            int mod, regop, rm;
1291846fb74ad58083497b91fc4668a56fddb36fbd2esgjesse@chromium.org            get_modrm(*data, &mod, &regop, &rm);
1292846fb74ad58083497b91fc4668a56fddb36fbd2esgjesse@chromium.org            AppendToBuffer("xorpd %s,%s",
1293846fb74ad58083497b91fc4668a56fddb36fbd2esgjesse@chromium.org                           NameOfXMMRegister(regop),
1294846fb74ad58083497b91fc4668a56fddb36fbd2esgjesse@chromium.org                           NameOfXMMRegister(rm));
1295846fb74ad58083497b91fc4668a56fddb36fbd2esgjesse@chromium.org            data++;
1296ce5e87bd905d592a8bd612b3dedf7a994177c13aager@chromium.org          } else if (*data == 0x6E) {
1297ce5e87bd905d592a8bd612b3dedf7a994177c13aager@chromium.org            data++;
1298ce5e87bd905d592a8bd612b3dedf7a994177c13aager@chromium.org            int mod, regop, rm;
1299ce5e87bd905d592a8bd612b3dedf7a994177c13aager@chromium.org            get_modrm(*data, &mod, &regop, &rm);
1300ce5e87bd905d592a8bd612b3dedf7a994177c13aager@chromium.org            AppendToBuffer("movd %s,", NameOfXMMRegister(regop));
1301ce5e87bd905d592a8bd612b3dedf7a994177c13aager@chromium.org            data += PrintRightOperand(data);
13020c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org          } else if (*data == 0x6F) {
13030c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org            data++;
13040c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org            int mod, regop, rm;
13050c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org            get_modrm(*data, &mod, &regop, &rm);
13060c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org            AppendToBuffer("movdqa %s,", NameOfXMMRegister(regop));
1307badaffc570baec00166b0ad3bdc96995751a7e13ricow@chromium.org            data += PrintRightXMMOperand(data);
13085f0c45f2cacb31d36a8f80c31f17bda7751a3644ager@chromium.org          } else if (*data == 0x70) {
13095f0c45f2cacb31d36a8f80c31f17bda7751a3644ager@chromium.org            data++;
13105f0c45f2cacb31d36a8f80c31f17bda7751a3644ager@chromium.org            int mod, regop, rm;
13115f0c45f2cacb31d36a8f80c31f17bda7751a3644ager@chromium.org            get_modrm(*data, &mod, &regop, &rm);
13125f0c45f2cacb31d36a8f80c31f17bda7751a3644ager@chromium.org            int8_t imm8 = static_cast<int8_t>(data[1]);
13135f0c45f2cacb31d36a8f80c31f17bda7751a3644ager@chromium.org            AppendToBuffer("pshufd %s,%s,%d",
13145f0c45f2cacb31d36a8f80c31f17bda7751a3644ager@chromium.org                           NameOfXMMRegister(regop),
13155f0c45f2cacb31d36a8f80c31f17bda7751a3644ager@chromium.org                           NameOfXMMRegister(rm),
13165f0c45f2cacb31d36a8f80c31f17bda7751a3644ager@chromium.org                           static_cast<int>(imm8));
13175f0c45f2cacb31d36a8f80c31f17bda7751a3644ager@chromium.org            data += 2;
131833e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org          } else if (*data == 0x76) {
131933e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org            data++;
132033e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org            int mod, regop, rm;
132133e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org            get_modrm(*data, &mod, &regop, &rm);
132233e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org            AppendToBuffer("pcmpeqd %s,%s",
132333e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org                           NameOfXMMRegister(regop),
132433e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org                           NameOfXMMRegister(rm));
132533e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org            data++;
132664e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org          } else if (*data == 0x90) {
132764e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org            data++;
132864e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org            AppendToBuffer("nop");  // 2 byte nop.
1329c6c5718277d4047fad1e034396228ce15571b5a4sgjesse@chromium.org          } else if (*data == 0xF3) {
1330c6c5718277d4047fad1e034396228ce15571b5a4sgjesse@chromium.org            data++;
1331c6c5718277d4047fad1e034396228ce15571b5a4sgjesse@chromium.org            int mod, regop, rm;
1332c6c5718277d4047fad1e034396228ce15571b5a4sgjesse@chromium.org            get_modrm(*data, &mod, &regop, &rm);
1333c6c5718277d4047fad1e034396228ce15571b5a4sgjesse@chromium.org            AppendToBuffer("psllq %s,%s",
1334c6c5718277d4047fad1e034396228ce15571b5a4sgjesse@chromium.org                           NameOfXMMRegister(regop),
1335c6c5718277d4047fad1e034396228ce15571b5a4sgjesse@chromium.org                           NameOfXMMRegister(rm));
1336c6c5718277d4047fad1e034396228ce15571b5a4sgjesse@chromium.org            data++;
13375f0c45f2cacb31d36a8f80c31f17bda7751a3644ager@chromium.org          } else if (*data == 0x73) {
13385f0c45f2cacb31d36a8f80c31f17bda7751a3644ager@chromium.org            data++;
13395f0c45f2cacb31d36a8f80c31f17bda7751a3644ager@chromium.org            int mod, regop, rm;
13405f0c45f2cacb31d36a8f80c31f17bda7751a3644ager@chromium.org            get_modrm(*data, &mod, &regop, &rm);
13415f0c45f2cacb31d36a8f80c31f17bda7751a3644ager@chromium.org            int8_t imm8 = static_cast<int8_t>(data[1]);
1342c6c5718277d4047fad1e034396228ce15571b5a4sgjesse@chromium.org            ASSERT(regop == esi || regop == edx);
1343c6c5718277d4047fad1e034396228ce15571b5a4sgjesse@chromium.org            AppendToBuffer("%s %s,%d",
1344c6c5718277d4047fad1e034396228ce15571b5a4sgjesse@chromium.org                           (regop == esi) ? "psllq" : "psrlq",
13455f0c45f2cacb31d36a8f80c31f17bda7751a3644ager@chromium.org                           NameOfXMMRegister(rm),
13465f0c45f2cacb31d36a8f80c31f17bda7751a3644ager@chromium.org                           static_cast<int>(imm8));
13475f0c45f2cacb31d36a8f80c31f17bda7751a3644ager@chromium.org            data += 2;
1348c6c5718277d4047fad1e034396228ce15571b5a4sgjesse@chromium.org          } else if (*data == 0xD3) {
1349c6c5718277d4047fad1e034396228ce15571b5a4sgjesse@chromium.org            data++;
1350c6c5718277d4047fad1e034396228ce15571b5a4sgjesse@chromium.org            int mod, regop, rm;
1351c6c5718277d4047fad1e034396228ce15571b5a4sgjesse@chromium.org            get_modrm(*data, &mod, &regop, &rm);
1352c6c5718277d4047fad1e034396228ce15571b5a4sgjesse@chromium.org            AppendToBuffer("psrlq %s,%s",
1353c6c5718277d4047fad1e034396228ce15571b5a4sgjesse@chromium.org                           NameOfXMMRegister(regop),
1354c6c5718277d4047fad1e034396228ce15571b5a4sgjesse@chromium.org                           NameOfXMMRegister(rm));
1355c6c5718277d4047fad1e034396228ce15571b5a4sgjesse@chromium.org            data++;
13560c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org          } else if (*data == 0x7F) {
13570c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org            AppendToBuffer("movdqa ");
13580c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org            data++;
13590c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org            int mod, regop, rm;
13600c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org            get_modrm(*data, &mod, &regop, &rm);
1361badaffc570baec00166b0ad3bdc96995751a7e13ricow@chromium.org            data += PrintRightXMMOperand(data);
13620c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org            AppendToBuffer(",%s", NameOfXMMRegister(regop));
13635f0c45f2cacb31d36a8f80c31f17bda7751a3644ager@chromium.org          } else if (*data == 0x7E) {
13645f0c45f2cacb31d36a8f80c31f17bda7751a3644ager@chromium.org            data++;
13655f0c45f2cacb31d36a8f80c31f17bda7751a3644ager@chromium.org            int mod, regop, rm;
13665f0c45f2cacb31d36a8f80c31f17bda7751a3644ager@chromium.org            get_modrm(*data, &mod, &regop, &rm);
13675f0c45f2cacb31d36a8f80c31f17bda7751a3644ager@chromium.org            AppendToBuffer("movd ");
13685f0c45f2cacb31d36a8f80c31f17bda7751a3644ager@chromium.org            data += PrintRightOperand(data);
13695f0c45f2cacb31d36a8f80c31f17bda7751a3644ager@chromium.org            AppendToBuffer(",%s", NameOfXMMRegister(regop));
13705f0c45f2cacb31d36a8f80c31f17bda7751a3644ager@chromium.org          } else if (*data == 0xDB) {
13715f0c45f2cacb31d36a8f80c31f17bda7751a3644ager@chromium.org            data++;
13725f0c45f2cacb31d36a8f80c31f17bda7751a3644ager@chromium.org            int mod, regop, rm;
13735f0c45f2cacb31d36a8f80c31f17bda7751a3644ager@chromium.org            get_modrm(*data, &mod, &regop, &rm);
13745f0c45f2cacb31d36a8f80c31f17bda7751a3644ager@chromium.org            AppendToBuffer("pand %s,%s",
13755f0c45f2cacb31d36a8f80c31f17bda7751a3644ager@chromium.org                           NameOfXMMRegister(regop),
13765f0c45f2cacb31d36a8f80c31f17bda7751a3644ager@chromium.org                           NameOfXMMRegister(rm));
13775f0c45f2cacb31d36a8f80c31f17bda7751a3644ager@chromium.org            data++;
13781af7e1b5f676e5556c041fe09a5c4f5a906f27a0lrn@chromium.org          } else if (*data == 0xE7) {
13791af7e1b5f676e5556c041fe09a5c4f5a906f27a0lrn@chromium.org            data++;
13801af7e1b5f676e5556c041fe09a5c4f5a906f27a0lrn@chromium.org            int mod, regop, rm;
13811af7e1b5f676e5556c041fe09a5c4f5a906f27a0lrn@chromium.org            get_modrm(*data, &mod, &regop, &rm);
1382badaffc570baec00166b0ad3bdc96995751a7e13ricow@chromium.org            if (mod == 3) {
1383badaffc570baec00166b0ad3bdc96995751a7e13ricow@chromium.org              AppendToBuffer("movntdq ");
1384badaffc570baec00166b0ad3bdc96995751a7e13ricow@chromium.org              data += PrintRightOperand(data);
1385badaffc570baec00166b0ad3bdc96995751a7e13ricow@chromium.org              AppendToBuffer(",%s", NameOfXMMRegister(regop));
1386badaffc570baec00166b0ad3bdc96995751a7e13ricow@chromium.org            } else {
1387badaffc570baec00166b0ad3bdc96995751a7e13ricow@chromium.org              UnimplementedInstruction();
1388badaffc570baec00166b0ad3bdc96995751a7e13ricow@chromium.org            }
1389ce5e87bd905d592a8bd612b3dedf7a994177c13aager@chromium.org          } else if (*data == 0xEF) {
13905f0c45f2cacb31d36a8f80c31f17bda7751a3644ager@chromium.org            data++;
13915f0c45f2cacb31d36a8f80c31f17bda7751a3644ager@chromium.org            int mod, regop, rm;
13925f0c45f2cacb31d36a8f80c31f17bda7751a3644ager@chromium.org            get_modrm(*data, &mod, &regop, &rm);
13935f0c45f2cacb31d36a8f80c31f17bda7751a3644ager@chromium.org            AppendToBuffer("pxor %s,%s",
13945f0c45f2cacb31d36a8f80c31f17bda7751a3644ager@chromium.org                           NameOfXMMRegister(regop),
13955f0c45f2cacb31d36a8f80c31f17bda7751a3644ager@chromium.org                           NameOfXMMRegister(rm));
13965f0c45f2cacb31d36a8f80c31f17bda7751a3644ager@chromium.org            data++;
1397c6c5718277d4047fad1e034396228ce15571b5a4sgjesse@chromium.org          } else if (*data == 0xEB) {
1398c6c5718277d4047fad1e034396228ce15571b5a4sgjesse@chromium.org            data++;
1399c6c5718277d4047fad1e034396228ce15571b5a4sgjesse@chromium.org            int mod, regop, rm;
1400c6c5718277d4047fad1e034396228ce15571b5a4sgjesse@chromium.org            get_modrm(*data, &mod, &regop, &rm);
1401c6c5718277d4047fad1e034396228ce15571b5a4sgjesse@chromium.org            AppendToBuffer("por %s,%s",
1402c6c5718277d4047fad1e034396228ce15571b5a4sgjesse@chromium.org                           NameOfXMMRegister(regop),
1403c6c5718277d4047fad1e034396228ce15571b5a4sgjesse@chromium.org                           NameOfXMMRegister(rm));
1404c6c5718277d4047fad1e034396228ce15571b5a4sgjesse@chromium.org            data++;
14059d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com          } else {
14069d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com            UnimplementedInstruction();
14079d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com          }
140843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen        } else {
140943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen          UnimplementedInstruction();
141043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen        }
141143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen        break;
141243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
141343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      case 0xFE:
141443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen        { data++;
141543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen          int mod, regop, rm;
141643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen          get_modrm(*data, &mod, &regop, &rm);
14174a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org          if (regop == ecx) {
14184a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org            AppendToBuffer("dec_b ");
14194a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org            data += PrintRightOperand(data);
142043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen          } else {
142143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen            UnimplementedInstruction();
142243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen          }
142343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen        }
142443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen        break;
142543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
142643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      case 0x68:
142743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen        AppendToBuffer("push 0x%x", *reinterpret_cast<int32_t*>(data+1));
142843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen        data += 5;
142943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen        break;
143043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
143143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      case 0x6A:
143243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen        AppendToBuffer("push 0x%x", *reinterpret_cast<int8_t*>(data + 1));
143343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen        data += 2;
143443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen        break;
143543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
143643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      case 0xA8:
143743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen        AppendToBuffer("test al,0x%x", *reinterpret_cast<uint8_t*>(data+1));
143843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen        data += 2;
143943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen        break;
144043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
144143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      case 0xA9:
144243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen        AppendToBuffer("test eax,0x%x", *reinterpret_cast<int32_t*>(data+1));
144343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen        data += 5;
144443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen        break;
144543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
144643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      case 0xD1:  // fall through
144743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      case 0xD3:  // fall through
144843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      case 0xC1:
144943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen        data += D1D3C1Instruction(data);
145043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen        break;
145143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
145243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      case 0xD9:  // fall through
14537276f14ca716596e0a0d17539516370c1f453847kasper.lund      case 0xDA:  // fall through
145443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      case 0xDB:  // fall through
145543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      case 0xDC:  // fall through
145643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      case 0xDD:  // fall through
145743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      case 0xDE:  // fall through
145843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      case 0xDF:
145943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen        data += FPUInstruction(data);
146043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen        break;
146143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
146243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      case 0xEB:
146343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen        data += JumpShort(data);
146443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen        break;
146543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
146643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      case 0xF2:
146743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen        if (*(data+1) == 0x0F) {
146843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen          byte b2 = *(data+2);
146943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen          if (b2 == 0x11) {
147043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen            AppendToBuffer("movsd ");
147143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen            data += 3;
147243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen            int mod, regop, rm;
147343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen            get_modrm(*data, &mod, &regop, &rm);
1474badaffc570baec00166b0ad3bdc96995751a7e13ricow@chromium.org            data += PrintRightXMMOperand(data);
147543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen            AppendToBuffer(",%s", NameOfXMMRegister(regop));
147643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen          } else if (b2 == 0x10) {
147743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen            data += 3;
147843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen            int mod, regop, rm;
147943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen            get_modrm(*data, &mod, &regop, &rm);
148043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen            AppendToBuffer("movsd %s,", NameOfXMMRegister(regop));
1481badaffc570baec00166b0ad3bdc96995751a7e13ricow@chromium.org            data += PrintRightXMMOperand(data);
14827979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org          } else  if (b2 == 0x5A) {
14837979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org            data += 3;
14847979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org            int mod, regop, rm;
14857979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org            get_modrm(*data, &mod, &regop, &rm);
14867979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org            AppendToBuffer("cvtsd2ss %s,", NameOfXMMRegister(regop));
14877979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org            data += PrintRightXMMOperand(data);
148843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen          } else {
148943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen            const char* mnem = "?";
149043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen            switch (b2) {
149143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen              case 0x2A: mnem = "cvtsi2sd"; break;
1492f837290e142d49c9e1332841ec2c49ee2f09584avegorov@chromium.org              case 0x2C: mnem = "cvttsd2si"; break;
149346839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org              case 0x2D: mnem = "cvtsd2si"; break;
1494ce5e87bd905d592a8bd612b3dedf7a994177c13aager@chromium.org              case 0x51: mnem = "sqrtsd"; break;
149543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen              case 0x58: mnem = "addsd"; break;
149643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen              case 0x59: mnem = "mulsd"; break;
149743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen              case 0x5C: mnem = "subsd"; break;
149843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen              case 0x5E: mnem = "divsd"; break;
149943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen            }
150043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen            data += 3;
150143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen            int mod, regop, rm;
150243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen            get_modrm(*data, &mod, &regop, &rm);
150343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen            if (b2 == 0x2A) {
1504badaffc570baec00166b0ad3bdc96995751a7e13ricow@chromium.org              AppendToBuffer("%s %s,", mnem, NameOfXMMRegister(regop));
1505badaffc570baec00166b0ad3bdc96995751a7e13ricow@chromium.org              data += PrintRightOperand(data);
150646839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org            } else if (b2 == 0x2C || b2 == 0x2D) {
1507badaffc570baec00166b0ad3bdc96995751a7e13ricow@chromium.org              AppendToBuffer("%s %s,", mnem, NameOfCPURegister(regop));
1508badaffc570baec00166b0ad3bdc96995751a7e13ricow@chromium.org              data += PrintRightXMMOperand(data);
1509c20610af4f0ca150977ca140a1174f98ee46f5aafschneider@chromium.org            } else if (b2 == 0xC2) {
1510c20610af4f0ca150977ca140a1174f98ee46f5aafschneider@chromium.org              // Intel manual 2A, Table 3-18.
1511c20610af4f0ca150977ca140a1174f98ee46f5aafschneider@chromium.org              const char* const pseudo_op[] = {
1512c20610af4f0ca150977ca140a1174f98ee46f5aafschneider@chromium.org                "cmpeqsd",
1513c20610af4f0ca150977ca140a1174f98ee46f5aafschneider@chromium.org                "cmpltsd",
1514c20610af4f0ca150977ca140a1174f98ee46f5aafschneider@chromium.org                "cmplesd",
1515c20610af4f0ca150977ca140a1174f98ee46f5aafschneider@chromium.org                "cmpunordsd",
1516c20610af4f0ca150977ca140a1174f98ee46f5aafschneider@chromium.org                "cmpneqsd",
1517c20610af4f0ca150977ca140a1174f98ee46f5aafschneider@chromium.org                "cmpnltsd",
1518c20610af4f0ca150977ca140a1174f98ee46f5aafschneider@chromium.org                "cmpnlesd",
1519c20610af4f0ca150977ca140a1174f98ee46f5aafschneider@chromium.org                "cmpordsd"
1520c20610af4f0ca150977ca140a1174f98ee46f5aafschneider@chromium.org              };
1521c20610af4f0ca150977ca140a1174f98ee46f5aafschneider@chromium.org              AppendToBuffer("%s %s,%s",
1522c20610af4f0ca150977ca140a1174f98ee46f5aafschneider@chromium.org                             pseudo_op[data[1]],
1523c20610af4f0ca150977ca140a1174f98ee46f5aafschneider@chromium.org                             NameOfXMMRegister(regop),
1524c20610af4f0ca150977ca140a1174f98ee46f5aafschneider@chromium.org                             NameOfXMMRegister(rm));
1525c20610af4f0ca150977ca140a1174f98ee46f5aafschneider@chromium.org              data += 2;
152643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen            } else {
1527badaffc570baec00166b0ad3bdc96995751a7e13ricow@chromium.org              AppendToBuffer("%s %s,", mnem, NameOfXMMRegister(regop));
1528badaffc570baec00166b0ad3bdc96995751a7e13ricow@chromium.org              data += PrintRightXMMOperand(data);
152943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen            }
153043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen          }
153143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen        } else {
153243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen          UnimplementedInstruction();
153343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen        }
153443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen        break;
153543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
153643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      case 0xF3:
15370c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org        if (*(data+1) == 0x0F) {
15387979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org          byte b2 = *(data+2);
15397979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org          if (b2 == 0x11) {
15407979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org            AppendToBuffer("movss ");
15417979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org            data += 3;
15427979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org            int mod, regop, rm;
15437979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org            get_modrm(*data, &mod, &regop, &rm);
15447979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org            data += PrintRightXMMOperand(data);
15457979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org            AppendToBuffer(",%s", NameOfXMMRegister(regop));
15467979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org          } else if (b2 == 0x10) {
15477979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org            data += 3;
15487979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org            int mod, regop, rm;
15497979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org            get_modrm(*data, &mod, &regop, &rm);
15507979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org            AppendToBuffer("movss %s,", NameOfXMMRegister(regop));
15517979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org            data += PrintRightXMMOperand(data);
15527979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org          } else if (b2 == 0x2C) {
15530c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org            data += 3;
1554badaffc570baec00166b0ad3bdc96995751a7e13ricow@chromium.org            int mod, regop, rm;
1555badaffc570baec00166b0ad3bdc96995751a7e13ricow@chromium.org            get_modrm(*data, &mod, &regop, &rm);
1556badaffc570baec00166b0ad3bdc96995751a7e13ricow@chromium.org            AppendToBuffer("cvttss2si %s,", NameOfCPURegister(regop));
1557badaffc570baec00166b0ad3bdc96995751a7e13ricow@chromium.org            data += PrintRightXMMOperand(data);
15587979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org          } else if (b2 == 0x5A) {
1559ce5e87bd905d592a8bd612b3dedf7a994177c13aager@chromium.org            data += 3;
1560ce5e87bd905d592a8bd612b3dedf7a994177c13aager@chromium.org            int mod, regop, rm;
1561ce5e87bd905d592a8bd612b3dedf7a994177c13aager@chromium.org            get_modrm(*data, &mod, &regop, &rm);
1562badaffc570baec00166b0ad3bdc96995751a7e13ricow@chromium.org            AppendToBuffer("cvtss2sd %s,", NameOfXMMRegister(regop));
1563badaffc570baec00166b0ad3bdc96995751a7e13ricow@chromium.org            data += PrintRightXMMOperand(data);
15647979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org          } else  if (b2 == 0x6F) {
15650c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org            data += 3;
15660c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org            int mod, regop, rm;
15670c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org            get_modrm(*data, &mod, &regop, &rm);
15680c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org            AppendToBuffer("movdqu %s,", NameOfXMMRegister(regop));
1569badaffc570baec00166b0ad3bdc96995751a7e13ricow@chromium.org            data += PrintRightXMMOperand(data);
15707979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org          } else  if (b2 == 0x7F) {
15710c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org            AppendToBuffer("movdqu ");
15720c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org            data += 3;
15730c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org            int mod, regop, rm;
15740c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org            get_modrm(*data, &mod, &regop, &rm);
1575badaffc570baec00166b0ad3bdc96995751a7e13ricow@chromium.org            data += PrintRightXMMOperand(data);
15760c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org            AppendToBuffer(",%s", NameOfXMMRegister(regop));
15770c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org          } else {
15780c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org            UnimplementedInstruction();
15790c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org          }
15800c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org        } else if (*(data+1) == 0xA5) {
15810c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org          data += 2;
15820c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org          AppendToBuffer("rep_movs");
1583ce5e87bd905d592a8bd612b3dedf7a994177c13aager@chromium.org        } else if (*(data+1) == 0xAB) {
1584ce5e87bd905d592a8bd612b3dedf7a994177c13aager@chromium.org          data += 2;
1585ce5e87bd905d592a8bd612b3dedf7a994177c13aager@chromium.org          AppendToBuffer("rep_stos");
158643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen        } else {
158743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen          UnimplementedInstruction();
158843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen        }
158943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen        break;
159043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
159143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      case 0xF7:
159243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen        data += F7Instruction(data);
159343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen        break;
159443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
159543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      default:
159643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen        UnimplementedInstruction();
159743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    }
159843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  }
159943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
160043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  if (tmp_buffer_pos_ < sizeof tmp_buffer_) {
160143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    tmp_buffer_[tmp_buffer_pos_] = '\0';
160243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  }
160343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
160443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  int instr_len = data - instr;
16050c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org  if (instr_len == 0) {
16060c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org    printf("%02x", *data);
16070c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org  }
16087276f14ca716596e0a0d17539516370c1f453847kasper.lund  ASSERT(instr_len > 0);  // Ensure progress.
16097276f14ca716596e0a0d17539516370c1f453847kasper.lund
16107276f14ca716596e0a0d17539516370c1f453847kasper.lund  int outp = 0;
16117276f14ca716596e0a0d17539516370c1f453847kasper.lund  // Instruction bytes.
16127276f14ca716596e0a0d17539516370c1f453847kasper.lund  for (byte* bp = instr; bp < data; bp++) {
16137276f14ca716596e0a0d17539516370c1f453847kasper.lund    outp += v8::internal::OS::SNPrintF(out_buffer + outp,
16147276f14ca716596e0a0d17539516370c1f453847kasper.lund                                       "%02x",
16157276f14ca716596e0a0d17539516370c1f453847kasper.lund                                       *bp);
16167276f14ca716596e0a0d17539516370c1f453847kasper.lund  }
16177276f14ca716596e0a0d17539516370c1f453847kasper.lund  for (int i = 6 - instr_len; i >= 0; i--) {
16187276f14ca716596e0a0d17539516370c1f453847kasper.lund    outp += v8::internal::OS::SNPrintF(out_buffer + outp,
16197276f14ca716596e0a0d17539516370c1f453847kasper.lund                                       "  ");
16207276f14ca716596e0a0d17539516370c1f453847kasper.lund  }
16217276f14ca716596e0a0d17539516370c1f453847kasper.lund
16227276f14ca716596e0a0d17539516370c1f453847kasper.lund  outp += v8::internal::OS::SNPrintF(out_buffer + outp,
16237276f14ca716596e0a0d17539516370c1f453847kasper.lund                                     " %s",
1624b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org                                     tmp_buffer_.start());
162543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  return instr_len;
1626c20610af4f0ca150977ca140a1174f98ee46f5aafschneider@chromium.org}  // NOLINT (function is too long)
162743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
162843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
162943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen//------------------------------------------------------------------------------
163043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
163143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
163243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansenstatic const char* cpu_regs[8] = {
16337be3c996bea370e151c9fe4ecf7f779cdc5f87adkasperl@chromium.org  "eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi"
16347be3c996bea370e151c9fe4ecf7f779cdc5f87adkasperl@chromium.org};
16357be3c996bea370e151c9fe4ecf7f779cdc5f87adkasperl@chromium.org
16367be3c996bea370e151c9fe4ecf7f779cdc5f87adkasperl@chromium.org
16377be3c996bea370e151c9fe4ecf7f779cdc5f87adkasperl@chromium.orgstatic const char* byte_cpu_regs[8] = {
16387be3c996bea370e151c9fe4ecf7f779cdc5f87adkasperl@chromium.org  "al", "cl", "dl", "bl", "ah", "ch", "dh", "bh"
163943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen};
164043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
164143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
164243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansenstatic const char* xmm_regs[8] = {
16437be3c996bea370e151c9fe4ecf7f779cdc5f87adkasperl@chromium.org  "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7"
164443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen};
164543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
164643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
164743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansenconst char* NameConverter::NameOfAddress(byte* addr) const {
1648ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  v8::internal::OS::SNPrintF(tmp_buffer_, "%p", addr);
1649ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  return tmp_buffer_.start();
165043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen}
165143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
165243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
165343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansenconst char* NameConverter::NameOfConstant(byte* addr) const {
165443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  return NameOfAddress(addr);
165543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen}
165643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
165743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
165843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansenconst char* NameConverter::NameOfCPURegister(int reg) const {
165943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  if (0 <= reg && reg < 8) return cpu_regs[reg];
166043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  return "noreg";
166143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen}
166243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
166343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
16647be3c996bea370e151c9fe4ecf7f779cdc5f87adkasperl@chromium.orgconst char* NameConverter::NameOfByteCPURegister(int reg) const {
16657be3c996bea370e151c9fe4ecf7f779cdc5f87adkasperl@chromium.org  if (0 <= reg && reg < 8) return byte_cpu_regs[reg];
16667be3c996bea370e151c9fe4ecf7f779cdc5f87adkasperl@chromium.org  return "noreg";
16677be3c996bea370e151c9fe4ecf7f779cdc5f87adkasperl@chromium.org}
16687be3c996bea370e151c9fe4ecf7f779cdc5f87adkasperl@chromium.org
16697be3c996bea370e151c9fe4ecf7f779cdc5f87adkasperl@chromium.org
167043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansenconst char* NameConverter::NameOfXMMRegister(int reg) const {
167143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  if (0 <= reg && reg < 8) return xmm_regs[reg];
167243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  return "noxmmreg";
167343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen}
167443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
167543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
167643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansenconst char* NameConverter::NameInCode(byte* addr) const {
167743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // IA32 does not embed debug strings at the moment.
167843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  UNREACHABLE();
167943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  return "";
168043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen}
168143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
168243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
168343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen//------------------------------------------------------------------------------
168443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
168543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansenDisassembler::Disassembler(const NameConverter& converter)
168643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    : converter_(converter) {}
168743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
168843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
168943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansenDisassembler::~Disassembler() {}
169043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
169143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
1692b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.orgint Disassembler::InstructionDecode(v8::internal::Vector<char> buffer,
169343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen                                    byte* instruction) {
169443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  DisassemblerIA32 d(converter_, false /*do not crash if unimplemented*/);
1695b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org  return d.InstructionDecode(buffer, instruction);
169643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen}
169743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
169843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
16997276f14ca716596e0a0d17539516370c1f453847kasper.lund// The IA-32 assembler does not currently use constant pools.
17007276f14ca716596e0a0d17539516370c1f453847kasper.lundint Disassembler::ConstantPoolSizeAt(byte* instruction) { return -1; }
17017276f14ca716596e0a0d17539516370c1f453847kasper.lund
17027276f14ca716596e0a0d17539516370c1f453847kasper.lund
170343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen/*static*/ void Disassembler::Disassemble(FILE* f, byte* begin, byte* end) {
17043bf7b91c90e9bff46f53eec55055d2d1a1949215ager@chromium.org  NameConverter converter;
17053bf7b91c90e9bff46f53eec55055d2d1a1949215ager@chromium.org  Disassembler d(converter);
170643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  for (byte* pc = begin; pc < end;) {
1707b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org    v8::internal::EmbeddedVector<char, 128> buffer;
170843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    buffer[0] = '\0';
170943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    byte* prev_pc = pc;
1710b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org    pc += d.InstructionDecode(buffer, pc);
171143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    fprintf(f, "%p", prev_pc);
171243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    fprintf(f, "    ");
171343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
171443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    for (byte* bp = prev_pc; bp < pc; bp++) {
171543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      fprintf(f, "%02x",  *bp);
171643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    }
171743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    for (int i = 6 - (pc - prev_pc); i >= 0; i--) {
171843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      fprintf(f, "  ");
171943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    }
1720b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org    fprintf(f, "  %s\n", buffer.start());
172143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  }
172243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen}
172343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
172443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
172543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen}  // namespace disasm
17269dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
17279dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com#endif  // V8_TARGET_ARCH_IA32
1728