disasm-ia32.cc revision 958fae7ec3f466955f8e5b50fa5b8d38b9e91675
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),
249958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        vex_byte0_(0),
250958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        vex_byte1_(0),
251958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        vex_byte2_(0),
2523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        instruction_table_(InstructionTable::get_instance()),
253a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        tmp_buffer_pos_(0),
254a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        abort_on_unimplemented_(abort_on_unimplemented) {
255a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    tmp_buffer_[0] = '\0';
256a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
257a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
258a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  virtual ~DisassemblerIA32() {}
259a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
260a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Writes one disassembled instruction into 'buffer' (0-terminated).
261a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Returns the length of the disassembled machine instruction in bytes.
262a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int InstructionDecode(v8::internal::Vector<char> buffer, byte* instruction);
263a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
264a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private:
265a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const NameConverter& converter_;
266958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  byte vex_byte0_;  // 0xc4 or 0xc5
267958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  byte vex_byte1_;
268958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  byte vex_byte2_;  // only for 3 bytes vex prefix
2693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  InstructionTable* instruction_table_;
270a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::internal::EmbeddedVector<char, 128> tmp_buffer_;
271a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  unsigned int tmp_buffer_pos_;
272a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bool abort_on_unimplemented_;
273a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
274a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  enum {
275a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    eax = 0,
276a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ecx = 1,
277a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    edx = 2,
278a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ebx = 3,
279a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    esp = 4,
280a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ebp = 5,
281a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    esi = 6,
282a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    edi = 7
283a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  };
284a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
285a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
286d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  enum ShiftOpcodeExtension {
287d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    kROL = 0,
288d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    kROR = 1,
289d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    kRCL = 2,
290d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    kRCR = 3,
291d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    kSHL = 4,
292d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    KSHR = 5,
293d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    kSAR = 7
294d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  };
295d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
296958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  bool vex_128() {
297958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    DCHECK(vex_byte0_ == 0xc4 || vex_byte0_ == 0xc5);
298958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    byte checked = vex_byte0_ == 0xc4 ? vex_byte2_ : vex_byte1_;
299958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    return (checked & 4) != 1;
300958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
301958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
302958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  bool vex_66() {
303958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    DCHECK(vex_byte0_ == 0xc4 || vex_byte0_ == 0xc5);
304958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    byte checked = vex_byte0_ == 0xc4 ? vex_byte2_ : vex_byte1_;
305958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    return (checked & 3) == 1;
306958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
307958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
308958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  bool vex_f3() {
309958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    DCHECK(vex_byte0_ == 0xc4 || vex_byte0_ == 0xc5);
310958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    byte checked = vex_byte0_ == 0xc4 ? vex_byte2_ : vex_byte1_;
311958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    return (checked & 3) == 2;
312958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
313958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
314958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  bool vex_f2() {
315958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    DCHECK(vex_byte0_ == 0xc4 || vex_byte0_ == 0xc5);
316958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    byte checked = vex_byte0_ == 0xc4 ? vex_byte2_ : vex_byte1_;
317958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    return (checked & 3) == 3;
318958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
319958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
320958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  bool vex_w() {
321958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    if (vex_byte0_ == 0xc5) return false;
322958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    return (vex_byte2_ & 0x80) != 0;
323958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
324958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
325958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  bool vex_0f() {
326958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    if (vex_byte0_ == 0xc5) return true;
327958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    return (vex_byte1_ & 3) == 1;
328958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
329958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
330958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  bool vex_0f38() {
331958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    if (vex_byte0_ == 0xc5) return false;
332958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    return (vex_byte1_ & 3) == 2;
333958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
334958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
335958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  bool vex_0f3a() {
336958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    if (vex_byte0_ == 0xc5) return false;
337958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    return (vex_byte1_ & 3) == 3;
338958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
339958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
340958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  int vex_vreg() {
341958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    DCHECK(vex_byte0_ == 0xc4 || vex_byte0_ == 0xc5);
342958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    byte checked = vex_byte0_ == 0xc4 ? vex_byte2_ : vex_byte1_;
343958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    return ~(checked >> 3) & 0xf;
344958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
345958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
346958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  char float_size_code() { return "sd"[vex_w()]; }
347d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
348a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const char* NameOfCPURegister(int reg) const {
349a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return converter_.NameOfCPURegister(reg);
350a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
351a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
352a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
353a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const char* NameOfByteCPURegister(int reg) const {
354a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return converter_.NameOfByteCPURegister(reg);
355a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
356a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
357a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
358a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const char* NameOfXMMRegister(int reg) const {
359a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return converter_.NameOfXMMRegister(reg);
360a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
361a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
362a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
363a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const char* NameOfAddress(byte* addr) const {
364a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return converter_.NameOfAddress(addr);
365a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
366a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
367a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
368a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Disassembler helper functions.
369a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  static void get_modrm(byte data, int* mod, int* regop, int* rm) {
370a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    *mod = (data >> 6) & 3;
371a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    *regop = (data & 0x38) >> 3;
372a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    *rm = data & 7;
373a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
374a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
375a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
376a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  static void get_sib(byte data, int* scale, int* index, int* base) {
377a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    *scale = (data >> 6) & 3;
378a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    *index = (data >> 3) & 7;
379a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    *base = data & 7;
380a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
381a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
382a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  typedef const char* (DisassemblerIA32::*RegisterNameMapping)(int reg) const;
383a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
384a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int PrintRightOperandHelper(byte* modrmp, RegisterNameMapping register_name);
385a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int PrintRightOperand(byte* modrmp);
386a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int PrintRightByteOperand(byte* modrmp);
38744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  int PrintRightXMMOperand(byte* modrmp);
388a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int PrintOperands(const char* mnem, OperandOrder op_order, byte* data);
389a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int PrintImmediateOp(byte* data);
390a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int F7Instruction(byte* data);
391a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int D1D3C1Instruction(byte* data);
392a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int JumpShort(byte* data);
393a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int JumpConditional(byte* data, const char* comment);
394a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int JumpConditionalShort(byte* data, const char* comment);
395a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int SetCC(byte* data);
3963ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  int CMov(byte* data);
397a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int FPUInstruction(byte* data);
398d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  int MemoryFPUInstruction(int escape_opcode, int regop, byte* modrm_start);
399d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  int RegisterFPUInstruction(int escape_opcode, byte modrm_byte);
400958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  int AVXInstruction(byte* data);
401a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void AppendToBuffer(const char* format, ...);
402a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
403a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
404a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void UnimplementedInstruction() {
405a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (abort_on_unimplemented_) {
406a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      UNIMPLEMENTED();
407a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    } else {
408a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      AppendToBuffer("'Unimplemented Instruction'");
409a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
410a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
411a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
412a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
413a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
414a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid DisassemblerIA32::AppendToBuffer(const char* format, ...) {
415a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::internal::Vector<char> buf = tmp_buffer_ + tmp_buffer_pos_;
416a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  va_list args;
417a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  va_start(args, format);
418b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int result = v8::internal::VSNPrintF(buf, format, args);
419a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  va_end(args);
420a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  tmp_buffer_pos_ += result;
421a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
422a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
423a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint DisassemblerIA32::PrintRightOperandHelper(
424a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    byte* modrmp,
42544f0eee88ff00398ff7f715fab053374d808c90dSteve Block    RegisterNameMapping direct_register_name) {
426a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int mod, regop, rm;
427a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  get_modrm(*modrmp, &mod, &regop, &rm);
42844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  RegisterNameMapping register_name = (mod == 3) ? direct_register_name :
42944f0eee88ff00398ff7f715fab053374d808c90dSteve Block      &DisassemblerIA32::NameOfCPURegister;
430a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  switch (mod) {
431a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case 0:
432a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      if (rm == ebp) {
433a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        int32_t disp = *reinterpret_cast<int32_t*>(modrmp+1);
434a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        AppendToBuffer("[0x%x]", disp);
435a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        return 5;
436a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      } else if (rm == esp) {
437a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        byte sib = *(modrmp + 1);
438a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        int scale, index, base;
439a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        get_sib(sib, &scale, &index, &base);
440a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        if (index == esp && base == esp && scale == 0 /*times_1*/) {
441a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          AppendToBuffer("[%s]", (this->*register_name)(rm));
442a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          return 2;
443a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        } else if (base == ebp) {
444a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          int32_t disp = *reinterpret_cast<int32_t*>(modrmp + 2);
445b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          AppendToBuffer("[%s*%d%s0x%x]",
446a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                         (this->*register_name)(index),
447a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                         1 << scale,
448b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                         disp < 0 ? "-" : "+",
449b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                         disp < 0 ? -disp : disp);
450a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          return 6;
451a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        } else if (index != esp && base != ebp) {
452a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          // [base+index*scale]
453a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          AppendToBuffer("[%s+%s*%d]",
454a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                         (this->*register_name)(base),
455a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                         (this->*register_name)(index),
456a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                         1 << scale);
457a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          return 2;
458a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        } else {
459a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          UnimplementedInstruction();
460a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          return 1;
461a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        }
462a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      } else {
463a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        AppendToBuffer("[%s]", (this->*register_name)(rm));
464a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        return 1;
465a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
466a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      break;
467a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case 1:  // fall through
468a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case 2:
469a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      if (rm == esp) {
470a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        byte sib = *(modrmp + 1);
471a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        int scale, index, base;
472a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        get_sib(sib, &scale, &index, &base);
473b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        int disp = mod == 2 ? *reinterpret_cast<int32_t*>(modrmp + 2)
474b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                            : *reinterpret_cast<int8_t*>(modrmp + 2);
475a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        if (index == base && index == rm /*esp*/ && scale == 0 /*times_1*/) {
476b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          AppendToBuffer("[%s%s0x%x]",
477b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                         (this->*register_name)(rm),
478b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                         disp < 0 ? "-" : "+",
479b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                         disp < 0 ? -disp : disp);
480a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        } else {
481b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          AppendToBuffer("[%s+%s*%d%s0x%x]",
482a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                         (this->*register_name)(base),
483a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                         (this->*register_name)(index),
484a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                         1 << scale,
485b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                         disp < 0 ? "-" : "+",
486b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                         disp < 0 ? -disp : disp);
487a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        }
488a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        return mod == 2 ? 6 : 3;
489a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      } else {
490a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        // No sib.
491b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        int disp = mod == 2 ? *reinterpret_cast<int32_t*>(modrmp + 1)
492b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                            : *reinterpret_cast<int8_t*>(modrmp + 1);
493b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        AppendToBuffer("[%s%s0x%x]",
494b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                       (this->*register_name)(rm),
495b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                       disp < 0 ? "-" : "+",
496b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                       disp < 0 ? -disp : disp);
497a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        return mod == 2 ? 5 : 2;
498a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
499a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      break;
500a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case 3:
501a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      AppendToBuffer("%s", (this->*register_name)(rm));
502a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      return 1;
503a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    default:
504a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      UnimplementedInstruction();
505a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      return 1;
506a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
507a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  UNREACHABLE();
508a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
509a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
510a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
511a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint DisassemblerIA32::PrintRightOperand(byte* modrmp) {
512a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return PrintRightOperandHelper(modrmp, &DisassemblerIA32::NameOfCPURegister);
513a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
514a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
515a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
516a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint DisassemblerIA32::PrintRightByteOperand(byte* modrmp) {
517a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return PrintRightOperandHelper(modrmp,
518a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                 &DisassemblerIA32::NameOfByteCPURegister);
519a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
520a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
521a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
52244f0eee88ff00398ff7f715fab053374d808c90dSteve Blockint DisassemblerIA32::PrintRightXMMOperand(byte* modrmp) {
52344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  return PrintRightOperandHelper(modrmp,
52444f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                 &DisassemblerIA32::NameOfXMMRegister);
52544f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
52644f0eee88ff00398ff7f715fab053374d808c90dSteve Block
52744f0eee88ff00398ff7f715fab053374d808c90dSteve Block
528a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Returns number of bytes used including the current *data.
529a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Writes instruction's mnemonic, left and right operands to 'tmp_buffer_'.
530a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint DisassemblerIA32::PrintOperands(const char* mnem,
531a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                    OperandOrder op_order,
532a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                    byte* data) {
533a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  byte modrm = *data;
534a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int mod, regop, rm;
535a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  get_modrm(modrm, &mod, &regop, &rm);
536a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int advance = 0;
537a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  switch (op_order) {
538a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case REG_OPER_OP_ORDER: {
539a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      AppendToBuffer("%s %s,", mnem, NameOfCPURegister(regop));
540a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      advance = PrintRightOperand(data);
541a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      break;
542a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
543a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case OPER_REG_OP_ORDER: {
544a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      AppendToBuffer("%s ", mnem);
545a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      advance = PrintRightOperand(data);
546a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      AppendToBuffer(",%s", NameOfCPURegister(regop));
547a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      break;
548a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
549a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    default:
550a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      UNREACHABLE();
551a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      break;
552a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
553a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return advance;
554a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
555a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
556a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
557a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Returns number of bytes used by machine instruction, including *data byte.
558a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Writes immediate instructions to 'tmp_buffer_'.
559a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint DisassemblerIA32::PrintImmediateOp(byte* data) {
560a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bool sign_extension_bit = (*data & 0x02) != 0;
561a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  byte modrm = *(data+1);
562a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int mod, regop, rm;
563a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  get_modrm(modrm, &mod, &regop, &rm);
564a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const char* mnem = "Imm???";
565a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  switch (regop) {
566a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case 0: mnem = "add"; break;
567a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case 1: mnem = "or"; break;
568a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case 2: mnem = "adc"; break;
569a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case 4: mnem = "and"; break;
570a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case 5: mnem = "sub"; break;
571a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case 6: mnem = "xor"; break;
572a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case 7: mnem = "cmp"; break;
573a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    default: UnimplementedInstruction();
574a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
575a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  AppendToBuffer("%s ", mnem);
576a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int count = PrintRightOperand(data+1);
577a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (sign_extension_bit) {
578a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    AppendToBuffer(",0x%x", *(data + 1 + count));
579a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return 1 + count + 1 /*int8*/;
580a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
581a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    AppendToBuffer(",0x%x", *reinterpret_cast<int32_t*>(data + 1 + count));
582a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return 1 + count + 4 /*int32_t*/;
583a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
584a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
585a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
586a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
587a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Returns number of bytes used, including *data.
588a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint DisassemblerIA32::F7Instruction(byte* data) {
589b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK_EQ(0xF7, *data);
590b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  byte modrm = *++data;
591a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int mod, regop, rm;
592a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  get_modrm(modrm, &mod, &regop, &rm);
593b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  const char* mnem = NULL;
594b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  switch (regop) {
595b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case 0:
596b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      mnem = "test";
597b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
598b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case 2:
599b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      mnem = "not";
600b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
601b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case 3:
602b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      mnem = "neg";
603b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
604b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case 4:
605b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      mnem = "mul";
606b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
607b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case 5:
608b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      mnem = "imul";
609b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
610b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case 6:
611b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      mnem = "div";
612b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
613b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case 7:
614b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      mnem = "idiv";
615b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
616b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    default:
617b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      UnimplementedInstruction();
618a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
619b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  AppendToBuffer("%s ", mnem);
620b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int count = PrintRightOperand(data);
621b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (regop == 0) {
622b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    AppendToBuffer(",0x%x", *reinterpret_cast<int32_t*>(data + count));
623b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    count += 4;
624b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
625b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return 1 + count;
626a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
627a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
628b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
629a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint DisassemblerIA32::D1D3C1Instruction(byte* data) {
630a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  byte op = *data;
631b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(op == 0xD1 || op == 0xD3 || op == 0xC1);
632b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  byte modrm = *++data;
633a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int mod, regop, rm;
634a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  get_modrm(modrm, &mod, &regop, &rm);
635a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int imm8 = -1;
636b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  const char* mnem = NULL;
637b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  switch (regop) {
638b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case kROL:
639b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      mnem = "rol";
640b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
641b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case kROR:
642b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      mnem = "ror";
643b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
644b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case kRCL:
645b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      mnem = "rcl";
646b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
647b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case kRCR:
648b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      mnem = "rcr";
649b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
650b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case kSHL:
651b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      mnem = "shl";
652b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
653b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case KSHR:
654b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      mnem = "shr";
655b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
656b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case kSAR:
657b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      mnem = "sar";
658b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
659b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    default:
660b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      UnimplementedInstruction();
661b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
662b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  AppendToBuffer("%s ", mnem);
663b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int count = PrintRightOperand(data);
664b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (op == 0xD1) {
665b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    imm8 = 1;
666b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else if (op == 0xC1) {
667b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    imm8 = *(data + 1);
668b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    count++;
669b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else if (op == 0xD3) {
670b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Shift/rotate by cl.
671b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
672b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (imm8 >= 0) {
673b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    AppendToBuffer(",%d", imm8);
674a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
675b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    AppendToBuffer(",cl");
676a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
677b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return 1 + count;
678a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
679a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
680a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
681a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Returns number of bytes used, including *data.
682a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint DisassemblerIA32::JumpShort(byte* data) {
683b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK_EQ(0xEB, *data);
684a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  byte b = *(data+1);
685a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  byte* dest = data + static_cast<int8_t>(b) + 2;
686a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  AppendToBuffer("jmp %s", NameOfAddress(dest));
687a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return 2;
688a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
689a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
690a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
691a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Returns number of bytes used, including *data.
692a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint DisassemblerIA32::JumpConditional(byte* data, const char* comment) {
693b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK_EQ(0x0F, *data);
694a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  byte cond = *(data+1) & 0x0F;
695a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  byte* dest = data + *reinterpret_cast<int32_t*>(data+2) + 6;
696a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const char* mnem = jump_conditional_mnem[cond];
697a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  AppendToBuffer("%s %s", mnem, NameOfAddress(dest));
698a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (comment != NULL) {
699a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    AppendToBuffer(", %s", comment);
700a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
701a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return 6;  // includes 0x0F
702a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
703a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
704a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
705a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Returns number of bytes used, including *data.
706a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint DisassemblerIA32::JumpConditionalShort(byte* data, const char* comment) {
707a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  byte cond = *data & 0x0F;
708a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  byte b = *(data+1);
709a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  byte* dest = data + static_cast<int8_t>(b) + 2;
710a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const char* mnem = jump_conditional_mnem[cond];
711a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  AppendToBuffer("%s %s", mnem, NameOfAddress(dest));
712a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (comment != NULL) {
713a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    AppendToBuffer(", %s", comment);
714a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
715a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return 2;
716a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
717a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
718a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
719a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Returns number of bytes used, including *data.
720a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint DisassemblerIA32::SetCC(byte* data) {
721b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK_EQ(0x0F, *data);
722a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  byte cond = *(data+1) & 0x0F;
723a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const char* mnem = set_conditional_mnem[cond];
724a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  AppendToBuffer("%s ", mnem);
725a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  PrintRightByteOperand(data+2);
726d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  return 3;  // Includes 0x0F.
727a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
728a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
729a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
730a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Returns number of bytes used, including *data.
7313ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockint DisassemblerIA32::CMov(byte* data) {
732b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK_EQ(0x0F, *data);
7333ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  byte cond = *(data + 1) & 0x0F;
7343ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  const char* mnem = conditional_move_mnem[cond];
7353ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  int op_size = PrintOperands(mnem, REG_OPER_OP_ORDER, data + 2);
7363ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  return 2 + op_size;  // includes 0x0F
7373ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
7383ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
7393ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
740958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernierint DisassemblerIA32::AVXInstruction(byte* data) {
741958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  byte opcode = *data;
742958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  byte* current = data + 1;
743958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  if (vex_66() && vex_0f38()) {
744958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    int mod, regop, rm, vvvv = vex_vreg();
745958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    get_modrm(*current, &mod, &regop, &rm);
746958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    switch (opcode) {
747958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      case 0x99:
748958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        AppendToBuffer("vfmadd132s%c %s,%s,", float_size_code(),
749958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                       NameOfXMMRegister(regop), NameOfXMMRegister(vvvv));
750958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        current += PrintRightXMMOperand(current);
751958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        break;
752958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      case 0xa9:
753958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        AppendToBuffer("vfmadd213s%c %s,%s,", float_size_code(),
754958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                       NameOfXMMRegister(regop), NameOfXMMRegister(vvvv));
755958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        current += PrintRightXMMOperand(current);
756958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        break;
757958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      case 0xb9:
758958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        AppendToBuffer("vfmadd231s%c %s,%s,", float_size_code(),
759958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                       NameOfXMMRegister(regop), NameOfXMMRegister(vvvv));
760958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        current += PrintRightXMMOperand(current);
761958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        break;
762958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      case 0x9b:
763958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        AppendToBuffer("vfmsub132s%c %s,%s,", float_size_code(),
764958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                       NameOfXMMRegister(regop), NameOfXMMRegister(vvvv));
765958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        current += PrintRightXMMOperand(current);
766958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        break;
767958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      case 0xab:
768958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        AppendToBuffer("vfmsub213s%c %s,%s,", float_size_code(),
769958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                       NameOfXMMRegister(regop), NameOfXMMRegister(vvvv));
770958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        current += PrintRightXMMOperand(current);
771958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        break;
772958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      case 0xbb:
773958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        AppendToBuffer("vfmsub231s%c %s,%s,", float_size_code(),
774958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                       NameOfXMMRegister(regop), NameOfXMMRegister(vvvv));
775958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        current += PrintRightXMMOperand(current);
776958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        break;
777958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      case 0x9d:
778958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        AppendToBuffer("vfnmadd132s%c %s,%s,", float_size_code(),
779958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                       NameOfXMMRegister(regop), NameOfXMMRegister(vvvv));
780958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        current += PrintRightXMMOperand(current);
781958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        break;
782958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      case 0xad:
783958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        AppendToBuffer("vfnmadd213s%c %s,%s,", float_size_code(),
784958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                       NameOfXMMRegister(regop), NameOfXMMRegister(vvvv));
785958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        current += PrintRightXMMOperand(current);
786958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        break;
787958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      case 0xbd:
788958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        AppendToBuffer("vfnmadd231s%c %s,%s,", float_size_code(),
789958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                       NameOfXMMRegister(regop), NameOfXMMRegister(vvvv));
790958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        current += PrintRightXMMOperand(current);
791958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        break;
792958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      case 0x9f:
793958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        AppendToBuffer("vfnmsub132s%c %s,%s,", float_size_code(),
794958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                       NameOfXMMRegister(regop), NameOfXMMRegister(vvvv));
795958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        current += PrintRightXMMOperand(current);
796958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        break;
797958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      case 0xaf:
798958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        AppendToBuffer("vfnmsub213s%c %s,%s,", float_size_code(),
799958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                       NameOfXMMRegister(regop), NameOfXMMRegister(vvvv));
800958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        current += PrintRightXMMOperand(current);
801958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        break;
802958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      case 0xbf:
803958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        AppendToBuffer("vfnmsub231s%c %s,%s,", float_size_code(),
804958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                       NameOfXMMRegister(regop), NameOfXMMRegister(vvvv));
805958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        current += PrintRightXMMOperand(current);
806958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        break;
807958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      default:
808958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        UnimplementedInstruction();
809958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    }
810958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  } else if (vex_f2() && vex_0f()) {
811958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    int mod, regop, rm, vvvv = vex_vreg();
812958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    get_modrm(*current, &mod, &regop, &rm);
813958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    switch (opcode) {
814958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      case 0x58:
815958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        AppendToBuffer("vaddsd %s,%s,", NameOfXMMRegister(regop),
816958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                       NameOfXMMRegister(vvvv));
817958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        current += PrintRightXMMOperand(current);
818958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        break;
819958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      case 0x59:
820958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        AppendToBuffer("vmulsd %s,%s,", NameOfXMMRegister(regop),
821958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                       NameOfXMMRegister(vvvv));
822958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        current += PrintRightXMMOperand(current);
823958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        break;
824958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      case 0x5c:
825958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        AppendToBuffer("vsubsd %s,%s,", NameOfXMMRegister(regop),
826958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                       NameOfXMMRegister(vvvv));
827958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        current += PrintRightXMMOperand(current);
828958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        break;
829958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      case 0x5e:
830958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        AppendToBuffer("vdivsd %s,%s,", NameOfXMMRegister(regop),
831958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                       NameOfXMMRegister(vvvv));
832958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        current += PrintRightXMMOperand(current);
833958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        break;
834958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      default:
835958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        UnimplementedInstruction();
836958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    }
837958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  } else {
838958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    UnimplementedInstruction();
839958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
840958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
841958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  return static_cast<int>(current - data);
842958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
843958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
844958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
8453ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// Returns number of bytes used, including *data.
846a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint DisassemblerIA32::FPUInstruction(byte* data) {
847d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  byte escape_opcode = *data;
848b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK_EQ(0xD8, escape_opcode & 0xF8);
849d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  byte modrm_byte = *(data+1);
850d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
851d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  if (modrm_byte >= 0xC0) {
852d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    return RegisterFPUInstruction(escape_opcode, modrm_byte);
853d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  } else {
854d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    return MemoryFPUInstruction(escape_opcode, modrm_byte, data+1);
855d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
856d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
857d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
858d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockint DisassemblerIA32::MemoryFPUInstruction(int escape_opcode,
859d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                                           int modrm_byte,
860d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                                           byte* modrm_start) {
861d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  const char* mnem = "?";
862d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  int regop = (modrm_byte >> 3) & 0x7;  // reg/op field of modrm byte.
863d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  switch (escape_opcode) {
864d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case 0xD9: switch (regop) {
865d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        case 0: mnem = "fld_s"; break;
866b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        case 2: mnem = "fst_s"; break;
867d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        case 3: mnem = "fstp_s"; break;
868d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        case 7: mnem = "fstcw"; break;
869a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        default: UnimplementedInstruction();
870a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
871d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
872d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
873d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case 0xDB: switch (regop) {
874d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        case 0: mnem = "fild_s"; break;
875d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        case 1: mnem = "fisttp_s"; break;
876d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        case 2: mnem = "fist_s"; break;
877d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        case 3: mnem = "fistp_s"; break;
878a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        default: UnimplementedInstruction();
879a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
880d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
881d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
882d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case 0xDD: switch (regop) {
883d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        case 0: mnem = "fld_d"; break;
8840d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        case 1: mnem = "fisttp_d"; break;
8850d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        case 2: mnem = "fst_d"; break;
886d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        case 3: mnem = "fstp_d"; break;
887d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        default: UnimplementedInstruction();
888d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      }
889d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
890d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
891d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case 0xDF: switch (regop) {
892d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        case 5: mnem = "fild_d"; break;
893d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        case 7: mnem = "fistp_d"; break;
894d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        default: UnimplementedInstruction();
895d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      }
896d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
897d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
898d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    default: UnimplementedInstruction();
899d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
900d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  AppendToBuffer("%s ", mnem);
901d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  int count = PrintRightOperand(modrm_start);
902d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  return count + 1;
903d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
904d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
905d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockint DisassemblerIA32::RegisterFPUInstruction(int escape_opcode,
906d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                                             byte modrm_byte) {
907d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  bool has_register = false;  // Is the FPU register encoded in modrm_byte?
908d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  const char* mnem = "?";
909d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
910d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  switch (escape_opcode) {
911d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case 0xD8:
912b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      has_register = true;
913b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      switch (modrm_byte & 0xF8) {
914b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        case 0xC0: mnem = "fadd_i"; break;
915b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        case 0xE0: mnem = "fsub_i"; break;
916b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        case 0xC8: mnem = "fmul_i"; break;
917b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        case 0xF0: mnem = "fdiv_i"; break;
918b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        default: UnimplementedInstruction();
919b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
920d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
921d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
922d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case 0xD9:
923d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      switch (modrm_byte & 0xF8) {
9240d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        case 0xC0:
9250d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          mnem = "fld";
9260d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          has_register = true;
9270d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          break;
928d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        case 0xC8:
929d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          mnem = "fxch";
930d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          has_register = true;
931d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          break;
932d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        default:
933d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          switch (modrm_byte) {
934d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block            case 0xE0: mnem = "fchs"; break;
935d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block            case 0xE1: mnem = "fabs"; break;
936d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block            case 0xE4: mnem = "ftst"; break;
937d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block            case 0xE8: mnem = "fld1"; break;
938402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu            case 0xEB: mnem = "fldpi"; break;
939b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            case 0xED: mnem = "fldln2"; break;
940d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block            case 0xEE: mnem = "fldz"; break;
9413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            case 0xF0: mnem = "f2xm1"; break;
942b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            case 0xF1: mnem = "fyl2x"; break;
943b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            case 0xF4: mnem = "fxtract"; break;
944d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block            case 0xF5: mnem = "fprem1"; break;
945d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block            case 0xF7: mnem = "fincstp"; break;
946d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block            case 0xF8: mnem = "fprem"; break;
9473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            case 0xFC: mnem = "frndint"; break;
9483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            case 0xFD: mnem = "fscale"; break;
949d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block            case 0xFE: mnem = "fsin"; break;
950d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block            case 0xFF: mnem = "fcos"; break;
951d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block            default: UnimplementedInstruction();
952d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          }
953d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      }
954d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
955d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
956d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case 0xDA:
957d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      if (modrm_byte == 0xE9) {
958d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        mnem = "fucompp";
959d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      } else {
960d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        UnimplementedInstruction();
961d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      }
962d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
963d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
964d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case 0xDB:
965d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      if ((modrm_byte & 0xF8) == 0xE8) {
966d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        mnem = "fucomi";
967d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        has_register = true;
968d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      } else if (modrm_byte  == 0xE2) {
969d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        mnem = "fclex";
9703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      } else if (modrm_byte == 0xE3) {
9713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        mnem = "fninit";
972d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      } else {
973d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        UnimplementedInstruction();
974d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      }
975d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
976d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
977d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case 0xDC:
978d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      has_register = true;
979d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      switch (modrm_byte & 0xF8) {
980d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        case 0xC0: mnem = "fadd"; break;
981d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        case 0xE8: mnem = "fsub"; break;
982d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        case 0xC8: mnem = "fmul"; break;
983d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        case 0xF8: mnem = "fdiv"; break;
984d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        default: UnimplementedInstruction();
985d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      }
986d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
987d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
988d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case 0xDD:
989d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      has_register = true;
990d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      switch (modrm_byte & 0xF8) {
991d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        case 0xC0: mnem = "ffree"; break;
992b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        case 0xD0: mnem = "fst"; break;
993d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        case 0xD8: mnem = "fstp"; break;
994d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        default: UnimplementedInstruction();
995d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      }
996d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
997d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
998d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case 0xDE:
999d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      if (modrm_byte  == 0xD9) {
1000d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        mnem = "fcompp";
1001d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      } else {
1002d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        has_register = true;
1003d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        switch (modrm_byte & 0xF8) {
1004d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          case 0xC0: mnem = "faddp"; break;
1005d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          case 0xE8: mnem = "fsubp"; break;
1006d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          case 0xC8: mnem = "fmulp"; break;
1007d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          case 0xF8: mnem = "fdivp"; break;
1008d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          default: UnimplementedInstruction();
1009d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        }
1010d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      }
1011d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
1012d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1013d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case 0xDF:
1014d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      if (modrm_byte == 0xE0) {
1015d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        mnem = "fnstsw_ax";
1016d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      } else if ((modrm_byte & 0xF8) == 0xE8) {
1017d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        mnem = "fucomip";
1018d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        has_register = true;
1019d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      }
1020d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
1021d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1022d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    default: UnimplementedInstruction();
1023d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
1024d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1025d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  if (has_register) {
1026d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    AppendToBuffer("%s st%d", mnem, modrm_byte & 0x7);
1027d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  } else {
1028a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    AppendToBuffer("%s", mnem);
1029a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1030a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return 2;
1031a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1032a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1033a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1034a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Mnemonics for instructions 0xF0 byte.
1035a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Returns NULL if the instruction is not handled here.
1036a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic const char* F0Mnem(byte f0byte) {
1037a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  switch (f0byte) {
10387f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    case 0x18: return "prefetch";
1039a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case 0xA2: return "cpuid";
1040a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case 0xBE: return "movsx_b";
1041a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case 0xBF: return "movsx_w";
1042a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case 0xB6: return "movzx_b";
1043a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case 0xB7: return "movzx_w";
1044a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case 0xAF: return "imul";
1045a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case 0xA5: return "shld";
1046a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case 0xAD: return "shrd";
1047b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case 0xAC: return "shrd";  // 3-operand version.
1048a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case 0xAB: return "bts";
1049b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case 0xBD: return "bsr";
1050a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    default: return NULL;
1051a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1052a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1053a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1054a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1055a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Disassembled instruction '*instr' and writes it into 'out_buffer'.
1056a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint DisassemblerIA32::InstructionDecode(v8::internal::Vector<char> out_buffer,
1057a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                        byte* instr) {
1058a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  tmp_buffer_pos_ = 0;  // starting to write as position 0
1059a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  byte* data = instr;
1060a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check for hints.
1061a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const char* branch_hint = NULL;
1062a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // We use these two prefixes only with branch prediction
1063a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (*data == 0x3E /*ds*/) {
1064a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    branch_hint = "predicted taken";
1065a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    data++;
1066a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else if (*data == 0x2E /*cs*/) {
1067a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    branch_hint = "predicted not taken";
1068a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    data++;
1069958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  } else if (*data == 0xC4 && *(data + 1) >= 0xc0) {
1070958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    vex_byte0_ = *data;
1071958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    vex_byte1_ = *(data + 1);
1072958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    vex_byte2_ = *(data + 2);
1073958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    data += 3;
1074958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  } else if (*data == 0xC5 && *(data + 1) >= 0xc0) {
1075958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    vex_byte0_ = *data;
1076958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    vex_byte1_ = *(data + 1);
1077958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    data += 2;
1078a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1079958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1080a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bool processed = true;  // Will be set to false if the current instruction
1081a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                          // is not in 'instructions' table.
1082958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Decode AVX instructions.
1083958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  if (vex_byte0_ != 0) {
1084958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    data += AVXInstruction(data);
1085958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  } else {
1086958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    const InstructionDesc& idesc = instruction_table_->Get(*data);
1087958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    switch (idesc.type) {
1088958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      case ZERO_OPERANDS_INSTR:
1089958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        AppendToBuffer(idesc.mnem);
1090958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        data++;
1091958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        break;
1092a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1093958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      case TWO_OPERANDS_INSTR:
1094958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        data++;
1095958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        data += PrintOperands(idesc.mnem, idesc.op_order_, data);
1096958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        break;
1097a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1098958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      case JUMP_CONDITIONAL_SHORT_INSTR:
1099958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        data += JumpConditionalShort(data, branch_hint);
1100958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        break;
1101a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1102958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      case REGISTER_INSTR:
1103958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        AppendToBuffer("%s %s", idesc.mnem, NameOfCPURegister(*data & 0x07));
1104958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        data++;
1105958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        break;
1106a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1107958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      case MOVE_REG_INSTR: {
1108958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        byte* addr =
1109958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier            reinterpret_cast<byte*>(*reinterpret_cast<int32_t*>(data + 1));
1110958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        AppendToBuffer("mov %s,%s", NameOfCPURegister(*data & 0x07),
1111958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                       NameOfAddress(addr));
1112958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        data += 5;
1113958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        break;
1114958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      }
1115a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1116958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      case CALL_JUMP_INSTR: {
1117958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        byte* addr = data + *reinterpret_cast<int32_t*>(data + 1) + 5;
1118958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        AppendToBuffer("%s %s", idesc.mnem, NameOfAddress(addr));
1119958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        data += 5;
1120958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        break;
1121958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      }
1122a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1123958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      case SHORT_IMMEDIATE_INSTR: {
1124958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        byte* addr =
1125958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier            reinterpret_cast<byte*>(*reinterpret_cast<int32_t*>(data + 1));
1126958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        AppendToBuffer("%s eax,%s", idesc.mnem, NameOfAddress(addr));
1127958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        data += 5;
1128958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        break;
1129958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      }
1130a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1131958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      case BYTE_IMMEDIATE_INSTR: {
1132958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        AppendToBuffer("%s al,0x%x", idesc.mnem, data[1]);
1133958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        data += 2;
1134958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        break;
1135958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      }
11363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1137958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      case NO_INSTR:
1138958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        processed = false;
1139958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        break;
1140a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1141958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      default:
1142958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        UNIMPLEMENTED();  // This type is not implemented.
1143958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    }
1144a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1145a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //----------------------------
1146a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (!processed) {
1147a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    switch (*data) {
1148a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 0xC2:
1149a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        AppendToBuffer("ret 0x%x", *reinterpret_cast<uint16_t*>(data+1));
1150a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        data += 3;
1151a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
1152a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1153b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case 0x6B: {
1154b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        data++;
1155b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        data += PrintOperands("imul", REG_OPER_OP_ORDER, data);
1156b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        AppendToBuffer(",%d", *data);
1157b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        data++;
1158b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      } break;
1159b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1160b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case 0x69: {
1161b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        data++;
1162b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        data += PrintOperands("imul", REG_OPER_OP_ORDER, data);
1163b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        AppendToBuffer(",%d", *reinterpret_cast<int32_t*>(data));
1164b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        data += 4;
1165a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        }
1166a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
1167a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1168a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 0xF6:
11697f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch        { data++;
11707f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch          int mod, regop, rm;
11717f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch          get_modrm(*data, &mod, &regop, &rm);
11727f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch          if (regop == eax) {
11737f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch            AppendToBuffer("test_b ");
117444f0eee88ff00398ff7f715fab053374d808c90dSteve Block            data += PrintRightByteOperand(data);
11757f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch            int32_t imm = *data;
11767f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch            AppendToBuffer(",0x%x", imm);
11777f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch            data++;
1178a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          } else {
1179a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            UnimplementedInstruction();
1180a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          }
1181a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        }
1182a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
1183a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1184a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 0x81:  // fall through
1185a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 0x83:  // 0x81 with sign extension bit set
1186a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        data += PrintImmediateOp(data);
1187a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
1188a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1189a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 0x0F:
11903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        { byte f0byte = data[1];
1191a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          const char* f0mnem = F0Mnem(f0byte);
11927f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch          if (f0byte == 0x18) {
1193b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            data += 2;
11947f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch            int mod, regop, rm;
11957f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch            get_modrm(*data, &mod, &regop, &rm);
11967f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch            const char* suffix[] = {"nta", "1", "2", "3"};
11977f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch            AppendToBuffer("%s%s ", f0mnem, suffix[regop & 0x03]);
11987f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch            data += PrintRightOperand(data);
11993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          } else if (f0byte == 0x1F && data[2] == 0) {
12003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            AppendToBuffer("nop");  // 3 byte nop.
12013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            data += 3;
12023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          } else if (f0byte == 0x1F && data[2] == 0x40 && data[3] == 0) {
12033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            AppendToBuffer("nop");  // 4 byte nop.
12043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            data += 4;
12053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          } else if (f0byte == 0x1F && data[2] == 0x44 && data[3] == 0 &&
12063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                     data[4] == 0) {
12073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            AppendToBuffer("nop");  // 5 byte nop.
12083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            data += 5;
12093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          } else if (f0byte == 0x1F && data[2] == 0x80 && data[3] == 0 &&
12103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                     data[4] == 0 && data[5] == 0 && data[6] == 0) {
12113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            AppendToBuffer("nop");  // 7 byte nop.
12123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            data += 7;
12133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          } else if (f0byte == 0x1F && data[2] == 0x84 && data[3] == 0 &&
12143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                     data[4] == 0 && data[5] == 0 && data[6] == 0 &&
12153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                     data[7] == 0) {
12163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            AppendToBuffer("nop");  // 8 byte nop.
12173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            data += 8;
12187f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch          } else if (f0byte == 0xA2 || f0byte == 0x31) {
1219a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            AppendToBuffer("%s", f0mnem);
1220a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            data += 2;
12210d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          } else if (f0byte == 0x28) {
12220d5e116f6aee03185f237311a943491bb079a768Kristian Monsen            data += 2;
12230d5e116f6aee03185f237311a943491bb079a768Kristian Monsen            int mod, regop, rm;
12240d5e116f6aee03185f237311a943491bb079a768Kristian Monsen            get_modrm(*data, &mod, &regop, &rm);
12250d5e116f6aee03185f237311a943491bb079a768Kristian Monsen            AppendToBuffer("movaps %s,%s",
12260d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                           NameOfXMMRegister(regop),
12270d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                           NameOfXMMRegister(rm));
12280d5e116f6aee03185f237311a943491bb079a768Kristian Monsen            data++;
1229958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier          } else if (f0byte == 0x2e) {
1230958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier            data += 2;
1231958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier            int mod, regop, rm;
1232958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier            get_modrm(*data, &mod, &regop, &rm);
1233958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier            AppendToBuffer("ucomiss %s,", NameOfXMMRegister(regop));
1234958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier            data += PrintRightXMMOperand(data);
1235b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          } else if (f0byte >= 0x53 && f0byte <= 0x5F) {
1236b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            const char* const pseudo_op[] = {
1237b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch              "rcpps",
1238b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch              "andps",
1239b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch              "andnps",
1240b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch              "orps",
1241b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch              "xorps",
1242b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch              "addps",
1243b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch              "mulps",
1244b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch              "cvtps2pd",
1245b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch              "cvtdq2ps",
1246b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch              "subps",
1247b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch              "minps",
1248b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch              "divps",
1249b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch              "maxps",
1250b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            };
1251b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1252257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch            data += 2;
1253257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch            int mod, regop, rm;
1254257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch            get_modrm(*data, &mod, &regop, &rm);
1255b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            AppendToBuffer("%s %s,",
1256b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                           pseudo_op[f0byte - 0x53],
1257b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                           NameOfXMMRegister(regop));
1258b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            data += PrintRightXMMOperand(data);
1259b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          } else if (f0byte == 0x50) {
1260b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            data += 2;
1261b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            int mod, regop, rm;
1262b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            get_modrm(*data, &mod, &regop, &rm);
1263b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            AppendToBuffer("movmskps %s,%s",
1264b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                           NameOfCPURegister(regop),
1265257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                           NameOfXMMRegister(rm));
1266257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch            data++;
1267b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          } else if (f0byte== 0xC6) {
1268b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            // shufps xmm, xmm/m128, imm8
1269b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            data += 2;
1270b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            int mod, regop, rm;
1271b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            get_modrm(*data, &mod, &regop, &rm);
1272b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            int8_t imm8 = static_cast<int8_t>(data[1]);
1273b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            AppendToBuffer("shufps %s,%s,%d",
1274b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                            NameOfXMMRegister(rm),
1275b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                            NameOfXMMRegister(regop),
1276b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                            static_cast<int>(imm8));
1277b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            data += 2;
1278a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          } else if ((f0byte & 0xF0) == 0x80) {
1279a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            data += JumpConditional(data, branch_hint);
1280a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          } else if (f0byte == 0xBE || f0byte == 0xBF || f0byte == 0xB6 ||
1281a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                     f0byte == 0xB7 || f0byte == 0xAF) {
1282a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            data += 2;
1283a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            data += PrintOperands(f0mnem, REG_OPER_OP_ORDER, data);
1284a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          } else if ((f0byte & 0xF0) == 0x90) {
1285a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            data += SetCC(data);
12863ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block          } else if ((f0byte & 0xF0) == 0x40) {
12873ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block            data += CMov(data);
1288b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          } else if (f0byte == 0xAB || f0byte == 0xA5 || f0byte == 0xAD) {
1289b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            // shrd, shld, bts
1290a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            data += 2;
1291b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            AppendToBuffer("%s ", f0mnem);
1292b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            int mod, regop, rm;
1293b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            get_modrm(*data, &mod, &regop, &rm);
1294b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            data += PrintRightOperand(data);
1295b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            if (f0byte == 0xAB) {
1296b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch              AppendToBuffer(",%s", NameOfCPURegister(regop));
1297a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            } else {
1298b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch              AppendToBuffer(",%s,cl", NameOfCPURegister(regop));
1299a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            }
1300b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          } else if (f0byte == 0xBD) {
1301b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            data += 2;
1302b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            int mod, regop, rm;
1303b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            get_modrm(*data, &mod, &regop, &rm);
1304b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            AppendToBuffer("%s %s,", f0mnem, NameOfCPURegister(regop));
1305b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            data += PrintRightOperand(data);
1306b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          } else {
1307b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            UnimplementedInstruction();
1308a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          }
1309a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        }
1310a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
1311a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1312a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 0x8F:
1313a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        { data++;
1314a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          int mod, regop, rm;
1315a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          get_modrm(*data, &mod, &regop, &rm);
1316a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          if (regop == eax) {
1317a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            AppendToBuffer("pop ");
1318a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            data += PrintRightOperand(data);
1319a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          }
1320a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        }
1321a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
1322a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1323a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 0xFF:
1324a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        { data++;
1325a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          int mod, regop, rm;
1326a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          get_modrm(*data, &mod, &regop, &rm);
1327a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          const char* mnem = NULL;
1328a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          switch (regop) {
1329a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            case esi: mnem = "push"; break;
1330a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            case eax: mnem = "inc"; break;
1331a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            case ecx: mnem = "dec"; break;
1332a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            case edx: mnem = "call"; break;
1333a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            case esp: mnem = "jmp"; break;
1334a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            default: mnem = "???";
1335a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          }
1336a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          AppendToBuffer("%s ", mnem);
1337a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          data += PrintRightOperand(data);
1338a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        }
1339a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
1340a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1341a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 0xC7:  // imm32, fall through
1342a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 0xC6:  // imm8
1343a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        { bool is_byte = *data == 0xC6;
1344a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          data++;
134544f0eee88ff00398ff7f715fab053374d808c90dSteve Block          if (is_byte) {
134644f0eee88ff00398ff7f715fab053374d808c90dSteve Block            AppendToBuffer("%s ", "mov_b");
134744f0eee88ff00398ff7f715fab053374d808c90dSteve Block            data += PrintRightByteOperand(data);
134844f0eee88ff00398ff7f715fab053374d808c90dSteve Block            int32_t imm = *data;
134944f0eee88ff00398ff7f715fab053374d808c90dSteve Block            AppendToBuffer(",0x%x", imm);
135044f0eee88ff00398ff7f715fab053374d808c90dSteve Block            data++;
135144f0eee88ff00398ff7f715fab053374d808c90dSteve Block          } else {
135244f0eee88ff00398ff7f715fab053374d808c90dSteve Block            AppendToBuffer("%s ", "mov");
135344f0eee88ff00398ff7f715fab053374d808c90dSteve Block            data += PrintRightOperand(data);
135444f0eee88ff00398ff7f715fab053374d808c90dSteve Block            int32_t imm = *reinterpret_cast<int32_t*>(data);
135544f0eee88ff00398ff7f715fab053374d808c90dSteve Block            AppendToBuffer(",0x%x", imm);
135644f0eee88ff00398ff7f715fab053374d808c90dSteve Block            data += 4;
135744f0eee88ff00398ff7f715fab053374d808c90dSteve Block          }
1358a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        }
1359a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
1360a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1361a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 0x80:
1362a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        { data++;
1363e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          int mod, regop, rm;
1364e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          get_modrm(*data, &mod, &regop, &rm);
1365e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          const char* mnem = NULL;
1366e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          switch (regop) {
1367e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke            case 5:  mnem = "subb"; break;
1368e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke            case 7:  mnem = "cmpb"; break;
1369e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke            default: UnimplementedInstruction();
1370e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          }
1371e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          AppendToBuffer("%s ", mnem);
137244f0eee88ff00398ff7f715fab053374d808c90dSteve Block          data += PrintRightByteOperand(data);
1373a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          int32_t imm = *data;
1374a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          AppendToBuffer(",0x%x", imm);
1375a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          data++;
1376a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        }
1377a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
1378a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1379a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 0x88:  // 8bit, fall through
1380a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 0x89:  // 32bit
1381a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        { bool is_byte = *data == 0x88;
1382a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          int mod, regop, rm;
1383a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          data++;
1384a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          get_modrm(*data, &mod, &regop, &rm);
138544f0eee88ff00398ff7f715fab053374d808c90dSteve Block          if (is_byte) {
138644f0eee88ff00398ff7f715fab053374d808c90dSteve Block            AppendToBuffer("%s ", "mov_b");
138744f0eee88ff00398ff7f715fab053374d808c90dSteve Block            data += PrintRightByteOperand(data);
138844f0eee88ff00398ff7f715fab053374d808c90dSteve Block            AppendToBuffer(",%s", NameOfByteCPURegister(regop));
138944f0eee88ff00398ff7f715fab053374d808c90dSteve Block          } else {
139044f0eee88ff00398ff7f715fab053374d808c90dSteve Block            AppendToBuffer("%s ", "mov");
139144f0eee88ff00398ff7f715fab053374d808c90dSteve Block            data += PrintRightOperand(data);
139244f0eee88ff00398ff7f715fab053374d808c90dSteve Block            AppendToBuffer(",%s", NameOfCPURegister(regop));
139344f0eee88ff00398ff7f715fab053374d808c90dSteve Block          }
1394a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        }
1395a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
1396a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1397a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 0x66:  // prefix
13983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        while (*data == 0x66) data++;
13993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        if (*data == 0xf && data[1] == 0x1f) {
14003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          AppendToBuffer("nop");  // 0x66 prefix
14013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        } else if (*data == 0x90) {
14023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          AppendToBuffer("nop");  // 0x66 prefix
14033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        } else if (*data == 0x8B) {
1404a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          data++;
1405a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          data += PrintOperands("mov_w", REG_OPER_OP_ORDER, data);
1406a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        } else if (*data == 0x89) {
1407a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          data++;
1408a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          int mod, regop, rm;
1409a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          get_modrm(*data, &mod, &regop, &rm);
1410a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          AppendToBuffer("mov_w ");
1411a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          data += PrintRightOperand(data);
1412a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          AppendToBuffer(",%s", NameOfCPURegister(regop));
1413b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        } else if (*data == 0xC7) {
1414b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          data++;
1415b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          AppendToBuffer("%s ", "mov_w");
1416b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          data += PrintRightOperand(data);
1417b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          int imm = *reinterpret_cast<int16_t*>(data);
1418b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          AppendToBuffer(",0x%x", imm);
1419b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          data += 2;
14203ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block        } else if (*data == 0x0F) {
14213ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block          data++;
14226ded16be15dd865a9b21ea304d5273c8be299c87Steve Block          if (*data == 0x38) {
14236ded16be15dd865a9b21ea304d5273c8be299c87Steve Block            data++;
14246ded16be15dd865a9b21ea304d5273c8be299c87Steve Block            if (*data == 0x17) {
14256ded16be15dd865a9b21ea304d5273c8be299c87Steve Block              data++;
14266ded16be15dd865a9b21ea304d5273c8be299c87Steve Block              int mod, regop, rm;
14276ded16be15dd865a9b21ea304d5273c8be299c87Steve Block              get_modrm(*data, &mod, &regop, &rm);
14286ded16be15dd865a9b21ea304d5273c8be299c87Steve Block              AppendToBuffer("ptest %s,%s",
14296ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                             NameOfXMMRegister(regop),
14306ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                             NameOfXMMRegister(rm));
14316ded16be15dd865a9b21ea304d5273c8be299c87Steve Block              data++;
14327f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch            } else if (*data == 0x2A) {
14337f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch              // movntdqa
14347f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch              data++;
14357f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch              int mod, regop, rm;
14367f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch              get_modrm(*data, &mod, &regop, &rm);
14377f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch              AppendToBuffer("movntdqa %s,", NameOfXMMRegister(regop));
14387f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch              data += PrintRightOperand(data);
14396ded16be15dd865a9b21ea304d5273c8be299c87Steve Block            } else {
14406ded16be15dd865a9b21ea304d5273c8be299c87Steve Block              UnimplementedInstruction();
14416ded16be15dd865a9b21ea304d5273c8be299c87Steve Block            }
1442b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          } else if (*data == 0x3A) {
1443b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            data++;
144469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch            if (*data == 0x0B) {
144569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch              data++;
144669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch              int mod, regop, rm;
144769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch              get_modrm(*data, &mod, &regop, &rm);
144869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch              int8_t imm8 = static_cast<int8_t>(data[1]);
144969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch              AppendToBuffer("roundsd %s,%s,%d",
145069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch                             NameOfXMMRegister(regop),
145169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch                             NameOfXMMRegister(rm),
145269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch                             static_cast<int>(imm8));
145369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch              data += 2;
145469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch            } else if (*data == 0x16) {
1455b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch              data++;
1456b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch              int mod, regop, rm;
1457b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch              get_modrm(*data, &mod, &regop, &rm);
1458b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch              int8_t imm8 = static_cast<int8_t>(data[1]);
1459b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch              AppendToBuffer("pextrd %s,%s,%d",
14601e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                             NameOfCPURegister(regop),
1461b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                             NameOfXMMRegister(rm),
1462b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                             static_cast<int>(imm8));
1463b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch              data += 2;
14643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            } else if (*data == 0x17) {
14653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch              data++;
14663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch              int mod, regop, rm;
14673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch              get_modrm(*data, &mod, &regop, &rm);
14683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch              int8_t imm8 = static_cast<int8_t>(data[1]);
14693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch              AppendToBuffer("extractps %s,%s,%d",
1470b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                             NameOfCPURegister(rm),
1471b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                             NameOfXMMRegister(regop),
14723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                             static_cast<int>(imm8));
14733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch              data += 2;
14741e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block            } else if (*data == 0x22) {
14751e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block              data++;
14761e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block              int mod, regop, rm;
14771e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block              get_modrm(*data, &mod, &regop, &rm);
14781e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block              int8_t imm8 = static_cast<int8_t>(data[1]);
14791e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block              AppendToBuffer("pinsrd %s,%s,%d",
14801e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                             NameOfXMMRegister(regop),
14811e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                             NameOfCPURegister(rm),
14821e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                             static_cast<int>(imm8));
14831e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block              data += 2;
1484b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            } else {
1485b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch              UnimplementedInstruction();
1486b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            }
14876ded16be15dd865a9b21ea304d5273c8be299c87Steve Block          } else if (*data == 0x2E || *data == 0x2F) {
14886ded16be15dd865a9b21ea304d5273c8be299c87Steve Block            const char* mnem = (*data == 0x2E) ? "ucomisd" : "comisd";
14893ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block            data++;
14903ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block            int mod, regop, rm;
14913ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block            get_modrm(*data, &mod, &regop, &rm);
14926ded16be15dd865a9b21ea304d5273c8be299c87Steve Block            if (mod == 0x3) {
14936ded16be15dd865a9b21ea304d5273c8be299c87Steve Block              AppendToBuffer("%s %s,%s", mnem,
14946ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                             NameOfXMMRegister(regop),
14956ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                             NameOfXMMRegister(rm));
14966ded16be15dd865a9b21ea304d5273c8be299c87Steve Block              data++;
14976ded16be15dd865a9b21ea304d5273c8be299c87Steve Block            } else {
14986ded16be15dd865a9b21ea304d5273c8be299c87Steve Block              AppendToBuffer("%s %s,", mnem, NameOfXMMRegister(regop));
14996ded16be15dd865a9b21ea304d5273c8be299c87Steve Block              data += PrintRightOperand(data);
15006ded16be15dd865a9b21ea304d5273c8be299c87Steve Block            }
15016ded16be15dd865a9b21ea304d5273c8be299c87Steve Block          } else if (*data == 0x50) {
15026ded16be15dd865a9b21ea304d5273c8be299c87Steve Block            data++;
15036ded16be15dd865a9b21ea304d5273c8be299c87Steve Block            int mod, regop, rm;
15046ded16be15dd865a9b21ea304d5273c8be299c87Steve Block            get_modrm(*data, &mod, &regop, &rm);
15056ded16be15dd865a9b21ea304d5273c8be299c87Steve Block            AppendToBuffer("movmskpd %s,%s",
15066ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                           NameOfCPURegister(regop),
15073ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                           NameOfXMMRegister(rm));
15083ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block            data++;
1509b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          } else if (*data == 0x54) {
1510b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            data++;
1511b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            int mod, regop, rm;
1512b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            get_modrm(*data, &mod, &regop, &rm);
1513b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            AppendToBuffer("andpd %s,%s",
1514b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                           NameOfXMMRegister(regop),
1515b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                           NameOfXMMRegister(rm));
1516b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            data++;
1517b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          } else if (*data == 0x56) {
1518b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            data++;
1519b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            int mod, regop, rm;
1520b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            get_modrm(*data, &mod, &regop, &rm);
1521b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            AppendToBuffer("orpd %s,%s",
1522b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                           NameOfXMMRegister(regop),
1523b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                           NameOfXMMRegister(rm));
1524b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            data++;
1525e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          } else if (*data == 0x57) {
1526e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke            data++;
1527e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke            int mod, regop, rm;
1528e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke            get_modrm(*data, &mod, &regop, &rm);
1529e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke            AppendToBuffer("xorpd %s,%s",
1530e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                           NameOfXMMRegister(regop),
1531e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                           NameOfXMMRegister(rm));
1532e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke            data++;
15336ded16be15dd865a9b21ea304d5273c8be299c87Steve Block          } else if (*data == 0x6E) {
15346ded16be15dd865a9b21ea304d5273c8be299c87Steve Block            data++;
15356ded16be15dd865a9b21ea304d5273c8be299c87Steve Block            int mod, regop, rm;
15366ded16be15dd865a9b21ea304d5273c8be299c87Steve Block            get_modrm(*data, &mod, &regop, &rm);
15376ded16be15dd865a9b21ea304d5273c8be299c87Steve Block            AppendToBuffer("movd %s,", NameOfXMMRegister(regop));
15386ded16be15dd865a9b21ea304d5273c8be299c87Steve Block            data += PrintRightOperand(data);
1539e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          } else if (*data == 0x6F) {
1540e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke            data++;
1541e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke            int mod, regop, rm;
1542e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke            get_modrm(*data, &mod, &regop, &rm);
1543e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke            AppendToBuffer("movdqa %s,", NameOfXMMRegister(regop));
154444f0eee88ff00398ff7f715fab053374d808c90dSteve Block            data += PrintRightXMMOperand(data);
1545b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          } else if (*data == 0x70) {
1546b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            data++;
1547b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            int mod, regop, rm;
1548b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            get_modrm(*data, &mod, &regop, &rm);
1549b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            int8_t imm8 = static_cast<int8_t>(data[1]);
1550b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            AppendToBuffer("pshufd %s,%s,%d",
1551b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                           NameOfXMMRegister(regop),
1552b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                           NameOfXMMRegister(rm),
1553b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                           static_cast<int>(imm8));
1554b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            data += 2;
1555b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          } else if (*data == 0x76) {
1556b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            data++;
1557b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            int mod, regop, rm;
1558b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            get_modrm(*data, &mod, &regop, &rm);
1559b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            AppendToBuffer("pcmpeqd %s,%s",
1560b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                           NameOfXMMRegister(regop),
1561b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                           NameOfXMMRegister(rm));
1562b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            data++;
15633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          } else if (*data == 0x90) {
15643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            data++;
15653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            AppendToBuffer("nop");  // 2 byte nop.
1566b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch          } else if (*data == 0xF3) {
1567b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch            data++;
1568b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch            int mod, regop, rm;
1569b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch            get_modrm(*data, &mod, &regop, &rm);
1570b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch            AppendToBuffer("psllq %s,%s",
1571b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch                           NameOfXMMRegister(regop),
1572b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch                           NameOfXMMRegister(rm));
1573b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch            data++;
1574958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier          } else if (*data == 0x72) {
1575958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier            data++;
1576958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier            int mod, regop, rm;
1577958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier            get_modrm(*data, &mod, &regop, &rm);
1578958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier            int8_t imm8 = static_cast<int8_t>(data[1]);
1579958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier            DCHECK(regop == esi || regop == edx);
1580958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier            AppendToBuffer("%s %s,%d", (regop == esi) ? "pslld" : "psrld",
1581958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                           NameOfXMMRegister(rm), static_cast<int>(imm8));
1582958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier            data += 2;
1583b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          } else if (*data == 0x73) {
1584b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            data++;
1585b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            int mod, regop, rm;
1586b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            get_modrm(*data, &mod, &regop, &rm);
1587b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            int8_t imm8 = static_cast<int8_t>(data[1]);
1588b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            DCHECK(regop == esi || regop == edx);
1589b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch            AppendToBuffer("%s %s,%d",
1590b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch                           (regop == esi) ? "psllq" : "psrlq",
1591b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                           NameOfXMMRegister(rm),
1592b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                           static_cast<int>(imm8));
1593b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            data += 2;
1594b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch          } else if (*data == 0xD3) {
1595b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch            data++;
1596b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch            int mod, regop, rm;
1597b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch            get_modrm(*data, &mod, &regop, &rm);
1598b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch            AppendToBuffer("psrlq %s,%s",
1599b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch                           NameOfXMMRegister(regop),
1600b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch                           NameOfXMMRegister(rm));
1601b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch            data++;
1602e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          } else if (*data == 0x7F) {
1603e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke            AppendToBuffer("movdqa ");
1604e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke            data++;
1605e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke            int mod, regop, rm;
1606e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke            get_modrm(*data, &mod, &regop, &rm);
160744f0eee88ff00398ff7f715fab053374d808c90dSteve Block            data += PrintRightXMMOperand(data);
1608e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke            AppendToBuffer(",%s", NameOfXMMRegister(regop));
1609b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          } else if (*data == 0x7E) {
1610b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            data++;
1611b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            int mod, regop, rm;
1612b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            get_modrm(*data, &mod, &regop, &rm);
1613b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            AppendToBuffer("movd ");
1614b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            data += PrintRightOperand(data);
1615b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            AppendToBuffer(",%s", NameOfXMMRegister(regop));
1616b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          } else if (*data == 0xDB) {
1617b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            data++;
1618b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            int mod, regop, rm;
1619b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            get_modrm(*data, &mod, &regop, &rm);
1620b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            AppendToBuffer("pand %s,%s",
1621b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                           NameOfXMMRegister(regop),
1622b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                           NameOfXMMRegister(rm));
1623b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            data++;
16247f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch          } else if (*data == 0xE7) {
16257f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch            data++;
16267f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch            int mod, regop, rm;
16277f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch            get_modrm(*data, &mod, &regop, &rm);
162844f0eee88ff00398ff7f715fab053374d808c90dSteve Block            if (mod == 3) {
162944f0eee88ff00398ff7f715fab053374d808c90dSteve Block              AppendToBuffer("movntdq ");
163044f0eee88ff00398ff7f715fab053374d808c90dSteve Block              data += PrintRightOperand(data);
163144f0eee88ff00398ff7f715fab053374d808c90dSteve Block              AppendToBuffer(",%s", NameOfXMMRegister(regop));
163244f0eee88ff00398ff7f715fab053374d808c90dSteve Block            } else {
163344f0eee88ff00398ff7f715fab053374d808c90dSteve Block              UnimplementedInstruction();
163444f0eee88ff00398ff7f715fab053374d808c90dSteve Block            }
16356ded16be15dd865a9b21ea304d5273c8be299c87Steve Block          } else if (*data == 0xEF) {
1636b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            data++;
1637b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            int mod, regop, rm;
1638b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            get_modrm(*data, &mod, &regop, &rm);
1639b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            AppendToBuffer("pxor %s,%s",
1640b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                           NameOfXMMRegister(regop),
1641b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                           NameOfXMMRegister(rm));
1642b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            data++;
1643b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch          } else if (*data == 0xEB) {
1644b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch            data++;
1645b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch            int mod, regop, rm;
1646b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch            get_modrm(*data, &mod, &regop, &rm);
1647b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch            AppendToBuffer("por %s,%s",
1648b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch                           NameOfXMMRegister(regop),
1649b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch                           NameOfXMMRegister(rm));
1650b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch            data++;
16513ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block          } else {
16523ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block            UnimplementedInstruction();
16533ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block          }
1654a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        } else {
1655a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          UnimplementedInstruction();
1656a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        }
1657a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
1658a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1659a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 0xFE:
1660a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        { data++;
1661a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          int mod, regop, rm;
1662a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          get_modrm(*data, &mod, &regop, &rm);
16630d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          if (regop == ecx) {
16640d5e116f6aee03185f237311a943491bb079a768Kristian Monsen            AppendToBuffer("dec_b ");
16650d5e116f6aee03185f237311a943491bb079a768Kristian Monsen            data += PrintRightOperand(data);
1666a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          } else {
1667a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            UnimplementedInstruction();
1668a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          }
1669a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        }
1670a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
1671a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1672a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 0x68:
1673a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        AppendToBuffer("push 0x%x", *reinterpret_cast<int32_t*>(data+1));
1674a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        data += 5;
1675a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
1676a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1677a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 0x6A:
1678a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        AppendToBuffer("push 0x%x", *reinterpret_cast<int8_t*>(data + 1));
1679a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        data += 2;
1680a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
1681a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1682a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 0xA8:
1683a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        AppendToBuffer("test al,0x%x", *reinterpret_cast<uint8_t*>(data+1));
1684a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        data += 2;
1685a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
1686a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1687a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 0xA9:
1688a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        AppendToBuffer("test eax,0x%x", *reinterpret_cast<int32_t*>(data+1));
1689a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        data += 5;
1690a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
1691a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1692a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 0xD1:  // fall through
1693a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 0xD3:  // fall through
1694a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 0xC1:
1695a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        data += D1D3C1Instruction(data);
1696a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
1697a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1698b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case 0xD8:  // fall through
1699a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 0xD9:  // fall through
1700a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 0xDA:  // fall through
1701a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 0xDB:  // fall through
1702a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 0xDC:  // fall through
1703a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 0xDD:  // fall through
1704a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 0xDE:  // fall through
1705a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 0xDF:
1706a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        data += FPUInstruction(data);
1707a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
1708a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1709a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 0xEB:
1710a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        data += JumpShort(data);
1711a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
1712a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1713a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 0xF2:
1714a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        if (*(data+1) == 0x0F) {
1715a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          byte b2 = *(data+2);
1716a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          if (b2 == 0x11) {
1717a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            AppendToBuffer("movsd ");
1718a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            data += 3;
1719a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            int mod, regop, rm;
1720a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            get_modrm(*data, &mod, &regop, &rm);
172144f0eee88ff00398ff7f715fab053374d808c90dSteve Block            data += PrintRightXMMOperand(data);
1722a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            AppendToBuffer(",%s", NameOfXMMRegister(regop));
1723a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          } else if (b2 == 0x10) {
1724a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            data += 3;
1725a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            int mod, regop, rm;
1726a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            get_modrm(*data, &mod, &regop, &rm);
1727a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            AppendToBuffer("movsd %s,", NameOfXMMRegister(regop));
172844f0eee88ff00398ff7f715fab053374d808c90dSteve Block            data += PrintRightXMMOperand(data);
172944f0eee88ff00398ff7f715fab053374d808c90dSteve Block          } else  if (b2 == 0x5A) {
173044f0eee88ff00398ff7f715fab053374d808c90dSteve Block            data += 3;
173144f0eee88ff00398ff7f715fab053374d808c90dSteve Block            int mod, regop, rm;
173244f0eee88ff00398ff7f715fab053374d808c90dSteve Block            get_modrm(*data, &mod, &regop, &rm);
173344f0eee88ff00398ff7f715fab053374d808c90dSteve Block            AppendToBuffer("cvtsd2ss %s,", NameOfXMMRegister(regop));
173444f0eee88ff00398ff7f715fab053374d808c90dSteve Block            data += PrintRightXMMOperand(data);
1735a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          } else {
1736a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            const char* mnem = "?";
1737a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            switch (b2) {
1738a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block              case 0x2A: mnem = "cvtsi2sd"; break;
17396ded16be15dd865a9b21ea304d5273c8be299c87Steve Block              case 0x2C: mnem = "cvttsd2si"; break;
1740b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch              case 0x2D: mnem = "cvtsd2si"; break;
17416ded16be15dd865a9b21ea304d5273c8be299c87Steve Block              case 0x51: mnem = "sqrtsd"; break;
1742a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block              case 0x58: mnem = "addsd"; break;
1743a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block              case 0x59: mnem = "mulsd"; break;
1744a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block              case 0x5C: mnem = "subsd"; break;
1745a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block              case 0x5E: mnem = "divsd"; break;
1746a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            }
1747a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            data += 3;
1748a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            int mod, regop, rm;
1749a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            get_modrm(*data, &mod, &regop, &rm);
1750a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            if (b2 == 0x2A) {
175144f0eee88ff00398ff7f715fab053374d808c90dSteve Block              AppendToBuffer("%s %s,", mnem, NameOfXMMRegister(regop));
175244f0eee88ff00398ff7f715fab053374d808c90dSteve Block              data += PrintRightOperand(data);
1753b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            } else if (b2 == 0x2C || b2 == 0x2D) {
175444f0eee88ff00398ff7f715fab053374d808c90dSteve Block              AppendToBuffer("%s %s,", mnem, NameOfCPURegister(regop));
175544f0eee88ff00398ff7f715fab053374d808c90dSteve Block              data += PrintRightXMMOperand(data);
17560d5e116f6aee03185f237311a943491bb079a768Kristian Monsen            } else if (b2 == 0xC2) {
17570d5e116f6aee03185f237311a943491bb079a768Kristian Monsen              // Intel manual 2A, Table 3-18.
17580d5e116f6aee03185f237311a943491bb079a768Kristian Monsen              const char* const pseudo_op[] = {
17590d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                "cmpeqsd",
17600d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                "cmpltsd",
17610d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                "cmplesd",
17620d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                "cmpunordsd",
17630d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                "cmpneqsd",
17640d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                "cmpnltsd",
17650d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                "cmpnlesd",
17660d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                "cmpordsd"
17670d5e116f6aee03185f237311a943491bb079a768Kristian Monsen              };
17680d5e116f6aee03185f237311a943491bb079a768Kristian Monsen              AppendToBuffer("%s %s,%s",
17690d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                             pseudo_op[data[1]],
17700d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                             NameOfXMMRegister(regop),
17710d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                             NameOfXMMRegister(rm));
17720d5e116f6aee03185f237311a943491bb079a768Kristian Monsen              data += 2;
1773a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            } else {
177444f0eee88ff00398ff7f715fab053374d808c90dSteve Block              AppendToBuffer("%s %s,", mnem, NameOfXMMRegister(regop));
177544f0eee88ff00398ff7f715fab053374d808c90dSteve Block              data += PrintRightXMMOperand(data);
1776a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            }
1777a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          }
1778a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        } else {
1779a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          UnimplementedInstruction();
1780a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        }
1781a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
1782a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1783a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 0xF3:
1784e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        if (*(data+1) == 0x0F) {
178544f0eee88ff00398ff7f715fab053374d808c90dSteve Block          byte b2 = *(data+2);
178644f0eee88ff00398ff7f715fab053374d808c90dSteve Block          if (b2 == 0x11) {
178744f0eee88ff00398ff7f715fab053374d808c90dSteve Block            AppendToBuffer("movss ");
1788e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke            data += 3;
178944f0eee88ff00398ff7f715fab053374d808c90dSteve Block            int mod, regop, rm;
179044f0eee88ff00398ff7f715fab053374d808c90dSteve Block            get_modrm(*data, &mod, &regop, &rm);
179144f0eee88ff00398ff7f715fab053374d808c90dSteve Block            data += PrintRightXMMOperand(data);
179244f0eee88ff00398ff7f715fab053374d808c90dSteve Block            AppendToBuffer(",%s", NameOfXMMRegister(regop));
179344f0eee88ff00398ff7f715fab053374d808c90dSteve Block          } else if (b2 == 0x10) {
17946ded16be15dd865a9b21ea304d5273c8be299c87Steve Block            data += 3;
17956ded16be15dd865a9b21ea304d5273c8be299c87Steve Block            int mod, regop, rm;
17966ded16be15dd865a9b21ea304d5273c8be299c87Steve Block            get_modrm(*data, &mod, &regop, &rm);
179744f0eee88ff00398ff7f715fab053374d808c90dSteve Block            AppendToBuffer("movss %s,", NameOfXMMRegister(regop));
179844f0eee88ff00398ff7f715fab053374d808c90dSteve Block            data += PrintRightXMMOperand(data);
179944f0eee88ff00398ff7f715fab053374d808c90dSteve Block          } else if (b2 == 0x2C) {
180044f0eee88ff00398ff7f715fab053374d808c90dSteve Block            data += 3;
180144f0eee88ff00398ff7f715fab053374d808c90dSteve Block            int mod, regop, rm;
180244f0eee88ff00398ff7f715fab053374d808c90dSteve Block            get_modrm(*data, &mod, &regop, &rm);
180344f0eee88ff00398ff7f715fab053374d808c90dSteve Block            AppendToBuffer("cvttss2si %s,", NameOfCPURegister(regop));
180444f0eee88ff00398ff7f715fab053374d808c90dSteve Block            data += PrintRightXMMOperand(data);
1805958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier          } else if (b2 == 0x58) {
1806958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier            data += 3;
1807958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier            int mod, regop, rm;
1808958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier            get_modrm(*data, &mod, &regop, &rm);
1809958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier            AppendToBuffer("addss %s,", NameOfXMMRegister(regop));
1810958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier            data += PrintRightXMMOperand(data);
1811958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier          } else if (b2 == 0x59) {
1812958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier            data += 3;
1813958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier            int mod, regop, rm;
1814958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier            get_modrm(*data, &mod, &regop, &rm);
1815958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier            AppendToBuffer("mulss %s,", NameOfXMMRegister(regop));
1816958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier            data += PrintRightXMMOperand(data);
181744f0eee88ff00398ff7f715fab053374d808c90dSteve Block          } else if (b2 == 0x5A) {
181844f0eee88ff00398ff7f715fab053374d808c90dSteve Block            data += 3;
181944f0eee88ff00398ff7f715fab053374d808c90dSteve Block            int mod, regop, rm;
182044f0eee88ff00398ff7f715fab053374d808c90dSteve Block            get_modrm(*data, &mod, &regop, &rm);
182144f0eee88ff00398ff7f715fab053374d808c90dSteve Block            AppendToBuffer("cvtss2sd %s,", NameOfXMMRegister(regop));
182244f0eee88ff00398ff7f715fab053374d808c90dSteve Block            data += PrintRightXMMOperand(data);
1823958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier          } else if (b2 == 0x5c) {
1824958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier            data += 3;
1825958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier            int mod, regop, rm;
1826958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier            get_modrm(*data, &mod, &regop, &rm);
1827958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier            AppendToBuffer("subss %s,", NameOfXMMRegister(regop));
1828958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier            data += PrintRightXMMOperand(data);
1829958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier          } else if (b2 == 0x5e) {
1830958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier            data += 3;
1831958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier            int mod, regop, rm;
1832958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier            get_modrm(*data, &mod, &regop, &rm);
1833958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier            AppendToBuffer("divss %s,", NameOfXMMRegister(regop));
1834958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier            data += PrintRightXMMOperand(data);
1835b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          } else if (b2 == 0x6F) {
1836e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke            data += 3;
1837e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke            int mod, regop, rm;
1838e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke            get_modrm(*data, &mod, &regop, &rm);
1839e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke            AppendToBuffer("movdqu %s,", NameOfXMMRegister(regop));
184044f0eee88ff00398ff7f715fab053374d808c90dSteve Block            data += PrintRightXMMOperand(data);
1841b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          } else if (b2 == 0x7F) {
1842e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke            AppendToBuffer("movdqu ");
1843e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke            data += 3;
1844e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke            int mod, regop, rm;
1845e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke            get_modrm(*data, &mod, &regop, &rm);
184644f0eee88ff00398ff7f715fab053374d808c90dSteve Block            data += PrintRightXMMOperand(data);
1847e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke            AppendToBuffer(",%s", NameOfXMMRegister(regop));
1848e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          } else {
1849e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke            UnimplementedInstruction();
1850e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          }
1851e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        } else if (*(data+1) == 0xA5) {
1852e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          data += 2;
1853e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          AppendToBuffer("rep_movs");
18546ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        } else if (*(data+1) == 0xAB) {
18556ded16be15dd865a9b21ea304d5273c8be299c87Steve Block          data += 2;
18566ded16be15dd865a9b21ea304d5273c8be299c87Steve Block          AppendToBuffer("rep_stos");
1857a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        } else {
1858a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          UnimplementedInstruction();
1859a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        }
1860a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
1861a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1862a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 0xF7:
1863a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        data += F7Instruction(data);
1864a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
1865a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1866a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      default:
1867a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        UnimplementedInstruction();
1868a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
1869a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1870a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1871a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (tmp_buffer_pos_ < sizeof tmp_buffer_) {
1872a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    tmp_buffer_[tmp_buffer_pos_] = '\0';
1873a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1874a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1875a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int instr_len = data - instr;
1876e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  if (instr_len == 0) {
1877e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    printf("%02x", *data);
1878e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  }
1879b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(instr_len > 0);  // Ensure progress.
1880a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1881a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int outp = 0;
1882a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Instruction bytes.
1883a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (byte* bp = instr; bp < data; bp++) {
1884b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    outp += v8::internal::SNPrintF(out_buffer + outp,
1885b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                   "%02x",
1886b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                   *bp);
1887a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1888a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (int i = 6 - instr_len; i >= 0; i--) {
1889b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    outp += v8::internal::SNPrintF(out_buffer + outp, "  ");
1890a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1891a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1892b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  outp += v8::internal::SNPrintF(out_buffer + outp,
1893b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                 " %s",
1894b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                 tmp_buffer_.start());
1895a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return instr_len;
18960d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}  // NOLINT (function is too long)
1897a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1898a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1899a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//------------------------------------------------------------------------------
1900a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1901a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1902958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernierstatic const char* const cpu_regs[8] = {
1903a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  "eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi"
1904a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
1905a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1906a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1907958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernierstatic const char* const byte_cpu_regs[8] = {
1908a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  "al", "cl", "dl", "bl", "ah", "ch", "dh", "bh"
1909a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
1910a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1911a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1912958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernierstatic const char* const xmm_regs[8] = {
1913a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7"
1914a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
1915a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1916a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1917a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockconst char* NameConverter::NameOfAddress(byte* addr) const {
1918b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::internal::SNPrintF(tmp_buffer_, "%p", addr);
191944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  return tmp_buffer_.start();
1920a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1921a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1922a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1923a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockconst char* NameConverter::NameOfConstant(byte* addr) const {
1924a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return NameOfAddress(addr);
1925a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1926a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1927a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1928a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockconst char* NameConverter::NameOfCPURegister(int reg) const {
1929a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (0 <= reg && reg < 8) return cpu_regs[reg];
1930a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return "noreg";
1931a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1932a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1933a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1934a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockconst char* NameConverter::NameOfByteCPURegister(int reg) const {
1935a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (0 <= reg && reg < 8) return byte_cpu_regs[reg];
1936a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return "noreg";
1937a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1938a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1939a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1940a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockconst char* NameConverter::NameOfXMMRegister(int reg) const {
1941a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (0 <= reg && reg < 8) return xmm_regs[reg];
1942a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return "noxmmreg";
1943a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1944a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1945a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1946a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockconst char* NameConverter::NameInCode(byte* addr) const {
1947a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // IA32 does not embed debug strings at the moment.
1948a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  UNREACHABLE();
1949a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return "";
1950a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1951a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1952a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1953a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//------------------------------------------------------------------------------
1954a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1955a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockDisassembler::Disassembler(const NameConverter& converter)
1956a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    : converter_(converter) {}
1957a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1958a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1959a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockDisassembler::~Disassembler() {}
1960a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1961a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1962a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint Disassembler::InstructionDecode(v8::internal::Vector<char> buffer,
1963a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                    byte* instruction) {
1964a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  DisassemblerIA32 d(converter_, false /*do not crash if unimplemented*/);
1965a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return d.InstructionDecode(buffer, instruction);
1966a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1967a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1968a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1969a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// The IA-32 assembler does not currently use constant pools.
1970a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint Disassembler::ConstantPoolSizeAt(byte* instruction) { return -1; }
1971a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1972a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1973a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block/*static*/ void Disassembler::Disassemble(FILE* f, byte* begin, byte* end) {
1974a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  NameConverter converter;
1975a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Disassembler d(converter);
1976a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (byte* pc = begin; pc < end;) {
1977a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    v8::internal::EmbeddedVector<char, 128> buffer;
1978a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    buffer[0] = '\0';
1979a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    byte* prev_pc = pc;
1980a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    pc += d.InstructionDecode(buffer, pc);
1981a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    fprintf(f, "%p", prev_pc);
1982a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    fprintf(f, "    ");
1983a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1984a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    for (byte* bp = prev_pc; bp < pc; bp++) {
1985a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      fprintf(f, "%02x",  *bp);
1986a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
1987a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    for (int i = 6 - (pc - prev_pc); i >= 0; i--) {
1988a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      fprintf(f, "  ");
1989a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
1990a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    fprintf(f, "  %s\n", buffer.start());
1991a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1992a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1993a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1994a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1995a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}  // namespace disasm
1996f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1997f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke#endif  // V8_TARGET_ARCH_IA32
1998