11 #include "src/base/compiler-specific.h" 12 #include "src/base/lazy-instance.h" 13 #include "src/base/v8-fallthrough.h" 14 #include "src/disasm.h" 15 #include "src/macro-assembler.h" 16 #include "src/x64/sse-instr.h" 23 REG_OPER_OP_ORDER = 1,
24 OPER_REG_OP_ORDER = 2,
26 BYTE_SIZE_OPERAND_FLAG = 4,
27 BYTE_REG_OPER_OP_ORDER = REG_OPER_OP_ORDER | BYTE_SIZE_OPERAND_FLAG,
28 BYTE_OPER_REG_OP_ORDER = OPER_REG_OP_ORDER | BYTE_SIZE_OPERAND_FLAG
37 OperandType op_order_;
42 static const ByteMnemonic two_operands_instr[] = {
43 { 0x00, BYTE_OPER_REG_OP_ORDER,
"add" },
44 { 0x01, OPER_REG_OP_ORDER,
"add" },
45 { 0x02, BYTE_REG_OPER_OP_ORDER,
"add" },
46 { 0x03, REG_OPER_OP_ORDER,
"add" },
47 { 0x08, BYTE_OPER_REG_OP_ORDER,
"or" },
48 { 0x09, OPER_REG_OP_ORDER,
"or" },
49 { 0x0A, BYTE_REG_OPER_OP_ORDER,
"or" },
50 { 0x0B, REG_OPER_OP_ORDER,
"or" },
51 { 0x10, BYTE_OPER_REG_OP_ORDER,
"adc" },
52 { 0x11, OPER_REG_OP_ORDER,
"adc" },
53 { 0x12, BYTE_REG_OPER_OP_ORDER,
"adc" },
54 { 0x13, REG_OPER_OP_ORDER,
"adc" },
55 { 0x18, BYTE_OPER_REG_OP_ORDER,
"sbb" },
56 { 0x19, OPER_REG_OP_ORDER,
"sbb" },
57 { 0x1A, BYTE_REG_OPER_OP_ORDER,
"sbb" },
58 { 0x1B, REG_OPER_OP_ORDER,
"sbb" },
59 { 0x20, BYTE_OPER_REG_OP_ORDER,
"and" },
60 { 0x21, OPER_REG_OP_ORDER,
"and" },
61 { 0x22, BYTE_REG_OPER_OP_ORDER,
"and" },
62 { 0x23, REG_OPER_OP_ORDER,
"and" },
63 { 0x28, BYTE_OPER_REG_OP_ORDER,
"sub" },
64 { 0x29, OPER_REG_OP_ORDER,
"sub" },
65 { 0x2A, BYTE_REG_OPER_OP_ORDER,
"sub" },
66 { 0x2B, REG_OPER_OP_ORDER,
"sub" },
67 { 0x30, BYTE_OPER_REG_OP_ORDER,
"xor" },
68 { 0x31, OPER_REG_OP_ORDER,
"xor" },
69 { 0x32, BYTE_REG_OPER_OP_ORDER,
"xor" },
70 { 0x33, REG_OPER_OP_ORDER,
"xor" },
71 { 0x38, BYTE_OPER_REG_OP_ORDER,
"cmp" },
72 { 0x39, OPER_REG_OP_ORDER,
"cmp" },
73 { 0x3A, BYTE_REG_OPER_OP_ORDER,
"cmp" },
74 { 0x3B, REG_OPER_OP_ORDER,
"cmp" },
75 { 0x63, REG_OPER_OP_ORDER,
"movsxl" },
76 { 0x84, BYTE_REG_OPER_OP_ORDER,
"test" },
77 { 0x85, REG_OPER_OP_ORDER,
"test" },
78 { 0x86, BYTE_REG_OPER_OP_ORDER,
"xchg" },
79 { 0x87, REG_OPER_OP_ORDER,
"xchg" },
80 { 0x88, BYTE_OPER_REG_OP_ORDER,
"mov" },
81 { 0x89, OPER_REG_OP_ORDER,
"mov" },
82 { 0x8A, BYTE_REG_OPER_OP_ORDER,
"mov" },
83 { 0x8B, REG_OPER_OP_ORDER,
"mov" },
84 { 0x8D, REG_OPER_OP_ORDER,
"lea" },
85 { -1, UNSET_OP_ORDER,
"" }
89 static const ByteMnemonic zero_operands_instr[] = {
90 { 0xC3, UNSET_OP_ORDER,
"ret" },
91 { 0xC9, UNSET_OP_ORDER,
"leave" },
92 { 0xF4, UNSET_OP_ORDER,
"hlt" },
93 { 0xFC, UNSET_OP_ORDER,
"cld" },
94 { 0xCC, UNSET_OP_ORDER,
"int3" },
95 { 0x60, UNSET_OP_ORDER,
"pushad" },
96 { 0x61, UNSET_OP_ORDER,
"popad" },
97 { 0x9C, UNSET_OP_ORDER,
"pushfd" },
98 { 0x9D, UNSET_OP_ORDER,
"popfd" },
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,
"" }
110 static const ByteMnemonic call_jump_instr[] = {
111 { 0xE8, UNSET_OP_ORDER,
"call" },
112 { 0xE9, UNSET_OP_ORDER,
"jmp" },
113 { -1, UNSET_OP_ORDER,
"" }
117 static const ByteMnemonic short_immediate_instr[] = {
118 { 0x05, UNSET_OP_ORDER,
"add" },
119 { 0x0D, UNSET_OP_ORDER,
"or" },
120 { 0x15, UNSET_OP_ORDER,
"adc" },
121 { 0x1D, UNSET_OP_ORDER,
"sbb" },
122 { 0x25, UNSET_OP_ORDER,
"and" },
123 { 0x2D, UNSET_OP_ORDER,
"sub" },
124 { 0x35, UNSET_OP_ORDER,
"xor" },
125 { 0x3D, UNSET_OP_ORDER,
"cmp" },
126 { -1, UNSET_OP_ORDER,
"" }
130 static const char*
const conditional_code_suffix[] = {
131 "o",
"no",
"c",
"nc",
"z",
"nz",
"na",
"a",
132 "s",
"ns",
"pe",
"po",
"l",
"ge",
"le",
"g" 136 enum InstructionType {
140 JUMP_CONDITIONAL_SHORT_INSTR,
145 SHORT_IMMEDIATE_INSTR
149 ESCAPE_PREFIX = 0x0F,
150 OPERAND_SIZE_OVERRIDE_PREFIX = 0x66,
151 ADDRESS_SIZE_OVERRIDE_PREFIX = 0x67,
157 REPEQ_PREFIX = REP_PREFIX
160 struct InstructionDesc {
162 InstructionType type;
163 OperandType op_order_;
164 bool byte_size_operation;
168 class InstructionTable {
171 const InstructionDesc& Get(byte x)
const {
172 return instructions_[x];
176 InstructionDesc instructions_[256];
179 void CopyTable(
const ByteMnemonic bm[], InstructionType type);
180 void SetTableRange(InstructionType type, byte start, byte end,
bool byte_size,
182 void AddJumpConditionalShort();
186 InstructionTable::InstructionTable() {
192 void InstructionTable::Clear() {
193 for (
int i = 0;
i < 256;
i++) {
194 instructions_[
i].mnem =
"(bad)";
195 instructions_[
i].type = NO_INSTR;
196 instructions_[
i].op_order_ = UNSET_OP_ORDER;
197 instructions_[
i].byte_size_operation =
false;
202 void InstructionTable::Init() {
203 CopyTable(two_operands_instr, TWO_OPERANDS_INSTR);
204 CopyTable(zero_operands_instr, ZERO_OPERANDS_INSTR);
205 CopyTable(call_jump_instr, CALL_JUMP_INSTR);
206 CopyTable(short_immediate_instr, SHORT_IMMEDIATE_INSTR);
207 AddJumpConditionalShort();
208 SetTableRange(PUSHPOP_INSTR, 0x50, 0x57,
false,
"push");
209 SetTableRange(PUSHPOP_INSTR, 0x58, 0x5F,
false,
"pop");
210 SetTableRange(MOVE_REG_INSTR, 0xB8, 0xBF,
false,
"mov");
214 void InstructionTable::CopyTable(
const ByteMnemonic bm[],
215 InstructionType type) {
216 for (
int i = 0; bm[
i].b >= 0;
i++) {
217 InstructionDesc*
id = &instructions_[bm[
i].b];
218 id->mnem = bm[
i].mnem;
219 OperandType op_order = bm[
i].op_order_;
221 static_cast<OperandType
>(op_order & ~BYTE_SIZE_OPERAND_FLAG);
222 DCHECK_EQ(NO_INSTR, id->type);
224 id->byte_size_operation = ((op_order & BYTE_SIZE_OPERAND_FLAG) != 0);
229 void InstructionTable::SetTableRange(InstructionType type,
234 for (byte b = start; b <= end; b++) {
235 InstructionDesc*
id = &instructions_[b];
236 DCHECK_EQ(NO_INSTR, id->type);
239 id->byte_size_operation = byte_size;
244 void InstructionTable::AddJumpConditionalShort() {
245 for (byte b = 0x70; b <= 0x7F; b++) {
246 InstructionDesc*
id = &instructions_[b];
247 DCHECK_EQ(NO_INSTR, id->type);
249 id->type = JUMP_CONDITIONAL_SHORT_INSTR;
255 LAZY_INSTANCE_INITIALIZER;
258 static const InstructionDesc cmov_instructions[16] = {
259 {
"cmovo", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER,
false},
260 {
"cmovno", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER,
false},
261 {
"cmovc", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER,
false},
262 {
"cmovnc", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER,
false},
263 {
"cmovz", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER,
false},
264 {
"cmovnz", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER,
false},
265 {
"cmovna", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER,
false},
266 {
"cmova", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER,
false},
267 {
"cmovs", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER,
false},
268 {
"cmovns", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER,
false},
269 {
"cmovpe", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER,
false},
270 {
"cmovpo", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER,
false},
271 {
"cmovl", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER,
false},
272 {
"cmovge", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER,
false},
273 {
"cmovle", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER,
false},
274 {
"cmovg", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER,
false}
284 class DisassemblerX64 {
286 DisassemblerX64(
const NameConverter& converter,
287 Disassembler::UnimplementedOpcodeAction unimplemented_action)
288 : converter_(converter),
290 abort_on_unimplemented_(unimplemented_action ==
291 Disassembler::kAbortOnUnimplementedOpcode),
298 byte_size_operand_(false),
299 instruction_table_(instruction_table.Pointer()) {
300 tmp_buffer_[0] =
'\0';
309 OPERAND_BYTE_SIZE = 0,
310 OPERAND_WORD_SIZE = 1,
311 OPERAND_DOUBLEWORD_SIZE = 2,
312 OPERAND_QUADWORD_SIZE = 3
315 const NameConverter& converter_;
317 unsigned int tmp_buffer_pos_;
318 bool abort_on_unimplemented_;
322 byte group_1_prefix_;
327 bool byte_size_operand_;
328 const InstructionTable*
const instruction_table_;
330 void setRex(byte rex) {
331 DCHECK_EQ(0x40, rex & 0xF0);
335 bool rex() {
return rex_ != 0; }
337 bool rex_b() {
return (rex_ & 0x01) != 0; }
340 int base_reg(
int low_bits) {
return low_bits | ((rex_ & 0x01) << 3); }
342 bool rex_x() {
return (rex_ & 0x02) != 0; }
344 bool rex_r() {
return (rex_ & 0x04) != 0; }
346 bool rex_w() {
return (rex_ & 0x08) != 0; }
349 DCHECK(vex_byte0_ == VEX3_PREFIX || vex_byte0_ == VEX2_PREFIX);
350 return vex_byte0_ == VEX3_PREFIX ? (vex_byte2_ & 0x80) != 0 :
false;
354 DCHECK(vex_byte0_ == VEX3_PREFIX || vex_byte0_ == VEX2_PREFIX);
355 byte checked = vex_byte0_ == VEX3_PREFIX ? vex_byte2_ : vex_byte1_;
356 return (checked & 4) == 0;
360 DCHECK(vex_byte0_ == VEX3_PREFIX || vex_byte0_ == VEX2_PREFIX);
361 byte checked = vex_byte0_ == VEX3_PREFIX ? vex_byte2_ : vex_byte1_;
362 return (checked & 3) == 0;
366 DCHECK(vex_byte0_ == VEX3_PREFIX || vex_byte0_ == VEX2_PREFIX);
367 byte checked = vex_byte0_ == VEX3_PREFIX ? vex_byte2_ : vex_byte1_;
368 return (checked & 3) == 1;
372 DCHECK(vex_byte0_ == VEX3_PREFIX || vex_byte0_ == VEX2_PREFIX);
373 byte checked = vex_byte0_ == VEX3_PREFIX ? vex_byte2_ : vex_byte1_;
374 return (checked & 3) == 2;
378 DCHECK(vex_byte0_ == VEX3_PREFIX || vex_byte0_ == VEX2_PREFIX);
379 byte checked = vex_byte0_ == VEX3_PREFIX ? vex_byte2_ : vex_byte1_;
380 return (checked & 3) == 3;
384 if (vex_byte0_ == VEX2_PREFIX)
return true;
385 return (vex_byte1_ & 3) == 1;
389 if (vex_byte0_ == VEX2_PREFIX)
return false;
390 return (vex_byte1_ & 3) == 2;
394 if (vex_byte0_ == VEX2_PREFIX)
return false;
395 return (vex_byte1_ & 3) == 3;
399 DCHECK(vex_byte0_ == VEX3_PREFIX || vex_byte0_ == VEX2_PREFIX);
400 byte checked = vex_byte0_ == VEX3_PREFIX ? vex_byte2_ : vex_byte1_;
401 return ~(checked >> 3) & 0xF;
404 OperandSize operand_size() {
405 if (byte_size_operand_)
return OPERAND_BYTE_SIZE;
406 if (rex_w())
return OPERAND_QUADWORD_SIZE;
407 if (operand_size_ != 0)
return OPERAND_WORD_SIZE;
408 return OPERAND_DOUBLEWORD_SIZE;
411 char operand_size_code() {
412 return "bwlq"[operand_size()];
415 char float_size_code() {
return "sd"[rex_w()]; }
417 const char* NameOfCPURegister(
int reg)
const {
418 return converter_.NameOfCPURegister(reg);
421 const char* NameOfByteCPURegister(
int reg)
const {
422 return converter_.NameOfByteCPURegister(reg);
425 const char* NameOfXMMRegister(
int reg)
const {
426 return converter_.NameOfXMMRegister(reg);
429 const char* NameOfAddress(byte* addr)
const {
430 return converter_.NameOfAddress(addr);
434 void get_modrm(byte data,
438 *mod = (data >> 6) & 3;
439 *regop = ((data & 0x38) >> 3) | (rex_r() ? 8 : 0);
440 *rm = (data & 7) | (rex_b() ? 8 : 0);
443 void get_sib(byte data,
447 *scale = (data >> 6) & 3;
448 *index = ((data >> 3) & 7) | (rex_x() ? 8 : 0);
449 *base = (data & 7) | (rex_b() ? 8 : 0);
452 typedef const char* (DisassemblerX64::*RegisterNameMapping)(
int reg)
const;
454 void TryAppendRootRelativeName(
int offset);
455 int PrintRightOperandHelper(byte* modrmp,
456 RegisterNameMapping register_name);
457 int PrintRightOperand(byte* modrmp);
458 int PrintRightByteOperand(byte* modrmp);
459 int PrintRightXMMOperand(byte* modrmp);
460 int PrintOperands(
const char* mnem,
461 OperandType op_order,
463 int PrintImmediate(byte* data, OperandSize size);
464 int PrintImmediateOp(byte* data);
465 const char* TwoByteMnemonic(byte opcode);
466 int TwoByteOpcodeInstruction(byte* data);
467 int F6F7Instruction(byte* data);
468 int ShiftInstruction(byte* data);
469 int JumpShort(byte* data);
470 int JumpConditional(byte* data);
471 int JumpConditionalShort(byte* data);
472 int SetCC(byte* data);
473 int FPUInstruction(byte* data);
474 int MemoryFPUInstruction(
int escape_opcode,
int regop, byte* modrm_start);
475 int RegisterFPUInstruction(
int escape_opcode, byte modrm_byte);
476 int AVXInstruction(byte* data);
477 PRINTF_FORMAT(2, 3) void AppendToBuffer(const
char* format, ...);
479 void UnimplementedInstruction() {
480 if (abort_on_unimplemented_) {
481 FATAL(
"'Unimplemented Instruction'");
483 AppendToBuffer(
"'Unimplemented Instruction'");
489 void DisassemblerX64::AppendToBuffer(
const char* format, ...) {
492 va_start(args, format);
493 int result = v8::internal::VSNPrintF(buf, format, args);
495 tmp_buffer_pos_ += result;
498 void DisassemblerX64::TryAppendRootRelativeName(
int offset) {
499 const char* maybe_name = converter_.RootRelativeName(offset);
500 if (maybe_name !=
nullptr) AppendToBuffer(
" (%s)", maybe_name);
503 int DisassemblerX64::PrintRightOperandHelper(
505 RegisterNameMapping direct_register_name) {
507 get_modrm(*modrmp, &mod, ®op, &rm);
508 RegisterNameMapping register_name = (mod == 3) ? direct_register_name :
509 &DisassemblerX64::NameOfCPURegister;
513 int32_t disp = *
reinterpret_cast<int32_t*
>(modrmp + 1);
514 AppendToBuffer(
"[rip+0x%x]", disp);
516 }
else if ((rm & 7) == 4) {
518 byte sib = *(modrmp + 1);
519 int scale, index, base;
520 get_sib(sib, &scale, &index, &base);
521 if (index == 4 && (base & 7) == 4 && scale == 0 ) {
524 AppendToBuffer(
"[%s]", NameOfCPURegister(base));
526 }
else if (base == 5) {
528 int32_t disp = *
reinterpret_cast<int32_t*
>(modrmp + 2);
529 AppendToBuffer(
"[%s*%d%s0x%x]",
530 NameOfCPURegister(index),
532 disp < 0 ?
"-" :
"+",
533 disp < 0 ? -disp : disp);
535 }
else if (index != 4 && base != 5) {
537 AppendToBuffer(
"[%s+%s*%d]",
538 NameOfCPURegister(base),
539 NameOfCPURegister(index),
543 UnimplementedInstruction();
547 AppendToBuffer(
"[%s]", NameOfCPURegister(rm));
554 byte sib = *(modrmp + 1);
555 int scale, index, base;
556 get_sib(sib, &scale, &index, &base);
557 int disp = (mod == 2) ? *reinterpret_cast<int32_t*>(modrmp + 2)
558 : *
reinterpret_cast<int8_t*
>(modrmp + 2);
559 if (index == 4 && (base & 7) == 4 && scale == 0 ) {
560 AppendToBuffer(
"[%s%s0x%x]",
561 NameOfCPURegister(base),
562 disp < 0 ?
"-" :
"+",
563 disp < 0 ? -disp : disp);
565 AppendToBuffer(
"[%s+%s*%d%s0x%x]",
566 NameOfCPURegister(base),
567 NameOfCPURegister(index),
569 disp < 0 ?
"-" :
"+",
570 disp < 0 ? -disp : disp);
572 return mod == 2 ? 6 : 3;
575 int disp = (mod == 2) ? *reinterpret_cast<int32_t*>(modrmp + 1)
576 : *
reinterpret_cast<int8_t*
>(modrmp + 1);
577 AppendToBuffer(
"[%s%s0x%x]",
578 NameOfCPURegister(rm),
579 disp < 0 ?
"-" :
"+",
580 disp < 0 ? -disp : disp);
581 if (rm == i::kRootRegister.code()) {
583 TryAppendRootRelativeName(disp);
585 return (mod == 2) ? 5 : 2;
589 AppendToBuffer(
"%s", (this->*register_name)(rm));
592 UnimplementedInstruction();
599 int DisassemblerX64::PrintImmediate(byte* data, OperandSize size) {
603 case OPERAND_BYTE_SIZE:
607 case OPERAND_WORD_SIZE:
608 value = *
reinterpret_cast<int16_t*
>(data);
611 case OPERAND_DOUBLEWORD_SIZE:
612 value = *
reinterpret_cast<uint32_t*
>(data);
615 case OPERAND_QUADWORD_SIZE:
616 value = *
reinterpret_cast<int32_t*
>(data);
622 AppendToBuffer(
"%" PRIx64, value);
627 int DisassemblerX64::PrintRightOperand(byte* modrmp) {
628 return PrintRightOperandHelper(modrmp,
629 &DisassemblerX64::NameOfCPURegister);
633 int DisassemblerX64::PrintRightByteOperand(byte* modrmp) {
634 return PrintRightOperandHelper(modrmp,
635 &DisassemblerX64::NameOfByteCPURegister);
639 int DisassemblerX64::PrintRightXMMOperand(byte* modrmp) {
640 return PrintRightOperandHelper(modrmp,
641 &DisassemblerX64::NameOfXMMRegister);
647 int DisassemblerX64::PrintOperands(
const char* mnem,
648 OperandType op_order,
652 get_modrm(modrm, &mod, ®op, &rm);
654 const char* register_name =
655 byte_size_operand_ ? NameOfByteCPURegister(regop)
656 : NameOfCPURegister(regop);
658 case REG_OPER_OP_ORDER: {
659 AppendToBuffer(
"%s%c %s,",
663 advance = byte_size_operand_ ? PrintRightByteOperand(data)
664 : PrintRightOperand(data);
667 case OPER_REG_OP_ORDER: {
668 AppendToBuffer(
"%s%c ", mnem, operand_size_code());
669 advance = byte_size_operand_ ? PrintRightByteOperand(data)
670 : PrintRightOperand(data);
671 AppendToBuffer(
",%s", register_name);
684 int DisassemblerX64::PrintImmediateOp(byte* data) {
685 bool byte_size_immediate = (*data & 0x02) != 0;
686 byte modrm = *(data + 1);
688 get_modrm(modrm, &mod, ®op, &rm);
689 const char* mnem =
"Imm???";
716 UnimplementedInstruction();
718 AppendToBuffer(
"%s%c ", mnem, operand_size_code());
719 int count = PrintRightOperand(data + 1);
720 AppendToBuffer(
",0x");
721 OperandSize immediate_size =
722 byte_size_immediate ? OPERAND_BYTE_SIZE : operand_size();
723 count += PrintImmediate(data + 1 + count, immediate_size);
729 int DisassemblerX64::F6F7Instruction(byte* data) {
730 DCHECK(*data == 0xF7 || *data == 0xF6);
731 byte modrm = *(data + 1);
733 get_modrm(modrm, &mod, ®op, &rm);
734 if (mod == 3 && regop != 0) {
735 const char* mnem =
nullptr;
756 UnimplementedInstruction();
758 AppendToBuffer(
"%s%c %s",
761 NameOfCPURegister(rm));
763 }
else if (regop == 0) {
764 AppendToBuffer(
"test%c ", operand_size_code());
765 int count = PrintRightOperand(data + 1);
766 AppendToBuffer(
",0x");
767 count += PrintImmediate(data + 1 + count, operand_size());
770 UnimplementedInstruction();
776 int DisassemblerX64::ShiftInstruction(byte* data) {
777 byte op = *data & (~1);
779 if (op != 0xD0 && op != 0xD2 && op != 0xC0) {
780 UnimplementedInstruction();
785 byte modrm = *(data + count);
787 get_modrm(modrm, &mod, ®op, &rm);
789 const char* mnem =
nullptr;
813 UnimplementedInstruction();
816 DCHECK_NOT_NULL(mnem);
817 AppendToBuffer(
"%s%c ", mnem, operand_size_code());
819 count += PrintRightOperand(data + count);
821 AppendToBuffer(
", cl");
828 imm8 = *(data + count);
831 AppendToBuffer(
", %d", imm8);
838 int DisassemblerX64::JumpShort(byte* data) {
839 DCHECK_EQ(0xEB, *data);
840 byte b = *(data + 1);
841 byte* dest = data +
static_cast<int8_t
>(b) + 2;
842 AppendToBuffer(
"jmp %s", NameOfAddress(dest));
848 int DisassemblerX64::JumpConditional(byte* data) {
849 DCHECK_EQ(0x0F, *data);
850 byte cond = *(data + 1) & 0x0F;
851 byte* dest = data + *
reinterpret_cast<int32_t*
>(data + 2) + 6;
852 const char* mnem = conditional_code_suffix[cond];
853 AppendToBuffer(
"j%s %s", mnem, NameOfAddress(dest));
859 int DisassemblerX64::JumpConditionalShort(byte* data) {
860 byte cond = *data & 0x0F;
861 byte b = *(data + 1);
862 byte* dest = data +
static_cast<int8_t
>(b) + 2;
863 const char* mnem = conditional_code_suffix[cond];
864 AppendToBuffer(
"j%s %s", mnem, NameOfAddress(dest));
870 int DisassemblerX64::SetCC(byte* data) {
871 DCHECK_EQ(0x0F, *data);
872 byte cond = *(data + 1) & 0x0F;
873 const char* mnem = conditional_code_suffix[cond];
874 AppendToBuffer(
"set%s%c ", mnem, operand_size_code());
875 PrintRightByteOperand(data + 2);
879 const char* sf_str[4] = {
"",
"rl",
"ra",
"ll"};
881 int DisassemblerX64::AVXInstruction(byte* data) {
883 byte* current = data + 1;
884 if (vex_66() && vex_0f38()) {
885 int mod, regop, rm, vvvv = vex_vreg();
886 get_modrm(*current, &mod, ®op, &rm);
889 AppendToBuffer(
"vfmadd132s%c %s,%s,", float_size_code(),
890 NameOfXMMRegister(regop), NameOfXMMRegister(vvvv));
891 current += PrintRightXMMOperand(current);
894 AppendToBuffer(
"vfmadd213s%c %s,%s,", float_size_code(),
895 NameOfXMMRegister(regop), NameOfXMMRegister(vvvv));
896 current += PrintRightXMMOperand(current);
899 AppendToBuffer(
"vfmadd231s%c %s,%s,", float_size_code(),
900 NameOfXMMRegister(regop), NameOfXMMRegister(vvvv));
901 current += PrintRightXMMOperand(current);
904 AppendToBuffer(
"vfmsub132s%c %s,%s,", float_size_code(),
905 NameOfXMMRegister(regop), NameOfXMMRegister(vvvv));
906 current += PrintRightXMMOperand(current);
909 AppendToBuffer(
"vfmsub213s%c %s,%s,", float_size_code(),
910 NameOfXMMRegister(regop), NameOfXMMRegister(vvvv));
911 current += PrintRightXMMOperand(current);
914 AppendToBuffer(
"vfmsub231s%c %s,%s,", float_size_code(),
915 NameOfXMMRegister(regop), NameOfXMMRegister(vvvv));
916 current += PrintRightXMMOperand(current);
919 AppendToBuffer(
"vfnmadd132s%c %s,%s,", float_size_code(),
920 NameOfXMMRegister(regop), NameOfXMMRegister(vvvv));
921 current += PrintRightXMMOperand(current);
924 AppendToBuffer(
"vfnmadd213s%c %s,%s,", float_size_code(),
925 NameOfXMMRegister(regop), NameOfXMMRegister(vvvv));
926 current += PrintRightXMMOperand(current);
929 AppendToBuffer(
"vfnmadd231s%c %s,%s,", float_size_code(),
930 NameOfXMMRegister(regop), NameOfXMMRegister(vvvv));
931 current += PrintRightXMMOperand(current);
934 AppendToBuffer(
"vfnmsub132s%c %s,%s,", float_size_code(),
935 NameOfXMMRegister(regop), NameOfXMMRegister(vvvv));
936 current += PrintRightXMMOperand(current);
939 AppendToBuffer(
"vfnmsub213s%c %s,%s,", float_size_code(),
940 NameOfXMMRegister(regop), NameOfXMMRegister(vvvv));
941 current += PrintRightXMMOperand(current);
944 AppendToBuffer(
"vfnmsub231s%c %s,%s,", float_size_code(),
945 NameOfXMMRegister(regop), NameOfXMMRegister(vvvv));
946 current += PrintRightXMMOperand(current);
949 AppendToBuffer(
"shlx%c %s,", operand_size_code(),
950 NameOfCPURegister(regop));
951 current += PrintRightOperand(current);
952 AppendToBuffer(
",%s", NameOfCPURegister(vvvv));
954 #define DECLARE_SSE_AVX_DIS_CASE(instruction, notUsed1, notUsed2, notUsed3, \ 957 AppendToBuffer("v" #instruction " %s,%s,", NameOfXMMRegister(regop), \ 958 NameOfXMMRegister(vvvv)); \ 959 current += PrintRightXMMOperand(current); \ 963 SSSE3_INSTRUCTION_LIST(DECLARE_SSE_AVX_DIS_CASE)
964 SSE4_INSTRUCTION_LIST(DECLARE_SSE_AVX_DIS_CASE)
965 #undef DECLARE_SSE_AVX_DIS_CASE 967 UnimplementedInstruction();
969 }
else if (vex_66() && vex_0f3a()) {
970 int mod, regop, rm, vvvv = vex_vreg();
971 get_modrm(*current, &mod, ®op, &rm);
974 AppendToBuffer(
"vroundss %s,%s,", NameOfXMMRegister(regop),
975 NameOfXMMRegister(vvvv));
976 current += PrintRightXMMOperand(current);
977 AppendToBuffer(
",0x%x", *current++);
980 AppendToBuffer(
"vroundsd %s,%s,", NameOfXMMRegister(regop),
981 NameOfXMMRegister(vvvv));
982 current += PrintRightXMMOperand(current);
983 AppendToBuffer(
",0x%x", *current++);
986 AppendToBuffer(
"vpextrb ");
987 current += PrintRightByteOperand(current);
988 AppendToBuffer(
",%s,0x%x,", NameOfXMMRegister(regop), *current++);
991 AppendToBuffer(
"vpextrw ");
992 current += PrintRightOperand(current);
993 AppendToBuffer(
",%s,0x%x,", NameOfXMMRegister(regop), *current++);
996 AppendToBuffer(
"vpextrd ");
997 current += PrintRightOperand(current);
998 AppendToBuffer(
",%s,0x%x,", NameOfXMMRegister(regop), *current++);
1001 AppendToBuffer(
"vpinsrb %s,%s,", NameOfXMMRegister(regop),
1002 NameOfXMMRegister(vvvv));
1003 current += PrintRightByteOperand(current);
1004 AppendToBuffer(
",0x%x", *current++);
1007 AppendToBuffer(
"vpinsrd %s,%s,", NameOfXMMRegister(regop),
1008 NameOfXMMRegister(vvvv));
1009 current += PrintRightOperand(current);
1010 AppendToBuffer(
",0x%x", *current++);
1013 UnimplementedInstruction();
1015 }
else if (vex_f3() && vex_0f()) {
1016 int mod, regop, rm, vvvv = vex_vreg();
1017 get_modrm(*current, &mod, ®op, &rm);
1020 AppendToBuffer(
"vmovss %s,", NameOfXMMRegister(regop));
1022 AppendToBuffer(
"%s,", NameOfXMMRegister(vvvv));
1024 current += PrintRightXMMOperand(current);
1027 AppendToBuffer(
"vmovss ");
1028 current += PrintRightXMMOperand(current);
1030 AppendToBuffer(
",%s", NameOfXMMRegister(vvvv));
1032 AppendToBuffer(
",%s", NameOfXMMRegister(regop));
1035 AppendToBuffer(
"%s %s,%s,", vex_w() ?
"vcvtqsi2ss" :
"vcvtlsi2ss",
1036 NameOfXMMRegister(regop), NameOfXMMRegister(vvvv));
1037 current += PrintRightOperand(current);
1040 AppendToBuffer(
"vcvttss2si%s %s,", vex_w() ?
"q" :
"",
1041 NameOfCPURegister(regop));
1042 current += PrintRightXMMOperand(current);
1045 AppendToBuffer(
"vsqrtss %s,%s,", NameOfXMMRegister(regop),
1046 NameOfXMMRegister(vvvv));
1047 current += PrintRightXMMOperand(current);
1050 AppendToBuffer(
"vaddss %s,%s,", NameOfXMMRegister(regop),
1051 NameOfXMMRegister(vvvv));
1052 current += PrintRightXMMOperand(current);
1055 AppendToBuffer(
"vmulss %s,%s,", NameOfXMMRegister(regop),
1056 NameOfXMMRegister(vvvv));
1057 current += PrintRightXMMOperand(current);
1060 AppendToBuffer(
"vcvtss2sd %s,%s,", NameOfXMMRegister(regop),
1061 NameOfXMMRegister(vvvv));
1062 current += PrintRightXMMOperand(current);
1065 AppendToBuffer(
"vsubss %s,%s,", NameOfXMMRegister(regop),
1066 NameOfXMMRegister(vvvv));
1067 current += PrintRightXMMOperand(current);
1070 AppendToBuffer(
"vminss %s,%s,", NameOfXMMRegister(regop),
1071 NameOfXMMRegister(vvvv));
1072 current += PrintRightXMMOperand(current);
1075 AppendToBuffer(
"vdivss %s,%s,", NameOfXMMRegister(regop),
1076 NameOfXMMRegister(vvvv));
1077 current += PrintRightXMMOperand(current);
1080 AppendToBuffer(
"vmaxss %s,%s,", NameOfXMMRegister(regop),
1081 NameOfXMMRegister(vvvv));
1082 current += PrintRightXMMOperand(current);
1085 UnimplementedInstruction();
1087 }
else if (vex_f2() && vex_0f()) {
1088 int mod, regop, rm, vvvv = vex_vreg();
1089 get_modrm(*current, &mod, ®op, &rm);
1092 AppendToBuffer(
"vmovsd %s,", NameOfXMMRegister(regop));
1094 AppendToBuffer(
"%s,", NameOfXMMRegister(vvvv));
1096 current += PrintRightXMMOperand(current);
1099 AppendToBuffer(
"vmovsd ");
1100 current += PrintRightXMMOperand(current);
1102 AppendToBuffer(
",%s", NameOfXMMRegister(vvvv));
1104 AppendToBuffer(
",%s", NameOfXMMRegister(regop));
1107 AppendToBuffer(
"%s %s,%s,", vex_w() ?
"vcvtqsi2sd" :
"vcvtlsi2sd",
1108 NameOfXMMRegister(regop), NameOfXMMRegister(vvvv));
1109 current += PrintRightOperand(current);
1112 AppendToBuffer(
"vcvttsd2si%s %s,", vex_w() ?
"q" :
"",
1113 NameOfCPURegister(regop));
1114 current += PrintRightXMMOperand(current);
1117 AppendToBuffer(
"vcvtsd2si%s %s,", vex_w() ?
"q" :
"",
1118 NameOfCPURegister(regop));
1119 current += PrintRightXMMOperand(current);
1122 AppendToBuffer(
"vsqrtsd %s,%s,", NameOfXMMRegister(regop),
1123 NameOfXMMRegister(vvvv));
1124 current += PrintRightXMMOperand(current);
1127 AppendToBuffer(
"vaddsd %s,%s,", NameOfXMMRegister(regop),
1128 NameOfXMMRegister(vvvv));
1129 current += PrintRightXMMOperand(current);
1132 AppendToBuffer(
"vmulsd %s,%s,", NameOfXMMRegister(regop),
1133 NameOfXMMRegister(vvvv));
1134 current += PrintRightXMMOperand(current);
1137 AppendToBuffer(
"vcvtsd2ss %s,%s,", NameOfXMMRegister(regop),
1138 NameOfXMMRegister(vvvv));
1139 current += PrintRightXMMOperand(current);
1142 AppendToBuffer(
"vsubsd %s,%s,", NameOfXMMRegister(regop),
1143 NameOfXMMRegister(vvvv));
1144 current += PrintRightXMMOperand(current);
1147 AppendToBuffer(
"vminsd %s,%s,", NameOfXMMRegister(regop),
1148 NameOfXMMRegister(vvvv));
1149 current += PrintRightXMMOperand(current);
1152 AppendToBuffer(
"vdivsd %s,%s,", NameOfXMMRegister(regop),
1153 NameOfXMMRegister(vvvv));
1154 current += PrintRightXMMOperand(current);
1157 AppendToBuffer(
"vmaxsd %s,%s,", NameOfXMMRegister(regop),
1158 NameOfXMMRegister(vvvv));
1159 current += PrintRightXMMOperand(current);
1162 AppendToBuffer(
"vlddqu %s,", NameOfXMMRegister(regop));
1163 current += PrintRightXMMOperand(current);
1166 AppendToBuffer(
"vhaddps %s,%s,", NameOfXMMRegister(regop),
1167 NameOfXMMRegister(vvvv));
1168 current += PrintRightXMMOperand(current);
1171 UnimplementedInstruction();
1173 }
else if (vex_none() && vex_0f38()) {
1174 int mod, regop, rm, vvvv = vex_vreg();
1175 get_modrm(*current, &mod, ®op, &rm);
1176 const char* mnem =
"?";
1179 AppendToBuffer(
"andn%c %s,%s,", operand_size_code(),
1180 NameOfCPURegister(regop), NameOfCPURegister(vvvv));
1181 current += PrintRightOperand(current);
1184 AppendToBuffer(
"bzhi%c %s,", operand_size_code(),
1185 NameOfCPURegister(regop));
1186 current += PrintRightOperand(current);
1187 AppendToBuffer(
",%s", NameOfCPURegister(vvvv));
1190 AppendToBuffer(
"bextr%c %s,", operand_size_code(),
1191 NameOfCPURegister(regop));
1192 current += PrintRightOperand(current);
1193 AppendToBuffer(
",%s", NameOfCPURegister(vvvv));
1207 UnimplementedInstruction();
1209 AppendToBuffer(
"%s%c %s,", mnem, operand_size_code(),
1210 NameOfCPURegister(vvvv));
1211 current += PrintRightOperand(current);
1215 UnimplementedInstruction();
1217 }
else if (vex_f2() && vex_0f38()) {
1218 int mod, regop, rm, vvvv = vex_vreg();
1219 get_modrm(*current, &mod, ®op, &rm);
1222 AppendToBuffer(
"pdep%c %s,%s,", operand_size_code(),
1223 NameOfCPURegister(regop), NameOfCPURegister(vvvv));
1224 current += PrintRightOperand(current);
1227 AppendToBuffer(
"mulx%c %s,%s,", operand_size_code(),
1228 NameOfCPURegister(regop), NameOfCPURegister(vvvv));
1229 current += PrintRightOperand(current);
1232 AppendToBuffer(
"shrx%c %s,", operand_size_code(),
1233 NameOfCPURegister(regop));
1234 current += PrintRightOperand(current);
1235 AppendToBuffer(
",%s", NameOfCPURegister(vvvv));
1238 UnimplementedInstruction();
1240 }
else if (vex_f3() && vex_0f38()) {
1241 int mod, regop, rm, vvvv = vex_vreg();
1242 get_modrm(*current, &mod, ®op, &rm);
1245 AppendToBuffer(
"pext%c %s,%s,", operand_size_code(),
1246 NameOfCPURegister(regop), NameOfCPURegister(vvvv));
1247 current += PrintRightOperand(current);
1250 AppendToBuffer(
"sarx%c %s,", operand_size_code(),
1251 NameOfCPURegister(regop));
1252 current += PrintRightOperand(current);
1253 AppendToBuffer(
",%s", NameOfCPURegister(vvvv));
1256 UnimplementedInstruction();
1258 }
else if (vex_f2() && vex_0f3a()) {
1260 get_modrm(*current, &mod, ®op, &rm);
1263 AppendToBuffer(
"rorx%c %s,", operand_size_code(),
1264 NameOfCPURegister(regop));
1265 current += PrintRightOperand(current);
1266 switch (operand_size()) {
1267 case OPERAND_DOUBLEWORD_SIZE:
1268 AppendToBuffer(
",%d", *current & 0x1F);
1270 case OPERAND_QUADWORD_SIZE:
1271 AppendToBuffer(
",%d", *current & 0x3F);
1274 UnimplementedInstruction();
1279 UnimplementedInstruction();
1281 }
else if (vex_none() && vex_0f()) {
1282 int mod, regop, rm, vvvv = vex_vreg();
1283 get_modrm(*current, &mod, ®op, &rm);
1286 AppendToBuffer(
"vmovups %s,", NameOfXMMRegister(regop));
1287 current += PrintRightXMMOperand(current);
1290 AppendToBuffer(
"vmovups ");
1291 current += PrintRightXMMOperand(current);
1292 AppendToBuffer(
",%s", NameOfXMMRegister(regop));
1295 AppendToBuffer(
"vmovaps %s,", NameOfXMMRegister(regop));
1296 current += PrintRightXMMOperand(current);
1299 AppendToBuffer(
"vmovaps ");
1300 current += PrintRightXMMOperand(current);
1301 AppendToBuffer(
",%s", NameOfXMMRegister(regop));
1304 AppendToBuffer(
"vucomiss %s,", NameOfXMMRegister(regop));
1305 current += PrintRightXMMOperand(current);
1308 AppendToBuffer(
"vmovmskps %s,", NameOfCPURegister(regop));
1309 current += PrintRightXMMOperand(current);
1312 AppendToBuffer(
"vandps %s,%s,", NameOfXMMRegister(regop),
1313 NameOfXMMRegister(vvvv));
1314 current += PrintRightXMMOperand(current);
1317 AppendToBuffer(
"vxorps %s,%s,", NameOfXMMRegister(regop),
1318 NameOfXMMRegister(vvvv));
1319 current += PrintRightXMMOperand(current);
1322 AppendToBuffer(
"vcmpps %s,%s,", NameOfXMMRegister(regop),
1323 NameOfXMMRegister(vvvv));
1324 current += PrintRightXMMOperand(current);
1325 const char*
const pseudo_op[] = {
"eq",
"lt",
"le",
"unord",
1326 "neq",
"nlt",
"nle",
"ord"};
1327 AppendToBuffer(
", (%s)", pseudo_op[*current]);
1332 UnimplementedInstruction();
1334 }
else if (vex_66() && vex_0f()) {
1335 int mod, regop, rm, vvvv = vex_vreg();
1336 get_modrm(*current, &mod, ®op, &rm);
1339 AppendToBuffer(
"vmovupd %s,", NameOfXMMRegister(regop));
1340 current += PrintRightXMMOperand(current);
1343 AppendToBuffer(
"vmovupd ");
1344 current += PrintRightXMMOperand(current);
1345 AppendToBuffer(
",%s", NameOfXMMRegister(regop));
1348 AppendToBuffer(
"vmovapd %s,", NameOfXMMRegister(regop));
1349 current += PrintRightXMMOperand(current);
1352 AppendToBuffer(
"vmovapd ");
1353 current += PrintRightXMMOperand(current);
1354 AppendToBuffer(
",%s", NameOfXMMRegister(regop));
1357 AppendToBuffer(
"vucomisd %s,", NameOfXMMRegister(regop));
1358 current += PrintRightXMMOperand(current);
1361 AppendToBuffer(
"vmovmskpd %s,", NameOfCPURegister(regop));
1362 current += PrintRightXMMOperand(current);
1365 AppendToBuffer(
"vandpd %s,%s,", NameOfXMMRegister(regop),
1366 NameOfXMMRegister(vvvv));
1367 current += PrintRightXMMOperand(current);
1370 AppendToBuffer(
"vorpd %s,%s,", NameOfXMMRegister(regop),
1371 NameOfXMMRegister(vvvv));
1372 current += PrintRightXMMOperand(current);
1375 AppendToBuffer(
"vxorpd %s,%s,", NameOfXMMRegister(regop),
1376 NameOfXMMRegister(vvvv));
1377 current += PrintRightXMMOperand(current);
1380 AppendToBuffer(
"vmov%c %s,", vex_w() ?
'q' :
'd',
1381 NameOfXMMRegister(regop));
1382 current += PrintRightOperand(current);
1385 AppendToBuffer(
"vpshufd %s,", NameOfXMMRegister(regop));
1386 current += PrintRightXMMOperand(current);
1387 AppendToBuffer(
",0x%x", *current++);
1390 AppendToBuffer(
"vps%sw %s,", sf_str[regop / 2],
1391 NameOfXMMRegister(vvvv));
1392 current += PrintRightXMMOperand(current);
1393 AppendToBuffer(
",%u", *current++);
1396 AppendToBuffer(
"vps%sd %s,", sf_str[regop / 2],
1397 NameOfXMMRegister(vvvv));
1398 current += PrintRightXMMOperand(current);
1399 AppendToBuffer(
",%u", *current++);
1402 AppendToBuffer(
"vps%sq %s,", sf_str[regop / 2],
1403 NameOfXMMRegister(vvvv));
1404 current += PrintRightXMMOperand(current);
1405 AppendToBuffer(
",%u", *current++);
1408 AppendToBuffer(
"vmov%c ", vex_w() ?
'q' :
'd');
1409 current += PrintRightOperand(current);
1410 AppendToBuffer(
",%s", NameOfXMMRegister(regop));
1413 AppendToBuffer(
"vcmppd %s,%s,", NameOfXMMRegister(regop),
1414 NameOfXMMRegister(vvvv));
1415 current += PrintRightXMMOperand(current);
1416 const char*
const pseudo_op[] = {
"eq",
"lt",
"le",
"unord",
1417 "neq",
"nlt",
"nle",
"ord"};
1418 AppendToBuffer(
", (%s)", pseudo_op[*current]);
1423 AppendToBuffer(
"vpinsrw %s,%s,", NameOfXMMRegister(regop),
1424 NameOfXMMRegister(vvvv));
1425 current += PrintRightOperand(current);
1426 AppendToBuffer(
",0x%x", *current++);
1429 AppendToBuffer(
"vpextrw %s,", NameOfCPURegister(regop));
1430 current += PrintRightXMMOperand(current);
1431 AppendToBuffer(
",0x%x", *current++);
1433 #define DECLARE_SSE_AVX_DIS_CASE(instruction, notUsed1, notUsed2, opcode) \ 1434 case 0x##opcode: { \ 1435 AppendToBuffer("v" #instruction " %s,%s,", NameOfXMMRegister(regop), \ 1436 NameOfXMMRegister(vvvv)); \ 1437 current += PrintRightXMMOperand(current); \ 1441 SSE2_INSTRUCTION_LIST(DECLARE_SSE_AVX_DIS_CASE)
1442 #undef DECLARE_SSE_AVX_DIS_CASE 1444 UnimplementedInstruction();
1448 UnimplementedInstruction();
1451 return static_cast<int>(current - data);
1455 int DisassemblerX64::FPUInstruction(byte* data) {
1456 byte escape_opcode = *data;
1457 DCHECK_EQ(0xD8, escape_opcode & 0xF8);
1458 byte modrm_byte = *(data+1);
1460 if (modrm_byte >= 0xC0) {
1461 return RegisterFPUInstruction(escape_opcode, modrm_byte);
1463 return MemoryFPUInstruction(escape_opcode, modrm_byte, data+1);
1467 int DisassemblerX64::MemoryFPUInstruction(
int escape_opcode,
1469 byte* modrm_start) {
1470 const char* mnem =
"?";
1471 int regop = (modrm_byte >> 3) & 0x7;
1472 switch (escape_opcode) {
1473 case 0xD9:
switch (regop) {
1474 case 0: mnem =
"fld_s";
break;
1475 case 3: mnem =
"fstp_s";
break;
1476 case 7: mnem =
"fstcw";
break;
1477 default: UnimplementedInstruction();
1481 case 0xDB:
switch (regop) {
1482 case 0: mnem =
"fild_s";
break;
1483 case 1: mnem =
"fisttp_s";
break;
1484 case 2: mnem =
"fist_s";
break;
1485 case 3: mnem =
"fistp_s";
break;
1486 default: UnimplementedInstruction();
1490 case 0xDD:
switch (regop) {
1491 case 0: mnem =
"fld_d";
break;
1492 case 3: mnem =
"fstp_d";
break;
1493 default: UnimplementedInstruction();
1497 case 0xDF:
switch (regop) {
1498 case 5: mnem =
"fild_d";
break;
1499 case 7: mnem =
"fistp_d";
break;
1500 default: UnimplementedInstruction();
1504 default: UnimplementedInstruction();
1506 AppendToBuffer(
"%s ", mnem);
1507 int count = PrintRightOperand(modrm_start);
1511 int DisassemblerX64::RegisterFPUInstruction(
int escape_opcode,
1513 bool has_register =
false;
1514 const char* mnem =
"?";
1516 switch (escape_opcode) {
1518 UnimplementedInstruction();
1522 switch (modrm_byte & 0xF8) {
1525 has_register =
true;
1529 has_register =
true;
1532 switch (modrm_byte) {
1533 case 0xE0: mnem =
"fchs";
break;
1534 case 0xE1: mnem =
"fabs";
break;
1535 case 0xE3: mnem =
"fninit";
break;
1536 case 0xE4: mnem =
"ftst";
break;
1537 case 0xE8: mnem =
"fld1";
break;
1538 case 0xEB: mnem =
"fldpi";
break;
1539 case 0xED: mnem =
"fldln2";
break;
1540 case 0xEE: mnem =
"fldz";
break;
1541 case 0xF0: mnem =
"f2xm1";
break;
1542 case 0xF1: mnem =
"fyl2x";
break;
1543 case 0xF2: mnem =
"fptan";
break;
1544 case 0xF5: mnem =
"fprem1";
break;
1545 case 0xF7: mnem =
"fincstp";
break;
1546 case 0xF8: mnem =
"fprem";
break;
1547 case 0xFC: mnem =
"frndint";
break;
1548 case 0xFD: mnem =
"fscale";
break;
1549 case 0xFE: mnem =
"fsin";
break;
1550 case 0xFF: mnem =
"fcos";
break;
1551 default: UnimplementedInstruction();
1557 if (modrm_byte == 0xE9) {
1560 UnimplementedInstruction();
1565 if ((modrm_byte & 0xF8) == 0xE8) {
1567 has_register =
true;
1568 }
else if (modrm_byte == 0xE2) {
1570 }
else if (modrm_byte == 0xE3) {
1573 UnimplementedInstruction();
1578 has_register =
true;
1579 switch (modrm_byte & 0xF8) {
1580 case 0xC0: mnem =
"fadd";
break;
1581 case 0xE8: mnem =
"fsub";
break;
1582 case 0xC8: mnem =
"fmul";
break;
1583 case 0xF8: mnem =
"fdiv";
break;
1584 default: UnimplementedInstruction();
1589 has_register =
true;
1590 switch (modrm_byte & 0xF8) {
1591 case 0xC0: mnem =
"ffree";
break;
1592 case 0xD8: mnem =
"fstp";
break;
1593 default: UnimplementedInstruction();
1598 if (modrm_byte == 0xD9) {
1601 has_register =
true;
1602 switch (modrm_byte & 0xF8) {
1603 case 0xC0: mnem =
"faddp";
break;
1604 case 0xE8: mnem =
"fsubp";
break;
1605 case 0xC8: mnem =
"fmulp";
break;
1606 case 0xF8: mnem =
"fdivp";
break;
1607 default: UnimplementedInstruction();
1613 if (modrm_byte == 0xE0) {
1615 }
else if ((modrm_byte & 0xF8) == 0xE8) {
1617 has_register =
true;
1621 default: UnimplementedInstruction();
1625 AppendToBuffer(
"%s st%d", mnem, modrm_byte & 0x7);
1627 AppendToBuffer(
"%s", mnem);
1637 int DisassemblerX64::TwoByteOpcodeInstruction(byte* data) {
1638 byte opcode = *(data + 1);
1639 byte* current = data + 2;
1641 const char* mnemonic = TwoByteMnemonic(opcode);
1642 if (operand_size_ == 0x66) {
1645 if (opcode == 0x38) {
1646 byte third_byte = *current;
1648 get_modrm(*current, &mod, ®op, &rm);
1649 switch (third_byte) {
1650 #define SSE34_DIS_CASE(instruction, notUsed1, notUsed2, notUsed3, opcode) \ 1651 case 0x##opcode: { \ 1652 AppendToBuffer(#instruction " %s,", NameOfXMMRegister(regop)); \ 1653 current += PrintRightXMMOperand(current); \ 1657 SSSE3_INSTRUCTION_LIST(SSE34_DIS_CASE)
1658 SSE4_INSTRUCTION_LIST(SSE34_DIS_CASE)
1659 #undef SSE34_DIS_CASE 1661 UnimplementedInstruction();
1663 }
else if (opcode == 0x3A) {
1664 byte third_byte = *current;
1666 if (third_byte == 0x17) {
1667 get_modrm(*current, &mod, ®op, &rm);
1668 AppendToBuffer(
"extractps ");
1669 current += PrintRightOperand(current);
1670 AppendToBuffer(
",%s,%d", NameOfXMMRegister(regop), (*current) & 3);
1672 }
else if (third_byte == 0x0A) {
1673 get_modrm(*current, &mod, ®op, &rm);
1674 AppendToBuffer(
"roundss %s,", NameOfXMMRegister(regop));
1675 current += PrintRightXMMOperand(current);
1676 AppendToBuffer(
",0x%x", (*current) & 3);
1678 }
else if (third_byte == 0x0B) {
1679 get_modrm(*current, &mod, ®op, &rm);
1681 AppendToBuffer(
"roundsd %s,", NameOfXMMRegister(regop));
1682 current += PrintRightXMMOperand(current);
1683 AppendToBuffer(
",0x%x", (*current) & 3);
1685 }
else if (third_byte == 0x0E) {
1686 get_modrm(*current, &mod, ®op, &rm);
1687 AppendToBuffer(
"pblendw %s,", NameOfXMMRegister(regop));
1688 current += PrintRightXMMOperand(data);
1689 AppendToBuffer(
",0x%x", (*current) & 3);
1691 }
else if (third_byte == 0x0F) {
1692 get_modrm(*data, &mod, ®op, &rm);
1693 AppendToBuffer(
"palignr %s,", NameOfXMMRegister(regop));
1694 current += PrintRightXMMOperand(data);
1695 AppendToBuffer(
",0x%x", (*current) & 3);
1697 }
else if (third_byte == 0x14) {
1698 get_modrm(*current, &mod, ®op, &rm);
1699 AppendToBuffer(
"pextrb ");
1700 current += PrintRightOperand(current);
1701 AppendToBuffer(
",%s,%d", NameOfXMMRegister(regop), (*current) & 3);
1703 }
else if (third_byte == 0x15) {
1704 get_modrm(*current, &mod, ®op, &rm);
1705 AppendToBuffer(
"pextrw ");
1706 current += PrintRightOperand(current);
1707 AppendToBuffer(
",%s,%d", NameOfXMMRegister(regop), (*current) & 7);
1709 }
else if (third_byte == 0x16) {
1710 get_modrm(*current, &mod, ®op, &rm);
1711 AppendToBuffer(
"pextrd ");
1712 current += PrintRightOperand(current);
1713 AppendToBuffer(
",%s,%d", NameOfXMMRegister(regop), (*current) & 3);
1715 }
else if (third_byte == 0x20) {
1716 get_modrm(*current, &mod, ®op, &rm);
1717 AppendToBuffer(
"pinsrd ");
1718 AppendToBuffer(
" %s,", NameOfXMMRegister(regop));
1719 current += PrintRightOperand(current);
1720 AppendToBuffer(
",%d", (*current) & 3);
1722 }
else if (third_byte == 0x21) {
1723 get_modrm(*current, &mod, ®op, &rm);
1725 AppendToBuffer(
"insertps %s,", NameOfXMMRegister(regop));
1726 current += PrintRightXMMOperand(current);
1727 AppendToBuffer(
",0x%x", (*current) & 3);
1729 }
else if (third_byte == 0x22) {
1730 get_modrm(*current, &mod, ®op, &rm);
1731 AppendToBuffer(
"pinsrd ");
1732 AppendToBuffer(
" %s,", NameOfXMMRegister(regop));
1733 current += PrintRightOperand(current);
1734 AppendToBuffer(
",%d", (*current) & 3);
1737 UnimplementedInstruction();
1740 get_modrm(*current, &mod, ®op, &rm);
1741 if (opcode == 0x1F) {
1748 }
else if (mod == 2) {
1751 AppendToBuffer(
"nop");
1752 }
else if (opcode == 0x10) {
1753 AppendToBuffer(
"movupd %s,", NameOfXMMRegister(regop));
1754 current += PrintRightXMMOperand(current);
1755 }
else if (opcode == 0x11) {
1756 AppendToBuffer(
"movupd ");
1757 current += PrintRightXMMOperand(current);
1758 AppendToBuffer(
",%s", NameOfXMMRegister(regop));
1759 }
else if (opcode == 0x28) {
1760 AppendToBuffer(
"movapd %s,", NameOfXMMRegister(regop));
1761 current += PrintRightXMMOperand(current);
1762 }
else if (opcode == 0x29) {
1763 AppendToBuffer(
"movapd ");
1764 current += PrintRightXMMOperand(current);
1765 AppendToBuffer(
",%s", NameOfXMMRegister(regop));
1766 }
else if (opcode == 0x6E) {
1767 AppendToBuffer(
"mov%c %s,",
1768 rex_w() ?
'q' :
'd',
1769 NameOfXMMRegister(regop));
1770 current += PrintRightOperand(current);
1771 }
else if (opcode == 0x6F) {
1772 AppendToBuffer(
"movdqa %s,",
1773 NameOfXMMRegister(regop));
1774 current += PrintRightXMMOperand(current);
1775 }
else if (opcode == 0x7E) {
1776 AppendToBuffer(
"mov%c ",
1777 rex_w() ?
'q' :
'd');
1778 current += PrintRightOperand(current);
1779 AppendToBuffer(
",%s", NameOfXMMRegister(regop));
1780 }
else if (opcode == 0x7F) {
1781 AppendToBuffer(
"movdqa ");
1782 current += PrintRightXMMOperand(current);
1783 AppendToBuffer(
",%s", NameOfXMMRegister(regop));
1784 }
else if (opcode == 0xD6) {
1785 AppendToBuffer(
"movq ");
1786 current += PrintRightXMMOperand(current);
1787 AppendToBuffer(
",%s", NameOfXMMRegister(regop));
1788 }
else if (opcode == 0x50) {
1789 AppendToBuffer(
"movmskpd %s,", NameOfCPURegister(regop));
1790 current += PrintRightXMMOperand(current);
1791 }
else if (opcode == 0x70) {
1792 AppendToBuffer(
"pshufd %s,", NameOfXMMRegister(regop));
1793 current += PrintRightXMMOperand(current);
1794 AppendToBuffer(
",0x%x", *current);
1796 }
else if (opcode == 0x71) {
1798 AppendToBuffer(
"ps%sw %s,%d", sf_str[regop / 2], NameOfXMMRegister(rm),
1801 }
else if (opcode == 0x72) {
1803 AppendToBuffer(
"ps%sd %s,%d", sf_str[regop / 2], NameOfXMMRegister(rm),
1806 }
else if (opcode == 0x73) {
1808 AppendToBuffer(
"ps%sq %s,%d", sf_str[regop / 2], NameOfXMMRegister(rm),
1811 }
else if (opcode == 0xB1) {
1812 current += PrintOperands(
"cmpxchg", OPER_REG_OP_ORDER, current);
1813 }
else if (opcode == 0xC4) {
1814 AppendToBuffer(
"pinsrw %s,", NameOfXMMRegister(regop));
1815 current += PrintRightOperand(current);
1816 AppendToBuffer(
",0x%x", (*current) & 7);
1819 const char* mnemonic;
1820 if (opcode == 0x54) {
1822 }
else if (opcode == 0x56) {
1824 }
else if (opcode == 0x57) {
1826 }
else if (opcode == 0x5B) {
1827 mnemonic =
"cvtps2dq";
1828 }
else if (opcode == 0x60) {
1829 mnemonic =
"punpcklbw";
1830 }
else if (opcode == 0x61) {
1831 mnemonic =
"punpcklwd";
1832 }
else if (opcode == 0x62) {
1833 mnemonic =
"punpckldq";
1834 }
else if (opcode == 0x63) {
1835 mnemonic =
"packsswb";
1836 }
else if (opcode == 0x64) {
1837 mnemonic =
"pcmpgtb";
1838 }
else if (opcode == 0x65) {
1839 mnemonic =
"pcmpgtw";
1840 }
else if (opcode == 0x66) {
1841 mnemonic =
"pcmpgtd";
1842 }
else if (opcode == 0x67) {
1843 mnemonic =
"packuswb";
1844 }
else if (opcode == 0x68) {
1845 mnemonic =
"punpckhbw";
1846 }
else if (opcode == 0x69) {
1847 mnemonic =
"punpckhwd";
1848 }
else if (opcode == 0x6A) {
1849 mnemonic =
"punpckhdq";
1850 }
else if (opcode == 0x6B) {
1851 mnemonic =
"packssdw";
1852 }
else if (opcode == 0x6C) {
1853 mnemonic =
"punpcklqdq";
1854 }
else if (opcode == 0x6D) {
1855 mnemonic =
"punpckhqdq";
1856 }
else if (opcode == 0x2E) {
1857 mnemonic =
"ucomisd";
1858 }
else if (opcode == 0x2F) {
1859 mnemonic =
"comisd";
1860 }
else if (opcode == 0x74) {
1861 mnemonic =
"pcmpeqb";
1862 }
else if (opcode == 0x75) {
1863 mnemonic =
"pcmpeqw";
1864 }
else if (opcode == 0x76) {
1865 mnemonic =
"pcmpeqd";
1866 }
else if (opcode == 0xD1) {
1868 }
else if (opcode == 0xD2) {
1870 }
else if (opcode == 0xD5) {
1871 mnemonic =
"pmullw";
1872 }
else if (opcode == 0xD7) {
1873 mnemonic =
"pmovmskb";
1874 }
else if (opcode == 0xD8) {
1875 mnemonic =
"psubusb";
1876 }
else if (opcode == 0xD9) {
1877 mnemonic =
"psubusw";
1878 }
else if (opcode == 0xDA) {
1880 }
else if (opcode == 0xDB) {
1881 mnemonic =
"pminub";
1882 }
else if (opcode == 0xDC) {
1883 mnemonic =
"paddusb";
1884 }
else if (opcode == 0xDD) {
1885 mnemonic =
"paddusw";
1886 }
else if (opcode == 0xDE) {
1887 mnemonic =
"pmaxub";
1888 }
else if (opcode == 0xE1) {
1890 }
else if (opcode == 0xE2) {
1892 }
else if (opcode == 0xE8) {
1893 mnemonic =
"psubsb";
1894 }
else if (opcode == 0xE9) {
1895 mnemonic =
"psubsw";
1896 }
else if (opcode == 0xEA) {
1897 mnemonic =
"pminsw";
1898 }
else if (opcode == 0xEB) {
1900 }
else if (opcode == 0xEC) {
1901 mnemonic =
"paddsb";
1902 }
else if (opcode == 0xED) {
1903 mnemonic =
"paddsw";
1904 }
else if (opcode == 0xEE) {
1905 mnemonic =
"pmaxsw";
1906 }
else if (opcode == 0xEF) {
1908 }
else if (opcode == 0xF1) {
1910 }
else if (opcode == 0xF2) {
1912 }
else if (opcode == 0xF4) {
1913 mnemonic =
"pmuludq";
1914 }
else if (opcode == 0xF8) {
1916 }
else if (opcode == 0xF9) {
1918 }
else if (opcode == 0xFA) {
1920 }
else if (opcode == 0xFC) {
1922 }
else if (opcode == 0xFD) {
1924 }
else if (opcode == 0xFE) {
1926 }
else if (opcode == 0xC2) {
1929 UnimplementedInstruction();
1931 AppendToBuffer(
"%s %s,", mnemonic, NameOfXMMRegister(regop));
1932 current += PrintRightXMMOperand(current);
1933 if (opcode == 0xC2) {
1934 const char*
const pseudo_op[] = {
"eq",
"lt",
"le",
"unord",
1935 "neq",
"nlt",
"nle",
"ord"};
1936 AppendToBuffer(
", (%s)", pseudo_op[*current]);
1941 }
else if (group_1_prefix_ == 0xF2) {
1944 if (opcode == 0x11 || opcode == 0x10) {
1946 AppendToBuffer(
"movsd ");
1948 get_modrm(*current, &mod, ®op, &rm);
1949 if (opcode == 0x11) {
1950 current += PrintRightXMMOperand(current);
1951 AppendToBuffer(
",%s", NameOfXMMRegister(regop));
1953 AppendToBuffer(
"%s,", NameOfXMMRegister(regop));
1954 current += PrintRightXMMOperand(current);
1956 }
else if (opcode == 0x2A) {
1959 get_modrm(*current, &mod, ®op, &rm);
1960 AppendToBuffer(
"%s %s,", mnemonic, NameOfXMMRegister(regop));
1961 current += PrintRightOperand(current);
1962 }
else if (opcode == 0x2C) {
1966 get_modrm(*current, &mod, ®op, &rm);
1967 AppendToBuffer(
"cvttsd2si%c %s,",
1968 operand_size_code(), NameOfCPURegister(regop));
1969 current += PrintRightXMMOperand(current);
1970 }
else if (opcode == 0x2D) {
1973 get_modrm(*current, &mod, ®op, &rm);
1974 AppendToBuffer(
"cvtsd2si%c %s,",
1975 operand_size_code(), NameOfCPURegister(regop));
1976 current += PrintRightXMMOperand(current);
1977 }
else if (opcode == 0x5B) {
1981 get_modrm(*current, &mod, ®op, &rm);
1982 AppendToBuffer(
"cvttps2dq%c %s,", operand_size_code(),
1983 NameOfCPURegister(regop));
1984 current += PrintRightXMMOperand(current);
1985 }
else if ((opcode & 0xF8) == 0x58 || opcode == 0x51) {
1988 get_modrm(*current, &mod, ®op, &rm);
1989 AppendToBuffer(
"%s %s,", mnemonic, NameOfXMMRegister(regop));
1990 current += PrintRightXMMOperand(current);
1991 }
else if (opcode == 0x70) {
1993 get_modrm(*current, &mod, ®op, &rm);
1994 AppendToBuffer(
"pshuflw %s, ", NameOfXMMRegister(regop));
1995 current += PrintRightXMMOperand(current);
1996 AppendToBuffer(
", %d", (*current) & 7);
1998 }
else if (opcode == 0xC2) {
2001 get_modrm(*current, &mod, ®op, &rm);
2002 const char*
const pseudo_op[] = {
2012 AppendToBuffer(
"%s %s,%s",
2013 pseudo_op[current[1]],
2014 NameOfXMMRegister(regop),
2015 NameOfXMMRegister(rm));
2017 }
else if (opcode == 0xF0) {
2019 get_modrm(*current, &mod, ®op, &rm);
2020 AppendToBuffer(
"lddqu %s,", NameOfXMMRegister(regop));
2021 current += PrintRightOperand(current);
2022 }
else if (opcode == 0x7C) {
2024 get_modrm(*current, &mod, ®op, &rm);
2025 AppendToBuffer(
"haddps %s,", NameOfXMMRegister(regop));
2026 current += PrintRightXMMOperand(current);
2028 UnimplementedInstruction();
2030 }
else if (group_1_prefix_ == 0xF3) {
2032 if (opcode == 0x11 || opcode == 0x10) {
2034 AppendToBuffer(
"movss ");
2036 get_modrm(*current, &mod, ®op, &rm);
2037 if (opcode == 0x11) {
2038 current += PrintRightOperand(current);
2039 AppendToBuffer(
",%s", NameOfXMMRegister(regop));
2041 AppendToBuffer(
"%s,", NameOfXMMRegister(regop));
2042 current += PrintRightOperand(current);
2044 }
else if (opcode == 0x2A) {
2047 get_modrm(*current, &mod, ®op, &rm);
2048 AppendToBuffer(
"%s %s,", mnemonic, NameOfXMMRegister(regop));
2049 current += PrintRightOperand(current);
2050 }
else if (opcode == 0x2C) {
2054 get_modrm(*current, &mod, ®op, &rm);
2055 AppendToBuffer(
"cvttss2si%c %s,",
2056 operand_size_code(), NameOfCPURegister(regop));
2057 current += PrintRightXMMOperand(current);
2058 }
else if (opcode == 0x70) {
2060 get_modrm(*current, &mod, ®op, &rm);
2061 AppendToBuffer(
"pshufhw %s, ", NameOfXMMRegister(regop));
2062 current += PrintRightXMMOperand(current);
2063 AppendToBuffer(
", %d", (*current) & 7);
2065 }
else if (opcode == 0x6F) {
2067 get_modrm(*current, &mod, ®op, &rm);
2068 AppendToBuffer(
"movdqu %s,", NameOfXMMRegister(regop));
2069 current += PrintRightXMMOperand(current);
2070 }
else if (opcode == 0x7E) {
2072 get_modrm(*current, &mod, ®op, &rm);
2073 AppendToBuffer(
"movq %s,", NameOfXMMRegister(regop));
2074 current += PrintRightXMMOperand(current);
2075 }
else if (opcode == 0x7F) {
2077 get_modrm(*current, &mod, ®op, &rm);
2078 AppendToBuffer(
"movdqu ");
2079 current += PrintRightXMMOperand(current);
2080 AppendToBuffer(
",%s", NameOfXMMRegister(regop));
2081 }
else if ((opcode & 0xF8) == 0x58 || opcode == 0x51) {
2084 get_modrm(*current, &mod, ®op, &rm);
2085 AppendToBuffer(
"%s %s,", mnemonic, NameOfXMMRegister(regop));
2086 current += PrintRightXMMOperand(current);
2087 }
else if (opcode == 0xB8) {
2089 get_modrm(*current, &mod, ®op, &rm);
2090 AppendToBuffer(
"popcnt%c %s,", operand_size_code(),
2091 NameOfCPURegister(regop));
2092 current += PrintRightOperand(current);
2093 }
else if (opcode == 0xBC) {
2095 get_modrm(*current, &mod, ®op, &rm);
2096 AppendToBuffer(
"tzcnt%c %s,", operand_size_code(),
2097 NameOfCPURegister(regop));
2098 current += PrintRightOperand(current);
2099 }
else if (opcode == 0xBD) {
2101 get_modrm(*current, &mod, ®op, &rm);
2102 AppendToBuffer(
"lzcnt%c %s,", operand_size_code(),
2103 NameOfCPURegister(regop));
2104 current += PrintRightOperand(current);
2105 }
else if (opcode == 0xC2) {
2108 get_modrm(*current, &mod, ®op, &rm);
2109 const char*
const pseudo_op[] = {
"cmpeqss",
"cmpltss",
"cmpless",
2110 "cmpunordss",
"cmpneqss",
"cmpnltss",
2111 "cmpnless",
"cmpordss"};
2112 AppendToBuffer(
"%s %s,%s", pseudo_op[current[1]],
2113 NameOfXMMRegister(regop), NameOfXMMRegister(rm));
2116 UnimplementedInstruction();
2118 }
else if (opcode == 0x10 || opcode == 0x11) {
2122 get_modrm(*current, &mod, ®op, &rm);
2123 AppendToBuffer(
"movups ");
2124 if (opcode == 0x11) {
2125 current += PrintRightXMMOperand(current);
2126 AppendToBuffer(
",%s", NameOfXMMRegister(regop));
2128 AppendToBuffer(
"%s,", NameOfXMMRegister(regop));
2129 current += PrintRightXMMOperand(current);
2131 }
else if (opcode == 0x1F) {
2134 get_modrm(*current, &mod, ®op, &rm);
2141 }
else if (mod == 2) {
2144 AppendToBuffer(
"nop");
2146 }
else if (opcode == 0x28) {
2149 get_modrm(*current, &mod, ®op, &rm);
2150 AppendToBuffer(
"movaps %s,", NameOfXMMRegister(regop));
2151 current += PrintRightXMMOperand(current);
2153 }
else if (opcode == 0x29) {
2156 get_modrm(*current, &mod, ®op, &rm);
2157 AppendToBuffer(
"movaps ");
2158 current += PrintRightXMMOperand(current);
2159 AppendToBuffer(
",%s", NameOfXMMRegister(regop));
2161 }
else if (opcode == 0x2E) {
2163 get_modrm(*current, &mod, ®op, &rm);
2164 AppendToBuffer(
"ucomiss %s,", NameOfXMMRegister(regop));
2165 current += PrintRightXMMOperand(current);
2166 }
else if (opcode == 0xA2) {
2168 AppendToBuffer(
"%s", mnemonic);
2169 }
else if ((opcode & 0xF0) == 0x40) {
2171 int condition = opcode & 0x0F;
2172 const InstructionDesc& idesc = cmov_instructions[condition];
2173 byte_size_operand_ = idesc.byte_size_operation;
2174 current += PrintOperands(idesc.mnem, idesc.op_order_, current);
2176 }
else if (opcode >= 0x51 && opcode <= 0x5F) {
2177 const char*
const pseudo_op[] = {
2178 "sqrtps",
"rsqrtps",
"rcpps",
"andps",
"andnps",
2179 "orps",
"xorps",
"addps",
"mulps",
"cvtps2pd",
2180 "cvtdq2ps",
"subps",
"minps",
"divps",
"maxps",
2183 get_modrm(*current, &mod, ®op, &rm);
2184 AppendToBuffer(
"%s %s,", pseudo_op[opcode - 0x51],
2185 NameOfXMMRegister(regop));
2186 current += PrintRightXMMOperand(current);
2188 }
else if (opcode == 0xC2) {
2191 get_modrm(*current, &mod, ®op, &rm);
2192 const char*
const pseudo_op[] = {
"eq",
"lt",
"le",
"unord",
2193 "neq",
"nlt",
"nle",
"ord"};
2194 AppendToBuffer(
"cmpps %s, ", NameOfXMMRegister(regop));
2195 current += PrintRightXMMOperand(current);
2196 AppendToBuffer(
", %s", pseudo_op[*current]);
2198 }
else if (opcode == 0xC6) {
2201 get_modrm(*current, &mod, ®op, &rm);
2202 AppendToBuffer(
"shufps %s, ", NameOfXMMRegister(regop));
2203 current += PrintRightXMMOperand(current);
2204 AppendToBuffer(
", %d", (*current) & 3);
2206 }
else if (opcode >= 0xC8 && opcode <= 0xCF) {
2208 int reg = (opcode - 0xC8) | (rex_r() ? 8 : 0);
2209 AppendToBuffer(
"bswap%c %s", operand_size_code(), NameOfCPURegister(reg));
2210 }
else if (opcode == 0x50) {
2213 get_modrm(*current, &mod, ®op, &rm);
2214 AppendToBuffer(
"movmskps %s,", NameOfCPURegister(regop));
2215 current += PrintRightXMMOperand(current);
2216 }
else if (opcode == 0x70) {
2218 get_modrm(*current, &mod, ®op, &rm);
2219 AppendToBuffer(
"pshufw %s, ", NameOfXMMRegister(regop));
2220 current += PrintRightXMMOperand(current);
2221 AppendToBuffer(
", %d", (*current) & 3);
2223 }
else if ((opcode & 0xF0) == 0x80) {
2225 current = data + JumpConditional(data);
2227 }
else if (opcode == 0xBE || opcode == 0xBF || opcode == 0xB6 ||
2228 opcode == 0xB7 || opcode == 0xAF) {
2230 current += PrintOperands(mnemonic, REG_OPER_OP_ORDER, current);
2231 }
else if ((opcode & 0xF0) == 0x90) {
2233 current = data + SetCC(data);
2234 }
else if (opcode == 0xA3 || opcode == 0xA5 || opcode == 0xAB ||
2238 AppendToBuffer(
"%s ", mnemonic);
2240 get_modrm(*current, &mod, ®op, &rm);
2241 current += PrintRightOperand(current);
2242 if (opcode == 0xAB) {
2243 AppendToBuffer(
",%s", NameOfCPURegister(regop));
2245 AppendToBuffer(
",%s,cl", NameOfCPURegister(regop));
2247 }
else if (opcode == 0xBA) {
2250 get_modrm(*current, &mod, ®op, &rm);
2251 mnemonic = regop == 5 ?
"bts" : regop == 6 ?
"btr" :
"?";
2252 AppendToBuffer(
"%s ", mnemonic);
2253 current += PrintRightOperand(current);
2254 AppendToBuffer(
",%d", *current++);
2255 }
else if (opcode == 0xB8 || opcode == 0xBC || opcode == 0xBD) {
2257 AppendToBuffer(
"%s%c ", mnemonic, operand_size_code());
2259 get_modrm(*current, &mod, ®op, &rm);
2260 AppendToBuffer(
"%s,", NameOfCPURegister(regop));
2261 current += PrintRightOperand(current);
2262 }
else if (opcode == 0x0B) {
2263 AppendToBuffer(
"ud2");
2264 }
else if (opcode == 0xB0 || opcode == 0xB1) {
2266 if (opcode == 0xB0) {
2267 byte_size_operand_ =
true;
2269 current += PrintOperands(mnemonic, OPER_REG_OP_ORDER, current);
2270 }
else if (opcode == 0xAE && (*(data + 2) & 0xF8) == 0xE8) {
2271 AppendToBuffer(
"lfence");
2274 UnimplementedInstruction();
2276 return static_cast<int>(current - data);
2282 const char* DisassemblerX64::TwoByteMnemonic(byte opcode) {
2283 if (opcode >= 0xC8 && opcode <= 0xCF)
return "bswap";
2288 return (group_1_prefix_ == 0xF2) ?
"cvtsi2sd" :
"cvtsi2ss";
2290 return (group_1_prefix_ == 0xF2) ?
"sqrtsd" :
"sqrtss";
2292 return (group_1_prefix_ == 0xF2) ?
"addsd" :
"addss";
2294 return (group_1_prefix_ == 0xF2) ?
"mulsd" :
"mulss";
2296 return (group_1_prefix_ == 0xF2) ?
"cvtsd2ss" :
"cvtss2sd";
2298 return (group_1_prefix_ == 0xF2) ?
"minsd" :
"minss";
2300 return (group_1_prefix_ == 0xF2) ?
"subsd" :
"subss";
2302 return (group_1_prefix_ == 0xF2) ?
"divsd" :
"divss";
2304 return (group_1_prefix_ == 0xF2) ?
"maxsd" :
"maxss";
2341 tmp_buffer_pos_ = 0;
2343 bool processed =
true;
2350 if (current == OPERAND_SIZE_OVERRIDE_PREFIX) {
2351 operand_size_ = current;
2352 }
else if ((current & 0xF0) == 0x40) {
2354 if (rex_w()) AppendToBuffer(
"REX.W ");
2355 }
else if ((current & 0xFE) == 0xF2) {
2356 group_1_prefix_ = current;
2357 }
else if (current == LOCK_PREFIX) {
2358 AppendToBuffer(
"lock ");
2359 }
else if (current == VEX3_PREFIX) {
2360 vex_byte0_ = current;
2361 vex_byte1_ = *(data + 1);
2362 vex_byte2_ = *(data + 2);
2363 setRex(0x40 | (~(vex_byte1_ >> 5) & 7) | ((vex_byte2_ >> 4) & 8));
2366 }
else if (current == VEX2_PREFIX) {
2367 vex_byte0_ = current;
2368 vex_byte1_ = *(data + 1);
2369 setRex(0x40 | (~(vex_byte1_ >> 5) & 4));
2379 if (vex_byte0_ != 0) {
2381 data += AVXInstruction(data);
2383 const InstructionDesc& idesc = instruction_table_->Get(current);
2384 byte_size_operand_ = idesc.byte_size_operation;
2385 switch (idesc.type) {
2386 case ZERO_OPERANDS_INSTR:
2387 if (current >= 0xA4 && current <= 0xA7) {
2389 if (group_1_prefix_ == REP_PREFIX) {
2391 AppendToBuffer(
"rep ");
2393 if (rex_w()) AppendToBuffer(
"REX.W ");
2394 AppendToBuffer(
"%s%c", idesc.mnem, operand_size_code());
2396 AppendToBuffer(
"%s%c", idesc.mnem, operand_size_code());
2401 case TWO_OPERANDS_INSTR:
2403 data += PrintOperands(idesc.mnem, idesc.op_order_, data);
2406 case JUMP_CONDITIONAL_SHORT_INSTR:
2407 data += JumpConditionalShort(data);
2410 case REGISTER_INSTR:
2411 AppendToBuffer(
"%s%c %s", idesc.mnem, operand_size_code(),
2412 NameOfCPURegister(base_reg(current & 0x07)));
2416 AppendToBuffer(
"%s %s", idesc.mnem,
2417 NameOfCPURegister(base_reg(current & 0x07)));
2420 case MOVE_REG_INSTR: {
2421 byte* addr =
nullptr;
2422 switch (operand_size()) {
2423 case OPERAND_WORD_SIZE:
2425 reinterpret_cast<byte*
>(*
reinterpret_cast<int16_t*
>(data + 1));
2428 case OPERAND_DOUBLEWORD_SIZE:
2430 reinterpret_cast<byte*
>(*
reinterpret_cast<uint32_t*
>(data + 1));
2433 case OPERAND_QUADWORD_SIZE:
2435 reinterpret_cast<byte*
>(*
reinterpret_cast<int64_t*
>(data + 1));
2441 AppendToBuffer(
"mov%c %s,%s", operand_size_code(),
2442 NameOfCPURegister(base_reg(current & 0x07)),
2443 NameOfAddress(addr));
2447 case CALL_JUMP_INSTR: {
2448 byte* addr = data + *
reinterpret_cast<int32_t*
>(data + 1) + 5;
2449 AppendToBuffer(
"%s %s", idesc.mnem, NameOfAddress(addr));
2454 case SHORT_IMMEDIATE_INSTR: {
2456 if (operand_size() == OPERAND_WORD_SIZE) {
2457 imm = *
reinterpret_cast<int16_t*
>(data + 1);
2460 imm = *
reinterpret_cast<int32_t*
>(data + 1);
2463 AppendToBuffer(
"%s rax,0x%x", idesc.mnem, imm);
2481 AppendToBuffer(
"ret 0x%x", *reinterpret_cast<uint16_t*>(data + 1));
2488 count += PrintOperands(
"imul", REG_OPER_OP_ORDER, data + count);
2489 AppendToBuffer(
",0x");
2490 if (*data == 0x69) {
2491 count += PrintImmediate(data + count, operand_size());
2493 count += PrintImmediate(data + count, OPERAND_BYTE_SIZE);
2501 data += PrintImmediateOp(data);
2505 data += TwoByteOpcodeInstruction(data);
2511 get_modrm(*data, &mod, ®op, &rm);
2513 AppendToBuffer(
"pop ");
2514 data += PrintRightOperand(data);
2522 get_modrm(*data, &mod, ®op, &rm);
2523 const char* mnem =
nullptr;
2544 AppendToBuffer(
"%s%c ", mnem, operand_size_code());
2546 AppendToBuffer(
"%s ", mnem);
2548 data += PrintRightOperand(data);
2555 bool is_byte = *data == 0xC6;
2558 AppendToBuffer(
"movb ");
2559 data += PrintRightByteOperand(data);
2560 int32_t imm = *data;
2561 AppendToBuffer(
",0x%x", imm);
2564 AppendToBuffer(
"mov%c ", operand_size_code());
2565 data += PrintRightOperand(data);
2566 if (operand_size() == OPERAND_WORD_SIZE) {
2567 int16_t imm = *
reinterpret_cast<int16_t*
>(data);
2568 AppendToBuffer(
",0x%x", imm);
2571 int32_t imm = *
reinterpret_cast<int32_t*
>(data);
2572 AppendToBuffer(
",0x%x", imm);
2581 AppendToBuffer(
"cmpb ");
2582 data += PrintRightByteOperand(data);
2583 int32_t imm = *data;
2584 AppendToBuffer(
",0x%x", imm);
2592 bool is_byte = *data == 0x88;
2595 get_modrm(*data, &mod, ®op, &rm);
2597 AppendToBuffer(
"movb ");
2598 data += PrintRightByteOperand(data);
2599 AppendToBuffer(
",%s", NameOfByteCPURegister(regop));
2601 AppendToBuffer(
"mov%c ", operand_size_code());
2602 data += PrintRightOperand(data);
2603 AppendToBuffer(
",%s", NameOfCPURegister(regop));
2616 int reg = (*data & 0x7) | (rex_b() ? 8 : 0);
2617 if (group_1_prefix_ == 0xF3 && *data == 0x90) {
2618 AppendToBuffer(
"pause");
2619 }
else if (reg == 0) {
2620 AppendToBuffer(
"nop");
2622 AppendToBuffer(
"xchg%c rax,%s",
2623 operand_size_code(),
2624 NameOfCPURegister(reg));
2646 byte opcode = *data;
2648 bool is_32bit = (opcode >= 0xB8);
2649 int reg = (opcode & 0x7) | (rex_b() ? 8 : 0);
2651 AppendToBuffer(
"mov%c %s,",
2652 operand_size_code(),
2653 NameOfCPURegister(reg));
2654 data += PrintImmediate(data, OPERAND_DOUBLEWORD_SIZE);
2656 AppendToBuffer(
"movb %s,",
2657 NameOfByteCPURegister(reg));
2658 data += PrintImmediate(data, OPERAND_BYTE_SIZE);
2665 get_modrm(*data, &mod, ®op, &rm);
2667 AppendToBuffer(
"decb ");
2668 data += PrintRightByteOperand(data);
2670 UnimplementedInstruction();
2675 AppendToBuffer(
"push 0x%x", *reinterpret_cast<int32_t*>(data + 1));
2680 AppendToBuffer(
"push 0x%x", *reinterpret_cast<int8_t*>(data + 1));
2686 switch (operand_size()) {
2687 case OPERAND_DOUBLEWORD_SIZE: {
2688 const char* memory_location = NameOfAddress(
2689 reinterpret_cast<byte*>(
2690 *reinterpret_cast<int32_t*>(data + 1)));
2691 if (*data == 0xA1) {
2692 AppendToBuffer(
"movzxlq rax,(%s)", memory_location);
2694 AppendToBuffer(
"movzxlq (%s),rax", memory_location);
2699 case OPERAND_QUADWORD_SIZE: {
2701 const char* memory_location = NameOfAddress(
2702 *reinterpret_cast<byte**>(data + 1));
2703 if (*data == 0xA1) {
2704 AppendToBuffer(
"movq rax,(%s)", memory_location);
2706 AppendToBuffer(
"movq (%s),rax", memory_location);
2712 UnimplementedInstruction();
2718 AppendToBuffer(
"test al,0x%x", *reinterpret_cast<uint8_t*>(data + 1));
2724 switch (operand_size()) {
2725 case OPERAND_WORD_SIZE:
2726 value = *
reinterpret_cast<uint16_t*
>(data + 1);
2729 case OPERAND_DOUBLEWORD_SIZE:
2730 value = *
reinterpret_cast<uint32_t*
>(data + 1);
2733 case OPERAND_QUADWORD_SIZE:
2734 value = *
reinterpret_cast<int32_t*
>(data + 1);
2740 AppendToBuffer(
"test%c rax,0x%" PRIx64, operand_size_code(), value);
2746 data += ShiftInstruction(data);
2751 byte_size_operand_ =
true;
2752 data += ShiftInstruction(data);
2762 data += FPUInstruction(data);
2766 data += JumpShort(data);
2770 byte_size_operand_ =
true;
2773 data += F6F7Instruction(data);
2777 AppendToBuffer(
"cmp al,0x%x", *reinterpret_cast<int8_t*>(data + 1));
2782 UnimplementedInstruction();
2787 if (tmp_buffer_pos_ <
sizeof tmp_buffer_) {
2788 tmp_buffer_[tmp_buffer_pos_] =
'\0';
2791 int instr_len =
static_cast<int>(data - instr);
2792 DCHECK_GT(instr_len, 0);
2796 for (byte* bp = instr; bp < data; bp++) {
2797 outp += v8::internal::SNPrintF(out_buffer + outp,
"%02x", *bp);
2799 for (
int i = 6 - instr_len;
i >= 0;
i--) {
2800 outp += v8::internal::SNPrintF(out_buffer + outp,
" ");
2803 outp += v8::internal::SNPrintF(out_buffer + outp,
" %s",
2804 tmp_buffer_.start());
2812 static const char*
const cpu_regs[16] = {
2813 "rax",
"rcx",
"rdx",
"rbx",
"rsp",
"rbp",
"rsi",
"rdi",
2814 "r8",
"r9",
"r10",
"r11",
"r12",
"r13",
"r14",
"r15" 2818 static const char*
const byte_cpu_regs[16] = {
2819 "al",
"cl",
"dl",
"bl",
"spl",
"bpl",
"sil",
"dil",
2820 "r8l",
"r9l",
"r10l",
"r11l",
"r12l",
"r13l",
"r14l",
"r15l" 2824 static const char*
const xmm_regs[16] = {
2825 "xmm0",
"xmm1",
"xmm2",
"xmm3",
"xmm4",
"xmm5",
"xmm6",
"xmm7",
2826 "xmm8",
"xmm9",
"xmm10",
"xmm11",
"xmm12",
"xmm13",
"xmm14",
"xmm15" 2830 const char* NameConverter::NameOfAddress(byte* addr)
const {
2831 v8::internal::SNPrintF(tmp_buffer_,
"%p", static_cast<void*>(addr));
2832 return tmp_buffer_.start();
2836 const char* NameConverter::NameOfConstant(byte* addr)
const {
2837 return NameOfAddress(addr);
2841 const char* NameConverter::NameOfCPURegister(
int reg)
const {
2842 if (0 <= reg && reg < 16)
2843 return cpu_regs[reg];
2848 const char* NameConverter::NameOfByteCPURegister(
int reg)
const {
2849 if (0 <= reg && reg < 16)
2850 return byte_cpu_regs[reg];
2855 const char* NameConverter::NameOfXMMRegister(
int reg)
const {
2856 if (0 <= reg && reg < 16)
2857 return xmm_regs[reg];
2862 const char* NameConverter::NameInCode(byte* addr)
const {
2871 byte* instruction) {
2872 DisassemblerX64 d(converter_, unimplemented_opcode_action());
2873 return d.InstructionDecode(buffer, instruction);
2877 int Disassembler::ConstantPoolSizeAt(byte* instruction) {
2881 void Disassembler::Disassemble(FILE* f, byte* begin, byte* end,
2882 UnimplementedOpcodeAction unimplemented_action) {
2883 NameConverter converter;
2884 Disassembler d(converter, unimplemented_action);
2885 for (byte* pc = begin; pc < end;) {
2889 pc += d.InstructionDecode(buffer, pc);
2890 fprintf(f,
"%p", static_cast<void*>(prev_pc));
2893 for (byte* bp = prev_pc; bp < pc; bp++) {
2894 fprintf(f,
"%02x", *bp);
2896 for (
int i = 6 - static_cast<int>(pc - prev_pc);
i >= 0;
i--) {
2899 fprintf(f,
" %s\n", buffer.start());
2905 #endif // V8_TARGET_ARCH_X64