1 // Copyright 2011 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include <assert.h>
6 #include <stdarg.h>
7 #include <stdio.h>
8
9 #if V8_TARGET_ARCH_IA32
10
11 #include "src/base/compiler-specific.h"
12 #include "src/disasm.h"
13 #include "src/ia32/sse-instr.h"
14
15 namespace disasm {
16
17 enum OperandOrder {
18 UNSET_OP_ORDER = 0,
19 REG_OPER_OP_ORDER,
20 OPER_REG_OP_ORDER
21 };
22
23
24 //------------------------------------------------------------------
25 // Tables
26 //------------------------------------------------------------------
27 struct ByteMnemonic {
28 int b; // -1 terminates, otherwise must be in range (0..255)
29 const char* mnem;
30 OperandOrder op_order_;
31 };
32
33 static const ByteMnemonic two_operands_instr[] = {
34 {0x01, "add", OPER_REG_OP_ORDER}, {0x03, "add", REG_OPER_OP_ORDER},
35 {0x09, "or", OPER_REG_OP_ORDER}, {0x0B, "or", REG_OPER_OP_ORDER},
36 {0x13, "adc", REG_OPER_OP_ORDER}, {0x1B, "sbb", REG_OPER_OP_ORDER},
37 {0x21, "and", OPER_REG_OP_ORDER}, {0x23, "and", REG_OPER_OP_ORDER},
38 {0x29, "sub", OPER_REG_OP_ORDER}, {0x2A, "subb", REG_OPER_OP_ORDER},
39 {0x2B, "sub", REG_OPER_OP_ORDER}, {0x31, "xor", OPER_REG_OP_ORDER},
40 {0x33, "xor", REG_OPER_OP_ORDER}, {0x38, "cmpb", OPER_REG_OP_ORDER},
41 {0x39, "cmp", OPER_REG_OP_ORDER}, {0x3A, "cmpb", REG_OPER_OP_ORDER},
42 {0x3B, "cmp", REG_OPER_OP_ORDER}, {0x84, "test_b", REG_OPER_OP_ORDER},
43 {0x85, "test", REG_OPER_OP_ORDER}, {0x86, "xchg_b", REG_OPER_OP_ORDER},
44 {0x87, "xchg", REG_OPER_OP_ORDER}, {0x8A, "mov_b", REG_OPER_OP_ORDER},
45 {0x8B, "mov", REG_OPER_OP_ORDER}, {0x8D, "lea", REG_OPER_OP_ORDER},
46 {-1, "", UNSET_OP_ORDER}};
47
48 static const ByteMnemonic zero_operands_instr[] = {
49 {0xC3, "ret", UNSET_OP_ORDER},
50 {0xC9, "leave", UNSET_OP_ORDER},
51 {0x90, "nop", UNSET_OP_ORDER},
52 {0xF4, "hlt", UNSET_OP_ORDER},
53 {0xCC, "int3", UNSET_OP_ORDER},
54 {0x60, "pushad", UNSET_OP_ORDER},
55 {0x61, "popad", UNSET_OP_ORDER},
56 {0x9C, "pushfd", UNSET_OP_ORDER},
57 {0x9D, "popfd", UNSET_OP_ORDER},
58 {0x9E, "sahf", UNSET_OP_ORDER},
59 {0x99, "cdq", UNSET_OP_ORDER},
60 {0x9B, "fwait", UNSET_OP_ORDER},
61 {0xFC, "cld", UNSET_OP_ORDER},
62 {0xAB, "stos", UNSET_OP_ORDER},
63 {-1, "", UNSET_OP_ORDER}
64 };
65
66
67 static const ByteMnemonic call_jump_instr[] = {
68 {0xE8, "call", UNSET_OP_ORDER},
69 {0xE9, "jmp", UNSET_OP_ORDER},
70 {-1, "", UNSET_OP_ORDER}
71 };
72
73
74 static const ByteMnemonic short_immediate_instr[] = {
75 {0x05, "add", UNSET_OP_ORDER},
76 {0x0D, "or", UNSET_OP_ORDER},
77 {0x15, "adc", UNSET_OP_ORDER},
78 {0x25, "and", UNSET_OP_ORDER},
79 {0x2D, "sub", UNSET_OP_ORDER},
80 {0x35, "xor", UNSET_OP_ORDER},
81 {0x3D, "cmp", UNSET_OP_ORDER},
82 {-1, "", UNSET_OP_ORDER}
83 };
84
85
86 // Generally we don't want to generate these because they are subject to partial
87 // register stalls. They are included for completeness and because the cmp
88 // variant is used by the RecordWrite stub. Because it does not update the
89 // register it is not subject to partial register stalls.
90 static ByteMnemonic byte_immediate_instr[] = {{0x0C, "or", UNSET_OP_ORDER},
91 {0x24, "and", UNSET_OP_ORDER},
92 {0x34, "xor", UNSET_OP_ORDER},
93 {0x3C, "cmp", UNSET_OP_ORDER},
94 {-1, "", UNSET_OP_ORDER}};
95
96 static const char* const jump_conditional_mnem[] = {
97 /*0*/ "jo", "jno", "jc", "jnc",
98 /*4*/ "jz", "jnz", "jna", "ja",
99 /*8*/ "js", "jns", "jpe", "jpo",
100 /*12*/ "jl", "jnl", "jng", "jg"
101 };
102
103
104 static const char* const set_conditional_mnem[] = {
105 /*0*/ "seto", "setno", "setc", "setnc",
106 /*4*/ "setz", "setnz", "setna", "seta",
107 /*8*/ "sets", "setns", "setpe", "setpo",
108 /*12*/ "setl", "setnl", "setng", "setg"
109 };
110
111
112 static const char* const conditional_move_mnem[] = {
113 /*0*/ "cmovo", "cmovno", "cmovc", "cmovnc",
114 /*4*/ "cmovz", "cmovnz", "cmovna", "cmova",
115 /*8*/ "cmovs", "cmovns", "cmovpe", "cmovpo",
116 /*12*/ "cmovl", "cmovnl", "cmovng", "cmovg"
117 };
118
119
120 enum InstructionType {
121 NO_INSTR,
122 ZERO_OPERANDS_INSTR,
123 TWO_OPERANDS_INSTR,
124 JUMP_CONDITIONAL_SHORT_INSTR,
125 REGISTER_INSTR,
126 MOVE_REG_INSTR,
127 CALL_JUMP_INSTR,
128 SHORT_IMMEDIATE_INSTR,
129 BYTE_IMMEDIATE_INSTR
130 };
131
132
133 struct InstructionDesc {
134 const char* mnem;
135 InstructionType type;
136 OperandOrder op_order_;
137 };
138
139
140 class InstructionTable {
141 public:
142 InstructionTable();
Get(byte x) const143 const InstructionDesc& Get(byte x) const { return instructions_[x]; }
get_instance()144 static InstructionTable* get_instance() {
145 static InstructionTable table;
146 return &table;
147 }
148
149 private:
150 InstructionDesc instructions_[256];
151 void Clear();
152 void Init();
153 void CopyTable(const ByteMnemonic bm[], InstructionType type);
154 void SetTableRange(InstructionType type,
155 byte start,
156 byte end,
157 const char* mnem);
158 void AddJumpConditionalShort();
159 };
160
161
InstructionTable()162 InstructionTable::InstructionTable() {
163 Clear();
164 Init();
165 }
166
167
Clear()168 void InstructionTable::Clear() {
169 for (int i = 0; i < 256; i++) {
170 instructions_[i].mnem = "";
171 instructions_[i].type = NO_INSTR;
172 instructions_[i].op_order_ = UNSET_OP_ORDER;
173 }
174 }
175
176
Init()177 void InstructionTable::Init() {
178 CopyTable(two_operands_instr, TWO_OPERANDS_INSTR);
179 CopyTable(zero_operands_instr, ZERO_OPERANDS_INSTR);
180 CopyTable(call_jump_instr, CALL_JUMP_INSTR);
181 CopyTable(short_immediate_instr, SHORT_IMMEDIATE_INSTR);
182 CopyTable(byte_immediate_instr, BYTE_IMMEDIATE_INSTR);
183 AddJumpConditionalShort();
184 SetTableRange(REGISTER_INSTR, 0x40, 0x47, "inc");
185 SetTableRange(REGISTER_INSTR, 0x48, 0x4F, "dec");
186 SetTableRange(REGISTER_INSTR, 0x50, 0x57, "push");
187 SetTableRange(REGISTER_INSTR, 0x58, 0x5F, "pop");
188 SetTableRange(REGISTER_INSTR, 0x91, 0x97, "xchg eax,"); // 0x90 is nop.
189 SetTableRange(MOVE_REG_INSTR, 0xB8, 0xBF, "mov");
190 }
191
192
CopyTable(const ByteMnemonic bm[],InstructionType type)193 void InstructionTable::CopyTable(const ByteMnemonic bm[],
194 InstructionType type) {
195 for (int i = 0; bm[i].b >= 0; i++) {
196 InstructionDesc* id = &instructions_[bm[i].b];
197 id->mnem = bm[i].mnem;
198 id->op_order_ = bm[i].op_order_;
199 DCHECK_EQ(NO_INSTR, id->type); // Information not already entered.
200 id->type = type;
201 }
202 }
203
204
SetTableRange(InstructionType type,byte start,byte end,const char * mnem)205 void InstructionTable::SetTableRange(InstructionType type,
206 byte start,
207 byte end,
208 const char* mnem) {
209 for (byte b = start; b <= end; b++) {
210 InstructionDesc* id = &instructions_[b];
211 DCHECK_EQ(NO_INSTR, id->type); // Information not already entered.
212 id->mnem = mnem;
213 id->type = type;
214 }
215 }
216
217
AddJumpConditionalShort()218 void InstructionTable::AddJumpConditionalShort() {
219 for (byte b = 0x70; b <= 0x7F; b++) {
220 InstructionDesc* id = &instructions_[b];
221 DCHECK_EQ(NO_INSTR, id->type); // Information not already entered.
222 id->mnem = jump_conditional_mnem[b & 0x0F];
223 id->type = JUMP_CONDITIONAL_SHORT_INSTR;
224 }
225 }
226
227
228 // The IA32 disassembler implementation.
229 class DisassemblerIA32 {
230 public:
DisassemblerIA32(const NameConverter & converter,Disassembler::UnimplementedOpcodeAction unimplemented_opcode_action)231 DisassemblerIA32(
232 const NameConverter& converter,
233 Disassembler::UnimplementedOpcodeAction unimplemented_opcode_action)
234 : converter_(converter),
235 vex_byte0_(0),
236 vex_byte1_(0),
237 vex_byte2_(0),
238 instruction_table_(InstructionTable::get_instance()),
239 tmp_buffer_pos_(0),
240 unimplemented_opcode_action_(unimplemented_opcode_action) {
241 tmp_buffer_[0] = '\0';
242 }
243
~DisassemblerIA32()244 virtual ~DisassemblerIA32() {}
245
246 // Writes one disassembled instruction into 'buffer' (0-terminated).
247 // Returns the length of the disassembled machine instruction in bytes.
248 int InstructionDecode(v8::internal::Vector<char> buffer, byte* instruction);
249
250 private:
251 const NameConverter& converter_;
252 byte vex_byte0_; // 0xC4 or 0xC5
253 byte vex_byte1_;
254 byte vex_byte2_; // only for 3 bytes vex prefix
255 InstructionTable* instruction_table_;
256 v8::internal::EmbeddedVector<char, 128> tmp_buffer_;
257 unsigned int tmp_buffer_pos_;
258 Disassembler::UnimplementedOpcodeAction unimplemented_opcode_action_;
259
260 enum {
261 eax = 0,
262 ecx = 1,
263 edx = 2,
264 ebx = 3,
265 esp = 4,
266 ebp = 5,
267 esi = 6,
268 edi = 7
269 };
270
271
272 enum ShiftOpcodeExtension {
273 kROL = 0,
274 kROR = 1,
275 kRCL = 2,
276 kRCR = 3,
277 kSHL = 4,
278 KSHR = 5,
279 kSAR = 7
280 };
281
vex_128()282 bool vex_128() {
283 DCHECK(vex_byte0_ == 0xC4 || vex_byte0_ == 0xC5);
284 byte checked = vex_byte0_ == 0xC4 ? vex_byte2_ : vex_byte1_;
285 return (checked & 4) == 0;
286 }
287
vex_none()288 bool vex_none() {
289 DCHECK(vex_byte0_ == 0xC4 || vex_byte0_ == 0xC5);
290 byte checked = vex_byte0_ == 0xC4 ? vex_byte2_ : vex_byte1_;
291 return (checked & 3) == 0;
292 }
293
vex_66()294 bool vex_66() {
295 DCHECK(vex_byte0_ == 0xC4 || vex_byte0_ == 0xC5);
296 byte checked = vex_byte0_ == 0xC4 ? vex_byte2_ : vex_byte1_;
297 return (checked & 3) == 1;
298 }
299
vex_f3()300 bool vex_f3() {
301 DCHECK(vex_byte0_ == 0xC4 || vex_byte0_ == 0xC5);
302 byte checked = vex_byte0_ == 0xC4 ? vex_byte2_ : vex_byte1_;
303 return (checked & 3) == 2;
304 }
305
vex_f2()306 bool vex_f2() {
307 DCHECK(vex_byte0_ == 0xC4 || vex_byte0_ == 0xC5);
308 byte checked = vex_byte0_ == 0xC4 ? vex_byte2_ : vex_byte1_;
309 return (checked & 3) == 3;
310 }
311
vex_w()312 bool vex_w() {
313 if (vex_byte0_ == 0xC5) return false;
314 return (vex_byte2_ & 0x80) != 0;
315 }
316
vex_0f()317 bool vex_0f() {
318 if (vex_byte0_ == 0xC5) return true;
319 return (vex_byte1_ & 3) == 1;
320 }
321
vex_0f38()322 bool vex_0f38() {
323 if (vex_byte0_ == 0xC5) return false;
324 return (vex_byte1_ & 3) == 2;
325 }
326
vex_0f3a()327 bool vex_0f3a() {
328 if (vex_byte0_ == 0xC5) return false;
329 return (vex_byte1_ & 3) == 3;
330 }
331
vex_vreg()332 int vex_vreg() {
333 DCHECK(vex_byte0_ == 0xC4 || vex_byte0_ == 0xC5);
334 byte checked = vex_byte0_ == 0xC4 ? vex_byte2_ : vex_byte1_;
335 return ~(checked >> 3) & 0xF;
336 }
337
float_size_code()338 char float_size_code() { return "sd"[vex_w()]; }
339
NameOfCPURegister(int reg) const340 const char* NameOfCPURegister(int reg) const {
341 return converter_.NameOfCPURegister(reg);
342 }
343
344
NameOfByteCPURegister(int reg) const345 const char* NameOfByteCPURegister(int reg) const {
346 return converter_.NameOfByteCPURegister(reg);
347 }
348
349
NameOfXMMRegister(int reg) const350 const char* NameOfXMMRegister(int reg) const {
351 return converter_.NameOfXMMRegister(reg);
352 }
353
354
NameOfAddress(byte * addr) const355 const char* NameOfAddress(byte* addr) const {
356 return converter_.NameOfAddress(addr);
357 }
358
359
360 // Disassembler helper functions.
get_modrm(byte data,int * mod,int * regop,int * rm)361 static void get_modrm(byte data, int* mod, int* regop, int* rm) {
362 *mod = (data >> 6) & 3;
363 *regop = (data & 0x38) >> 3;
364 *rm = data & 7;
365 }
366
367
get_sib(byte data,int * scale,int * index,int * base)368 static void get_sib(byte data, int* scale, int* index, int* base) {
369 *scale = (data >> 6) & 3;
370 *index = (data >> 3) & 7;
371 *base = data & 7;
372 }
373
374 typedef const char* (DisassemblerIA32::*RegisterNameMapping)(int reg) const;
375
376 int PrintRightOperandHelper(byte* modrmp, RegisterNameMapping register_name);
377 int PrintRightOperand(byte* modrmp);
378 int PrintRightByteOperand(byte* modrmp);
379 int PrintRightXMMOperand(byte* modrmp);
380 int PrintOperands(const char* mnem, OperandOrder op_order, byte* data);
381 int PrintImmediateOp(byte* data);
382 int F7Instruction(byte* data);
383 int D1D3C1Instruction(byte* data);
384 int JumpShort(byte* data);
385 int JumpConditional(byte* data, const char* comment);
386 int JumpConditionalShort(byte* data, const char* comment);
387 int SetCC(byte* data);
388 int CMov(byte* data);
389 int FPUInstruction(byte* data);
390 int MemoryFPUInstruction(int escape_opcode, int regop, byte* modrm_start);
391 int RegisterFPUInstruction(int escape_opcode, byte modrm_byte);
392 int AVXInstruction(byte* data);
393 PRINTF_FORMAT(2, 3) void AppendToBuffer(const char* format, ...);
394
UnimplementedInstruction()395 void UnimplementedInstruction() {
396 if (unimplemented_opcode_action_ ==
397 Disassembler::kAbortOnUnimplementedOpcode) {
398 FATAL("Unimplemented instruction in disassembler");
399 } else {
400 AppendToBuffer("'Unimplemented Instruction'");
401 }
402 }
403 };
404
405
AppendToBuffer(const char * format,...)406 void DisassemblerIA32::AppendToBuffer(const char* format, ...) {
407 v8::internal::Vector<char> buf = tmp_buffer_ + tmp_buffer_pos_;
408 va_list args;
409 va_start(args, format);
410 int result = v8::internal::VSNPrintF(buf, format, args);
411 va_end(args);
412 tmp_buffer_pos_ += result;
413 }
414
PrintRightOperandHelper(byte * modrmp,RegisterNameMapping direct_register_name)415 int DisassemblerIA32::PrintRightOperandHelper(
416 byte* modrmp,
417 RegisterNameMapping direct_register_name) {
418 int mod, regop, rm;
419 get_modrm(*modrmp, &mod, ®op, &rm);
420 RegisterNameMapping register_name = (mod == 3) ? direct_register_name :
421 &DisassemblerIA32::NameOfCPURegister;
422 switch (mod) {
423 case 0:
424 if (rm == ebp) {
425 int32_t disp = *reinterpret_cast<int32_t*>(modrmp+1);
426 AppendToBuffer("[0x%x]", disp);
427 return 5;
428 } else if (rm == esp) {
429 byte sib = *(modrmp + 1);
430 int scale, index, base;
431 get_sib(sib, &scale, &index, &base);
432 if (index == esp && base == esp && scale == 0 /*times_1*/) {
433 AppendToBuffer("[%s]", (this->*register_name)(rm));
434 return 2;
435 } else if (base == ebp) {
436 int32_t disp = *reinterpret_cast<int32_t*>(modrmp + 2);
437 AppendToBuffer("[%s*%d%s0x%x]",
438 (this->*register_name)(index),
439 1 << scale,
440 disp < 0 ? "-" : "+",
441 disp < 0 ? -disp : disp);
442 return 6;
443 } else if (index != esp && base != ebp) {
444 // [base+index*scale]
445 AppendToBuffer("[%s+%s*%d]",
446 (this->*register_name)(base),
447 (this->*register_name)(index),
448 1 << scale);
449 return 2;
450 } else {
451 UnimplementedInstruction();
452 return 1;
453 }
454 } else {
455 AppendToBuffer("[%s]", (this->*register_name)(rm));
456 return 1;
457 }
458 break;
459 case 1: // fall through
460 case 2:
461 if (rm == esp) {
462 byte sib = *(modrmp + 1);
463 int scale, index, base;
464 get_sib(sib, &scale, &index, &base);
465 int disp = mod == 2 ? *reinterpret_cast<int32_t*>(modrmp + 2)
466 : *reinterpret_cast<int8_t*>(modrmp + 2);
467 if (index == base && index == rm /*esp*/ && scale == 0 /*times_1*/) {
468 AppendToBuffer("[%s%s0x%x]",
469 (this->*register_name)(rm),
470 disp < 0 ? "-" : "+",
471 disp < 0 ? -disp : disp);
472 } else {
473 AppendToBuffer("[%s+%s*%d%s0x%x]",
474 (this->*register_name)(base),
475 (this->*register_name)(index),
476 1 << scale,
477 disp < 0 ? "-" : "+",
478 disp < 0 ? -disp : disp);
479 }
480 return mod == 2 ? 6 : 3;
481 } else {
482 // No sib.
483 int disp = mod == 2 ? *reinterpret_cast<int32_t*>(modrmp + 1)
484 : *reinterpret_cast<int8_t*>(modrmp + 1);
485 AppendToBuffer("[%s%s0x%x]",
486 (this->*register_name)(rm),
487 disp < 0 ? "-" : "+",
488 disp < 0 ? -disp : disp);
489 return mod == 2 ? 5 : 2;
490 }
491 break;
492 case 3:
493 AppendToBuffer("%s", (this->*register_name)(rm));
494 return 1;
495 default:
496 UnimplementedInstruction();
497 return 1;
498 }
499 UNREACHABLE();
500 }
501
502
PrintRightOperand(byte * modrmp)503 int DisassemblerIA32::PrintRightOperand(byte* modrmp) {
504 return PrintRightOperandHelper(modrmp, &DisassemblerIA32::NameOfCPURegister);
505 }
506
507
PrintRightByteOperand(byte * modrmp)508 int DisassemblerIA32::PrintRightByteOperand(byte* modrmp) {
509 return PrintRightOperandHelper(modrmp,
510 &DisassemblerIA32::NameOfByteCPURegister);
511 }
512
513
PrintRightXMMOperand(byte * modrmp)514 int DisassemblerIA32::PrintRightXMMOperand(byte* modrmp) {
515 return PrintRightOperandHelper(modrmp,
516 &DisassemblerIA32::NameOfXMMRegister);
517 }
518
519
520 // Returns number of bytes used including the current *data.
521 // Writes instruction's mnemonic, left and right operands to 'tmp_buffer_'.
PrintOperands(const char * mnem,OperandOrder op_order,byte * data)522 int DisassemblerIA32::PrintOperands(const char* mnem,
523 OperandOrder op_order,
524 byte* data) {
525 byte modrm = *data;
526 int mod, regop, rm;
527 get_modrm(modrm, &mod, ®op, &rm);
528 int advance = 0;
529 switch (op_order) {
530 case REG_OPER_OP_ORDER: {
531 AppendToBuffer("%s %s,", mnem, NameOfCPURegister(regop));
532 advance = PrintRightOperand(data);
533 break;
534 }
535 case OPER_REG_OP_ORDER: {
536 AppendToBuffer("%s ", mnem);
537 advance = PrintRightOperand(data);
538 AppendToBuffer(",%s", NameOfCPURegister(regop));
539 break;
540 }
541 default:
542 UNREACHABLE();
543 break;
544 }
545 return advance;
546 }
547
548
549 // Returns number of bytes used by machine instruction, including *data byte.
550 // Writes immediate instructions to 'tmp_buffer_'.
PrintImmediateOp(byte * data)551 int DisassemblerIA32::PrintImmediateOp(byte* data) {
552 bool sign_extension_bit = (*data & 0x02) != 0;
553 byte modrm = *(data+1);
554 int mod, regop, rm;
555 get_modrm(modrm, &mod, ®op, &rm);
556 const char* mnem = "Imm???";
557 switch (regop) {
558 case 0: mnem = "add"; break;
559 case 1: mnem = "or"; break;
560 case 2: mnem = "adc"; break;
561 case 4: mnem = "and"; break;
562 case 5: mnem = "sub"; break;
563 case 6: mnem = "xor"; break;
564 case 7: mnem = "cmp"; break;
565 default: UnimplementedInstruction();
566 }
567 AppendToBuffer("%s ", mnem);
568 int count = PrintRightOperand(data+1);
569 if (sign_extension_bit) {
570 AppendToBuffer(",0x%x", *(data + 1 + count));
571 return 1 + count + 1 /*int8*/;
572 } else {
573 AppendToBuffer(",0x%x", *reinterpret_cast<int32_t*>(data + 1 + count));
574 return 1 + count + 4 /*int32_t*/;
575 }
576 }
577
578
579 // Returns number of bytes used, including *data.
F7Instruction(byte * data)580 int DisassemblerIA32::F7Instruction(byte* data) {
581 DCHECK_EQ(0xF7, *data);
582 byte modrm = *++data;
583 int mod, regop, rm;
584 get_modrm(modrm, &mod, ®op, &rm);
585 const char* mnem = nullptr;
586 switch (regop) {
587 case 0:
588 mnem = "test";
589 break;
590 case 2:
591 mnem = "not";
592 break;
593 case 3:
594 mnem = "neg";
595 break;
596 case 4:
597 mnem = "mul";
598 break;
599 case 5:
600 mnem = "imul";
601 break;
602 case 6:
603 mnem = "div";
604 break;
605 case 7:
606 mnem = "idiv";
607 break;
608 default:
609 UnimplementedInstruction();
610 }
611 AppendToBuffer("%s ", mnem);
612 int count = PrintRightOperand(data);
613 if (regop == 0) {
614 AppendToBuffer(",0x%x", *reinterpret_cast<int32_t*>(data + count));
615 count += 4;
616 }
617 return 1 + count;
618 }
619
620
D1D3C1Instruction(byte * data)621 int DisassemblerIA32::D1D3C1Instruction(byte* data) {
622 byte op = *data;
623 DCHECK(op == 0xD1 || op == 0xD3 || op == 0xC1);
624 byte modrm = *++data;
625 int mod, regop, rm;
626 get_modrm(modrm, &mod, ®op, &rm);
627 int imm8 = -1;
628 const char* mnem = nullptr;
629 switch (regop) {
630 case kROL:
631 mnem = "rol";
632 break;
633 case kROR:
634 mnem = "ror";
635 break;
636 case kRCL:
637 mnem = "rcl";
638 break;
639 case kRCR:
640 mnem = "rcr";
641 break;
642 case kSHL:
643 mnem = "shl";
644 break;
645 case KSHR:
646 mnem = "shr";
647 break;
648 case kSAR:
649 mnem = "sar";
650 break;
651 default:
652 UnimplementedInstruction();
653 }
654 AppendToBuffer("%s ", mnem);
655 int count = PrintRightOperand(data);
656 if (op == 0xD1) {
657 imm8 = 1;
658 } else if (op == 0xC1) {
659 imm8 = *(data + 1);
660 count++;
661 } else if (op == 0xD3) {
662 // Shift/rotate by cl.
663 }
664 if (imm8 >= 0) {
665 AppendToBuffer(",%d", imm8);
666 } else {
667 AppendToBuffer(",cl");
668 }
669 return 1 + count;
670 }
671
672
673 // Returns number of bytes used, including *data.
JumpShort(byte * data)674 int DisassemblerIA32::JumpShort(byte* data) {
675 DCHECK_EQ(0xEB, *data);
676 byte b = *(data+1);
677 byte* dest = data + static_cast<int8_t>(b) + 2;
678 AppendToBuffer("jmp %s", NameOfAddress(dest));
679 return 2;
680 }
681
682
683 // Returns number of bytes used, including *data.
JumpConditional(byte * data,const char * comment)684 int DisassemblerIA32::JumpConditional(byte* data, const char* comment) {
685 DCHECK_EQ(0x0F, *data);
686 byte cond = *(data+1) & 0x0F;
687 byte* dest = data + *reinterpret_cast<int32_t*>(data+2) + 6;
688 const char* mnem = jump_conditional_mnem[cond];
689 AppendToBuffer("%s %s", mnem, NameOfAddress(dest));
690 if (comment != nullptr) {
691 AppendToBuffer(", %s", comment);
692 }
693 return 6; // includes 0x0F
694 }
695
696
697 // Returns number of bytes used, including *data.
JumpConditionalShort(byte * data,const char * comment)698 int DisassemblerIA32::JumpConditionalShort(byte* data, const char* comment) {
699 byte cond = *data & 0x0F;
700 byte b = *(data+1);
701 byte* dest = data + static_cast<int8_t>(b) + 2;
702 const char* mnem = jump_conditional_mnem[cond];
703 AppendToBuffer("%s %s", mnem, NameOfAddress(dest));
704 if (comment != nullptr) {
705 AppendToBuffer(", %s", comment);
706 }
707 return 2;
708 }
709
710
711 // Returns number of bytes used, including *data.
SetCC(byte * data)712 int DisassemblerIA32::SetCC(byte* data) {
713 DCHECK_EQ(0x0F, *data);
714 byte cond = *(data+1) & 0x0F;
715 const char* mnem = set_conditional_mnem[cond];
716 AppendToBuffer("%s ", mnem);
717 PrintRightByteOperand(data+2);
718 return 3; // Includes 0x0F.
719 }
720
721
722 // Returns number of bytes used, including *data.
CMov(byte * data)723 int DisassemblerIA32::CMov(byte* data) {
724 DCHECK_EQ(0x0F, *data);
725 byte cond = *(data + 1) & 0x0F;
726 const char* mnem = conditional_move_mnem[cond];
727 int op_size = PrintOperands(mnem, REG_OPER_OP_ORDER, data + 2);
728 return 2 + op_size; // includes 0x0F
729 }
730
731 const char* sf_str[4] = {"", "rl", "ra", "ll"};
732
AVXInstruction(byte * data)733 int DisassemblerIA32::AVXInstruction(byte* data) {
734 byte opcode = *data;
735 byte* current = data + 1;
736 if (vex_66() && vex_0f38()) {
737 int mod, regop, rm, vvvv = vex_vreg();
738 get_modrm(*current, &mod, ®op, &rm);
739 switch (opcode) {
740 case 0x99:
741 AppendToBuffer("vfmadd132s%c %s,%s,", float_size_code(),
742 NameOfXMMRegister(regop), NameOfXMMRegister(vvvv));
743 current += PrintRightXMMOperand(current);
744 break;
745 case 0xA9:
746 AppendToBuffer("vfmadd213s%c %s,%s,", float_size_code(),
747 NameOfXMMRegister(regop), NameOfXMMRegister(vvvv));
748 current += PrintRightXMMOperand(current);
749 break;
750 case 0xB9:
751 AppendToBuffer("vfmadd231s%c %s,%s,", float_size_code(),
752 NameOfXMMRegister(regop), NameOfXMMRegister(vvvv));
753 current += PrintRightXMMOperand(current);
754 break;
755 case 0x9B:
756 AppendToBuffer("vfmsub132s%c %s,%s,", float_size_code(),
757 NameOfXMMRegister(regop), NameOfXMMRegister(vvvv));
758 current += PrintRightXMMOperand(current);
759 break;
760 case 0xAB:
761 AppendToBuffer("vfmsub213s%c %s,%s,", float_size_code(),
762 NameOfXMMRegister(regop), NameOfXMMRegister(vvvv));
763 current += PrintRightXMMOperand(current);
764 break;
765 case 0xBB:
766 AppendToBuffer("vfmsub231s%c %s,%s,", float_size_code(),
767 NameOfXMMRegister(regop), NameOfXMMRegister(vvvv));
768 current += PrintRightXMMOperand(current);
769 break;
770 case 0x9D:
771 AppendToBuffer("vfnmadd132s%c %s,%s,", float_size_code(),
772 NameOfXMMRegister(regop), NameOfXMMRegister(vvvv));
773 current += PrintRightXMMOperand(current);
774 break;
775 case 0xAD:
776 AppendToBuffer("vfnmadd213s%c %s,%s,", float_size_code(),
777 NameOfXMMRegister(regop), NameOfXMMRegister(vvvv));
778 current += PrintRightXMMOperand(current);
779 break;
780 case 0xBD:
781 AppendToBuffer("vfnmadd231s%c %s,%s,", float_size_code(),
782 NameOfXMMRegister(regop), NameOfXMMRegister(vvvv));
783 current += PrintRightXMMOperand(current);
784 break;
785 case 0x9F:
786 AppendToBuffer("vfnmsub132s%c %s,%s,", float_size_code(),
787 NameOfXMMRegister(regop), NameOfXMMRegister(vvvv));
788 current += PrintRightXMMOperand(current);
789 break;
790 case 0xAF:
791 AppendToBuffer("vfnmsub213s%c %s,%s,", float_size_code(),
792 NameOfXMMRegister(regop), NameOfXMMRegister(vvvv));
793 current += PrintRightXMMOperand(current);
794 break;
795 case 0xBF:
796 AppendToBuffer("vfnmsub231s%c %s,%s,", float_size_code(),
797 NameOfXMMRegister(regop), NameOfXMMRegister(vvvv));
798 current += PrintRightXMMOperand(current);
799 break;
800 case 0xF7:
801 AppendToBuffer("shlx %s,", NameOfCPURegister(regop));
802 current += PrintRightOperand(current);
803 AppendToBuffer(",%s", NameOfCPURegister(vvvv));
804 break;
805 #define DECLARE_SSE_AVX_DIS_CASE(instruction, notUsed1, notUsed2, notUsed3, \
806 opcode) \
807 case 0x##opcode: { \
808 AppendToBuffer("v" #instruction " %s,%s,", NameOfXMMRegister(regop), \
809 NameOfXMMRegister(vvvv)); \
810 current += PrintRightXMMOperand(current); \
811 break; \
812 }
813
814 SSSE3_INSTRUCTION_LIST(DECLARE_SSE_AVX_DIS_CASE)
815 SSE4_INSTRUCTION_LIST(DECLARE_SSE_AVX_DIS_CASE)
816 #undef DECLARE_SSE_AVX_DIS_CASE
817 #define DECLARE_SSE_AVX_RM_DIS_CASE(instruction, notUsed1, notUsed2, notUsed3, \
818 opcode) \
819 case 0x##opcode: { \
820 AppendToBuffer("v" #instruction " %s,", NameOfXMMRegister(regop)); \
821 current += PrintRightXMMOperand(current); \
822 break; \
823 }
824
825 SSE4_RM_INSTRUCTION_LIST(DECLARE_SSE_AVX_RM_DIS_CASE)
826 #undef DECLARE_SSE_AVX_RM_DIS_CASE
827 default:
828 UnimplementedInstruction();
829 }
830 } else if (vex_66() && vex_0f3a()) {
831 int mod, regop, rm, vvvv = vex_vreg();
832 get_modrm(*current, &mod, ®op, &rm);
833 switch (opcode) {
834 case 0x0E:
835 AppendToBuffer("vpblendw %s,%s,", NameOfXMMRegister(regop),
836 NameOfXMMRegister(vvvv));
837 current += PrintRightXMMOperand(current);
838 AppendToBuffer(",%d", *reinterpret_cast<uint8_t*>(current));
839 current++;
840 break;
841 case 0x0F:
842 AppendToBuffer("vpalignr %s,%s,", NameOfXMMRegister(regop),
843 NameOfXMMRegister(vvvv));
844 current += PrintRightXMMOperand(current);
845 AppendToBuffer(",%d", *reinterpret_cast<uint8_t*>(current));
846 current++;
847 break;
848 case 0x14:
849 AppendToBuffer("vpextrb ");
850 current += PrintRightOperand(current);
851 AppendToBuffer(",%s,%d", NameOfXMMRegister(regop),
852 *reinterpret_cast<int8_t*>(current));
853 current++;
854 break;
855 case 0x15:
856 AppendToBuffer("vpextrw ");
857 current += PrintRightOperand(current);
858 AppendToBuffer(",%s,%d", NameOfXMMRegister(regop),
859 *reinterpret_cast<int8_t*>(current));
860 current++;
861 break;
862 case 0x16:
863 AppendToBuffer("vpextrd ");
864 current += PrintRightOperand(current);
865 AppendToBuffer(",%s,%d", NameOfXMMRegister(regop),
866 *reinterpret_cast<int8_t*>(current));
867 current++;
868 break;
869 case 0x20:
870 AppendToBuffer("vpinsrb %s,%s,", NameOfXMMRegister(regop),
871 NameOfXMMRegister(vvvv));
872 current += PrintRightOperand(current);
873 AppendToBuffer(",%d", *reinterpret_cast<int8_t*>(current));
874 current++;
875 break;
876 case 0x21:
877 AppendToBuffer("vinsertps %s,%s,", NameOfXMMRegister(regop),
878 NameOfXMMRegister(vvvv));
879 current += PrintRightXMMOperand(current);
880 AppendToBuffer(",%d", *reinterpret_cast<int8_t*>(current));
881 current++;
882 break;
883 case 0x22:
884 AppendToBuffer("vpinsrd %s,%s,", NameOfXMMRegister(regop),
885 NameOfXMMRegister(vvvv));
886 current += PrintRightOperand(current);
887 AppendToBuffer(",%d", *reinterpret_cast<int8_t*>(current));
888 current++;
889 break;
890 default:
891 UnimplementedInstruction();
892 }
893 } else if (vex_f2() && vex_0f()) {
894 int mod, regop, rm, vvvv = vex_vreg();
895 get_modrm(*current, &mod, ®op, &rm);
896 switch (opcode) {
897 case 0x51:
898 AppendToBuffer("vsqrtsd %s,%s,", NameOfXMMRegister(regop),
899 NameOfXMMRegister(vvvv));
900 current += PrintRightXMMOperand(current);
901 break;
902 case 0x58:
903 AppendToBuffer("vaddsd %s,%s,", NameOfXMMRegister(regop),
904 NameOfXMMRegister(vvvv));
905 current += PrintRightXMMOperand(current);
906 break;
907 case 0x59:
908 AppendToBuffer("vmulsd %s,%s,", NameOfXMMRegister(regop),
909 NameOfXMMRegister(vvvv));
910 current += PrintRightXMMOperand(current);
911 break;
912 case 0x5C:
913 AppendToBuffer("vsubsd %s,%s,", NameOfXMMRegister(regop),
914 NameOfXMMRegister(vvvv));
915 current += PrintRightXMMOperand(current);
916 break;
917 case 0x5D:
918 AppendToBuffer("vminsd %s,%s,", NameOfXMMRegister(regop),
919 NameOfXMMRegister(vvvv));
920 current += PrintRightXMMOperand(current);
921 break;
922 case 0x5E:
923 AppendToBuffer("vdivsd %s,%s,", NameOfXMMRegister(regop),
924 NameOfXMMRegister(vvvv));
925 current += PrintRightXMMOperand(current);
926 break;
927 case 0x5F:
928 AppendToBuffer("vmaxsd %s,%s,", NameOfXMMRegister(regop),
929 NameOfXMMRegister(vvvv));
930 current += PrintRightXMMOperand(current);
931 break;
932 case 0x70:
933 AppendToBuffer("vpshuflw %s,", NameOfXMMRegister(regop));
934 current += PrintRightXMMOperand(current);
935 AppendToBuffer(",%d", *reinterpret_cast<int8_t*>(current));
936 current++;
937 break;
938 case 0x7C:
939 AppendToBuffer("vhaddps %s,%s,", NameOfXMMRegister(regop),
940 NameOfXMMRegister(vvvv));
941 current += PrintRightXMMOperand(current);
942 break;
943 default:
944 UnimplementedInstruction();
945 }
946 } else if (vex_f3() && vex_0f()) {
947 int mod, regop, rm, vvvv = vex_vreg();
948 get_modrm(*current, &mod, ®op, &rm);
949 switch (opcode) {
950 case 0x51:
951 AppendToBuffer("vsqrtss %s,%s,", NameOfXMMRegister(regop),
952 NameOfXMMRegister(vvvv));
953 current += PrintRightXMMOperand(current);
954 break;
955 case 0x58:
956 AppendToBuffer("vaddss %s,%s,", NameOfXMMRegister(regop),
957 NameOfXMMRegister(vvvv));
958 current += PrintRightXMMOperand(current);
959 break;
960 case 0x59:
961 AppendToBuffer("vmulss %s,%s,", NameOfXMMRegister(regop),
962 NameOfXMMRegister(vvvv));
963 current += PrintRightXMMOperand(current);
964 break;
965 case 0x5B:
966 AppendToBuffer("vcvttps2dq %s,", NameOfXMMRegister(regop));
967 current += PrintRightXMMOperand(current);
968 break;
969 case 0x5C:
970 AppendToBuffer("vsubss %s,%s,", NameOfXMMRegister(regop),
971 NameOfXMMRegister(vvvv));
972 current += PrintRightXMMOperand(current);
973 break;
974 case 0x5D:
975 AppendToBuffer("vminss %s,%s,", NameOfXMMRegister(regop),
976 NameOfXMMRegister(vvvv));
977 current += PrintRightXMMOperand(current);
978 break;
979 case 0x5E:
980 AppendToBuffer("vdivss %s,%s,", NameOfXMMRegister(regop),
981 NameOfXMMRegister(vvvv));
982 current += PrintRightXMMOperand(current);
983 break;
984 case 0x5F:
985 AppendToBuffer("vmaxss %s,%s,", NameOfXMMRegister(regop),
986 NameOfXMMRegister(vvvv));
987 current += PrintRightXMMOperand(current);
988 break;
989 case 0x6f:
990 AppendToBuffer("vmovdqu %s,", NameOfXMMRegister(regop));
991 current += PrintRightOperand(current);
992 break;
993 case 0x70:
994 AppendToBuffer("vpshufhw %s,", NameOfXMMRegister(regop));
995 current += PrintRightXMMOperand(current);
996 AppendToBuffer(",%d", *reinterpret_cast<int8_t*>(current));
997 current++;
998 break;
999 case 0x7f:
1000 AppendToBuffer("vmovdqu ");
1001 current += PrintRightOperand(current);
1002 AppendToBuffer(",%s", NameOfXMMRegister(regop));
1003 break;
1004 default:
1005 UnimplementedInstruction();
1006 }
1007 } else if (vex_none() && vex_0f38()) {
1008 int mod, regop, rm, vvvv = vex_vreg();
1009 get_modrm(*current, &mod, ®op, &rm);
1010 const char* mnem = "?";
1011 switch (opcode) {
1012 case 0xF2:
1013 AppendToBuffer("andn %s,%s,", NameOfCPURegister(regop),
1014 NameOfCPURegister(vvvv));
1015 current += PrintRightOperand(current);
1016 break;
1017 case 0xF5:
1018 AppendToBuffer("bzhi %s,", NameOfCPURegister(regop));
1019 current += PrintRightOperand(current);
1020 AppendToBuffer(",%s", NameOfCPURegister(vvvv));
1021 break;
1022 case 0xF7:
1023 AppendToBuffer("bextr %s,", NameOfCPURegister(regop));
1024 current += PrintRightOperand(current);
1025 AppendToBuffer(",%s", NameOfCPURegister(vvvv));
1026 break;
1027 case 0xF3:
1028 switch (regop) {
1029 case 1:
1030 mnem = "blsr";
1031 break;
1032 case 2:
1033 mnem = "blsmsk";
1034 break;
1035 case 3:
1036 mnem = "blsi";
1037 break;
1038 default:
1039 UnimplementedInstruction();
1040 }
1041 AppendToBuffer("%s %s,", mnem, NameOfCPURegister(vvvv));
1042 current += PrintRightOperand(current);
1043 mnem = "?";
1044 break;
1045 default:
1046 UnimplementedInstruction();
1047 }
1048 } else if (vex_f2() && vex_0f38()) {
1049 int mod, regop, rm, vvvv = vex_vreg();
1050 get_modrm(*current, &mod, ®op, &rm);
1051 switch (opcode) {
1052 case 0xF5:
1053 AppendToBuffer("pdep %s,%s,", NameOfCPURegister(regop),
1054 NameOfCPURegister(vvvv));
1055 current += PrintRightOperand(current);
1056 break;
1057 case 0xF6:
1058 AppendToBuffer("mulx %s,%s,", NameOfCPURegister(regop),
1059 NameOfCPURegister(vvvv));
1060 current += PrintRightOperand(current);
1061 break;
1062 case 0xF7:
1063 AppendToBuffer("shrx %s,", NameOfCPURegister(regop));
1064 current += PrintRightOperand(current);
1065 AppendToBuffer(",%s", NameOfCPURegister(vvvv));
1066 break;
1067 default:
1068 UnimplementedInstruction();
1069 }
1070 } else if (vex_f3() && vex_0f38()) {
1071 int mod, regop, rm, vvvv = vex_vreg();
1072 get_modrm(*current, &mod, ®op, &rm);
1073 switch (opcode) {
1074 case 0xF5:
1075 AppendToBuffer("pext %s,%s,", NameOfCPURegister(regop),
1076 NameOfCPURegister(vvvv));
1077 current += PrintRightOperand(current);
1078 break;
1079 case 0xF7:
1080 AppendToBuffer("sarx %s,", NameOfCPURegister(regop));
1081 current += PrintRightOperand(current);
1082 AppendToBuffer(",%s", NameOfCPURegister(vvvv));
1083 break;
1084 default:
1085 UnimplementedInstruction();
1086 }
1087 } else if (vex_f2() && vex_0f3a()) {
1088 int mod, regop, rm;
1089 get_modrm(*current, &mod, ®op, &rm);
1090 switch (opcode) {
1091 case 0xF0:
1092 AppendToBuffer("rorx %s,", NameOfCPURegister(regop));
1093 current += PrintRightOperand(current);
1094 AppendToBuffer(",%d", *current & 0x1F);
1095 current += 1;
1096 break;
1097 default:
1098 UnimplementedInstruction();
1099 }
1100 } else if (vex_none() && vex_0f()) {
1101 int mod, regop, rm, vvvv = vex_vreg();
1102 get_modrm(*current, &mod, ®op, &rm);
1103 switch (opcode) {
1104 case 0x28:
1105 AppendToBuffer("vmovaps %s,", NameOfXMMRegister(regop));
1106 current += PrintRightXMMOperand(current);
1107 break;
1108 case 0x52:
1109 AppendToBuffer("vrsqrtps %s,", NameOfXMMRegister(regop));
1110 current += PrintRightXMMOperand(current);
1111 break;
1112 case 0x53:
1113 AppendToBuffer("vrcpps %s,", NameOfXMMRegister(regop));
1114 current += PrintRightXMMOperand(current);
1115 break;
1116 case 0x54:
1117 AppendToBuffer("vandps %s,%s,", NameOfXMMRegister(regop),
1118 NameOfXMMRegister(vvvv));
1119 current += PrintRightXMMOperand(current);
1120 break;
1121 case 0x57:
1122 AppendToBuffer("vxorps %s,%s,", NameOfXMMRegister(regop),
1123 NameOfXMMRegister(vvvv));
1124 current += PrintRightXMMOperand(current);
1125 break;
1126 case 0x58:
1127 AppendToBuffer("vaddps %s,%s,", NameOfXMMRegister(regop),
1128 NameOfXMMRegister(vvvv));
1129 current += PrintRightXMMOperand(current);
1130 break;
1131 case 0x59:
1132 AppendToBuffer("vmulps %s,%s,", NameOfXMMRegister(regop),
1133 NameOfXMMRegister(vvvv));
1134 current += PrintRightXMMOperand(current);
1135 break;
1136 case 0x5B:
1137 AppendToBuffer("vcvtdq2ps %s,", NameOfXMMRegister(regop));
1138 current += PrintRightXMMOperand(current);
1139 break;
1140 case 0x5C:
1141 AppendToBuffer("vsubps %s,%s,", NameOfXMMRegister(regop),
1142 NameOfXMMRegister(vvvv));
1143 current += PrintRightXMMOperand(current);
1144 break;
1145 case 0x5D:
1146 AppendToBuffer("vminps %s,%s,", NameOfXMMRegister(regop),
1147 NameOfXMMRegister(vvvv));
1148 current += PrintRightXMMOperand(current);
1149 break;
1150 case 0x5E:
1151 AppendToBuffer("vdivps %s,%s,", NameOfXMMRegister(regop),
1152 NameOfXMMRegister(vvvv));
1153 current += PrintRightXMMOperand(current);
1154 break;
1155 case 0x5F:
1156 AppendToBuffer("vmaxps %s,%s,", NameOfXMMRegister(regop),
1157 NameOfXMMRegister(vvvv));
1158 current += PrintRightXMMOperand(current);
1159 break;
1160 case 0xC2: {
1161 const char* const pseudo_op[] = {"eq", "lt", "le", "unord",
1162 "neq", "nlt", "nle", "ord"};
1163 AppendToBuffer("vcmpps %s,%s,", NameOfXMMRegister(regop),
1164 NameOfXMMRegister(vvvv));
1165 current += PrintRightXMMOperand(current);
1166 AppendToBuffer(", (%s)", pseudo_op[*current]);
1167 current++;
1168 break;
1169 }
1170 case 0xC6:
1171 AppendToBuffer("vshufps %s,%s,", NameOfXMMRegister(regop),
1172 NameOfXMMRegister(vvvv));
1173 current += PrintRightXMMOperand(current);
1174 AppendToBuffer(", %d", (*current) & 3);
1175 current += 1;
1176 break;
1177 default:
1178 UnimplementedInstruction();
1179 }
1180 } else if (vex_66() && vex_0f()) {
1181 int mod, regop, rm, vvvv = vex_vreg();
1182 get_modrm(*current, &mod, ®op, &rm);
1183 switch (opcode) {
1184 case 0x54:
1185 AppendToBuffer("vandpd %s,%s,", NameOfXMMRegister(regop),
1186 NameOfXMMRegister(vvvv));
1187 current += PrintRightXMMOperand(current);
1188 break;
1189 case 0x57:
1190 AppendToBuffer("vxorpd %s,%s,", NameOfXMMRegister(regop),
1191 NameOfXMMRegister(vvvv));
1192 current += PrintRightXMMOperand(current);
1193 break;
1194 case 0x58:
1195 AppendToBuffer("vaddpd %s,%s,", NameOfXMMRegister(regop),
1196 NameOfXMMRegister(vvvv));
1197 current += PrintRightXMMOperand(current);
1198 break;
1199 case 0x59:
1200 AppendToBuffer("vmulpd %s,%s,", NameOfXMMRegister(regop),
1201 NameOfXMMRegister(vvvv));
1202 current += PrintRightXMMOperand(current);
1203 break;
1204 case 0x5C:
1205 AppendToBuffer("vsubpd %s,%s,", NameOfXMMRegister(regop),
1206 NameOfXMMRegister(vvvv));
1207 current += PrintRightXMMOperand(current);
1208 break;
1209 case 0x5D:
1210 AppendToBuffer("vminpd %s,%s,", NameOfXMMRegister(regop),
1211 NameOfXMMRegister(vvvv));
1212 current += PrintRightXMMOperand(current);
1213 break;
1214 case 0x5E:
1215 AppendToBuffer("vdivpd %s,%s,", NameOfXMMRegister(regop),
1216 NameOfXMMRegister(vvvv));
1217 current += PrintRightXMMOperand(current);
1218 break;
1219 case 0x5F:
1220 AppendToBuffer("vmaxpd %s,%s,", NameOfXMMRegister(regop),
1221 NameOfXMMRegister(vvvv));
1222 current += PrintRightXMMOperand(current);
1223 break;
1224 case 0x6E:
1225 AppendToBuffer("vmovd %s,", NameOfXMMRegister(regop));
1226 current += PrintRightOperand(current);
1227 break;
1228 case 0x70:
1229 AppendToBuffer("vpshufd %s,", NameOfXMMRegister(regop));
1230 current += PrintRightXMMOperand(current);
1231 AppendToBuffer(",%d", *reinterpret_cast<int8_t*>(current));
1232 current++;
1233 break;
1234 case 0x71:
1235 AppendToBuffer("vps%sw %s,%s", sf_str[regop / 2],
1236 NameOfXMMRegister(vvvv), NameOfXMMRegister(rm));
1237 current++;
1238 AppendToBuffer(",%u", *current++);
1239 break;
1240 case 0x72:
1241 AppendToBuffer("vps%sd %s,%s", sf_str[regop / 2],
1242 NameOfXMMRegister(vvvv), NameOfXMMRegister(rm));
1243 current++;
1244 AppendToBuffer(",%u", *current++);
1245 break;
1246 case 0x7E:
1247 AppendToBuffer("vmovd ");
1248 current += PrintRightOperand(current);
1249 AppendToBuffer(",%s", NameOfXMMRegister(regop));
1250 break;
1251 case 0xC4:
1252 AppendToBuffer("vpinsrw %s,%s,", NameOfXMMRegister(regop),
1253 NameOfXMMRegister(vvvv));
1254 current += PrintRightOperand(current);
1255 AppendToBuffer(",%d", *reinterpret_cast<int8_t*>(current));
1256 current++;
1257 break;
1258 #define DECLARE_SSE_AVX_DIS_CASE(instruction, notUsed1, notUsed2, opcode) \
1259 case 0x##opcode: { \
1260 AppendToBuffer("v" #instruction " %s,%s,", NameOfXMMRegister(regop), \
1261 NameOfXMMRegister(vvvv)); \
1262 current += PrintRightXMMOperand(current); \
1263 break; \
1264 }
1265
1266 SSE2_INSTRUCTION_LIST(DECLARE_SSE_AVX_DIS_CASE)
1267 #undef DECLARE_SSE_AVX_DIS_CASE
1268 default:
1269 UnimplementedInstruction();
1270 }
1271 } else {
1272 UnimplementedInstruction();
1273 }
1274
1275 return static_cast<int>(current - data);
1276 }
1277
1278
1279 // Returns number of bytes used, including *data.
FPUInstruction(byte * data)1280 int DisassemblerIA32::FPUInstruction(byte* data) {
1281 byte escape_opcode = *data;
1282 DCHECK_EQ(0xD8, escape_opcode & 0xF8);
1283 byte modrm_byte = *(data+1);
1284
1285 if (modrm_byte >= 0xC0) {
1286 return RegisterFPUInstruction(escape_opcode, modrm_byte);
1287 } else {
1288 return MemoryFPUInstruction(escape_opcode, modrm_byte, data+1);
1289 }
1290 }
1291
MemoryFPUInstruction(int escape_opcode,int modrm_byte,byte * modrm_start)1292 int DisassemblerIA32::MemoryFPUInstruction(int escape_opcode,
1293 int modrm_byte,
1294 byte* modrm_start) {
1295 const char* mnem = "?";
1296 int regop = (modrm_byte >> 3) & 0x7; // reg/op field of modrm byte.
1297 switch (escape_opcode) {
1298 case 0xD9: switch (regop) {
1299 case 0: mnem = "fld_s"; break;
1300 case 2: mnem = "fst_s"; break;
1301 case 3: mnem = "fstp_s"; break;
1302 case 7: mnem = "fstcw"; break;
1303 default: UnimplementedInstruction();
1304 }
1305 break;
1306
1307 case 0xDB: switch (regop) {
1308 case 0: mnem = "fild_s"; break;
1309 case 1: mnem = "fisttp_s"; break;
1310 case 2: mnem = "fist_s"; break;
1311 case 3: mnem = "fistp_s"; break;
1312 default: UnimplementedInstruction();
1313 }
1314 break;
1315
1316 case 0xDD: switch (regop) {
1317 case 0: mnem = "fld_d"; break;
1318 case 1: mnem = "fisttp_d"; break;
1319 case 2: mnem = "fst_d"; break;
1320 case 3: mnem = "fstp_d"; break;
1321 default: UnimplementedInstruction();
1322 }
1323 break;
1324
1325 case 0xDF: switch (regop) {
1326 case 5: mnem = "fild_d"; break;
1327 case 7: mnem = "fistp_d"; break;
1328 default: UnimplementedInstruction();
1329 }
1330 break;
1331
1332 default: UnimplementedInstruction();
1333 }
1334 AppendToBuffer("%s ", mnem);
1335 int count = PrintRightOperand(modrm_start);
1336 return count + 1;
1337 }
1338
RegisterFPUInstruction(int escape_opcode,byte modrm_byte)1339 int DisassemblerIA32::RegisterFPUInstruction(int escape_opcode,
1340 byte modrm_byte) {
1341 bool has_register = false; // Is the FPU register encoded in modrm_byte?
1342 const char* mnem = "?";
1343
1344 switch (escape_opcode) {
1345 case 0xD8:
1346 has_register = true;
1347 switch (modrm_byte & 0xF8) {
1348 case 0xC0: mnem = "fadd_i"; break;
1349 case 0xE0: mnem = "fsub_i"; break;
1350 case 0xC8: mnem = "fmul_i"; break;
1351 case 0xF0: mnem = "fdiv_i"; break;
1352 default: UnimplementedInstruction();
1353 }
1354 break;
1355
1356 case 0xD9:
1357 switch (modrm_byte & 0xF8) {
1358 case 0xC0:
1359 mnem = "fld";
1360 has_register = true;
1361 break;
1362 case 0xC8:
1363 mnem = "fxch";
1364 has_register = true;
1365 break;
1366 default:
1367 switch (modrm_byte) {
1368 case 0xE0: mnem = "fchs"; break;
1369 case 0xE1: mnem = "fabs"; break;
1370 case 0xE4: mnem = "ftst"; break;
1371 case 0xE8: mnem = "fld1"; break;
1372 case 0xEB: mnem = "fldpi"; break;
1373 case 0xED: mnem = "fldln2"; break;
1374 case 0xEE: mnem = "fldz"; break;
1375 case 0xF0: mnem = "f2xm1"; break;
1376 case 0xF1: mnem = "fyl2x"; break;
1377 case 0xF4: mnem = "fxtract"; break;
1378 case 0xF5: mnem = "fprem1"; break;
1379 case 0xF7: mnem = "fincstp"; break;
1380 case 0xF8: mnem = "fprem"; break;
1381 case 0xFC: mnem = "frndint"; break;
1382 case 0xFD: mnem = "fscale"; break;
1383 case 0xFE: mnem = "fsin"; break;
1384 case 0xFF: mnem = "fcos"; break;
1385 default: UnimplementedInstruction();
1386 }
1387 }
1388 break;
1389
1390 case 0xDA:
1391 if (modrm_byte == 0xE9) {
1392 mnem = "fucompp";
1393 } else {
1394 UnimplementedInstruction();
1395 }
1396 break;
1397
1398 case 0xDB:
1399 if ((modrm_byte & 0xF8) == 0xE8) {
1400 mnem = "fucomi";
1401 has_register = true;
1402 } else if (modrm_byte == 0xE2) {
1403 mnem = "fclex";
1404 } else if (modrm_byte == 0xE3) {
1405 mnem = "fninit";
1406 } else {
1407 UnimplementedInstruction();
1408 }
1409 break;
1410
1411 case 0xDC:
1412 has_register = true;
1413 switch (modrm_byte & 0xF8) {
1414 case 0xC0: mnem = "fadd"; break;
1415 case 0xE8: mnem = "fsub"; break;
1416 case 0xC8: mnem = "fmul"; break;
1417 case 0xF8: mnem = "fdiv"; break;
1418 default: UnimplementedInstruction();
1419 }
1420 break;
1421
1422 case 0xDD:
1423 has_register = true;
1424 switch (modrm_byte & 0xF8) {
1425 case 0xC0: mnem = "ffree"; break;
1426 case 0xD0: mnem = "fst"; break;
1427 case 0xD8: mnem = "fstp"; break;
1428 default: UnimplementedInstruction();
1429 }
1430 break;
1431
1432 case 0xDE:
1433 if (modrm_byte == 0xD9) {
1434 mnem = "fcompp";
1435 } else {
1436 has_register = true;
1437 switch (modrm_byte & 0xF8) {
1438 case 0xC0: mnem = "faddp"; break;
1439 case 0xE8: mnem = "fsubp"; break;
1440 case 0xC8: mnem = "fmulp"; break;
1441 case 0xF8: mnem = "fdivp"; break;
1442 default: UnimplementedInstruction();
1443 }
1444 }
1445 break;
1446
1447 case 0xDF:
1448 if (modrm_byte == 0xE0) {
1449 mnem = "fnstsw_ax";
1450 } else if ((modrm_byte & 0xF8) == 0xE8) {
1451 mnem = "fucomip";
1452 has_register = true;
1453 }
1454 break;
1455
1456 default: UnimplementedInstruction();
1457 }
1458
1459 if (has_register) {
1460 AppendToBuffer("%s st%d", mnem, modrm_byte & 0x7);
1461 } else {
1462 AppendToBuffer("%s", mnem);
1463 }
1464 return 2;
1465 }
1466
1467 // Mnemonics for instructions 0xF0 byte.
1468 // Returns nullptr if the instruction is not handled here.
F0Mnem(byte f0byte)1469 static const char* F0Mnem(byte f0byte) {
1470 switch (f0byte) {
1471 case 0x0B:
1472 return "ud2";
1473 case 0x18:
1474 return "prefetch";
1475 case 0xA2:
1476 return "cpuid";
1477 case 0xBE:
1478 return "movsx_b";
1479 case 0xBF:
1480 return "movsx_w";
1481 case 0xB6:
1482 return "movzx_b";
1483 case 0xB7:
1484 return "movzx_w";
1485 case 0xAF:
1486 return "imul";
1487 case 0xA4:
1488 return "shld";
1489 case 0xA5:
1490 return "shld";
1491 case 0xAD:
1492 return "shrd";
1493 case 0xAC:
1494 return "shrd"; // 3-operand version.
1495 case 0xAB:
1496 return "bts";
1497 case 0xB0:
1498 return "cmpxchg_b";
1499 case 0xB1:
1500 return "cmpxchg";
1501 case 0xBC:
1502 return "bsf";
1503 case 0xBD:
1504 return "bsr";
1505 case 0xC7:
1506 return "cmpxchg8b";
1507 default:
1508 return nullptr;
1509 }
1510 }
1511
1512
1513 // Disassembled instruction '*instr' and writes it into 'out_buffer'.
InstructionDecode(v8::internal::Vector<char> out_buffer,byte * instr)1514 int DisassemblerIA32::InstructionDecode(v8::internal::Vector<char> out_buffer,
1515 byte* instr) {
1516 tmp_buffer_pos_ = 0; // starting to write as position 0
1517 byte* data = instr;
1518 // Check for hints.
1519 const char* branch_hint = nullptr;
1520 // We use these two prefixes only with branch prediction
1521 if (*data == 0x3E /*ds*/) {
1522 branch_hint = "predicted taken";
1523 data++;
1524 } else if (*data == 0x2E /*cs*/) {
1525 branch_hint = "predicted not taken";
1526 data++;
1527 } else if (*data == 0xC4 && *(data + 1) >= 0xC0) {
1528 vex_byte0_ = *data;
1529 vex_byte1_ = *(data + 1);
1530 vex_byte2_ = *(data + 2);
1531 data += 3;
1532 } else if (*data == 0xC5 && *(data + 1) >= 0xC0) {
1533 vex_byte0_ = *data;
1534 vex_byte1_ = *(data + 1);
1535 data += 2;
1536 } else if (*data == 0xF0 /*lock*/) {
1537 AppendToBuffer("lock ");
1538 data++;
1539 }
1540
1541 bool processed = true; // Will be set to false if the current instruction
1542 // is not in 'instructions' table.
1543 // Decode AVX instructions.
1544 if (vex_byte0_ != 0) {
1545 data += AVXInstruction(data);
1546 } else {
1547 const InstructionDesc& idesc = instruction_table_->Get(*data);
1548 switch (idesc.type) {
1549 case ZERO_OPERANDS_INSTR:
1550 AppendToBuffer("%s", idesc.mnem);
1551 data++;
1552 break;
1553
1554 case TWO_OPERANDS_INSTR:
1555 data++;
1556 data += PrintOperands(idesc.mnem, idesc.op_order_, data);
1557 break;
1558
1559 case JUMP_CONDITIONAL_SHORT_INSTR:
1560 data += JumpConditionalShort(data, branch_hint);
1561 break;
1562
1563 case REGISTER_INSTR:
1564 AppendToBuffer("%s %s", idesc.mnem, NameOfCPURegister(*data & 0x07));
1565 data++;
1566 break;
1567
1568 case MOVE_REG_INSTR: {
1569 byte* addr =
1570 reinterpret_cast<byte*>(*reinterpret_cast<int32_t*>(data + 1));
1571 AppendToBuffer("mov %s,%s", NameOfCPURegister(*data & 0x07),
1572 NameOfAddress(addr));
1573 data += 5;
1574 break;
1575 }
1576
1577 case CALL_JUMP_INSTR: {
1578 byte* addr = data + *reinterpret_cast<int32_t*>(data + 1) + 5;
1579 AppendToBuffer("%s %s", idesc.mnem, NameOfAddress(addr));
1580 data += 5;
1581 break;
1582 }
1583
1584 case SHORT_IMMEDIATE_INSTR: {
1585 byte* addr =
1586 reinterpret_cast<byte*>(*reinterpret_cast<int32_t*>(data + 1));
1587 AppendToBuffer("%s eax,%s", idesc.mnem, NameOfAddress(addr));
1588 data += 5;
1589 break;
1590 }
1591
1592 case BYTE_IMMEDIATE_INSTR: {
1593 AppendToBuffer("%s al,0x%x", idesc.mnem, data[1]);
1594 data += 2;
1595 break;
1596 }
1597
1598 case NO_INSTR:
1599 processed = false;
1600 break;
1601
1602 default:
1603 UNIMPLEMENTED(); // This type is not implemented.
1604 }
1605 }
1606 //----------------------------
1607 if (!processed) {
1608 switch (*data) {
1609 case 0xC2:
1610 AppendToBuffer("ret 0x%x", *reinterpret_cast<uint16_t*>(data+1));
1611 data += 3;
1612 break;
1613
1614 case 0x6B: {
1615 data++;
1616 data += PrintOperands("imul", REG_OPER_OP_ORDER, data);
1617 AppendToBuffer(",%d", *data);
1618 data++;
1619 } break;
1620
1621 case 0x69: {
1622 data++;
1623 data += PrintOperands("imul", REG_OPER_OP_ORDER, data);
1624 AppendToBuffer(",%d", *reinterpret_cast<int32_t*>(data));
1625 data += 4;
1626 }
1627 break;
1628
1629 case 0xF6:
1630 { data++;
1631 int mod, regop, rm;
1632 get_modrm(*data, &mod, ®op, &rm);
1633 if (regop == eax) {
1634 AppendToBuffer("test_b ");
1635 data += PrintRightByteOperand(data);
1636 int32_t imm = *data;
1637 AppendToBuffer(",0x%x", imm);
1638 data++;
1639 } else {
1640 UnimplementedInstruction();
1641 }
1642 }
1643 break;
1644
1645 case 0x81: // fall through
1646 case 0x83: // 0x81 with sign extension bit set
1647 data += PrintImmediateOp(data);
1648 break;
1649
1650 case 0x0F:
1651 { byte f0byte = data[1];
1652 const char* f0mnem = F0Mnem(f0byte);
1653 if (f0byte == 0x18) {
1654 data += 2;
1655 int mod, regop, rm;
1656 get_modrm(*data, &mod, ®op, &rm);
1657 const char* suffix[] = {"nta", "1", "2", "3"};
1658 AppendToBuffer("%s%s ", f0mnem, suffix[regop & 0x03]);
1659 data += PrintRightOperand(data);
1660 } else if (f0byte == 0x1F && data[2] == 0) {
1661 AppendToBuffer("nop"); // 3 byte nop.
1662 data += 3;
1663 } else if (f0byte == 0x1F && data[2] == 0x40 && data[3] == 0) {
1664 AppendToBuffer("nop"); // 4 byte nop.
1665 data += 4;
1666 } else if (f0byte == 0x1F && data[2] == 0x44 && data[3] == 0 &&
1667 data[4] == 0) {
1668 AppendToBuffer("nop"); // 5 byte nop.
1669 data += 5;
1670 } else if (f0byte == 0x1F && data[2] == 0x80 && data[3] == 0 &&
1671 data[4] == 0 && data[5] == 0 && data[6] == 0) {
1672 AppendToBuffer("nop"); // 7 byte nop.
1673 data += 7;
1674 } else if (f0byte == 0x1F && data[2] == 0x84 && data[3] == 0 &&
1675 data[4] == 0 && data[5] == 0 && data[6] == 0 &&
1676 data[7] == 0) {
1677 AppendToBuffer("nop"); // 8 byte nop.
1678 data += 8;
1679 } else if (f0byte == 0x0B || f0byte == 0xA2 || f0byte == 0x31) {
1680 AppendToBuffer("%s", f0mnem);
1681 data += 2;
1682 } else if (f0byte == 0x28) {
1683 data += 2;
1684 int mod, regop, rm;
1685 get_modrm(*data, &mod, ®op, &rm);
1686 AppendToBuffer("movaps %s,%s",
1687 NameOfXMMRegister(regop),
1688 NameOfXMMRegister(rm));
1689 data++;
1690 } else if (f0byte == 0x10 || f0byte == 0x11) {
1691 data += 2;
1692 // movups xmm, xmm/m128
1693 // movups xmm/m128, xmm
1694 int mod, regop, rm;
1695 get_modrm(*data, &mod, ®op, &rm);
1696 AppendToBuffer("movups ");
1697 if (f0byte == 0x11) {
1698 data += PrintRightXMMOperand(data);
1699 AppendToBuffer(",%s", NameOfXMMRegister(regop));
1700 } else {
1701 AppendToBuffer("%s,", NameOfXMMRegister(regop));
1702 data += PrintRightXMMOperand(data);
1703 }
1704 } else if (f0byte == 0x2E) {
1705 data += 2;
1706 int mod, regop, rm;
1707 get_modrm(*data, &mod, ®op, &rm);
1708 AppendToBuffer("ucomiss %s,", NameOfXMMRegister(regop));
1709 data += PrintRightXMMOperand(data);
1710 } else if (f0byte >= 0x52 && f0byte <= 0x5F) {
1711 const char* const pseudo_op[] = {
1712 "rsqrtps", "rcpps", "andps", "andnps", "orps",
1713 "xorps", "addps", "mulps", "cvtps2pd", "cvtdq2ps",
1714 "subps", "minps", "divps", "maxps",
1715 };
1716
1717 data += 2;
1718 int mod, regop, rm;
1719 get_modrm(*data, &mod, ®op, &rm);
1720 AppendToBuffer("%s %s,", pseudo_op[f0byte - 0x52],
1721 NameOfXMMRegister(regop));
1722 data += PrintRightXMMOperand(data);
1723 } else if (f0byte == 0x50) {
1724 data += 2;
1725 int mod, regop, rm;
1726 get_modrm(*data, &mod, ®op, &rm);
1727 AppendToBuffer("movmskps %s,%s",
1728 NameOfCPURegister(regop),
1729 NameOfXMMRegister(rm));
1730 data++;
1731 } else if (f0byte == 0xC2) {
1732 data += 2;
1733 int mod, regop, rm;
1734 get_modrm(*data, &mod, ®op, &rm);
1735 const char* const pseudo_op[] = {"eq", "lt", "le", "unord",
1736 "neq", "nlt", "nle", "ord"};
1737 AppendToBuffer("cmpps %s, ", NameOfXMMRegister(regop));
1738 data += PrintRightXMMOperand(data);
1739 AppendToBuffer(", (%s)", pseudo_op[*data]);
1740 data++;
1741 } else if (f0byte== 0xC6) {
1742 // shufps xmm, xmm/m128, imm8
1743 data += 2;
1744 int mod, regop, rm;
1745 get_modrm(*data, &mod, ®op, &rm);
1746 int8_t imm8 = static_cast<int8_t>(data[1]);
1747 AppendToBuffer("shufps %s,%s,%d",
1748 NameOfXMMRegister(rm),
1749 NameOfXMMRegister(regop),
1750 static_cast<int>(imm8));
1751 data += 2;
1752 } else if (f0byte >= 0xC8 && f0byte <= 0xCF) {
1753 // bswap
1754 data += 2;
1755 int reg = f0byte - 0xC8;
1756 AppendToBuffer("bswap %s", NameOfCPURegister(reg));
1757 } else if ((f0byte & 0xF0) == 0x80) {
1758 data += JumpConditional(data, branch_hint);
1759 } else if (f0byte == 0xBE || f0byte == 0xBF || f0byte == 0xB6 ||
1760 f0byte == 0xB7 || f0byte == 0xAF) {
1761 data += 2;
1762 data += PrintOperands(f0mnem, REG_OPER_OP_ORDER, data);
1763 } else if ((f0byte & 0xF0) == 0x90) {
1764 data += SetCC(data);
1765 } else if ((f0byte & 0xF0) == 0x40) {
1766 data += CMov(data);
1767 } else if (f0byte == 0xA4 || f0byte == 0xAC) {
1768 // shld, shrd
1769 data += 2;
1770 AppendToBuffer("%s ", f0mnem);
1771 int mod, regop, rm;
1772 get_modrm(*data, &mod, ®op, &rm);
1773 int8_t imm8 = static_cast<int8_t>(data[1]);
1774 data += 2;
1775 AppendToBuffer("%s,%s,%d", NameOfCPURegister(rm),
1776 NameOfCPURegister(regop), static_cast<int>(imm8));
1777 } else if (f0byte == 0xAB || f0byte == 0xA5 || f0byte == 0xAD) {
1778 // shrd_cl, shld_cl, bts
1779 data += 2;
1780 AppendToBuffer("%s ", f0mnem);
1781 int mod, regop, rm;
1782 get_modrm(*data, &mod, ®op, &rm);
1783 data += PrintRightOperand(data);
1784 if (f0byte == 0xAB) {
1785 AppendToBuffer(",%s", NameOfCPURegister(regop));
1786 } else {
1787 AppendToBuffer(",%s,cl", NameOfCPURegister(regop));
1788 }
1789 } else if (f0byte == 0xB0) {
1790 // cmpxchg_b
1791 data += 2;
1792 AppendToBuffer("%s ", f0mnem);
1793 int mod, regop, rm;
1794 get_modrm(*data, &mod, ®op, &rm);
1795 data += PrintRightOperand(data);
1796 AppendToBuffer(",%s", NameOfByteCPURegister(regop));
1797 } else if (f0byte == 0xB1) {
1798 // cmpxchg
1799 data += 2;
1800 data += PrintOperands(f0mnem, OPER_REG_OP_ORDER, data);
1801 } else if (f0byte == 0xBC) {
1802 data += 2;
1803 int mod, regop, rm;
1804 get_modrm(*data, &mod, ®op, &rm);
1805 AppendToBuffer("%s %s,", f0mnem, NameOfCPURegister(regop));
1806 data += PrintRightOperand(data);
1807 } else if (f0byte == 0xBD) {
1808 data += 2;
1809 int mod, regop, rm;
1810 get_modrm(*data, &mod, ®op, &rm);
1811 AppendToBuffer("%s %s,", f0mnem, NameOfCPURegister(regop));
1812 data += PrintRightOperand(data);
1813 } else if (f0byte == 0xC7) {
1814 // cmpxchg8b
1815 data += 2;
1816 AppendToBuffer("%s ", f0mnem);
1817 int mod, regop, rm;
1818 get_modrm(*data, &mod, ®op, &rm);
1819 data += PrintRightOperand(data);
1820 } else if (f0byte == 0xAE && (data[2] & 0xF8) == 0xE8) {
1821 AppendToBuffer("lfence");
1822 data += 3;
1823 } else {
1824 UnimplementedInstruction();
1825 }
1826 }
1827 break;
1828
1829 case 0x8F:
1830 { data++;
1831 int mod, regop, rm;
1832 get_modrm(*data, &mod, ®op, &rm);
1833 if (regop == eax) {
1834 AppendToBuffer("pop ");
1835 data += PrintRightOperand(data);
1836 }
1837 }
1838 break;
1839
1840 case 0xFF:
1841 { data++;
1842 int mod, regop, rm;
1843 get_modrm(*data, &mod, ®op, &rm);
1844 const char* mnem = nullptr;
1845 switch (regop) {
1846 case esi: mnem = "push"; break;
1847 case eax: mnem = "inc"; break;
1848 case ecx: mnem = "dec"; break;
1849 case edx: mnem = "call"; break;
1850 case esp: mnem = "jmp"; break;
1851 default: mnem = "???";
1852 }
1853 AppendToBuffer("%s ", mnem);
1854 data += PrintRightOperand(data);
1855 }
1856 break;
1857
1858 case 0xC7: // imm32, fall through
1859 case 0xC6: // imm8
1860 { bool is_byte = *data == 0xC6;
1861 data++;
1862 if (is_byte) {
1863 AppendToBuffer("%s ", "mov_b");
1864 data += PrintRightByteOperand(data);
1865 int32_t imm = *data;
1866 AppendToBuffer(",0x%x", imm);
1867 data++;
1868 } else {
1869 AppendToBuffer("%s ", "mov");
1870 data += PrintRightOperand(data);
1871 int32_t imm = *reinterpret_cast<int32_t*>(data);
1872 AppendToBuffer(",0x%x", imm);
1873 data += 4;
1874 }
1875 }
1876 break;
1877
1878 case 0x80:
1879 { data++;
1880 int mod, regop, rm;
1881 get_modrm(*data, &mod, ®op, &rm);
1882 const char* mnem = nullptr;
1883 switch (regop) {
1884 case 5: mnem = "subb"; break;
1885 case 7: mnem = "cmpb"; break;
1886 default: UnimplementedInstruction();
1887 }
1888 AppendToBuffer("%s ", mnem);
1889 data += PrintRightByteOperand(data);
1890 int32_t imm = *data;
1891 AppendToBuffer(",0x%x", imm);
1892 data++;
1893 }
1894 break;
1895
1896 case 0x88: // 8bit, fall through
1897 case 0x89: // 32bit
1898 { bool is_byte = *data == 0x88;
1899 int mod, regop, rm;
1900 data++;
1901 get_modrm(*data, &mod, ®op, &rm);
1902 if (is_byte) {
1903 AppendToBuffer("%s ", "mov_b");
1904 data += PrintRightByteOperand(data);
1905 AppendToBuffer(",%s", NameOfByteCPURegister(regop));
1906 } else {
1907 AppendToBuffer("%s ", "mov");
1908 data += PrintRightOperand(data);
1909 AppendToBuffer(",%s", NameOfCPURegister(regop));
1910 }
1911 }
1912 break;
1913
1914 case 0x66: // prefix
1915 while (*data == 0x66) data++;
1916 if (*data == 0xF && data[1] == 0x1F) {
1917 AppendToBuffer("nop"); // 0x66 prefix
1918 } else if (*data == 0x39) {
1919 data++;
1920 data += PrintOperands("cmpw", OPER_REG_OP_ORDER, data);
1921 } else if (*data == 0x3B) {
1922 data++;
1923 data += PrintOperands("cmpw", REG_OPER_OP_ORDER, data);
1924 } else if (*data == 0x81) {
1925 data++;
1926 AppendToBuffer("cmpw ");
1927 data += PrintRightOperand(data);
1928 int imm = *reinterpret_cast<int16_t*>(data);
1929 AppendToBuffer(",0x%x", imm);
1930 data += 2;
1931 } else if (*data == 0x87) {
1932 data++;
1933 int mod, regop, rm;
1934 get_modrm(*data, &mod, ®op, &rm);
1935 AppendToBuffer("xchg_w %s,", NameOfCPURegister(regop));
1936 data += PrintRightOperand(data);
1937 } else if (*data == 0x89) {
1938 data++;
1939 int mod, regop, rm;
1940 get_modrm(*data, &mod, ®op, &rm);
1941 AppendToBuffer("mov_w ");
1942 data += PrintRightOperand(data);
1943 AppendToBuffer(",%s", NameOfCPURegister(regop));
1944 } else if (*data == 0x8B) {
1945 data++;
1946 data += PrintOperands("mov_w", REG_OPER_OP_ORDER, data);
1947 } else if (*data == 0x90) {
1948 AppendToBuffer("nop"); // 0x66 prefix
1949 } else if (*data == 0xC7) {
1950 data++;
1951 AppendToBuffer("%s ", "mov_w");
1952 data += PrintRightOperand(data);
1953 int imm = *reinterpret_cast<int16_t*>(data);
1954 AppendToBuffer(",0x%x", imm);
1955 data += 2;
1956 } else if (*data == 0xF7) {
1957 data++;
1958 AppendToBuffer("%s ", "test_w");
1959 data += PrintRightOperand(data);
1960 int imm = *reinterpret_cast<int16_t*>(data);
1961 AppendToBuffer(",0x%x", imm);
1962 data += 2;
1963 } else if (*data == 0x0F) {
1964 data++;
1965 if (*data == 0x38) {
1966 data++;
1967 byte op = *data;
1968 data++;
1969 int mod, regop, rm;
1970 get_modrm(*data, &mod, ®op, &rm);
1971 switch (op) {
1972 #define SSE34_DIS_CASE(instruction, notUsed1, notUsed2, notUsed3, opcode) \
1973 case 0x##opcode: { \
1974 AppendToBuffer(#instruction " %s,", NameOfXMMRegister(regop)); \
1975 data += PrintRightXMMOperand(data); \
1976 break; \
1977 }
1978
1979 SSSE3_INSTRUCTION_LIST(SSE34_DIS_CASE)
1980 SSE4_INSTRUCTION_LIST(SSE34_DIS_CASE)
1981 SSE4_RM_INSTRUCTION_LIST(SSE34_DIS_CASE)
1982 #undef SSE34_DIS_CASE
1983 default:
1984 UnimplementedInstruction();
1985 }
1986 } else if (*data == 0x3A) {
1987 data++;
1988 if (*data == 0x0A) {
1989 data++;
1990 int mod, regop, rm;
1991 get_modrm(*data, &mod, ®op, &rm);
1992 int8_t imm8 = static_cast<int8_t>(data[1]);
1993 AppendToBuffer("roundss %s,%s,%d", NameOfXMMRegister(regop),
1994 NameOfXMMRegister(rm), static_cast<int>(imm8));
1995 data += 2;
1996 } else if (*data == 0x0B) {
1997 data++;
1998 int mod, regop, rm;
1999 get_modrm(*data, &mod, ®op, &rm);
2000 int8_t imm8 = static_cast<int8_t>(data[1]);
2001 AppendToBuffer("roundsd %s,%s,%d",
2002 NameOfXMMRegister(regop),
2003 NameOfXMMRegister(rm),
2004 static_cast<int>(imm8));
2005 data += 2;
2006 } else if (*data == 0x0E) {
2007 data++;
2008 int mod, regop, rm;
2009 get_modrm(*data, &mod, ®op, &rm);
2010 AppendToBuffer("pblendw %s,", NameOfXMMRegister(regop));
2011 data += PrintRightXMMOperand(data);
2012 AppendToBuffer(",%d", *reinterpret_cast<uint8_t*>(data));
2013 data++;
2014 } else if (*data == 0x0F) {
2015 data++;
2016 int mod, regop, rm;
2017 get_modrm(*data, &mod, ®op, &rm);
2018 AppendToBuffer("palignr %s,", NameOfXMMRegister(regop));
2019 data += PrintRightXMMOperand(data);
2020 AppendToBuffer(",%d", *reinterpret_cast<uint8_t*>(data));
2021 data++;
2022 } else if (*data == 0x14) {
2023 data++;
2024 int mod, regop, rm;
2025 get_modrm(*data, &mod, ®op, &rm);
2026 AppendToBuffer("pextrb ");
2027 data += PrintRightOperand(data);
2028 AppendToBuffer(",%s,%d", NameOfXMMRegister(regop),
2029 *reinterpret_cast<int8_t*>(data));
2030 data++;
2031 } else if (*data == 0x15) {
2032 data++;
2033 int mod, regop, rm;
2034 get_modrm(*data, &mod, ®op, &rm);
2035 AppendToBuffer("pextrw ");
2036 data += PrintRightOperand(data);
2037 AppendToBuffer(",%s,%d", NameOfXMMRegister(regop),
2038 *reinterpret_cast<int8_t*>(data));
2039 data++;
2040 } else if (*data == 0x16) {
2041 data++;
2042 int mod, regop, rm;
2043 get_modrm(*data, &mod, ®op, &rm);
2044 AppendToBuffer("pextrd ");
2045 data += PrintRightOperand(data);
2046 AppendToBuffer(",%s,%d", NameOfXMMRegister(regop),
2047 *reinterpret_cast<int8_t*>(data));
2048 data++;
2049 } else if (*data == 0x17) {
2050 data++;
2051 int mod, regop, rm;
2052 get_modrm(*data, &mod, ®op, &rm);
2053 int8_t imm8 = static_cast<int8_t>(data[1]);
2054 AppendToBuffer("extractps %s,%s,%d",
2055 NameOfCPURegister(rm),
2056 NameOfXMMRegister(regop),
2057 static_cast<int>(imm8));
2058 data += 2;
2059 } else if (*data == 0x20) {
2060 data++;
2061 int mod, regop, rm;
2062 get_modrm(*data, &mod, ®op, &rm);
2063 AppendToBuffer("pinsrb %s,", NameOfXMMRegister(regop));
2064 data += PrintRightOperand(data);
2065 AppendToBuffer(",%d", *reinterpret_cast<int8_t*>(data));
2066 data++;
2067 } else if (*data == 0x21) {
2068 data++;
2069 int mod, regop, rm;
2070 get_modrm(*data, &mod, ®op, &rm);
2071 AppendToBuffer("insertps %s,", NameOfXMMRegister(regop));
2072 data += PrintRightXMMOperand(data);
2073 AppendToBuffer(",%d", *reinterpret_cast<int8_t*>(data));
2074 data++;
2075 } else if (*data == 0x22) {
2076 data++;
2077 int mod, regop, rm;
2078 get_modrm(*data, &mod, ®op, &rm);
2079 AppendToBuffer("pinsrd %s,", NameOfXMMRegister(regop));
2080 data += PrintRightOperand(data);
2081 AppendToBuffer(",%d", *reinterpret_cast<int8_t*>(data));
2082 data++;
2083 } else {
2084 UnimplementedInstruction();
2085 }
2086 } else if (*data == 0x2E || *data == 0x2F) {
2087 const char* mnem = (*data == 0x2E) ? "ucomisd" : "comisd";
2088 data++;
2089 int mod, regop, rm;
2090 get_modrm(*data, &mod, ®op, &rm);
2091 if (mod == 0x3) {
2092 AppendToBuffer("%s %s,%s", mnem,
2093 NameOfXMMRegister(regop),
2094 NameOfXMMRegister(rm));
2095 data++;
2096 } else {
2097 AppendToBuffer("%s %s,", mnem, NameOfXMMRegister(regop));
2098 data += PrintRightOperand(data);
2099 }
2100 } else if (*data == 0x50) {
2101 data++;
2102 int mod, regop, rm;
2103 get_modrm(*data, &mod, ®op, &rm);
2104 AppendToBuffer("movmskpd %s,%s",
2105 NameOfCPURegister(regop),
2106 NameOfXMMRegister(rm));
2107 data++;
2108 } else if (*data == 0x54) {
2109 data++;
2110 int mod, regop, rm;
2111 get_modrm(*data, &mod, ®op, &rm);
2112 AppendToBuffer("andpd %s,%s",
2113 NameOfXMMRegister(regop),
2114 NameOfXMMRegister(rm));
2115 data++;
2116 } else if (*data == 0x56) {
2117 data++;
2118 int mod, regop, rm;
2119 get_modrm(*data, &mod, ®op, &rm);
2120 AppendToBuffer("orpd %s,%s",
2121 NameOfXMMRegister(regop),
2122 NameOfXMMRegister(rm));
2123 data++;
2124 } else if (*data == 0x57) {
2125 data++;
2126 int mod, regop, rm;
2127 get_modrm(*data, &mod, ®op, &rm);
2128 AppendToBuffer("xorpd %s,%s",
2129 NameOfXMMRegister(regop),
2130 NameOfXMMRegister(rm));
2131 data++;
2132 } else if (*data == 0x6E) {
2133 data++;
2134 int mod, regop, rm;
2135 get_modrm(*data, &mod, ®op, &rm);
2136 AppendToBuffer("movd %s,", NameOfXMMRegister(regop));
2137 data += PrintRightOperand(data);
2138 } else if (*data == 0x6F) {
2139 data++;
2140 int mod, regop, rm;
2141 get_modrm(*data, &mod, ®op, &rm);
2142 AppendToBuffer("movdqa %s,", NameOfXMMRegister(regop));
2143 data += PrintRightXMMOperand(data);
2144 } else if (*data == 0x70) {
2145 data++;
2146 int mod, regop, rm;
2147 get_modrm(*data, &mod, ®op, &rm);
2148 AppendToBuffer("pshufd %s,", NameOfXMMRegister(regop));
2149 data += PrintRightXMMOperand(data);
2150 AppendToBuffer(",%d", *reinterpret_cast<int8_t*>(data));
2151 data++;
2152 } else if (*data == 0x90) {
2153 data++;
2154 AppendToBuffer("nop"); // 2 byte nop.
2155 } else if (*data == 0xF3) {
2156 data++;
2157 int mod, regop, rm;
2158 get_modrm(*data, &mod, ®op, &rm);
2159 AppendToBuffer("psllq %s,%s",
2160 NameOfXMMRegister(regop),
2161 NameOfXMMRegister(rm));
2162 data++;
2163 } else if (*data == 0x71) {
2164 data++;
2165 int mod, regop, rm;
2166 get_modrm(*data, &mod, ®op, &rm);
2167 int8_t imm8 = static_cast<int8_t>(data[1]);
2168 AppendToBuffer("ps%sw %s,%d", sf_str[regop / 2],
2169 NameOfXMMRegister(rm), static_cast<int>(imm8));
2170 data += 2;
2171 } else if (*data == 0x72) {
2172 data++;
2173 int mod, regop, rm;
2174 get_modrm(*data, &mod, ®op, &rm);
2175 int8_t imm8 = static_cast<int8_t>(data[1]);
2176 AppendToBuffer("ps%sd %s,%d", sf_str[regop / 2],
2177 NameOfXMMRegister(rm), static_cast<int>(imm8));
2178 data += 2;
2179 } else if (*data == 0x73) {
2180 data++;
2181 int mod, regop, rm;
2182 get_modrm(*data, &mod, ®op, &rm);
2183 int8_t imm8 = static_cast<int8_t>(data[1]);
2184 DCHECK(regop == esi || regop == edx);
2185 AppendToBuffer("ps%sq %s,%d", sf_str[regop / 2],
2186 NameOfXMMRegister(rm), static_cast<int>(imm8));
2187 data += 2;
2188 } else if (*data == 0xD3) {
2189 data++;
2190 int mod, regop, rm;
2191 get_modrm(*data, &mod, ®op, &rm);
2192 AppendToBuffer("psrlq %s,%s",
2193 NameOfXMMRegister(regop),
2194 NameOfXMMRegister(rm));
2195 data++;
2196 } else if (*data == 0x7F) {
2197 AppendToBuffer("movdqa ");
2198 data++;
2199 int mod, regop, rm;
2200 get_modrm(*data, &mod, ®op, &rm);
2201 data += PrintRightXMMOperand(data);
2202 AppendToBuffer(",%s", NameOfXMMRegister(regop));
2203 } else if (*data == 0x7E) {
2204 data++;
2205 int mod, regop, rm;
2206 get_modrm(*data, &mod, ®op, &rm);
2207 AppendToBuffer("movd ");
2208 data += PrintRightOperand(data);
2209 AppendToBuffer(",%s", NameOfXMMRegister(regop));
2210 } else if (*data == 0xC4) {
2211 data++;
2212 int mod, regop, rm;
2213 get_modrm(*data, &mod, ®op, &rm);
2214 AppendToBuffer("pinsrw %s,", NameOfXMMRegister(regop));
2215 data += PrintRightOperand(data);
2216 AppendToBuffer(",%d", *reinterpret_cast<int8_t*>(data));
2217 data++;
2218 } else if (*data == 0xE7) {
2219 data++;
2220 int mod, regop, rm;
2221 get_modrm(*data, &mod, ®op, &rm);
2222 if (mod == 3) {
2223 // movntdq
2224 UnimplementedInstruction();
2225 } else {
2226 UnimplementedInstruction();
2227 }
2228 } else if (*data == 0xB1) {
2229 data++;
2230 data += PrintOperands("cmpxchg_w", OPER_REG_OP_ORDER, data);
2231 } else {
2232 byte op = *data;
2233 data++;
2234 int mod, regop, rm;
2235 get_modrm(*data, &mod, ®op, &rm);
2236 switch (op) {
2237 #define SSE2_DIS_CASE(instruction, notUsed1, notUsed2, opcode) \
2238 case 0x##opcode: { \
2239 AppendToBuffer(#instruction " %s,", NameOfXMMRegister(regop)); \
2240 data += PrintRightXMMOperand(data); \
2241 break; \
2242 }
2243
2244 SSE2_INSTRUCTION_LIST(SSE2_DIS_CASE)
2245 #undef SSE2_DIS_CASE
2246 default:
2247 UnimplementedInstruction();
2248 }
2249 }
2250 } else {
2251 UnimplementedInstruction();
2252 }
2253 break;
2254
2255 case 0xFE:
2256 { data++;
2257 int mod, regop, rm;
2258 get_modrm(*data, &mod, ®op, &rm);
2259 if (regop == ecx) {
2260 AppendToBuffer("dec_b ");
2261 data += PrintRightOperand(data);
2262 } else {
2263 UnimplementedInstruction();
2264 }
2265 }
2266 break;
2267
2268 case 0x68:
2269 AppendToBuffer("push 0x%x", *reinterpret_cast<int32_t*>(data+1));
2270 data += 5;
2271 break;
2272
2273 case 0x6A:
2274 AppendToBuffer("push 0x%x", *reinterpret_cast<int8_t*>(data + 1));
2275 data += 2;
2276 break;
2277
2278 case 0xA8:
2279 AppendToBuffer("test al,0x%x", *reinterpret_cast<uint8_t*>(data+1));
2280 data += 2;
2281 break;
2282
2283 case 0xA9:
2284 AppendToBuffer("test eax,0x%x", *reinterpret_cast<int32_t*>(data+1));
2285 data += 5;
2286 break;
2287
2288 case 0xD1: // fall through
2289 case 0xD3: // fall through
2290 case 0xC1:
2291 data += D1D3C1Instruction(data);
2292 break;
2293
2294 case 0xD8: // fall through
2295 case 0xD9: // fall through
2296 case 0xDA: // fall through
2297 case 0xDB: // fall through
2298 case 0xDC: // fall through
2299 case 0xDD: // fall through
2300 case 0xDE: // fall through
2301 case 0xDF:
2302 data += FPUInstruction(data);
2303 break;
2304
2305 case 0xEB:
2306 data += JumpShort(data);
2307 break;
2308
2309 case 0xF2:
2310 if (*(data+1) == 0x0F) {
2311 byte b2 = *(data+2);
2312 if (b2 == 0x11) {
2313 AppendToBuffer("movsd ");
2314 data += 3;
2315 int mod, regop, rm;
2316 get_modrm(*data, &mod, ®op, &rm);
2317 data += PrintRightXMMOperand(data);
2318 AppendToBuffer(",%s", NameOfXMMRegister(regop));
2319 } else if (b2 == 0x10) {
2320 data += 3;
2321 int mod, regop, rm;
2322 get_modrm(*data, &mod, ®op, &rm);
2323 AppendToBuffer("movsd %s,", NameOfXMMRegister(regop));
2324 data += PrintRightXMMOperand(data);
2325 } else if (b2 == 0x5A) {
2326 data += 3;
2327 int mod, regop, rm;
2328 get_modrm(*data, &mod, ®op, &rm);
2329 AppendToBuffer("cvtsd2ss %s,", NameOfXMMRegister(regop));
2330 data += PrintRightXMMOperand(data);
2331 } else if (b2 == 0x70) {
2332 data += 3;
2333 int mod, regop, rm;
2334 get_modrm(*data, &mod, ®op, &rm);
2335 AppendToBuffer("pshuflw %s,", NameOfXMMRegister(regop));
2336 data += PrintRightXMMOperand(data);
2337 AppendToBuffer(",%d", *reinterpret_cast<int8_t*>(data));
2338 data++;
2339 } else {
2340 const char* mnem = "?";
2341 switch (b2) {
2342 case 0x2A:
2343 mnem = "cvtsi2sd";
2344 break;
2345 case 0x2C:
2346 mnem = "cvttsd2si";
2347 break;
2348 case 0x2D:
2349 mnem = "cvtsd2si";
2350 break;
2351 case 0x51:
2352 mnem = "sqrtsd";
2353 break;
2354 case 0x58:
2355 mnem = "addsd";
2356 break;
2357 case 0x59:
2358 mnem = "mulsd";
2359 break;
2360 case 0x5C:
2361 mnem = "subsd";
2362 break;
2363 case 0x5D:
2364 mnem = "minsd";
2365 break;
2366 case 0x5E:
2367 mnem = "divsd";
2368 break;
2369 case 0x5F:
2370 mnem = "maxsd";
2371 break;
2372 case 0x7C:
2373 mnem = "haddps";
2374 break;
2375 }
2376 data += 3;
2377 int mod, regop, rm;
2378 get_modrm(*data, &mod, ®op, &rm);
2379 if (b2 == 0x2A) {
2380 AppendToBuffer("%s %s,", mnem, NameOfXMMRegister(regop));
2381 data += PrintRightOperand(data);
2382 } else if (b2 == 0x2C || b2 == 0x2D) {
2383 AppendToBuffer("%s %s,", mnem, NameOfCPURegister(regop));
2384 data += PrintRightXMMOperand(data);
2385 } else if (b2 == 0xC2) {
2386 // Intel manual 2A, Table 3-18.
2387 const char* const pseudo_op[] = {
2388 "cmpeqsd",
2389 "cmpltsd",
2390 "cmplesd",
2391 "cmpunordsd",
2392 "cmpneqsd",
2393 "cmpnltsd",
2394 "cmpnlesd",
2395 "cmpordsd"
2396 };
2397 AppendToBuffer("%s %s,%s",
2398 pseudo_op[data[1]],
2399 NameOfXMMRegister(regop),
2400 NameOfXMMRegister(rm));
2401 data += 2;
2402 } else {
2403 AppendToBuffer("%s %s,", mnem, NameOfXMMRegister(regop));
2404 data += PrintRightXMMOperand(data);
2405 }
2406 }
2407 } else {
2408 UnimplementedInstruction();
2409 }
2410 break;
2411
2412 case 0xF3:
2413 if (*(data+1) == 0x0F) {
2414 byte b2 = *(data+2);
2415 if (b2 == 0x11) {
2416 AppendToBuffer("movss ");
2417 data += 3;
2418 int mod, regop, rm;
2419 get_modrm(*data, &mod, ®op, &rm);
2420 data += PrintRightXMMOperand(data);
2421 AppendToBuffer(",%s", NameOfXMMRegister(regop));
2422 } else if (b2 == 0x10) {
2423 data += 3;
2424 int mod, regop, rm;
2425 get_modrm(*data, &mod, ®op, &rm);
2426 AppendToBuffer("movss %s,", NameOfXMMRegister(regop));
2427 data += PrintRightXMMOperand(data);
2428 } else if (b2 == 0x5A) {
2429 data += 3;
2430 int mod, regop, rm;
2431 get_modrm(*data, &mod, ®op, &rm);
2432 AppendToBuffer("cvtss2sd %s,", NameOfXMMRegister(regop));
2433 data += PrintRightXMMOperand(data);
2434 } else if (b2 == 0x6F) {
2435 data += 3;
2436 int mod, regop, rm;
2437 get_modrm(*data, &mod, ®op, &rm);
2438 AppendToBuffer("movdqu %s,", NameOfXMMRegister(regop));
2439 data += PrintRightXMMOperand(data);
2440 } else if (b2 == 0x70) {
2441 data += 3;
2442 int mod, regop, rm;
2443 get_modrm(*data, &mod, ®op, &rm);
2444 AppendToBuffer("pshufhw %s,", NameOfXMMRegister(regop));
2445 data += PrintRightXMMOperand(data);
2446 AppendToBuffer(",%d", *reinterpret_cast<int8_t*>(data));
2447 data++;
2448 } else if (b2 == 0x7F) {
2449 AppendToBuffer("movdqu ");
2450 data += 3;
2451 int mod, regop, rm;
2452 get_modrm(*data, &mod, ®op, &rm);
2453 data += PrintRightXMMOperand(data);
2454 AppendToBuffer(",%s", NameOfXMMRegister(regop));
2455 } else if (b2 == 0xB8) {
2456 data += 3;
2457 int mod, regop, rm;
2458 get_modrm(*data, &mod, ®op, &rm);
2459 AppendToBuffer("popcnt %s,", NameOfCPURegister(regop));
2460 data += PrintRightOperand(data);
2461 } else if (b2 == 0xBC) {
2462 data += 3;
2463 int mod, regop, rm;
2464 get_modrm(*data, &mod, ®op, &rm);
2465 AppendToBuffer("tzcnt %s,", NameOfCPURegister(regop));
2466 data += PrintRightOperand(data);
2467 } else if (b2 == 0xBD) {
2468 data += 3;
2469 int mod, regop, rm;
2470 get_modrm(*data, &mod, ®op, &rm);
2471 AppendToBuffer("lzcnt %s,", NameOfCPURegister(regop));
2472 data += PrintRightOperand(data);
2473 } else {
2474 const char* mnem = "?";
2475 switch (b2) {
2476 case 0x2A:
2477 mnem = "cvtsi2ss";
2478 break;
2479 case 0x2C:
2480 mnem = "cvttss2si";
2481 break;
2482 case 0x2D:
2483 mnem = "cvtss2si";
2484 break;
2485 case 0x51:
2486 mnem = "sqrtss";
2487 break;
2488 case 0x58:
2489 mnem = "addss";
2490 break;
2491 case 0x59:
2492 mnem = "mulss";
2493 break;
2494 case 0x5B:
2495 mnem = "cvttps2dq";
2496 break;
2497 case 0x5C:
2498 mnem = "subss";
2499 break;
2500 case 0x5D:
2501 mnem = "minss";
2502 break;
2503 case 0x5E:
2504 mnem = "divss";
2505 break;
2506 case 0x5F:
2507 mnem = "maxss";
2508 break;
2509 case 0x7E:
2510 mnem = "movq";
2511 break;
2512 }
2513 data += 3;
2514 int mod, regop, rm;
2515 get_modrm(*data, &mod, ®op, &rm);
2516 if (b2 == 0x2A) {
2517 AppendToBuffer("%s %s,", mnem, NameOfXMMRegister(regop));
2518 data += PrintRightOperand(data);
2519 } else if (b2 == 0x2C || b2 == 0x2D) {
2520 AppendToBuffer("%s %s,", mnem, NameOfCPURegister(regop));
2521 data += PrintRightXMMOperand(data);
2522 } else if (b2 == 0xC2) {
2523 // Intel manual 2A, Table 3-18.
2524 const char* const pseudo_op[] = {
2525 "cmpeqss", "cmpltss", "cmpless", "cmpunordss",
2526 "cmpneqss", "cmpnltss", "cmpnless", "cmpordss"};
2527 AppendToBuffer("%s %s,%s", pseudo_op[data[1]],
2528 NameOfXMMRegister(regop), NameOfXMMRegister(rm));
2529 data += 2;
2530 } else {
2531 AppendToBuffer("%s %s,", mnem, NameOfXMMRegister(regop));
2532 data += PrintRightXMMOperand(data);
2533 }
2534 }
2535 } else if (*(data+1) == 0xA5) {
2536 data += 2;
2537 AppendToBuffer("rep_movs");
2538 } else if (*(data+1) == 0xAB) {
2539 data += 2;
2540 AppendToBuffer("rep_stos");
2541 } else if (*(data + 1) == 0x90) {
2542 data += 2;
2543 AppendToBuffer("pause");
2544 } else {
2545 UnimplementedInstruction();
2546 }
2547 break;
2548
2549 case 0xF7:
2550 data += F7Instruction(data);
2551 break;
2552
2553 default:
2554 UnimplementedInstruction();
2555 }
2556 }
2557
2558 if (tmp_buffer_pos_ < sizeof tmp_buffer_) {
2559 tmp_buffer_[tmp_buffer_pos_] = '\0';
2560 }
2561
2562 int instr_len = data - instr;
2563 if (instr_len == 0) {
2564 printf("%02x", *data);
2565 }
2566 DCHECK_GT(instr_len, 0); // Ensure progress.
2567
2568 int outp = 0;
2569 // Instruction bytes.
2570 for (byte* bp = instr; bp < data; bp++) {
2571 outp += v8::internal::SNPrintF(out_buffer + outp,
2572 "%02x",
2573 *bp);
2574 }
2575 for (int i = 6 - instr_len; i >= 0; i--) {
2576 outp += v8::internal::SNPrintF(out_buffer + outp, " ");
2577 }
2578
2579 outp += v8::internal::SNPrintF(out_buffer + outp,
2580 " %s",
2581 tmp_buffer_.start());
2582 return instr_len;
2583 } // NOLINT (function is too long)
2584
2585
2586 //------------------------------------------------------------------------------
2587
2588
2589 static const char* const cpu_regs[8] = {
2590 "eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi"
2591 };
2592
2593
2594 static const char* const byte_cpu_regs[8] = {
2595 "al", "cl", "dl", "bl", "ah", "ch", "dh", "bh"
2596 };
2597
2598
2599 static const char* const xmm_regs[8] = {
2600 "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7"
2601 };
2602
2603
NameOfAddress(byte * addr) const2604 const char* NameConverter::NameOfAddress(byte* addr) const {
2605 v8::internal::SNPrintF(tmp_buffer_, "%p", static_cast<void*>(addr));
2606 return tmp_buffer_.start();
2607 }
2608
2609
NameOfConstant(byte * addr) const2610 const char* NameConverter::NameOfConstant(byte* addr) const {
2611 return NameOfAddress(addr);
2612 }
2613
2614
NameOfCPURegister(int reg) const2615 const char* NameConverter::NameOfCPURegister(int reg) const {
2616 if (0 <= reg && reg < 8) return cpu_regs[reg];
2617 return "noreg";
2618 }
2619
2620
NameOfByteCPURegister(int reg) const2621 const char* NameConverter::NameOfByteCPURegister(int reg) const {
2622 if (0 <= reg && reg < 8) return byte_cpu_regs[reg];
2623 return "noreg";
2624 }
2625
2626
NameOfXMMRegister(int reg) const2627 const char* NameConverter::NameOfXMMRegister(int reg) const {
2628 if (0 <= reg && reg < 8) return xmm_regs[reg];
2629 return "noxmmreg";
2630 }
2631
2632
NameInCode(byte * addr) const2633 const char* NameConverter::NameInCode(byte* addr) const {
2634 // IA32 does not embed debug strings at the moment.
2635 UNREACHABLE();
2636 }
2637
2638
2639 //------------------------------------------------------------------------------
2640
InstructionDecode(v8::internal::Vector<char> buffer,byte * instruction)2641 int Disassembler::InstructionDecode(v8::internal::Vector<char> buffer,
2642 byte* instruction) {
2643 DisassemblerIA32 d(converter_, unimplemented_opcode_action());
2644 return d.InstructionDecode(buffer, instruction);
2645 }
2646
2647 // The IA-32 assembler does not currently use constant pools.
ConstantPoolSizeAt(byte * instruction)2648 int Disassembler::ConstantPoolSizeAt(byte* instruction) { return -1; }
2649
2650 // static
Disassemble(FILE * f,byte * begin,byte * end,UnimplementedOpcodeAction unimplemented_action)2651 void Disassembler::Disassemble(FILE* f, byte* begin, byte* end,
2652 UnimplementedOpcodeAction unimplemented_action) {
2653 NameConverter converter;
2654 Disassembler d(converter, unimplemented_action);
2655 for (byte* pc = begin; pc < end;) {
2656 v8::internal::EmbeddedVector<char, 128> buffer;
2657 buffer[0] = '\0';
2658 byte* prev_pc = pc;
2659 pc += d.InstructionDecode(buffer, pc);
2660 fprintf(f, "%p", static_cast<void*>(prev_pc));
2661 fprintf(f, " ");
2662
2663 for (byte* bp = prev_pc; bp < pc; bp++) {
2664 fprintf(f, "%02x", *bp);
2665 }
2666 for (int i = 6 - (pc - prev_pc); i >= 0; i--) {
2667 fprintf(f, " ");
2668 }
2669 fprintf(f, " %s\n", buffer.start());
2670 }
2671 }
2672
2673
2674 } // namespace disasm
2675
2676 #endif // V8_TARGET_ARCH_IA32
2677