disasm-ia32.cc revision f91f0611dbaf29ca0f1d4aecb357ce243a19d2fa
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, ®op, &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, ®op, &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, ®op, &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, ®op, &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, ®op, &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, ®op, &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, ®op, &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, ®op, &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, ®op, &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, ®op, &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, ®op, &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, ®op, &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, ®op, &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, ®op, &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, ®op, &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, ®op, &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, ®op, &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, ®op, &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, ®op, &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, ®op, &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, ®op, &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, ®op, &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, ®op, &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, ®op, &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, ®op, &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, ®op, &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, ®op, &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, ®op, &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, ®op, &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, ®op, &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, ®op, &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, ®op, &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, ®op, &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, ®op, &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, ®op, &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, ®op, &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, ®op); 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, ®op, &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, ®op, &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, ®op, &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, ®op, &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, ®op, &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, ®op, &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, ®op, &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, ®op, &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, ®op, &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, ®op, &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, ®op, &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, ®op, &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, ®op, &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, ®op, &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, ®op, &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, ®op, &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, ®op, &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, ®op, &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, ®op, &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, ®op, &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, ®op, &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, ®op, &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, ®op, &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, ®op, &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, ®op, &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, ®op, &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, ®op, &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, ®op, &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, ®op, &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, ®op, &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, ®op, &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, ®op, &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, ®op, &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, ®op, &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, ®op, &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, ®op, &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, ®op, &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