27 REG_OPER_OP_ORDER = 1,
28 OPER_REG_OP_ORDER = 2,
30 BYTE_SIZE_OPERAND_FLAG = 4,
31 BYTE_REG_OPER_OP_ORDER = REG_OPER_OP_ORDER | BYTE_SIZE_OPERAND_FLAG,
32 BYTE_OPER_REG_OP_ORDER = OPER_REG_OP_ORDER | BYTE_SIZE_OPERAND_FLAG,
36 XMMREG_XMMOPER_OP_ORDER,
37 XMMOPER_XMMREG_OP_ORDER,
49static const ByteMnemonic two_operands_instr[] = {
50 {0x00, BYTE_OPER_REG_OP_ORDER,
"add"},
51 {0x01, OPER_REG_OP_ORDER,
"add"},
52 {0x02, BYTE_REG_OPER_OP_ORDER,
"add"},
53 {0x03, REG_OPER_OP_ORDER,
"add"},
54 {0x08, BYTE_OPER_REG_OP_ORDER,
"or"},
55 {0x09, OPER_REG_OP_ORDER,
"or"},
56 {0x0A, BYTE_REG_OPER_OP_ORDER,
"or"},
57 {0x0B, REG_OPER_OP_ORDER,
"or"},
58 {0x10, BYTE_OPER_REG_OP_ORDER,
"adc"},
59 {0x11, OPER_REG_OP_ORDER,
"adc"},
60 {0x12, BYTE_REG_OPER_OP_ORDER,
"adc"},
61 {0x13, REG_OPER_OP_ORDER,
"adc"},
62 {0x18, BYTE_OPER_REG_OP_ORDER,
"sbb"},
63 {0x19, OPER_REG_OP_ORDER,
"sbb"},
64 {0x1A, BYTE_REG_OPER_OP_ORDER,
"sbb"},
65 {0x1B, REG_OPER_OP_ORDER,
"sbb"},
66 {0x20, BYTE_OPER_REG_OP_ORDER,
"and"},
67 {0x21, OPER_REG_OP_ORDER,
"and"},
68 {0x22, BYTE_REG_OPER_OP_ORDER,
"and"},
69 {0x23, REG_OPER_OP_ORDER,
"and"},
70 {0x28, BYTE_OPER_REG_OP_ORDER,
"sub"},
71 {0x29, OPER_REG_OP_ORDER,
"sub"},
72 {0x2A, BYTE_REG_OPER_OP_ORDER,
"sub"},
73 {0x2B, REG_OPER_OP_ORDER,
"sub"},
74 {0x30, BYTE_OPER_REG_OP_ORDER,
"xor"},
75 {0x31, OPER_REG_OP_ORDER,
"xor"},
76 {0x32, BYTE_REG_OPER_OP_ORDER,
"xor"},
77 {0x33, REG_OPER_OP_ORDER,
"xor"},
78 {0x38, BYTE_OPER_REG_OP_ORDER,
"cmp"},
79 {0x39, OPER_REG_OP_ORDER,
"cmp"},
80 {0x3A, BYTE_REG_OPER_OP_ORDER,
"cmp"},
81 {0x3B, REG_OPER_OP_ORDER,
"cmp"},
82 {0x63, REG_OPER_OP_ORDER,
"movsxl"},
83 {0x84, BYTE_REG_OPER_OP_ORDER,
"test"},
84 {0x85, REG_OPER_OP_ORDER,
"test"},
85 {0x86, BYTE_REG_OPER_OP_ORDER,
"xchg"},
86 {0x87, REG_OPER_OP_ORDER,
"xchg"},
87 {0x88, BYTE_OPER_REG_OP_ORDER,
"mov"},
88 {0x89, OPER_REG_OP_ORDER,
"mov"},
89 {0x8A, BYTE_REG_OPER_OP_ORDER,
"mov"},
90 {0x8B, REG_OPER_OP_ORDER,
"mov"},
91 {0x8D, REG_OPER_OP_ORDER,
"lea"},
92 {-1, UNSET_OP_ORDER,
""}};
94static const ByteMnemonic zero_operands_instr[] = {
95 {0xC3, UNSET_OP_ORDER,
"ret"}, {0xC9, UNSET_OP_ORDER,
"leave"},
96 {0xF4, UNSET_OP_ORDER,
"hlt"}, {0xFC, UNSET_OP_ORDER,
"cld"},
97 {0xCC, UNSET_OP_ORDER,
"int3"}, {0x60, UNSET_OP_ORDER,
"pushad"},
98 {0x61, UNSET_OP_ORDER,
"popad"}, {0x9C, UNSET_OP_ORDER,
"pushfd"},
99 {0x9D, UNSET_OP_ORDER,
"popfd"}, {0x9E, UNSET_OP_ORDER,
"sahf"},
100 {0x99, UNSET_OP_ORDER,
"cdq"}, {0x9B, UNSET_OP_ORDER,
"fwait"},
101 {0xAB, UNSET_OP_ORDER,
"stos"}, {0xA4, UNSET_OP_ORDER,
"movs"},
102 {0xA5, UNSET_OP_ORDER,
"movs"}, {0xA6, UNSET_OP_ORDER,
"cmps"},
103 {0xA7, UNSET_OP_ORDER,
"cmps"}, {-1, UNSET_OP_ORDER,
""}};
105static const ByteMnemonic call_jump_instr[] = {{0xE8, UNSET_OP_ORDER,
"call"},
106 {0xE9, UNSET_OP_ORDER,
"jmp"},
107 {-1, UNSET_OP_ORDER,
""}};
109static const ByteMnemonic short_immediate_instr[] = {
110 {0x05, UNSET_OP_ORDER,
"add"}, {0x0D, UNSET_OP_ORDER,
"or"},
111 {0x15, UNSET_OP_ORDER,
"adc"}, {0x1D, UNSET_OP_ORDER,
"sbb"},
112 {0x25, UNSET_OP_ORDER,
"and"}, {0x2D, UNSET_OP_ORDER,
"sub"},
113 {0x35, UNSET_OP_ORDER,
"xor"}, {0x3D, UNSET_OP_ORDER,
"cmp"},
114 {-1, UNSET_OP_ORDER,
""}};
116static const char*
const conditional_code_suffix[] = {
117 "o",
"no",
"c",
"nc",
"z",
"nz",
"na",
"a",
118 "s",
"ns",
"pe",
"po",
"l",
"ge",
"le",
"g"};
120enum InstructionType {
124 JUMP_CONDITIONAL_SHORT_INSTR,
129 SHORT_IMMEDIATE_INSTR
133 ESCAPE_PREFIX = 0x0F,
134 SEGMENT_FS_OVERRIDE_PREFIX = 0x64,
135 OPERAND_SIZE_OVERRIDE_PREFIX = 0x66,
136 ADDRESS_SIZE_OVERRIDE_PREFIX = 0x67,
142 REPEQ_PREFIX = REP_PREFIX
145struct InstructionDesc {
147 InstructionType
type;
149 bool byte_size_operation;
152class InstructionTable {
155 const InstructionDesc&
Get(uint8_t
x)
const {
return instructions_[
x]; }
158 InstructionDesc instructions_[256];
161 void CopyTable(
const ByteMnemonic bm[], InstructionType type);
162 void SetTableRange(InstructionType type, uint8_t
start, uint8_t
end,
163 bool byte_size,
const char* mnem);
164 void AddJumpConditionalShort();
167InstructionTable::InstructionTable() {
172void InstructionTable::Clear() {
173 for (
int i = 0;
i < 256;
i++) {
174 instructions_[
i].mnem =
"(bad)";
175 instructions_[
i].type = NO_INSTR;
176 instructions_[
i].op_order_ = UNSET_OP_ORDER;
177 instructions_[
i].byte_size_operation =
false;
181void InstructionTable::Init() {
182 CopyTable(two_operands_instr, TWO_OPERANDS_INSTR);
183 CopyTable(zero_operands_instr, ZERO_OPERANDS_INSTR);
184 CopyTable(call_jump_instr, CALL_JUMP_INSTR);
185 CopyTable(short_immediate_instr, SHORT_IMMEDIATE_INSTR);
186 AddJumpConditionalShort();
187 SetTableRange(PUSHPOP_INSTR, 0x50, 0x57,
false,
"push");
188 SetTableRange(PUSHPOP_INSTR, 0x58, 0x5F,
false,
"pop");
189 SetTableRange(MOVE_REG_INSTR, 0xB8, 0xBF,
false,
"mov");
192void InstructionTable::CopyTable(
const ByteMnemonic bm[],
193 InstructionType type) {
194 for (
int i = 0; bm[
i].b >= 0;
i++) {
195 InstructionDesc*
id = &instructions_[bm[
i].b];
196 id->mnem = bm[
i].mnem;
199 static_cast<OperandType>(op_order & ~BYTE_SIZE_OPERAND_FLAG);
202 id->byte_size_operation = ((op_order & BYTE_SIZE_OPERAND_FLAG) != 0);
206void InstructionTable::SetTableRange(InstructionType type, uint8_t
start,
207 uint8_t
end,
bool byte_size,
209 for (uint8_t b =
start; b <=
end; b++) {
210 InstructionDesc*
id = &instructions_[b];
214 id->byte_size_operation = byte_size;
218void InstructionTable::AddJumpConditionalShort() {
219 for (uint8_t b = 0x70; b <= 0x7F; b++) {
220 InstructionDesc*
id = &instructions_[b];
223 id->type = JUMP_CONDITIONAL_SHORT_INSTR;
231static const InstructionDesc cmov_instructions[16] = {
232 {
"cmovo", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER,
false},
233 {
"cmovno", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER,
false},
234 {
"cmovc", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER,
false},
235 {
"cmovnc", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER,
false},
236 {
"cmovz", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER,
false},
237 {
"cmovnz", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER,
false},
238 {
"cmovna", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER,
false},
239 {
"cmova", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER,
false},
240 {
"cmovs", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER,
false},
241 {
"cmovns", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER,
false},
242 {
"cmovpe", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER,
false},
243 {
"cmovpo", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER,
false},
244 {
"cmovl", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER,
false},
245 {
"cmovge", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER,
false},
246 {
"cmovle", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER,
false},
247 {
"cmovg", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER,
false}};
249static const char*
const cmp_pseudo_op[16] = {
250 "eq",
"lt",
"le",
"unord",
"neq",
"nlt",
"nle",
"ord",
251 "eq_uq",
"nge",
"ngt",
"false",
"neq_oq",
"ge",
"gt",
"true"};
254int8_t Imm8(
const uint8_t* data) {
255 return *
reinterpret_cast<const int8_t*
>(
data);
257uint8_t Imm8_U(
const uint8_t* data) {
258 return *
reinterpret_cast<const uint8_t*
>(
data);
260int16_t Imm16(
const uint8_t* data) {
264uint16_t Imm16_U(
const uint8_t* data) {
268int32_t Imm32(
const uint8_t* data) {
272uint32_t Imm32_U(
const uint8_t* data) {
276int64_t Imm64(
const uint8_t* data) {
287const char* NameOfYMMRegister(
int reg);
291class DisassemblerX64 {
293 DisassemblerX64(
const NameConverter& converter,
294 Disassembler::UnimplementedOpcodeAction unimplemented_action)
295 : converter_(converter),
297 abort_on_unimplemented_(unimplemented_action ==
298 Disassembler::kAbortOnUnimplementedOpcode),
303 address_size_prefix_(0),
307 byte_size_operand_(false),
308 instruction_table_(GetInstructionTable()) {
309 tmp_buffer_[0] =
'\0';
318 OPERAND_BYTE_SIZE = 0,
319 OPERAND_WORD_SIZE = 1,
320 OPERAND_DOUBLEWORD_SIZE = 2,
321 OPERAND_QUADWORD_SIZE = 3
324 const NameConverter& converter_;
326 unsigned int tmp_buffer_pos_;
327 bool abort_on_unimplemented_;
330 uint8_t operand_size_;
331 uint8_t group_1_prefix_;
332 uint8_t segment_prefix_;
333 uint8_t address_size_prefix_;
338 bool byte_size_operand_;
339 const InstructionTable*
const instruction_table_;
341 void setRex(uint8_t rex) {
346 bool rex() {
return rex_ != 0; }
348 bool rex_b() {
return (rex_ & 0x01) != 0; }
351 int base_reg(
int low_bits) {
return low_bits | ((rex_ & 0x01) << 3); }
353 bool rex_x() {
return (rex_ & 0x02) != 0; }
355 bool rex_r() {
return (rex_ & 0x04) != 0; }
357 bool rex_w() {
return (rex_ & 0x08) != 0; }
360 DCHECK(vex_byte0_ == VEX3_PREFIX || vex_byte0_ == VEX2_PREFIX);
361 return vex_byte0_ == VEX3_PREFIX ? (vex_byte2_ & 0x80) != 0 : false;
365 DCHECK(vex_byte0_ == VEX3_PREFIX || vex_byte0_ == VEX2_PREFIX);
366 uint8_t checked = vex_byte0_ == VEX3_PREFIX ? vex_byte2_ : vex_byte1_;
367 return (checked & 4) == 0;
370 bool vex_256()
const {
371 DCHECK(vex_byte0_ == VEX3_PREFIX || vex_byte0_ == VEX2_PREFIX);
372 uint8_t checked = vex_byte0_ == VEX3_PREFIX ? vex_byte2_ : vex_byte1_;
373 return (checked & 4) != 0;
377 DCHECK(vex_byte0_ == VEX3_PREFIX || vex_byte0_ == VEX2_PREFIX);
378 uint8_t checked = vex_byte0_ == VEX3_PREFIX ? vex_byte2_ : vex_byte1_;
379 return (checked & 3) == 0;
383 DCHECK(vex_byte0_ == VEX3_PREFIX || vex_byte0_ == VEX2_PREFIX);
384 uint8_t checked = vex_byte0_ == VEX3_PREFIX ? vex_byte2_ : vex_byte1_;
385 return (checked & 3) == 1;
389 DCHECK(vex_byte0_ == VEX3_PREFIX || vex_byte0_ == VEX2_PREFIX);
390 uint8_t checked = vex_byte0_ == VEX3_PREFIX ? vex_byte2_ : vex_byte1_;
391 return (checked & 3) == 2;
395 DCHECK(vex_byte0_ == VEX3_PREFIX || vex_byte0_ == VEX2_PREFIX);
396 uint8_t checked = vex_byte0_ == VEX3_PREFIX ? vex_byte2_ : vex_byte1_;
397 return (checked & 3) == 3;
401 if (vex_byte0_ == VEX2_PREFIX)
return true;
402 return (vex_byte1_ & 3) == 1;
406 if (vex_byte0_ == VEX2_PREFIX)
return false;
407 return (vex_byte1_ & 3) == 2;
411 if (vex_byte0_ == VEX2_PREFIX)
return false;
412 return (vex_byte1_ & 3) == 3;
416 DCHECK(vex_byte0_ == VEX3_PREFIX || vex_byte0_ == VEX2_PREFIX);
417 uint8_t checked = vex_byte0_ == VEX3_PREFIX ? vex_byte2_ : vex_byte1_;
418 return ~(checked >> 3) & 0xF;
422 if (byte_size_operand_)
return OPERAND_BYTE_SIZE;
423 if (rex_w())
return OPERAND_QUADWORD_SIZE;
424 if (operand_size_ != 0)
return OPERAND_WORD_SIZE;
425 return OPERAND_DOUBLEWORD_SIZE;
428 char operand_size_code() {
return "bwlq"[operand_size()]; }
430 char float_size_code() {
return "sd"[rex_w()]; }
432 const char* NameOfCPURegister(
int reg)
const {
433 return converter_.NameOfCPURegister(
reg);
436 const char* NameOfByteCPURegister(
int reg)
const {
437 return converter_.NameOfByteCPURegister(
reg);
440 const char* NameOfXMMRegister(
int reg)
const {
441 return converter_.NameOfXMMRegister(
reg);
444 const char* NameOfAVXRegister(
int reg)
const {
446 return NameOfYMMRegister(
reg);
448 return converter_.NameOfXMMRegister(
reg);
452 const char* NameOfAddress(uint8_t* addr)
const {
453 return converter_.NameOfAddress(addr);
457 void get_modrm(uint8_t data,
int* mod,
int* regop,
int* rm) {
458 *mod = (data >> 6) & 3;
459 *regop = ((data & 0x38) >> 3) | (rex_r() ? 8 : 0);
460 *rm = (data & 7) | (rex_b() ? 8 : 0);
463 void get_sib(uint8_t data,
int*
scale,
int* index,
int*
base) {
464 *
scale = (data >> 6) & 3;
465 *index = ((data >> 3) & 7) | (rex_x() ? 8 : 0);
466 *
base = (data & 7) | (rex_b() ? 8 : 0);
469 using RegisterNameMapping =
const char* (DisassemblerX64::*)(
int reg)
const;
471 void TryAppendRootRelativeName(
int offset);
472 int PrintRightOperandHelper(uint8_t* modrmp, RegisterNameMapping);
473 int PrintRightOperand(uint8_t* modrmp);
474 int PrintRightByteOperand(uint8_t* modrmp);
475 int PrintRightXMMOperand(uint8_t* modrmp);
476 int PrintRightAVXOperand(uint8_t* modrmp);
477 int PrintOperands(
const char* mnem, OperandType op_order, uint8_t* data);
478 int PrintImmediate(uint8_t* data, OperandSize size);
479 int PrintImmediateOp(uint8_t* data);
480 const char* TwoByteMnemonic(uint8_t opcode);
481 int TwoByteOpcodeInstruction(uint8_t* data);
482 int ThreeByteOpcodeInstruction(uint8_t* data);
483 int F6F7Instruction(uint8_t* data);
484 int ShiftInstruction(uint8_t* data);
485 int JumpShort(uint8_t* data);
486 int JumpConditional(uint8_t* data);
487 int JumpConditionalShort(uint8_t* data);
488 int SetCC(uint8_t* data);
489 int FPUInstruction(uint8_t* data);
490 int MemoryFPUInstruction(
int escape_opcode,
int regop, uint8_t* modrm_start);
491 int RegisterFPUInstruction(
int escape_opcode, uint8_t modrm_byte);
492 int AVXInstruction(uint8_t* data);
493 PRINTF_FORMAT(2, 3) void AppendToBuffer(const
char* format, ...);
495 void UnimplementedInstruction() {
496 if (abort_on_unimplemented_) {
497 FATAL(
"'Unimplemented Instruction'");
499 AppendToBuffer(
"'Unimplemented Instruction'");
504void DisassemblerX64::AppendToBuffer(
const char* format, ...) {
507 va_start(
args, format);
510 tmp_buffer_pos_ +=
result;
513void DisassemblerX64::TryAppendRootRelativeName(
int offset) {
514 const char* maybe_name = converter_.RootRelativeName(
offset);
515 if (maybe_name !=
nullptr) AppendToBuffer(
" (%s)", maybe_name);
518int DisassemblerX64::PrintRightOperandHelper(
519 uint8_t* modrmp, RegisterNameMapping direct_register_name) {
521 get_modrm(*modrmp, &mod, ®op, &rm);
522 RegisterNameMapping register_name =
523 (mod == 3) ? direct_register_name : &DisassemblerX64::NameOfCPURegister;
527 AppendToBuffer(
"[rip+0x%x]", Imm32(modrmp + 1));
529 }
else if ((rm & 7) == 4) {
531 uint8_t sib = *(modrmp + 1);
534 if (index == 4 && (
base & 7) == 4 &&
scale == 0 ) {
537 AppendToBuffer(
"[%s]", NameOfCPURegister(
base));
539 }
else if (
base == 5) {
541 int32_t disp = Imm32(modrmp + 2);
542 AppendToBuffer(
"[%s*%d%s0x%x]", NameOfCPURegister(index), 1 <<
scale,
543 disp < 0 ?
"-" :
"+", disp < 0 ? -disp : disp);
545 }
else if (index != 4 &&
base != 5) {
547 AppendToBuffer(
"[%s+%s*%d]", NameOfCPURegister(
base),
548 NameOfCPURegister(index), 1 <<
scale);
551 UnimplementedInstruction();
555 AppendToBuffer(
"[%s]", NameOfCPURegister(rm));
561 uint8_t sib = *(modrmp + 1);
564 int disp = (mod == 2) ? Imm32(modrmp + 2) : Imm8(modrmp + 2);
565 if (index == 4 && (
base & 7) == 4 &&
scale == 0 ) {
566 AppendToBuffer(
"[%s%s0x%x]", NameOfCPURegister(
base),
567 disp < 0 ?
"-" :
"+", disp < 0 ? -disp : disp);
569 AppendToBuffer(
"[%s+%s*%d%s0x%x]", NameOfCPURegister(
base),
570 NameOfCPURegister(index), 1 <<
scale,
571 disp < 0 ?
"-" :
"+", disp < 0 ? -disp : disp);
573 return mod == 2 ? 6 : 3;
576 int disp = (mod == 2) ? Imm32(modrmp + 1) : Imm8(modrmp + 1);
577 AppendToBuffer(
"[%s%s0x%x]", NameOfCPURegister(rm),
578 disp < 0 ?
"-" :
"+", disp < 0 ? -disp : disp);
581 TryAppendRootRelativeName(disp);
583 return (mod == 2) ? 5 : 2;
586 AppendToBuffer(
"%s", (this->*register_name)(rm));
589 UnimplementedInstruction();
595int DisassemblerX64::PrintImmediate(uint8_t* data, OperandSize size) {
599 case OPERAND_BYTE_SIZE:
603 case OPERAND_WORD_SIZE:
607 case OPERAND_DOUBLEWORD_SIZE:
608 value = Imm32_U(data);
611 case OPERAND_QUADWORD_SIZE:
618 AppendToBuffer(
"%" PRIx64, value);
622int DisassemblerX64::PrintRightOperand(uint8_t* modrmp) {
623 return PrintRightOperandHelper(modrmp, &DisassemblerX64::NameOfCPURegister);
626int DisassemblerX64::PrintRightByteOperand(uint8_t* modrmp) {
627 return PrintRightOperandHelper(modrmp,
628 &DisassemblerX64::NameOfByteCPURegister);
631int DisassemblerX64::PrintRightXMMOperand(uint8_t* modrmp) {
632 return PrintRightOperandHelper(modrmp, &DisassemblerX64::NameOfXMMRegister);
635int DisassemblerX64::PrintRightAVXOperand(uint8_t* modrmp) {
636 return PrintRightOperandHelper(modrmp, &DisassemblerX64::NameOfAVXRegister);
641int DisassemblerX64::PrintOperands(
const char* mnem, OperandType op_order,
643 uint8_t modrm = *
data;
645 get_modrm(modrm, &mod, ®op, &rm);
647 const char* register_name = byte_size_operand_ ? NameOfByteCPURegister(regop)
648 : NameOfCPURegister(regop);
650 case REG_OPER_OP_ORDER: {
651 AppendToBuffer(
"%s%c %s,", mnem, operand_size_code(), register_name);
652 advance = byte_size_operand_ ? PrintRightByteOperand(data)
653 : PrintRightOperand(data);
656 case OPER_REG_OP_ORDER: {
657 AppendToBuffer(
"%s%c ", mnem, operand_size_code());
658 advance = byte_size_operand_ ? PrintRightByteOperand(data)
659 : PrintRightOperand(data);
660 AppendToBuffer(
",%s", register_name);
663 case XMMREG_XMMOPER_OP_ORDER: {
664 AppendToBuffer(
"%s %s,", mnem, NameOfXMMRegister(regop));
665 advance = PrintRightXMMOperand(data);
668 case XMMOPER_XMMREG_OP_ORDER: {
669 AppendToBuffer(
"%s ", mnem);
670 advance = PrintRightXMMOperand(data);
671 AppendToBuffer(
",%s", NameOfXMMRegister(regop));
674 case OPER_XMMREG_OP_ORDER: {
675 AppendToBuffer(
"%s ", mnem);
676 advance = PrintRightOperand(data);
677 AppendToBuffer(
",%s", NameOfXMMRegister(regop));
680 case XMMREG_OPER_OP_ORDER: {
681 AppendToBuffer(
"%s %s,", mnem, NameOfXMMRegister(regop));
682 advance = PrintRightOperand(data);
693int DisassemblerX64::PrintImmediateOp(uint8_t* data) {
694 DCHECK(*data == 0x80 || *data == 0x81 || *data == 0x83);
695 bool byte_size_immediate = *data != 0x81;
696 uint8_t modrm = *(data + 1);
698 get_modrm(modrm, &mod, ®op, &rm);
699 const char* mnem =
"Imm???";
726 UnimplementedInstruction();
728 AppendToBuffer(
"%s%c ", mnem, operand_size_code());
729 int count = byte_size_operand_ ? PrintRightByteOperand(data + 1)
730 : PrintRightOperand(data + 1);
731 AppendToBuffer(
",0x");
733 byte_size_immediate ? OPERAND_BYTE_SIZE : operand_size();
734 count += PrintImmediate(data + 1 + count, immediate_size);
739int DisassemblerX64::F6F7Instruction(uint8_t* data) {
740 DCHECK(*data == 0xF7 || *data == 0xF6);
741 uint8_t modrm = *(data + 1);
743 get_modrm(modrm, &mod, ®op, &rm);
745 const char* mnem =
nullptr;
766 UnimplementedInstruction();
769 AppendToBuffer(
"%s%c %s", mnem, operand_size_code(),
770 NameOfCPURegister(rm));
772 }
else if (mod == 1 ||
774 AppendToBuffer(
"%s%c ", mnem, operand_size_code());
775 int count = PrintRightOperand(data + 1);
778 UnimplementedInstruction();
781 }
else if (regop == 0) {
782 AppendToBuffer(
"test%c ", operand_size_code());
783 int count = PrintRightOperand(data + 1);
784 AppendToBuffer(
",0x");
785 count += PrintImmediate(data + 1 + count, operand_size());
788 UnimplementedInstruction();
793int DisassemblerX64::ShiftInstruction(uint8_t* data) {
794 uint8_t op = *data & (~1);
796 if (op != 0xD0 && op != 0xD2 && op != 0xC0) {
797 UnimplementedInstruction();
802 uint8_t modrm = *(data +
count);
804 get_modrm(modrm, &mod, ®op, &rm);
806 const char* mnem =
nullptr;
830 UnimplementedInstruction();
834 AppendToBuffer(
"%s%c ", mnem, operand_size_code());
836 count += PrintRightOperand(data + count);
838 AppendToBuffer(
", cl");
845 imm8 = *(data +
count);
848 AppendToBuffer(
", %d", imm8);
854int DisassemblerX64::JumpShort(uint8_t* data) {
856 uint8_t b = *(data + 1);
857 uint8_t* dest = data +
static_cast<int8_t
>(b) + 2;
858 AppendToBuffer(
"jmp %s", NameOfAddress(dest));
863int DisassemblerX64::JumpConditional(uint8_t* data) {
865 uint8_t cond = *(data + 1) & 0x0F;
866 uint8_t* dest = data + Imm32(data + 2) + 6;
867 const char* mnem = conditional_code_suffix[cond];
868 AppendToBuffer(
"j%s %s", mnem, NameOfAddress(dest));
873int DisassemblerX64::JumpConditionalShort(uint8_t* data) {
874 uint8_t cond = *data & 0x0F;
875 uint8_t b = *(data + 1);
876 uint8_t* dest = data +
static_cast<int8_t
>(b) + 2;
877 const char* mnem = conditional_code_suffix[cond];
878 AppendToBuffer(
"j%s %s", mnem, NameOfAddress(dest));
883int DisassemblerX64::SetCC(uint8_t* data) {
885 uint8_t cond = *(data + 1) & 0x0F;
886 const char* mnem = conditional_code_suffix[cond];
887 AppendToBuffer(
"set%s%c ", mnem, operand_size_code());
888 PrintRightByteOperand(data + 2);
892const char* sf_str[4] = {
"",
"rl",
"ra",
"ll"};
894int DisassemblerX64::AVXInstruction(uint8_t* data) {
895 uint8_t opcode = *
data;
896 uint8_t* current = data + 1;
897 if (vex_66() && vex_0f38()) {
898 int mod, regop, rm, vvvv = vex_vreg();
899 get_modrm(*current, &mod, ®op, &rm);
902 AppendToBuffer(
"vcvtph2ps %s,", NameOfAVXRegister(regop));
903 current += PrintRightXMMOperand(current);
906 AppendToBuffer(
"vbroadcastss %s,", NameOfAVXRegister(regop));
907 current += PrintRightXMMOperand(current);
910 AppendToBuffer(
"vbroadcastsd %s,", NameOfAVXRegister(regop));
911 current += PrintRightXMMOperand(current);
914 AppendToBuffer(
"shlx%c %s,", operand_size_code(),
915 NameOfCPURegister(regop));
916 current += PrintRightOperand(current);
917 AppendToBuffer(
",%s", NameOfCPURegister(vvvv));
920 AppendToBuffer(
"vpdpbusd %s,%s,", NameOfAVXRegister(regop),
921 NameOfAVXRegister(vvvv));
922 current += PrintRightAVXOperand(current);
924#define DECLARE_SSE_AVX_DIS_CASE(instruction, notUsed1, notUsed2, notUsed3, \
927 AppendToBuffer("v" #instruction " %s,%s,", NameOfAVXRegister(regop), \
928 NameOfAVXRegister(vvvv)); \
929 current += PrintRightAVXOperand(current); \
936#undef DECLARE_SSE_AVX_DIS_CASE
938#define DECLARE_SSE_UNOP_AVX_DIS_CASE(instruction, notUsed1, notUsed2, \
941 AppendToBuffer("v" #instruction " %s,", NameOfAVXRegister(regop)); \
942 current += PrintRightAVXOperand(current); \
947#undef DECLARE_SSE_UNOP_AVX_DIS_CASE
949#define DISASSEMBLE_AVX2_BROADCAST(instruction, _1, _2, _3, code) \
951 AppendToBuffer("" #instruction " %s,", NameOfAVXRegister(regop)); \
952 current += PrintRightXMMOperand(current); \
955#undef DISASSEMBLE_AVX2_BROADCAST
958#define DECLARE_FMA_DISASM(instruction, _1, _2, _3, _4, code) \
960 AppendToBuffer(#instruction " %s,%s,", NameOfAVXRegister(regop), \
961 NameOfAVXRegister(vvvv)); \
962 current += PrintRightAVXOperand(current); \
972 UnimplementedInstruction();
980 UnimplementedInstruction();
984#undef DECLARE_FMA_DISASM
987 }
else if (vex_66() && vex_0f3a()) {
988 int mod, regop, rm, vvvv = vex_vreg();
989 get_modrm(*current, &mod, ®op, &rm);
992 AppendToBuffer(
"vpermq %s,", NameOfAVXRegister(regop));
993 current += PrintRightAVXOperand(current);
994 AppendToBuffer(
",0x%x", *current++);
997 AppendToBuffer(
"vperm2f128 %s,%s,", NameOfAVXRegister(regop),
998 NameOfAVXRegister(vvvv));
999 current += PrintRightAVXOperand(current);
1000 AppendToBuffer(
",0x%x", *current++);
1003 AppendToBuffer(
"vroundps %s,", NameOfAVXRegister(regop));
1004 current += PrintRightAVXOperand(current);
1005 AppendToBuffer(
",0x%x", *current++);
1008 AppendToBuffer(
"vroundpd %s,", NameOfAVXRegister(regop));
1009 current += PrintRightAVXOperand(current);
1010 AppendToBuffer(
",0x%x", *current++);
1013 AppendToBuffer(
"vroundss %s,%s,", NameOfAVXRegister(regop),
1014 NameOfAVXRegister(vvvv));
1015 current += PrintRightAVXOperand(current);
1016 AppendToBuffer(
",0x%x", *current++);
1019 AppendToBuffer(
"vroundsd %s,%s,", NameOfAVXRegister(regop),
1020 NameOfAVXRegister(vvvv));
1021 current += PrintRightAVXOperand(current);
1022 AppendToBuffer(
",0x%x", *current++);
1025 AppendToBuffer(
"vpblendw %s,%s,", NameOfAVXRegister(regop),
1026 NameOfAVXRegister(vvvv));
1027 current += PrintRightAVXOperand(current);
1028 AppendToBuffer(
",0x%x", *current++);
1031 AppendToBuffer(
"vpalignr %s,%s,", NameOfAVXRegister(regop),
1032 NameOfAVXRegister(vvvv));
1033 current += PrintRightAVXOperand(current);
1034 AppendToBuffer(
",0x%x", *current++);
1037 AppendToBuffer(
"vpextrb ");
1038 current += PrintRightByteOperand(current);
1039 AppendToBuffer(
",%s,0x%x", NameOfAVXRegister(regop), *current++);
1042 AppendToBuffer(
"vpextrw ");
1043 current += PrintRightOperand(current);
1044 AppendToBuffer(
",%s,0x%x", NameOfAVXRegister(regop), *current++);
1047 AppendToBuffer(
"vpextr%c ", rex_w() ?
'q' :
'd');
1048 current += PrintRightOperand(current);
1049 AppendToBuffer(
",%s,0x%x", NameOfAVXRegister(regop), *current++);
1052 AppendToBuffer(
"vextractps ");
1053 current += PrintRightOperand(current);
1054 AppendToBuffer(
",%s,0x%x", NameOfAVXRegister(regop), *current++);
1057 AppendToBuffer(
"vextractf128 ");
1058 current += PrintRightXMMOperand(current);
1059 AppendToBuffer(
",%s,0x%x", NameOfAVXRegister(regop), *current++);
1062 AppendToBuffer(
"vcvtps2ph ");
1063 current += PrintRightXMMOperand(current);
1064 AppendToBuffer(
",%s,0x%x", NameOfAVXRegister(regop), *current++);
1067 AppendToBuffer(
"vpinsrb %s,%s,", NameOfAVXRegister(regop),
1068 NameOfAVXRegister(vvvv));
1069 current += PrintRightByteOperand(current);
1070 AppendToBuffer(
",0x%x", *current++);
1073 AppendToBuffer(
"vinsertps %s,%s,", NameOfAVXRegister(regop),
1074 NameOfAVXRegister(vvvv));
1075 current += PrintRightAVXOperand(current);
1076 AppendToBuffer(
",0x%x", *current++);
1079 AppendToBuffer(
"vpinsr%c %s,%s,", rex_w() ?
'q' :
'd',
1080 NameOfAVXRegister(regop), NameOfAVXRegister(vvvv));
1081 current += PrintRightOperand(current);
1082 AppendToBuffer(
",0x%x", *current++);
1085 AppendToBuffer(
"vinserti128 %s,%s,", NameOfAVXRegister(regop),
1086 NameOfAVXRegister(vvvv));
1087 current += PrintRightXMMOperand(current);
1088 AppendToBuffer(
",0x%x", *current++);
1091 AppendToBuffer(
"vblendvps %s,%s,", NameOfAVXRegister(regop),
1092 NameOfAVXRegister(vvvv));
1093 current += PrintRightAVXOperand(current);
1094 AppendToBuffer(
",%s", NameOfAVXRegister((*current++) >> 4));
1098 AppendToBuffer(
"vblendvpd %s,%s,", NameOfAVXRegister(regop),
1099 NameOfAVXRegister(vvvv));
1100 current += PrintRightAVXOperand(current);
1101 AppendToBuffer(
",%s", NameOfAVXRegister((*current++) >> 4));
1105 AppendToBuffer(
"vpblendvb %s,%s,", NameOfAVXRegister(regop),
1106 NameOfAVXRegister(vvvv));
1107 current += PrintRightAVXOperand(current);
1108 AppendToBuffer(
",%s", NameOfAVXRegister((*current++) >> 4));
1112 UnimplementedInstruction();
1114 }
else if (vex_f3() && vex_0f()) {
1115 int mod, regop, rm, vvvv = vex_vreg();
1116 get_modrm(*current, &mod, ®op, &rm);
1119 AppendToBuffer(
"vmovss %s,", NameOfAVXRegister(regop));
1121 AppendToBuffer(
"%s,", NameOfAVXRegister(vvvv));
1123 current += PrintRightAVXOperand(current);
1126 AppendToBuffer(
"vmovss ");
1127 current += PrintRightAVXOperand(current);
1129 AppendToBuffer(
",%s", NameOfAVXRegister(vvvv));
1131 AppendToBuffer(
",%s", NameOfAVXRegister(regop));
1134 AppendToBuffer(
"vmovshdup %s,", NameOfAVXRegister(regop));
1135 current += PrintRightAVXOperand(current);
1138 AppendToBuffer(
"%s %s,%s,", vex_w() ?
"vcvtqsi2ss" :
"vcvtlsi2ss",
1139 NameOfAVXRegister(regop), NameOfAVXRegister(vvvv));
1140 current += PrintRightOperand(current);
1143 AppendToBuffer(
"vcvttss2si%s %s,", vex_w() ?
"q" :
"",
1144 NameOfCPURegister(regop));
1145 current += PrintRightAVXOperand(current);
1148 AppendToBuffer(
"vsqrtss %s,%s,", NameOfAVXRegister(regop),
1149 NameOfAVXRegister(vvvv));
1150 current += PrintRightAVXOperand(current);
1153 AppendToBuffer(
"vaddss %s,%s,", NameOfAVXRegister(regop),
1154 NameOfAVXRegister(vvvv));
1155 current += PrintRightAVXOperand(current);
1158 AppendToBuffer(
"vmulss %s,%s,", NameOfAVXRegister(regop),
1159 NameOfAVXRegister(vvvv));
1160 current += PrintRightAVXOperand(current);
1163 AppendToBuffer(
"vcvtss2sd %s,%s,", NameOfAVXRegister(regop),
1164 NameOfAVXRegister(vvvv));
1165 current += PrintRightAVXOperand(current);
1168 AppendToBuffer(
"vcvttps2dq %s,", NameOfAVXRegister(regop));
1169 current += PrintRightAVXOperand(current);
1172 AppendToBuffer(
"vsubss %s,%s,", NameOfAVXRegister(regop),
1173 NameOfAVXRegister(vvvv));
1174 current += PrintRightAVXOperand(current);
1177 AppendToBuffer(
"vminss %s,%s,", NameOfAVXRegister(regop),
1178 NameOfAVXRegister(vvvv));
1179 current += PrintRightAVXOperand(current);
1182 AppendToBuffer(
"vdivss %s,%s,", NameOfAVXRegister(regop),
1183 NameOfAVXRegister(vvvv));
1184 current += PrintRightAVXOperand(current);
1187 AppendToBuffer(
"vmaxss %s,%s,", NameOfAVXRegister(regop),
1188 NameOfAVXRegister(vvvv));
1189 current += PrintRightAVXOperand(current);
1192 AppendToBuffer(
"vmovdqu %s,", NameOfAVXRegister(regop));
1193 current += PrintRightAVXOperand(current);
1196 AppendToBuffer(
"vpshufhw %s,", NameOfAVXRegister(regop));
1197 current += PrintRightAVXOperand(current);
1198 AppendToBuffer(
",0x%x", *current++);
1201 AppendToBuffer(
"vmovdqu ");
1202 current += PrintRightAVXOperand(current);
1203 AppendToBuffer(
",%s", NameOfAVXRegister(regop));
1206 AppendToBuffer(
"vcvtdq2pd %s,", NameOfAVXRegister(regop));
1207 current += PrintRightXMMOperand(current);
1210 AppendToBuffer(
"vcmpss %s,%s,", NameOfAVXRegister(regop),
1211 NameOfAVXRegister(vvvv));
1212 current += PrintRightAVXOperand(current);
1213 AppendToBuffer(
", (%s)", cmp_pseudo_op[*current]);
1217 UnimplementedInstruction();
1219 }
else if (vex_f2() && vex_0f()) {
1220 int mod, regop, rm, vvvv = vex_vreg();
1221 get_modrm(*current, &mod, ®op, &rm);
1224 AppendToBuffer(
"vmovsd %s,", NameOfAVXRegister(regop));
1226 AppendToBuffer(
"%s,", NameOfAVXRegister(vvvv));
1228 current += PrintRightAVXOperand(current);
1231 AppendToBuffer(
"vmovsd ");
1232 current += PrintRightAVXOperand(current);
1234 AppendToBuffer(
",%s", NameOfAVXRegister(vvvv));
1236 AppendToBuffer(
",%s", NameOfAVXRegister(regop));
1239 AppendToBuffer(
"vmovddup %s,", NameOfAVXRegister(regop));
1240 current += PrintRightAVXOperand(current);
1243 AppendToBuffer(
"%s %s,%s,", vex_w() ?
"vcvtqsi2sd" :
"vcvtlsi2sd",
1244 NameOfAVXRegister(regop), NameOfAVXRegister(vvvv));
1245 current += PrintRightOperand(current);
1248 AppendToBuffer(
"vcvttsd2si%s %s,", vex_w() ?
"q" :
"",
1249 NameOfCPURegister(regop));
1250 current += PrintRightAVXOperand(current);
1253 AppendToBuffer(
"vcvtsd2si%s %s,", vex_w() ?
"q" :
"",
1254 NameOfCPURegister(regop));
1255 current += PrintRightAVXOperand(current);
1258 AppendToBuffer(
"vlddqu %s,", NameOfAVXRegister(regop));
1259 current += PrintRightAVXOperand(current);
1262 AppendToBuffer(
"vpshuflw %s,", NameOfAVXRegister(regop));
1263 current += PrintRightAVXOperand(current);
1264 AppendToBuffer(
",0x%x", *current++);
1267 AppendToBuffer(
"vhaddps %s,%s,", NameOfAVXRegister(regop),
1268 NameOfAVXRegister(vvvv));
1269 current += PrintRightAVXOperand(current);
1272 AppendToBuffer(
"vcmpsd %s,%s,", NameOfAVXRegister(regop),
1273 NameOfAVXRegister(vvvv));
1274 current += PrintRightAVXOperand(current);
1275 AppendToBuffer(
", (%s)", cmp_pseudo_op[*current]);
1278#define DISASM_SSE2_INSTRUCTION_LIST_SD(instruction, _1, _2, opcode) \
1280 AppendToBuffer("v" #instruction " %s,%s,", NameOfAVXRegister(regop), \
1281 NameOfAVXRegister(vvvv)); \
1282 current += PrintRightAVXOperand(current); \
1285#undef DISASM_SSE2_INSTRUCTION_LIST_SD
1287 UnimplementedInstruction();
1289 }
else if (vex_none() && vex_0f38()) {
1290 int mod, regop, rm, vvvv = vex_vreg();
1291 get_modrm(*current, &mod, ®op, &rm);
1292 const char* mnem =
"?";
1295 AppendToBuffer(
"andn%c %s,%s,", operand_size_code(),
1296 NameOfCPURegister(regop), NameOfCPURegister(vvvv));
1297 current += PrintRightOperand(current);
1300 AppendToBuffer(
"bzhi%c %s,", operand_size_code(),
1301 NameOfCPURegister(regop));
1302 current += PrintRightOperand(current);
1303 AppendToBuffer(
",%s", NameOfCPURegister(vvvv));
1306 AppendToBuffer(
"bextr%c %s,", operand_size_code(),
1307 NameOfCPURegister(regop));
1308 current += PrintRightOperand(current);
1309 AppendToBuffer(
",%s", NameOfCPURegister(vvvv));
1323 UnimplementedInstruction();
1325 AppendToBuffer(
"%s%c %s,", mnem, operand_size_code(),
1326 NameOfCPURegister(vvvv));
1327 current += PrintRightOperand(current);
1331 UnimplementedInstruction();
1333 }
else if (vex_f2() && vex_0f38()) {
1334 int mod, regop, rm, vvvv = vex_vreg();
1335 get_modrm(*current, &mod, ®op, &rm);
1338 AppendToBuffer(
"pdep%c %s,%s,", operand_size_code(),
1339 NameOfCPURegister(regop), NameOfCPURegister(vvvv));
1340 current += PrintRightOperand(current);
1343 AppendToBuffer(
"mulx%c %s,%s,", operand_size_code(),
1344 NameOfCPURegister(regop), NameOfCPURegister(vvvv));
1345 current += PrintRightOperand(current);
1348 AppendToBuffer(
"shrx%c %s,", operand_size_code(),
1349 NameOfCPURegister(regop));
1350 current += PrintRightOperand(current);
1351 AppendToBuffer(
",%s", NameOfCPURegister(vvvv));
1354 AppendToBuffer(
"vpdpbssd %s,%s,", NameOfAVXRegister(regop),
1355 NameOfAVXRegister(vvvv));
1356 current += PrintRightAVXOperand(current);
1359 UnimplementedInstruction();
1361 }
else if (vex_f3() && vex_0f38()) {
1362 int mod, regop, rm, vvvv = vex_vreg();
1363 get_modrm(*current, &mod, ®op, &rm);
1366 AppendToBuffer(
"pext%c %s,%s,", operand_size_code(),
1367 NameOfCPURegister(regop), NameOfCPURegister(vvvv));
1368 current += PrintRightOperand(current);
1371 AppendToBuffer(
"sarx%c %s,", operand_size_code(),
1372 NameOfCPURegister(regop));
1373 current += PrintRightOperand(current);
1374 AppendToBuffer(
",%s", NameOfCPURegister(vvvv));
1377 UnimplementedInstruction();
1379 }
else if (vex_f2() && vex_0f3a()) {
1381 get_modrm(*current, &mod, ®op, &rm);
1384 AppendToBuffer(
"rorx%c %s,", operand_size_code(),
1385 NameOfCPURegister(regop));
1386 current += PrintRightOperand(current);
1387 switch (operand_size()) {
1388 case OPERAND_DOUBLEWORD_SIZE:
1389 AppendToBuffer(
",%d", *current & 0x1F);
1391 case OPERAND_QUADWORD_SIZE:
1392 AppendToBuffer(
",%d", *current & 0x3F);
1395 UnimplementedInstruction();
1400 UnimplementedInstruction();
1402 }
else if (vex_none() && vex_0f()) {
1403 int mod, regop, rm, vvvv = vex_vreg();
1404 get_modrm(*current, &mod, ®op, &rm);
1407 AppendToBuffer(
"vmovups %s,", NameOfAVXRegister(regop));
1408 current += PrintRightAVXOperand(current);
1411 AppendToBuffer(
"vmovups ");
1412 current += PrintRightAVXOperand(current);
1413 AppendToBuffer(
",%s", NameOfAVXRegister(regop));
1417 AppendToBuffer(
"vmovhlps %s,%s,", NameOfAVXRegister(regop),
1418 NameOfAVXRegister(vvvv));
1419 current += PrintRightAVXOperand(current);
1421 AppendToBuffer(
"vmovlps %s,%s,", NameOfAVXRegister(regop),
1422 NameOfAVXRegister(vvvv));
1423 current += PrintRightAVXOperand(current);
1427 AppendToBuffer(
"vmovlps ");
1428 current += PrintRightAVXOperand(current);
1429 AppendToBuffer(
",%s", NameOfAVXRegister(regop));
1433 AppendToBuffer(
"vmovlhps %s,%s,", NameOfAVXRegister(regop),
1434 NameOfAVXRegister(vvvv));
1435 current += PrintRightAVXOperand(current);
1437 AppendToBuffer(
"vmovhps %s,%s,", NameOfAVXRegister(regop),
1438 NameOfAVXRegister(vvvv));
1439 current += PrintRightAVXOperand(current);
1443 AppendToBuffer(
"vmovhps ");
1444 current += PrintRightAVXOperand(current);
1445 AppendToBuffer(
",%s", NameOfAVXRegister(regop));
1448 AppendToBuffer(
"vmovaps %s,", NameOfAVXRegister(regop));
1449 current += PrintRightAVXOperand(current);
1452 AppendToBuffer(
"vmovaps ");
1453 current += PrintRightAVXOperand(current);
1454 AppendToBuffer(
",%s", NameOfAVXRegister(regop));
1457 AppendToBuffer(
"vucomiss %s,", NameOfAVXRegister(regop));
1458 current += PrintRightAVXOperand(current);
1461 AppendToBuffer(
"vmovmskps %s,", NameOfCPURegister(regop));
1462 current += PrintRightAVXOperand(current);
1465 AppendToBuffer(
"vcmpps %s,%s,", NameOfAVXRegister(regop),
1466 NameOfAVXRegister(vvvv));
1467 current += PrintRightAVXOperand(current);
1468 AppendToBuffer(
", (%s)", cmp_pseudo_op[*current]);
1473 AppendToBuffer(
"vshufps %s,%s,", NameOfAVXRegister(regop),
1474 NameOfAVXRegister(vvvv));
1475 current += PrintRightAVXOperand(current);
1476 AppendToBuffer(
",0x%x", *current++);
1479#define SSE_UNOP_CASE(instruction, unused, code) \
1481 AppendToBuffer("v" #instruction " %s,", NameOfAVXRegister(regop)); \
1482 current += PrintRightAVXOperand(current); \
1486#define SSE_BINOP_CASE(instruction, unused, code) \
1488 AppendToBuffer("v" #instruction " %s,%s,", NameOfAVXRegister(regop), \
1489 NameOfAVXRegister(vvvv)); \
1490 current += PrintRightAVXOperand(current); \
1493#undef SSE_BINOP_CASE
1495 UnimplementedInstruction();
1497 }
else if (vex_66() && vex_0f()) {
1498 int mod, regop, rm, vvvv = vex_vreg();
1499 get_modrm(*current, &mod, ®op, &rm);
1502 AppendToBuffer(
"vmovupd %s,", NameOfAVXRegister(regop));
1503 current += PrintRightAVXOperand(current);
1506 AppendToBuffer(
"vmovupd ");
1507 current += PrintRightAVXOperand(current);
1508 AppendToBuffer(
",%s", NameOfAVXRegister(regop));
1511 AppendToBuffer(
"vmovapd %s,", NameOfAVXRegister(regop));
1512 current += PrintRightAVXOperand(current);
1515 AppendToBuffer(
"vmovapd ");
1516 current += PrintRightAVXOperand(current);
1517 AppendToBuffer(
",%s", NameOfAVXRegister(regop));
1520 AppendToBuffer(
"vmovmskpd %s,", NameOfCPURegister(regop));
1521 current += PrintRightAVXOperand(current);
1524 AppendToBuffer(
"vmov%c %s,", vex_w() ?
'q' :
'd',
1525 NameOfAVXRegister(regop));
1526 current += PrintRightOperand(current);
1529 AppendToBuffer(
"vmovdqa %s,", NameOfAVXRegister(regop));
1530 current += PrintRightAVXOperand(current);
1533 AppendToBuffer(
"vpshufd %s,", NameOfAVXRegister(regop));
1534 current += PrintRightAVXOperand(current);
1535 AppendToBuffer(
",0x%x", *current++);
1538 AppendToBuffer(
"vps%sw %s,", sf_str[regop / 2],
1539 NameOfAVXRegister(vvvv));
1540 current += PrintRightAVXOperand(current);
1541 AppendToBuffer(
",%u", *current++);
1544 AppendToBuffer(
"vps%sd %s,", sf_str[regop / 2],
1545 NameOfAVXRegister(vvvv));
1546 current += PrintRightAVXOperand(current);
1547 AppendToBuffer(
",%u", *current++);
1550 AppendToBuffer(
"vps%sq %s,", sf_str[regop / 2],
1551 NameOfAVXRegister(vvvv));
1552 current += PrintRightAVXOperand(current);
1553 AppendToBuffer(
",%u", *current++);
1556 AppendToBuffer(
"vmov%c ", vex_w() ?
'q' :
'd');
1557 current += PrintRightOperand(current);
1558 AppendToBuffer(
",%s", NameOfAVXRegister(regop));
1561 AppendToBuffer(
"vcmppd %s,%s,", NameOfAVXRegister(regop),
1562 NameOfAVXRegister(vvvv));
1563 current += PrintRightAVXOperand(current);
1564 AppendToBuffer(
", (%s)", cmp_pseudo_op[*current]);
1569 AppendToBuffer(
"vpinsrw %s,%s,", NameOfAVXRegister(regop),
1570 NameOfAVXRegister(vvvv));
1571 current += PrintRightOperand(current);
1572 AppendToBuffer(
",0x%x", *current++);
1575 AppendToBuffer(
"vpextrw %s,", NameOfCPURegister(regop));
1576 current += PrintRightAVXOperand(current);
1577 AppendToBuffer(
",0x%x", *current++);
1580 AppendToBuffer(
"vpmovmskb %s,", NameOfCPURegister(regop));
1581 current += PrintRightAVXOperand(current);
1583#define DECLARE_SSE_AVX_DIS_CASE(instruction, notUsed1, notUsed2, opcode) \
1584 case 0x##opcode: { \
1585 AppendToBuffer("v" #instruction " %s,%s,", NameOfAVXRegister(regop), \
1586 NameOfAVXRegister(vvvv)); \
1587 current += PrintRightAVXOperand(current); \
1592#undef DECLARE_SSE_AVX_DIS_CASE
1593#define DECLARE_SSE_UNOP_AVX_DIS_CASE(instruction, opcode, SIMDRegister) \
1594 case 0x##opcode: { \
1595 AppendToBuffer("v" #instruction " %s,", NameOf##SIMDRegister(regop)); \
1596 current += PrintRightAVXOperand(current); \
1599 DECLARE_SSE_UNOP_AVX_DIS_CASE(ucomisd, 2E, AVXRegister)
1600 DECLARE_SSE_UNOP_AVX_DIS_CASE(sqrtpd, 51, AVXRegister)
1601 DECLARE_SSE_UNOP_AVX_DIS_CASE(cvtpd2ps, 5A, XMMRegister)
1602 DECLARE_SSE_UNOP_AVX_DIS_CASE(cvtps2dq, 5B, AVXRegister)
1603 DECLARE_SSE_UNOP_AVX_DIS_CASE(cvttpd2dq, E6, XMMRegister)
1604#undef DECLARE_SSE_UNOP_AVX_DIS_CASE
1606 UnimplementedInstruction();
1610 UnimplementedInstruction();
1613 return static_cast<int>(current -
data);
1617int DisassemblerX64::FPUInstruction(uint8_t* data) {
1618 uint8_t escape_opcode = *
data;
1620 uint8_t modrm_byte = *(data + 1);
1622 if (modrm_byte >= 0xC0) {
1623 return RegisterFPUInstruction(escape_opcode, modrm_byte);
1625 return MemoryFPUInstruction(escape_opcode, modrm_byte, data + 1);
1629int DisassemblerX64::MemoryFPUInstruction(
int escape_opcode,
int modrm_byte,
1630 uint8_t* modrm_start) {
1631 const char* mnem =
"?";
1632 int regop = (modrm_byte >> 3) & 0x7;
1633 switch (escape_opcode) {
1646 UnimplementedInstruction();
1665 UnimplementedInstruction();
1678 UnimplementedInstruction();
1691 UnimplementedInstruction();
1696 UnimplementedInstruction();
1698 AppendToBuffer(
"%s ", mnem);
1699 int count = PrintRightOperand(modrm_start);
1703int DisassemblerX64::RegisterFPUInstruction(
int escape_opcode,
1704 uint8_t modrm_byte) {
1705 bool has_register =
false;
1706 const char* mnem =
"?";
1708 switch (escape_opcode) {
1710 UnimplementedInstruction();
1714 switch (modrm_byte & 0xF8) {
1717 has_register =
true;
1721 has_register =
true;
1724 switch (modrm_byte) {
1780 UnimplementedInstruction();
1786 if (modrm_byte == 0xE9) {
1789 UnimplementedInstruction();
1794 if ((modrm_byte & 0xF8) == 0xE8) {
1796 has_register =
true;
1797 }
else if (modrm_byte == 0xE2) {
1799 }
else if (modrm_byte == 0xE3) {
1802 UnimplementedInstruction();
1807 has_register =
true;
1808 switch (modrm_byte & 0xF8) {
1822 UnimplementedInstruction();
1827 has_register =
true;
1828 switch (modrm_byte & 0xF8) {
1836 UnimplementedInstruction();
1841 if (modrm_byte == 0xD9) {
1844 has_register =
true;
1845 switch (modrm_byte & 0xF8) {
1859 UnimplementedInstruction();
1865 if (modrm_byte == 0xE0) {
1867 }
else if ((modrm_byte & 0xF8) == 0xE8) {
1869 has_register =
true;
1874 UnimplementedInstruction();
1878 AppendToBuffer(
"%s st%d", mnem, modrm_byte & 0x7);
1880 AppendToBuffer(
"%s", mnem);
1887int DisassemblerX64::TwoByteOpcodeInstruction(uint8_t* data) {
1888 uint8_t opcode = *(data + 1);
1889 uint8_t* current = data + 2;
1891 const char* mnemonic = TwoByteMnemonic(opcode);
1895 get_modrm(*current, &mod, ®op, &rm);
1896 if (operand_size_ == 0x66) {
1901 if (opcode == 0xC1) {
1902 current += PrintOperands(
"xadd", OPER_REG_OP_ORDER, current);
1903 }
else if (opcode == 0x1F) {
1910 }
else if (mod == 2) {
1913 AppendToBuffer(
"nop");
1914 }
else if (opcode == 0x10) {
1915 current += PrintOperands(
"movupd", XMMREG_XMMOPER_OP_ORDER, current);
1916 }
else if (opcode == 0x11) {
1917 current += PrintOperands(
"movupd", XMMOPER_XMMREG_OP_ORDER, current);
1918 }
else if (opcode == 0x28) {
1919 current += PrintOperands(
"movapd", XMMREG_XMMOPER_OP_ORDER, current);
1920 }
else if (opcode == 0x29) {
1921 current += PrintOperands(
"movapd", XMMOPER_XMMREG_OP_ORDER, current);
1922 }
else if (opcode == 0x6E) {
1923 current += PrintOperands(rex_w() ?
"movq" :
"movd", XMMREG_OPER_OP_ORDER,
1925 }
else if (opcode == 0x6F) {
1926 current += PrintOperands(
"movdqa", XMMREG_XMMOPER_OP_ORDER, current);
1927 }
else if (opcode == 0x7E) {
1928 current += PrintOperands(rex_w() ?
"movq" :
"movd", OPER_XMMREG_OP_ORDER,
1930 }
else if (opcode == 0x7F) {
1931 current += PrintOperands(
"movdqa", XMMOPER_XMMREG_OP_ORDER, current);
1932 }
else if (opcode == 0xD6) {
1933 current += PrintOperands(
"movq", XMMOPER_XMMREG_OP_ORDER, current);
1934 }
else if (opcode == 0x50) {
1935 AppendToBuffer(
"movmskpd %s,", NameOfCPURegister(regop));
1936 current += PrintRightXMMOperand(current);
1937 }
else if (opcode == 0x70) {
1938 current += PrintOperands(
"pshufd", XMMREG_XMMOPER_OP_ORDER, current);
1939 AppendToBuffer(
",0x%x", *current++);
1940 }
else if (opcode == 0x71) {
1942 AppendToBuffer(
"ps%sw %s,%d", sf_str[regop / 2], NameOfXMMRegister(rm),
1945 }
else if (opcode == 0x72) {
1947 AppendToBuffer(
"ps%sd %s,%d", sf_str[regop / 2], NameOfXMMRegister(rm),
1950 }
else if (opcode == 0x73) {
1952 AppendToBuffer(
"ps%sq %s,%d", sf_str[regop / 2], NameOfXMMRegister(rm),
1955 }
else if (opcode == 0xB1) {
1956 current += PrintOperands(
"cmpxchg", OPER_REG_OP_ORDER, current);
1957 }
else if (opcode == 0xC2) {
1958 AppendToBuffer(
"cmppd %s,", NameOfXMMRegister(regop));
1959 current += PrintRightXMMOperand(current);
1960 AppendToBuffer(
", (%s)", cmp_pseudo_op[*current++]);
1961 }
else if (opcode == 0xC4) {
1962 current += PrintOperands(
"pinsrw", XMMREG_OPER_OP_ORDER, current);
1963 AppendToBuffer(
",0x%x", (*current++) & 7);
1964 }
else if (opcode == 0xD7) {
1965 current += PrintOperands(
"pmovmskb", OPER_XMMREG_OP_ORDER, current);
1967#define SSE2_CASE(instruction, notUsed1, notUsed2, opcode) \
1969 mnemonic = "" #instruction; \
1977 AppendToBuffer(
"%s %s,", mnemonic, NameOfXMMRegister(regop));
1978 current += PrintRightXMMOperand(current);
1980 }
else if (group_1_prefix_ == 0xF2) {
1982 if (opcode == 0x10) {
1984 current += PrintOperands(
"movsd", XMMREG_XMMOPER_OP_ORDER, current);
1985 }
else if (opcode == 0x11) {
1986 current += PrintOperands(
"movsd", XMMOPER_XMMREG_OP_ORDER, current);
1987 }
else if (opcode == 0x12) {
1988 current += PrintOperands(
"movddup", XMMREG_XMMOPER_OP_ORDER, current);
1989 }
else if (opcode == 0x2A) {
1991 current += PrintOperands(mnemonic, XMMREG_OPER_OP_ORDER, current);
1992 }
else if (opcode == 0x2C) {
1995 AppendToBuffer(
"cvttsd2si%c %s,", operand_size_code(),
1996 NameOfCPURegister(regop));
1997 current += PrintRightXMMOperand(current);
1998 }
else if (opcode == 0x2D) {
2000 AppendToBuffer(
"cvtsd2si%c %s,", operand_size_code(),
2001 NameOfCPURegister(regop));
2002 current += PrintRightXMMOperand(current);
2003 }
else if (opcode == 0x5B) {
2006 AppendToBuffer(
"cvttps2dq%c %s,", operand_size_code(),
2007 NameOfCPURegister(regop));
2008 current += PrintRightXMMOperand(current);
2009 }
else if ((opcode & 0xF8) == 0x58 || opcode == 0x51) {
2011 current += PrintOperands(mnemonic, XMMREG_XMMOPER_OP_ORDER, current);
2012 }
else if (opcode == 0x70) {
2013 current += PrintOperands(
"pshuflw", XMMREG_XMMOPER_OP_ORDER, current);
2014 AppendToBuffer(
",%d", *current++);
2015 }
else if (opcode == 0xC2) {
2016 AppendToBuffer(
"cmp%ssd %s,%s", cmp_pseudo_op[current[1]],
2017 NameOfXMMRegister(regop), NameOfXMMRegister(rm));
2019 }
else if (opcode == 0xF0) {
2020 current += PrintOperands(
"lddqu", XMMREG_OPER_OP_ORDER, current);
2021 }
else if (opcode == 0x7C) {
2022 current += PrintOperands(
"haddps", XMMREG_XMMOPER_OP_ORDER, current);
2024 UnimplementedInstruction();
2026 }
else if (group_1_prefix_ == 0xF3) {
2028 if (opcode == 0x10) {
2030 current += PrintOperands(
"movss", XMMREG_XMMOPER_OP_ORDER, current);
2031 }
else if (opcode == 0x11) {
2032 current += PrintOperands(
"movss", OPER_XMMREG_OP_ORDER, current);
2033 }
else if (opcode == 0x16) {
2034 current += PrintOperands(
"movshdup", XMMREG_XMMOPER_OP_ORDER, current);
2035 }
else if (opcode == 0x2A) {
2037 current += PrintOperands(mnemonic, XMMREG_OPER_OP_ORDER, current);
2038 }
else if (opcode == 0x2C) {
2041 AppendToBuffer(
"cvttss2si%c %s,", operand_size_code(),
2042 NameOfCPURegister(regop));
2043 current += PrintRightXMMOperand(current);
2044 }
else if (opcode == 0x70) {
2045 current += PrintOperands(
"pshufhw", XMMREG_XMMOPER_OP_ORDER, current);
2046 AppendToBuffer(
",%d", *current++);
2047 }
else if (opcode == 0x6F) {
2048 current += PrintOperands(
"movdqu", XMMREG_XMMOPER_OP_ORDER, current);
2049 }
else if (opcode == 0x7E) {
2050 current += PrintOperands(
"movq", XMMREG_XMMOPER_OP_ORDER, current);
2051 }
else if (opcode == 0x7F) {
2052 current += PrintOperands(
"movdqu", XMMOPER_XMMREG_OP_ORDER, current);
2053 }
else if ((opcode & 0xF8) == 0x58 || opcode == 0x51) {
2055 current += PrintOperands(mnemonic, XMMREG_XMMOPER_OP_ORDER, current);
2056 }
else if (opcode == 0xB8) {
2057 AppendToBuffer(
"popcnt%c %s,", operand_size_code(),
2058 NameOfCPURegister(regop));
2059 current += PrintRightOperand(current);
2060 }
else if (opcode == 0xBC) {
2061 AppendToBuffer(
"tzcnt%c %s,", operand_size_code(),
2062 NameOfCPURegister(regop));
2063 current += PrintRightOperand(current);
2064 }
else if (opcode == 0xBD) {
2065 AppendToBuffer(
"lzcnt%c %s,", operand_size_code(),
2066 NameOfCPURegister(regop));
2067 current += PrintRightOperand(current);
2068 }
else if (opcode == 0xC2) {
2069 AppendToBuffer(
"cmp%sss %s,%s", cmp_pseudo_op[current[1]],
2070 NameOfXMMRegister(regop), NameOfXMMRegister(rm));
2072 }
else if (opcode == 0xE6) {
2073 current += PrintOperands(
"cvtdq2pd", XMMREG_XMMOPER_OP_ORDER, current);
2074 }
else if (opcode == 0xAE) {
2076 AppendToBuffer(
"incssp%c ", operand_size_code());
2077 current += PrintRightOperand(current);
2079 UnimplementedInstruction();
2081 }
else if (opcode == 0x10) {
2083 current += PrintOperands(
"movups", XMMREG_XMMOPER_OP_ORDER, current);
2084 }
else if (opcode == 0x11) {
2086 current += PrintOperands(
"movups", XMMOPER_XMMREG_OP_ORDER, current);
2087 }
else if (opcode == 0x12) {
2091 current += PrintOperands(
"movhlps", XMMREG_XMMOPER_OP_ORDER, current);
2093 current += PrintOperands(
"movlps", XMMREG_OPER_OP_ORDER, current);
2095 }
else if (opcode == 0x13) {
2097 current += PrintOperands(
"movlps", XMMOPER_XMMREG_OP_ORDER, current);
2098 }
else if (opcode == 0x16) {
2100 current += PrintOperands(
"movlhps", XMMREG_XMMOPER_OP_ORDER, current);
2102 current += PrintOperands(
"movhps", XMMREG_XMMOPER_OP_ORDER, current);
2104 }
else if (opcode == 0x17) {
2105 current += PrintOperands(
"movhps", XMMOPER_XMMREG_OP_ORDER, current);
2106 }
else if (opcode == 0x1F) {
2114 }
else if (mod == 2) {
2117 AppendToBuffer(
"nop");
2119 }
else if (opcode == 0x28) {
2120 current += PrintOperands(
"movaps", XMMREG_XMMOPER_OP_ORDER, current);
2121 }
else if (opcode == 0x29) {
2122 current += PrintOperands(
"movaps", XMMOPER_XMMREG_OP_ORDER, current);
2123 }
else if (opcode == 0x2E) {
2124 current += PrintOperands(
"ucomiss", XMMREG_XMMOPER_OP_ORDER, current);
2125 }
else if (opcode == 0xA2) {
2127 AppendToBuffer(
"%s", mnemonic);
2128 }
else if ((opcode & 0xF0) == 0x40) {
2131 const InstructionDesc& idesc = cmov_instructions[
condition];
2132 byte_size_operand_ = idesc.byte_size_operation;
2133 current += PrintOperands(idesc.mnem, idesc.op_order_, current);
2134 }
else if (opcode == 0xC0) {
2135 byte_size_operand_ =
true;
2136 current += PrintOperands(
"xadd", OPER_REG_OP_ORDER, current);
2137 }
else if (opcode == 0xC1) {
2138 current += PrintOperands(
"xadd", OPER_REG_OP_ORDER, current);
2139 }
else if (opcode == 0xC2) {
2141 AppendToBuffer(
"cmpps %s, ", NameOfXMMRegister(regop));
2142 current += PrintRightXMMOperand(current);
2143 AppendToBuffer(
", %s", cmp_pseudo_op[*current]);
2145 }
else if (opcode == 0xC6) {
2147 AppendToBuffer(
"shufps %s,", NameOfXMMRegister(regop));
2148 current += PrintRightXMMOperand(current);
2149 AppendToBuffer(
",%d", *current);
2151 }
else if (opcode >= 0xC8 && opcode <= 0xCF) {
2153 int reg = (opcode - 0xC8) | (rex_b() ? 8 : 0);
2154 AppendToBuffer(
"bswap%c %s", operand_size_code(), NameOfCPURegister(
reg));
2155 }
else if (opcode == 0x50) {
2157 AppendToBuffer(
"movmskps %s,", NameOfCPURegister(regop));
2158 current += PrintRightXMMOperand(current);
2159 }
else if ((opcode & 0xF0) == 0x80) {
2161 current = data + JumpConditional(data);
2163 }
else if (opcode == 0xBE || opcode == 0xBF || opcode == 0xB6 ||
2164 opcode == 0xB7 || opcode == 0xAF) {
2166 current += PrintOperands(mnemonic, REG_OPER_OP_ORDER, current);
2167 }
else if ((opcode & 0xF0) == 0x90) {
2169 current = data +
SetCC(data);
2170 }
else if (opcode == 0xA3 || opcode == 0xA5 || opcode == 0xAB ||
2174 AppendToBuffer(
"%s ", mnemonic);
2175 current += PrintRightOperand(current);
2176 if (opcode == 0xAB) {
2177 AppendToBuffer(
",%s", NameOfCPURegister(regop));
2179 AppendToBuffer(
",%s,cl", NameOfCPURegister(regop));
2181 }
else if (opcode == 0xBA) {
2183 mnemonic = regop == 5 ?
"bts" : regop == 6 ?
"btr" :
"?";
2184 AppendToBuffer(
"%s ", mnemonic);
2185 current += PrintRightOperand(current);
2186 AppendToBuffer(
",%d", *current++);
2187 }
else if (opcode == 0xB8 || opcode == 0xBC || opcode == 0xBD) {
2189 AppendToBuffer(
"%s%c ", mnemonic, operand_size_code());
2190 AppendToBuffer(
"%s,", NameOfCPURegister(regop));
2191 current += PrintRightOperand(current);
2192 }
else if (opcode == 0x0B) {
2193 AppendToBuffer(
"ud2");
2194 }
else if (opcode == 0xB0 || opcode == 0xB1) {
2196 if (opcode == 0xB0) {
2197 byte_size_operand_ =
true;
2199 current += PrintOperands(mnemonic, OPER_REG_OP_ORDER, current);
2200 }
else if (opcode == 0xAE && (data[2] & 0xF8) == 0xF0) {
2201 AppendToBuffer(
"mfence");
2203 }
else if (opcode == 0xAE && (data[2] & 0xF8) == 0xE8) {
2204 AppendToBuffer(
"lfence");
2207#define SSE_DISASM_CASE(instruction, unused, code) \
2208 } else if (opcode == 0x##code) { \
2209 current += PrintOperands(#instruction, XMMREG_XMMOPER_OP_ORDER, current);
2212#undef SSE_DISASM_CASE
2215 UnimplementedInstruction();
2217 return static_cast<int>(current -
data);
2223int DisassemblerX64::ThreeByteOpcodeInstruction(uint8_t* data) {
2227 uint8_t second_byte = *(data + 1);
2228 uint8_t third_byte = *(data + 2);
2229 uint8_t* current = data + 3;
2231 get_modrm(*current, &mod, ®op, &rm);
2232 if (second_byte == 0x38) {
2233 switch (third_byte) {
2235 current += PrintOperands(
"pblendvb", XMMREG_XMMOPER_OP_ORDER, current);
2236 AppendToBuffer(
",<xmm0>");
2240 current += PrintOperands(
"blendvps", XMMREG_XMMOPER_OP_ORDER, current);
2241 AppendToBuffer(
",<xmm0>");
2245 current += PrintOperands(
"blendvpd", XMMREG_XMMOPER_OP_ORDER, current);
2246 AppendToBuffer(
",<xmm0>");
2249#define SSE34_DIS_CASE(instruction, notUsed1, notUsed2, notUsed3, opcode) \
2250 case 0x##opcode: { \
2251 current += PrintOperands(#instruction, XMMREG_XMMOPER_OP_ORDER, current); \
2260#undef SSE34_DIS_CASE
2262 UnimplementedInstruction();
2266 if (third_byte == 0x17) {
2267 current += PrintOperands(
"extractps", OPER_XMMREG_OP_ORDER, current);
2268 AppendToBuffer(
",%d", (*current++) & 3);
2269 }
else if (third_byte == 0x08) {
2270 current += PrintOperands(
"roundps", XMMREG_XMMOPER_OP_ORDER, current);
2271 AppendToBuffer(
",0x%x", (*current++) & 3);
2272 }
else if (third_byte == 0x09) {
2273 current += PrintOperands(
"roundpd", XMMREG_XMMOPER_OP_ORDER, current);
2274 AppendToBuffer(
",0x%x", (*current++) & 3);
2275 }
else if (third_byte == 0x0A) {
2276 current += PrintOperands(
"roundss", XMMREG_XMMOPER_OP_ORDER, current);
2277 AppendToBuffer(
",0x%x", (*current++) & 3);
2278 }
else if (third_byte == 0x0B) {
2279 current += PrintOperands(
"roundsd", XMMREG_XMMOPER_OP_ORDER, current);
2280 AppendToBuffer(
",0x%x", (*current++) & 3);
2281 }
else if (third_byte == 0x0E) {
2282 current += PrintOperands(
"pblendw", XMMREG_XMMOPER_OP_ORDER, current);
2283 AppendToBuffer(
",0x%x", *current++);
2284 }
else if (third_byte == 0x0F) {
2285 current += PrintOperands(
"palignr", XMMREG_XMMOPER_OP_ORDER, current);
2286 AppendToBuffer(
",0x%x", *current++);
2287 }
else if (third_byte == 0x14) {
2288 current += PrintOperands(
"pextrb", OPER_XMMREG_OP_ORDER, current);
2289 AppendToBuffer(
",%d", (*current++) & 0xf);
2290 }
else if (third_byte == 0x15) {
2291 current += PrintOperands(
"pextrw", OPER_XMMREG_OP_ORDER, current);
2292 AppendToBuffer(
",%d", (*current++) & 7);
2293 }
else if (third_byte == 0x16) {
2294 const char* mnem = rex_w() ?
"pextrq" :
"pextrd";
2295 current += PrintOperands(mnem, OPER_XMMREG_OP_ORDER, current);
2296 AppendToBuffer(
",%d", (*current++) & 3);
2297 }
else if (third_byte == 0x20) {
2298 current += PrintOperands(
"pinsrb", XMMREG_OPER_OP_ORDER, current);
2299 AppendToBuffer(
",%d", (*current++) & 0xf);
2300 }
else if (third_byte == 0x21) {
2301 current += PrintOperands(
"insertps", XMMREG_XMMOPER_OP_ORDER, current);
2302 AppendToBuffer(
",0x%x", *current++);
2303 }
else if (third_byte == 0x22) {
2304 const char* mnem = rex_w() ?
"pinsrq" :
"pinsrd";
2305 current += PrintOperands(mnem, XMMREG_OPER_OP_ORDER, current);
2306 AppendToBuffer(
",%d", (*current++) & 3);
2308 UnimplementedInstruction();
2311 return static_cast<int>(current -
data);
2317const char* DisassemblerX64::TwoByteMnemonic(uint8_t opcode) {
2318 if (opcode >= 0xC8 && opcode <= 0xCF)
return "bswap";
2323 return (group_1_prefix_ == 0xF2) ?
"cvtsi2sd" :
"cvtsi2ss";
2325 return (group_1_prefix_ == 0xF2) ?
"sqrtsd" :
"sqrtss";
2327 return (group_1_prefix_ == 0xF2) ?
"addsd" :
"addss";
2329 return (group_1_prefix_ == 0xF2) ?
"mulsd" :
"mulss";
2331 return (group_1_prefix_ == 0xF2) ?
"cvtsd2ss" :
"cvtss2sd";
2335 return (group_1_prefix_ == 0xF2) ?
"minsd" :
"minss";
2337 return (group_1_prefix_ == 0xF2) ?
"subsd" :
"subss";
2339 return (group_1_prefix_ == 0xF2) ?
"divsd" :
"divss";
2341 return (group_1_prefix_ == 0xF2) ?
"maxsd" :
"maxss";
2379 tmp_buffer_pos_ = 0;
2380 uint8_t* data =
instr;
2381 bool processed =
true;
2388 if (current == OPERAND_SIZE_OVERRIDE_PREFIX) {
2390 }
else if ((current & 0xF0) == 0x40) {
2392 if (rex_w()) AppendToBuffer(
"REX.W ");
2393 }
else if ((current & 0xFE) == 0xF2) {
2395 }
else if (current == LOCK_PREFIX) {
2396 AppendToBuffer(
"lock ");
2397 }
else if (current == VEX3_PREFIX) {
2399 vex_byte1_ = *(data + 1);
2400 vex_byte2_ = *(data + 2);
2401 setRex(0x40 | (~(vex_byte1_ >> 5) & 7) | ((vex_byte2_ >> 4) & 8));
2404 }
else if (current == VEX2_PREFIX) {
2406 vex_byte1_ = *(data + 1);
2407 setRex(0x40 | (~(vex_byte1_ >> 5) & 4));
2410 }
else if (current == SEGMENT_FS_OVERRIDE_PREFIX) {
2412 }
else if (current == ADDRESS_SIZE_OVERRIDE_PREFIX) {
2413 address_size_prefix_ =
current;
2421 if (vex_byte0_ != 0) {
2423 data += AVXInstruction(data);
2424 }
else if (segment_prefix_ != 0 && address_size_prefix_ != 0) {
2425 if (*data == 0x90 && *(data + 1) == 0x90 && *(data + 2) == 0x90) {
2426 AppendToBuffer(
"sscmark");
2431 const InstructionDesc& idesc = instruction_table_->Get(current);
2432 byte_size_operand_ = idesc.byte_size_operation;
2433 switch (idesc.type) {
2434 case ZERO_OPERANDS_INSTR:
2435 if ((current >= 0xA4 && current <= 0xA7) ||
2436 (current >= 0xAA && current <= 0xAD)) {
2438 if (group_1_prefix_ == REP_PREFIX) {
2440 AppendToBuffer(
"rep ");
2442 AppendToBuffer(
"%s%c", idesc.mnem, operand_size_code());
2444 AppendToBuffer(
"%s%c", idesc.mnem, operand_size_code());
2449 case TWO_OPERANDS_INSTR:
2451 data += PrintOperands(idesc.mnem, idesc.op_order_, data);
2454 case JUMP_CONDITIONAL_SHORT_INSTR:
2455 data += JumpConditionalShort(data);
2458 case REGISTER_INSTR:
2459 AppendToBuffer(
"%s%c %s", idesc.mnem, operand_size_code(),
2460 NameOfCPURegister(base_reg(current & 0x07)));
2464 AppendToBuffer(
"%s %s", idesc.mnem,
2465 NameOfCPURegister(base_reg(current & 0x07)));
2468 case MOVE_REG_INSTR: {
2469 uint8_t* addr =
nullptr;
2470 switch (operand_size()) {
2471 case OPERAND_WORD_SIZE:
2472 addr =
reinterpret_cast<uint8_t*
>(Imm16(data + 1));
2475 case OPERAND_DOUBLEWORD_SIZE:
2476 addr =
reinterpret_cast<uint8_t*
>(Imm32_U(data + 1));
2479 case OPERAND_QUADWORD_SIZE:
2480 addr =
reinterpret_cast<uint8_t*
>(Imm64(data + 1));
2486 AppendToBuffer(
"mov%c %s,%s", operand_size_code(),
2487 NameOfCPURegister(base_reg(current & 0x07)),
2488 NameOfAddress(addr));
2492 case CALL_JUMP_INSTR: {
2493 uint8_t* addr = data + Imm32(data + 1) + 5;
2494 AppendToBuffer(
"%s %s", idesc.mnem, NameOfAddress(addr));
2499 case SHORT_IMMEDIATE_INSTR: {
2501 if (operand_size() == OPERAND_WORD_SIZE) {
2502 imm = Imm16(data + 1);
2505 imm = Imm32(data + 1);
2508 AppendToBuffer(
"%s rax,0x%x", idesc.mnem, imm);
2526 AppendToBuffer(
"ret 0x%x", Imm16_U(data + 1));
2533 count += PrintOperands(
"imul", REG_OPER_OP_ORDER, data + count);
2534 AppendToBuffer(
",0x");
2535 if (*data == 0x69) {
2536 count += PrintImmediate(data + count, operand_size());
2538 count += PrintImmediate(data + count, OPERAND_BYTE_SIZE);
2545 byte_size_operand_ =
true;
2549 data += PrintImmediateOp(data);
2554 if (*(data + 1) == 0x38 || *(data + 1) == 0x3A) {
2555 data += ThreeByteOpcodeInstruction(data);
2557 data += TwoByteOpcodeInstruction(data);
2564 get_modrm(*data, &mod, ®op, &rm);
2566 AppendToBuffer(
"pop ");
2567 data += PrintRightOperand(data);
2574 get_modrm(*data, &mod, ®op, &rm);
2575 const char* mnem =
nullptr;
2596 AppendToBuffer(
"%s%c ", mnem, operand_size_code());
2598 AppendToBuffer(
"%s ", mnem);
2600 data += PrintRightOperand(data);
2606 bool is_byte = *data == 0xC6;
2609 AppendToBuffer(
"movb ");
2610 data += PrintRightByteOperand(data);
2612 AppendToBuffer(
",0x%x", imm);
2615 AppendToBuffer(
"mov%c ", operand_size_code());
2616 data += PrintRightOperand(data);
2617 if (operand_size() == OPERAND_WORD_SIZE) {
2618 AppendToBuffer(
",0x%x", Imm16(data));
2621 AppendToBuffer(
",0x%x", Imm32(data));
2630 bool is_byte = *data == 0x88;
2633 get_modrm(*data, &mod, ®op, &rm);
2635 AppendToBuffer(
"movb ");
2636 data += PrintRightByteOperand(data);
2637 AppendToBuffer(
",%s", NameOfByteCPURegister(regop));
2639 AppendToBuffer(
"mov%c ", operand_size_code());
2640 data += PrintRightOperand(data);
2641 AppendToBuffer(
",%s", NameOfCPURegister(regop));
2653 int reg = (*data & 0x7) | (rex_b() ? 8 : 0);
2654 if (group_1_prefix_ == 0xF3 && *data == 0x90) {
2655 AppendToBuffer(
"pause");
2656 }
else if (
reg == 0) {
2657 AppendToBuffer(
"nop");
2659 AppendToBuffer(
"xchg%c rax,%s", operand_size_code(),
2660 NameOfCPURegister(
reg));
2681 uint8_t opcode = *
data;
2683 bool is_32bit = (opcode >= 0xB8);
2684 int reg = (opcode & 0x7) | (rex_b() ? 8 : 0);
2686 AppendToBuffer(
"mov%c %s,", operand_size_code(),
2687 NameOfCPURegister(
reg));
2688 data += PrintImmediate(data, OPERAND_DOUBLEWORD_SIZE);
2690 AppendToBuffer(
"movb %s,", NameOfByteCPURegister(
reg));
2691 data += PrintImmediate(data, OPERAND_BYTE_SIZE);
2698 get_modrm(*data, &mod, ®op, &rm);
2700 AppendToBuffer(
"decb ");
2701 data += PrintRightByteOperand(data);
2703 UnimplementedInstruction();
2708 AppendToBuffer(
"push 0x%x", Imm32(data + 1));
2713 AppendToBuffer(
"push 0x%x", Imm8(data + 1));
2719 switch (operand_size()) {
2720 case OPERAND_DOUBLEWORD_SIZE: {
2721 const char* memory_location =
2722 NameOfAddress(
reinterpret_cast<uint8_t*
>(Imm32(data + 1)));
2723 if (*data == 0xA1) {
2724 AppendToBuffer(
"movzxlq rax,(%s)", memory_location);
2726 AppendToBuffer(
"movzxlq (%s),rax", memory_location);
2731 case OPERAND_QUADWORD_SIZE: {
2733 const char* memory_location =
2734 NameOfAddress(
reinterpret_cast<uint8_t*
>(Imm64(data + 1)));
2735 if (*data == 0xA1) {
2736 AppendToBuffer(
"movq rax,(%s)", memory_location);
2738 AppendToBuffer(
"movq (%s),rax", memory_location);
2744 UnimplementedInstruction();
2750 AppendToBuffer(
"test al,0x%x", Imm8_U(data + 1));
2756 switch (operand_size()) {
2757 case OPERAND_WORD_SIZE:
2758 value = Imm16_U(data + 1);
2761 case OPERAND_DOUBLEWORD_SIZE:
2762 value = Imm32_U(data + 1);
2765 case OPERAND_QUADWORD_SIZE:
2766 value = Imm32(data + 1);
2772 AppendToBuffer(
"test%c rax,0x%" PRIx64, operand_size_code(), value);
2778 data += ShiftInstruction(data);
2783 byte_size_operand_ =
true;
2784 data += ShiftInstruction(data);
2794 data += FPUInstruction(data);
2798 data += JumpShort(data);
2802 byte_size_operand_ =
true;
2805 data += F6F7Instruction(data);
2809 AppendToBuffer(
"cmpb al,0x%x", Imm8(data + 1));
2814 UnimplementedInstruction();
2819 if (tmp_buffer_pos_ <
sizeof tmp_buffer_) {
2820 tmp_buffer_[tmp_buffer_pos_] =
'\0';
2823 int instr_len =
static_cast<int>(data -
instr);
2828 for (uint8_t* bp =
instr; bp <
data; bp++) {
2843static const char*
const cpu_regs[16] = {
2844 "rax",
"rcx",
"rdx",
"rbx",
"rsp",
"rbp",
"rsi",
"rdi",
2845 "r8",
"r9",
"r10",
"r11",
"r12",
"r13",
"r14",
"r15"};
2847static const char*
const byte_cpu_regs[16] = {
2848 "al",
"cl",
"dl",
"bl",
"spl",
"bpl",
"sil",
"dil",
2849 "r8l",
"r9l",
"r10l",
"r11l",
"r12l",
"r13l",
"r14l",
"r15l"};
2851static const char*
const xmm_regs[16] = {
2852 "xmm0",
"xmm1",
"xmm2",
"xmm3",
"xmm4",
"xmm5",
"xmm6",
"xmm7",
2853 "xmm8",
"xmm9",
"xmm10",
"xmm11",
"xmm12",
"xmm13",
"xmm14",
"xmm15"};
2855static const char*
const ymm_regs[16] = {
2856 "ymm0",
"ymm1",
"ymm2",
"ymm3",
"ymm4",
"ymm5",
"ymm6",
"ymm7",
2857 "ymm8",
"ymm9",
"ymm10",
"ymm11",
"ymm12",
"ymm13",
"ymm14",
"ymm15"};
2869 if (0 <=
reg &&
reg < 16)
return cpu_regs[
reg];
2874 if (0 <=
reg &&
reg < 16)
return byte_cpu_regs[
reg];
2879 if (0 <=
reg &&
reg < 16)
return xmm_regs[
reg];
2883const char* NameOfYMMRegister(
int reg) {
2884 if (0 <=
reg &&
reg < 16)
return ymm_regs[
reg];
2896 uint8_t* instruction) {
2898 return d.InstructionDecode(buffer, instruction);
2905 UnimplementedOpcodeAction unimplemented_action) {
2906 NameConverter converter;
2908 for (uint8_t*
pc = begin;
pc <
end;) {
2911 uint8_t* prev_pc =
pc;
2912 pc += d.InstructionDecode(buffer,
pc);
2913 fprintf(f,
"%p",
static_cast<void*
>(prev_pc));
2916 for (uint8_t* bp = prev_pc; bp <
pc; bp++) {
2917 fprintf(f,
"%02x", *bp);
2919 for (
int i = 6 -
static_cast<int>(
pc - prev_pc);
i >= 0;
i--) {
2922 fprintf(f,
" %s\n", buffer.
begin());
interpreter::OperandScale scale
union v8::internal::@341::BuiltinMetadata::KindSpecificData data
static V8_EXPORT_PRIVATE void Disassemble(FILE *f, uint8_t *begin, uint8_t *end, UnimplementedOpcodeAction unimplemented_action=kAbortOnUnimplementedOpcode)
V8_EXPORT_PRIVATE int InstructionDecode(v8::base::Vector< char > buffer, uint8_t *instruction)
int ConstantPoolSizeAt(uint8_t *instruction)
Disassembler(const NameConverter &converter, UnimplementedOpcodeAction unimplemented_opcode_action=kAbortOnUnimplementedOpcode)
UnimplementedOpcodeAction unimplemented_opcode_action() const
const NameConverter & converter_
virtual const char * NameOfAddress(uint8_t *addr) const
virtual const char * NameOfXMMRegister(int reg) const
virtual const char * NameInCode(uint8_t *addr) const
virtual const char * NameOfConstant(uint8_t *addr) const
v8::base::EmbeddedVector< char, 128 > tmp_buffer_
virtual const char * NameOfByteCPURegister(int reg) const
virtual const char * NameOfCPURegister(int reg) const
constexpr T * begin() const
base::Vector< const DirectHandle< Object > > args
#define FMA_SD_INSTRUCTION_LIST(V)
#define FMA_PD_INSTRUCTION_LIST(V)
#define FMA_SS_INSTRUCTION_LIST(V)
#define FMA_PS_INSTRUCTION_LIST(V)
#define SSE_UNOP_INSTRUCTION_LIST(V)
#define SSSE3_UNOP_INSTRUCTION_LIST(V)
#define SSE4_INSTRUCTION_LIST(V)
#define SSE2_INSTRUCTION_LIST(V)
#define SSE2_INSTRUCTION_LIST_SD(V)
#define SSSE3_INSTRUCTION_LIST(V)
#define AVX2_BROADCAST_LIST(V)
ZoneVector< RpoNumber > & result
#define DEFINE_LAZY_LEAKY_OBJECT_GETTER(T, FunctionName,...)
static V ReadUnalignedValue(Address p)
int SNPrintF(Vector< char > str, const char *format,...)
int VSNPrintF(Vector< char > str, const char *format, va_list args)
V8_INLINE const Operation & Get(const Graph &graph, OpIndex index)
constexpr Register kRootRegister
#define PRINTF_FORMAT(format_param, dots_param)
#define DCHECK_NOT_NULL(val)
#define DCHECK_NE(v1, v2)
#define DCHECK(condition)
#define DCHECK_EQ(v1, v2)
#define DCHECK_GT(v1, v2)
std::unique_ptr< ValueMirror > value
#define SSE_BINOP_INSTRUCTION_LIST(V)
#define SSE2_UNOP_INSTRUCTION_LIST(V)
#define SSE4_UNOP_INSTRUCTION_LIST(V)
#define SSE4_2_INSTRUCTION_LIST(V)