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#if V8_TARGET_ARCH_IA32
10f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
11bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch#include "src/base/compiler-specific.h"
12b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/disasm.h"
13a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
14a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace disasm {
15a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
16a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockenum OperandOrder {
17a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  UNSET_OP_ORDER = 0,
18a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  REG_OPER_OP_ORDER,
19a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  OPER_REG_OP_ORDER
20a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
21a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
22a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
23a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//------------------------------------------------------------------
24a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Tables
25a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//------------------------------------------------------------------
26a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstruct ByteMnemonic {
27a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int b;  // -1 terminates, otherwise must be in range (0..255)
28a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const char* mnem;
29a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  OperandOrder op_order_;
30a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
31a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdochstatic const ByteMnemonic two_operands_instr[] = {
33bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    {0x01, "add", OPER_REG_OP_ORDER},  {0x03, "add", REG_OPER_OP_ORDER},
34bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    {0x09, "or", OPER_REG_OP_ORDER},   {0x0B, "or", REG_OPER_OP_ORDER},
35bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    {0x13, "adc", REG_OPER_OP_ORDER},  {0x1B, "sbb", REG_OPER_OP_ORDER},
36bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    {0x21, "and", OPER_REG_OP_ORDER},  {0x23, "and", REG_OPER_OP_ORDER},
37bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    {0x29, "sub", OPER_REG_OP_ORDER},  {0x2A, "subb", REG_OPER_OP_ORDER},
38bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    {0x2B, "sub", REG_OPER_OP_ORDER},  {0x31, "xor", OPER_REG_OP_ORDER},
39bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    {0x33, "xor", REG_OPER_OP_ORDER},  {0x38, "cmpb", OPER_REG_OP_ORDER},
40bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    {0x39, "cmp", OPER_REG_OP_ORDER},  {0x3A, "cmpb", REG_OPER_OP_ORDER},
41bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    {0x3B, "cmp", REG_OPER_OP_ORDER},  {0x84, "test_b", REG_OPER_OP_ORDER},
42bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    {0x85, "test", REG_OPER_OP_ORDER}, {0x86, "xchg_b", REG_OPER_OP_ORDER},
43bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    {0x87, "xchg", REG_OPER_OP_ORDER}, {0x8A, "mov_b", REG_OPER_OP_ORDER},
44bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    {0x8B, "mov", REG_OPER_OP_ORDER},  {0x8D, "lea", REG_OPER_OP_ORDER},
45bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    {-1, "", UNSET_OP_ORDER}};
46a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdochstatic const ByteMnemonic zero_operands_instr[] = {
48a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  {0xC3, "ret", UNSET_OP_ORDER},
49a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  {0xC9, "leave", UNSET_OP_ORDER},
50a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  {0x90, "nop", UNSET_OP_ORDER},
51a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  {0xF4, "hlt", UNSET_OP_ORDER},
52a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  {0xCC, "int3", UNSET_OP_ORDER},
53a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  {0x60, "pushad", UNSET_OP_ORDER},
54a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  {0x61, "popad", UNSET_OP_ORDER},
55a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  {0x9C, "pushfd", UNSET_OP_ORDER},
56a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  {0x9D, "popfd", UNSET_OP_ORDER},
57a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  {0x9E, "sahf", UNSET_OP_ORDER},
58a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  {0x99, "cdq", UNSET_OP_ORDER},
59a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  {0x9B, "fwait", UNSET_OP_ORDER},
606ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  {0xFC, "cld", UNSET_OP_ORDER},
61f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  {0xAB, "stos", UNSET_OP_ORDER},
62a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  {-1, "", UNSET_OP_ORDER}
63a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
64a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
65a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
6669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdochstatic const ByteMnemonic call_jump_instr[] = {
67a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  {0xE8, "call", UNSET_OP_ORDER},
68a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  {0xE9, "jmp", UNSET_OP_ORDER},
69a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  {-1, "", UNSET_OP_ORDER}
70a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
71a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
72a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
7369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdochstatic const ByteMnemonic short_immediate_instr[] = {
74a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  {0x05, "add", UNSET_OP_ORDER},
75a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  {0x0D, "or", UNSET_OP_ORDER},
76a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  {0x15, "adc", UNSET_OP_ORDER},
77a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  {0x25, "and", UNSET_OP_ORDER},
78a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  {0x2D, "sub", UNSET_OP_ORDER},
79a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  {0x35, "xor", UNSET_OP_ORDER},
80a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  {0x3D, "cmp", UNSET_OP_ORDER},
81a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  {-1, "", UNSET_OP_ORDER}
82a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
83a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
84a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// Generally we don't want to generate these because they are subject to partial
863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// register stalls.  They are included for completeness and because the cmp
873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// variant is used by the RecordWrite stub.  Because it does not update the
883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// register it is not subject to partial register stalls.
893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochstatic ByteMnemonic byte_immediate_instr[] = {
903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  {0x0c, "or", UNSET_OP_ORDER},
913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  {0x24, "and", UNSET_OP_ORDER},
923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  {0x34, "xor", UNSET_OP_ORDER},
933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  {0x3c, "cmp", UNSET_OP_ORDER},
943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  {-1, "", UNSET_OP_ORDER}
953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch};
963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
9869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdochstatic const char* const jump_conditional_mnem[] = {
99a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  /*0*/ "jo", "jno", "jc", "jnc",
100a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  /*4*/ "jz", "jnz", "jna", "ja",
101a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  /*8*/ "js", "jns", "jpe", "jpo",
102a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  /*12*/ "jl", "jnl", "jng", "jg"
103a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
104a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
105a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
10669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdochstatic const char* const set_conditional_mnem[] = {
107a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  /*0*/ "seto", "setno", "setc", "setnc",
108a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  /*4*/ "setz", "setnz", "setna", "seta",
109a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  /*8*/ "sets", "setns", "setpe", "setpo",
110a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  /*12*/ "setl", "setnl", "setng", "setg"
111a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
112a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
113a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
11469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdochstatic const char* const conditional_move_mnem[] = {
1153ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  /*0*/ "cmovo", "cmovno", "cmovc", "cmovnc",
1163ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  /*4*/ "cmovz", "cmovnz", "cmovna", "cmova",
1173ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  /*8*/ "cmovs", "cmovns", "cmovpe", "cmovpo",
1183ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  /*12*/ "cmovl", "cmovnl", "cmovng", "cmovg"
1193ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block};
1203ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
1213ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
122a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockenum InstructionType {
123a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  NO_INSTR,
124a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ZERO_OPERANDS_INSTR,
125a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  TWO_OPERANDS_INSTR,
126a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  JUMP_CONDITIONAL_SHORT_INSTR,
127a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  REGISTER_INSTR,
128a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  MOVE_REG_INSTR,
129a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CALL_JUMP_INSTR,
1303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  SHORT_IMMEDIATE_INSTR,
1313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  BYTE_IMMEDIATE_INSTR
132a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
133a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
134a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
135a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstruct InstructionDesc {
136a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const char* mnem;
137a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  InstructionType type;
138a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  OperandOrder op_order_;
139a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
140a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
141a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
142a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass InstructionTable {
143a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public:
144a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  InstructionTable();
145a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const InstructionDesc& Get(byte x) const { return instructions_[x]; }
1463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  static InstructionTable* get_instance() {
1473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    static InstructionTable table;
1483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return &table;
1493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
150a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
151a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private:
152a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  InstructionDesc instructions_[256];
153a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void Clear();
154a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void Init();
15569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  void CopyTable(const ByteMnemonic bm[], InstructionType type);
156a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void SetTableRange(InstructionType type,
157a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                     byte start,
158a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                     byte end,
159a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                     const char* mnem);
160a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void AddJumpConditionalShort();
161a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
162a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
163a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
164a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockInstructionTable::InstructionTable() {
165a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Clear();
166a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Init();
167a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
168a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
169a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
170a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid InstructionTable::Clear() {
171a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (int i = 0; i < 256; i++) {
172a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    instructions_[i].mnem = "";
173a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    instructions_[i].type = NO_INSTR;
174a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    instructions_[i].op_order_ = UNSET_OP_ORDER;
175a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
176a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
177a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
178a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
179a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid InstructionTable::Init() {
180a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CopyTable(two_operands_instr, TWO_OPERANDS_INSTR);
181a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CopyTable(zero_operands_instr, ZERO_OPERANDS_INSTR);
182a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CopyTable(call_jump_instr, CALL_JUMP_INSTR);
183a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CopyTable(short_immediate_instr, SHORT_IMMEDIATE_INSTR);
1843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CopyTable(byte_immediate_instr, BYTE_IMMEDIATE_INSTR);
185a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  AddJumpConditionalShort();
186a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  SetTableRange(REGISTER_INSTR, 0x40, 0x47, "inc");
187a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  SetTableRange(REGISTER_INSTR, 0x48, 0x4F, "dec");
188a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  SetTableRange(REGISTER_INSTR, 0x50, 0x57, "push");
189a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  SetTableRange(REGISTER_INSTR, 0x58, 0x5F, "pop");
190a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  SetTableRange(REGISTER_INSTR, 0x91, 0x97, "xchg eax,");  // 0x90 is nop.
191a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  SetTableRange(MOVE_REG_INSTR, 0xB8, 0xBF, "mov");
192a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
193a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
194a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
19569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdochvoid InstructionTable::CopyTable(const ByteMnemonic bm[],
19669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch                                 InstructionType type) {
197a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (int i = 0; bm[i].b >= 0; i++) {
198a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    InstructionDesc* id = &instructions_[bm[i].b];
199a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    id->mnem = bm[i].mnem;
200a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    id->op_order_ = bm[i].op_order_;
201b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK_EQ(NO_INSTR, id->type);  // Information not already entered.
202a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    id->type = type;
203a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
204a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
205a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
206a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
207a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid InstructionTable::SetTableRange(InstructionType type,
208a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                     byte start,
209a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                     byte end,
210a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                     const char* mnem) {
211a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (byte b = start; b <= end; b++) {
212a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    InstructionDesc* id = &instructions_[b];
213b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK_EQ(NO_INSTR, id->type);  // Information not already entered.
214a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    id->mnem = mnem;
215a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    id->type = type;
216a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
217a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
218a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
219a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
220a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid InstructionTable::AddJumpConditionalShort() {
221a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (byte b = 0x70; b <= 0x7F; b++) {
222a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    InstructionDesc* id = &instructions_[b];
223b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK_EQ(NO_INSTR, id->type);  // Information not already entered.
224a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    id->mnem = jump_conditional_mnem[b & 0x0F];
225a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    id->type = JUMP_CONDITIONAL_SHORT_INSTR;
226a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
227a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
228a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
229a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
230a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// The IA32 disassembler implementation.
231a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass DisassemblerIA32 {
232a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public:
233a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  DisassemblerIA32(const NameConverter& converter,
234a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                   bool abort_on_unimplemented = true)
235a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      : converter_(converter),
236958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        vex_byte0_(0),
237958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        vex_byte1_(0),
238958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        vex_byte2_(0),
2393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        instruction_table_(InstructionTable::get_instance()),
240a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        tmp_buffer_pos_(0),
241a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        abort_on_unimplemented_(abort_on_unimplemented) {
242a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    tmp_buffer_[0] = '\0';
243a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
244a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
245a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  virtual ~DisassemblerIA32() {}
246a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
247a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Writes one disassembled instruction into 'buffer' (0-terminated).
248a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Returns the length of the disassembled machine instruction in bytes.
249a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int InstructionDecode(v8::internal::Vector<char> buffer, byte* instruction);
250a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
251a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private:
252a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const NameConverter& converter_;
253958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  byte vex_byte0_;  // 0xc4 or 0xc5
254958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  byte vex_byte1_;
255958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  byte vex_byte2_;  // only for 3 bytes vex prefix
2563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  InstructionTable* instruction_table_;
257a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::internal::EmbeddedVector<char, 128> tmp_buffer_;
258a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  unsigned int tmp_buffer_pos_;
259a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bool abort_on_unimplemented_;
260a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
261a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  enum {
262a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    eax = 0,
263a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ecx = 1,
264a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    edx = 2,
265a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ebx = 3,
266a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    esp = 4,
267a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ebp = 5,
268a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    esi = 6,
269a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    edi = 7
270a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  };
271a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
272a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
273d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  enum ShiftOpcodeExtension {
274d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    kROL = 0,
275d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    kROR = 1,
276d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    kRCL = 2,
277d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    kRCR = 3,
278d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    kSHL = 4,
279d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    KSHR = 5,
280d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    kSAR = 7
281d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  };
282d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
283958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  bool vex_128() {
284958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    DCHECK(vex_byte0_ == 0xc4 || vex_byte0_ == 0xc5);
285958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    byte checked = vex_byte0_ == 0xc4 ? vex_byte2_ : vex_byte1_;
286bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    return (checked & 4) == 0;
287958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
288958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
289014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  bool vex_none() {
290014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    DCHECK(vex_byte0_ == 0xc4 || vex_byte0_ == 0xc5);
291014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    byte checked = vex_byte0_ == 0xc4 ? vex_byte2_ : vex_byte1_;
292014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return (checked & 3) == 0;
293014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
294014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
295958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  bool vex_66() {
296958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    DCHECK(vex_byte0_ == 0xc4 || vex_byte0_ == 0xc5);
297958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    byte checked = vex_byte0_ == 0xc4 ? vex_byte2_ : vex_byte1_;
298958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    return (checked & 3) == 1;
299958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
300958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
301958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  bool vex_f3() {
302958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    DCHECK(vex_byte0_ == 0xc4 || vex_byte0_ == 0xc5);
303958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    byte checked = vex_byte0_ == 0xc4 ? vex_byte2_ : vex_byte1_;
304958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    return (checked & 3) == 2;
305958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
306958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
307958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  bool vex_f2() {
308958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    DCHECK(vex_byte0_ == 0xc4 || vex_byte0_ == 0xc5);
309958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    byte checked = vex_byte0_ == 0xc4 ? vex_byte2_ : vex_byte1_;
310958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    return (checked & 3) == 3;
311958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
312958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
313958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  bool vex_w() {
314958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    if (vex_byte0_ == 0xc5) return false;
315958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    return (vex_byte2_ & 0x80) != 0;
316958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
317958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
318958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  bool vex_0f() {
319958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    if (vex_byte0_ == 0xc5) return true;
320958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    return (vex_byte1_ & 3) == 1;
321958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
322958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
323958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  bool vex_0f38() {
324958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    if (vex_byte0_ == 0xc5) return false;
325958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    return (vex_byte1_ & 3) == 2;
326958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
327958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
328958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  bool vex_0f3a() {
329958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    if (vex_byte0_ == 0xc5) return false;
330958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    return (vex_byte1_ & 3) == 3;
331958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
332958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
333958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  int vex_vreg() {
334958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    DCHECK(vex_byte0_ == 0xc4 || vex_byte0_ == 0xc5);
335958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    byte checked = vex_byte0_ == 0xc4 ? vex_byte2_ : vex_byte1_;
336958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    return ~(checked >> 3) & 0xf;
337958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
338958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
339958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  char float_size_code() { return "sd"[vex_w()]; }
340d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
341a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const char* NameOfCPURegister(int reg) const {
342a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return converter_.NameOfCPURegister(reg);
343a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
344a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
345a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
346a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const char* NameOfByteCPURegister(int reg) const {
347a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return converter_.NameOfByteCPURegister(reg);
348a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
349a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
350a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
351a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const char* NameOfXMMRegister(int reg) const {
352a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return converter_.NameOfXMMRegister(reg);
353a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
354a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
355a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
356a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const char* NameOfAddress(byte* addr) const {
357a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return converter_.NameOfAddress(addr);
358a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
359a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
360a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
361a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Disassembler helper functions.
362a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  static void get_modrm(byte data, int* mod, int* regop, int* rm) {
363a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    *mod = (data >> 6) & 3;
364a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    *regop = (data & 0x38) >> 3;
365a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    *rm = data & 7;
366a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
367a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
368a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
369a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  static void get_sib(byte data, int* scale, int* index, int* base) {
370a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    *scale = (data >> 6) & 3;
371a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    *index = (data >> 3) & 7;
372a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    *base = data & 7;
373a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
374a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
375a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  typedef const char* (DisassemblerIA32::*RegisterNameMapping)(int reg) const;
376a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
377a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int PrintRightOperandHelper(byte* modrmp, RegisterNameMapping register_name);
378a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int PrintRightOperand(byte* modrmp);
379a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int PrintRightByteOperand(byte* modrmp);
38044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  int PrintRightXMMOperand(byte* modrmp);
381a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int PrintOperands(const char* mnem, OperandOrder op_order, byte* data);
382a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int PrintImmediateOp(byte* data);
383a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int F7Instruction(byte* data);
384a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int D1D3C1Instruction(byte* data);
385a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int JumpShort(byte* data);
386a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int JumpConditional(byte* data, const char* comment);
387a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int JumpConditionalShort(byte* data, const char* comment);
388a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int SetCC(byte* data);
3893ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  int CMov(byte* data);
390a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int FPUInstruction(byte* data);
391d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  int MemoryFPUInstruction(int escape_opcode, int regop, byte* modrm_start);
392d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  int RegisterFPUInstruction(int escape_opcode, byte modrm_byte);
393958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  int AVXInstruction(byte* data);
394bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  PRINTF_FORMAT(2, 3) void AppendToBuffer(const char* format, ...);
395a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
396a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void UnimplementedInstruction() {
397a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (abort_on_unimplemented_) {
398a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      UNIMPLEMENTED();
399a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    } else {
400a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      AppendToBuffer("'Unimplemented Instruction'");
401a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
402a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
403a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
404a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
405a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
406a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid DisassemblerIA32::AppendToBuffer(const char* format, ...) {
407a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::internal::Vector<char> buf = tmp_buffer_ + tmp_buffer_pos_;
408a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  va_list args;
409a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  va_start(args, format);
410b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int result = v8::internal::VSNPrintF(buf, format, args);
411a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  va_end(args);
412a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  tmp_buffer_pos_ += result;
413a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
414a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
415a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint DisassemblerIA32::PrintRightOperandHelper(
416a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    byte* modrmp,
41744f0eee88ff00398ff7f715fab053374d808c90dSteve Block    RegisterNameMapping direct_register_name) {
418a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int mod, regop, rm;
419a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  get_modrm(*modrmp, &mod, &regop, &rm);
42044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  RegisterNameMapping register_name = (mod == 3) ? direct_register_name :
42144f0eee88ff00398ff7f715fab053374d808c90dSteve Block      &DisassemblerIA32::NameOfCPURegister;
422a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  switch (mod) {
423a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case 0:
424a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      if (rm == ebp) {
425a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        int32_t disp = *reinterpret_cast<int32_t*>(modrmp+1);
426a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        AppendToBuffer("[0x%x]", disp);
427a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        return 5;
428a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      } else if (rm == esp) {
429a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        byte sib = *(modrmp + 1);
430a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        int scale, index, base;
431a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        get_sib(sib, &scale, &index, &base);
432a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        if (index == esp && base == esp && scale == 0 /*times_1*/) {
433a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          AppendToBuffer("[%s]", (this->*register_name)(rm));
434a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          return 2;
435a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        } else if (base == ebp) {
436a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          int32_t disp = *reinterpret_cast<int32_t*>(modrmp + 2);
437b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          AppendToBuffer("[%s*%d%s0x%x]",
438a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                         (this->*register_name)(index),
439a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                         1 << scale,
440b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                         disp < 0 ? "-" : "+",
441b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                         disp < 0 ? -disp : disp);
442a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          return 6;
443a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        } else if (index != esp && base != ebp) {
444a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          // [base+index*scale]
445a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          AppendToBuffer("[%s+%s*%d]",
446a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                         (this->*register_name)(base),
447a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                         (this->*register_name)(index),
448a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                         1 << scale);
449a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          return 2;
450a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        } else {
451a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          UnimplementedInstruction();
452a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          return 1;
453a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        }
454a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      } else {
455a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        AppendToBuffer("[%s]", (this->*register_name)(rm));
456a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        return 1;
457a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
458a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      break;
459a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case 1:  // fall through
460a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case 2:
461a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      if (rm == esp) {
462a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        byte sib = *(modrmp + 1);
463a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        int scale, index, base;
464a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        get_sib(sib, &scale, &index, &base);
465b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        int disp = mod == 2 ? *reinterpret_cast<int32_t*>(modrmp + 2)
466b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                            : *reinterpret_cast<int8_t*>(modrmp + 2);
467a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        if (index == base && index == rm /*esp*/ && scale == 0 /*times_1*/) {
468b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          AppendToBuffer("[%s%s0x%x]",
469b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                         (this->*register_name)(rm),
470b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                         disp < 0 ? "-" : "+",
471b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                         disp < 0 ? -disp : disp);
472a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        } else {
473b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          AppendToBuffer("[%s+%s*%d%s0x%x]",
474a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                         (this->*register_name)(base),
475a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                         (this->*register_name)(index),
476a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                         1 << scale,
477b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                         disp < 0 ? "-" : "+",
478b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                         disp < 0 ? -disp : disp);
479a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        }
480a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        return mod == 2 ? 6 : 3;
481a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      } else {
482a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        // No sib.
483b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        int disp = mod == 2 ? *reinterpret_cast<int32_t*>(modrmp + 1)
484b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                            : *reinterpret_cast<int8_t*>(modrmp + 1);
485b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        AppendToBuffer("[%s%s0x%x]",
486b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                       (this->*register_name)(rm),
487b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                       disp < 0 ? "-" : "+",
488b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                       disp < 0 ? -disp : disp);
489a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        return mod == 2 ? 5 : 2;
490a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
491a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      break;
492a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case 3:
493a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      AppendToBuffer("%s", (this->*register_name)(rm));
494a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      return 1;
495a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    default:
496a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      UnimplementedInstruction();
497a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      return 1;
498a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
499a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  UNREACHABLE();
500a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
501a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
502a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
503a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint DisassemblerIA32::PrintRightOperand(byte* modrmp) {
504a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return PrintRightOperandHelper(modrmp, &DisassemblerIA32::NameOfCPURegister);
505a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
506a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
507a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
508a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint DisassemblerIA32::PrintRightByteOperand(byte* modrmp) {
509a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return PrintRightOperandHelper(modrmp,
510a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                 &DisassemblerIA32::NameOfByteCPURegister);
511a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
512a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
513a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
51444f0eee88ff00398ff7f715fab053374d808c90dSteve Blockint DisassemblerIA32::PrintRightXMMOperand(byte* modrmp) {
51544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  return PrintRightOperandHelper(modrmp,
51644f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                 &DisassemblerIA32::NameOfXMMRegister);
51744f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
51844f0eee88ff00398ff7f715fab053374d808c90dSteve Block
51944f0eee88ff00398ff7f715fab053374d808c90dSteve Block
520a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Returns number of bytes used including the current *data.
521a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Writes instruction's mnemonic, left and right operands to 'tmp_buffer_'.
522a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint DisassemblerIA32::PrintOperands(const char* mnem,
523a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                    OperandOrder op_order,
524a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                    byte* data) {
525a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  byte modrm = *data;
526a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int mod, regop, rm;
527a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  get_modrm(modrm, &mod, &regop, &rm);
528a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int advance = 0;
529a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  switch (op_order) {
530a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case REG_OPER_OP_ORDER: {
531a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      AppendToBuffer("%s %s,", mnem, NameOfCPURegister(regop));
532a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      advance = PrintRightOperand(data);
533a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      break;
534a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
535a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case OPER_REG_OP_ORDER: {
536a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      AppendToBuffer("%s ", mnem);
537a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      advance = PrintRightOperand(data);
538a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      AppendToBuffer(",%s", NameOfCPURegister(regop));
539a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      break;
540a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
541a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    default:
542a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      UNREACHABLE();
543a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      break;
544a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
545a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return advance;
546a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
547a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
548a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
549a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Returns number of bytes used by machine instruction, including *data byte.
550a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Writes immediate instructions to 'tmp_buffer_'.
551a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint DisassemblerIA32::PrintImmediateOp(byte* data) {
552a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bool sign_extension_bit = (*data & 0x02) != 0;
553a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  byte modrm = *(data+1);
554a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int mod, regop, rm;
555a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  get_modrm(modrm, &mod, &regop, &rm);
556a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const char* mnem = "Imm???";
557a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  switch (regop) {
558a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case 0: mnem = "add"; break;
559a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case 1: mnem = "or"; break;
560a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case 2: mnem = "adc"; break;
561a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case 4: mnem = "and"; break;
562a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case 5: mnem = "sub"; break;
563a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case 6: mnem = "xor"; break;
564a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case 7: mnem = "cmp"; break;
565a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    default: UnimplementedInstruction();
566a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
567a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  AppendToBuffer("%s ", mnem);
568a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int count = PrintRightOperand(data+1);
569a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (sign_extension_bit) {
570a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    AppendToBuffer(",0x%x", *(data + 1 + count));
571a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return 1 + count + 1 /*int8*/;
572a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
573a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    AppendToBuffer(",0x%x", *reinterpret_cast<int32_t*>(data + 1 + count));
574a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return 1 + count + 4 /*int32_t*/;
575a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
576a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
577a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
578a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
579a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Returns number of bytes used, including *data.
580a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint DisassemblerIA32::F7Instruction(byte* data) {
581b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK_EQ(0xF7, *data);
582b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  byte modrm = *++data;
583a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int mod, regop, rm;
584a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  get_modrm(modrm, &mod, &regop, &rm);
585b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  const char* mnem = NULL;
586b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  switch (regop) {
587b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case 0:
588b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      mnem = "test";
589b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
590b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case 2:
591b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      mnem = "not";
592b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
593b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case 3:
594b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      mnem = "neg";
595b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
596b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case 4:
597b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      mnem = "mul";
598b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
599b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case 5:
600b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      mnem = "imul";
601b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
602b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case 6:
603b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      mnem = "div";
604b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
605b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case 7:
606b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      mnem = "idiv";
607b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
608b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    default:
609b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      UnimplementedInstruction();
610a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
611b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  AppendToBuffer("%s ", mnem);
612b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int count = PrintRightOperand(data);
613b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (regop == 0) {
614b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    AppendToBuffer(",0x%x", *reinterpret_cast<int32_t*>(data + count));
615b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    count += 4;
616b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
617b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return 1 + count;
618a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
619a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
620b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
621a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint DisassemblerIA32::D1D3C1Instruction(byte* data) {
622a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  byte op = *data;
623b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(op == 0xD1 || op == 0xD3 || op == 0xC1);
624b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  byte modrm = *++data;
625a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int mod, regop, rm;
626a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  get_modrm(modrm, &mod, &regop, &rm);
627a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int imm8 = -1;
628b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  const char* mnem = NULL;
629b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  switch (regop) {
630b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case kROL:
631b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      mnem = "rol";
632b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
633b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case kROR:
634b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      mnem = "ror";
635b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
636b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case kRCL:
637b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      mnem = "rcl";
638b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
639b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case kRCR:
640b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      mnem = "rcr";
641b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
642b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case kSHL:
643b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      mnem = "shl";
644b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
645b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case KSHR:
646b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      mnem = "shr";
647b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
648b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case kSAR:
649b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      mnem = "sar";
650b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
651b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    default:
652b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      UnimplementedInstruction();
653b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
654b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  AppendToBuffer("%s ", mnem);
655b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int count = PrintRightOperand(data);
656b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (op == 0xD1) {
657b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    imm8 = 1;
658b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else if (op == 0xC1) {
659b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    imm8 = *(data + 1);
660b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    count++;
661b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else if (op == 0xD3) {
662b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Shift/rotate by cl.
663b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
664b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (imm8 >= 0) {
665b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    AppendToBuffer(",%d", imm8);
666a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
667b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    AppendToBuffer(",cl");
668a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
669b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return 1 + count;
670a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
671a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
672a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
673a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Returns number of bytes used, including *data.
674a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint DisassemblerIA32::JumpShort(byte* data) {
675b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK_EQ(0xEB, *data);
676a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  byte b = *(data+1);
677a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  byte* dest = data + static_cast<int8_t>(b) + 2;
678a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  AppendToBuffer("jmp %s", NameOfAddress(dest));
679a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return 2;
680a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
681a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
682a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
683a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Returns number of bytes used, including *data.
684a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint DisassemblerIA32::JumpConditional(byte* data, const char* comment) {
685b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK_EQ(0x0F, *data);
686a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  byte cond = *(data+1) & 0x0F;
687a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  byte* dest = data + *reinterpret_cast<int32_t*>(data+2) + 6;
688a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const char* mnem = jump_conditional_mnem[cond];
689a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  AppendToBuffer("%s %s", mnem, NameOfAddress(dest));
690a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (comment != NULL) {
691a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    AppendToBuffer(", %s", comment);
692a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
693a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return 6;  // includes 0x0F
694a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
695a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
696a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
697a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Returns number of bytes used, including *data.
698a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint DisassemblerIA32::JumpConditionalShort(byte* data, const char* comment) {
699a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  byte cond = *data & 0x0F;
700a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  byte b = *(data+1);
701a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  byte* dest = data + static_cast<int8_t>(b) + 2;
702a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const char* mnem = jump_conditional_mnem[cond];
703a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  AppendToBuffer("%s %s", mnem, NameOfAddress(dest));
704a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (comment != NULL) {
705a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    AppendToBuffer(", %s", comment);
706a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
707a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return 2;
708a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
709a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
710a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
711a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Returns number of bytes used, including *data.
712a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint DisassemblerIA32::SetCC(byte* data) {
713b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK_EQ(0x0F, *data);
714a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  byte cond = *(data+1) & 0x0F;
715a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const char* mnem = set_conditional_mnem[cond];
716a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  AppendToBuffer("%s ", mnem);
717a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  PrintRightByteOperand(data+2);
718d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  return 3;  // Includes 0x0F.
719a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
720a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
721a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
722a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Returns number of bytes used, including *data.
7233ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockint DisassemblerIA32::CMov(byte* data) {
724b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK_EQ(0x0F, *data);
7253ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  byte cond = *(data + 1) & 0x0F;
7263ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  const char* mnem = conditional_move_mnem[cond];
7273ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  int op_size = PrintOperands(mnem, REG_OPER_OP_ORDER, data + 2);
7283ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  return 2 + op_size;  // includes 0x0F
7293ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
7303ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
7313ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
732958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernierint DisassemblerIA32::AVXInstruction(byte* data) {
733958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  byte opcode = *data;
734958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  byte* current = data + 1;
735958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  if (vex_66() && vex_0f38()) {
736958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    int mod, regop, rm, vvvv = vex_vreg();
737958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    get_modrm(*current, &mod, &regop, &rm);
738958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    switch (opcode) {
739958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      case 0x99:
740958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        AppendToBuffer("vfmadd132s%c %s,%s,", float_size_code(),
741958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                       NameOfXMMRegister(regop), NameOfXMMRegister(vvvv));
742958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        current += PrintRightXMMOperand(current);
743958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        break;
744958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      case 0xa9:
745958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        AppendToBuffer("vfmadd213s%c %s,%s,", float_size_code(),
746958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                       NameOfXMMRegister(regop), NameOfXMMRegister(vvvv));
747958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        current += PrintRightXMMOperand(current);
748958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        break;
749958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      case 0xb9:
750958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        AppendToBuffer("vfmadd231s%c %s,%s,", float_size_code(),
751958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                       NameOfXMMRegister(regop), NameOfXMMRegister(vvvv));
752958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        current += PrintRightXMMOperand(current);
753958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        break;
754958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      case 0x9b:
755958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        AppendToBuffer("vfmsub132s%c %s,%s,", float_size_code(),
756958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                       NameOfXMMRegister(regop), NameOfXMMRegister(vvvv));
757958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        current += PrintRightXMMOperand(current);
758958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        break;
759958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      case 0xab:
760958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        AppendToBuffer("vfmsub213s%c %s,%s,", float_size_code(),
761958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                       NameOfXMMRegister(regop), NameOfXMMRegister(vvvv));
762958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        current += PrintRightXMMOperand(current);
763958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        break;
764958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      case 0xbb:
765958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        AppendToBuffer("vfmsub231s%c %s,%s,", float_size_code(),
766958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                       NameOfXMMRegister(regop), NameOfXMMRegister(vvvv));
767958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        current += PrintRightXMMOperand(current);
768958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        break;
769958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      case 0x9d:
770958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        AppendToBuffer("vfnmadd132s%c %s,%s,", float_size_code(),
771958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                       NameOfXMMRegister(regop), NameOfXMMRegister(vvvv));
772958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        current += PrintRightXMMOperand(current);
773958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        break;
774958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      case 0xad:
775958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        AppendToBuffer("vfnmadd213s%c %s,%s,", float_size_code(),
776958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                       NameOfXMMRegister(regop), NameOfXMMRegister(vvvv));
777958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        current += PrintRightXMMOperand(current);
778958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        break;
779958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      case 0xbd:
780958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        AppendToBuffer("vfnmadd231s%c %s,%s,", float_size_code(),
781958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                       NameOfXMMRegister(regop), NameOfXMMRegister(vvvv));
782958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        current += PrintRightXMMOperand(current);
783958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        break;
784958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      case 0x9f:
785958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        AppendToBuffer("vfnmsub132s%c %s,%s,", float_size_code(),
786958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                       NameOfXMMRegister(regop), NameOfXMMRegister(vvvv));
787958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        current += PrintRightXMMOperand(current);
788958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        break;
789958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      case 0xaf:
790958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        AppendToBuffer("vfnmsub213s%c %s,%s,", float_size_code(),
791958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                       NameOfXMMRegister(regop), NameOfXMMRegister(vvvv));
792958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        current += PrintRightXMMOperand(current);
793958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        break;
794958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      case 0xbf:
795958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        AppendToBuffer("vfnmsub231s%c %s,%s,", float_size_code(),
796958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                       NameOfXMMRegister(regop), NameOfXMMRegister(vvvv));
797958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        current += PrintRightXMMOperand(current);
798958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        break;
799014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      case 0xf7:
800014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        AppendToBuffer("shlx %s,", NameOfCPURegister(regop));
801014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        current += PrintRightOperand(current);
802014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        AppendToBuffer(",%s", NameOfCPURegister(vvvv));
803014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        break;
804958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      default:
805958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        UnimplementedInstruction();
806958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    }
807958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  } else if (vex_f2() && vex_0f()) {
808958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    int mod, regop, rm, vvvv = vex_vreg();
809958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    get_modrm(*current, &mod, &regop, &rm);
810958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    switch (opcode) {
811958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      case 0x58:
812958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        AppendToBuffer("vaddsd %s,%s,", NameOfXMMRegister(regop),
813958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                       NameOfXMMRegister(vvvv));
814958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        current += PrintRightXMMOperand(current);
815958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        break;
816958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      case 0x59:
817958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        AppendToBuffer("vmulsd %s,%s,", NameOfXMMRegister(regop),
818958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                       NameOfXMMRegister(vvvv));
819958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        current += PrintRightXMMOperand(current);
820958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        break;
821958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      case 0x5c:
822958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        AppendToBuffer("vsubsd %s,%s,", NameOfXMMRegister(regop),
823958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                       NameOfXMMRegister(vvvv));
824958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        current += PrintRightXMMOperand(current);
825958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        break;
826014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      case 0x5d:
827014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        AppendToBuffer("vminsd %s,%s,", NameOfXMMRegister(regop),
828014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                       NameOfXMMRegister(vvvv));
829014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        current += PrintRightXMMOperand(current);
830014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        break;
831958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      case 0x5e:
832958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        AppendToBuffer("vdivsd %s,%s,", NameOfXMMRegister(regop),
833958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                       NameOfXMMRegister(vvvv));
834958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        current += PrintRightXMMOperand(current);
835958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        break;
836014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      case 0x5f:
837014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        AppendToBuffer("vmaxsd %s,%s,", NameOfXMMRegister(regop),
838014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                       NameOfXMMRegister(vvvv));
839014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        current += PrintRightXMMOperand(current);
840014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        break;
841014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      default:
842014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        UnimplementedInstruction();
843014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
844014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  } else if (vex_f3() && vex_0f()) {
845014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    int mod, regop, rm, vvvv = vex_vreg();
846014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    get_modrm(*current, &mod, &regop, &rm);
847014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    switch (opcode) {
848014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      case 0x58:
849014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        AppendToBuffer("vaddss %s,%s,", NameOfXMMRegister(regop),
850014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                       NameOfXMMRegister(vvvv));
851014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        current += PrintRightXMMOperand(current);
852014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        break;
853014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      case 0x59:
854014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        AppendToBuffer("vmulss %s,%s,", NameOfXMMRegister(regop),
855014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                       NameOfXMMRegister(vvvv));
856014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        current += PrintRightXMMOperand(current);
857014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        break;
858014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      case 0x5c:
859014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        AppendToBuffer("vsubss %s,%s,", NameOfXMMRegister(regop),
860014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                       NameOfXMMRegister(vvvv));
861014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        current += PrintRightXMMOperand(current);
862014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        break;
863014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      case 0x5d:
864014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        AppendToBuffer("vminss %s,%s,", NameOfXMMRegister(regop),
865014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                       NameOfXMMRegister(vvvv));
866014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        current += PrintRightXMMOperand(current);
867014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        break;
868014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      case 0x5e:
869014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        AppendToBuffer("vdivss %s,%s,", NameOfXMMRegister(regop),
870014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                       NameOfXMMRegister(vvvv));
871014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        current += PrintRightXMMOperand(current);
872014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        break;
873014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      case 0x5f:
874014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        AppendToBuffer("vmaxss %s,%s,", NameOfXMMRegister(regop),
875014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                       NameOfXMMRegister(vvvv));
876014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        current += PrintRightXMMOperand(current);
877014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        break;
878014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      default:
879014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        UnimplementedInstruction();
880014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
881014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  } else if (vex_none() && vex_0f38()) {
882014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    int mod, regop, rm, vvvv = vex_vreg();
883014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    get_modrm(*current, &mod, &regop, &rm);
884014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    const char* mnem = "?";
885014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    switch (opcode) {
886014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      case 0xf2:
887014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        AppendToBuffer("andn %s,%s,", NameOfCPURegister(regop),
888014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                       NameOfCPURegister(vvvv));
889014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        current += PrintRightOperand(current);
890014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        break;
891014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      case 0xf5:
892014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        AppendToBuffer("bzhi %s,", NameOfCPURegister(regop));
893014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        current += PrintRightOperand(current);
894014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        AppendToBuffer(",%s", NameOfCPURegister(vvvv));
895014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        break;
896014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      case 0xf7:
897014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        AppendToBuffer("bextr %s,", NameOfCPURegister(regop));
898014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        current += PrintRightOperand(current);
899014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        AppendToBuffer(",%s", NameOfCPURegister(vvvv));
900014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        break;
901014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      case 0xf3:
902014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        switch (regop) {
903014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          case 1:
904014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            mnem = "blsr";
905014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            break;
906014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          case 2:
907014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            mnem = "blsmsk";
908014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            break;
909014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          case 3:
910014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            mnem = "blsi";
911014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            break;
912014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          default:
913014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            UnimplementedInstruction();
914014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        }
915014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        AppendToBuffer("%s %s,", mnem, NameOfCPURegister(vvvv));
916014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        current += PrintRightOperand(current);
917014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        mnem = "?";
918014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        break;
919014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      default:
920014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        UnimplementedInstruction();
921014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
922014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  } else if (vex_f2() && vex_0f38()) {
923014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    int mod, regop, rm, vvvv = vex_vreg();
924014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    get_modrm(*current, &mod, &regop, &rm);
925014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    switch (opcode) {
926014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      case 0xf5:
927014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        AppendToBuffer("pdep %s,%s,", NameOfCPURegister(regop),
928014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                       NameOfCPURegister(vvvv));
929014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        current += PrintRightOperand(current);
930014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        break;
931014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      case 0xf6:
932014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        AppendToBuffer("mulx %s,%s,", NameOfCPURegister(regop),
933014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                       NameOfCPURegister(vvvv));
934014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        current += PrintRightOperand(current);
935014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        break;
936014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      case 0xf7:
937014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        AppendToBuffer("shrx %s,", NameOfCPURegister(regop));
938014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        current += PrintRightOperand(current);
939014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        AppendToBuffer(",%s", NameOfCPURegister(vvvv));
940014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        break;
941014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      default:
942014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        UnimplementedInstruction();
943014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
944014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  } else if (vex_f3() && vex_0f38()) {
945014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    int mod, regop, rm, vvvv = vex_vreg();
946014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    get_modrm(*current, &mod, &regop, &rm);
947014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    switch (opcode) {
948014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      case 0xf5:
949014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        AppendToBuffer("pext %s,%s,", NameOfCPURegister(regop),
950014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                       NameOfCPURegister(vvvv));
951014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        current += PrintRightOperand(current);
952014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        break;
953014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      case 0xf7:
954014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        AppendToBuffer("sarx %s,", NameOfCPURegister(regop));
955014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        current += PrintRightOperand(current);
956014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        AppendToBuffer(",%s", NameOfCPURegister(vvvv));
957014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        break;
958014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      default:
959014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        UnimplementedInstruction();
960014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
961014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  } else if (vex_f2() && vex_0f3a()) {
962014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    int mod, regop, rm;
963014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    get_modrm(*current, &mod, &regop, &rm);
964014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    switch (opcode) {
965014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      case 0xf0:
966014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        AppendToBuffer("rorx %s,", NameOfCPURegister(regop));
967014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        current += PrintRightOperand(current);
968014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        AppendToBuffer(",%d", *current & 0x1f);
969014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        current += 1;
970014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        break;
971014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      default:
972014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        UnimplementedInstruction();
973014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
974014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  } else if (vex_none() && vex_0f()) {
975014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    int mod, regop, rm, vvvv = vex_vreg();
976014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    get_modrm(*current, &mod, &regop, &rm);
977014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    switch (opcode) {
978014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      case 0x54:
979014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        AppendToBuffer("vandps %s,%s,", NameOfXMMRegister(regop),
980014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                       NameOfXMMRegister(vvvv));
981014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        current += PrintRightXMMOperand(current);
982014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        break;
983014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      case 0x57:
984014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        AppendToBuffer("vxorps %s,%s,", NameOfXMMRegister(regop),
985014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                       NameOfXMMRegister(vvvv));
986014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        current += PrintRightXMMOperand(current);
987014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        break;
988014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      default:
989014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        UnimplementedInstruction();
990014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
991014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  } else if (vex_66() && vex_0f()) {
992014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    int mod, regop, rm, vvvv = vex_vreg();
993014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    get_modrm(*current, &mod, &regop, &rm);
994014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    switch (opcode) {
995014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      case 0x54:
996014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        AppendToBuffer("vandpd %s,%s,", NameOfXMMRegister(regop),
997014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                       NameOfXMMRegister(vvvv));
998014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        current += PrintRightXMMOperand(current);
999014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        break;
1000014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      case 0x57:
1001014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        AppendToBuffer("vxorpd %s,%s,", NameOfXMMRegister(regop),
1002014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                       NameOfXMMRegister(vvvv));
1003014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        current += PrintRightXMMOperand(current);
1004014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        break;
1005958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      default:
1006958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        UnimplementedInstruction();
1007958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    }
1008958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  } else {
1009958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    UnimplementedInstruction();
1010958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
1011958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1012958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  return static_cast<int>(current - data);
1013958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
1014958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1015958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
10163ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// Returns number of bytes used, including *data.
1017a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint DisassemblerIA32::FPUInstruction(byte* data) {
1018d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  byte escape_opcode = *data;
1019b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK_EQ(0xD8, escape_opcode & 0xF8);
1020d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  byte modrm_byte = *(data+1);
1021d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1022d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  if (modrm_byte >= 0xC0) {
1023d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    return RegisterFPUInstruction(escape_opcode, modrm_byte);
1024d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  } else {
1025d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    return MemoryFPUInstruction(escape_opcode, modrm_byte, data+1);
1026d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
1027d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
1028d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1029d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockint DisassemblerIA32::MemoryFPUInstruction(int escape_opcode,
1030d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                                           int modrm_byte,
1031d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                                           byte* modrm_start) {
1032d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  const char* mnem = "?";
1033d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  int regop = (modrm_byte >> 3) & 0x7;  // reg/op field of modrm byte.
1034d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  switch (escape_opcode) {
1035d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case 0xD9: switch (regop) {
1036d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        case 0: mnem = "fld_s"; break;
1037b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        case 2: mnem = "fst_s"; break;
1038d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        case 3: mnem = "fstp_s"; break;
1039d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        case 7: mnem = "fstcw"; break;
1040a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        default: UnimplementedInstruction();
1041a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
1042d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
1043d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1044d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case 0xDB: switch (regop) {
1045d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        case 0: mnem = "fild_s"; break;
1046d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        case 1: mnem = "fisttp_s"; break;
1047d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        case 2: mnem = "fist_s"; break;
1048d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        case 3: mnem = "fistp_s"; break;
1049a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        default: UnimplementedInstruction();
1050a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
1051d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
1052d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1053d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case 0xDD: switch (regop) {
1054d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        case 0: mnem = "fld_d"; break;
10550d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        case 1: mnem = "fisttp_d"; break;
10560d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        case 2: mnem = "fst_d"; break;
1057d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        case 3: mnem = "fstp_d"; break;
1058d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        default: UnimplementedInstruction();
1059d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      }
1060d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
1061d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1062d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case 0xDF: switch (regop) {
1063d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        case 5: mnem = "fild_d"; break;
1064d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        case 7: mnem = "fistp_d"; break;
1065d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        default: UnimplementedInstruction();
1066d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      }
1067d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
1068d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1069d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    default: UnimplementedInstruction();
1070d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
1071d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  AppendToBuffer("%s ", mnem);
1072d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  int count = PrintRightOperand(modrm_start);
1073d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  return count + 1;
1074d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
1075d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1076d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockint DisassemblerIA32::RegisterFPUInstruction(int escape_opcode,
1077d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                                             byte modrm_byte) {
1078d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  bool has_register = false;  // Is the FPU register encoded in modrm_byte?
1079d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  const char* mnem = "?";
1080d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1081d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  switch (escape_opcode) {
1082d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case 0xD8:
1083b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      has_register = true;
1084b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      switch (modrm_byte & 0xF8) {
1085b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        case 0xC0: mnem = "fadd_i"; break;
1086b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        case 0xE0: mnem = "fsub_i"; break;
1087b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        case 0xC8: mnem = "fmul_i"; break;
1088b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        case 0xF0: mnem = "fdiv_i"; break;
1089b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        default: UnimplementedInstruction();
1090b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
1091d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
1092d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1093d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case 0xD9:
1094d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      switch (modrm_byte & 0xF8) {
10950d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        case 0xC0:
10960d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          mnem = "fld";
10970d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          has_register = true;
10980d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          break;
1099d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        case 0xC8:
1100d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          mnem = "fxch";
1101d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          has_register = true;
1102d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          break;
1103d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        default:
1104d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          switch (modrm_byte) {
1105d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block            case 0xE0: mnem = "fchs"; break;
1106d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block            case 0xE1: mnem = "fabs"; break;
1107d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block            case 0xE4: mnem = "ftst"; break;
1108d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block            case 0xE8: mnem = "fld1"; break;
1109402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu            case 0xEB: mnem = "fldpi"; break;
1110b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            case 0xED: mnem = "fldln2"; break;
1111d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block            case 0xEE: mnem = "fldz"; break;
11123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            case 0xF0: mnem = "f2xm1"; break;
1113b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            case 0xF1: mnem = "fyl2x"; break;
1114b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            case 0xF4: mnem = "fxtract"; break;
1115d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block            case 0xF5: mnem = "fprem1"; break;
1116d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block            case 0xF7: mnem = "fincstp"; break;
1117d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block            case 0xF8: mnem = "fprem"; break;
11183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            case 0xFC: mnem = "frndint"; break;
11193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            case 0xFD: mnem = "fscale"; break;
1120d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block            case 0xFE: mnem = "fsin"; break;
1121d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block            case 0xFF: mnem = "fcos"; break;
1122d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block            default: UnimplementedInstruction();
1123d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          }
1124d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      }
1125d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
1126d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1127d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case 0xDA:
1128d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      if (modrm_byte == 0xE9) {
1129d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        mnem = "fucompp";
1130d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      } else {
1131d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        UnimplementedInstruction();
1132d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      }
1133d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
1134d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1135d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case 0xDB:
1136d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      if ((modrm_byte & 0xF8) == 0xE8) {
1137d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        mnem = "fucomi";
1138d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        has_register = true;
1139d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      } else if (modrm_byte  == 0xE2) {
1140d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        mnem = "fclex";
11413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      } else if (modrm_byte == 0xE3) {
11423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        mnem = "fninit";
1143d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      } else {
1144d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        UnimplementedInstruction();
1145d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      }
1146d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
1147d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1148d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case 0xDC:
1149d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      has_register = true;
1150d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      switch (modrm_byte & 0xF8) {
1151d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        case 0xC0: mnem = "fadd"; break;
1152d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        case 0xE8: mnem = "fsub"; break;
1153d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        case 0xC8: mnem = "fmul"; break;
1154d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        case 0xF8: mnem = "fdiv"; break;
1155d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        default: UnimplementedInstruction();
1156d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      }
1157d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
1158d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1159d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case 0xDD:
1160d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      has_register = true;
1161d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      switch (modrm_byte & 0xF8) {
1162d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        case 0xC0: mnem = "ffree"; break;
1163b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        case 0xD0: mnem = "fst"; break;
1164d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        case 0xD8: mnem = "fstp"; break;
1165d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        default: UnimplementedInstruction();
1166d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      }
1167d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
1168d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1169d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case 0xDE:
1170d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      if (modrm_byte  == 0xD9) {
1171d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        mnem = "fcompp";
1172d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      } else {
1173d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        has_register = true;
1174d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        switch (modrm_byte & 0xF8) {
1175d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          case 0xC0: mnem = "faddp"; break;
1176d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          case 0xE8: mnem = "fsubp"; break;
1177d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          case 0xC8: mnem = "fmulp"; break;
1178d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          case 0xF8: mnem = "fdivp"; break;
1179d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          default: UnimplementedInstruction();
1180d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        }
1181d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      }
1182d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
1183d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1184d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    case 0xDF:
1185d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      if (modrm_byte == 0xE0) {
1186d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        mnem = "fnstsw_ax";
1187d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      } else if ((modrm_byte & 0xF8) == 0xE8) {
1188d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        mnem = "fucomip";
1189d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        has_register = true;
1190d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      }
1191d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      break;
1192d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1193d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    default: UnimplementedInstruction();
1194d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
1195d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1196d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  if (has_register) {
1197d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    AppendToBuffer("%s st%d", mnem, modrm_byte & 0x7);
1198d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  } else {
1199a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    AppendToBuffer("%s", mnem);
1200a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1201a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return 2;
1202a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1203a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1204a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1205a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Mnemonics for instructions 0xF0 byte.
1206a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Returns NULL if the instruction is not handled here.
1207a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic const char* F0Mnem(byte f0byte) {
1208a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  switch (f0byte) {
1209014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    case 0x0B:
1210014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      return "ud2";
12113b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    case 0x18:
12123b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      return "prefetch";
12133b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    case 0xA2:
12143b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      return "cpuid";
12153b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    case 0xBE:
12163b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      return "movsx_b";
12173b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    case 0xBF:
12183b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      return "movsx_w";
12193b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    case 0xB6:
12203b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      return "movzx_b";
12213b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    case 0xB7:
12223b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      return "movzx_w";
12233b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    case 0xAF:
12243b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      return "imul";
12253b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    case 0xA4:
12263b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      return "shld";
12273b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    case 0xA5:
12283b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      return "shld";
12293b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    case 0xAD:
12303b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      return "shrd";
12313b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    case 0xAC:
12323b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      return "shrd";  // 3-operand version.
12333b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    case 0xAB:
12343b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      return "bts";
123513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    case 0xB0:
123613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      return "cmpxchg_b";
123713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    case 0xB1:
123813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      return "cmpxchg";
1239014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    case 0xBC:
1240014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      return "bsf";
12413b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    case 0xBD:
12423b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      return "bsr";
1243a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    default: return NULL;
1244a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1245a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1246a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1247a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1248a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Disassembled instruction '*instr' and writes it into 'out_buffer'.
1249a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint DisassemblerIA32::InstructionDecode(v8::internal::Vector<char> out_buffer,
1250a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                        byte* instr) {
1251a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  tmp_buffer_pos_ = 0;  // starting to write as position 0
1252a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  byte* data = instr;
1253a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check for hints.
1254a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const char* branch_hint = NULL;
1255a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // We use these two prefixes only with branch prediction
1256a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (*data == 0x3E /*ds*/) {
1257a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    branch_hint = "predicted taken";
1258a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    data++;
1259a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else if (*data == 0x2E /*cs*/) {
1260a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    branch_hint = "predicted not taken";
1261a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    data++;
1262958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  } else if (*data == 0xC4 && *(data + 1) >= 0xc0) {
1263958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    vex_byte0_ = *data;
1264958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    vex_byte1_ = *(data + 1);
1265958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    vex_byte2_ = *(data + 2);
1266958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    data += 3;
1267958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  } else if (*data == 0xC5 && *(data + 1) >= 0xc0) {
1268958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    vex_byte0_ = *data;
1269958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    vex_byte1_ = *(data + 1);
1270958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    data += 2;
127113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  } else if (*data == 0xF0 /*lock*/) {
127213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    AppendToBuffer("lock ");
127313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    data++;
1274a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1275958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1276a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bool processed = true;  // Will be set to false if the current instruction
1277a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                          // is not in 'instructions' table.
1278958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Decode AVX instructions.
1279958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  if (vex_byte0_ != 0) {
1280958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    data += AVXInstruction(data);
1281958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  } else {
1282958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    const InstructionDesc& idesc = instruction_table_->Get(*data);
1283958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    switch (idesc.type) {
1284958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      case ZERO_OPERANDS_INSTR:
1285bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch        AppendToBuffer("%s", idesc.mnem);
1286958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        data++;
1287958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        break;
1288a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1289958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      case TWO_OPERANDS_INSTR:
1290958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        data++;
1291958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        data += PrintOperands(idesc.mnem, idesc.op_order_, data);
1292958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        break;
1293a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1294958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      case JUMP_CONDITIONAL_SHORT_INSTR:
1295958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        data += JumpConditionalShort(data, branch_hint);
1296958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        break;
1297a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1298958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      case REGISTER_INSTR:
1299958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        AppendToBuffer("%s %s", idesc.mnem, NameOfCPURegister(*data & 0x07));
1300958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        data++;
1301958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        break;
1302a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1303958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      case MOVE_REG_INSTR: {
1304958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        byte* addr =
1305958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier            reinterpret_cast<byte*>(*reinterpret_cast<int32_t*>(data + 1));
1306958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        AppendToBuffer("mov %s,%s", NameOfCPURegister(*data & 0x07),
1307958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                       NameOfAddress(addr));
1308958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        data += 5;
1309958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        break;
1310958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      }
1311a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1312958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      case CALL_JUMP_INSTR: {
1313958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        byte* addr = data + *reinterpret_cast<int32_t*>(data + 1) + 5;
1314958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        AppendToBuffer("%s %s", idesc.mnem, NameOfAddress(addr));
1315958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        data += 5;
1316958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        break;
1317958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      }
1318a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1319958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      case SHORT_IMMEDIATE_INSTR: {
1320958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        byte* addr =
1321958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier            reinterpret_cast<byte*>(*reinterpret_cast<int32_t*>(data + 1));
1322958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        AppendToBuffer("%s eax,%s", idesc.mnem, NameOfAddress(addr));
1323958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        data += 5;
1324958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        break;
1325958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      }
1326a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1327958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      case BYTE_IMMEDIATE_INSTR: {
1328958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        AppendToBuffer("%s al,0x%x", idesc.mnem, data[1]);
1329958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        data += 2;
1330958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        break;
1331958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      }
13323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1333958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      case NO_INSTR:
1334958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        processed = false;
1335958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        break;
1336a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1337958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      default:
1338958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        UNIMPLEMENTED();  // This type is not implemented.
1339958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    }
1340a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1341a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //----------------------------
1342a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (!processed) {
1343a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    switch (*data) {
1344a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 0xC2:
1345a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        AppendToBuffer("ret 0x%x", *reinterpret_cast<uint16_t*>(data+1));
1346a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        data += 3;
1347a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
1348a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1349b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case 0x6B: {
1350b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        data++;
1351b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        data += PrintOperands("imul", REG_OPER_OP_ORDER, data);
1352b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        AppendToBuffer(",%d", *data);
1353b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        data++;
1354b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      } break;
1355b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1356b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case 0x69: {
1357b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        data++;
1358b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        data += PrintOperands("imul", REG_OPER_OP_ORDER, data);
1359b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        AppendToBuffer(",%d", *reinterpret_cast<int32_t*>(data));
1360b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        data += 4;
1361a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        }
1362a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
1363a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1364a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 0xF6:
13657f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch        { data++;
13667f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch          int mod, regop, rm;
13677f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch          get_modrm(*data, &mod, &regop, &rm);
13687f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch          if (regop == eax) {
13697f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch            AppendToBuffer("test_b ");
137044f0eee88ff00398ff7f715fab053374d808c90dSteve Block            data += PrintRightByteOperand(data);
13717f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch            int32_t imm = *data;
13727f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch            AppendToBuffer(",0x%x", imm);
13737f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch            data++;
1374a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          } else {
1375a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            UnimplementedInstruction();
1376a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          }
1377a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        }
1378a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
1379a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1380a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 0x81:  // fall through
1381a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 0x83:  // 0x81 with sign extension bit set
1382a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        data += PrintImmediateOp(data);
1383a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
1384a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1385a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 0x0F:
13863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        { byte f0byte = data[1];
1387a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          const char* f0mnem = F0Mnem(f0byte);
13887f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch          if (f0byte == 0x18) {
1389b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            data += 2;
13907f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch            int mod, regop, rm;
13917f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch            get_modrm(*data, &mod, &regop, &rm);
13927f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch            const char* suffix[] = {"nta", "1", "2", "3"};
13937f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch            AppendToBuffer("%s%s ", f0mnem, suffix[regop & 0x03]);
13947f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch            data += PrintRightOperand(data);
13953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          } else if (f0byte == 0x1F && data[2] == 0) {
13963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            AppendToBuffer("nop");  // 3 byte nop.
13973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            data += 3;
13983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          } else if (f0byte == 0x1F && data[2] == 0x40 && data[3] == 0) {
13993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            AppendToBuffer("nop");  // 4 byte nop.
14003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            data += 4;
14013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          } else if (f0byte == 0x1F && data[2] == 0x44 && data[3] == 0 &&
14023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                     data[4] == 0) {
14033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            AppendToBuffer("nop");  // 5 byte nop.
14043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            data += 5;
14053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          } else if (f0byte == 0x1F && data[2] == 0x80 && data[3] == 0 &&
14063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                     data[4] == 0 && data[5] == 0 && data[6] == 0) {
14073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            AppendToBuffer("nop");  // 7 byte nop.
14083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            data += 7;
14093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          } else if (f0byte == 0x1F && data[2] == 0x84 && data[3] == 0 &&
14103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                     data[4] == 0 && data[5] == 0 && data[6] == 0 &&
14113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                     data[7] == 0) {
14123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            AppendToBuffer("nop");  // 8 byte nop.
14133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            data += 8;
1414014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          } else if (f0byte == 0x0B || f0byte == 0xA2 || f0byte == 0x31) {
1415a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            AppendToBuffer("%s", f0mnem);
1416a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            data += 2;
14170d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          } else if (f0byte == 0x28) {
14180d5e116f6aee03185f237311a943491bb079a768Kristian Monsen            data += 2;
14190d5e116f6aee03185f237311a943491bb079a768Kristian Monsen            int mod, regop, rm;
14200d5e116f6aee03185f237311a943491bb079a768Kristian Monsen            get_modrm(*data, &mod, &regop, &rm);
14210d5e116f6aee03185f237311a943491bb079a768Kristian Monsen            AppendToBuffer("movaps %s,%s",
14220d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                           NameOfXMMRegister(regop),
14230d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                           NameOfXMMRegister(rm));
14240d5e116f6aee03185f237311a943491bb079a768Kristian Monsen            data++;
1425f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch          } else if (f0byte == 0x10 || f0byte == 0x11) {
1426f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch            data += 2;
1427f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch            // movups xmm, xmm/m128
1428f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch            // movups xmm/m128, xmm
1429f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch            int mod, regop, rm;
1430f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch            get_modrm(*data, &mod, &regop, &rm);
1431f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch            AppendToBuffer("movups ");
1432f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch            if (f0byte == 0x11) {
1433f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch              data += PrintRightXMMOperand(data);
1434f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch              AppendToBuffer(",%s", NameOfXMMRegister(regop));
1435f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch            } else {
1436f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch              AppendToBuffer("%s,", NameOfXMMRegister(regop));
1437f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch              data += PrintRightXMMOperand(data);
1438f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch            }
1439958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier          } else if (f0byte == 0x2e) {
1440958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier            data += 2;
1441958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier            int mod, regop, rm;
1442958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier            get_modrm(*data, &mod, &regop, &rm);
1443958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier            AppendToBuffer("ucomiss %s,", NameOfXMMRegister(regop));
1444958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier            data += PrintRightXMMOperand(data);
1445b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          } else if (f0byte >= 0x53 && f0byte <= 0x5F) {
1446b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            const char* const pseudo_op[] = {
1447b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch              "rcpps",
1448b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch              "andps",
1449b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch              "andnps",
1450b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch              "orps",
1451b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch              "xorps",
1452b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch              "addps",
1453b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch              "mulps",
1454b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch              "cvtps2pd",
1455b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch              "cvtdq2ps",
1456b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch              "subps",
1457b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch              "minps",
1458b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch              "divps",
1459b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch              "maxps",
1460b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            };
1461b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1462257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch            data += 2;
1463257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch            int mod, regop, rm;
1464257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch            get_modrm(*data, &mod, &regop, &rm);
1465b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            AppendToBuffer("%s %s,",
1466b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                           pseudo_op[f0byte - 0x53],
1467b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                           NameOfXMMRegister(regop));
1468b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            data += PrintRightXMMOperand(data);
1469b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          } else if (f0byte == 0x50) {
1470b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            data += 2;
1471b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            int mod, regop, rm;
1472b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            get_modrm(*data, &mod, &regop, &rm);
1473b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            AppendToBuffer("movmskps %s,%s",
1474b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                           NameOfCPURegister(regop),
1475257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                           NameOfXMMRegister(rm));
1476257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch            data++;
1477b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          } else if (f0byte== 0xC6) {
1478b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            // shufps xmm, xmm/m128, imm8
1479b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            data += 2;
1480b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            int mod, regop, rm;
1481b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            get_modrm(*data, &mod, &regop, &rm);
1482b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            int8_t imm8 = static_cast<int8_t>(data[1]);
1483b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            AppendToBuffer("shufps %s,%s,%d",
1484b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                            NameOfXMMRegister(rm),
1485b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                            NameOfXMMRegister(regop),
1486b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                            static_cast<int>(imm8));
1487b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            data += 2;
1488a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          } else if ((f0byte & 0xF0) == 0x80) {
1489a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            data += JumpConditional(data, branch_hint);
1490a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          } else if (f0byte == 0xBE || f0byte == 0xBF || f0byte == 0xB6 ||
1491a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                     f0byte == 0xB7 || f0byte == 0xAF) {
1492a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            data += 2;
1493a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            data += PrintOperands(f0mnem, REG_OPER_OP_ORDER, data);
1494a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          } else if ((f0byte & 0xF0) == 0x90) {
1495a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            data += SetCC(data);
14963ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block          } else if ((f0byte & 0xF0) == 0x40) {
14973ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block            data += CMov(data);
14983b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch          } else if (f0byte == 0xA4 || f0byte == 0xAC) {
14993b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch            // shld, shrd
15003b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch            data += 2;
15013b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch            AppendToBuffer("%s ", f0mnem);
15023b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch            int mod, regop, rm;
15033b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch            get_modrm(*data, &mod, &regop, &rm);
15043b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch            int8_t imm8 = static_cast<int8_t>(data[1]);
15053b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch            data += 2;
15063b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch            AppendToBuffer("%s,%s,%d", NameOfCPURegister(rm),
15073b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch                           NameOfCPURegister(regop), static_cast<int>(imm8));
1508b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          } else if (f0byte == 0xAB || f0byte == 0xA5 || f0byte == 0xAD) {
15093b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch            // shrd_cl, shld_cl, bts
1510a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            data += 2;
1511b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            AppendToBuffer("%s ", f0mnem);
1512b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            int mod, regop, rm;
1513b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            get_modrm(*data, &mod, &regop, &rm);
1514b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            data += PrintRightOperand(data);
1515b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            if (f0byte == 0xAB) {
1516b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch              AppendToBuffer(",%s", NameOfCPURegister(regop));
1517a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            } else {
1518b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch              AppendToBuffer(",%s,cl", NameOfCPURegister(regop));
1519a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            }
152013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch          } else if (f0byte == 0xB0) {
152113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch            // cmpxchg_b
152213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch            data += 2;
152313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch            AppendToBuffer("%s ", f0mnem);
152413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch            int mod, regop, rm;
152513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch            get_modrm(*data, &mod, &regop, &rm);
152613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch            data += PrintRightOperand(data);
152713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch            AppendToBuffer(",%s", NameOfByteCPURegister(regop));
152813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch          } else if (f0byte == 0xB1) {
152913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch            // cmpxchg
153013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch            data += 2;
153113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch            data += PrintOperands(f0mnem, OPER_REG_OP_ORDER, data);
1532014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          } else if (f0byte == 0xBC) {
1533014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            data += 2;
1534014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            int mod, regop, rm;
1535014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            get_modrm(*data, &mod, &regop, &rm);
1536014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            AppendToBuffer("%s %s,", f0mnem, NameOfCPURegister(regop));
1537014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            data += PrintRightOperand(data);
1538b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          } else if (f0byte == 0xBD) {
1539b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            data += 2;
1540b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            int mod, regop, rm;
1541b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            get_modrm(*data, &mod, &regop, &rm);
1542b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            AppendToBuffer("%s %s,", f0mnem, NameOfCPURegister(regop));
1543b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            data += PrintRightOperand(data);
1544b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          } else {
1545b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            UnimplementedInstruction();
1546a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          }
1547a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        }
1548a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
1549a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1550a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 0x8F:
1551a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        { data++;
1552a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          int mod, regop, rm;
1553a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          get_modrm(*data, &mod, &regop, &rm);
1554a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          if (regop == eax) {
1555a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            AppendToBuffer("pop ");
1556a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            data += PrintRightOperand(data);
1557a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          }
1558a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        }
1559a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
1560a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1561a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 0xFF:
1562a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        { data++;
1563a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          int mod, regop, rm;
1564a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          get_modrm(*data, &mod, &regop, &rm);
1565a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          const char* mnem = NULL;
1566a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          switch (regop) {
1567a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            case esi: mnem = "push"; break;
1568a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            case eax: mnem = "inc"; break;
1569a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            case ecx: mnem = "dec"; break;
1570a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            case edx: mnem = "call"; break;
1571a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            case esp: mnem = "jmp"; break;
1572a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            default: mnem = "???";
1573a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          }
1574a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          AppendToBuffer("%s ", mnem);
1575a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          data += PrintRightOperand(data);
1576a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        }
1577a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
1578a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1579a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 0xC7:  // imm32, fall through
1580a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 0xC6:  // imm8
1581a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        { bool is_byte = *data == 0xC6;
1582a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          data++;
158344f0eee88ff00398ff7f715fab053374d808c90dSteve Block          if (is_byte) {
158444f0eee88ff00398ff7f715fab053374d808c90dSteve Block            AppendToBuffer("%s ", "mov_b");
158544f0eee88ff00398ff7f715fab053374d808c90dSteve Block            data += PrintRightByteOperand(data);
158644f0eee88ff00398ff7f715fab053374d808c90dSteve Block            int32_t imm = *data;
158744f0eee88ff00398ff7f715fab053374d808c90dSteve Block            AppendToBuffer(",0x%x", imm);
158844f0eee88ff00398ff7f715fab053374d808c90dSteve Block            data++;
158944f0eee88ff00398ff7f715fab053374d808c90dSteve Block          } else {
159044f0eee88ff00398ff7f715fab053374d808c90dSteve Block            AppendToBuffer("%s ", "mov");
159144f0eee88ff00398ff7f715fab053374d808c90dSteve Block            data += PrintRightOperand(data);
159244f0eee88ff00398ff7f715fab053374d808c90dSteve Block            int32_t imm = *reinterpret_cast<int32_t*>(data);
159344f0eee88ff00398ff7f715fab053374d808c90dSteve Block            AppendToBuffer(",0x%x", imm);
159444f0eee88ff00398ff7f715fab053374d808c90dSteve Block            data += 4;
159544f0eee88ff00398ff7f715fab053374d808c90dSteve Block          }
1596a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        }
1597a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
1598a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1599a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 0x80:
1600a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        { data++;
1601e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          int mod, regop, rm;
1602e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          get_modrm(*data, &mod, &regop, &rm);
1603e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          const char* mnem = NULL;
1604e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          switch (regop) {
1605e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke            case 5:  mnem = "subb"; break;
1606e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke            case 7:  mnem = "cmpb"; break;
1607e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke            default: UnimplementedInstruction();
1608e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          }
1609e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          AppendToBuffer("%s ", mnem);
161044f0eee88ff00398ff7f715fab053374d808c90dSteve Block          data += PrintRightByteOperand(data);
1611a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          int32_t imm = *data;
1612a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          AppendToBuffer(",0x%x", imm);
1613a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          data++;
1614a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        }
1615a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
1616a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1617a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 0x88:  // 8bit, fall through
1618a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 0x89:  // 32bit
1619a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        { bool is_byte = *data == 0x88;
1620a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          int mod, regop, rm;
1621a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          data++;
1622a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          get_modrm(*data, &mod, &regop, &rm);
162344f0eee88ff00398ff7f715fab053374d808c90dSteve Block          if (is_byte) {
162444f0eee88ff00398ff7f715fab053374d808c90dSteve Block            AppendToBuffer("%s ", "mov_b");
162544f0eee88ff00398ff7f715fab053374d808c90dSteve Block            data += PrintRightByteOperand(data);
162644f0eee88ff00398ff7f715fab053374d808c90dSteve Block            AppendToBuffer(",%s", NameOfByteCPURegister(regop));
162744f0eee88ff00398ff7f715fab053374d808c90dSteve Block          } else {
162844f0eee88ff00398ff7f715fab053374d808c90dSteve Block            AppendToBuffer("%s ", "mov");
162944f0eee88ff00398ff7f715fab053374d808c90dSteve Block            data += PrintRightOperand(data);
163044f0eee88ff00398ff7f715fab053374d808c90dSteve Block            AppendToBuffer(",%s", NameOfCPURegister(regop));
163144f0eee88ff00398ff7f715fab053374d808c90dSteve Block          }
1632a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        }
1633a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
1634a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1635a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 0x66:  // prefix
16363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        while (*data == 0x66) data++;
16373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        if (*data == 0xf && data[1] == 0x1f) {
16383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          AppendToBuffer("nop");  // 0x66 prefix
1639bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch        } else if (*data == 0x39) {
1640a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          data++;
1641bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch          data += PrintOperands("cmpw", OPER_REG_OP_ORDER, data);
1642bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch        } else if (*data == 0x3B) {
1643bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch          data++;
1644bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch          data += PrintOperands("cmpw", REG_OPER_OP_ORDER, data);
1645bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch        } else if (*data == 0x81) {
1646bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch          data++;
1647bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch          AppendToBuffer("cmpw ");
1648bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch          data += PrintRightOperand(data);
1649bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch          int imm = *reinterpret_cast<int16_t*>(data);
1650bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch          AppendToBuffer(",0x%x", imm);
1651bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch          data += 2;
1652bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch        } else if (*data == 0x87) {
1653bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch          data++;
1654bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch          int mod, regop, rm;
1655bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch          get_modrm(*data, &mod, &regop, &rm);
165613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch          AppendToBuffer("xchg_w %s,", NameOfCPURegister(regop));
1657bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch          data += PrintRightOperand(data);
1658a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        } else if (*data == 0x89) {
1659a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          data++;
1660a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          int mod, regop, rm;
1661a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          get_modrm(*data, &mod, &regop, &rm);
1662a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          AppendToBuffer("mov_w ");
1663a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          data += PrintRightOperand(data);
1664a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          AppendToBuffer(",%s", NameOfCPURegister(regop));
1665bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch        } else if (*data == 0x8B) {
1666bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch          data++;
1667bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch          data += PrintOperands("mov_w", REG_OPER_OP_ORDER, data);
1668bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch        } else if (*data == 0x90) {
1669bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch          AppendToBuffer("nop");  // 0x66 prefix
1670b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        } else if (*data == 0xC7) {
1671b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          data++;
1672b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          AppendToBuffer("%s ", "mov_w");
1673b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          data += PrintRightOperand(data);
1674b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          int imm = *reinterpret_cast<int16_t*>(data);
1675b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          AppendToBuffer(",0x%x", imm);
1676b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          data += 2;
16773b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch        } else if (*data == 0xF7) {
16783b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch          data++;
16793b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch          AppendToBuffer("%s ", "test_w");
16803b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch          data += PrintRightOperand(data);
16813b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch          int imm = *reinterpret_cast<int16_t*>(data);
16823b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch          AppendToBuffer(",0x%x", imm);
16833b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch          data += 2;
16843ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block        } else if (*data == 0x0F) {
16853ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block          data++;
16866ded16be15dd865a9b21ea304d5273c8be299c87Steve Block          if (*data == 0x38) {
16876ded16be15dd865a9b21ea304d5273c8be299c87Steve Block            data++;
16886ded16be15dd865a9b21ea304d5273c8be299c87Steve Block            if (*data == 0x17) {
16896ded16be15dd865a9b21ea304d5273c8be299c87Steve Block              data++;
16906ded16be15dd865a9b21ea304d5273c8be299c87Steve Block              int mod, regop, rm;
16916ded16be15dd865a9b21ea304d5273c8be299c87Steve Block              get_modrm(*data, &mod, &regop, &rm);
16926ded16be15dd865a9b21ea304d5273c8be299c87Steve Block              AppendToBuffer("ptest %s,%s",
16936ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                             NameOfXMMRegister(regop),
16946ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                             NameOfXMMRegister(rm));
16956ded16be15dd865a9b21ea304d5273c8be299c87Steve Block              data++;
16967f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch            } else if (*data == 0x2A) {
16977f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch              // movntdqa
1698014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch              UnimplementedInstruction();
16996ded16be15dd865a9b21ea304d5273c8be299c87Steve Block            } else {
17006ded16be15dd865a9b21ea304d5273c8be299c87Steve Block              UnimplementedInstruction();
17016ded16be15dd865a9b21ea304d5273c8be299c87Steve Block            }
1702b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          } else if (*data == 0x3A) {
1703b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            data++;
1704109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch            if (*data == 0x0A) {
1705109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch              data++;
1706109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch              int mod, regop, rm;
1707109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch              get_modrm(*data, &mod, &regop, &rm);
1708109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch              int8_t imm8 = static_cast<int8_t>(data[1]);
1709109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch              AppendToBuffer("roundss %s,%s,%d", NameOfXMMRegister(regop),
1710109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch                             NameOfXMMRegister(rm), static_cast<int>(imm8));
1711109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch              data += 2;
1712109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch            } else if (*data == 0x0B) {
171369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch              data++;
171469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch              int mod, regop, rm;
171569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch              get_modrm(*data, &mod, &regop, &rm);
171669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch              int8_t imm8 = static_cast<int8_t>(data[1]);
171769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch              AppendToBuffer("roundsd %s,%s,%d",
171869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch                             NameOfXMMRegister(regop),
171969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch                             NameOfXMMRegister(rm),
172069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch                             static_cast<int>(imm8));
172169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch              data += 2;
172269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch            } else if (*data == 0x16) {
1723b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch              data++;
1724b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch              int mod, regop, rm;
1725014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch              get_modrm(*data, &mod, &rm, &regop);
1726b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch              int8_t imm8 = static_cast<int8_t>(data[1]);
1727b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch              AppendToBuffer("pextrd %s,%s,%d",
17281e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                             NameOfCPURegister(regop),
1729b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                             NameOfXMMRegister(rm),
1730b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                             static_cast<int>(imm8));
1731b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch              data += 2;
17323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            } else if (*data == 0x17) {
17333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch              data++;
17343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch              int mod, regop, rm;
17353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch              get_modrm(*data, &mod, &regop, &rm);
17363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch              int8_t imm8 = static_cast<int8_t>(data[1]);
17373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch              AppendToBuffer("extractps %s,%s,%d",
1738b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                             NameOfCPURegister(rm),
1739b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                             NameOfXMMRegister(regop),
17403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                             static_cast<int>(imm8));
17413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch              data += 2;
17421e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block            } else if (*data == 0x22) {
17431e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block              data++;
17441e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block              int mod, regop, rm;
17451e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block              get_modrm(*data, &mod, &regop, &rm);
17461e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block              int8_t imm8 = static_cast<int8_t>(data[1]);
17471e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block              AppendToBuffer("pinsrd %s,%s,%d",
17481e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                             NameOfXMMRegister(regop),
17491e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                             NameOfCPURegister(rm),
17501e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                             static_cast<int>(imm8));
17511e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block              data += 2;
1752b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            } else {
1753b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch              UnimplementedInstruction();
1754b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            }
17556ded16be15dd865a9b21ea304d5273c8be299c87Steve Block          } else if (*data == 0x2E || *data == 0x2F) {
17566ded16be15dd865a9b21ea304d5273c8be299c87Steve Block            const char* mnem = (*data == 0x2E) ? "ucomisd" : "comisd";
17573ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block            data++;
17583ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block            int mod, regop, rm;
17593ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block            get_modrm(*data, &mod, &regop, &rm);
17606ded16be15dd865a9b21ea304d5273c8be299c87Steve Block            if (mod == 0x3) {
17616ded16be15dd865a9b21ea304d5273c8be299c87Steve Block              AppendToBuffer("%s %s,%s", mnem,
17626ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                             NameOfXMMRegister(regop),
17636ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                             NameOfXMMRegister(rm));
17646ded16be15dd865a9b21ea304d5273c8be299c87Steve Block              data++;
17656ded16be15dd865a9b21ea304d5273c8be299c87Steve Block            } else {
17666ded16be15dd865a9b21ea304d5273c8be299c87Steve Block              AppendToBuffer("%s %s,", mnem, NameOfXMMRegister(regop));
17676ded16be15dd865a9b21ea304d5273c8be299c87Steve Block              data += PrintRightOperand(data);
17686ded16be15dd865a9b21ea304d5273c8be299c87Steve Block            }
17696ded16be15dd865a9b21ea304d5273c8be299c87Steve Block          } else if (*data == 0x50) {
17706ded16be15dd865a9b21ea304d5273c8be299c87Steve Block            data++;
17716ded16be15dd865a9b21ea304d5273c8be299c87Steve Block            int mod, regop, rm;
17726ded16be15dd865a9b21ea304d5273c8be299c87Steve Block            get_modrm(*data, &mod, &regop, &rm);
17736ded16be15dd865a9b21ea304d5273c8be299c87Steve Block            AppendToBuffer("movmskpd %s,%s",
17746ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                           NameOfCPURegister(regop),
17753ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                           NameOfXMMRegister(rm));
17763ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block            data++;
1777b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          } else if (*data == 0x54) {
1778b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            data++;
1779b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            int mod, regop, rm;
1780b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            get_modrm(*data, &mod, &regop, &rm);
1781b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            AppendToBuffer("andpd %s,%s",
1782b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                           NameOfXMMRegister(regop),
1783b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                           NameOfXMMRegister(rm));
1784b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            data++;
1785b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          } else if (*data == 0x56) {
1786b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            data++;
1787b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            int mod, regop, rm;
1788b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            get_modrm(*data, &mod, &regop, &rm);
1789b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            AppendToBuffer("orpd %s,%s",
1790b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                           NameOfXMMRegister(regop),
1791b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                           NameOfXMMRegister(rm));
1792b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            data++;
1793e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          } else if (*data == 0x57) {
1794e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke            data++;
1795e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke            int mod, regop, rm;
1796e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke            get_modrm(*data, &mod, &regop, &rm);
1797e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke            AppendToBuffer("xorpd %s,%s",
1798e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                           NameOfXMMRegister(regop),
1799e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                           NameOfXMMRegister(rm));
1800e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke            data++;
18016ded16be15dd865a9b21ea304d5273c8be299c87Steve Block          } else if (*data == 0x6E) {
18026ded16be15dd865a9b21ea304d5273c8be299c87Steve Block            data++;
18036ded16be15dd865a9b21ea304d5273c8be299c87Steve Block            int mod, regop, rm;
18046ded16be15dd865a9b21ea304d5273c8be299c87Steve Block            get_modrm(*data, &mod, &regop, &rm);
18056ded16be15dd865a9b21ea304d5273c8be299c87Steve Block            AppendToBuffer("movd %s,", NameOfXMMRegister(regop));
18066ded16be15dd865a9b21ea304d5273c8be299c87Steve Block            data += PrintRightOperand(data);
1807e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          } else if (*data == 0x6F) {
1808e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke            data++;
1809e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke            int mod, regop, rm;
1810e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke            get_modrm(*data, &mod, &regop, &rm);
1811e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke            AppendToBuffer("movdqa %s,", NameOfXMMRegister(regop));
181244f0eee88ff00398ff7f715fab053374d808c90dSteve Block            data += PrintRightXMMOperand(data);
1813b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          } else if (*data == 0x70) {
1814b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            data++;
1815b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            int mod, regop, rm;
1816b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            get_modrm(*data, &mod, &regop, &rm);
1817b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            int8_t imm8 = static_cast<int8_t>(data[1]);
1818b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            AppendToBuffer("pshufd %s,%s,%d",
1819b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                           NameOfXMMRegister(regop),
1820b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                           NameOfXMMRegister(rm),
1821b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                           static_cast<int>(imm8));
1822b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            data += 2;
1823014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          } else if (*data == 0x62) {
1824014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            data++;
1825014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            int mod, regop, rm;
1826014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            get_modrm(*data, &mod, &regop, &rm);
1827014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            AppendToBuffer("punpckldq %s,%s", NameOfXMMRegister(regop),
1828014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                           NameOfXMMRegister(rm));
1829014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            data++;
1830014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          } else if (*data == 0x6A) {
1831014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            data++;
1832014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            int mod, regop, rm;
1833014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            get_modrm(*data, &mod, &regop, &rm);
1834014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            AppendToBuffer("punpckhdq %s,%s", NameOfXMMRegister(regop),
1835014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                           NameOfXMMRegister(rm));
1836014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            data++;
1837b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          } else if (*data == 0x76) {
1838b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            data++;
1839b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            int mod, regop, rm;
1840b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            get_modrm(*data, &mod, &regop, &rm);
1841b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            AppendToBuffer("pcmpeqd %s,%s",
1842b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                           NameOfXMMRegister(regop),
1843b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                           NameOfXMMRegister(rm));
1844b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            data++;
18453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          } else if (*data == 0x90) {
18463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            data++;
18473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            AppendToBuffer("nop");  // 2 byte nop.
1848b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch          } else if (*data == 0xF3) {
1849b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch            data++;
1850b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch            int mod, regop, rm;
1851b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch            get_modrm(*data, &mod, &regop, &rm);
1852b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch            AppendToBuffer("psllq %s,%s",
1853b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch                           NameOfXMMRegister(regop),
1854b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch                           NameOfXMMRegister(rm));
1855b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch            data++;
1856958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier          } else if (*data == 0x72) {
1857958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier            data++;
1858958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier            int mod, regop, rm;
1859958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier            get_modrm(*data, &mod, &regop, &rm);
1860958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier            int8_t imm8 = static_cast<int8_t>(data[1]);
1861958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier            DCHECK(regop == esi || regop == edx);
1862958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier            AppendToBuffer("%s %s,%d", (regop == esi) ? "pslld" : "psrld",
1863958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                           NameOfXMMRegister(rm), static_cast<int>(imm8));
1864958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier            data += 2;
1865b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          } else if (*data == 0x73) {
1866b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            data++;
1867b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            int mod, regop, rm;
1868b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            get_modrm(*data, &mod, &regop, &rm);
1869b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            int8_t imm8 = static_cast<int8_t>(data[1]);
1870b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            DCHECK(regop == esi || regop == edx);
1871b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch            AppendToBuffer("%s %s,%d",
1872b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch                           (regop == esi) ? "psllq" : "psrlq",
1873b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                           NameOfXMMRegister(rm),
1874b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                           static_cast<int>(imm8));
1875b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            data += 2;
1876b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch          } else if (*data == 0xD3) {
1877b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch            data++;
1878b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch            int mod, regop, rm;
1879b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch            get_modrm(*data, &mod, &regop, &rm);
1880b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch            AppendToBuffer("psrlq %s,%s",
1881b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch                           NameOfXMMRegister(regop),
1882b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch                           NameOfXMMRegister(rm));
1883b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch            data++;
1884e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          } else if (*data == 0x7F) {
1885e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke            AppendToBuffer("movdqa ");
1886e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke            data++;
1887e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke            int mod, regop, rm;
1888e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke            get_modrm(*data, &mod, &regop, &rm);
188944f0eee88ff00398ff7f715fab053374d808c90dSteve Block            data += PrintRightXMMOperand(data);
1890e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke            AppendToBuffer(",%s", NameOfXMMRegister(regop));
1891b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          } else if (*data == 0x7E) {
1892b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            data++;
1893b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            int mod, regop, rm;
1894b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            get_modrm(*data, &mod, &regop, &rm);
1895b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            AppendToBuffer("movd ");
1896b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            data += PrintRightOperand(data);
1897b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            AppendToBuffer(",%s", NameOfXMMRegister(regop));
1898b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          } else if (*data == 0xDB) {
1899b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            data++;
1900b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            int mod, regop, rm;
1901b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            get_modrm(*data, &mod, &regop, &rm);
1902b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            AppendToBuffer("pand %s,%s",
1903b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                           NameOfXMMRegister(regop),
1904b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                           NameOfXMMRegister(rm));
1905b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            data++;
19067f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch          } else if (*data == 0xE7) {
19077f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch            data++;
19087f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch            int mod, regop, rm;
19097f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch            get_modrm(*data, &mod, &regop, &rm);
191044f0eee88ff00398ff7f715fab053374d808c90dSteve Block            if (mod == 3) {
1911014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch              // movntdq
1912014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch              UnimplementedInstruction();
191344f0eee88ff00398ff7f715fab053374d808c90dSteve Block            } else {
191444f0eee88ff00398ff7f715fab053374d808c90dSteve Block              UnimplementedInstruction();
191544f0eee88ff00398ff7f715fab053374d808c90dSteve Block            }
19166ded16be15dd865a9b21ea304d5273c8be299c87Steve Block          } else if (*data == 0xEF) {
1917b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            data++;
1918b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            int mod, regop, rm;
1919b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            get_modrm(*data, &mod, &regop, &rm);
1920b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            AppendToBuffer("pxor %s,%s",
1921b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                           NameOfXMMRegister(regop),
1922b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                           NameOfXMMRegister(rm));
1923b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            data++;
1924b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch          } else if (*data == 0xEB) {
1925b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch            data++;
1926b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch            int mod, regop, rm;
1927b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch            get_modrm(*data, &mod, &regop, &rm);
1928b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch            AppendToBuffer("por %s,%s",
1929b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch                           NameOfXMMRegister(regop),
1930b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch                           NameOfXMMRegister(rm));
1931b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch            data++;
193213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch          } else if (*data == 0xB1) {
193313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch            data++;
193413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch            data += PrintOperands("cmpxchg_w", OPER_REG_OP_ORDER, data);
19353ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block          } else {
19363ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block            UnimplementedInstruction();
19373ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block          }
1938a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        } else {
1939a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          UnimplementedInstruction();
1940a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        }
1941a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
1942a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1943a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 0xFE:
1944a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        { data++;
1945a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          int mod, regop, rm;
1946a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          get_modrm(*data, &mod, &regop, &rm);
19470d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          if (regop == ecx) {
19480d5e116f6aee03185f237311a943491bb079a768Kristian Monsen            AppendToBuffer("dec_b ");
19490d5e116f6aee03185f237311a943491bb079a768Kristian Monsen            data += PrintRightOperand(data);
1950a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          } else {
1951a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            UnimplementedInstruction();
1952a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          }
1953a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        }
1954a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
1955a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1956a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 0x68:
1957a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        AppendToBuffer("push 0x%x", *reinterpret_cast<int32_t*>(data+1));
1958a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        data += 5;
1959a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
1960a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1961a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 0x6A:
1962a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        AppendToBuffer("push 0x%x", *reinterpret_cast<int8_t*>(data + 1));
1963a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        data += 2;
1964a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
1965a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1966a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 0xA8:
1967a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        AppendToBuffer("test al,0x%x", *reinterpret_cast<uint8_t*>(data+1));
1968a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        data += 2;
1969a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
1970a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1971a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 0xA9:
1972a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        AppendToBuffer("test eax,0x%x", *reinterpret_cast<int32_t*>(data+1));
1973a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        data += 5;
1974a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
1975a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1976a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 0xD1:  // fall through
1977a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 0xD3:  // fall through
1978a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 0xC1:
1979a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        data += D1D3C1Instruction(data);
1980a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
1981a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1982b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case 0xD8:  // fall through
1983a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 0xD9:  // fall through
1984a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 0xDA:  // fall through
1985a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 0xDB:  // fall through
1986a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 0xDC:  // fall through
1987a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 0xDD:  // fall through
1988a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 0xDE:  // fall through
1989a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 0xDF:
1990a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        data += FPUInstruction(data);
1991a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
1992a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1993a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 0xEB:
1994a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        data += JumpShort(data);
1995a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
1996a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1997a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 0xF2:
1998a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        if (*(data+1) == 0x0F) {
1999a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          byte b2 = *(data+2);
2000a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          if (b2 == 0x11) {
2001a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            AppendToBuffer("movsd ");
2002a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            data += 3;
2003a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            int mod, regop, rm;
2004a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            get_modrm(*data, &mod, &regop, &rm);
200544f0eee88ff00398ff7f715fab053374d808c90dSteve Block            data += PrintRightXMMOperand(data);
2006a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            AppendToBuffer(",%s", NameOfXMMRegister(regop));
2007a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          } else if (b2 == 0x10) {
2008a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            data += 3;
2009a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            int mod, regop, rm;
2010a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            get_modrm(*data, &mod, &regop, &rm);
2011a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            AppendToBuffer("movsd %s,", NameOfXMMRegister(regop));
201244f0eee88ff00398ff7f715fab053374d808c90dSteve Block            data += PrintRightXMMOperand(data);
201344f0eee88ff00398ff7f715fab053374d808c90dSteve Block          } else  if (b2 == 0x5A) {
201444f0eee88ff00398ff7f715fab053374d808c90dSteve Block            data += 3;
201544f0eee88ff00398ff7f715fab053374d808c90dSteve Block            int mod, regop, rm;
201644f0eee88ff00398ff7f715fab053374d808c90dSteve Block            get_modrm(*data, &mod, &regop, &rm);
201744f0eee88ff00398ff7f715fab053374d808c90dSteve Block            AppendToBuffer("cvtsd2ss %s,", NameOfXMMRegister(regop));
201844f0eee88ff00398ff7f715fab053374d808c90dSteve Block            data += PrintRightXMMOperand(data);
2019a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          } else {
2020a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            const char* mnem = "?";
2021a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            switch (b2) {
2022014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch              case 0x2A:
2023014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                mnem = "cvtsi2sd";
2024014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                break;
2025014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch              case 0x2C:
2026014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                mnem = "cvttsd2si";
2027014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                break;
2028014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch              case 0x2D:
2029014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                mnem = "cvtsd2si";
2030014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                break;
2031014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch              case 0x51:
2032014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                mnem = "sqrtsd";
2033014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                break;
2034014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch              case 0x58:
2035014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                mnem = "addsd";
2036014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                break;
2037014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch              case 0x59:
2038014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                mnem = "mulsd";
2039014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                break;
2040014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch              case 0x5C:
2041014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                mnem = "subsd";
2042014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                break;
2043014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch              case 0x5D:
2044014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                mnem = "minsd";
2045014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                break;
2046014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch              case 0x5E:
2047014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                mnem = "divsd";
2048014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                break;
2049014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch              case 0x5F:
2050014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                mnem = "maxsd";
2051014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                break;
2052a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            }
2053a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            data += 3;
2054a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            int mod, regop, rm;
2055a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            get_modrm(*data, &mod, &regop, &rm);
2056a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            if (b2 == 0x2A) {
205744f0eee88ff00398ff7f715fab053374d808c90dSteve Block              AppendToBuffer("%s %s,", mnem, NameOfXMMRegister(regop));
205844f0eee88ff00398ff7f715fab053374d808c90dSteve Block              data += PrintRightOperand(data);
2059b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            } else if (b2 == 0x2C || b2 == 0x2D) {
206044f0eee88ff00398ff7f715fab053374d808c90dSteve Block              AppendToBuffer("%s %s,", mnem, NameOfCPURegister(regop));
206144f0eee88ff00398ff7f715fab053374d808c90dSteve Block              data += PrintRightXMMOperand(data);
20620d5e116f6aee03185f237311a943491bb079a768Kristian Monsen            } else if (b2 == 0xC2) {
20630d5e116f6aee03185f237311a943491bb079a768Kristian Monsen              // Intel manual 2A, Table 3-18.
20640d5e116f6aee03185f237311a943491bb079a768Kristian Monsen              const char* const pseudo_op[] = {
20650d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                "cmpeqsd",
20660d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                "cmpltsd",
20670d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                "cmplesd",
20680d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                "cmpunordsd",
20690d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                "cmpneqsd",
20700d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                "cmpnltsd",
20710d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                "cmpnlesd",
20720d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                "cmpordsd"
20730d5e116f6aee03185f237311a943491bb079a768Kristian Monsen              };
20740d5e116f6aee03185f237311a943491bb079a768Kristian Monsen              AppendToBuffer("%s %s,%s",
20750d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                             pseudo_op[data[1]],
20760d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                             NameOfXMMRegister(regop),
20770d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                             NameOfXMMRegister(rm));
20780d5e116f6aee03185f237311a943491bb079a768Kristian Monsen              data += 2;
2079a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            } else {
208044f0eee88ff00398ff7f715fab053374d808c90dSteve Block              AppendToBuffer("%s %s,", mnem, NameOfXMMRegister(regop));
208144f0eee88ff00398ff7f715fab053374d808c90dSteve Block              data += PrintRightXMMOperand(data);
2082a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            }
2083a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          }
2084a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        } else {
2085a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          UnimplementedInstruction();
2086a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        }
2087a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
2088a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2089a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 0xF3:
2090e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        if (*(data+1) == 0x0F) {
209144f0eee88ff00398ff7f715fab053374d808c90dSteve Block          byte b2 = *(data+2);
209244f0eee88ff00398ff7f715fab053374d808c90dSteve Block          if (b2 == 0x11) {
209344f0eee88ff00398ff7f715fab053374d808c90dSteve Block            AppendToBuffer("movss ");
2094e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke            data += 3;
209544f0eee88ff00398ff7f715fab053374d808c90dSteve Block            int mod, regop, rm;
209644f0eee88ff00398ff7f715fab053374d808c90dSteve Block            get_modrm(*data, &mod, &regop, &rm);
209744f0eee88ff00398ff7f715fab053374d808c90dSteve Block            data += PrintRightXMMOperand(data);
209844f0eee88ff00398ff7f715fab053374d808c90dSteve Block            AppendToBuffer(",%s", NameOfXMMRegister(regop));
209944f0eee88ff00398ff7f715fab053374d808c90dSteve Block          } else if (b2 == 0x10) {
21006ded16be15dd865a9b21ea304d5273c8be299c87Steve Block            data += 3;
21016ded16be15dd865a9b21ea304d5273c8be299c87Steve Block            int mod, regop, rm;
21026ded16be15dd865a9b21ea304d5273c8be299c87Steve Block            get_modrm(*data, &mod, &regop, &rm);
210344f0eee88ff00398ff7f715fab053374d808c90dSteve Block            AppendToBuffer("movss %s,", NameOfXMMRegister(regop));
210444f0eee88ff00398ff7f715fab053374d808c90dSteve Block            data += PrintRightXMMOperand(data);
2105014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          } else if (b2 == 0x5A) {
2106958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier            data += 3;
2107958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier            int mod, regop, rm;
2108958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier            get_modrm(*data, &mod, &regop, &rm);
2109014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            AppendToBuffer("cvtss2sd %s,", NameOfXMMRegister(regop));
2110958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier            data += PrintRightXMMOperand(data);
2111014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          } else if (b2 == 0x6F) {
2112958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier            data += 3;
2113958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier            int mod, regop, rm;
2114958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier            get_modrm(*data, &mod, &regop, &rm);
2115014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            AppendToBuffer("movdqu %s,", NameOfXMMRegister(regop));
2116958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier            data += PrintRightXMMOperand(data);
2117014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          } else if (b2 == 0x7F) {
2118014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            AppendToBuffer("movdqu ");
211944f0eee88ff00398ff7f715fab053374d808c90dSteve Block            data += 3;
212044f0eee88ff00398ff7f715fab053374d808c90dSteve Block            int mod, regop, rm;
212144f0eee88ff00398ff7f715fab053374d808c90dSteve Block            get_modrm(*data, &mod, &regop, &rm);
212244f0eee88ff00398ff7f715fab053374d808c90dSteve Block            data += PrintRightXMMOperand(data);
2123014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            AppendToBuffer(",%s", NameOfXMMRegister(regop));
2124014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          } else if (b2 == 0xB8) {
2125958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier            data += 3;
2126958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier            int mod, regop, rm;
2127958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier            get_modrm(*data, &mod, &regop, &rm);
2128014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            AppendToBuffer("popcnt %s,", NameOfCPURegister(regop));
2129014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            data += PrintRightOperand(data);
2130014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          } else if (b2 == 0xBC) {
2131958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier            data += 3;
2132958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier            int mod, regop, rm;
2133958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier            get_modrm(*data, &mod, &regop, &rm);
2134014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            AppendToBuffer("tzcnt %s,", NameOfCPURegister(regop));
2135014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            data += PrintRightOperand(data);
2136014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          } else if (b2 == 0xBD) {
2137e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke            data += 3;
2138e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke            int mod, regop, rm;
2139e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke            get_modrm(*data, &mod, &regop, &rm);
2140014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            AppendToBuffer("lzcnt %s,", NameOfCPURegister(regop));
2141014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            data += PrintRightOperand(data);
2142014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          } else {
2143014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            const char* mnem = "?";
2144014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            switch (b2) {
2145014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch              case 0x2A:
2146014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                mnem = "cvtsi2ss";
2147014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                break;
2148014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch              case 0x2C:
2149014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                mnem = "cvttss2si";
2150014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                break;
2151014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch              case 0x2D:
2152014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                mnem = "cvtss2si";
2153014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                break;
2154014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch              case 0x51:
2155014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                mnem = "sqrtss";
2156014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                break;
2157014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch              case 0x58:
2158014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                mnem = "addss";
2159014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                break;
2160014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch              case 0x59:
2161014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                mnem = "mulss";
2162014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                break;
2163014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch              case 0x5C:
2164014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                mnem = "subss";
2165014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                break;
2166014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch              case 0x5D:
2167014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                mnem = "minss";
2168014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                break;
2169014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch              case 0x5E:
2170014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                mnem = "divss";
2171014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                break;
2172014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch              case 0x5F:
2173014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                mnem = "maxss";
2174014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                break;
2175014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            }
2176e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke            data += 3;
2177e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke            int mod, regop, rm;
2178e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke            get_modrm(*data, &mod, &regop, &rm);
2179014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            if (b2 == 0x2A) {
2180014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch              AppendToBuffer("%s %s,", mnem, NameOfXMMRegister(regop));
2181014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch              data += PrintRightOperand(data);
2182014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            } else if (b2 == 0x2C || b2 == 0x2D) {
2183014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch              AppendToBuffer("%s %s,", mnem, NameOfCPURegister(regop));
2184014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch              data += PrintRightXMMOperand(data);
2185014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            } else if (b2 == 0xC2) {
2186014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch              // Intel manual 2A, Table 3-18.
2187014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch              const char* const pseudo_op[] = {
2188014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                  "cmpeqss",  "cmpltss",  "cmpless",  "cmpunordss",
2189014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                  "cmpneqss", "cmpnltss", "cmpnless", "cmpordss"};
2190014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch              AppendToBuffer("%s %s,%s", pseudo_op[data[1]],
2191014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                             NameOfXMMRegister(regop), NameOfXMMRegister(rm));
2192014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch              data += 2;
2193014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            } else {
2194014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch              AppendToBuffer("%s %s,", mnem, NameOfXMMRegister(regop));
2195014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch              data += PrintRightXMMOperand(data);
2196014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            }
2197e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          }
2198e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        } else if (*(data+1) == 0xA5) {
2199e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          data += 2;
2200e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          AppendToBuffer("rep_movs");
22016ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        } else if (*(data+1) == 0xAB) {
22026ded16be15dd865a9b21ea304d5273c8be299c87Steve Block          data += 2;
22036ded16be15dd865a9b21ea304d5273c8be299c87Steve Block          AppendToBuffer("rep_stos");
2204a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        } else {
2205a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          UnimplementedInstruction();
2206a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        }
2207a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
2208a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2209a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 0xF7:
2210a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        data += F7Instruction(data);
2211a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
2212a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2213a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      default:
2214a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        UnimplementedInstruction();
2215a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
2216a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2217a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2218a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (tmp_buffer_pos_ < sizeof tmp_buffer_) {
2219a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    tmp_buffer_[tmp_buffer_pos_] = '\0';
2220a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2221a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2222a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int instr_len = data - instr;
2223e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  if (instr_len == 0) {
2224e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    printf("%02x", *data);
2225e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  }
2226b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(instr_len > 0);  // Ensure progress.
2227a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2228a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int outp = 0;
2229a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Instruction bytes.
2230a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (byte* bp = instr; bp < data; bp++) {
2231b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    outp += v8::internal::SNPrintF(out_buffer + outp,
2232b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                   "%02x",
2233b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                   *bp);
2234a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2235a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (int i = 6 - instr_len; i >= 0; i--) {
2236b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    outp += v8::internal::SNPrintF(out_buffer + outp, "  ");
2237a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2238a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2239b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  outp += v8::internal::SNPrintF(out_buffer + outp,
2240b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                 " %s",
2241b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                 tmp_buffer_.start());
2242a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return instr_len;
22430d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}  // NOLINT (function is too long)
2244a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2245a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2246a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//------------------------------------------------------------------------------
2247a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2248a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2249958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernierstatic const char* const cpu_regs[8] = {
2250a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  "eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi"
2251a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
2252a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2253a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2254958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernierstatic const char* const byte_cpu_regs[8] = {
2255a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  "al", "cl", "dl", "bl", "ah", "ch", "dh", "bh"
2256a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
2257a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2258a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2259958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernierstatic const char* const xmm_regs[8] = {
2260a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7"
2261a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
2262a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2263a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2264a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockconst char* NameConverter::NameOfAddress(byte* addr) const {
226513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  v8::internal::SNPrintF(tmp_buffer_, "%p", static_cast<void*>(addr));
226644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  return tmp_buffer_.start();
2267a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2268a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2269a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2270a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockconst char* NameConverter::NameOfConstant(byte* addr) const {
2271a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return NameOfAddress(addr);
2272a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2273a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2274a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2275a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockconst char* NameConverter::NameOfCPURegister(int reg) const {
2276a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (0 <= reg && reg < 8) return cpu_regs[reg];
2277a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return "noreg";
2278a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2279a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2280a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2281a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockconst char* NameConverter::NameOfByteCPURegister(int reg) const {
2282a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (0 <= reg && reg < 8) return byte_cpu_regs[reg];
2283a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return "noreg";
2284a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2285a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2286a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2287a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockconst char* NameConverter::NameOfXMMRegister(int reg) const {
2288a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (0 <= reg && reg < 8) return xmm_regs[reg];
2289a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return "noxmmreg";
2290a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2291a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2292a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2293a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockconst char* NameConverter::NameInCode(byte* addr) const {
2294a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // IA32 does not embed debug strings at the moment.
2295a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  UNREACHABLE();
2296a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return "";
2297a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2298a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2299a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2300a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//------------------------------------------------------------------------------
2301a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2302a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockDisassembler::Disassembler(const NameConverter& converter)
2303a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    : converter_(converter) {}
2304a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2305a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2306a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockDisassembler::~Disassembler() {}
2307a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2308a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2309a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint Disassembler::InstructionDecode(v8::internal::Vector<char> buffer,
2310a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                    byte* instruction) {
2311a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  DisassemblerIA32 d(converter_, false /*do not crash if unimplemented*/);
2312a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return d.InstructionDecode(buffer, instruction);
2313a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2314a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2315a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2316a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// The IA-32 assembler does not currently use constant pools.
2317a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint Disassembler::ConstantPoolSizeAt(byte* instruction) { return -1; }
2318a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2319a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2320a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block/*static*/ void Disassembler::Disassemble(FILE* f, byte* begin, byte* end) {
2321a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  NameConverter converter;
2322a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Disassembler d(converter);
2323a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (byte* pc = begin; pc < end;) {
2324a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    v8::internal::EmbeddedVector<char, 128> buffer;
2325a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    buffer[0] = '\0';
2326a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    byte* prev_pc = pc;
2327a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    pc += d.InstructionDecode(buffer, pc);
232813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    fprintf(f, "%p", static_cast<void*>(prev_pc));
2329a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    fprintf(f, "    ");
2330a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2331a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    for (byte* bp = prev_pc; bp < pc; bp++) {
2332a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      fprintf(f, "%02x",  *bp);
2333a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
2334a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    for (int i = 6 - (pc - prev_pc); i >= 0; i--) {
2335a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      fprintf(f, "  ");
2336a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
2337a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    fprintf(f, "  %s\n", buffer.start());
2338a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2339a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2340a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2341a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2342a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}  // namespace disasm
2343f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
2344f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke#endif  // V8_TARGET_ARCH_IA32
2345