disasm-ia32.cc revision b8a8cc1952d61a2f3a2568848933943a543b5d3e
1257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// Copyright 2011 the V8 project authors. All rights reserved.
2b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Use of this source code is governed by a BSD-style license that can be
3b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// found in the LICENSE file.
4a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include <assert.h>
6a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include <stdarg.h>
7b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include <stdio.h>
8a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
9b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/v8.h"
10f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
11b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#if V8_TARGET_ARCH_IA32
12f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
13b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/disasm.h"
14a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
15a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace disasm {
16a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
17a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockenum OperandOrder {
18a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  UNSET_OP_ORDER = 0,
19a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  REG_OPER_OP_ORDER,
20a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  OPER_REG_OP_ORDER
21a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
22a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
23a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
24a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//------------------------------------------------------------------
25a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Tables
26a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//------------------------------------------------------------------
27a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstruct ByteMnemonic {
28a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int b;  // -1 terminates, otherwise must be in range (0..255)
29a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const char* mnem;
30a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  OperandOrder op_order_;
31a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
32a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
33a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdochstatic const ByteMnemonic two_operands_instr[] = {
353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  {0x01, "add", OPER_REG_OP_ORDER},
36a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  {0x03, "add", REG_OPER_OP_ORDER},
37a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  {0x09, "or", OPER_REG_OP_ORDER},
38a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  {0x0B, "or", REG_OPER_OP_ORDER},
39a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  {0x1B, "sbb", REG_OPER_OP_ORDER},
40d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  {0x21, "and", OPER_REG_OP_ORDER},
41d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  {0x23, "and", REG_OPER_OP_ORDER},
42a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  {0x29, "sub", OPER_REG_OP_ORDER},
43e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  {0x2A, "subb", REG_OPER_OP_ORDER},
44a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  {0x2B, "sub", REG_OPER_OP_ORDER},
45eab96aab0834f21954b5d6aa6366bcfb348ed811Leon Clarke  {0x31, "xor", OPER_REG_OP_ORDER},
46eab96aab0834f21954b5d6aa6366bcfb348ed811Leon Clarke  {0x33, "xor", REG_OPER_OP_ORDER},
47d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  {0x38, "cmpb", OPER_REG_OP_ORDER},
48d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  {0x3A, "cmpb", REG_OPER_OP_ORDER},
49d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  {0x3B, "cmp", REG_OPER_OP_ORDER},
50d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  {0x84, "test_b", REG_OPER_OP_ORDER},
51d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  {0x85, "test", REG_OPER_OP_ORDER},
52a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  {0x87, "xchg", REG_OPER_OP_ORDER},
53a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  {0x8A, "mov_b", REG_OPER_OP_ORDER},
54a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  {0x8B, "mov", REG_OPER_OP_ORDER},
55d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  {0x8D, "lea", REG_OPER_OP_ORDER},
56a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  {-1, "", UNSET_OP_ORDER}
57a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
58a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
59a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
6069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdochstatic const ByteMnemonic zero_operands_instr[] = {
61a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  {0xC3, "ret", UNSET_OP_ORDER},
62a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  {0xC9, "leave", UNSET_OP_ORDER},
63a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  {0x90, "nop", UNSET_OP_ORDER},
64a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  {0xF4, "hlt", UNSET_OP_ORDER},
65a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  {0xCC, "int3", UNSET_OP_ORDER},
66a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  {0x60, "pushad", UNSET_OP_ORDER},
67a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  {0x61, "popad", UNSET_OP_ORDER},
68a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  {0x9C, "pushfd", UNSET_OP_ORDER},
69a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  {0x9D, "popfd", UNSET_OP_ORDER},
70a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  {0x9E, "sahf", UNSET_OP_ORDER},
71a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  {0x99, "cdq", UNSET_OP_ORDER},
72a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  {0x9B, "fwait", UNSET_OP_ORDER},
736ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  {0xFC, "cld", UNSET_OP_ORDER},
74f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  {0xAB, "stos", UNSET_OP_ORDER},
75a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  {-1, "", UNSET_OP_ORDER}
76a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
77a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
78a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
7969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdochstatic const ByteMnemonic call_jump_instr[] = {
80a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  {0xE8, "call", UNSET_OP_ORDER},
81a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  {0xE9, "jmp", UNSET_OP_ORDER},
82a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  {-1, "", UNSET_OP_ORDER}
83a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
84a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
85a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
8669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdochstatic const ByteMnemonic short_immediate_instr[] = {
87a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  {0x05, "add", UNSET_OP_ORDER},
88a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  {0x0D, "or", UNSET_OP_ORDER},
89a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  {0x15, "adc", UNSET_OP_ORDER},
90a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  {0x25, "and", UNSET_OP_ORDER},
91a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  {0x2D, "sub", UNSET_OP_ORDER},
92a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  {0x35, "xor", UNSET_OP_ORDER},
93a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  {0x3D, "cmp", UNSET_OP_ORDER},
94a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  {-1, "", UNSET_OP_ORDER}
95a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
96a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
97a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// Generally we don't want to generate these because they are subject to partial
993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// register stalls.  They are included for completeness and because the cmp
1003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// variant is used by the RecordWrite stub.  Because it does not update the
1013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// register it is not subject to partial register stalls.
1023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochstatic ByteMnemonic byte_immediate_instr[] = {
1033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  {0x0c, "or", UNSET_OP_ORDER},
1043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  {0x24, "and", UNSET_OP_ORDER},
1053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  {0x34, "xor", UNSET_OP_ORDER},
1063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  {0x3c, "cmp", UNSET_OP_ORDER},
1073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  {-1, "", UNSET_OP_ORDER}
1083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch};
1093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
11169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdochstatic const char* const jump_conditional_mnem[] = {
112a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  /*0*/ "jo", "jno", "jc", "jnc",
113a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  /*4*/ "jz", "jnz", "jna", "ja",
114a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  /*8*/ "js", "jns", "jpe", "jpo",
115a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  /*12*/ "jl", "jnl", "jng", "jg"
116a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
117a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
118a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
11969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdochstatic const char* const set_conditional_mnem[] = {
120a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  /*0*/ "seto", "setno", "setc", "setnc",
121a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  /*4*/ "setz", "setnz", "setna", "seta",
122a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  /*8*/ "sets", "setns", "setpe", "setpo",
123a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  /*12*/ "setl", "setnl", "setng", "setg"
124a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
125a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
126a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
12769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdochstatic const char* const conditional_move_mnem[] = {
1283ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  /*0*/ "cmovo", "cmovno", "cmovc", "cmovnc",
1293ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  /*4*/ "cmovz", "cmovnz", "cmovna", "cmova",
1303ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  /*8*/ "cmovs", "cmovns", "cmovpe", "cmovpo",
1313ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  /*12*/ "cmovl", "cmovnl", "cmovng", "cmovg"
1323ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block};
1333ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
1343ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
135a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockenum InstructionType {
136a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  NO_INSTR,
137a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ZERO_OPERANDS_INSTR,
138a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  TWO_OPERANDS_INSTR,
139a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  JUMP_CONDITIONAL_SHORT_INSTR,
140a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  REGISTER_INSTR,
141a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  MOVE_REG_INSTR,
142a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CALL_JUMP_INSTR,
1433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  SHORT_IMMEDIATE_INSTR,
1443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  BYTE_IMMEDIATE_INSTR
145a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
146a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
147a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
148a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstruct InstructionDesc {
149a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const char* mnem;
150a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  InstructionType type;
151a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  OperandOrder op_order_;
152a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
153a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
154a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
155a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass InstructionTable {
156a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public:
157a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  InstructionTable();
158a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const InstructionDesc& Get(byte x) const { return instructions_[x]; }
1593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  static InstructionTable* get_instance() {
1603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    static InstructionTable table;
1613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return &table;
1623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
163a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
164a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private:
165a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  InstructionDesc instructions_[256];
166a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void Clear();
167a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void Init();
16869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  void CopyTable(const ByteMnemonic bm[], InstructionType type);
169a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void SetTableRange(InstructionType type,
170a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                     byte start,
171a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                     byte end,
172a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                     const char* mnem);
173a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void AddJumpConditionalShort();
174a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
175a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
176a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
177a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockInstructionTable::InstructionTable() {
178a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Clear();
179a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Init();
180a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
181a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
182a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
183a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid InstructionTable::Clear() {
184a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (int i = 0; i < 256; i++) {
185a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    instructions_[i].mnem = "";
186a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    instructions_[i].type = NO_INSTR;
187a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    instructions_[i].op_order_ = UNSET_OP_ORDER;
188a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
189a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
190a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
191a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
192a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid InstructionTable::Init() {
193a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CopyTable(two_operands_instr, TWO_OPERANDS_INSTR);
194a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CopyTable(zero_operands_instr, ZERO_OPERANDS_INSTR);
195a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CopyTable(call_jump_instr, CALL_JUMP_INSTR);
196a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CopyTable(short_immediate_instr, SHORT_IMMEDIATE_INSTR);
1973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CopyTable(byte_immediate_instr, BYTE_IMMEDIATE_INSTR);
198a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  AddJumpConditionalShort();
199a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  SetTableRange(REGISTER_INSTR, 0x40, 0x47, "inc");
200a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  SetTableRange(REGISTER_INSTR, 0x48, 0x4F, "dec");
201a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  SetTableRange(REGISTER_INSTR, 0x50, 0x57, "push");
202a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  SetTableRange(REGISTER_INSTR, 0x58, 0x5F, "pop");
203a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  SetTableRange(REGISTER_INSTR, 0x91, 0x97, "xchg eax,");  // 0x90 is nop.
204a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  SetTableRange(MOVE_REG_INSTR, 0xB8, 0xBF, "mov");
205a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
206a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
207a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
20869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdochvoid InstructionTable::CopyTable(const ByteMnemonic bm[],
20969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch                                 InstructionType type) {
210a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (int i = 0; bm[i].b >= 0; i++) {
211a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    InstructionDesc* id = &instructions_[bm[i].b];
212a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    id->mnem = bm[i].mnem;
213a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    id->op_order_ = bm[i].op_order_;
214b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK_EQ(NO_INSTR, id->type);  // Information not already entered.
215a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    id->type = type;
216a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
217a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
218a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
219a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
220a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid InstructionTable::SetTableRange(InstructionType type,
221a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                     byte start,
222a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                     byte end,
223a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                     const char* mnem) {
224a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (byte b = start; b <= end; b++) {
225a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    InstructionDesc* id = &instructions_[b];
226b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK_EQ(NO_INSTR, id->type);  // Information not already entered.
227a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    id->mnem = mnem;
228a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    id->type = type;
229a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
230a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
231a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
232a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
233a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid InstructionTable::AddJumpConditionalShort() {
234a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (byte b = 0x70; b <= 0x7F; b++) {
235a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    InstructionDesc* id = &instructions_[b];
236b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK_EQ(NO_INSTR, id->type);  // Information not already entered.
237a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    id->mnem = jump_conditional_mnem[b & 0x0F];
238a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    id->type = JUMP_CONDITIONAL_SHORT_INSTR;
239a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
240a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
241a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
242a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
243a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// The IA32 disassembler implementation.
244a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass DisassemblerIA32 {
245a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public:
246a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  DisassemblerIA32(const NameConverter& converter,
247a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                   bool abort_on_unimplemented = true)
248a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      : converter_(converter),
2493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        instruction_table_(InstructionTable::get_instance()),
250a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        tmp_buffer_pos_(0),
251a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        abort_on_unimplemented_(abort_on_unimplemented) {
252a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    tmp_buffer_[0] = '\0';
253a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
254a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
255a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  virtual ~DisassemblerIA32() {}
256a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
257a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Writes one disassembled instruction into 'buffer' (0-terminated).
258a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Returns the length of the disassembled machine instruction in bytes.
259a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int InstructionDecode(v8::internal::Vector<char> buffer, byte* instruction);
260a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
261a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private:
262a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const NameConverter& converter_;
2633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  InstructionTable* instruction_table_;
264a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::internal::EmbeddedVector<char, 128> tmp_buffer_;
265a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  unsigned int tmp_buffer_pos_;
266a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bool abort_on_unimplemented_;
267a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
268a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  enum {
269a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    eax = 0,
270a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ecx = 1,
271a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    edx = 2,
272a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ebx = 3,
273a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    esp = 4,
274a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ebp = 5,
275a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    esi = 6,
276a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    edi = 7
277a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  };
278a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
279a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
280d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  enum ShiftOpcodeExtension {
281d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    kROL = 0,
282d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    kROR = 1,
283d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    kRCL = 2,
284d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    kRCR = 3,
285d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    kSHL = 4,
286d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    KSHR = 5,
287d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    kSAR = 7
288d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  };
289d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
290d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
291a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const char* NameOfCPURegister(int reg) const {
292a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return converter_.NameOfCPURegister(reg);
293a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
294a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
295a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
296a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const char* NameOfByteCPURegister(int reg) const {
297a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return converter_.NameOfByteCPURegister(reg);
298a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
299a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
300a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
301a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const char* NameOfXMMRegister(int reg) const {
302a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return converter_.NameOfXMMRegister(reg);
303a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
304a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
305a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
306a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const char* NameOfAddress(byte* addr) const {
307a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return converter_.NameOfAddress(addr);
308a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
309a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
310a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
311a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Disassembler helper functions.
312a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  static void get_modrm(byte data, int* mod, int* regop, int* rm) {
313a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    *mod = (data >> 6) & 3;
314a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    *regop = (data & 0x38) >> 3;
315a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    *rm = data & 7;
316a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
317a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
318a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
319a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  static void get_sib(byte data, int* scale, int* index, int* base) {
320a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    *scale = (data >> 6) & 3;
321a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    *index = (data >> 3) & 7;
322a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    *base = data & 7;
323a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
324a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
325a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  typedef const char* (DisassemblerIA32::*RegisterNameMapping)(int reg) const;
326a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
327a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int PrintRightOperandHelper(byte* modrmp, RegisterNameMapping register_name);
328a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int PrintRightOperand(byte* modrmp);
329a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int PrintRightByteOperand(byte* modrmp);
33044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  int PrintRightXMMOperand(byte* modrmp);
331a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int PrintOperands(const char* mnem, OperandOrder op_order, byte* data);
332a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int PrintImmediateOp(byte* data);
333a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int F7Instruction(byte* data);
334a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int D1D3C1Instruction(byte* data);
335a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int JumpShort(byte* data);
336a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int JumpConditional(byte* data, const char* comment);
337a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int JumpConditionalShort(byte* data, const char* comment);
338a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int SetCC(byte* data);
3393ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  int CMov(byte* data);
340a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int FPUInstruction(byte* data);
341d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  int MemoryFPUInstruction(int escape_opcode, int regop, byte* modrm_start);
342d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  int RegisterFPUInstruction(int escape_opcode, byte modrm_byte);
343a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void AppendToBuffer(const char* format, ...);
344a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
345a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
346a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void UnimplementedInstruction() {
347a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (abort_on_unimplemented_) {
348a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      UNIMPLEMENTED();
349a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    } else {
350a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      AppendToBuffer("'Unimplemented Instruction'");
351a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
352a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
353a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
354a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
355a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
356a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid DisassemblerIA32::AppendToBuffer(const char* format, ...) {
357a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::internal::Vector<char> buf = tmp_buffer_ + tmp_buffer_pos_;
358a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  va_list args;
359a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  va_start(args, format);
360b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int result = v8::internal::VSNPrintF(buf, format, args);
361a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  va_end(args);
362a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  tmp_buffer_pos_ += result;
363a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
364a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
365a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint DisassemblerIA32::PrintRightOperandHelper(
366a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    byte* modrmp,
36744f0eee88ff00398ff7f715fab053374d808c90dSteve Block    RegisterNameMapping direct_register_name) {
368a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int mod, regop, rm;
369a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  get_modrm(*modrmp, &mod, &regop, &rm);
37044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  RegisterNameMapping register_name = (mod == 3) ? direct_register_name :
37144f0eee88ff00398ff7f715fab053374d808c90dSteve Block      &DisassemblerIA32::NameOfCPURegister;
372a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  switch (mod) {
373a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case 0:
374a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      if (rm == ebp) {
375a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        int32_t disp = *reinterpret_cast<int32_t*>(modrmp+1);
376a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        AppendToBuffer("[0x%x]", disp);
377a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        return 5;
378a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      } else if (rm == esp) {
379a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        byte sib = *(modrmp + 1);
380a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        int scale, index, base;
381a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        get_sib(sib, &scale, &index, &base);
382a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        if (index == esp && base == esp && scale == 0 /*times_1*/) {
383a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          AppendToBuffer("[%s]", (this->*register_name)(rm));
384a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          return 2;
385a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        } else if (base == ebp) {
386a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          int32_t disp = *reinterpret_cast<int32_t*>(modrmp + 2);
387b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          AppendToBuffer("[%s*%d%s0x%x]",
388a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                         (this->*register_name)(index),
389a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                         1 << scale,
390b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                         disp < 0 ? "-" : "+",
391b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                         disp < 0 ? -disp : disp);
392a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          return 6;
393a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        } else if (index != esp && base != ebp) {
394a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          // [base+index*scale]
395a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          AppendToBuffer("[%s+%s*%d]",
396a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                         (this->*register_name)(base),
397a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                         (this->*register_name)(index),
398a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                         1 << scale);
399a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          return 2;
400a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        } else {
401a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          UnimplementedInstruction();
402a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          return 1;
403a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        }
404a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      } else {
405a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        AppendToBuffer("[%s]", (this->*register_name)(rm));
406a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        return 1;
407a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
408a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      break;
409a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case 1:  // fall through
410a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case 2:
411a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      if (rm == esp) {
412a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        byte sib = *(modrmp + 1);
413a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        int scale, index, base;
414a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        get_sib(sib, &scale, &index, &base);
415b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        int disp = mod == 2 ? *reinterpret_cast<int32_t*>(modrmp + 2)
416b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                            : *reinterpret_cast<int8_t*>(modrmp + 2);
417a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        if (index == base && index == rm /*esp*/ && scale == 0 /*times_1*/) {
418b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          AppendToBuffer("[%s%s0x%x]",
419b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                         (this->*register_name)(rm),
420b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                         disp < 0 ? "-" : "+",
421b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                         disp < 0 ? -disp : disp);
422a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        } else {
423b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          AppendToBuffer("[%s+%s*%d%s0x%x]",
424a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                         (this->*register_name)(base),
425a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                         (this->*register_name)(index),
426a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                         1 << scale,
427b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                         disp < 0 ? "-" : "+",
428b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                         disp < 0 ? -disp : disp);
429a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        }
430a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        return mod == 2 ? 6 : 3;
431a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      } else {
432a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        // No sib.
433b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        int disp = mod == 2 ? *reinterpret_cast<int32_t*>(modrmp + 1)
434b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                            : *reinterpret_cast<int8_t*>(modrmp + 1);
435b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        AppendToBuffer("[%s%s0x%x]",
436b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                       (this->*register_name)(rm),
437b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                       disp < 0 ? "-" : "+",
438b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                       disp < 0 ? -disp : disp);
439a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        return mod == 2 ? 5 : 2;
440a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
441a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      break;
442a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case 3:
443a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      AppendToBuffer("%s", (this->*register_name)(rm));
444a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      return 1;
445a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    default:
446a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      UnimplementedInstruction();
447a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      return 1;
448a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
449a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  UNREACHABLE();
450a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
451a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
452a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
453a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint DisassemblerIA32::PrintRightOperand(byte* modrmp) {
454a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return PrintRightOperandHelper(modrmp, &DisassemblerIA32::NameOfCPURegister);
455a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
456a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
457a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
458a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint DisassemblerIA32::PrintRightByteOperand(byte* modrmp) {
459a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return PrintRightOperandHelper(modrmp,
460a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                 &DisassemblerIA32::NameOfByteCPURegister);
461a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
462a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
463a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
46444f0eee88ff00398ff7f715fab053374d808c90dSteve Blockint DisassemblerIA32::PrintRightXMMOperand(byte* modrmp) {
46544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  return PrintRightOperandHelper(modrmp,
46644f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                 &DisassemblerIA32::NameOfXMMRegister);
46744f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
46844f0eee88ff00398ff7f715fab053374d808c90dSteve Block
46944f0eee88ff00398ff7f715fab053374d808c90dSteve Block
470a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Returns number of bytes used including the current *data.
471a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Writes instruction's mnemonic, left and right operands to 'tmp_buffer_'.
472a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint DisassemblerIA32::PrintOperands(const char* mnem,
473a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                    OperandOrder op_order,
474a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                    byte* data) {
475a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  byte modrm = *data;
476a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int mod, regop, rm;
477a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  get_modrm(modrm, &mod, &regop, &rm);
478a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int advance = 0;
479a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  switch (op_order) {
480a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case REG_OPER_OP_ORDER: {
481a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      AppendToBuffer("%s %s,", mnem, NameOfCPURegister(regop));
482a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      advance = PrintRightOperand(data);
483a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      break;
484a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
485a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case OPER_REG_OP_ORDER: {
486a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      AppendToBuffer("%s ", mnem);
487a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      advance = PrintRightOperand(data);
488a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      AppendToBuffer(",%s", NameOfCPURegister(regop));
489a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      break;
490a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
491a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    default:
492a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      UNREACHABLE();
493a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      break;
494a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
495a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return advance;
496a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
497a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
498a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
499a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Returns number of bytes used by machine instruction, including *data byte.
500a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Writes immediate instructions to 'tmp_buffer_'.
501a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint DisassemblerIA32::PrintImmediateOp(byte* data) {
502a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bool sign_extension_bit = (*data & 0x02) != 0;
503a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  byte modrm = *(data+1);
504a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int mod, regop, rm;
505a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  get_modrm(modrm, &mod, &regop, &rm);
506a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const char* mnem = "Imm???";
507a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  switch (regop) {
508a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case 0: mnem = "add"; break;
509a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case 1: mnem = "or"; break;
510a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case 2: mnem = "adc"; break;
511a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case 4: mnem = "and"; break;
512a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case 5: mnem = "sub"; break;
513a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case 6: mnem = "xor"; break;
514a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case 7: mnem = "cmp"; break;
515a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    default: UnimplementedInstruction();
516a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
517a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  AppendToBuffer("%s ", mnem);
518a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int count = PrintRightOperand(data+1);
519a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (sign_extension_bit) {
520a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    AppendToBuffer(",0x%x", *(data + 1 + count));
521a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return 1 + count + 1 /*int8*/;
522a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
523a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    AppendToBuffer(",0x%x", *reinterpret_cast<int32_t*>(data + 1 + count));
524a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return 1 + count + 4 /*int32_t*/;
525a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
526a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
527a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
528a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
529a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Returns number of bytes used, including *data.
530a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint DisassemblerIA32::F7Instruction(byte* data) {
531b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK_EQ(0xF7, *data);
532b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  byte modrm = *++data;
533a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int mod, regop, rm;
534a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  get_modrm(modrm, &mod, &regop, &rm);
535b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  const char* mnem = NULL;
536b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  switch (regop) {
537b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case 0:
538b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      mnem = "test";
539b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
540b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case 2:
541b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      mnem = "not";
542b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
543b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case 3:
544b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      mnem = "neg";
545b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
546b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case 4:
547b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      mnem = "mul";
548b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
549b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case 5:
550b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      mnem = "imul";
551b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
552b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case 6:
553b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      mnem = "div";
554b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
555b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case 7:
556b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      mnem = "idiv";
557b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
558b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    default:
559b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      UnimplementedInstruction();
560a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
561b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  AppendToBuffer("%s ", mnem);
562b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int count = PrintRightOperand(data);
563b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (regop == 0) {
564b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    AppendToBuffer(",0x%x", *reinterpret_cast<int32_t*>(data + count));
565b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    count += 4;
566b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
567b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return 1 + count;
568a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
569a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
570b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
571a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint DisassemblerIA32::D1D3C1Instruction(byte* data) {
572a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  byte op = *data;
573b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(op == 0xD1 || op == 0xD3 || op == 0xC1);
574b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  byte modrm = *++data;
575a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int mod, regop, rm;
576a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  get_modrm(modrm, &mod, &regop, &rm);
577a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int imm8 = -1;
578b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  const char* mnem = NULL;
579b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  switch (regop) {
580b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case kROL:
581b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      mnem = "rol";
582b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
583b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case kROR:
584b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      mnem = "ror";
585b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
586b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case kRCL:
587b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      mnem = "rcl";
588b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
589b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case kRCR:
590b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      mnem = "rcr";
591b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
592b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case kSHL:
593b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      mnem = "shl";
594b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
595b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case KSHR:
596b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      mnem = "shr";
597b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
598b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case kSAR:
599b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      mnem = "sar";
600b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
601b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    default:
602b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      UnimplementedInstruction();
603b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
604b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  AppendToBuffer("%s ", mnem);
605b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int count = PrintRightOperand(data);
606b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (op == 0xD1) {
607b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    imm8 = 1;
608b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else if (op == 0xC1) {
609b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    imm8 = *(data + 1);
610b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    count++;
611b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else if (op == 0xD3) {
612b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Shift/rotate by cl.
613b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
614b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (imm8 >= 0) {
615b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    AppendToBuffer(",%d", imm8);
616a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
617b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    AppendToBuffer(",cl");
618a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
619b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return 1 + count;
620a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
621a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
622a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
623a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Returns number of bytes used, including *data.
624a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint DisassemblerIA32::JumpShort(byte* data) {
625b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK_EQ(0xEB, *data);
626a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  byte b = *(data+1);
627a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  byte* dest = data + static_cast<int8_t>(b) + 2;
628a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  AppendToBuffer("jmp %s", NameOfAddress(dest));
629a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return 2;
630a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
631a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
632a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
633a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Returns number of bytes used, including *data.
634a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint DisassemblerIA32::JumpConditional(byte* data, const char* comment) {
635b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK_EQ(0x0F, *data);
636a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  byte cond = *(data+1) & 0x0F;
637a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  byte* dest = data + *reinterpret_cast<int32_t*>(data+2) + 6;
638a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const char* mnem = jump_conditional_mnem[cond];
639a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  AppendToBuffer("%s %s", mnem, NameOfAddress(dest));
640a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (comment != NULL) {
641a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    AppendToBuffer(", %s", comment);
642a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
643a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return 6;  // includes 0x0F
644a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
645a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
646a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
647a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Returns number of bytes used, including *data.
648a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint DisassemblerIA32::JumpConditionalShort(byte* data, const char* comment) {
649a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  byte cond = *data & 0x0F;
650a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  byte b = *(data+1);
651a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  byte* dest = data + static_cast<int8_t>(b) + 2;
652a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const char* mnem = jump_conditional_mnem[cond];
653a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  AppendToBuffer("%s %s", mnem, NameOfAddress(dest));
654a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (comment != NULL) {
655a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    AppendToBuffer(", %s", comment);
656a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
657a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return 2;
658a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
659a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
660a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
661a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Returns number of bytes used, including *data.
662a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint DisassemblerIA32::SetCC(byte* data) {
663b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK_EQ(0x0F, *data);
664a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  byte cond = *(data+1) & 0x0F;
665a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const char* mnem = set_conditional_mnem[cond];
666a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  AppendToBuffer("%s ", mnem);
667a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  PrintRightByteOperand(data+2);
668d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  return 3;  // Includes 0x0F.
669a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
670a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
671a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
672a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Returns number of bytes used, including *data.
6733ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockint DisassemblerIA32::CMov(byte* data) {
674b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK_EQ(0x0F, *data);
6753ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  byte cond = *(data + 1) & 0x0F;
6763ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  const char* mnem = conditional_move_mnem[cond];
6773ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  int op_size = PrintOperands(mnem, REG_OPER_OP_ORDER, data + 2);
6783ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  return 2 + op_size;  // includes 0x0F
6793ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
6803ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
6813ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
6823ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// Returns number of bytes used, including *data.
683a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint DisassemblerIA32::FPUInstruction(byte* data) {
684d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  byte escape_opcode = *data;
685b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK_EQ(0xD8, escape_opcode & 0xF8);
686d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  byte modrm_byte = *(data+1);
687d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
688d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  if (modrm_byte >= 0xC0) {
689d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    return RegisterFPUInstruction(escape_opcode, modrm_byte);
690d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  } else {
691d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    return MemoryFPUInstruction(escape_opcode, modrm_byte, data+1);
692d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
693d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
694d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
695d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockint DisassemblerIA32::MemoryFPUInstruction(int escape_opcode,
696d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                                           int modrm_byte,
697d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                                           byte* modrm_start) {
698d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  const char* mnem = "?";
699d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  int regop = (modrm_byte >> 3) & 0x7;  // reg/op field of modrm byte.
700d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  switch (escape_opcode) {
701d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case 0xD9: switch (regop) {
702d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        case 0: mnem = "fld_s"; break;
703b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        case 2: mnem = "fst_s"; break;
704d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        case 3: mnem = "fstp_s"; break;
705d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        case 7: mnem = "fstcw"; break;
706a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        default: UnimplementedInstruction();
707a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
708d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
709d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
710d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case 0xDB: switch (regop) {
711d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        case 0: mnem = "fild_s"; break;
712d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        case 1: mnem = "fisttp_s"; break;
713d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        case 2: mnem = "fist_s"; break;
714d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        case 3: mnem = "fistp_s"; break;
715a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        default: UnimplementedInstruction();
716a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
717d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
718d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
719d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case 0xDD: switch (regop) {
720d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        case 0: mnem = "fld_d"; break;
7210d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        case 1: mnem = "fisttp_d"; break;
7220d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        case 2: mnem = "fst_d"; break;
723d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        case 3: mnem = "fstp_d"; break;
724d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        default: UnimplementedInstruction();
725d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      }
726d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
727d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
728d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case 0xDF: switch (regop) {
729d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        case 5: mnem = "fild_d"; break;
730d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        case 7: mnem = "fistp_d"; break;
731d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        default: UnimplementedInstruction();
732d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      }
733d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
734d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
735d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    default: UnimplementedInstruction();
736d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
737d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  AppendToBuffer("%s ", mnem);
738d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  int count = PrintRightOperand(modrm_start);
739d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  return count + 1;
740d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
741d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
742d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockint DisassemblerIA32::RegisterFPUInstruction(int escape_opcode,
743d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                                             byte modrm_byte) {
744d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  bool has_register = false;  // Is the FPU register encoded in modrm_byte?
745d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  const char* mnem = "?";
746d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
747d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  switch (escape_opcode) {
748d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case 0xD8:
749b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      has_register = true;
750b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      switch (modrm_byte & 0xF8) {
751b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        case 0xC0: mnem = "fadd_i"; break;
752b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        case 0xE0: mnem = "fsub_i"; break;
753b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        case 0xC8: mnem = "fmul_i"; break;
754b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        case 0xF0: mnem = "fdiv_i"; break;
755b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        default: UnimplementedInstruction();
756b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
757d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
758d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
759d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case 0xD9:
760d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      switch (modrm_byte & 0xF8) {
7610d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        case 0xC0:
7620d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          mnem = "fld";
7630d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          has_register = true;
7640d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          break;
765d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        case 0xC8:
766d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          mnem = "fxch";
767d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          has_register = true;
768d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          break;
769d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        default:
770d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          switch (modrm_byte) {
771d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block            case 0xE0: mnem = "fchs"; break;
772d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block            case 0xE1: mnem = "fabs"; break;
773d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block            case 0xE4: mnem = "ftst"; break;
774d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block            case 0xE8: mnem = "fld1"; break;
775402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu            case 0xEB: mnem = "fldpi"; break;
776b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            case 0xED: mnem = "fldln2"; break;
777d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block            case 0xEE: mnem = "fldz"; break;
7783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            case 0xF0: mnem = "f2xm1"; break;
779b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            case 0xF1: mnem = "fyl2x"; break;
780b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            case 0xF4: mnem = "fxtract"; break;
781d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block            case 0xF5: mnem = "fprem1"; break;
782d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block            case 0xF7: mnem = "fincstp"; break;
783d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block            case 0xF8: mnem = "fprem"; break;
7843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            case 0xFC: mnem = "frndint"; break;
7853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            case 0xFD: mnem = "fscale"; break;
786d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block            case 0xFE: mnem = "fsin"; break;
787d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block            case 0xFF: mnem = "fcos"; break;
788d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block            default: UnimplementedInstruction();
789d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          }
790d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      }
791d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
792d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
793d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case 0xDA:
794d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      if (modrm_byte == 0xE9) {
795d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        mnem = "fucompp";
796d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      } else {
797d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        UnimplementedInstruction();
798d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      }
799d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
800d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
801d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case 0xDB:
802d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      if ((modrm_byte & 0xF8) == 0xE8) {
803d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        mnem = "fucomi";
804d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        has_register = true;
805d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      } else if (modrm_byte  == 0xE2) {
806d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        mnem = "fclex";
8073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      } else if (modrm_byte == 0xE3) {
8083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        mnem = "fninit";
809d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      } else {
810d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        UnimplementedInstruction();
811d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      }
812d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
813d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
814d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case 0xDC:
815d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      has_register = true;
816d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      switch (modrm_byte & 0xF8) {
817d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        case 0xC0: mnem = "fadd"; break;
818d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        case 0xE8: mnem = "fsub"; break;
819d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        case 0xC8: mnem = "fmul"; break;
820d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        case 0xF8: mnem = "fdiv"; break;
821d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        default: UnimplementedInstruction();
822d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      }
823d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
824d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
825d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case 0xDD:
826d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      has_register = true;
827d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      switch (modrm_byte & 0xF8) {
828d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        case 0xC0: mnem = "ffree"; break;
829b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        case 0xD0: mnem = "fst"; break;
830d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        case 0xD8: mnem = "fstp"; break;
831d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        default: UnimplementedInstruction();
832d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      }
833d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
834d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
835d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case 0xDE:
836d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      if (modrm_byte  == 0xD9) {
837d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        mnem = "fcompp";
838d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      } else {
839d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        has_register = true;
840d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        switch (modrm_byte & 0xF8) {
841d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          case 0xC0: mnem = "faddp"; break;
842d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          case 0xE8: mnem = "fsubp"; break;
843d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          case 0xC8: mnem = "fmulp"; break;
844d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          case 0xF8: mnem = "fdivp"; break;
845d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          default: UnimplementedInstruction();
846d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        }
847d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      }
848d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
849d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
850d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case 0xDF:
851d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      if (modrm_byte == 0xE0) {
852d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        mnem = "fnstsw_ax";
853d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      } else if ((modrm_byte & 0xF8) == 0xE8) {
854d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        mnem = "fucomip";
855d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        has_register = true;
856d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      }
857d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
858d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
859d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    default: UnimplementedInstruction();
860d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
861d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
862d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  if (has_register) {
863d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    AppendToBuffer("%s st%d", mnem, modrm_byte & 0x7);
864d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  } else {
865a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    AppendToBuffer("%s", mnem);
866a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
867a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return 2;
868a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
869a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
870a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
871a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Mnemonics for instructions 0xF0 byte.
872a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Returns NULL if the instruction is not handled here.
873a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic const char* F0Mnem(byte f0byte) {
874a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  switch (f0byte) {
8757f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    case 0x18: return "prefetch";
876a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case 0xA2: return "cpuid";
877a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case 0xBE: return "movsx_b";
878a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case 0xBF: return "movsx_w";
879a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case 0xB6: return "movzx_b";
880a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case 0xB7: return "movzx_w";
881a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case 0xAF: return "imul";
882a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case 0xA5: return "shld";
883a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case 0xAD: return "shrd";
884b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case 0xAC: return "shrd";  // 3-operand version.
885a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case 0xAB: return "bts";
886b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case 0xBD: return "bsr";
887a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    default: return NULL;
888a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
889a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
890a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
891a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
892a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Disassembled instruction '*instr' and writes it into 'out_buffer'.
893a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint DisassemblerIA32::InstructionDecode(v8::internal::Vector<char> out_buffer,
894a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                        byte* instr) {
895a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  tmp_buffer_pos_ = 0;  // starting to write as position 0
896a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  byte* data = instr;
897a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check for hints.
898a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const char* branch_hint = NULL;
899a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // We use these two prefixes only with branch prediction
900a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (*data == 0x3E /*ds*/) {
901a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    branch_hint = "predicted taken";
902a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    data++;
903a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else if (*data == 0x2E /*cs*/) {
904a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    branch_hint = "predicted not taken";
905a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    data++;
906a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
907a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bool processed = true;  // Will be set to false if the current instruction
908a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                          // is not in 'instructions' table.
9093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  const InstructionDesc& idesc = instruction_table_->Get(*data);
910a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  switch (idesc.type) {
911a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case ZERO_OPERANDS_INSTR:
912a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      AppendToBuffer(idesc.mnem);
913a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      data++;
914a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      break;
915a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
916a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case TWO_OPERANDS_INSTR:
917a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      data++;
918a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      data += PrintOperands(idesc.mnem, idesc.op_order_, data);
919a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      break;
920a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
921a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case JUMP_CONDITIONAL_SHORT_INSTR:
922a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      data += JumpConditionalShort(data, branch_hint);
923a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      break;
924a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
925a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case REGISTER_INSTR:
926a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      AppendToBuffer("%s %s", idesc.mnem, NameOfCPURegister(*data & 0x07));
927a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      data++;
928a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      break;
929a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
930a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case MOVE_REG_INSTR: {
931a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      byte* addr = reinterpret_cast<byte*>(*reinterpret_cast<int32_t*>(data+1));
932a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      AppendToBuffer("mov %s,%s",
933a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                     NameOfCPURegister(*data & 0x07),
934a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                     NameOfAddress(addr));
935a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      data += 5;
936a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      break;
937a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
938a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
939a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case CALL_JUMP_INSTR: {
940a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      byte* addr = data + *reinterpret_cast<int32_t*>(data+1) + 5;
941a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      AppendToBuffer("%s %s", idesc.mnem, NameOfAddress(addr));
942a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      data += 5;
943a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      break;
944a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
945a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
946a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case SHORT_IMMEDIATE_INSTR: {
947a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      byte* addr = reinterpret_cast<byte*>(*reinterpret_cast<int32_t*>(data+1));
948b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      AppendToBuffer("%s eax,%s", idesc.mnem, NameOfAddress(addr));
949a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      data += 5;
950a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      break;
951a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
952a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
9533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    case BYTE_IMMEDIATE_INSTR: {
954b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      AppendToBuffer("%s al,0x%x", idesc.mnem, data[1]);
9553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      data += 2;
9563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      break;
9573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
9583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
959a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case NO_INSTR:
960a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      processed = false;
961a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      break;
962a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
963a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    default:
964a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      UNIMPLEMENTED();  // This type is not implemented.
965a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
966a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //----------------------------
967a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (!processed) {
968a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    switch (*data) {
969a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 0xC2:
970a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        AppendToBuffer("ret 0x%x", *reinterpret_cast<uint16_t*>(data+1));
971a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        data += 3;
972a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
973a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
974b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case 0x6B: {
975b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        data++;
976b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        data += PrintOperands("imul", REG_OPER_OP_ORDER, data);
977b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        AppendToBuffer(",%d", *data);
978b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        data++;
979b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      } break;
980b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
981b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case 0x69: {
982b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        data++;
983b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        data += PrintOperands("imul", REG_OPER_OP_ORDER, data);
984b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        AppendToBuffer(",%d", *reinterpret_cast<int32_t*>(data));
985b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        data += 4;
986a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        }
987a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
988a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
989a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 0xF6:
9907f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch        { data++;
9917f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch          int mod, regop, rm;
9927f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch          get_modrm(*data, &mod, &regop, &rm);
9937f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch          if (regop == eax) {
9947f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch            AppendToBuffer("test_b ");
99544f0eee88ff00398ff7f715fab053374d808c90dSteve Block            data += PrintRightByteOperand(data);
9967f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch            int32_t imm = *data;
9977f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch            AppendToBuffer(",0x%x", imm);
9987f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch            data++;
999a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          } else {
1000a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            UnimplementedInstruction();
1001a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          }
1002a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        }
1003a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
1004a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1005a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 0x81:  // fall through
1006a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 0x83:  // 0x81 with sign extension bit set
1007a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        data += PrintImmediateOp(data);
1008a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
1009a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1010a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 0x0F:
10113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        { byte f0byte = data[1];
1012a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          const char* f0mnem = F0Mnem(f0byte);
10137f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch          if (f0byte == 0x18) {
1014b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            data += 2;
10157f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch            int mod, regop, rm;
10167f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch            get_modrm(*data, &mod, &regop, &rm);
10177f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch            const char* suffix[] = {"nta", "1", "2", "3"};
10187f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch            AppendToBuffer("%s%s ", f0mnem, suffix[regop & 0x03]);
10197f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch            data += PrintRightOperand(data);
10203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          } else if (f0byte == 0x1F && data[2] == 0) {
10213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            AppendToBuffer("nop");  // 3 byte nop.
10223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            data += 3;
10233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          } else if (f0byte == 0x1F && data[2] == 0x40 && data[3] == 0) {
10243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            AppendToBuffer("nop");  // 4 byte nop.
10253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            data += 4;
10263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          } else if (f0byte == 0x1F && data[2] == 0x44 && data[3] == 0 &&
10273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                     data[4] == 0) {
10283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            AppendToBuffer("nop");  // 5 byte nop.
10293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            data += 5;
10303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          } else if (f0byte == 0x1F && data[2] == 0x80 && data[3] == 0 &&
10313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                     data[4] == 0 && data[5] == 0 && data[6] == 0) {
10323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            AppendToBuffer("nop");  // 7 byte nop.
10333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            data += 7;
10343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          } else if (f0byte == 0x1F && data[2] == 0x84 && data[3] == 0 &&
10353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                     data[4] == 0 && data[5] == 0 && data[6] == 0 &&
10363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                     data[7] == 0) {
10373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            AppendToBuffer("nop");  // 8 byte nop.
10383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            data += 8;
10397f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch          } else if (f0byte == 0xA2 || f0byte == 0x31) {
1040a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            AppendToBuffer("%s", f0mnem);
1041a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            data += 2;
10420d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          } else if (f0byte == 0x28) {
10430d5e116f6aee03185f237311a943491bb079a768Kristian Monsen            data += 2;
10440d5e116f6aee03185f237311a943491bb079a768Kristian Monsen            int mod, regop, rm;
10450d5e116f6aee03185f237311a943491bb079a768Kristian Monsen            get_modrm(*data, &mod, &regop, &rm);
10460d5e116f6aee03185f237311a943491bb079a768Kristian Monsen            AppendToBuffer("movaps %s,%s",
10470d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                           NameOfXMMRegister(regop),
10480d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                           NameOfXMMRegister(rm));
10490d5e116f6aee03185f237311a943491bb079a768Kristian Monsen            data++;
1050b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          } else if (f0byte >= 0x53 && f0byte <= 0x5F) {
1051b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            const char* const pseudo_op[] = {
1052b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch              "rcpps",
1053b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch              "andps",
1054b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch              "andnps",
1055b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch              "orps",
1056b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch              "xorps",
1057b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch              "addps",
1058b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch              "mulps",
1059b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch              "cvtps2pd",
1060b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch              "cvtdq2ps",
1061b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch              "subps",
1062b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch              "minps",
1063b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch              "divps",
1064b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch              "maxps",
1065b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            };
1066b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1067257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch            data += 2;
1068257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch            int mod, regop, rm;
1069257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch            get_modrm(*data, &mod, &regop, &rm);
1070b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            AppendToBuffer("%s %s,",
1071b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                           pseudo_op[f0byte - 0x53],
1072b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                           NameOfXMMRegister(regop));
1073b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            data += PrintRightXMMOperand(data);
1074b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          } else if (f0byte == 0x50) {
1075b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            data += 2;
1076b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            int mod, regop, rm;
1077b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            get_modrm(*data, &mod, &regop, &rm);
1078b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            AppendToBuffer("movmskps %s,%s",
1079b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                           NameOfCPURegister(regop),
1080257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                           NameOfXMMRegister(rm));
1081257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch            data++;
1082b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          } else if (f0byte== 0xC6) {
1083b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            // shufps xmm, xmm/m128, imm8
1084b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            data += 2;
1085b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            int mod, regop, rm;
1086b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            get_modrm(*data, &mod, &regop, &rm);
1087b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            int8_t imm8 = static_cast<int8_t>(data[1]);
1088b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            AppendToBuffer("shufps %s,%s,%d",
1089b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                            NameOfXMMRegister(rm),
1090b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                            NameOfXMMRegister(regop),
1091b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                            static_cast<int>(imm8));
1092b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            data += 2;
1093a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          } else if ((f0byte & 0xF0) == 0x80) {
1094a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            data += JumpConditional(data, branch_hint);
1095a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          } else if (f0byte == 0xBE || f0byte == 0xBF || f0byte == 0xB6 ||
1096a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                     f0byte == 0xB7 || f0byte == 0xAF) {
1097a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            data += 2;
1098a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            data += PrintOperands(f0mnem, REG_OPER_OP_ORDER, data);
1099a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          } else if ((f0byte & 0xF0) == 0x90) {
1100a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            data += SetCC(data);
11013ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block          } else if ((f0byte & 0xF0) == 0x40) {
11023ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block            data += CMov(data);
1103b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          } else if (f0byte == 0xAB || f0byte == 0xA5 || f0byte == 0xAD) {
1104b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            // shrd, shld, bts
1105a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            data += 2;
1106b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            AppendToBuffer("%s ", f0mnem);
1107b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            int mod, regop, rm;
1108b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            get_modrm(*data, &mod, &regop, &rm);
1109b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            data += PrintRightOperand(data);
1110b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            if (f0byte == 0xAB) {
1111b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch              AppendToBuffer(",%s", NameOfCPURegister(regop));
1112a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            } else {
1113b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch              AppendToBuffer(",%s,cl", NameOfCPURegister(regop));
1114a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            }
1115b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          } else if (f0byte == 0xBD) {
1116b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            data += 2;
1117b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            int mod, regop, rm;
1118b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            get_modrm(*data, &mod, &regop, &rm);
1119b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            AppendToBuffer("%s %s,", f0mnem, NameOfCPURegister(regop));
1120b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            data += PrintRightOperand(data);
1121b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          } else {
1122b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            UnimplementedInstruction();
1123a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          }
1124a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        }
1125a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
1126a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1127a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 0x8F:
1128a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        { data++;
1129a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          int mod, regop, rm;
1130a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          get_modrm(*data, &mod, &regop, &rm);
1131a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          if (regop == eax) {
1132a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            AppendToBuffer("pop ");
1133a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            data += PrintRightOperand(data);
1134a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          }
1135a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        }
1136a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
1137a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1138a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 0xFF:
1139a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        { data++;
1140a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          int mod, regop, rm;
1141a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          get_modrm(*data, &mod, &regop, &rm);
1142a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          const char* mnem = NULL;
1143a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          switch (regop) {
1144a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            case esi: mnem = "push"; break;
1145a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            case eax: mnem = "inc"; break;
1146a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            case ecx: mnem = "dec"; break;
1147a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            case edx: mnem = "call"; break;
1148a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            case esp: mnem = "jmp"; break;
1149a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            default: mnem = "???";
1150a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          }
1151a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          AppendToBuffer("%s ", mnem);
1152a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          data += PrintRightOperand(data);
1153a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        }
1154a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
1155a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1156a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 0xC7:  // imm32, fall through
1157a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 0xC6:  // imm8
1158a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        { bool is_byte = *data == 0xC6;
1159a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          data++;
116044f0eee88ff00398ff7f715fab053374d808c90dSteve Block          if (is_byte) {
116144f0eee88ff00398ff7f715fab053374d808c90dSteve Block            AppendToBuffer("%s ", "mov_b");
116244f0eee88ff00398ff7f715fab053374d808c90dSteve Block            data += PrintRightByteOperand(data);
116344f0eee88ff00398ff7f715fab053374d808c90dSteve Block            int32_t imm = *data;
116444f0eee88ff00398ff7f715fab053374d808c90dSteve Block            AppendToBuffer(",0x%x", imm);
116544f0eee88ff00398ff7f715fab053374d808c90dSteve Block            data++;
116644f0eee88ff00398ff7f715fab053374d808c90dSteve Block          } else {
116744f0eee88ff00398ff7f715fab053374d808c90dSteve Block            AppendToBuffer("%s ", "mov");
116844f0eee88ff00398ff7f715fab053374d808c90dSteve Block            data += PrintRightOperand(data);
116944f0eee88ff00398ff7f715fab053374d808c90dSteve Block            int32_t imm = *reinterpret_cast<int32_t*>(data);
117044f0eee88ff00398ff7f715fab053374d808c90dSteve Block            AppendToBuffer(",0x%x", imm);
117144f0eee88ff00398ff7f715fab053374d808c90dSteve Block            data += 4;
117244f0eee88ff00398ff7f715fab053374d808c90dSteve Block          }
1173a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        }
1174a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
1175a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1176a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 0x80:
1177a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        { data++;
1178e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          int mod, regop, rm;
1179e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          get_modrm(*data, &mod, &regop, &rm);
1180e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          const char* mnem = NULL;
1181e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          switch (regop) {
1182e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke            case 5:  mnem = "subb"; break;
1183e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke            case 7:  mnem = "cmpb"; break;
1184e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke            default: UnimplementedInstruction();
1185e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          }
1186e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          AppendToBuffer("%s ", mnem);
118744f0eee88ff00398ff7f715fab053374d808c90dSteve Block          data += PrintRightByteOperand(data);
1188a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          int32_t imm = *data;
1189a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          AppendToBuffer(",0x%x", imm);
1190a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          data++;
1191a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        }
1192a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
1193a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1194a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 0x88:  // 8bit, fall through
1195a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 0x89:  // 32bit
1196a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        { bool is_byte = *data == 0x88;
1197a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          int mod, regop, rm;
1198a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          data++;
1199a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          get_modrm(*data, &mod, &regop, &rm);
120044f0eee88ff00398ff7f715fab053374d808c90dSteve Block          if (is_byte) {
120144f0eee88ff00398ff7f715fab053374d808c90dSteve Block            AppendToBuffer("%s ", "mov_b");
120244f0eee88ff00398ff7f715fab053374d808c90dSteve Block            data += PrintRightByteOperand(data);
120344f0eee88ff00398ff7f715fab053374d808c90dSteve Block            AppendToBuffer(",%s", NameOfByteCPURegister(regop));
120444f0eee88ff00398ff7f715fab053374d808c90dSteve Block          } else {
120544f0eee88ff00398ff7f715fab053374d808c90dSteve Block            AppendToBuffer("%s ", "mov");
120644f0eee88ff00398ff7f715fab053374d808c90dSteve Block            data += PrintRightOperand(data);
120744f0eee88ff00398ff7f715fab053374d808c90dSteve Block            AppendToBuffer(",%s", NameOfCPURegister(regop));
120844f0eee88ff00398ff7f715fab053374d808c90dSteve Block          }
1209a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        }
1210a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
1211a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1212a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 0x66:  // prefix
12133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        while (*data == 0x66) data++;
12143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        if (*data == 0xf && data[1] == 0x1f) {
12153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          AppendToBuffer("nop");  // 0x66 prefix
12163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        } else if (*data == 0x90) {
12173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          AppendToBuffer("nop");  // 0x66 prefix
12183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        } else if (*data == 0x8B) {
1219a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          data++;
1220a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          data += PrintOperands("mov_w", REG_OPER_OP_ORDER, data);
1221a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        } else if (*data == 0x89) {
1222a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          data++;
1223a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          int mod, regop, rm;
1224a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          get_modrm(*data, &mod, &regop, &rm);
1225a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          AppendToBuffer("mov_w ");
1226a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          data += PrintRightOperand(data);
1227a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          AppendToBuffer(",%s", NameOfCPURegister(regop));
1228b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        } else if (*data == 0xC7) {
1229b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          data++;
1230b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          AppendToBuffer("%s ", "mov_w");
1231b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          data += PrintRightOperand(data);
1232b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          int imm = *reinterpret_cast<int16_t*>(data);
1233b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          AppendToBuffer(",0x%x", imm);
1234b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          data += 2;
12353ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block        } else if (*data == 0x0F) {
12363ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block          data++;
12376ded16be15dd865a9b21ea304d5273c8be299c87Steve Block          if (*data == 0x38) {
12386ded16be15dd865a9b21ea304d5273c8be299c87Steve Block            data++;
12396ded16be15dd865a9b21ea304d5273c8be299c87Steve Block            if (*data == 0x17) {
12406ded16be15dd865a9b21ea304d5273c8be299c87Steve Block              data++;
12416ded16be15dd865a9b21ea304d5273c8be299c87Steve Block              int mod, regop, rm;
12426ded16be15dd865a9b21ea304d5273c8be299c87Steve Block              get_modrm(*data, &mod, &regop, &rm);
12436ded16be15dd865a9b21ea304d5273c8be299c87Steve Block              AppendToBuffer("ptest %s,%s",
12446ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                             NameOfXMMRegister(regop),
12456ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                             NameOfXMMRegister(rm));
12466ded16be15dd865a9b21ea304d5273c8be299c87Steve Block              data++;
12477f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch            } else if (*data == 0x2A) {
12487f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch              // movntdqa
12497f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch              data++;
12507f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch              int mod, regop, rm;
12517f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch              get_modrm(*data, &mod, &regop, &rm);
12527f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch              AppendToBuffer("movntdqa %s,", NameOfXMMRegister(regop));
12537f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch              data += PrintRightOperand(data);
12546ded16be15dd865a9b21ea304d5273c8be299c87Steve Block            } else {
12556ded16be15dd865a9b21ea304d5273c8be299c87Steve Block              UnimplementedInstruction();
12566ded16be15dd865a9b21ea304d5273c8be299c87Steve Block            }
1257b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          } else if (*data == 0x3A) {
1258b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            data++;
125969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch            if (*data == 0x0B) {
126069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch              data++;
126169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch              int mod, regop, rm;
126269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch              get_modrm(*data, &mod, &regop, &rm);
126369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch              int8_t imm8 = static_cast<int8_t>(data[1]);
126469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch              AppendToBuffer("roundsd %s,%s,%d",
126569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch                             NameOfXMMRegister(regop),
126669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch                             NameOfXMMRegister(rm),
126769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch                             static_cast<int>(imm8));
126869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch              data += 2;
126969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch            } else if (*data == 0x16) {
1270b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch              data++;
1271b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch              int mod, regop, rm;
1272b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch              get_modrm(*data, &mod, &regop, &rm);
1273b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch              int8_t imm8 = static_cast<int8_t>(data[1]);
1274b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch              AppendToBuffer("pextrd %s,%s,%d",
12751e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                             NameOfCPURegister(regop),
1276b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                             NameOfXMMRegister(rm),
1277b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                             static_cast<int>(imm8));
1278b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch              data += 2;
12793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            } else if (*data == 0x17) {
12803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch              data++;
12813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch              int mod, regop, rm;
12823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch              get_modrm(*data, &mod, &regop, &rm);
12833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch              int8_t imm8 = static_cast<int8_t>(data[1]);
12843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch              AppendToBuffer("extractps %s,%s,%d",
1285b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                             NameOfCPURegister(rm),
1286b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                             NameOfXMMRegister(regop),
12873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                             static_cast<int>(imm8));
12883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch              data += 2;
12891e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block            } else if (*data == 0x22) {
12901e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block              data++;
12911e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block              int mod, regop, rm;
12921e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block              get_modrm(*data, &mod, &regop, &rm);
12931e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block              int8_t imm8 = static_cast<int8_t>(data[1]);
12941e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block              AppendToBuffer("pinsrd %s,%s,%d",
12951e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                             NameOfXMMRegister(regop),
12961e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                             NameOfCPURegister(rm),
12971e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                             static_cast<int>(imm8));
12981e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block              data += 2;
1299b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            } else {
1300b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch              UnimplementedInstruction();
1301b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            }
13026ded16be15dd865a9b21ea304d5273c8be299c87Steve Block          } else if (*data == 0x2E || *data == 0x2F) {
13036ded16be15dd865a9b21ea304d5273c8be299c87Steve Block            const char* mnem = (*data == 0x2E) ? "ucomisd" : "comisd";
13043ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block            data++;
13053ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block            int mod, regop, rm;
13063ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block            get_modrm(*data, &mod, &regop, &rm);
13076ded16be15dd865a9b21ea304d5273c8be299c87Steve Block            if (mod == 0x3) {
13086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block              AppendToBuffer("%s %s,%s", mnem,
13096ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                             NameOfXMMRegister(regop),
13106ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                             NameOfXMMRegister(rm));
13116ded16be15dd865a9b21ea304d5273c8be299c87Steve Block              data++;
13126ded16be15dd865a9b21ea304d5273c8be299c87Steve Block            } else {
13136ded16be15dd865a9b21ea304d5273c8be299c87Steve Block              AppendToBuffer("%s %s,", mnem, NameOfXMMRegister(regop));
13146ded16be15dd865a9b21ea304d5273c8be299c87Steve Block              data += PrintRightOperand(data);
13156ded16be15dd865a9b21ea304d5273c8be299c87Steve Block            }
13166ded16be15dd865a9b21ea304d5273c8be299c87Steve Block          } else if (*data == 0x50) {
13176ded16be15dd865a9b21ea304d5273c8be299c87Steve Block            data++;
13186ded16be15dd865a9b21ea304d5273c8be299c87Steve Block            int mod, regop, rm;
13196ded16be15dd865a9b21ea304d5273c8be299c87Steve Block            get_modrm(*data, &mod, &regop, &rm);
13206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block            AppendToBuffer("movmskpd %s,%s",
13216ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                           NameOfCPURegister(regop),
13223ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                           NameOfXMMRegister(rm));
13233ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block            data++;
1324b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          } else if (*data == 0x54) {
1325b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            data++;
1326b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            int mod, regop, rm;
1327b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            get_modrm(*data, &mod, &regop, &rm);
1328b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            AppendToBuffer("andpd %s,%s",
1329b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                           NameOfXMMRegister(regop),
1330b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                           NameOfXMMRegister(rm));
1331b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            data++;
1332b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          } else if (*data == 0x56) {
1333b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            data++;
1334b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            int mod, regop, rm;
1335b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            get_modrm(*data, &mod, &regop, &rm);
1336b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            AppendToBuffer("orpd %s,%s",
1337b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                           NameOfXMMRegister(regop),
1338b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                           NameOfXMMRegister(rm));
1339b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            data++;
1340e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          } else if (*data == 0x57) {
1341e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke            data++;
1342e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke            int mod, regop, rm;
1343e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke            get_modrm(*data, &mod, &regop, &rm);
1344e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke            AppendToBuffer("xorpd %s,%s",
1345e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                           NameOfXMMRegister(regop),
1346e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                           NameOfXMMRegister(rm));
1347e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke            data++;
13486ded16be15dd865a9b21ea304d5273c8be299c87Steve Block          } else if (*data == 0x6E) {
13496ded16be15dd865a9b21ea304d5273c8be299c87Steve Block            data++;
13506ded16be15dd865a9b21ea304d5273c8be299c87Steve Block            int mod, regop, rm;
13516ded16be15dd865a9b21ea304d5273c8be299c87Steve Block            get_modrm(*data, &mod, &regop, &rm);
13526ded16be15dd865a9b21ea304d5273c8be299c87Steve Block            AppendToBuffer("movd %s,", NameOfXMMRegister(regop));
13536ded16be15dd865a9b21ea304d5273c8be299c87Steve Block            data += PrintRightOperand(data);
1354e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          } else if (*data == 0x6F) {
1355e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke            data++;
1356e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke            int mod, regop, rm;
1357e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke            get_modrm(*data, &mod, &regop, &rm);
1358e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke            AppendToBuffer("movdqa %s,", NameOfXMMRegister(regop));
135944f0eee88ff00398ff7f715fab053374d808c90dSteve Block            data += PrintRightXMMOperand(data);
1360b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          } else if (*data == 0x70) {
1361b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            data++;
1362b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            int mod, regop, rm;
1363b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            get_modrm(*data, &mod, &regop, &rm);
1364b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            int8_t imm8 = static_cast<int8_t>(data[1]);
1365b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            AppendToBuffer("pshufd %s,%s,%d",
1366b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                           NameOfXMMRegister(regop),
1367b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                           NameOfXMMRegister(rm),
1368b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                           static_cast<int>(imm8));
1369b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            data += 2;
1370b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          } else if (*data == 0x76) {
1371b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            data++;
1372b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            int mod, regop, rm;
1373b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            get_modrm(*data, &mod, &regop, &rm);
1374b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            AppendToBuffer("pcmpeqd %s,%s",
1375b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                           NameOfXMMRegister(regop),
1376b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                           NameOfXMMRegister(rm));
1377b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            data++;
13783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          } else if (*data == 0x90) {
13793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            data++;
13803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            AppendToBuffer("nop");  // 2 byte nop.
1381b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch          } else if (*data == 0xF3) {
1382b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch            data++;
1383b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch            int mod, regop, rm;
1384b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch            get_modrm(*data, &mod, &regop, &rm);
1385b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch            AppendToBuffer("psllq %s,%s",
1386b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch                           NameOfXMMRegister(regop),
1387b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch                           NameOfXMMRegister(rm));
1388b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch            data++;
1389b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          } else if (*data == 0x73) {
1390b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            data++;
1391b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            int mod, regop, rm;
1392b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            get_modrm(*data, &mod, &regop, &rm);
1393b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            int8_t imm8 = static_cast<int8_t>(data[1]);
1394b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            DCHECK(regop == esi || regop == edx);
1395b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch            AppendToBuffer("%s %s,%d",
1396b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch                           (regop == esi) ? "psllq" : "psrlq",
1397b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                           NameOfXMMRegister(rm),
1398b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                           static_cast<int>(imm8));
1399b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            data += 2;
1400b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch          } else if (*data == 0xD3) {
1401b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch            data++;
1402b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch            int mod, regop, rm;
1403b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch            get_modrm(*data, &mod, &regop, &rm);
1404b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch            AppendToBuffer("psrlq %s,%s",
1405b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch                           NameOfXMMRegister(regop),
1406b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch                           NameOfXMMRegister(rm));
1407b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch            data++;
1408e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          } else if (*data == 0x7F) {
1409e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke            AppendToBuffer("movdqa ");
1410e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke            data++;
1411e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke            int mod, regop, rm;
1412e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke            get_modrm(*data, &mod, &regop, &rm);
141344f0eee88ff00398ff7f715fab053374d808c90dSteve Block            data += PrintRightXMMOperand(data);
1414e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke            AppendToBuffer(",%s", NameOfXMMRegister(regop));
1415b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          } else if (*data == 0x7E) {
1416b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            data++;
1417b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            int mod, regop, rm;
1418b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            get_modrm(*data, &mod, &regop, &rm);
1419b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            AppendToBuffer("movd ");
1420b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            data += PrintRightOperand(data);
1421b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            AppendToBuffer(",%s", NameOfXMMRegister(regop));
1422b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          } else if (*data == 0xDB) {
1423b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            data++;
1424b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            int mod, regop, rm;
1425b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            get_modrm(*data, &mod, &regop, &rm);
1426b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            AppendToBuffer("pand %s,%s",
1427b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                           NameOfXMMRegister(regop),
1428b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                           NameOfXMMRegister(rm));
1429b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            data++;
14307f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch          } else if (*data == 0xE7) {
14317f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch            data++;
14327f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch            int mod, regop, rm;
14337f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch            get_modrm(*data, &mod, &regop, &rm);
143444f0eee88ff00398ff7f715fab053374d808c90dSteve Block            if (mod == 3) {
143544f0eee88ff00398ff7f715fab053374d808c90dSteve Block              AppendToBuffer("movntdq ");
143644f0eee88ff00398ff7f715fab053374d808c90dSteve Block              data += PrintRightOperand(data);
143744f0eee88ff00398ff7f715fab053374d808c90dSteve Block              AppendToBuffer(",%s", NameOfXMMRegister(regop));
143844f0eee88ff00398ff7f715fab053374d808c90dSteve Block            } else {
143944f0eee88ff00398ff7f715fab053374d808c90dSteve Block              UnimplementedInstruction();
144044f0eee88ff00398ff7f715fab053374d808c90dSteve Block            }
14416ded16be15dd865a9b21ea304d5273c8be299c87Steve Block          } else if (*data == 0xEF) {
1442b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            data++;
1443b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            int mod, regop, rm;
1444b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            get_modrm(*data, &mod, &regop, &rm);
1445b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            AppendToBuffer("pxor %s,%s",
1446b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                           NameOfXMMRegister(regop),
1447b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                           NameOfXMMRegister(rm));
1448b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            data++;
1449b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch          } else if (*data == 0xEB) {
1450b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch            data++;
1451b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch            int mod, regop, rm;
1452b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch            get_modrm(*data, &mod, &regop, &rm);
1453b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch            AppendToBuffer("por %s,%s",
1454b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch                           NameOfXMMRegister(regop),
1455b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch                           NameOfXMMRegister(rm));
1456b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch            data++;
14573ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block          } else {
14583ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block            UnimplementedInstruction();
14593ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block          }
1460a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        } else {
1461a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          UnimplementedInstruction();
1462a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        }
1463a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
1464a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1465a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 0xFE:
1466a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        { data++;
1467a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          int mod, regop, rm;
1468a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          get_modrm(*data, &mod, &regop, &rm);
14690d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          if (regop == ecx) {
14700d5e116f6aee03185f237311a943491bb079a768Kristian Monsen            AppendToBuffer("dec_b ");
14710d5e116f6aee03185f237311a943491bb079a768Kristian Monsen            data += PrintRightOperand(data);
1472a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          } else {
1473a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            UnimplementedInstruction();
1474a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          }
1475a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        }
1476a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
1477a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1478a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 0x68:
1479a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        AppendToBuffer("push 0x%x", *reinterpret_cast<int32_t*>(data+1));
1480a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        data += 5;
1481a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
1482a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1483a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 0x6A:
1484a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        AppendToBuffer("push 0x%x", *reinterpret_cast<int8_t*>(data + 1));
1485a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        data += 2;
1486a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
1487a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1488a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 0xA8:
1489a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        AppendToBuffer("test al,0x%x", *reinterpret_cast<uint8_t*>(data+1));
1490a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        data += 2;
1491a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
1492a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1493a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 0xA9:
1494a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        AppendToBuffer("test eax,0x%x", *reinterpret_cast<int32_t*>(data+1));
1495a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        data += 5;
1496a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
1497a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1498a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 0xD1:  // fall through
1499a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 0xD3:  // fall through
1500a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 0xC1:
1501a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        data += D1D3C1Instruction(data);
1502a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
1503a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1504b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case 0xD8:  // fall through
1505a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 0xD9:  // fall through
1506a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 0xDA:  // fall through
1507a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 0xDB:  // fall through
1508a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 0xDC:  // fall through
1509a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 0xDD:  // fall through
1510a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 0xDE:  // fall through
1511a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 0xDF:
1512a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        data += FPUInstruction(data);
1513a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
1514a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1515a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 0xEB:
1516a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        data += JumpShort(data);
1517a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
1518a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1519a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 0xF2:
1520a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        if (*(data+1) == 0x0F) {
1521a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          byte b2 = *(data+2);
1522a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          if (b2 == 0x11) {
1523a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            AppendToBuffer("movsd ");
1524a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            data += 3;
1525a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            int mod, regop, rm;
1526a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            get_modrm(*data, &mod, &regop, &rm);
152744f0eee88ff00398ff7f715fab053374d808c90dSteve Block            data += PrintRightXMMOperand(data);
1528a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            AppendToBuffer(",%s", NameOfXMMRegister(regop));
1529a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          } else if (b2 == 0x10) {
1530a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            data += 3;
1531a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            int mod, regop, rm;
1532a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            get_modrm(*data, &mod, &regop, &rm);
1533a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            AppendToBuffer("movsd %s,", NameOfXMMRegister(regop));
153444f0eee88ff00398ff7f715fab053374d808c90dSteve Block            data += PrintRightXMMOperand(data);
153544f0eee88ff00398ff7f715fab053374d808c90dSteve Block          } else  if (b2 == 0x5A) {
153644f0eee88ff00398ff7f715fab053374d808c90dSteve Block            data += 3;
153744f0eee88ff00398ff7f715fab053374d808c90dSteve Block            int mod, regop, rm;
153844f0eee88ff00398ff7f715fab053374d808c90dSteve Block            get_modrm(*data, &mod, &regop, &rm);
153944f0eee88ff00398ff7f715fab053374d808c90dSteve Block            AppendToBuffer("cvtsd2ss %s,", NameOfXMMRegister(regop));
154044f0eee88ff00398ff7f715fab053374d808c90dSteve Block            data += PrintRightXMMOperand(data);
1541a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          } else {
1542a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            const char* mnem = "?";
1543a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            switch (b2) {
1544a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block              case 0x2A: mnem = "cvtsi2sd"; break;
15456ded16be15dd865a9b21ea304d5273c8be299c87Steve Block              case 0x2C: mnem = "cvttsd2si"; break;
1546b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch              case 0x2D: mnem = "cvtsd2si"; break;
15476ded16be15dd865a9b21ea304d5273c8be299c87Steve Block              case 0x51: mnem = "sqrtsd"; break;
1548a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block              case 0x58: mnem = "addsd"; break;
1549a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block              case 0x59: mnem = "mulsd"; break;
1550a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block              case 0x5C: mnem = "subsd"; break;
1551a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block              case 0x5E: mnem = "divsd"; break;
1552a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            }
1553a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            data += 3;
1554a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            int mod, regop, rm;
1555a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            get_modrm(*data, &mod, &regop, &rm);
1556a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            if (b2 == 0x2A) {
155744f0eee88ff00398ff7f715fab053374d808c90dSteve Block              AppendToBuffer("%s %s,", mnem, NameOfXMMRegister(regop));
155844f0eee88ff00398ff7f715fab053374d808c90dSteve Block              data += PrintRightOperand(data);
1559b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            } else if (b2 == 0x2C || b2 == 0x2D) {
156044f0eee88ff00398ff7f715fab053374d808c90dSteve Block              AppendToBuffer("%s %s,", mnem, NameOfCPURegister(regop));
156144f0eee88ff00398ff7f715fab053374d808c90dSteve Block              data += PrintRightXMMOperand(data);
15620d5e116f6aee03185f237311a943491bb079a768Kristian Monsen            } else if (b2 == 0xC2) {
15630d5e116f6aee03185f237311a943491bb079a768Kristian Monsen              // Intel manual 2A, Table 3-18.
15640d5e116f6aee03185f237311a943491bb079a768Kristian Monsen              const char* const pseudo_op[] = {
15650d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                "cmpeqsd",
15660d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                "cmpltsd",
15670d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                "cmplesd",
15680d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                "cmpunordsd",
15690d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                "cmpneqsd",
15700d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                "cmpnltsd",
15710d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                "cmpnlesd",
15720d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                "cmpordsd"
15730d5e116f6aee03185f237311a943491bb079a768Kristian Monsen              };
15740d5e116f6aee03185f237311a943491bb079a768Kristian Monsen              AppendToBuffer("%s %s,%s",
15750d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                             pseudo_op[data[1]],
15760d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                             NameOfXMMRegister(regop),
15770d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                             NameOfXMMRegister(rm));
15780d5e116f6aee03185f237311a943491bb079a768Kristian Monsen              data += 2;
1579a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            } else {
158044f0eee88ff00398ff7f715fab053374d808c90dSteve Block              AppendToBuffer("%s %s,", mnem, NameOfXMMRegister(regop));
158144f0eee88ff00398ff7f715fab053374d808c90dSteve Block              data += PrintRightXMMOperand(data);
1582a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            }
1583a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          }
1584a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        } else {
1585a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          UnimplementedInstruction();
1586a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        }
1587a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
1588a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1589a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 0xF3:
1590e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        if (*(data+1) == 0x0F) {
159144f0eee88ff00398ff7f715fab053374d808c90dSteve Block          byte b2 = *(data+2);
159244f0eee88ff00398ff7f715fab053374d808c90dSteve Block          if (b2 == 0x11) {
159344f0eee88ff00398ff7f715fab053374d808c90dSteve Block            AppendToBuffer("movss ");
1594e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke            data += 3;
159544f0eee88ff00398ff7f715fab053374d808c90dSteve Block            int mod, regop, rm;
159644f0eee88ff00398ff7f715fab053374d808c90dSteve Block            get_modrm(*data, &mod, &regop, &rm);
159744f0eee88ff00398ff7f715fab053374d808c90dSteve Block            data += PrintRightXMMOperand(data);
159844f0eee88ff00398ff7f715fab053374d808c90dSteve Block            AppendToBuffer(",%s", NameOfXMMRegister(regop));
159944f0eee88ff00398ff7f715fab053374d808c90dSteve Block          } else if (b2 == 0x10) {
16006ded16be15dd865a9b21ea304d5273c8be299c87Steve Block            data += 3;
16016ded16be15dd865a9b21ea304d5273c8be299c87Steve Block            int mod, regop, rm;
16026ded16be15dd865a9b21ea304d5273c8be299c87Steve Block            get_modrm(*data, &mod, &regop, &rm);
160344f0eee88ff00398ff7f715fab053374d808c90dSteve Block            AppendToBuffer("movss %s,", NameOfXMMRegister(regop));
160444f0eee88ff00398ff7f715fab053374d808c90dSteve Block            data += PrintRightXMMOperand(data);
160544f0eee88ff00398ff7f715fab053374d808c90dSteve Block          } else if (b2 == 0x2C) {
160644f0eee88ff00398ff7f715fab053374d808c90dSteve Block            data += 3;
160744f0eee88ff00398ff7f715fab053374d808c90dSteve Block            int mod, regop, rm;
160844f0eee88ff00398ff7f715fab053374d808c90dSteve Block            get_modrm(*data, &mod, &regop, &rm);
160944f0eee88ff00398ff7f715fab053374d808c90dSteve Block            AppendToBuffer("cvttss2si %s,", NameOfCPURegister(regop));
161044f0eee88ff00398ff7f715fab053374d808c90dSteve Block            data += PrintRightXMMOperand(data);
161144f0eee88ff00398ff7f715fab053374d808c90dSteve Block          } else if (b2 == 0x5A) {
161244f0eee88ff00398ff7f715fab053374d808c90dSteve Block            data += 3;
161344f0eee88ff00398ff7f715fab053374d808c90dSteve Block            int mod, regop, rm;
161444f0eee88ff00398ff7f715fab053374d808c90dSteve Block            get_modrm(*data, &mod, &regop, &rm);
161544f0eee88ff00398ff7f715fab053374d808c90dSteve Block            AppendToBuffer("cvtss2sd %s,", NameOfXMMRegister(regop));
161644f0eee88ff00398ff7f715fab053374d808c90dSteve Block            data += PrintRightXMMOperand(data);
1617b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          } else if (b2 == 0x6F) {
1618e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke            data += 3;
1619e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke            int mod, regop, rm;
1620e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke            get_modrm(*data, &mod, &regop, &rm);
1621e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke            AppendToBuffer("movdqu %s,", NameOfXMMRegister(regop));
162244f0eee88ff00398ff7f715fab053374d808c90dSteve Block            data += PrintRightXMMOperand(data);
1623b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          } else if (b2 == 0x7F) {
1624e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke            AppendToBuffer("movdqu ");
1625e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke            data += 3;
1626e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke            int mod, regop, rm;
1627e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke            get_modrm(*data, &mod, &regop, &rm);
162844f0eee88ff00398ff7f715fab053374d808c90dSteve Block            data += PrintRightXMMOperand(data);
1629e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke            AppendToBuffer(",%s", NameOfXMMRegister(regop));
1630e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          } else {
1631e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke            UnimplementedInstruction();
1632e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          }
1633e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        } else if (*(data+1) == 0xA5) {
1634e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          data += 2;
1635e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          AppendToBuffer("rep_movs");
16366ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        } else if (*(data+1) == 0xAB) {
16376ded16be15dd865a9b21ea304d5273c8be299c87Steve Block          data += 2;
16386ded16be15dd865a9b21ea304d5273c8be299c87Steve Block          AppendToBuffer("rep_stos");
1639a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        } else {
1640a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          UnimplementedInstruction();
1641a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        }
1642a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
1643a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1644a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 0xF7:
1645a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        data += F7Instruction(data);
1646a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
1647a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1648a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      default:
1649a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        UnimplementedInstruction();
1650a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
1651a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1652a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1653a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (tmp_buffer_pos_ < sizeof tmp_buffer_) {
1654a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    tmp_buffer_[tmp_buffer_pos_] = '\0';
1655a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1656a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1657a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int instr_len = data - instr;
1658e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  if (instr_len == 0) {
1659e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    printf("%02x", *data);
1660e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  }
1661b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(instr_len > 0);  // Ensure progress.
1662a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1663a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int outp = 0;
1664a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Instruction bytes.
1665a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (byte* bp = instr; bp < data; bp++) {
1666b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    outp += v8::internal::SNPrintF(out_buffer + outp,
1667b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                   "%02x",
1668b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                   *bp);
1669a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1670a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (int i = 6 - instr_len; i >= 0; i--) {
1671b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    outp += v8::internal::SNPrintF(out_buffer + outp, "  ");
1672a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1673a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1674b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  outp += v8::internal::SNPrintF(out_buffer + outp,
1675b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                 " %s",
1676b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                 tmp_buffer_.start());
1677a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return instr_len;
16780d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}  // NOLINT (function is too long)
1679a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1680a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1681a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//------------------------------------------------------------------------------
1682a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1683a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1684a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic const char* cpu_regs[8] = {
1685a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  "eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi"
1686a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
1687a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1688a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1689a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic const char* byte_cpu_regs[8] = {
1690a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  "al", "cl", "dl", "bl", "ah", "ch", "dh", "bh"
1691a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
1692a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1693a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1694a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic const char* xmm_regs[8] = {
1695a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7"
1696a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
1697a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1698a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1699a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockconst char* NameConverter::NameOfAddress(byte* addr) const {
1700b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::internal::SNPrintF(tmp_buffer_, "%p", addr);
170144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  return tmp_buffer_.start();
1702a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1703a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1704a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1705a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockconst char* NameConverter::NameOfConstant(byte* addr) const {
1706a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return NameOfAddress(addr);
1707a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1708a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1709a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1710a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockconst char* NameConverter::NameOfCPURegister(int reg) const {
1711a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (0 <= reg && reg < 8) return cpu_regs[reg];
1712a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return "noreg";
1713a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1714a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1715a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1716a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockconst char* NameConverter::NameOfByteCPURegister(int reg) const {
1717a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (0 <= reg && reg < 8) return byte_cpu_regs[reg];
1718a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return "noreg";
1719a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1720a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1721a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1722a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockconst char* NameConverter::NameOfXMMRegister(int reg) const {
1723a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (0 <= reg && reg < 8) return xmm_regs[reg];
1724a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return "noxmmreg";
1725a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1726a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1727a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1728a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockconst char* NameConverter::NameInCode(byte* addr) const {
1729a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // IA32 does not embed debug strings at the moment.
1730a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  UNREACHABLE();
1731a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return "";
1732a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1733a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1734a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1735a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//------------------------------------------------------------------------------
1736a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1737a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockDisassembler::Disassembler(const NameConverter& converter)
1738a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    : converter_(converter) {}
1739a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1740a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1741a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockDisassembler::~Disassembler() {}
1742a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1743a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1744a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint Disassembler::InstructionDecode(v8::internal::Vector<char> buffer,
1745a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                    byte* instruction) {
1746a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  DisassemblerIA32 d(converter_, false /*do not crash if unimplemented*/);
1747a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return d.InstructionDecode(buffer, instruction);
1748a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1749a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1750a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1751a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// The IA-32 assembler does not currently use constant pools.
1752a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint Disassembler::ConstantPoolSizeAt(byte* instruction) { return -1; }
1753a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1754a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1755a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block/*static*/ void Disassembler::Disassemble(FILE* f, byte* begin, byte* end) {
1756a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  NameConverter converter;
1757a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Disassembler d(converter);
1758a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (byte* pc = begin; pc < end;) {
1759a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    v8::internal::EmbeddedVector<char, 128> buffer;
1760a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    buffer[0] = '\0';
1761a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    byte* prev_pc = pc;
1762a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    pc += d.InstructionDecode(buffer, pc);
1763a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    fprintf(f, "%p", prev_pc);
1764a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    fprintf(f, "    ");
1765a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1766a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    for (byte* bp = prev_pc; bp < pc; bp++) {
1767a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      fprintf(f, "%02x",  *bp);
1768a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
1769a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    for (int i = 6 - (pc - prev_pc); i >= 0; i--) {
1770a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      fprintf(f, "  ");
1771a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
1772a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    fprintf(f, "  %s\n", buffer.start());
1773a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1774a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1775a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1776a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1777a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}  // namespace disasm
1778f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1779f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke#endif  // V8_TARGET_ARCH_IA32
1780