| OLD | NEW |
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 #include "vm/disassembler.h" | 5 #include "vm/disassembler.h" |
| 6 | 6 |
| 7 #include "vm/globals.h" // Needed here to get TARGET_ARCH_IA32. | 7 #include "vm/globals.h" // Needed here to get TARGET_ARCH_IA32. |
| 8 #if defined(TARGET_ARCH_X64) | 8 #if defined(TARGET_ARCH_X64) |
| 9 #include "platform/utils.h" | 9 #include "platform/utils.h" |
| 10 #include "vm/allocation.h" | 10 #include "vm/allocation.h" |
| (...skipping 22 matching lines...) Expand all Loading... |
| 33 // Tables | 33 // Tables |
| 34 //------------------------------------------------------------------ | 34 //------------------------------------------------------------------ |
| 35 struct ByteMnemonic { | 35 struct ByteMnemonic { |
| 36 int b; // -1 terminates, otherwise must be in range (0..255) | 36 int b; // -1 terminates, otherwise must be in range (0..255) |
| 37 OperandType op_order_; | 37 OperandType op_order_; |
| 38 const char* mnem; | 38 const char* mnem; |
| 39 }; | 39 }; |
| 40 | 40 |
| 41 | 41 |
| 42 static const ByteMnemonic two_operands_instr[] = { | 42 static const ByteMnemonic two_operands_instr[] = { |
| 43 { 0x00, BYTE_OPER_REG_OP_ORDER, "add" }, | 43 {0x00, BYTE_OPER_REG_OP_ORDER, "add"}, |
| 44 { 0x01, OPER_REG_OP_ORDER, "add" }, | 44 {0x01, OPER_REG_OP_ORDER, "add"}, |
| 45 { 0x02, BYTE_REG_OPER_OP_ORDER, "add" }, | 45 {0x02, BYTE_REG_OPER_OP_ORDER, "add"}, |
| 46 { 0x03, REG_OPER_OP_ORDER, "add" }, | 46 {0x03, REG_OPER_OP_ORDER, "add"}, |
| 47 { 0x08, BYTE_OPER_REG_OP_ORDER, "or" }, | 47 {0x08, BYTE_OPER_REG_OP_ORDER, "or"}, |
| 48 { 0x09, OPER_REG_OP_ORDER, "or" }, | 48 {0x09, OPER_REG_OP_ORDER, "or"}, |
| 49 { 0x0A, BYTE_REG_OPER_OP_ORDER, "or" }, | 49 {0x0A, BYTE_REG_OPER_OP_ORDER, "or"}, |
| 50 { 0x0B, REG_OPER_OP_ORDER, "or" }, | 50 {0x0B, REG_OPER_OP_ORDER, "or"}, |
| 51 { 0x10, BYTE_OPER_REG_OP_ORDER, "adc" }, | 51 {0x10, BYTE_OPER_REG_OP_ORDER, "adc"}, |
| 52 { 0x11, OPER_REG_OP_ORDER, "adc" }, | 52 {0x11, OPER_REG_OP_ORDER, "adc"}, |
| 53 { 0x12, BYTE_REG_OPER_OP_ORDER, "adc" }, | 53 {0x12, BYTE_REG_OPER_OP_ORDER, "adc"}, |
| 54 { 0x13, REG_OPER_OP_ORDER, "adc" }, | 54 {0x13, REG_OPER_OP_ORDER, "adc"}, |
| 55 { 0x18, BYTE_OPER_REG_OP_ORDER, "sbb" }, | 55 {0x18, BYTE_OPER_REG_OP_ORDER, "sbb"}, |
| 56 { 0x19, OPER_REG_OP_ORDER, "sbb" }, | 56 {0x19, OPER_REG_OP_ORDER, "sbb"}, |
| 57 { 0x1A, BYTE_REG_OPER_OP_ORDER, "sbb" }, | 57 {0x1A, BYTE_REG_OPER_OP_ORDER, "sbb"}, |
| 58 { 0x1B, REG_OPER_OP_ORDER, "sbb" }, | 58 {0x1B, REG_OPER_OP_ORDER, "sbb"}, |
| 59 { 0x20, BYTE_OPER_REG_OP_ORDER, "and" }, | 59 {0x20, BYTE_OPER_REG_OP_ORDER, "and"}, |
| 60 { 0x21, OPER_REG_OP_ORDER, "and" }, | 60 {0x21, OPER_REG_OP_ORDER, "and"}, |
| 61 { 0x22, BYTE_REG_OPER_OP_ORDER, "and" }, | 61 {0x22, BYTE_REG_OPER_OP_ORDER, "and"}, |
| 62 { 0x23, REG_OPER_OP_ORDER, "and" }, | 62 {0x23, REG_OPER_OP_ORDER, "and"}, |
| 63 { 0x28, BYTE_OPER_REG_OP_ORDER, "sub" }, | 63 {0x28, BYTE_OPER_REG_OP_ORDER, "sub"}, |
| 64 { 0x29, OPER_REG_OP_ORDER, "sub" }, | 64 {0x29, OPER_REG_OP_ORDER, "sub"}, |
| 65 { 0x2A, BYTE_REG_OPER_OP_ORDER, "sub" }, | 65 {0x2A, BYTE_REG_OPER_OP_ORDER, "sub"}, |
| 66 { 0x2B, REG_OPER_OP_ORDER, "sub" }, | 66 {0x2B, REG_OPER_OP_ORDER, "sub"}, |
| 67 { 0x30, BYTE_OPER_REG_OP_ORDER, "xor" }, | 67 {0x30, BYTE_OPER_REG_OP_ORDER, "xor"}, |
| 68 { 0x31, OPER_REG_OP_ORDER, "xor" }, | 68 {0x31, OPER_REG_OP_ORDER, "xor"}, |
| 69 { 0x32, BYTE_REG_OPER_OP_ORDER, "xor" }, | 69 {0x32, BYTE_REG_OPER_OP_ORDER, "xor"}, |
| 70 { 0x33, REG_OPER_OP_ORDER, "xor" }, | 70 {0x33, REG_OPER_OP_ORDER, "xor"}, |
| 71 { 0x38, BYTE_OPER_REG_OP_ORDER, "cmp" }, | 71 {0x38, BYTE_OPER_REG_OP_ORDER, "cmp"}, |
| 72 { 0x39, OPER_REG_OP_ORDER, "cmp" }, | 72 {0x39, OPER_REG_OP_ORDER, "cmp"}, |
| 73 { 0x3A, BYTE_REG_OPER_OP_ORDER, "cmp" }, | 73 {0x3A, BYTE_REG_OPER_OP_ORDER, "cmp"}, |
| 74 { 0x3B, REG_OPER_OP_ORDER, "cmp" }, | 74 {0x3B, REG_OPER_OP_ORDER, "cmp"}, |
| 75 { 0x63, REG_OPER_OP_ORDER, "movsxd" }, | 75 {0x63, REG_OPER_OP_ORDER, "movsxd"}, |
| 76 { 0x84, BYTE_REG_OPER_OP_ORDER, "test" }, | 76 {0x84, BYTE_REG_OPER_OP_ORDER, "test"}, |
| 77 { 0x85, REG_OPER_OP_ORDER, "test" }, | 77 {0x85, REG_OPER_OP_ORDER, "test"}, |
| 78 { 0x86, BYTE_REG_OPER_OP_ORDER, "xchg" }, | 78 {0x86, BYTE_REG_OPER_OP_ORDER, "xchg"}, |
| 79 { 0x87, REG_OPER_OP_ORDER, "xchg" }, | 79 {0x87, REG_OPER_OP_ORDER, "xchg"}, |
| 80 { 0x88, BYTE_OPER_REG_OP_ORDER, "mov" }, | 80 {0x88, BYTE_OPER_REG_OP_ORDER, "mov"}, |
| 81 { 0x89, OPER_REG_OP_ORDER, "mov" }, | 81 {0x89, OPER_REG_OP_ORDER, "mov"}, |
| 82 { 0x8A, BYTE_REG_OPER_OP_ORDER, "mov" }, | 82 {0x8A, BYTE_REG_OPER_OP_ORDER, "mov"}, |
| 83 { 0x8B, REG_OPER_OP_ORDER, "mov" }, | 83 {0x8B, REG_OPER_OP_ORDER, "mov"}, |
| 84 { 0x8D, REG_OPER_OP_ORDER, "lea" }, | 84 {0x8D, REG_OPER_OP_ORDER, "lea"}, |
| 85 { -1, UNSET_OP_ORDER, "" } | 85 {-1, UNSET_OP_ORDER, ""}}; |
| 86 }; | |
| 87 | 86 |
| 88 | 87 |
| 89 static const ByteMnemonic zero_operands_instr[] = { | 88 static const ByteMnemonic zero_operands_instr[] = { |
| 90 { 0xC3, UNSET_OP_ORDER, "ret" }, | 89 {0xC3, UNSET_OP_ORDER, "ret"}, {0xC9, UNSET_OP_ORDER, "leave"}, |
| 91 { 0xC9, UNSET_OP_ORDER, "leave" }, | 90 {0xF4, UNSET_OP_ORDER, "hlt"}, {0xFC, UNSET_OP_ORDER, "cld"}, |
| 92 { 0xF4, UNSET_OP_ORDER, "hlt" }, | 91 {0xCC, UNSET_OP_ORDER, "int3"}, {0x60, UNSET_OP_ORDER, "pushad"}, |
| 93 { 0xFC, UNSET_OP_ORDER, "cld" }, | 92 {0x61, UNSET_OP_ORDER, "popad"}, {0x9C, UNSET_OP_ORDER, "pushfd"}, |
| 94 { 0xCC, UNSET_OP_ORDER, "int3" }, | 93 {0x9D, UNSET_OP_ORDER, "popfd"}, {0x9E, UNSET_OP_ORDER, "sahf"}, |
| 95 { 0x60, UNSET_OP_ORDER, "pushad" }, | 94 {0x99, UNSET_OP_ORDER, "cdq"}, {0x9B, UNSET_OP_ORDER, "fwait"}, |
| 96 { 0x61, UNSET_OP_ORDER, "popad" }, | 95 {0xA4, UNSET_OP_ORDER, "movs"}, {0xA5, UNSET_OP_ORDER, "movs"}, |
| 97 { 0x9C, UNSET_OP_ORDER, "pushfd" }, | 96 {0xA6, UNSET_OP_ORDER, "cmps"}, {0xA7, UNSET_OP_ORDER, "cmps"}, |
| 98 { 0x9D, UNSET_OP_ORDER, "popfd" }, | 97 {-1, UNSET_OP_ORDER, ""}}; |
| 99 { 0x9E, UNSET_OP_ORDER, "sahf" }, | |
| 100 { 0x99, UNSET_OP_ORDER, "cdq" }, | |
| 101 { 0x9B, UNSET_OP_ORDER, "fwait" }, | |
| 102 { 0xA4, UNSET_OP_ORDER, "movs" }, | |
| 103 { 0xA5, UNSET_OP_ORDER, "movs" }, | |
| 104 { 0xA6, UNSET_OP_ORDER, "cmps" }, | |
| 105 { 0xA7, UNSET_OP_ORDER, "cmps" }, | |
| 106 { -1, UNSET_OP_ORDER, "" } | |
| 107 }; | |
| 108 | 98 |
| 109 | 99 |
| 110 static const ByteMnemonic call_jump_instr[] = { | 100 static const ByteMnemonic call_jump_instr[] = {{0xE8, UNSET_OP_ORDER, "call"}, |
| 111 { 0xE8, UNSET_OP_ORDER, "call" }, | 101 {0xE9, UNSET_OP_ORDER, "jmp"}, |
| 112 { 0xE9, UNSET_OP_ORDER, "jmp" }, | 102 {-1, UNSET_OP_ORDER, ""}}; |
| 113 { -1, UNSET_OP_ORDER, "" } | |
| 114 }; | |
| 115 | 103 |
| 116 | 104 |
| 117 static const ByteMnemonic short_immediate_instr[] = { | 105 static const ByteMnemonic short_immediate_instr[] = { |
| 118 { 0x05, UNSET_OP_ORDER, "add" }, | 106 {0x05, UNSET_OP_ORDER, "add"}, {0x0D, UNSET_OP_ORDER, "or"}, |
| 119 { 0x0D, UNSET_OP_ORDER, "or" }, | 107 {0x15, UNSET_OP_ORDER, "adc"}, {0x1D, UNSET_OP_ORDER, "sbb"}, |
| 120 { 0x15, UNSET_OP_ORDER, "adc" }, | 108 {0x25, UNSET_OP_ORDER, "and"}, {0x2D, UNSET_OP_ORDER, "sub"}, |
| 121 { 0x1D, UNSET_OP_ORDER, "sbb" }, | 109 {0x35, UNSET_OP_ORDER, "xor"}, {0x3D, UNSET_OP_ORDER, "cmp"}, |
| 122 { 0x25, UNSET_OP_ORDER, "and" }, | 110 {-1, UNSET_OP_ORDER, ""}}; |
| 123 { 0x2D, UNSET_OP_ORDER, "sub" }, | |
| 124 { 0x35, UNSET_OP_ORDER, "xor" }, | |
| 125 { 0x3D, UNSET_OP_ORDER, "cmp" }, | |
| 126 { -1, UNSET_OP_ORDER, "" } | |
| 127 }; | |
| 128 | 111 |
| 129 | 112 |
| 130 static const char* const conditional_code_suffix[] = { | 113 static const char* const conditional_code_suffix[] = { |
| 131 "o", "no", "c", "nc", "z", "nz", "na", "a", | 114 "o", "no", "c", "nc", "z", "nz", "na", "a", |
| 132 "s", "ns", "pe", "po", "l", "ge", "le", "g" | 115 "s", "ns", "pe", "po", "l", "ge", "le", "g"}; |
| 133 }; | |
| 134 | 116 |
| 135 | 117 |
| 136 enum InstructionType { | 118 enum InstructionType { |
| 137 NO_INSTR, | 119 NO_INSTR, |
| 138 ZERO_OPERANDS_INSTR, | 120 ZERO_OPERANDS_INSTR, |
| 139 TWO_OPERANDS_INSTR, | 121 TWO_OPERANDS_INSTR, |
| 140 JUMP_CONDITIONAL_SHORT_INSTR, | 122 JUMP_CONDITIONAL_SHORT_INSTR, |
| 141 REGISTER_INSTR, | 123 REGISTER_INSTR, |
| 142 PUSHPOP_INSTR, // Has implicit 64-bit operand size. | 124 PUSHPOP_INSTR, // Has implicit 64-bit operand size. |
| 143 MOVE_REG_INSTR, | 125 MOVE_REG_INSTR, |
| (...skipping 16 matching lines...) Expand all Loading... |
| 160 const char* mnem; | 142 const char* mnem; |
| 161 InstructionType type; | 143 InstructionType type; |
| 162 OperandType op_order_; | 144 OperandType op_order_; |
| 163 bool byte_size_operation; // Fixed 8-bit operation. | 145 bool byte_size_operation; // Fixed 8-bit operation. |
| 164 }; | 146 }; |
| 165 | 147 |
| 166 | 148 |
| 167 class InstructionTable : public ValueObject { | 149 class InstructionTable : public ValueObject { |
| 168 public: | 150 public: |
| 169 InstructionTable(); | 151 InstructionTable(); |
| 170 const InstructionDesc& Get(uint8_t x) const { | 152 const InstructionDesc& Get(uint8_t x) const { return instructions_[x]; } |
| 171 return instructions_[x]; | |
| 172 } | |
| 173 | 153 |
| 174 private: | 154 private: |
| 175 InstructionDesc instructions_[256]; | 155 InstructionDesc instructions_[256]; |
| 176 void Clear(); | 156 void Clear(); |
| 177 void Init(); | 157 void Init(); |
| 178 void CopyTable(const ByteMnemonic bm[], InstructionType type); | 158 void CopyTable(const ByteMnemonic bm[], InstructionType type); |
| 179 void SetTableRange(InstructionType type, | 159 void SetTableRange(InstructionType type, |
| 180 uint8_t start, | 160 uint8_t start, |
| 181 uint8_t end, | 161 uint8_t end, |
| 182 bool byte_size, | 162 bool byte_size, |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 242 id->type = type; | 222 id->type = type; |
| 243 id->byte_size_operation = byte_size; | 223 id->byte_size_operation = byte_size; |
| 244 } | 224 } |
| 245 } | 225 } |
| 246 | 226 |
| 247 | 227 |
| 248 void InstructionTable::AddJumpConditionalShort() { | 228 void InstructionTable::AddJumpConditionalShort() { |
| 249 for (uint8_t b = 0x70; b <= 0x7F; b++) { | 229 for (uint8_t b = 0x70; b <= 0x7F; b++) { |
| 250 InstructionDesc* id = &instructions_[b]; | 230 InstructionDesc* id = &instructions_[b]; |
| 251 ASSERT(NO_INSTR == id->type); // Information not already entered | 231 ASSERT(NO_INSTR == id->type); // Information not already entered |
| 252 id->mnem = NULL; // Computed depending on condition code. | 232 id->mnem = NULL; // Computed depending on condition code. |
| 253 id->type = JUMP_CONDITIONAL_SHORT_INSTR; | 233 id->type = JUMP_CONDITIONAL_SHORT_INSTR; |
| 254 } | 234 } |
| 255 } | 235 } |
| 256 | 236 |
| 257 | 237 |
| 258 static InstructionTable instruction_table; | 238 static InstructionTable instruction_table; |
| 259 | 239 |
| 260 | 240 |
| 261 static InstructionDesc cmov_instructions[16] = { | 241 static InstructionDesc cmov_instructions[16] = { |
| 262 {"cmovo", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false}, | 242 {"cmovo", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false}, |
| 263 {"cmovno", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false}, | 243 {"cmovno", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false}, |
| 264 {"cmovc", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false}, | 244 {"cmovc", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false}, |
| 265 {"cmovnc", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false}, | 245 {"cmovnc", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false}, |
| 266 {"cmovz", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false}, | 246 {"cmovz", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false}, |
| 267 {"cmovnz", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false}, | 247 {"cmovnz", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false}, |
| 268 {"cmovna", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false}, | 248 {"cmovna", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false}, |
| 269 {"cmova", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false}, | 249 {"cmova", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false}, |
| 270 {"cmovs", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false}, | 250 {"cmovs", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false}, |
| 271 {"cmovns", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false}, | 251 {"cmovns", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false}, |
| 272 {"cmovpe", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false}, | 252 {"cmovpe", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false}, |
| 273 {"cmovpo", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false}, | 253 {"cmovpo", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false}, |
| 274 {"cmovl", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false}, | 254 {"cmovl", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false}, |
| 275 {"cmovge", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false}, | 255 {"cmovge", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false}, |
| 276 {"cmovle", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false}, | 256 {"cmovle", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false}, |
| 277 {"cmovg", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false} | 257 {"cmovg", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false}}; |
| 278 }; | |
| 279 | 258 |
| 280 | 259 |
| 281 //------------------------------------------------- | 260 //------------------------------------------------- |
| 282 // DisassemblerX64 implementation. | 261 // DisassemblerX64 implementation. |
| 283 | 262 |
| 284 | 263 |
| 285 static const int kMaxXmmRegisters = 16; | 264 static const int kMaxXmmRegisters = 16; |
| 286 static const char* xmm_regs[kMaxXmmRegisters] = { | 265 static const char* xmm_regs[kMaxXmmRegisters] = { |
| 287 "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", | 266 "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", |
| 288 "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15" | 267 "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15"}; |
| 289 }; | |
| 290 | 268 |
| 291 class DisassemblerX64 : public ValueObject { | 269 class DisassemblerX64 : public ValueObject { |
| 292 public: | 270 public: |
| 293 DisassemblerX64(char* buffer, intptr_t buffer_size) | 271 DisassemblerX64(char* buffer, intptr_t buffer_size) |
| 294 : buffer_(buffer), | 272 : buffer_(buffer), |
| 295 buffer_size_(buffer_size), | 273 buffer_size_(buffer_size), |
| 296 buffer_pos_(0), | 274 buffer_pos_(0), |
| 297 rex_(0), | 275 rex_(0), |
| 298 operand_size_(0), | 276 operand_size_(0), |
| 299 group_1_prefix_(0), | 277 group_1_prefix_(0), |
| 300 byte_size_operand_(false) { | 278 byte_size_operand_(false) { |
| 301 buffer_[buffer_pos_] = '\0'; | 279 buffer_[buffer_pos_] = '\0'; |
| 302 } | 280 } |
| 303 | 281 |
| 304 virtual ~DisassemblerX64() { | 282 virtual ~DisassemblerX64() {} |
| 305 } | |
| 306 | 283 |
| 307 int InstructionDecode(uword pc); | 284 int InstructionDecode(uword pc); |
| 308 | 285 |
| 309 private: | 286 private: |
| 310 enum OperandSize { | 287 enum OperandSize { |
| 311 BYTE_SIZE = 0, | 288 BYTE_SIZE = 0, |
| 312 WORD_SIZE = 1, | 289 WORD_SIZE = 1, |
| 313 DOUBLEWORD_SIZE = 2, | 290 DOUBLEWORD_SIZE = 2, |
| 314 QUADWORD_SIZE = 3 | 291 QUADWORD_SIZE = 3 |
| 315 }; | 292 }; |
| (...skipping 16 matching lines...) Expand all Loading... |
| 332 | 309 |
| 333 bool rex_w() { return (rex_ & 0x08) != 0; } | 310 bool rex_w() { return (rex_ & 0x08) != 0; } |
| 334 | 311 |
| 335 OperandSize operand_size() { | 312 OperandSize operand_size() { |
| 336 if (byte_size_operand_) return BYTE_SIZE; | 313 if (byte_size_operand_) return BYTE_SIZE; |
| 337 if (rex_w()) return QUADWORD_SIZE; | 314 if (rex_w()) return QUADWORD_SIZE; |
| 338 if (operand_size_ != 0) return WORD_SIZE; | 315 if (operand_size_ != 0) return WORD_SIZE; |
| 339 return DOUBLEWORD_SIZE; | 316 return DOUBLEWORD_SIZE; |
| 340 } | 317 } |
| 341 | 318 |
| 342 char operand_size_code() { | 319 char operand_size_code() { return "bwlq"[operand_size()]; } |
| 343 return "bwlq"[operand_size()]; | |
| 344 } | |
| 345 | 320 |
| 346 // Disassembler helper functions. | 321 // Disassembler helper functions. |
| 347 void get_modrm(uint8_t data, | 322 void get_modrm(uint8_t data, int* mod, int* regop, int* rm) { |
| 348 int* mod, | |
| 349 int* regop, | |
| 350 int* rm) { | |
| 351 *mod = (data >> 6) & 3; | 323 *mod = (data >> 6) & 3; |
| 352 *regop = ((data & 0x38) >> 3) | (rex_r() ? 8 : 0); | 324 *regop = ((data & 0x38) >> 3) | (rex_r() ? 8 : 0); |
| 353 *rm = (data & 7) | (rex_b() ? 8 : 0); | 325 *rm = (data & 7) | (rex_b() ? 8 : 0); |
| 354 } | 326 } |
| 355 | 327 |
| 356 void get_sib(uint8_t data, | 328 void get_sib(uint8_t data, int* scale, int* index, int* base) { |
| 357 int* scale, | |
| 358 int* index, | |
| 359 int* base) { | |
| 360 *scale = (data >> 6) & 3; | 329 *scale = (data >> 6) & 3; |
| 361 *index = ((data >> 3) & 7) | (rex_x() ? 8 : 0); | 330 *index = ((data >> 3) & 7) | (rex_x() ? 8 : 0); |
| 362 *base = (data & 7) | (rex_b() ? 8 : 0); | 331 *base = (data & 7) | (rex_b() ? 8 : 0); |
| 363 } | 332 } |
| 364 | 333 |
| 365 const char* NameOfCPURegister(int reg) const { | 334 const char* NameOfCPURegister(int reg) const { |
| 366 return Assembler::RegisterName(static_cast<Register>(reg)); | 335 return Assembler::RegisterName(static_cast<Register>(reg)); |
| 367 } | 336 } |
| 368 | 337 |
| 369 const char* NameOfByteCPURegister(int reg) const { | 338 const char* NameOfByteCPURegister(int reg) const { |
| 370 return NameOfCPURegister(reg); | 339 return NameOfCPURegister(reg); |
| 371 } | 340 } |
| 372 | 341 |
| 373 const char* NameOfXMMRegister(int reg) const { | 342 const char* NameOfXMMRegister(int reg) const { |
| 374 ASSERT((0 <= reg) && (reg < kMaxXmmRegisters)); | 343 ASSERT((0 <= reg) && (reg < kMaxXmmRegisters)); |
| 375 return xmm_regs[reg]; | 344 return xmm_regs[reg]; |
| 376 } | 345 } |
| 377 | 346 |
| 378 void Print(const char* format, ...) PRINTF_ATTRIBUTE(2, 3); | 347 void Print(const char* format, ...) PRINTF_ATTRIBUTE(2, 3); |
| 379 void PrintAddress(uint8_t* addr); | 348 void PrintAddress(uint8_t* addr); |
| 380 | 349 |
| 381 int PrintOperands(const char* mnem, | 350 int PrintOperands(const char* mnem, OperandType op_order, uint8_t* data); |
| 382 OperandType op_order, | |
| 383 uint8_t* data); | |
| 384 | 351 |
| 385 typedef const char* (DisassemblerX64::*RegisterNameMapping)(int reg) const; | 352 typedef const char* (DisassemblerX64::*RegisterNameMapping)(int reg) const; |
| 386 | 353 |
| 387 int PrintRightOperandHelper(uint8_t* modrmp, | 354 int PrintRightOperandHelper(uint8_t* modrmp, |
| 388 RegisterNameMapping register_name); | 355 RegisterNameMapping register_name); |
| 389 int PrintRightOperand(uint8_t* modrmp); | 356 int PrintRightOperand(uint8_t* modrmp); |
| 390 int PrintRightByteOperand(uint8_t* modrmp); | 357 int PrintRightByteOperand(uint8_t* modrmp); |
| 391 int PrintRightXMMOperand(uint8_t* modrmp); | 358 int PrintRightXMMOperand(uint8_t* modrmp); |
| 392 void PrintDisp(int disp, const char* after); | 359 void PrintDisp(int disp, const char* after); |
| 393 int PrintImmediate(uint8_t* data, OperandSize size); | 360 int PrintImmediate(uint8_t* data, OperandSize size); |
| 394 void PrintImmediateValue(int64_t value); | 361 void PrintImmediateValue(int64_t value); |
| 395 int PrintImmediateOp(uint8_t* data); | 362 int PrintImmediateOp(uint8_t* data); |
| 396 const char* TwoByteMnemonic(uint8_t opcode); | 363 const char* TwoByteMnemonic(uint8_t opcode); |
| 397 int TwoByteOpcodeInstruction(uint8_t* data); | 364 int TwoByteOpcodeInstruction(uint8_t* data); |
| 398 | 365 |
| 399 int F6F7Instruction(uint8_t* data); | 366 int F6F7Instruction(uint8_t* data); |
| 400 int ShiftInstruction(uint8_t* data); | 367 int ShiftInstruction(uint8_t* data); |
| 401 int JumpShort(uint8_t* data); | 368 int JumpShort(uint8_t* data); |
| 402 int JumpConditional(uint8_t* data); | 369 int JumpConditional(uint8_t* data); |
| 403 int JumpConditionalShort(uint8_t* data); | 370 int JumpConditionalShort(uint8_t* data); |
| 404 int SetCC(uint8_t* data); | 371 int SetCC(uint8_t* data); |
| 405 int FPUInstruction(uint8_t* data); | 372 int FPUInstruction(uint8_t* data); |
| 406 int MemoryFPUInstruction(int escape_opcode, int regop, uint8_t* modrm_start); | 373 int MemoryFPUInstruction(int escape_opcode, int regop, uint8_t* modrm_start); |
| 407 int RegisterFPUInstruction(int escape_opcode, uint8_t modrm_byte); | 374 int RegisterFPUInstruction(int escape_opcode, uint8_t modrm_byte); |
| 408 | 375 |
| 409 bool DecodeInstructionType(uint8_t** data); | 376 bool DecodeInstructionType(uint8_t** data); |
| 410 | 377 |
| 411 void UnimplementedInstruction() { | 378 void UnimplementedInstruction() { Print("'Unimplemented Instruction'"); } |
| 412 Print("'Unimplemented Instruction'"); | |
| 413 } | |
| 414 | 379 |
| 415 char* buffer_; // Decode instructions into this buffer. | 380 char* buffer_; // Decode instructions into this buffer. |
| 416 intptr_t buffer_size_; // The size of the buffer_. | 381 intptr_t buffer_size_; // The size of the buffer_. |
| 417 intptr_t buffer_pos_; // Current character position in the buffer_. | 382 intptr_t buffer_pos_; // Current character position in the buffer_. |
| 418 | 383 |
| 419 // Prefixes parsed | 384 // Prefixes parsed |
| 420 uint8_t rex_; | 385 uint8_t rex_; |
| 421 uint8_t operand_size_; // 0x66 or (if no group 3 prefix is present) 0x0. | 386 uint8_t operand_size_; // 0x66 or (if no group 3 prefix is present) 0x0. |
| 422 // 0xF2, 0xF3, or (if no group 1 prefix is present) 0. | 387 // 0xF2, 0xF3, or (if no group 1 prefix is present) 0. |
| 423 uint8_t group_1_prefix_; | 388 uint8_t group_1_prefix_; |
| 424 // Byte size operand override. | 389 // Byte size operand override. |
| 425 bool byte_size_operand_; | 390 bool byte_size_operand_; |
| 426 | 391 |
| 427 DISALLOW_COPY_AND_ASSIGN(DisassemblerX64); | 392 DISALLOW_COPY_AND_ASSIGN(DisassemblerX64); |
| (...skipping 16 matching lines...) Expand all Loading... |
| 444 (length >= available) ? (buffer_size_ - 1) : (buffer_pos_ + length); | 409 (length >= available) ? (buffer_size_ - 1) : (buffer_pos_ + length); |
| 445 ASSERT(buffer_pos_ < buffer_size_); | 410 ASSERT(buffer_pos_ < buffer_size_); |
| 446 } | 411 } |
| 447 | 412 |
| 448 | 413 |
| 449 int DisassemblerX64::PrintRightOperandHelper( | 414 int DisassemblerX64::PrintRightOperandHelper( |
| 450 uint8_t* modrmp, | 415 uint8_t* modrmp, |
| 451 RegisterNameMapping direct_register_name) { | 416 RegisterNameMapping direct_register_name) { |
| 452 int mod, regop, rm; | 417 int mod, regop, rm; |
| 453 get_modrm(*modrmp, &mod, ®op, &rm); | 418 get_modrm(*modrmp, &mod, ®op, &rm); |
| 454 RegisterNameMapping register_name = (mod == 3) ? direct_register_name : | 419 RegisterNameMapping register_name = |
| 455 &DisassemblerX64::NameOfCPURegister; | 420 (mod == 3) ? direct_register_name : &DisassemblerX64::NameOfCPURegister; |
| 456 switch (mod) { | 421 switch (mod) { |
| 457 case 0: | 422 case 0: |
| 458 if ((rm & 7) == 5) { | 423 if ((rm & 7) == 5) { |
| 459 int32_t disp = *reinterpret_cast<int32_t*>(modrmp + 1); | 424 int32_t disp = *reinterpret_cast<int32_t*>(modrmp + 1); |
| 460 Print("[rip"); | 425 Print("[rip"); |
| 461 PrintDisp(disp, "]"); | 426 PrintDisp(disp, "]"); |
| 462 return 5; | 427 return 5; |
| 463 } else if ((rm & 7) == 4) { | 428 } else if ((rm & 7) == 4) { |
| 464 // Codes for SIB byte. | 429 // Codes for SIB byte. |
| 465 uint8_t sib = *(modrmp + 1); | 430 uint8_t sib = *(modrmp + 1); |
| 466 int scale, index, base; | 431 int scale, index, base; |
| 467 get_sib(sib, &scale, &index, &base); | 432 get_sib(sib, &scale, &index, &base); |
| 468 if (index == 4 && (base & 7) == 4 && scale == 0 /*times_1*/) { | 433 if (index == 4 && (base & 7) == 4 && scale == 0 /*times_1*/) { |
| 469 // index == rsp means no index. Only use sib byte with no index for | 434 // index == rsp means no index. Only use sib byte with no index for |
| 470 // rsp and r12 base. | 435 // rsp and r12 base. |
| 471 Print("[%s]", NameOfCPURegister(base)); | 436 Print("[%s]", NameOfCPURegister(base)); |
| 472 return 2; | 437 return 2; |
| 473 } else if (base == 5) { | 438 } else if (base == 5) { |
| 474 // base == rbp means no base register (when mod == 0). | 439 // base == rbp means no base register (when mod == 0). |
| 475 int32_t disp = *reinterpret_cast<int32_t*>(modrmp + 2); | 440 int32_t disp = *reinterpret_cast<int32_t*>(modrmp + 2); |
| 476 Print("[%s*%d", NameOfCPURegister(index), 1 << scale); | 441 Print("[%s*%d", NameOfCPURegister(index), 1 << scale); |
| 477 PrintDisp(disp, "]"); | 442 PrintDisp(disp, "]"); |
| 478 return 6; | 443 return 6; |
| 479 } else if (index != 4 && base != 5) { | 444 } else if (index != 4 && base != 5) { |
| 480 // [base+index*scale] | 445 // [base+index*scale] |
| 481 Print("[%s+%s*%d]", | 446 Print("[%s+%s*%d]", NameOfCPURegister(base), NameOfCPURegister(index), |
| 482 NameOfCPURegister(base), | |
| 483 NameOfCPURegister(index), | |
| 484 1 << scale); | 447 1 << scale); |
| 485 return 2; | 448 return 2; |
| 486 } else { | 449 } else { |
| 487 UnimplementedInstruction(); | 450 UnimplementedInstruction(); |
| 488 return 1; | 451 return 1; |
| 489 } | 452 } |
| 490 } else { | 453 } else { |
| 491 Print("[%s]", NameOfCPURegister(rm)); | 454 Print("[%s]", NameOfCPURegister(rm)); |
| 492 return 1; | 455 return 1; |
| 493 } | 456 } |
| 494 break; | 457 break; |
| 495 case 1: // fall through | 458 case 1: // fall through |
| 496 case 2: | 459 case 2: |
| 497 if ((rm & 7) == 4) { | 460 if ((rm & 7) == 4) { |
| 498 uint8_t sib = *(modrmp + 1); | 461 uint8_t sib = *(modrmp + 1); |
| 499 int scale, index, base; | 462 int scale, index, base; |
| 500 get_sib(sib, &scale, &index, &base); | 463 get_sib(sib, &scale, &index, &base); |
| 501 int disp = (mod == 2) ? *reinterpret_cast<int32_t*>(modrmp + 2) | 464 int disp = (mod == 2) ? *reinterpret_cast<int32_t*>(modrmp + 2) |
| 502 : *reinterpret_cast<char*>(modrmp + 2); | 465 : *reinterpret_cast<char*>(modrmp + 2); |
| 503 if (index == 4 && (base & 7) == 4 && scale == 0 /*times_1*/) { | 466 if (index == 4 && (base & 7) == 4 && scale == 0 /*times_1*/) { |
| 504 Print("[%s", NameOfCPURegister(base)); | 467 Print("[%s", NameOfCPURegister(base)); |
| 505 PrintDisp(disp, "]"); | 468 PrintDisp(disp, "]"); |
| 506 } else { | 469 } else { |
| 507 Print("[%s+%s*%d", | 470 Print("[%s+%s*%d", NameOfCPURegister(base), NameOfCPURegister(index), |
| 508 NameOfCPURegister(base), | |
| 509 NameOfCPURegister(index), | |
| 510 1 << scale); | 471 1 << scale); |
| 511 PrintDisp(disp, "]"); | 472 PrintDisp(disp, "]"); |
| 512 } | 473 } |
| 513 return mod == 2 ? 6 : 3; | 474 return mod == 2 ? 6 : 3; |
| 514 } else { | 475 } else { |
| 515 // No sib. | 476 // No sib. |
| 516 int disp = (mod == 2) ? *reinterpret_cast<int32_t*>(modrmp + 1) | 477 int disp = (mod == 2) ? *reinterpret_cast<int32_t*>(modrmp + 1) |
| 517 : *reinterpret_cast<char*>(modrmp + 1); | 478 : *reinterpret_cast<char*>(modrmp + 1); |
| 518 Print("[%s", NameOfCPURegister(rm)); | 479 Print("[%s", NameOfCPURegister(rm)); |
| 519 PrintDisp(disp, "]"); | 480 PrintDisp(disp, "]"); |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 571 void DisassemblerX64::PrintDisp(int disp, const char* after) { | 532 void DisassemblerX64::PrintDisp(int disp, const char* after) { |
| 572 if (-disp > 0) { | 533 if (-disp > 0) { |
| 573 Print("-%#x", -disp); | 534 Print("-%#x", -disp); |
| 574 } else { | 535 } else { |
| 575 Print("+%#x", disp); | 536 Print("+%#x", disp); |
| 576 } | 537 } |
| 577 if (after != NULL) Print("%s", after); | 538 if (after != NULL) Print("%s", after); |
| 578 } | 539 } |
| 579 | 540 |
| 580 | 541 |
| 581 | |
| 582 | |
| 583 // Returns number of bytes used by machine instruction, including *data byte. | 542 // Returns number of bytes used by machine instruction, including *data byte. |
| 584 // Writes immediate instructions to 'tmp_buffer_'. | 543 // Writes immediate instructions to 'tmp_buffer_'. |
| 585 int DisassemblerX64::PrintImmediateOp(uint8_t* data) { | 544 int DisassemblerX64::PrintImmediateOp(uint8_t* data) { |
| 586 bool byte_size_immediate = (*data & 0x02) != 0; | 545 bool byte_size_immediate = (*data & 0x02) != 0; |
| 587 uint8_t modrm = *(data + 1); | 546 uint8_t modrm = *(data + 1); |
| 588 int mod, regop, rm; | 547 int mod, regop, rm; |
| 589 get_modrm(modrm, &mod, ®op, &rm); | 548 get_modrm(modrm, &mod, ®op, &rm); |
| 590 const char* mnem = "Imm???"; | 549 const char* mnem = "Imm???"; |
| 591 switch (regop) { | 550 switch (regop) { |
| 592 case 0: | 551 case 0: |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 645 break; | 604 break; |
| 646 case 6: | 605 case 6: |
| 647 mnem = "div"; | 606 mnem = "div"; |
| 648 break; | 607 break; |
| 649 case 7: | 608 case 7: |
| 650 mnem = "idiv"; | 609 mnem = "idiv"; |
| 651 break; | 610 break; |
| 652 default: | 611 default: |
| 653 UnimplementedInstruction(); | 612 UnimplementedInstruction(); |
| 654 } | 613 } |
| 655 Print("%s%c %s", | 614 Print("%s%c %s", mnem, operand_size_code(), NameOfCPURegister(rm)); |
| 656 mnem, | |
| 657 operand_size_code(), | |
| 658 NameOfCPURegister(rm)); | |
| 659 return 2; | 615 return 2; |
| 660 } else if (regop == 0) { | 616 } else if (regop == 0) { |
| 661 Print("test%c ", operand_size_code()); | 617 Print("test%c ", operand_size_code()); |
| 662 int count = PrintRightOperand(data + 1); // Use name of 64-bit register. | 618 int count = PrintRightOperand(data + 1); // Use name of 64-bit register. |
| 663 Print(","); | 619 Print(","); |
| 664 count += PrintImmediate(data + 1 + count, operand_size()); | 620 count += PrintImmediate(data + 1 + count, operand_size()); |
| 665 return 1 + count; | 621 return 1 + count; |
| 666 } else { | 622 } else { |
| 667 UnimplementedInstruction(); | 623 UnimplementedInstruction(); |
| 668 return 2; | 624 return 2; |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 713 UnimplementedInstruction(); | 669 UnimplementedInstruction(); |
| 714 return num_bytes; | 670 return num_bytes; |
| 715 } | 671 } |
| 716 ASSERT(NULL != mnem); | 672 ASSERT(NULL != mnem); |
| 717 if (op == 0xD0) { | 673 if (op == 0xD0) { |
| 718 imm8 = 1; | 674 imm8 = 1; |
| 719 } else if (op == 0xC0) { | 675 } else if (op == 0xC0) { |
| 720 imm8 = *(data + 2); | 676 imm8 = *(data + 2); |
| 721 num_bytes = 3; | 677 num_bytes = 3; |
| 722 } | 678 } |
| 723 Print("%s%c %s,", | 679 Print("%s%c %s,", mnem, operand_size_code(), |
| 724 mnem, | 680 byte_size_operand_ ? NameOfByteCPURegister(rm) : NameOfCPURegister(rm)); |
| 725 operand_size_code(), | |
| 726 byte_size_operand_ ? NameOfByteCPURegister(rm) | |
| 727 : NameOfCPURegister(rm)); | |
| 728 if (op == 0xD2) { | 681 if (op == 0xD2) { |
| 729 Print("cl"); | 682 Print("cl"); |
| 730 } else { | 683 } else { |
| 731 Print("%d", imm8); | 684 Print("%d", imm8); |
| 732 } | 685 } |
| 733 return num_bytes; | 686 return num_bytes; |
| 734 } | 687 } |
| 735 | 688 |
| 736 | 689 |
| 737 int DisassemblerX64::PrintRightOperand(uint8_t* modrmp) { | 690 int DisassemblerX64::PrintRightOperand(uint8_t* modrmp) { |
| 738 return PrintRightOperandHelper(modrmp, | 691 return PrintRightOperandHelper(modrmp, &DisassemblerX64::NameOfCPURegister); |
| 739 &DisassemblerX64::NameOfCPURegister); | |
| 740 } | 692 } |
| 741 | 693 |
| 742 | 694 |
| 743 int DisassemblerX64::PrintRightByteOperand(uint8_t* modrmp) { | 695 int DisassemblerX64::PrintRightByteOperand(uint8_t* modrmp) { |
| 744 return PrintRightOperandHelper(modrmp, | 696 return PrintRightOperandHelper(modrmp, |
| 745 &DisassemblerX64::NameOfByteCPURegister); | 697 &DisassemblerX64::NameOfByteCPURegister); |
| 746 } | 698 } |
| 747 | 699 |
| 748 | 700 |
| 749 int DisassemblerX64::PrintRightXMMOperand(uint8_t* modrmp) { | 701 int DisassemblerX64::PrintRightXMMOperand(uint8_t* modrmp) { |
| 750 return PrintRightOperandHelper(modrmp, | 702 return PrintRightOperandHelper(modrmp, &DisassemblerX64::NameOfXMMRegister); |
| 751 &DisassemblerX64::NameOfXMMRegister); | |
| 752 } | 703 } |
| 753 | 704 |
| 754 | 705 |
| 755 // Returns number of bytes used including the current *data. | 706 // Returns number of bytes used including the current *data. |
| 756 // Writes instruction's mnemonic, left and right operands to 'tmp_buffer_'. | 707 // Writes instruction's mnemonic, left and right operands to 'tmp_buffer_'. |
| 757 int DisassemblerX64::PrintOperands(const char* mnem, | 708 int DisassemblerX64::PrintOperands(const char* mnem, |
| 758 OperandType op_order, | 709 OperandType op_order, |
| 759 uint8_t* data) { | 710 uint8_t* data) { |
| 760 uint8_t modrm = *data; | 711 uint8_t modrm = *data; |
| 761 int mod, regop, rm; | 712 int mod, regop, rm; |
| 762 get_modrm(modrm, &mod, ®op, &rm); | 713 get_modrm(modrm, &mod, ®op, &rm); |
| 763 int advance = 0; | 714 int advance = 0; |
| 764 const char* register_name = | 715 const char* register_name = byte_size_operand_ ? NameOfByteCPURegister(regop) |
| 765 byte_size_operand_ ? NameOfByteCPURegister(regop) | 716 : NameOfCPURegister(regop); |
| 766 : NameOfCPURegister(regop); | |
| 767 switch (op_order) { | 717 switch (op_order) { |
| 768 case REG_OPER_OP_ORDER: { | 718 case REG_OPER_OP_ORDER: { |
| 769 Print("%s%c %s,", mnem, operand_size_code(), register_name); | 719 Print("%s%c %s,", mnem, operand_size_code(), register_name); |
| 770 advance = byte_size_operand_ ? PrintRightByteOperand(data) | 720 advance = byte_size_operand_ ? PrintRightByteOperand(data) |
| 771 : PrintRightOperand(data); | 721 : PrintRightOperand(data); |
| 772 break; | 722 break; |
| 773 } | 723 } |
| 774 case OPER_REG_OP_ORDER: { | 724 case OPER_REG_OP_ORDER: { |
| 775 Print("%s%c ", mnem, operand_size_code()); | 725 Print("%s%c ", mnem, operand_size_code()); |
| 776 advance = byte_size_operand_ ? PrintRightByteOperand(data) | 726 advance = byte_size_operand_ ? PrintRightByteOperand(data) |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 835 Print("set%s%c ", mnem, operand_size_code()); | 785 Print("set%s%c ", mnem, operand_size_code()); |
| 836 PrintRightByteOperand(data + 2); | 786 PrintRightByteOperand(data + 2); |
| 837 return 3; // includes 0x0F | 787 return 3; // includes 0x0F |
| 838 } | 788 } |
| 839 | 789 |
| 840 | 790 |
| 841 // Returns number of bytes used, including *data. | 791 // Returns number of bytes used, including *data. |
| 842 int DisassemblerX64::FPUInstruction(uint8_t* data) { | 792 int DisassemblerX64::FPUInstruction(uint8_t* data) { |
| 843 uint8_t escape_opcode = *data; | 793 uint8_t escape_opcode = *data; |
| 844 ASSERT(0xD8 == (escape_opcode & 0xF8)); | 794 ASSERT(0xD8 == (escape_opcode & 0xF8)); |
| 845 uint8_t modrm_byte = *(data+1); | 795 uint8_t modrm_byte = *(data + 1); |
| 846 | 796 |
| 847 if (modrm_byte >= 0xC0) { | 797 if (modrm_byte >= 0xC0) { |
| 848 return RegisterFPUInstruction(escape_opcode, modrm_byte); | 798 return RegisterFPUInstruction(escape_opcode, modrm_byte); |
| 849 } else { | 799 } else { |
| 850 return MemoryFPUInstruction(escape_opcode, modrm_byte, data+1); | 800 return MemoryFPUInstruction(escape_opcode, modrm_byte, data + 1); |
| 851 } | 801 } |
| 852 } | 802 } |
| 853 | 803 |
| 854 | 804 |
| 855 int DisassemblerX64::MemoryFPUInstruction(int escape_opcode, | 805 int DisassemblerX64::MemoryFPUInstruction(int escape_opcode, |
| 856 int modrm_byte, | 806 int modrm_byte, |
| 857 uint8_t* modrm_start) { | 807 uint8_t* modrm_start) { |
| 858 const char* mnem = "?"; | 808 const char* mnem = "?"; |
| 859 int regop = (modrm_byte >> 3) & 0x7; // reg/op field of modrm byte. | 809 int regop = (modrm_byte >> 3) & 0x7; // reg/op field of modrm byte. |
| 860 switch (escape_opcode) { | 810 switch (escape_opcode) { |
| 861 case 0xD9: switch (regop) { | 811 case 0xD9: |
| 862 case 0: mnem = "fld_s"; break; | 812 switch (regop) { |
| 863 case 3: mnem = "fstp_s"; break; | 813 case 0: |
| 864 case 7: mnem = "fstcw"; break; | 814 mnem = "fld_s"; |
| 865 default: UnimplementedInstruction(); | 815 break; |
| 816 case 3: |
| 817 mnem = "fstp_s"; |
| 818 break; |
| 819 case 7: |
| 820 mnem = "fstcw"; |
| 821 break; |
| 822 default: |
| 823 UnimplementedInstruction(); |
| 866 } | 824 } |
| 867 break; | 825 break; |
| 868 | 826 |
| 869 case 0xDB: switch (regop) { | 827 case 0xDB: |
| 870 case 0: mnem = "fild_s"; break; | 828 switch (regop) { |
| 871 case 1: mnem = "fisttp_s"; break; | 829 case 0: |
| 872 case 2: mnem = "fist_s"; break; | 830 mnem = "fild_s"; |
| 873 case 3: mnem = "fistp_s"; break; | 831 break; |
| 874 default: UnimplementedInstruction(); | 832 case 1: |
| 833 mnem = "fisttp_s"; |
| 834 break; |
| 835 case 2: |
| 836 mnem = "fist_s"; |
| 837 break; |
| 838 case 3: |
| 839 mnem = "fistp_s"; |
| 840 break; |
| 841 default: |
| 842 UnimplementedInstruction(); |
| 875 } | 843 } |
| 876 break; | 844 break; |
| 877 | 845 |
| 878 case 0xDD: switch (regop) { | 846 case 0xDD: |
| 879 case 0: mnem = "fld_d"; break; | 847 switch (regop) { |
| 880 case 3: mnem = "fstp_d"; break; | 848 case 0: |
| 881 default: UnimplementedInstruction(); | 849 mnem = "fld_d"; |
| 850 break; |
| 851 case 3: |
| 852 mnem = "fstp_d"; |
| 853 break; |
| 854 default: |
| 855 UnimplementedInstruction(); |
| 882 } | 856 } |
| 883 break; | 857 break; |
| 884 | 858 |
| 885 case 0xDF: switch (regop) { | 859 case 0xDF: |
| 886 case 5: mnem = "fild_d"; break; | 860 switch (regop) { |
| 887 case 7: mnem = "fistp_d"; break; | 861 case 5: |
| 888 default: UnimplementedInstruction(); | 862 mnem = "fild_d"; |
| 863 break; |
| 864 case 7: |
| 865 mnem = "fistp_d"; |
| 866 break; |
| 867 default: |
| 868 UnimplementedInstruction(); |
| 889 } | 869 } |
| 890 break; | 870 break; |
| 891 | 871 |
| 892 default: UnimplementedInstruction(); | 872 default: |
| 873 UnimplementedInstruction(); |
| 893 } | 874 } |
| 894 Print("%s ", mnem); | 875 Print("%s ", mnem); |
| 895 int count = PrintRightOperand(modrm_start); | 876 int count = PrintRightOperand(modrm_start); |
| 896 return count + 1; | 877 return count + 1; |
| 897 } | 878 } |
| 898 | 879 |
| 899 int DisassemblerX64::RegisterFPUInstruction(int escape_opcode, | 880 int DisassemblerX64::RegisterFPUInstruction(int escape_opcode, |
| 900 uint8_t modrm_byte) { | 881 uint8_t modrm_byte) { |
| 901 bool has_register = false; // Is the FPU register encoded in modrm_byte? | 882 bool has_register = false; // Is the FPU register encoded in modrm_byte? |
| 902 const char* mnem = "?"; | 883 const char* mnem = "?"; |
| 903 | 884 |
| 904 switch (escape_opcode) { | 885 switch (escape_opcode) { |
| 905 case 0xD8: | 886 case 0xD8: |
| 906 UnimplementedInstruction(); | 887 UnimplementedInstruction(); |
| 907 break; | 888 break; |
| 908 | 889 |
| 909 case 0xD9: | 890 case 0xD9: |
| 910 switch (modrm_byte & 0xF8) { | 891 switch (modrm_byte & 0xF8) { |
| 911 case 0xC0: | 892 case 0xC0: |
| 912 mnem = "fld"; | 893 mnem = "fld"; |
| 913 has_register = true; | 894 has_register = true; |
| 914 break; | 895 break; |
| 915 case 0xC8: | 896 case 0xC8: |
| 916 mnem = "fxch"; | 897 mnem = "fxch"; |
| 917 has_register = true; | 898 has_register = true; |
| 918 break; | 899 break; |
| 919 default: | 900 default: |
| 920 switch (modrm_byte) { | 901 switch (modrm_byte) { |
| 921 case 0xE0: mnem = "fchs"; break; | 902 case 0xE0: |
| 922 case 0xE1: mnem = "fabs"; break; | 903 mnem = "fchs"; |
| 923 case 0xE3: mnem = "fninit"; break; | 904 break; |
| 924 case 0xE4: mnem = "ftst"; break; | 905 case 0xE1: |
| 925 case 0xE8: mnem = "fld1"; break; | 906 mnem = "fabs"; |
| 926 case 0xEB: mnem = "fldpi"; break; | 907 break; |
| 927 case 0xED: mnem = "fldln2"; break; | 908 case 0xE3: |
| 928 case 0xEE: mnem = "fldz"; break; | 909 mnem = "fninit"; |
| 929 case 0xF0: mnem = "f2xm1"; break; | 910 break; |
| 930 case 0xF1: mnem = "fyl2x"; break; | 911 case 0xE4: |
| 931 case 0xF2: mnem = "fptan"; break; | 912 mnem = "ftst"; |
| 932 case 0xF5: mnem = "fprem1"; break; | 913 break; |
| 933 case 0xF7: mnem = "fincstp"; break; | 914 case 0xE8: |
| 934 case 0xF8: mnem = "fprem"; break; | 915 mnem = "fld1"; |
| 935 case 0xFD: mnem = "fscale"; break; | 916 break; |
| 936 case 0xFE: mnem = "fsin"; break; | 917 case 0xEB: |
| 937 case 0xFF: mnem = "fcos"; break; | 918 mnem = "fldpi"; |
| 938 default: UnimplementedInstruction(); | 919 break; |
| 920 case 0xED: |
| 921 mnem = "fldln2"; |
| 922 break; |
| 923 case 0xEE: |
| 924 mnem = "fldz"; |
| 925 break; |
| 926 case 0xF0: |
| 927 mnem = "f2xm1"; |
| 928 break; |
| 929 case 0xF1: |
| 930 mnem = "fyl2x"; |
| 931 break; |
| 932 case 0xF2: |
| 933 mnem = "fptan"; |
| 934 break; |
| 935 case 0xF5: |
| 936 mnem = "fprem1"; |
| 937 break; |
| 938 case 0xF7: |
| 939 mnem = "fincstp"; |
| 940 break; |
| 941 case 0xF8: |
| 942 mnem = "fprem"; |
| 943 break; |
| 944 case 0xFD: |
| 945 mnem = "fscale"; |
| 946 break; |
| 947 case 0xFE: |
| 948 mnem = "fsin"; |
| 949 break; |
| 950 case 0xFF: |
| 951 mnem = "fcos"; |
| 952 break; |
| 953 default: |
| 954 UnimplementedInstruction(); |
| 939 } | 955 } |
| 940 } | 956 } |
| 941 break; | 957 break; |
| 942 | 958 |
| 943 case 0xDA: | 959 case 0xDA: |
| 944 if (modrm_byte == 0xE9) { | 960 if (modrm_byte == 0xE9) { |
| 945 mnem = "fucompp"; | 961 mnem = "fucompp"; |
| 946 } else { | 962 } else { |
| 947 UnimplementedInstruction(); | 963 UnimplementedInstruction(); |
| 948 } | 964 } |
| 949 break; | 965 break; |
| 950 | 966 |
| 951 case 0xDB: | 967 case 0xDB: |
| 952 if ((modrm_byte & 0xF8) == 0xE8) { | 968 if ((modrm_byte & 0xF8) == 0xE8) { |
| 953 mnem = "fucomi"; | 969 mnem = "fucomi"; |
| 954 has_register = true; | 970 has_register = true; |
| 955 } else if (modrm_byte == 0xE2) { | 971 } else if (modrm_byte == 0xE2) { |
| 956 mnem = "fclex"; | 972 mnem = "fclex"; |
| 957 } else { | 973 } else { |
| 958 UnimplementedInstruction(); | 974 UnimplementedInstruction(); |
| 959 } | 975 } |
| 960 break; | 976 break; |
| 961 | 977 |
| 962 case 0xDC: | 978 case 0xDC: |
| 963 has_register = true; | 979 has_register = true; |
| 964 switch (modrm_byte & 0xF8) { | 980 switch (modrm_byte & 0xF8) { |
| 965 case 0xC0: mnem = "fadd"; break; | 981 case 0xC0: |
| 966 case 0xE8: mnem = "fsub"; break; | 982 mnem = "fadd"; |
| 967 case 0xC8: mnem = "fmul"; break; | 983 break; |
| 968 case 0xF8: mnem = "fdiv"; break; | 984 case 0xE8: |
| 969 default: UnimplementedInstruction(); | 985 mnem = "fsub"; |
| 986 break; |
| 987 case 0xC8: |
| 988 mnem = "fmul"; |
| 989 break; |
| 990 case 0xF8: |
| 991 mnem = "fdiv"; |
| 992 break; |
| 993 default: |
| 994 UnimplementedInstruction(); |
| 970 } | 995 } |
| 971 break; | 996 break; |
| 972 | 997 |
| 973 case 0xDD: | 998 case 0xDD: |
| 974 has_register = true; | 999 has_register = true; |
| 975 switch (modrm_byte & 0xF8) { | 1000 switch (modrm_byte & 0xF8) { |
| 976 case 0xC0: mnem = "ffree"; break; | 1001 case 0xC0: |
| 977 case 0xD8: mnem = "fstp"; break; | 1002 mnem = "ffree"; |
| 978 default: UnimplementedInstruction(); | 1003 break; |
| 1004 case 0xD8: |
| 1005 mnem = "fstp"; |
| 1006 break; |
| 1007 default: |
| 1008 UnimplementedInstruction(); |
| 979 } | 1009 } |
| 980 break; | 1010 break; |
| 981 | 1011 |
| 982 case 0xDE: | 1012 case 0xDE: |
| 983 if (modrm_byte == 0xD9) { | 1013 if (modrm_byte == 0xD9) { |
| 984 mnem = "fcompp"; | 1014 mnem = "fcompp"; |
| 985 } else { | 1015 } else { |
| 986 has_register = true; | 1016 has_register = true; |
| 987 switch (modrm_byte & 0xF8) { | 1017 switch (modrm_byte & 0xF8) { |
| 988 case 0xC0: mnem = "faddp"; break; | 1018 case 0xC0: |
| 989 case 0xE8: mnem = "fsubp"; break; | 1019 mnem = "faddp"; |
| 990 case 0xC8: mnem = "fmulp"; break; | 1020 break; |
| 991 case 0xF8: mnem = "fdivp"; break; | 1021 case 0xE8: |
| 992 default: UnimplementedInstruction(); | 1022 mnem = "fsubp"; |
| 1023 break; |
| 1024 case 0xC8: |
| 1025 mnem = "fmulp"; |
| 1026 break; |
| 1027 case 0xF8: |
| 1028 mnem = "fdivp"; |
| 1029 break; |
| 1030 default: |
| 1031 UnimplementedInstruction(); |
| 993 } | 1032 } |
| 994 } | 1033 } |
| 995 break; | 1034 break; |
| 996 | 1035 |
| 997 case 0xDF: | 1036 case 0xDF: |
| 998 if (modrm_byte == 0xE0) { | 1037 if (modrm_byte == 0xE0) { |
| 999 mnem = "fnstsw_ax"; | 1038 mnem = "fnstsw_ax"; |
| 1000 } else if ((modrm_byte & 0xF8) == 0xE8) { | 1039 } else if ((modrm_byte & 0xF8) == 0xE8) { |
| 1001 mnem = "fucomip"; | 1040 mnem = "fucomip"; |
| 1002 has_register = true; | 1041 has_register = true; |
| 1003 } | 1042 } |
| 1004 break; | 1043 break; |
| 1005 | 1044 |
| 1006 default: UnimplementedInstruction(); | 1045 default: |
| 1046 UnimplementedInstruction(); |
| 1007 } | 1047 } |
| 1008 | 1048 |
| 1009 if (has_register) { | 1049 if (has_register) { |
| 1010 Print("%s st%d", mnem, modrm_byte & 0x7); | 1050 Print("%s st%d", mnem, modrm_byte & 0x7); |
| 1011 } else { | 1051 } else { |
| 1012 Print("%s", mnem); | 1052 Print("%s", mnem); |
| 1013 } | 1053 } |
| 1014 return 2; | 1054 return 2; |
| 1015 } | 1055 } |
| 1016 | 1056 |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1061 case TWO_OPERANDS_INSTR: | 1101 case TWO_OPERANDS_INSTR: |
| 1062 (*data)++; | 1102 (*data)++; |
| 1063 (*data) += PrintOperands(idesc.mnem, idesc.op_order_, *data); | 1103 (*data) += PrintOperands(idesc.mnem, idesc.op_order_, *data); |
| 1064 break; | 1104 break; |
| 1065 | 1105 |
| 1066 case JUMP_CONDITIONAL_SHORT_INSTR: | 1106 case JUMP_CONDITIONAL_SHORT_INSTR: |
| 1067 (*data) += JumpConditionalShort(*data); | 1107 (*data) += JumpConditionalShort(*data); |
| 1068 break; | 1108 break; |
| 1069 | 1109 |
| 1070 case REGISTER_INSTR: | 1110 case REGISTER_INSTR: |
| 1071 Print("%s%c %s", | 1111 Print("%s%c %s", idesc.mnem, operand_size_code(), |
| 1072 idesc.mnem, | |
| 1073 operand_size_code(), | |
| 1074 NameOfCPURegister(base_reg(current & 0x07))); | 1112 NameOfCPURegister(base_reg(current & 0x07))); |
| 1075 (*data)++; | 1113 (*data)++; |
| 1076 break; | 1114 break; |
| 1077 case PUSHPOP_INSTR: | 1115 case PUSHPOP_INSTR: |
| 1078 Print("%s %s", | 1116 Print("%s %s", idesc.mnem, NameOfCPURegister(base_reg(current & 0x07))); |
| 1079 idesc.mnem, | |
| 1080 NameOfCPURegister(base_reg(current & 0x07))); | |
| 1081 (*data)++; | 1117 (*data)++; |
| 1082 break; | 1118 break; |
| 1083 case MOVE_REG_INSTR: { | 1119 case MOVE_REG_INSTR: { |
| 1084 uint8_t* addr = NULL; | 1120 uint8_t* addr = NULL; |
| 1085 switch (operand_size()) { | 1121 switch (operand_size()) { |
| 1086 case WORD_SIZE: | 1122 case WORD_SIZE: |
| 1087 addr = reinterpret_cast<uint8_t*>( | 1123 addr = reinterpret_cast<uint8_t*>( |
| 1088 *reinterpret_cast<int16_t*>(*data + 1)); | 1124 *reinterpret_cast<int16_t*>(*data + 1)); |
| 1089 (*data) += 3; | 1125 (*data) += 3; |
| 1090 break; | 1126 break; |
| 1091 case DOUBLEWORD_SIZE: | 1127 case DOUBLEWORD_SIZE: |
| 1092 addr = reinterpret_cast<uint8_t*>( | 1128 addr = reinterpret_cast<uint8_t*>( |
| 1093 *reinterpret_cast<int32_t*>(*data + 1)); | 1129 *reinterpret_cast<int32_t*>(*data + 1)); |
| 1094 (*data) += 5; | 1130 (*data) += 5; |
| 1095 break; | 1131 break; |
| 1096 case QUADWORD_SIZE: | 1132 case QUADWORD_SIZE: |
| 1097 addr = reinterpret_cast<uint8_t*>( | 1133 addr = reinterpret_cast<uint8_t*>( |
| 1098 *reinterpret_cast<int64_t*>(*data + 1)); | 1134 *reinterpret_cast<int64_t*>(*data + 1)); |
| 1099 (*data) += 9; | 1135 (*data) += 9; |
| 1100 break; | 1136 break; |
| 1101 default: | 1137 default: |
| 1102 UNREACHABLE(); | 1138 UNREACHABLE(); |
| 1103 } | 1139 } |
| 1104 Print("mov%c %s,", | 1140 Print("mov%c %s,", operand_size_code(), |
| 1105 operand_size_code(), | |
| 1106 NameOfCPURegister(base_reg(current & 0x07))); | 1141 NameOfCPURegister(base_reg(current & 0x07))); |
| 1107 PrintAddress(addr); | 1142 PrintAddress(addr); |
| 1108 break; | 1143 break; |
| 1109 } | 1144 } |
| 1110 | 1145 |
| 1111 case CALL_JUMP_INSTR: { | 1146 case CALL_JUMP_INSTR: { |
| 1112 uint8_t* addr = *data + *reinterpret_cast<int32_t*>(*data + 1) + 5; | 1147 uint8_t* addr = *data + *reinterpret_cast<int32_t*>(*data + 1) + 5; |
| 1113 Print("%s ", idesc.mnem); | 1148 Print("%s ", idesc.mnem); |
| 1114 PrintAddress(addr); | 1149 PrintAddress(addr); |
| 1115 (*data) += 5; | 1150 (*data) += 5; |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1157 uint8_t third_byte = *current; | 1192 uint8_t third_byte = *current; |
| 1158 current = data + 3; | 1193 current = data + 3; |
| 1159 if (third_byte == 0x17) { | 1194 if (third_byte == 0x17) { |
| 1160 get_modrm(*current, &mod, ®op, &rm); | 1195 get_modrm(*current, &mod, ®op, &rm); |
| 1161 Print("extractps "); // reg/m32, xmm, imm8 | 1196 Print("extractps "); // reg/m32, xmm, imm8 |
| 1162 current += PrintRightOperand(current); | 1197 current += PrintRightOperand(current); |
| 1163 Print(", %s, %d", NameOfCPURegister(regop), (*current) & 3); | 1198 Print(", %s, %d", NameOfCPURegister(regop), (*current) & 3); |
| 1164 current += 1; | 1199 current += 1; |
| 1165 } else if (third_byte == 0x0b) { | 1200 } else if (third_byte == 0x0b) { |
| 1166 get_modrm(*current, &mod, ®op, &rm); | 1201 get_modrm(*current, &mod, ®op, &rm); |
| 1167 // roundsd xmm, xmm/m64, imm8 | 1202 // roundsd xmm, xmm/m64, imm8 |
| 1168 Print("roundsd %s, ", NameOfCPURegister(regop)); | 1203 Print("roundsd %s, ", NameOfCPURegister(regop)); |
| 1169 current += PrintRightOperand(current); | 1204 current += PrintRightOperand(current); |
| 1170 Print(", %d", (*current) & 3); | 1205 Print(", %d", (*current) & 3); |
| 1171 current += 1; | 1206 current += 1; |
| 1172 } else { | 1207 } else { |
| 1173 UnimplementedInstruction(); | 1208 UnimplementedInstruction(); |
| 1174 } | 1209 } |
| 1175 } else { | 1210 } else { |
| 1176 get_modrm(*current, &mod, ®op, &rm); | 1211 get_modrm(*current, &mod, ®op, &rm); |
| 1177 if (opcode == 0x1f) { | 1212 if (opcode == 0x1f) { |
| 1178 current++; | 1213 current++; |
| 1179 if (rm == 4) { // SIB byte present. | 1214 if (rm == 4) { // SIB byte present. |
| 1180 current++; | 1215 current++; |
| 1181 } | 1216 } |
| 1182 if (mod == 1) { // Byte displacement. | 1217 if (mod == 1) { // Byte displacement. |
| 1183 current += 1; | 1218 current += 1; |
| 1184 } else if (mod == 2) { // 32-bit displacement. | 1219 } else if (mod == 2) { // 32-bit displacement. |
| 1185 current += 4; | 1220 current += 4; |
| 1186 } // else no immediate displacement. | 1221 } // else no immediate displacement. |
| 1187 Print("nop"); | 1222 Print("nop"); |
| 1188 } else if (opcode == 0x28) { | 1223 } else if (opcode == 0x28) { |
| 1189 Print("movapd %s, ", NameOfXMMRegister(regop)); | 1224 Print("movapd %s, ", NameOfXMMRegister(regop)); |
| 1190 current += PrintRightXMMOperand(current); | 1225 current += PrintRightXMMOperand(current); |
| 1191 } else if (opcode == 0x29) { | 1226 } else if (opcode == 0x29) { |
| 1192 Print("movapd "); | 1227 Print("movapd "); |
| 1193 current += PrintRightXMMOperand(current); | 1228 current += PrintRightXMMOperand(current); |
| 1194 Print(", %s", NameOfXMMRegister(regop)); | 1229 Print(", %s", NameOfXMMRegister(regop)); |
| 1195 } else if (opcode == 0x6E) { | 1230 } else if (opcode == 0x6E) { |
| 1196 Print("mov%c %s,", | 1231 Print("mov%c %s,", rex_w() ? 'q' : 'd', NameOfXMMRegister(regop)); |
| 1197 rex_w() ? 'q' : 'd', | |
| 1198 NameOfXMMRegister(regop)); | |
| 1199 current += PrintRightOperand(current); | 1232 current += PrintRightOperand(current); |
| 1200 } else if (opcode == 0x6F) { | 1233 } else if (opcode == 0x6F) { |
| 1201 Print("movdqa %s,", | 1234 Print("movdqa %s,", NameOfXMMRegister(regop)); |
| 1202 NameOfXMMRegister(regop)); | |
| 1203 current += PrintRightXMMOperand(current); | 1235 current += PrintRightXMMOperand(current); |
| 1204 } else if (opcode == 0x7E) { | 1236 } else if (opcode == 0x7E) { |
| 1205 Print("mov%c ", | 1237 Print("mov%c ", rex_w() ? 'q' : 'd'); |
| 1206 rex_w() ? 'q' : 'd'); | |
| 1207 current += PrintRightOperand(current); | 1238 current += PrintRightOperand(current); |
| 1208 Print(", %s", NameOfXMMRegister(regop)); | 1239 Print(", %s", NameOfXMMRegister(regop)); |
| 1209 } else if (opcode == 0x7F) { | 1240 } else if (opcode == 0x7F) { |
| 1210 Print("movdqa "); | 1241 Print("movdqa "); |
| 1211 current += PrintRightXMMOperand(current); | 1242 current += PrintRightXMMOperand(current); |
| 1212 Print(", %s", NameOfXMMRegister(regop)); | 1243 Print(", %s", NameOfXMMRegister(regop)); |
| 1213 } else if (opcode == 0xD6) { | 1244 } else if (opcode == 0xD6) { |
| 1214 Print("movq "); | 1245 Print("movq "); |
| 1215 current += PrintRightXMMOperand(current); | 1246 current += PrintRightXMMOperand(current); |
| 1216 Print(", %s", NameOfXMMRegister(regop)); | 1247 Print(", %s", NameOfXMMRegister(regop)); |
| 1217 } else if (opcode == 0x50) { | 1248 } else if (opcode == 0x50) { |
| 1218 Print("movmskpd %s,", NameOfCPURegister(regop)); | 1249 Print("movmskpd %s,", NameOfCPURegister(regop)); |
| 1219 current += PrintRightXMMOperand(current); | 1250 current += PrintRightXMMOperand(current); |
| 1220 } else { | 1251 } else { |
| 1221 const char* mnemonic = "?"; | 1252 const char* mnemonic = "?"; |
| 1222 if (opcode == 0x14) { | 1253 if (opcode == 0x14) { |
| 1223 mnemonic = "unpcklpd"; | 1254 mnemonic = "unpcklpd"; |
| 1224 } else if (opcode == 0x15) { | 1255 } else if (opcode == 0x15) { |
| 1225 mnemonic = "unpckhpd"; | 1256 mnemonic = "unpckhpd"; |
| 1226 } else if (opcode == 0x54) { | 1257 } else if (opcode == 0x54) { |
| 1227 mnemonic = "andpd"; | 1258 mnemonic = "andpd"; |
| 1228 } else if (opcode == 0x56) { | 1259 } else if (opcode == 0x56) { |
| 1229 mnemonic = "orpd"; | 1260 mnemonic = "orpd"; |
| 1230 } else if (opcode == 0x57) { | 1261 } else if (opcode == 0x57) { |
| 1231 mnemonic = "xorpd"; | 1262 mnemonic = "xorpd"; |
| 1232 } else if (opcode == 0x2E) { | 1263 } else if (opcode == 0x2E) { |
| 1233 mnemonic = "ucomisd"; | 1264 mnemonic = "ucomisd"; |
| 1234 } else if (opcode == 0x2F) { | 1265 } else if (opcode == 0x2F) { |
| 1235 mnemonic = "comisd"; | 1266 mnemonic = "comisd"; |
| 1236 } else if (opcode == 0xFE) { | 1267 } else if (opcode == 0xFE) { |
| 1237 mnemonic = "paddd"; | 1268 mnemonic = "paddd"; |
| 1238 } else if (opcode == 0xFA) { | 1269 } else if (opcode == 0xFA) { |
| 1239 mnemonic = "psubd"; | 1270 mnemonic = "psubd"; |
| 1240 } else if (opcode == 0x58) { | 1271 } else if (opcode == 0x58) { |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1279 // CVTSI2SD: integer to XMM double conversion. | 1310 // CVTSI2SD: integer to XMM double conversion. |
| 1280 int mod, regop, rm; | 1311 int mod, regop, rm; |
| 1281 get_modrm(*current, &mod, ®op, &rm); | 1312 get_modrm(*current, &mod, ®op, &rm); |
| 1282 Print("%sd %s,", mnemonic, NameOfXMMRegister(regop)); | 1313 Print("%sd %s,", mnemonic, NameOfXMMRegister(regop)); |
| 1283 current += PrintRightOperand(current); | 1314 current += PrintRightOperand(current); |
| 1284 } else if (opcode == 0x2C) { | 1315 } else if (opcode == 0x2C) { |
| 1285 // CVTTSD2SI: | 1316 // CVTTSD2SI: |
| 1286 // Convert with truncation scalar double-precision FP to integer. | 1317 // Convert with truncation scalar double-precision FP to integer. |
| 1287 int mod, regop, rm; | 1318 int mod, regop, rm; |
| 1288 get_modrm(*current, &mod, ®op, &rm); | 1319 get_modrm(*current, &mod, ®op, &rm); |
| 1289 Print("cvttsd2si%c %s,", | 1320 Print("cvttsd2si%c %s,", operand_size_code(), NameOfCPURegister(regop)); |
| 1290 operand_size_code(), NameOfCPURegister(regop)); | |
| 1291 current += PrintRightXMMOperand(current); | 1321 current += PrintRightXMMOperand(current); |
| 1292 } else if (opcode == 0x2D) { | 1322 } else if (opcode == 0x2D) { |
| 1293 // CVTSD2SI: Convert scalar double-precision FP to integer. | 1323 // CVTSD2SI: Convert scalar double-precision FP to integer. |
| 1294 int mod, regop, rm; | 1324 int mod, regop, rm; |
| 1295 get_modrm(*current, &mod, ®op, &rm); | 1325 get_modrm(*current, &mod, ®op, &rm); |
| 1296 Print("cvtsd2si%c %s,", | 1326 Print("cvtsd2si%c %s,", operand_size_code(), NameOfCPURegister(regop)); |
| 1297 operand_size_code(), NameOfCPURegister(regop)); | |
| 1298 current += PrintRightXMMOperand(current); | 1327 current += PrintRightXMMOperand(current); |
| 1299 } else if ((opcode & 0xF8) == 0x58 || opcode == 0x51) { | 1328 } else if ((opcode & 0xF8) == 0x58 || opcode == 0x51) { |
| 1300 // XMM arithmetic. Mnemonic was retrieved at the start of this function. | 1329 // XMM arithmetic. Mnemonic was retrieved at the start of this function. |
| 1301 int mod, regop, rm; | 1330 int mod, regop, rm; |
| 1302 get_modrm(*current, &mod, ®op, &rm); | 1331 get_modrm(*current, &mod, ®op, &rm); |
| 1303 Print("%s %s,", mnemonic, NameOfXMMRegister(regop)); | 1332 Print("%s %s,", mnemonic, NameOfXMMRegister(regop)); |
| 1304 current += PrintRightXMMOperand(current); | 1333 current += PrintRightXMMOperand(current); |
| 1305 } else { | 1334 } else { |
| 1306 UnimplementedInstruction(); | 1335 UnimplementedInstruction(); |
| 1307 } | 1336 } |
| (...skipping 15 matching lines...) Expand all Loading... |
| 1323 // CVTSI2SS: integer to XMM single conversion. | 1352 // CVTSI2SS: integer to XMM single conversion. |
| 1324 int mod, regop, rm; | 1353 int mod, regop, rm; |
| 1325 get_modrm(*current, &mod, ®op, &rm); | 1354 get_modrm(*current, &mod, ®op, &rm); |
| 1326 Print("%ss %s,", mnemonic, NameOfXMMRegister(regop)); | 1355 Print("%ss %s,", mnemonic, NameOfXMMRegister(regop)); |
| 1327 current += PrintRightOperand(current); | 1356 current += PrintRightOperand(current); |
| 1328 } else if (opcode == 0x2C) { | 1357 } else if (opcode == 0x2C) { |
| 1329 // CVTTSS2SI: | 1358 // CVTTSS2SI: |
| 1330 // Convert with truncation scalar single-precision FP to dword integer. | 1359 // Convert with truncation scalar single-precision FP to dword integer. |
| 1331 int mod, regop, rm; | 1360 int mod, regop, rm; |
| 1332 get_modrm(*current, &mod, ®op, &rm); | 1361 get_modrm(*current, &mod, ®op, &rm); |
| 1333 Print("cvttss2si%c %s,", | 1362 Print("cvttss2si%c %s,", operand_size_code(), NameOfCPURegister(regop)); |
| 1334 operand_size_code(), NameOfCPURegister(regop)); | |
| 1335 current += PrintRightXMMOperand(current); | 1363 current += PrintRightXMMOperand(current); |
| 1336 } else if (opcode == 0x5A) { | 1364 } else if (opcode == 0x5A) { |
| 1337 // CVTSS2SD: | 1365 // CVTSS2SD: |
| 1338 // Convert scalar single-precision FP to scalar double-precision FP. | 1366 // Convert scalar single-precision FP to scalar double-precision FP. |
| 1339 int mod, regop, rm; | 1367 int mod, regop, rm; |
| 1340 get_modrm(*current, &mod, ®op, &rm); | 1368 get_modrm(*current, &mod, ®op, &rm); |
| 1341 Print("cvtss2sd %s,", NameOfXMMRegister(regop)); | 1369 Print("cvtss2sd %s,", NameOfXMMRegister(regop)); |
| 1342 current += PrintRightXMMOperand(current); | 1370 current += PrintRightXMMOperand(current); |
| 1343 } else if (opcode == 0x7E) { | 1371 } else if (opcode == 0x7E) { |
| 1344 int mod, regop, rm; | 1372 int mod, regop, rm; |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1411 current += PrintOperands(idesc.mnem, idesc.op_order_, current); | 1439 current += PrintOperands(idesc.mnem, idesc.op_order_, current); |
| 1412 | 1440 |
| 1413 } else if (opcode == 0x12 || opcode == 0x14 || opcode == 0x15 || | 1441 } else if (opcode == 0x12 || opcode == 0x14 || opcode == 0x15 || |
| 1414 opcode == 0x16 || opcode == 0x51 || opcode == 0x52 || | 1442 opcode == 0x16 || opcode == 0x51 || opcode == 0x52 || |
| 1415 opcode == 0x53 || opcode == 0x54 || opcode == 0x56 || | 1443 opcode == 0x53 || opcode == 0x54 || opcode == 0x56 || |
| 1416 opcode == 0x57 || opcode == 0x58 || opcode == 0x59 || | 1444 opcode == 0x57 || opcode == 0x58 || opcode == 0x59 || |
| 1417 opcode == 0x5A || opcode == 0x5C || opcode == 0x5D || | 1445 opcode == 0x5A || opcode == 0x5C || opcode == 0x5D || |
| 1418 opcode == 0x5E || opcode == 0x5F) { | 1446 opcode == 0x5E || opcode == 0x5F) { |
| 1419 const char* mnemonic = NULL; | 1447 const char* mnemonic = NULL; |
| 1420 switch (opcode) { | 1448 switch (opcode) { |
| 1421 case 0x12: mnemonic = "movhlps"; break; | 1449 case 0x12: |
| 1422 case 0x14: mnemonic = "unpcklps"; break; | 1450 mnemonic = "movhlps"; |
| 1423 case 0x15: mnemonic = "unpckhps"; break; | 1451 break; |
| 1424 case 0x16: mnemonic = "movlhps"; break; | 1452 case 0x14: |
| 1425 case 0x51: mnemonic = "sqrtps"; break; | 1453 mnemonic = "unpcklps"; |
| 1426 case 0x52: mnemonic = "rsqrtps"; break; | 1454 break; |
| 1427 case 0x53: mnemonic = "rcpps"; break; | 1455 case 0x15: |
| 1428 case 0x54: mnemonic = "andps"; break; | 1456 mnemonic = "unpckhps"; |
| 1429 case 0x56: mnemonic = "orps"; break; | 1457 break; |
| 1430 case 0x57: mnemonic = "xorps"; break; | 1458 case 0x16: |
| 1431 case 0x58: mnemonic = "addps"; break; | 1459 mnemonic = "movlhps"; |
| 1432 case 0x59: mnemonic = "mulps"; break; | 1460 break; |
| 1433 case 0x5A: mnemonic = "cvtsd2ss"; break; | 1461 case 0x51: |
| 1434 case 0x5C: mnemonic = "subps"; break; | 1462 mnemonic = "sqrtps"; |
| 1435 case 0x5D: mnemonic = "minps"; break; | 1463 break; |
| 1436 case 0x5E: mnemonic = "divps"; break; | 1464 case 0x52: |
| 1437 case 0x5F: mnemonic = "maxps"; break; | 1465 mnemonic = "rsqrtps"; |
| 1438 default: UNREACHABLE(); | 1466 break; |
| 1467 case 0x53: |
| 1468 mnemonic = "rcpps"; |
| 1469 break; |
| 1470 case 0x54: |
| 1471 mnemonic = "andps"; |
| 1472 break; |
| 1473 case 0x56: |
| 1474 mnemonic = "orps"; |
| 1475 break; |
| 1476 case 0x57: |
| 1477 mnemonic = "xorps"; |
| 1478 break; |
| 1479 case 0x58: |
| 1480 mnemonic = "addps"; |
| 1481 break; |
| 1482 case 0x59: |
| 1483 mnemonic = "mulps"; |
| 1484 break; |
| 1485 case 0x5A: |
| 1486 mnemonic = "cvtsd2ss"; |
| 1487 break; |
| 1488 case 0x5C: |
| 1489 mnemonic = "subps"; |
| 1490 break; |
| 1491 case 0x5D: |
| 1492 mnemonic = "minps"; |
| 1493 break; |
| 1494 case 0x5E: |
| 1495 mnemonic = "divps"; |
| 1496 break; |
| 1497 case 0x5F: |
| 1498 mnemonic = "maxps"; |
| 1499 break; |
| 1500 default: |
| 1501 UNREACHABLE(); |
| 1439 } | 1502 } |
| 1440 int mod, regop, rm; | 1503 int mod, regop, rm; |
| 1441 get_modrm(*current, &mod, ®op, &rm); | 1504 get_modrm(*current, &mod, ®op, &rm); |
| 1442 Print("%s %s, ", mnemonic, NameOfXMMRegister(regop)); | 1505 Print("%s %s, ", mnemonic, NameOfXMMRegister(regop)); |
| 1443 current += PrintRightXMMOperand(current); | 1506 current += PrintRightXMMOperand(current); |
| 1444 } else if (opcode == 0xC2 || opcode == 0xC6) { | 1507 } else if (opcode == 0xC2 || opcode == 0xC6) { |
| 1445 int mod, regop, rm; | 1508 int mod, regop, rm; |
| 1446 get_modrm(*current, &mod, ®op, &rm); | 1509 get_modrm(*current, &mod, ®op, &rm); |
| 1447 if (opcode == 0xC2) { | 1510 if (opcode == 0xC2) { |
| 1448 Print("cmpps %s, ", NameOfXMMRegister(regop)); | 1511 Print("cmpps %s, ", NameOfXMMRegister(regop)); |
| (...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1555 | 1618 |
| 1556 if (!processed) { | 1619 if (!processed) { |
| 1557 switch (*data) { | 1620 switch (*data) { |
| 1558 case 0xC2: | 1621 case 0xC2: |
| 1559 Print("ret "); | 1622 Print("ret "); |
| 1560 PrintImmediateValue(*reinterpret_cast<uint16_t*>(data + 1)); | 1623 PrintImmediateValue(*reinterpret_cast<uint16_t*>(data + 1)); |
| 1561 data += 3; | 1624 data += 3; |
| 1562 break; | 1625 break; |
| 1563 | 1626 |
| 1564 case 0xC8: | 1627 case 0xC8: |
| 1565 Print("enter %d, %d", | 1628 Print("enter %d, %d", *reinterpret_cast<uint16_t*>(data + 1), data[3]); |
| 1566 *reinterpret_cast<uint16_t*>(data + 1), | |
| 1567 data[3]); | |
| 1568 data += 4; | 1629 data += 4; |
| 1569 break; | 1630 break; |
| 1570 | 1631 |
| 1571 case 0x69: // fall through | 1632 case 0x69: // fall through |
| 1572 case 0x6B: { | 1633 case 0x6B: { |
| 1573 int mod, regop, rm; | 1634 int mod, regop, rm; |
| 1574 get_modrm(*(data + 1), &mod, ®op, &rm); | 1635 get_modrm(*(data + 1), &mod, ®op, &rm); |
| 1575 int32_t imm = *data == 0x6B ? *(data + 2) | 1636 int32_t imm = |
| 1576 : *reinterpret_cast<int32_t*>(data + 2); | 1637 *data == 0x6B ? *(data + 2) : *reinterpret_cast<int32_t*>(data + 2); |
| 1577 Print("imul%c %s,%s,", | 1638 Print("imul%c %s,%s,", operand_size_code(), NameOfCPURegister(regop), |
| 1578 operand_size_code(), | |
| 1579 NameOfCPURegister(regop), | |
| 1580 NameOfCPURegister(rm)); | 1639 NameOfCPURegister(rm)); |
| 1581 PrintImmediateValue(imm); | 1640 PrintImmediateValue(imm); |
| 1582 data += 2 + (*data == 0x6B ? 1 : 4); | 1641 data += 2 + (*data == 0x6B ? 1 : 4); |
| 1583 break; | 1642 break; |
| 1584 } | 1643 } |
| 1585 | 1644 |
| 1586 case 0x81: // fall through | 1645 case 0x81: // fall through |
| 1587 case 0x83: // 0x81 with sign extension bit set | 1646 case 0x83: // 0x81 with sign extension bit set |
| 1588 data += PrintImmediateOp(data); | 1647 data += PrintImmediateOp(data); |
| 1589 break; | 1648 break; |
| 1590 | 1649 |
| 1591 case 0x0F: | 1650 case 0x0F: |
| 1592 data += TwoByteOpcodeInstruction(data); | 1651 data += TwoByteOpcodeInstruction(data); |
| 1593 break; | 1652 break; |
| 1594 | 1653 |
| 1595 case 0x8F: { | 1654 case 0x8F: { |
| 1596 data++; | 1655 data++; |
| 1597 int mod, regop, rm; | 1656 int mod, regop, rm; |
| 1598 get_modrm(*data, &mod, ®op, &rm); | 1657 get_modrm(*data, &mod, ®op, &rm); |
| 1599 if (regop == 0) { | 1658 if (regop == 0) { |
| 1600 Print("pop "); | 1659 Print("pop "); |
| 1601 data += PrintRightOperand(data); | 1660 data += PrintRightOperand(data); |
| 1602 } | 1661 } |
| 1603 } | 1662 } break; |
| 1604 break; | |
| 1605 | 1663 |
| 1606 case 0xFF: { | 1664 case 0xFF: { |
| 1607 data++; | 1665 data++; |
| 1608 int mod, regop, rm; | 1666 int mod, regop, rm; |
| 1609 get_modrm(*data, &mod, ®op, &rm); | 1667 get_modrm(*data, &mod, ®op, &rm); |
| 1610 const char* mnem = NULL; | 1668 const char* mnem = NULL; |
| 1611 switch (regop) { | 1669 switch (regop) { |
| 1612 case 0: | 1670 case 0: |
| 1613 mnem = "inc"; | 1671 mnem = "inc"; |
| 1614 break; | 1672 break; |
| (...skipping 11 matching lines...) Expand all Loading... |
| 1626 break; | 1684 break; |
| 1627 default: | 1685 default: |
| 1628 mnem = "???"; | 1686 mnem = "???"; |
| 1629 } | 1687 } |
| 1630 if (regop <= 1) { | 1688 if (regop <= 1) { |
| 1631 Print("%s%c ", mnem, operand_size_code()); | 1689 Print("%s%c ", mnem, operand_size_code()); |
| 1632 } else { | 1690 } else { |
| 1633 Print("%s ", mnem); | 1691 Print("%s ", mnem); |
| 1634 } | 1692 } |
| 1635 data += PrintRightOperand(data); | 1693 data += PrintRightOperand(data); |
| 1636 } | 1694 } break; |
| 1637 break; | |
| 1638 | 1695 |
| 1639 case 0xC7: // imm32, fall through | 1696 case 0xC7: // imm32, fall through |
| 1640 case 0xC6: // imm8 | 1697 case 0xC6: // imm8 |
| 1641 { | 1698 { |
| 1642 bool is_byte = *data == 0xC6; | 1699 bool is_byte = *data == 0xC6; |
| 1643 data++; | 1700 data++; |
| 1644 if (is_byte) { | 1701 if (is_byte) { |
| 1645 Print("movb "); | 1702 Print("movb "); |
| 1646 data += PrintRightByteOperand(data); | 1703 data += PrintRightByteOperand(data); |
| 1647 int32_t imm = *data; | 1704 int32_t imm = *data; |
| 1648 Print(","); | 1705 Print(","); |
| 1649 PrintImmediateValue(imm); | 1706 PrintImmediateValue(imm); |
| 1650 data++; | 1707 data++; |
| 1651 } else { | 1708 } else { |
| 1652 Print("mov%c ", operand_size_code()); | 1709 Print("mov%c ", operand_size_code()); |
| 1653 data += PrintRightOperand(data); | 1710 data += PrintRightOperand(data); |
| 1654 int32_t imm = *reinterpret_cast<int32_t*>(data); | 1711 int32_t imm = *reinterpret_cast<int32_t*>(data); |
| 1655 Print(","); | 1712 Print(","); |
| 1656 PrintImmediateValue(imm); | 1713 PrintImmediateValue(imm); |
| 1657 data += 4; | 1714 data += 4; |
| 1658 } | 1715 } |
| 1659 } | 1716 } break; |
| 1660 break; | |
| 1661 | 1717 |
| 1662 case 0x80: { | 1718 case 0x80: { |
| 1663 data++; | 1719 data++; |
| 1664 Print("cmpb "); | 1720 Print("cmpb "); |
| 1665 data += PrintRightByteOperand(data); | 1721 data += PrintRightByteOperand(data); |
| 1666 int32_t imm = *data; | 1722 int32_t imm = *data; |
| 1667 Print(","); | 1723 Print(","); |
| 1668 PrintImmediateValue(imm); | 1724 PrintImmediateValue(imm); |
| 1669 data++; | 1725 data++; |
| 1670 } | 1726 } break; |
| 1671 break; | |
| 1672 | 1727 |
| 1673 case 0x88: // 8bit, fall through | 1728 case 0x88: // 8bit, fall through |
| 1674 case 0x89: // 32bit | 1729 case 0x89: // 32bit |
| 1675 { | 1730 { |
| 1676 bool is_byte = *data == 0x88; | 1731 bool is_byte = *data == 0x88; |
| 1677 int mod, regop, rm; | 1732 int mod, regop, rm; |
| 1678 data++; | 1733 data++; |
| 1679 get_modrm(*data, &mod, ®op, &rm); | 1734 get_modrm(*data, &mod, ®op, &rm); |
| 1680 if (is_byte) { | 1735 if (is_byte) { |
| 1681 Print("movb "); | 1736 Print("movb "); |
| 1682 data += PrintRightByteOperand(data); | 1737 data += PrintRightByteOperand(data); |
| 1683 Print(",%s", NameOfByteCPURegister(regop)); | 1738 Print(",%s", NameOfByteCPURegister(regop)); |
| 1684 } else { | 1739 } else { |
| 1685 Print("mov%c ", operand_size_code()); | 1740 Print("mov%c ", operand_size_code()); |
| 1686 data += PrintRightOperand(data); | 1741 data += PrintRightOperand(data); |
| 1687 Print(",%s", NameOfCPURegister(regop)); | 1742 Print(",%s", NameOfCPURegister(regop)); |
| 1688 } | 1743 } |
| 1689 } | 1744 } break; |
| 1690 break; | |
| 1691 | 1745 |
| 1692 case 0x90: | 1746 case 0x90: |
| 1693 case 0x91: | 1747 case 0x91: |
| 1694 case 0x92: | 1748 case 0x92: |
| 1695 case 0x93: | 1749 case 0x93: |
| 1696 case 0x94: | 1750 case 0x94: |
| 1697 case 0x95: | 1751 case 0x95: |
| 1698 case 0x96: | 1752 case 0x96: |
| 1699 case 0x97: { | 1753 case 0x97: { |
| 1700 int reg = (*data & 0x7) | (rex_b() ? 8 : 0); | 1754 int reg = (*data & 0x7) | (rex_b() ? 8 : 0); |
| 1701 if (reg == 0) { | 1755 if (reg == 0) { |
| 1702 Print("nop"); // Common name for xchg rax,rax. | 1756 Print("nop"); // Common name for xchg rax,rax. |
| 1703 } else { | 1757 } else { |
| 1704 Print("xchg%c rax, %s", operand_size_code(), NameOfCPURegister(reg)); | 1758 Print("xchg%c rax, %s", operand_size_code(), NameOfCPURegister(reg)); |
| 1705 } | 1759 } |
| 1706 data++; | 1760 data++; |
| 1707 } | 1761 } break; |
| 1708 break; | |
| 1709 case 0xB0: | 1762 case 0xB0: |
| 1710 case 0xB1: | 1763 case 0xB1: |
| 1711 case 0xB2: | 1764 case 0xB2: |
| 1712 case 0xB3: | 1765 case 0xB3: |
| 1713 case 0xB4: | 1766 case 0xB4: |
| 1714 case 0xB5: | 1767 case 0xB5: |
| 1715 case 0xB6: | 1768 case 0xB6: |
| 1716 case 0xB7: | 1769 case 0xB7: |
| 1717 case 0xB8: | 1770 case 0xB8: |
| 1718 case 0xB9: | 1771 case 0xB9: |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1757 case 0x6A: | 1810 case 0x6A: |
| 1758 Print("push "); | 1811 Print("push "); |
| 1759 PrintImmediateValue(*reinterpret_cast<int8_t*>(data + 1)); | 1812 PrintImmediateValue(*reinterpret_cast<int8_t*>(data + 1)); |
| 1760 data += 2; | 1813 data += 2; |
| 1761 break; | 1814 break; |
| 1762 | 1815 |
| 1763 case 0xA1: // Fall through. | 1816 case 0xA1: // Fall through. |
| 1764 case 0xA3: | 1817 case 0xA3: |
| 1765 switch (operand_size()) { | 1818 switch (operand_size()) { |
| 1766 case DOUBLEWORD_SIZE: { | 1819 case DOUBLEWORD_SIZE: { |
| 1767 PrintAddress( | 1820 PrintAddress(reinterpret_cast<uint8_t*>( |
| 1768 reinterpret_cast<uint8_t*>( | 1821 *reinterpret_cast<int32_t*>(data + 1))); |
| 1769 *reinterpret_cast<int32_t*>(data + 1))); | |
| 1770 if (*data == 0xA1) { // Opcode 0xA1 | 1822 if (*data == 0xA1) { // Opcode 0xA1 |
| 1771 Print("movzxlq rax,("); | 1823 Print("movzxlq rax,("); |
| 1772 PrintAddress( | 1824 PrintAddress(reinterpret_cast<uint8_t*>( |
| 1773 reinterpret_cast<uint8_t*>( | 1825 *reinterpret_cast<int32_t*>(data + 1))); |
| 1774 *reinterpret_cast<int32_t*>(data + 1))); | |
| 1775 Print(")"); | 1826 Print(")"); |
| 1776 } else { // Opcode 0xA3 | 1827 } else { // Opcode 0xA3 |
| 1777 Print("movzxlq ("); | 1828 Print("movzxlq ("); |
| 1778 PrintAddress( | 1829 PrintAddress(reinterpret_cast<uint8_t*>( |
| 1779 reinterpret_cast<uint8_t*>( | 1830 *reinterpret_cast<int32_t*>(data + 1))); |
| 1780 *reinterpret_cast<int32_t*>(data + 1))); | |
| 1781 Print("),rax"); | 1831 Print("),rax"); |
| 1782 } | 1832 } |
| 1783 data += 5; | 1833 data += 5; |
| 1784 break; | 1834 break; |
| 1785 } | 1835 } |
| 1786 case QUADWORD_SIZE: { | 1836 case QUADWORD_SIZE: { |
| 1787 // New x64 instruction mov rax,(imm_64). | 1837 // New x64 instruction mov rax,(imm_64). |
| 1788 if (*data == 0xA1) { // Opcode 0xA1 | 1838 if (*data == 0xA1) { // Opcode 0xA1 |
| 1789 Print("movq rax,("); | 1839 Print("movq rax,("); |
| 1790 PrintAddress(*reinterpret_cast<uint8_t**>(data + 1)); | 1840 PrintAddress(*reinterpret_cast<uint8_t**>(data + 1)); |
| 1791 Print(")"); | 1841 Print(")"); |
| 1792 } else { // Opcode 0xA3 | 1842 } else { // Opcode 0xA3 |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1871 | 1921 |
| 1872 ASSERT(buffer_[buffer_pos_] == '\0'); | 1922 ASSERT(buffer_[buffer_pos_] == '\0'); |
| 1873 | 1923 |
| 1874 int instr_len = data - reinterpret_cast<uint8_t*>(pc); | 1924 int instr_len = data - reinterpret_cast<uint8_t*>(pc); |
| 1875 ASSERT(instr_len > 0); // Ensure progress. | 1925 ASSERT(instr_len > 0); // Ensure progress. |
| 1876 | 1926 |
| 1877 return instr_len; | 1927 return instr_len; |
| 1878 } | 1928 } |
| 1879 | 1929 |
| 1880 | 1930 |
| 1881 void Disassembler::DecodeInstruction(char* hex_buffer, intptr_t hex_size, | 1931 void Disassembler::DecodeInstruction(char* hex_buffer, |
| 1882 char* human_buffer, intptr_t human_size, | 1932 intptr_t hex_size, |
| 1883 int* out_instr_len, const Code& code, | 1933 char* human_buffer, |
| 1884 Object** object, uword pc) { | 1934 intptr_t human_size, |
| 1935 int* out_instr_len, |
| 1936 const Code& code, |
| 1937 Object** object, |
| 1938 uword pc) { |
| 1885 ASSERT(hex_size > 0); | 1939 ASSERT(hex_size > 0); |
| 1886 ASSERT(human_size > 0); | 1940 ASSERT(human_size > 0); |
| 1887 DisassemblerX64 decoder(human_buffer, human_size); | 1941 DisassemblerX64 decoder(human_buffer, human_size); |
| 1888 int instruction_length = decoder.InstructionDecode(pc); | 1942 int instruction_length = decoder.InstructionDecode(pc); |
| 1889 uint8_t* pc_ptr = reinterpret_cast<uint8_t*>(pc); | 1943 uint8_t* pc_ptr = reinterpret_cast<uint8_t*>(pc); |
| 1890 int hex_index = 0; | 1944 int hex_index = 0; |
| 1891 int remaining_size = hex_size - hex_index; | 1945 int remaining_size = hex_size - hex_index; |
| 1892 for (int i = 0; (i < instruction_length) && (remaining_size > 2); ++i) { | 1946 for (int i = 0; (i < instruction_length) && (remaining_size > 2); ++i) { |
| 1893 OS::SNPrint(&hex_buffer[hex_index], remaining_size, "%02x", pc_ptr[i]); | 1947 OS::SNPrint(&hex_buffer[hex_index], remaining_size, "%02x", pc_ptr[i]); |
| 1894 hex_index += 2; | 1948 hex_index += 2; |
| (...skipping 11 matching lines...) Expand all Loading... |
| 1906 *object = NULL; | 1960 *object = NULL; |
| 1907 } | 1961 } |
| 1908 } | 1962 } |
| 1909 } | 1963 } |
| 1910 | 1964 |
| 1911 #endif // !PRODUCT | 1965 #endif // !PRODUCT |
| 1912 | 1966 |
| 1913 } // namespace dart | 1967 } // namespace dart |
| 1914 | 1968 |
| 1915 #endif // defined TARGET_ARCH_X64 | 1969 #endif // defined TARGET_ARCH_X64 |
| OLD | NEW |