11 #if V8_TARGET_ARCH_IA32
30 OperandOrder op_order_;
34 static const ByteMnemonic two_operands_instr[] = {
35 {0x01,
"add", OPER_REG_OP_ORDER},
36 {0x03,
"add", REG_OPER_OP_ORDER},
37 {0x09,
"or", OPER_REG_OP_ORDER},
38 {0x0B,
"or", REG_OPER_OP_ORDER},
39 {0x1B,
"sbb", REG_OPER_OP_ORDER},
40 {0x21,
"and", OPER_REG_OP_ORDER},
41 {0x23,
"and", REG_OPER_OP_ORDER},
42 {0x29,
"sub", OPER_REG_OP_ORDER},
43 {0x2A,
"subb", REG_OPER_OP_ORDER},
44 {0x2B,
"sub", REG_OPER_OP_ORDER},
45 {0x31,
"xor", OPER_REG_OP_ORDER},
46 {0x33,
"xor", REG_OPER_OP_ORDER},
47 {0x38,
"cmpb", OPER_REG_OP_ORDER},
48 {0x3A,
"cmpb", REG_OPER_OP_ORDER},
49 {0x3B,
"cmp", REG_OPER_OP_ORDER},
50 {0x84,
"test_b", REG_OPER_OP_ORDER},
51 {0x85,
"test", REG_OPER_OP_ORDER},
52 {0x87,
"xchg", REG_OPER_OP_ORDER},
53 {0x8A,
"mov_b", REG_OPER_OP_ORDER},
54 {0x8B,
"mov", REG_OPER_OP_ORDER},
55 {0x8D,
"lea", REG_OPER_OP_ORDER},
56 {-1,
"", UNSET_OP_ORDER}
60 static const ByteMnemonic zero_operands_instr[] = {
61 {0xC3,
"ret", UNSET_OP_ORDER},
62 {0xC9,
"leave", UNSET_OP_ORDER},
63 {0x90,
"nop", UNSET_OP_ORDER},
64 {0xF4,
"hlt", UNSET_OP_ORDER},
65 {0xCC,
"int3", UNSET_OP_ORDER},
66 {0x60,
"pushad", UNSET_OP_ORDER},
67 {0x61,
"popad", UNSET_OP_ORDER},
68 {0x9C,
"pushfd", UNSET_OP_ORDER},
69 {0x9D,
"popfd", UNSET_OP_ORDER},
70 {0x9E,
"sahf", UNSET_OP_ORDER},
71 {0x99,
"cdq", UNSET_OP_ORDER},
72 {0x9B,
"fwait", UNSET_OP_ORDER},
73 {0xFC,
"cld", UNSET_OP_ORDER},
74 {0xAB,
"stos", UNSET_OP_ORDER},
75 {-1,
"", UNSET_OP_ORDER}
79 static const ByteMnemonic call_jump_instr[] = {
80 {0xE8,
"call", UNSET_OP_ORDER},
81 {0xE9,
"jmp", UNSET_OP_ORDER},
82 {-1,
"", UNSET_OP_ORDER}
86 static const ByteMnemonic short_immediate_instr[] = {
87 {0x05,
"add", UNSET_OP_ORDER},
88 {0x0D,
"or", UNSET_OP_ORDER},
89 {0x15,
"adc", UNSET_OP_ORDER},
90 {0x25,
"and", UNSET_OP_ORDER},
91 {0x2D,
"sub", UNSET_OP_ORDER},
92 {0x35,
"xor", UNSET_OP_ORDER},
93 {0x3D,
"cmp", UNSET_OP_ORDER},
94 {-1,
"", UNSET_OP_ORDER}
102 static ByteMnemonic byte_immediate_instr[] = {
103 {0x0c,
"or", UNSET_OP_ORDER},
104 {0x24,
"and", UNSET_OP_ORDER},
105 {0x34,
"xor", UNSET_OP_ORDER},
106 {0x3c,
"cmp", UNSET_OP_ORDER},
107 {-1,
"", UNSET_OP_ORDER}
111 static const char*
const jump_conditional_mnem[] = {
112 "jo",
"jno",
"jc",
"jnc",
113 "jz",
"jnz",
"jna",
"ja",
114 "js",
"jns",
"jpe",
"jpo",
115 "jl",
"jnl",
"jng",
"jg"
119 static const char*
const set_conditional_mnem[] = {
120 "seto",
"setno",
"setc",
"setnc",
121 "setz",
"setnz",
"setna",
"seta",
122 "sets",
"setns",
"setpe",
"setpo",
123 "setl",
"setnl",
"setng",
"setg"
127 static const char*
const conditional_move_mnem[] = {
128 "cmovo",
"cmovno",
"cmovc",
"cmovnc",
129 "cmovz",
"cmovnz",
"cmovna",
"cmova",
130 "cmovs",
"cmovns",
"cmovpe",
"cmovpo",
131 "cmovl",
"cmovnl",
"cmovng",
"cmovg"
135 enum InstructionType {
139 JUMP_CONDITIONAL_SHORT_INSTR,
143 SHORT_IMMEDIATE_INSTR,
148 struct InstructionDesc {
150 InstructionType type;
151 OperandOrder op_order_;
155 class InstructionTable {
158 const InstructionDesc& Get(
byte x)
const {
return instructions_[x]; }
159 static InstructionTable* get_instance() {
160 static InstructionTable table;
165 InstructionDesc instructions_[256];
168 void CopyTable(
const ByteMnemonic bm[], InstructionType type);
169 void SetTableRange(InstructionType type,
173 void AddJumpConditionalShort();
177 InstructionTable::InstructionTable() {
183 void InstructionTable::Clear() {
184 for (
int i = 0;
i < 256;
i++) {
185 instructions_[
i].mnem =
"";
186 instructions_[
i].type = NO_INSTR;
187 instructions_[
i].op_order_ = UNSET_OP_ORDER;
192 void InstructionTable::Init() {
193 CopyTable(two_operands_instr, TWO_OPERANDS_INSTR);
194 CopyTable(zero_operands_instr, ZERO_OPERANDS_INSTR);
195 CopyTable(call_jump_instr, CALL_JUMP_INSTR);
196 CopyTable(short_immediate_instr, SHORT_IMMEDIATE_INSTR);
197 CopyTable(byte_immediate_instr, BYTE_IMMEDIATE_INSTR);
198 AddJumpConditionalShort();
199 SetTableRange(REGISTER_INSTR, 0x40, 0x47,
"inc");
200 SetTableRange(REGISTER_INSTR, 0x48, 0x4F,
"dec");
201 SetTableRange(REGISTER_INSTR, 0x50, 0x57,
"push");
202 SetTableRange(REGISTER_INSTR, 0x58, 0x5F,
"pop");
203 SetTableRange(REGISTER_INSTR, 0x91, 0x97,
"xchg eax,");
204 SetTableRange(MOVE_REG_INSTR, 0xB8, 0xBF,
"mov");
208 void InstructionTable::CopyTable(
const ByteMnemonic bm[],
209 InstructionType type) {
210 for (
int i = 0; bm[
i].b >= 0;
i++) {
211 InstructionDesc*
id = &instructions_[bm[
i].b];
212 id->mnem = bm[
i].mnem;
213 id->op_order_ = bm[
i].op_order_;
220 void InstructionTable::SetTableRange(InstructionType type,
224 for (
byte b = start; b <= end; b++) {
225 InstructionDesc*
id = &instructions_[b];
233 void InstructionTable::AddJumpConditionalShort() {
234 for (
byte b = 0x70; b <= 0x7F; b++) {
235 InstructionDesc*
id = &instructions_[b];
237 id->mnem = jump_conditional_mnem[b & 0x0F];
238 id->type = JUMP_CONDITIONAL_SHORT_INSTR;
244 class DisassemblerIA32 {
246 DisassemblerIA32(
const NameConverter& converter,
247 bool abort_on_unimplemented =
true)
248 : converter_(converter),
249 instruction_table_(InstructionTable::get_instance()),
251 abort_on_unimplemented_(abort_on_unimplemented) {
252 tmp_buffer_[0] =
'\0';
255 virtual ~DisassemblerIA32() {}
262 const NameConverter& converter_;
263 InstructionTable* instruction_table_;
265 unsigned int tmp_buffer_pos_;
266 bool abort_on_unimplemented_;
280 enum ShiftOpcodeExtension {
291 const char* NameOfCPURegister(
int reg)
const {
292 return converter_.NameOfCPURegister(reg);
296 const char* NameOfByteCPURegister(
int reg)
const {
297 return converter_.NameOfByteCPURegister(reg);
301 const char* NameOfXMMRegister(
int reg)
const {
302 return converter_.NameOfXMMRegister(reg);
306 const char* NameOfAddress(
byte* addr)
const {
307 return converter_.NameOfAddress(addr);
312 static void get_modrm(
byte data,
int* mod,
int* regop,
int* rm) {
313 *mod = (data >> 6) & 3;
314 *regop = (data & 0x38) >> 3;
319 static void get_sib(
byte data,
int* scale,
int* index,
int* base) {
320 *scale = (data >> 6) & 3;
321 *index = (data >> 3) & 7;
325 typedef const char* (DisassemblerIA32::*RegisterNameMapping)(
int reg)
const;
327 int PrintRightOperandHelper(
byte* modrmp, RegisterNameMapping register_name);
328 int PrintRightOperand(
byte* modrmp);
329 int PrintRightByteOperand(
byte* modrmp);
330 int PrintRightXMMOperand(
byte* modrmp);
331 int PrintOperands(
const char* mnem, OperandOrder op_order,
byte* data);
332 int PrintImmediateOp(
byte* data);
333 int F7Instruction(
byte* data);
334 int D1D3C1Instruction(
byte* data);
335 int JumpShort(
byte* data);
336 int JumpConditional(
byte* data,
const char* comment);
337 int JumpConditionalShort(
byte* data,
const char* comment);
338 int SetCC(
byte* data);
339 int CMov(
byte* data);
340 int FPUInstruction(
byte* data);
341 int MemoryFPUInstruction(
int escape_opcode,
int regop,
byte* modrm_start);
342 int RegisterFPUInstruction(
int escape_opcode,
byte modrm_byte);
343 void AppendToBuffer(
const char* format, ...);
346 void UnimplementedInstruction() {
347 if (abort_on_unimplemented_) {
350 AppendToBuffer(
"'Unimplemented Instruction'");
356 void DisassemblerIA32::AppendToBuffer(
const char* format, ...) {
359 va_start(args, format);
362 tmp_buffer_pos_ += result;
365 int DisassemblerIA32::PrintRightOperandHelper(
367 RegisterNameMapping direct_register_name) {
369 get_modrm(*modrmp, &mod, ®op, &rm);
370 RegisterNameMapping register_name = (mod == 3) ? direct_register_name :
371 &DisassemblerIA32::NameOfCPURegister;
376 AppendToBuffer(
"[0x%x]", disp);
378 }
else if (rm ==
esp) {
379 byte sib = *(modrmp + 1);
380 int scale, index, base;
381 get_sib(sib, &scale, &index, &base);
382 if (index ==
esp && base ==
esp && scale == 0 ) {
383 AppendToBuffer(
"[%s]", (this->*register_name)(rm));
385 }
else if (base ==
ebp) {
387 AppendToBuffer(
"[%s*%d%s0x%x]",
388 (this->*register_name)(index),
390 disp < 0 ?
"-" :
"+",
391 disp < 0 ? -disp : disp);
393 }
else if (index !=
esp && base !=
ebp) {
395 AppendToBuffer(
"[%s+%s*%d]",
396 (this->*register_name)(base),
397 (this->*register_name)(index),
401 UnimplementedInstruction();
405 AppendToBuffer(
"[%s]", (this->*register_name)(rm));
412 byte sib = *(modrmp + 1);
413 int scale, index, base;
414 get_sib(sib, &scale, &index, &base);
415 int disp = mod == 2 ? *
reinterpret_cast<int32_t*
>(modrmp + 2)
416 : *
reinterpret_cast<int8_t*
>(modrmp + 2);
417 if (index == base && index == rm && scale == 0 ) {
418 AppendToBuffer(
"[%s%s0x%x]",
419 (this->*register_name)(rm),
420 disp < 0 ?
"-" :
"+",
421 disp < 0 ? -disp : disp);
423 AppendToBuffer(
"[%s+%s*%d%s0x%x]",
424 (this->*register_name)(base),
425 (this->*register_name)(index),
427 disp < 0 ?
"-" :
"+",
428 disp < 0 ? -disp : disp);
430 return mod == 2 ? 6 : 3;
433 int disp = mod == 2 ? *
reinterpret_cast<int32_t*
>(modrmp + 1)
434 : *
reinterpret_cast<int8_t*
>(modrmp + 1);
435 AppendToBuffer(
"[%s%s0x%x]",
436 (this->*register_name)(rm),
437 disp < 0 ?
"-" :
"+",
438 disp < 0 ? -disp : disp);
439 return mod == 2 ? 5 : 2;
443 AppendToBuffer(
"%s", (this->*register_name)(rm));
446 UnimplementedInstruction();
453 int DisassemblerIA32::PrintRightOperand(
byte* modrmp) {
454 return PrintRightOperandHelper(modrmp, &DisassemblerIA32::NameOfCPURegister);
458 int DisassemblerIA32::PrintRightByteOperand(
byte* modrmp) {
459 return PrintRightOperandHelper(modrmp,
460 &DisassemblerIA32::NameOfByteCPURegister);
464 int DisassemblerIA32::PrintRightXMMOperand(
byte* modrmp) {
465 return PrintRightOperandHelper(modrmp,
466 &DisassemblerIA32::NameOfXMMRegister);
472 int DisassemblerIA32::PrintOperands(
const char* mnem,
473 OperandOrder op_order,
477 get_modrm(modrm, &mod, ®op, &rm);
480 case REG_OPER_OP_ORDER: {
481 AppendToBuffer(
"%s %s,", mnem, NameOfCPURegister(regop));
482 advance = PrintRightOperand(data);
485 case OPER_REG_OP_ORDER: {
486 AppendToBuffer(
"%s ", mnem);
487 advance = PrintRightOperand(data);
488 AppendToBuffer(
",%s", NameOfCPURegister(regop));
501 int DisassemblerIA32::PrintImmediateOp(
byte* data) {
502 bool sign_extension_bit = (*data & 0x02) != 0;
503 byte modrm = *(data+1);
505 get_modrm(modrm, &mod, ®op, &rm);
506 const char* mnem =
"Imm???";
508 case 0: mnem =
"add";
break;
509 case 1: mnem =
"or";
break;
510 case 2: mnem =
"adc";
break;
511 case 4: mnem =
"and";
break;
512 case 5: mnem =
"sub";
break;
513 case 6: mnem =
"xor";
break;
514 case 7: mnem =
"cmp";
break;
515 default: UnimplementedInstruction();
517 AppendToBuffer(
"%s ", mnem);
518 int count = PrintRightOperand(data+1);
519 if (sign_extension_bit) {
520 AppendToBuffer(
",0x%x", *(data + 1 + count));
521 return 1 + count + 1 ;
523 AppendToBuffer(
",0x%x", *
reinterpret_cast<int32_t*
>(data + 1 + count));
524 return 1 + count + 4 ;
530 int DisassemblerIA32::F7Instruction(
byte* data) {
532 byte modrm = *++data;
534 get_modrm(modrm, &mod, ®op, &rm);
535 const char* mnem =
NULL;
559 UnimplementedInstruction();
561 AppendToBuffer(
"%s ", mnem);
562 int count = PrintRightOperand(data);
564 AppendToBuffer(
",0x%x", *
reinterpret_cast<int32_t*
>(data + count));
571 int DisassemblerIA32::D1D3C1Instruction(
byte* data) {
573 DCHECK(op == 0xD1 || op == 0xD3 || op == 0xC1);
574 byte modrm = *++data;
576 get_modrm(modrm, &mod, ®op, &rm);
578 const char* mnem =
NULL;
602 UnimplementedInstruction();
604 AppendToBuffer(
"%s ", mnem);
605 int count = PrintRightOperand(data);
608 }
else if (op == 0xC1) {
611 }
else if (op == 0xD3) {
615 AppendToBuffer(
",%d", imm8);
617 AppendToBuffer(
",cl");
624 int DisassemblerIA32::JumpShort(
byte* data) {
627 byte* dest = data +
static_cast<int8_t
>(b) + 2;
628 AppendToBuffer(
"jmp %s", NameOfAddress(dest));
634 int DisassemblerIA32::JumpConditional(
byte* data,
const char* comment) {
636 byte cond = *(data+1) & 0x0F;
637 byte* dest = data + *
reinterpret_cast<int32_t*
>(data+2) + 6;
638 const char* mnem = jump_conditional_mnem[cond];
639 AppendToBuffer(
"%s %s", mnem, NameOfAddress(dest));
640 if (comment !=
NULL) {
641 AppendToBuffer(
", %s", comment);
648 int DisassemblerIA32::JumpConditionalShort(
byte* data,
const char* comment) {
649 byte cond = *data & 0x0F;
651 byte* dest = data +
static_cast<int8_t
>(b) + 2;
652 const char* mnem = jump_conditional_mnem[cond];
653 AppendToBuffer(
"%s %s", mnem, NameOfAddress(dest));
654 if (comment !=
NULL) {
655 AppendToBuffer(
", %s", comment);
664 byte cond = *(data+1) & 0x0F;
665 const char* mnem = set_conditional_mnem[cond];
666 AppendToBuffer(
"%s ", mnem);
667 PrintRightByteOperand(data+2);
673 int DisassemblerIA32::CMov(
byte* data) {
675 byte cond = *(data + 1) & 0x0F;
676 const char* mnem = conditional_move_mnem[cond];
677 int op_size = PrintOperands(mnem, REG_OPER_OP_ORDER, data + 2);
683 int DisassemblerIA32::FPUInstruction(
byte* data) {
684 byte escape_opcode = *data;
686 byte modrm_byte = *(data+1);
688 if (modrm_byte >= 0xC0) {
689 return RegisterFPUInstruction(escape_opcode, modrm_byte);
691 return MemoryFPUInstruction(escape_opcode, modrm_byte, data+1);
695 int DisassemblerIA32::MemoryFPUInstruction(
int escape_opcode,
698 const char* mnem =
"?";
699 int regop = (modrm_byte >> 3) & 0x7;
700 switch (escape_opcode) {
701 case 0xD9:
switch (regop) {
702 case 0: mnem =
"fld_s";
break;
703 case 2: mnem =
"fst_s";
break;
704 case 3: mnem =
"fstp_s";
break;
705 case 7: mnem =
"fstcw";
break;
706 default: UnimplementedInstruction();
710 case 0xDB:
switch (regop) {
711 case 0: mnem =
"fild_s";
break;
712 case 1: mnem =
"fisttp_s";
break;
713 case 2: mnem =
"fist_s";
break;
714 case 3: mnem =
"fistp_s";
break;
715 default: UnimplementedInstruction();
719 case 0xDD:
switch (regop) {
720 case 0: mnem =
"fld_d";
break;
721 case 1: mnem =
"fisttp_d";
break;
722 case 2: mnem =
"fst_d";
break;
723 case 3: mnem =
"fstp_d";
break;
724 default: UnimplementedInstruction();
728 case 0xDF:
switch (regop) {
729 case 5: mnem =
"fild_d";
break;
730 case 7: mnem =
"fistp_d";
break;
731 default: UnimplementedInstruction();
735 default: UnimplementedInstruction();
737 AppendToBuffer(
"%s ", mnem);
738 int count = PrintRightOperand(modrm_start);
742 int DisassemblerIA32::RegisterFPUInstruction(
int escape_opcode,
744 bool has_register =
false;
745 const char* mnem =
"?";
747 switch (escape_opcode) {
750 switch (modrm_byte & 0xF8) {
751 case 0xC0: mnem =
"fadd_i";
break;
752 case 0xE0: mnem =
"fsub_i";
break;
753 case 0xC8: mnem =
"fmul_i";
break;
754 case 0xF0: mnem =
"fdiv_i";
break;
755 default: UnimplementedInstruction();
760 switch (modrm_byte & 0xF8) {
770 switch (modrm_byte) {
771 case 0xE0: mnem =
"fchs";
break;
772 case 0xE1: mnem =
"fabs";
break;
773 case 0xE4: mnem =
"ftst";
break;
774 case 0xE8: mnem =
"fld1";
break;
775 case 0xEB: mnem =
"fldpi";
break;
776 case 0xED: mnem =
"fldln2";
break;
777 case 0xEE: mnem =
"fldz";
break;
778 case 0xF0: mnem =
"f2xm1";
break;
779 case 0xF1: mnem =
"fyl2x";
break;
780 case 0xF4: mnem =
"fxtract";
break;
781 case 0xF5: mnem =
"fprem1";
break;
782 case 0xF7: mnem =
"fincstp";
break;
783 case 0xF8: mnem =
"fprem";
break;
784 case 0xFC: mnem =
"frndint";
break;
785 case 0xFD: mnem =
"fscale";
break;
786 case 0xFE: mnem =
"fsin";
break;
787 case 0xFF: mnem =
"fcos";
break;
788 default: UnimplementedInstruction();
794 if (modrm_byte == 0xE9) {
797 UnimplementedInstruction();
802 if ((modrm_byte & 0xF8) == 0xE8) {
805 }
else if (modrm_byte == 0xE2) {
807 }
else if (modrm_byte == 0xE3) {
810 UnimplementedInstruction();
816 switch (modrm_byte & 0xF8) {
817 case 0xC0: mnem =
"fadd";
break;
818 case 0xE8: mnem =
"fsub";
break;
819 case 0xC8: mnem =
"fmul";
break;
820 case 0xF8: mnem =
"fdiv";
break;
821 default: UnimplementedInstruction();
827 switch (modrm_byte & 0xF8) {
828 case 0xC0: mnem =
"ffree";
break;
829 case 0xD0: mnem =
"fst";
break;
830 case 0xD8: mnem =
"fstp";
break;
831 default: UnimplementedInstruction();
836 if (modrm_byte == 0xD9) {
840 switch (modrm_byte & 0xF8) {
841 case 0xC0: mnem =
"faddp";
break;
842 case 0xE8: mnem =
"fsubp";
break;
843 case 0xC8: mnem =
"fmulp";
break;
844 case 0xF8: mnem =
"fdivp";
break;
845 default: UnimplementedInstruction();
851 if (modrm_byte == 0xE0) {
853 }
else if ((modrm_byte & 0xF8) == 0xE8) {
859 default: UnimplementedInstruction();
863 AppendToBuffer(
"%s st%d", mnem, modrm_byte & 0x7);
865 AppendToBuffer(
"%s", mnem);
873 static const char* F0Mnem(
byte f0byte) {
875 case 0x18:
return "prefetch";
876 case 0xA2:
return "cpuid";
877 case 0xBE:
return "movsx_b";
878 case 0xBF:
return "movsx_w";
879 case 0xB6:
return "movzx_b";
880 case 0xB7:
return "movzx_w";
881 case 0xAF:
return "imul";
882 case 0xA5:
return "shld";
883 case 0xAD:
return "shrd";
884 case 0xAC:
return "shrd";
885 case 0xAB:
return "bts";
886 case 0xBD:
return "bsr";
887 default:
return NULL;
898 const char* branch_hint =
NULL;
900 if (*data == 0x3E ) {
901 branch_hint =
"predicted taken";
903 }
else if (*data == 0x2E ) {
904 branch_hint =
"predicted not taken";
907 bool processed =
true;
909 const InstructionDesc& idesc = instruction_table_->Get(*data);
910 switch (idesc.type) {
911 case ZERO_OPERANDS_INSTR:
912 AppendToBuffer(idesc.mnem);
916 case TWO_OPERANDS_INSTR:
918 data += PrintOperands(idesc.mnem, idesc.op_order_, data);
921 case JUMP_CONDITIONAL_SHORT_INSTR:
922 data += JumpConditionalShort(data, branch_hint);
926 AppendToBuffer(
"%s %s", idesc.mnem, NameOfCPURegister(*data & 0x07));
930 case MOVE_REG_INSTR: {
931 byte* addr =
reinterpret_cast<byte*
>(*
reinterpret_cast<int32_t*
>(data+1));
932 AppendToBuffer(
"mov %s,%s",
933 NameOfCPURegister(*data & 0x07),
934 NameOfAddress(addr));
939 case CALL_JUMP_INSTR: {
940 byte* addr = data + *
reinterpret_cast<int32_t*
>(data+1) + 5;
941 AppendToBuffer(
"%s %s", idesc.mnem, NameOfAddress(addr));
946 case SHORT_IMMEDIATE_INSTR: {
947 byte* addr =
reinterpret_cast<byte*
>(*
reinterpret_cast<int32_t*
>(data+1));
948 AppendToBuffer(
"%s eax,%s", idesc.mnem, NameOfAddress(addr));
953 case BYTE_IMMEDIATE_INSTR: {
954 AppendToBuffer(
"%s al,0x%x", idesc.mnem, data[1]);
970 AppendToBuffer(
"ret 0x%x", *
reinterpret_cast<uint16_t*
>(data+1));
976 data += PrintOperands(
"imul", REG_OPER_OP_ORDER, data);
977 AppendToBuffer(
",%d", *data);
983 data += PrintOperands(
"imul", REG_OPER_OP_ORDER, data);
984 AppendToBuffer(
",%d", *
reinterpret_cast<int32_t*
>(data));
992 get_modrm(*data, &mod, ®op, &rm);
994 AppendToBuffer(
"test_b ");
995 data += PrintRightByteOperand(data);
997 AppendToBuffer(
",0x%x", imm);
1000 UnimplementedInstruction();
1007 data += PrintImmediateOp(data);
1011 {
byte f0byte = data[1];
1012 const char* f0mnem = F0Mnem(f0byte);
1013 if (f0byte == 0x18) {
1016 get_modrm(*data, &mod, ®op, &rm);
1017 const char* suffix[] = {
"nta",
"1",
"2",
"3"};
1018 AppendToBuffer(
"%s%s ", f0mnem, suffix[regop & 0x03]);
1019 data += PrintRightOperand(data);
1020 }
else if (f0byte == 0x1F && data[2] == 0) {
1021 AppendToBuffer(
"nop");
1023 }
else if (f0byte == 0x1F && data[2] == 0x40 && data[3] == 0) {
1024 AppendToBuffer(
"nop");
1026 }
else if (f0byte == 0x1F && data[2] == 0x44 && data[3] == 0 &&
1028 AppendToBuffer(
"nop");
1030 }
else if (f0byte == 0x1F && data[2] == 0x80 && data[3] == 0 &&
1031 data[4] == 0 && data[5] == 0 && data[6] == 0) {
1032 AppendToBuffer(
"nop");
1034 }
else if (f0byte == 0x1F && data[2] == 0x84 && data[3] == 0 &&
1035 data[4] == 0 && data[5] == 0 && data[6] == 0 &&
1037 AppendToBuffer(
"nop");
1039 }
else if (f0byte == 0xA2 || f0byte == 0x31) {
1040 AppendToBuffer(
"%s", f0mnem);
1042 }
else if (f0byte == 0x28) {
1045 get_modrm(*data, &mod, ®op, &rm);
1046 AppendToBuffer(
"movaps %s,%s",
1047 NameOfXMMRegister(regop),
1048 NameOfXMMRegister(rm));
1050 }
else if (f0byte >= 0x53 && f0byte <= 0x5F) {
1051 const char*
const pseudo_op[] = {
1069 get_modrm(*data, &mod, ®op, &rm);
1070 AppendToBuffer(
"%s %s,",
1071 pseudo_op[f0byte - 0x53],
1072 NameOfXMMRegister(regop));
1073 data += PrintRightXMMOperand(data);
1074 }
else if (f0byte == 0x50) {
1077 get_modrm(*data, &mod, ®op, &rm);
1078 AppendToBuffer(
"movmskps %s,%s",
1079 NameOfCPURegister(regop),
1080 NameOfXMMRegister(rm));
1082 }
else if (f0byte== 0xC6) {
1086 get_modrm(*data, &mod, ®op, &rm);
1087 int8_t imm8 =
static_cast<int8_t
>(data[1]);
1088 AppendToBuffer(
"shufps %s,%s,%d",
1089 NameOfXMMRegister(rm),
1090 NameOfXMMRegister(regop),
1091 static_cast<int>(imm8));
1093 }
else if ((f0byte & 0xF0) == 0x80) {
1094 data += JumpConditional(data, branch_hint);
1095 }
else if (f0byte == 0xBE || f0byte == 0xBF || f0byte == 0xB6 ||
1096 f0byte == 0xB7 || f0byte == 0xAF) {
1098 data += PrintOperands(f0mnem, REG_OPER_OP_ORDER, data);
1099 }
else if ((f0byte & 0xF0) == 0x90) {
1100 data +=
SetCC(data);
1101 }
else if ((f0byte & 0xF0) == 0x40) {
1103 }
else if (f0byte == 0xAB || f0byte == 0xA5 || f0byte == 0xAD) {
1106 AppendToBuffer(
"%s ", f0mnem);
1108 get_modrm(*data, &mod, ®op, &rm);
1109 data += PrintRightOperand(data);
1110 if (f0byte == 0xAB) {
1111 AppendToBuffer(
",%s", NameOfCPURegister(regop));
1113 AppendToBuffer(
",%s,cl", NameOfCPURegister(regop));
1115 }
else if (f0byte == 0xBD) {
1118 get_modrm(*data, &mod, ®op, &rm);
1119 AppendToBuffer(
"%s %s,", f0mnem, NameOfCPURegister(regop));
1120 data += PrintRightOperand(data);
1122 UnimplementedInstruction();
1130 get_modrm(*data, &mod, ®op, &rm);
1132 AppendToBuffer(
"pop ");
1133 data += PrintRightOperand(data);
1141 get_modrm(*data, &mod, ®op, &rm);
1142 const char* mnem =
NULL;
1144 case esi: mnem =
"push";
break;
1145 case eax: mnem =
"inc";
break;
1146 case ecx: mnem =
"dec";
break;
1147 case edx: mnem =
"call";
break;
1148 case esp: mnem =
"jmp";
break;
1149 default: mnem =
"???";
1151 AppendToBuffer(
"%s ", mnem);
1152 data += PrintRightOperand(data);
1158 {
bool is_byte = *data == 0xC6;
1161 AppendToBuffer(
"%s ",
"mov_b");
1162 data += PrintRightByteOperand(data);
1164 AppendToBuffer(
",0x%x", imm);
1167 AppendToBuffer(
"%s ",
"mov");
1168 data += PrintRightOperand(data);
1170 AppendToBuffer(
",0x%x", imm);
1179 get_modrm(*data, &mod, ®op, &rm);
1180 const char* mnem =
NULL;
1182 case 5: mnem =
"subb";
break;
1183 case 7: mnem =
"cmpb";
break;
1184 default: UnimplementedInstruction();
1186 AppendToBuffer(
"%s ", mnem);
1187 data += PrintRightByteOperand(data);
1189 AppendToBuffer(
",0x%x", imm);
1196 {
bool is_byte = *data == 0x88;
1199 get_modrm(*data, &mod, ®op, &rm);
1201 AppendToBuffer(
"%s ",
"mov_b");
1202 data += PrintRightByteOperand(data);
1203 AppendToBuffer(
",%s", NameOfByteCPURegister(regop));
1205 AppendToBuffer(
"%s ",
"mov");
1206 data += PrintRightOperand(data);
1207 AppendToBuffer(
",%s", NameOfCPURegister(regop));
1213 while (*data == 0x66) data++;
1214 if (*data == 0xf && data[1] == 0x1f) {
1215 AppendToBuffer(
"nop");
1216 }
else if (*data == 0x90) {
1217 AppendToBuffer(
"nop");
1218 }
else if (*data == 0x8B) {
1220 data += PrintOperands(
"mov_w", REG_OPER_OP_ORDER, data);
1221 }
else if (*data == 0x89) {
1224 get_modrm(*data, &mod, ®op, &rm);
1225 AppendToBuffer(
"mov_w ");
1226 data += PrintRightOperand(data);
1227 AppendToBuffer(
",%s", NameOfCPURegister(regop));
1228 }
else if (*data == 0xC7) {
1230 AppendToBuffer(
"%s ",
"mov_w");
1231 data += PrintRightOperand(data);
1232 int imm = *
reinterpret_cast<int16_t*
>(data);
1233 AppendToBuffer(
",0x%x", imm);
1235 }
else if (*data == 0x0F) {
1237 if (*data == 0x38) {
1239 if (*data == 0x17) {
1242 get_modrm(*data, &mod, ®op, &rm);
1243 AppendToBuffer(
"ptest %s,%s",
1244 NameOfXMMRegister(regop),
1245 NameOfXMMRegister(rm));
1247 }
else if (*data == 0x2A) {
1251 get_modrm(*data, &mod, ®op, &rm);
1252 AppendToBuffer(
"movntdqa %s,", NameOfXMMRegister(regop));
1253 data += PrintRightOperand(data);
1255 UnimplementedInstruction();
1257 }
else if (*data == 0x3A) {
1259 if (*data == 0x0B) {
1262 get_modrm(*data, &mod, ®op, &rm);
1263 int8_t imm8 =
static_cast<int8_t
>(data[1]);
1264 AppendToBuffer(
"roundsd %s,%s,%d",
1265 NameOfXMMRegister(regop),
1266 NameOfXMMRegister(rm),
1267 static_cast<int>(imm8));
1269 }
else if (*data == 0x16) {
1272 get_modrm(*data, &mod, ®op, &rm);
1273 int8_t imm8 =
static_cast<int8_t
>(data[1]);
1274 AppendToBuffer(
"pextrd %s,%s,%d",
1275 NameOfCPURegister(regop),
1276 NameOfXMMRegister(rm),
1277 static_cast<int>(imm8));
1279 }
else if (*data == 0x17) {
1282 get_modrm(*data, &mod, ®op, &rm);
1283 int8_t imm8 =
static_cast<int8_t
>(data[1]);
1284 AppendToBuffer(
"extractps %s,%s,%d",
1285 NameOfCPURegister(rm),
1286 NameOfXMMRegister(regop),
1287 static_cast<int>(imm8));
1289 }
else if (*data == 0x22) {
1292 get_modrm(*data, &mod, ®op, &rm);
1293 int8_t imm8 =
static_cast<int8_t
>(data[1]);
1294 AppendToBuffer(
"pinsrd %s,%s,%d",
1295 NameOfXMMRegister(regop),
1296 NameOfCPURegister(rm),
1297 static_cast<int>(imm8));
1300 UnimplementedInstruction();
1302 }
else if (*data == 0x2E || *data == 0x2F) {
1303 const char* mnem = (*data == 0x2E) ?
"ucomisd" :
"comisd";
1306 get_modrm(*data, &mod, ®op, &rm);
1308 AppendToBuffer(
"%s %s,%s", mnem,
1309 NameOfXMMRegister(regop),
1310 NameOfXMMRegister(rm));
1313 AppendToBuffer(
"%s %s,", mnem, NameOfXMMRegister(regop));
1314 data += PrintRightOperand(data);
1316 }
else if (*data == 0x50) {
1319 get_modrm(*data, &mod, ®op, &rm);
1320 AppendToBuffer(
"movmskpd %s,%s",
1321 NameOfCPURegister(regop),
1322 NameOfXMMRegister(rm));
1324 }
else if (*data == 0x54) {
1327 get_modrm(*data, &mod, ®op, &rm);
1328 AppendToBuffer(
"andpd %s,%s",
1329 NameOfXMMRegister(regop),
1330 NameOfXMMRegister(rm));
1332 }
else if (*data == 0x56) {
1335 get_modrm(*data, &mod, ®op, &rm);
1336 AppendToBuffer(
"orpd %s,%s",
1337 NameOfXMMRegister(regop),
1338 NameOfXMMRegister(rm));
1340 }
else if (*data == 0x57) {
1343 get_modrm(*data, &mod, ®op, &rm);
1344 AppendToBuffer(
"xorpd %s,%s",
1345 NameOfXMMRegister(regop),
1346 NameOfXMMRegister(rm));
1348 }
else if (*data == 0x6E) {
1351 get_modrm(*data, &mod, ®op, &rm);
1352 AppendToBuffer(
"movd %s,", NameOfXMMRegister(regop));
1353 data += PrintRightOperand(data);
1354 }
else if (*data == 0x6F) {
1357 get_modrm(*data, &mod, ®op, &rm);
1358 AppendToBuffer(
"movdqa %s,", NameOfXMMRegister(regop));
1359 data += PrintRightXMMOperand(data);
1360 }
else if (*data == 0x70) {
1363 get_modrm(*data, &mod, ®op, &rm);
1364 int8_t imm8 =
static_cast<int8_t
>(data[1]);
1365 AppendToBuffer(
"pshufd %s,%s,%d",
1366 NameOfXMMRegister(regop),
1367 NameOfXMMRegister(rm),
1368 static_cast<int>(imm8));
1370 }
else if (*data == 0x76) {
1373 get_modrm(*data, &mod, ®op, &rm);
1374 AppendToBuffer(
"pcmpeqd %s,%s",
1375 NameOfXMMRegister(regop),
1376 NameOfXMMRegister(rm));
1378 }
else if (*data == 0x90) {
1380 AppendToBuffer(
"nop");
1381 }
else if (*data == 0xF3) {
1384 get_modrm(*data, &mod, ®op, &rm);
1385 AppendToBuffer(
"psllq %s,%s",
1386 NameOfXMMRegister(regop),
1387 NameOfXMMRegister(rm));
1389 }
else if (*data == 0x73) {
1392 get_modrm(*data, &mod, ®op, &rm);
1393 int8_t imm8 =
static_cast<int8_t
>(data[1]);
1395 AppendToBuffer(
"%s %s,%d",
1396 (regop ==
esi) ?
"psllq" :
"psrlq",
1397 NameOfXMMRegister(rm),
1398 static_cast<int>(imm8));
1400 }
else if (*data == 0xD3) {
1403 get_modrm(*data, &mod, ®op, &rm);
1404 AppendToBuffer(
"psrlq %s,%s",
1405 NameOfXMMRegister(regop),
1406 NameOfXMMRegister(rm));
1408 }
else if (*data == 0x7F) {
1409 AppendToBuffer(
"movdqa ");
1412 get_modrm(*data, &mod, ®op, &rm);
1413 data += PrintRightXMMOperand(data);
1414 AppendToBuffer(
",%s", NameOfXMMRegister(regop));
1415 }
else if (*data == 0x7E) {
1418 get_modrm(*data, &mod, ®op, &rm);
1419 AppendToBuffer(
"movd ");
1420 data += PrintRightOperand(data);
1421 AppendToBuffer(
",%s", NameOfXMMRegister(regop));
1422 }
else if (*data == 0xDB) {
1425 get_modrm(*data, &mod, ®op, &rm);
1426 AppendToBuffer(
"pand %s,%s",
1427 NameOfXMMRegister(regop),
1428 NameOfXMMRegister(rm));
1430 }
else if (*data == 0xE7) {
1433 get_modrm(*data, &mod, ®op, &rm);
1435 AppendToBuffer(
"movntdq ");
1436 data += PrintRightOperand(data);
1437 AppendToBuffer(
",%s", NameOfXMMRegister(regop));
1439 UnimplementedInstruction();
1441 }
else if (*data == 0xEF) {
1444 get_modrm(*data, &mod, ®op, &rm);
1445 AppendToBuffer(
"pxor %s,%s",
1446 NameOfXMMRegister(regop),
1447 NameOfXMMRegister(rm));
1449 }
else if (*data == 0xEB) {
1452 get_modrm(*data, &mod, ®op, &rm);
1453 AppendToBuffer(
"por %s,%s",
1454 NameOfXMMRegister(regop),
1455 NameOfXMMRegister(rm));
1458 UnimplementedInstruction();
1461 UnimplementedInstruction();
1468 get_modrm(*data, &mod, ®op, &rm);
1470 AppendToBuffer(
"dec_b ");
1471 data += PrintRightOperand(data);
1473 UnimplementedInstruction();
1479 AppendToBuffer(
"push 0x%x", *
reinterpret_cast<int32_t*
>(data+1));
1484 AppendToBuffer(
"push 0x%x", *
reinterpret_cast<int8_t*
>(data + 1));
1489 AppendToBuffer(
"test al,0x%x", *
reinterpret_cast<uint8_t*
>(data+1));
1494 AppendToBuffer(
"test eax,0x%x", *
reinterpret_cast<int32_t*
>(data+1));
1501 data += D1D3C1Instruction(data);
1512 data += FPUInstruction(data);
1516 data += JumpShort(data);
1520 if (*(data+1) == 0x0F) {
1521 byte b2 = *(data+2);
1523 AppendToBuffer(
"movsd ");
1526 get_modrm(*data, &mod, ®op, &rm);
1527 data += PrintRightXMMOperand(data);
1528 AppendToBuffer(
",%s", NameOfXMMRegister(regop));
1529 }
else if (b2 == 0x10) {
1532 get_modrm(*data, &mod, ®op, &rm);
1533 AppendToBuffer(
"movsd %s,", NameOfXMMRegister(regop));
1534 data += PrintRightXMMOperand(data);
1535 }
else if (b2 == 0x5A) {
1538 get_modrm(*data, &mod, ®op, &rm);
1539 AppendToBuffer(
"cvtsd2ss %s,", NameOfXMMRegister(regop));
1540 data += PrintRightXMMOperand(data);
1542 const char* mnem =
"?";
1544 case 0x2A: mnem =
"cvtsi2sd";
break;
1545 case 0x2C: mnem =
"cvttsd2si";
break;
1546 case 0x2D: mnem =
"cvtsd2si";
break;
1547 case 0x51: mnem =
"sqrtsd";
break;
1548 case 0x58: mnem =
"addsd";
break;
1549 case 0x59: mnem =
"mulsd";
break;
1550 case 0x5C: mnem =
"subsd";
break;
1551 case 0x5E: mnem =
"divsd";
break;
1555 get_modrm(*data, &mod, ®op, &rm);
1557 AppendToBuffer(
"%s %s,", mnem, NameOfXMMRegister(regop));
1558 data += PrintRightOperand(data);
1559 }
else if (b2 == 0x2C || b2 == 0x2D) {
1560 AppendToBuffer(
"%s %s,", mnem, NameOfCPURegister(regop));
1561 data += PrintRightXMMOperand(data);
1562 }
else if (b2 == 0xC2) {
1564 const char*
const pseudo_op[] = {
1574 AppendToBuffer(
"%s %s,%s",
1576 NameOfXMMRegister(regop),
1577 NameOfXMMRegister(rm));
1580 AppendToBuffer(
"%s %s,", mnem, NameOfXMMRegister(regop));
1581 data += PrintRightXMMOperand(data);
1585 UnimplementedInstruction();
1590 if (*(data+1) == 0x0F) {
1591 byte b2 = *(data+2);
1593 AppendToBuffer(
"movss ");
1596 get_modrm(*data, &mod, ®op, &rm);
1597 data += PrintRightXMMOperand(data);
1598 AppendToBuffer(
",%s", NameOfXMMRegister(regop));
1599 }
else if (b2 == 0x10) {
1602 get_modrm(*data, &mod, ®op, &rm);
1603 AppendToBuffer(
"movss %s,", NameOfXMMRegister(regop));
1604 data += PrintRightXMMOperand(data);
1605 }
else if (b2 == 0x2C) {
1608 get_modrm(*data, &mod, ®op, &rm);
1609 AppendToBuffer(
"cvttss2si %s,", NameOfCPURegister(regop));
1610 data += PrintRightXMMOperand(data);
1611 }
else if (b2 == 0x5A) {
1614 get_modrm(*data, &mod, ®op, &rm);
1615 AppendToBuffer(
"cvtss2sd %s,", NameOfXMMRegister(regop));
1616 data += PrintRightXMMOperand(data);
1617 }
else if (b2 == 0x6F) {
1620 get_modrm(*data, &mod, ®op, &rm);
1621 AppendToBuffer(
"movdqu %s,", NameOfXMMRegister(regop));
1622 data += PrintRightXMMOperand(data);
1623 }
else if (b2 == 0x7F) {
1624 AppendToBuffer(
"movdqu ");
1627 get_modrm(*data, &mod, ®op, &rm);
1628 data += PrintRightXMMOperand(data);
1629 AppendToBuffer(
",%s", NameOfXMMRegister(regop));
1631 UnimplementedInstruction();
1633 }
else if (*(data+1) == 0xA5) {
1635 AppendToBuffer(
"rep_movs");
1636 }
else if (*(data+1) == 0xAB) {
1638 AppendToBuffer(
"rep_stos");
1640 UnimplementedInstruction();
1645 data += F7Instruction(data);
1649 UnimplementedInstruction();
1653 if (tmp_buffer_pos_ <
sizeof tmp_buffer_) {
1654 tmp_buffer_[tmp_buffer_pos_] =
'\0';
1657 int instr_len = data - instr;
1658 if (instr_len == 0) {
1659 printf(
"%02x", *data);
1665 for (
byte* bp = instr; bp < data; bp++) {
1670 for (
int i = 6 - instr_len;
i >= 0;
i--) {
1676 tmp_buffer_.
start());
1684 static const char* cpu_regs[8] = {
1685 "eax",
"ecx",
"edx",
"ebx",
"esp",
"ebp",
"esi",
"edi"
1689 static const char* byte_cpu_regs[8] = {
1690 "al",
"cl",
"dl",
"bl",
"ah",
"ch",
"dh",
"bh"
1694 static const char* xmm_regs[8] = {
1695 "xmm0",
"xmm1",
"xmm2",
"xmm3",
"xmm4",
"xmm5",
"xmm6",
"xmm7"
1711 if (0 <= reg && reg < 8)
return cpu_regs[reg];
1717 if (0 <= reg && reg < 8)
return byte_cpu_regs[reg];
1723 if (0 <= reg && reg < 8)
return xmm_regs[reg];
1738 : converter_(converter) {}
1741 Disassembler::~Disassembler() {}
1745 byte* instruction) {
1746 DisassemblerIA32 d(converter_,
false );
1747 return d.InstructionDecode(buffer, instruction);
1752 int Disassembler::ConstantPoolSizeAt(
byte* instruction) {
return -1; }
1755 void Disassembler::Disassemble(FILE* f,
byte* begin,
byte* end) {
1756 NameConverter converter;
1757 Disassembler d(converter);
1758 for (
byte*
pc = begin;
pc < end;) {
1762 pc += d.InstructionDecode(buffer,
pc);
1763 fprintf(f,
"%p", prev_pc);
1766 for (
byte* bp = prev_pc; bp <
pc; bp++) {
1767 fprintf(f,
"%02x", *bp);
1769 for (
int i = 6 - (
pc - prev_pc);
i >= 0;
i--) {
1772 fprintf(f,
" %s\n", buffer.
start());
Disassembler(const NameConverter &converter)
v8::internal::EmbeddedVector< char, 128 > tmp_buffer_
virtual const char * NameInCode(byte *addr) const
virtual const char * NameOfByteCPURegister(int reg) const
virtual const char * NameOfXMMRegister(int reg) const
virtual const char * NameOfAddress(byte *addr) const
virtual const char * NameOfCPURegister(int reg) const
virtual const char * NameOfConstant(byte *addr) const
enable harmony numeric enable harmony object literal extensions Optimize object Array DOM strings and string trace pretenuring decisions of HAllocate instructions Enables optimizations which favor memory size over execution speed maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining trace the tracking of allocation sites deoptimize every n garbage collections perform array bounds checks elimination analyze liveness of environment slots and zap dead values flushes the cache of optimized code for closures on every GC allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms do not emit check maps for constant values that have a leaf deoptimize the optimized code if the layout of the maps changes enable context specialization in TurboFan execution budget before interrupt is triggered max percentage of megamorphic generic ICs to allow optimization enable use of SAHF instruction if enable use of VFP3 instructions if available enable use of NEON instructions if enable use of SDIV and UDIV instructions if enable use of MLS instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of d16 d31 registers on ARM this requires VFP3 force all emitted branches to be in long enable alignment of csp to bytes on platforms which prefer the register to always be NULL
#define DCHECK(condition)
#define DCHECK_EQ(v1, v2)
int SNPrintF(Vector< char > str, const char *format,...)
int VSNPrintF(Vector< char > str, const char *format, va_list args)