11 #if V8_TARGET_ARCH_X87
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 DisassemblerX87 {
246 DisassemblerX87(
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 ~DisassemblerX87() {}
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* (DisassemblerX87::*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 DisassemblerX87::AppendToBuffer(
const char* format, ...) {
359 va_start(args, format);
362 tmp_buffer_pos_ += result;
365 int DisassemblerX87::PrintRightOperandHelper(
367 RegisterNameMapping direct_register_name) {
369 get_modrm(*modrmp, &mod, ®op, &rm);
370 RegisterNameMapping register_name = (mod == 3) ? direct_register_name :
371 &DisassemblerX87::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 DisassemblerX87::PrintRightOperand(
byte* modrmp) {
454 return PrintRightOperandHelper(modrmp, &DisassemblerX87::NameOfCPURegister);
458 int DisassemblerX87::PrintRightByteOperand(
byte* modrmp) {
459 return PrintRightOperandHelper(modrmp,
460 &DisassemblerX87::NameOfByteCPURegister);
464 int DisassemblerX87::PrintRightXMMOperand(
byte* modrmp) {
465 return PrintRightOperandHelper(modrmp,
466 &DisassemblerX87::NameOfXMMRegister);
472 int DisassemblerX87::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 DisassemblerX87::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 DisassemblerX87::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 DisassemblerX87::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 DisassemblerX87::JumpShort(
byte* data) {
627 byte* dest = data +
static_cast<int8_t
>(b) + 2;
628 AppendToBuffer(
"jmp %s", NameOfAddress(dest));
634 int DisassemblerX87::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 DisassemblerX87::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 DisassemblerX87::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 DisassemblerX87::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 DisassemblerX87::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;
711 default: UnimplementedInstruction();
715 case 0xDB:
switch (regop) {
716 case 0: mnem =
"fild_s";
break;
717 case 1: mnem =
"fisttp_s";
break;
718 case 2: mnem =
"fist_s";
break;
719 case 3: mnem =
"fistp_s";
break;
720 default: UnimplementedInstruction();
730 UnimplementedInstruction();
734 case 0xDD:
switch (regop) {
735 case 0: mnem =
"fld_d";
break;
736 case 1: mnem =
"fisttp_d";
break;
737 case 2: mnem =
"fst_d";
break;
738 case 3: mnem =
"fstp_d";
break;
745 default: UnimplementedInstruction();
749 case 0xDF:
switch (regop) {
750 case 5: mnem =
"fild_d";
break;
751 case 7: mnem =
"fistp_d";
break;
752 default: UnimplementedInstruction();
756 default: UnimplementedInstruction();
758 AppendToBuffer(
"%s ", mnem);
759 int count = PrintRightOperand(modrm_start);
763 int DisassemblerX87::RegisterFPUInstruction(
int escape_opcode,
765 bool has_register =
false;
766 const char* mnem =
"?";
768 switch (escape_opcode) {
771 switch (modrm_byte & 0xF8) {
772 case 0xC0: mnem =
"fadd_i";
break;
773 case 0xE0: mnem =
"fsub_i";
break;
774 case 0xC8: mnem =
"fmul_i";
break;
775 case 0xF0: mnem =
"fdiv_i";
break;
776 default: UnimplementedInstruction();
781 switch (modrm_byte & 0xF8) {
791 switch (modrm_byte) {
792 case 0xE0: mnem =
"fchs";
break;
793 case 0xE1: mnem =
"fabs";
break;
794 case 0xE4: mnem =
"ftst";
break;
795 case 0xE8: mnem =
"fld1";
break;
796 case 0xEB: mnem =
"fldpi";
break;
797 case 0xED: mnem =
"fldln2";
break;
798 case 0xEE: mnem =
"fldz";
break;
799 case 0xF0: mnem =
"f2xm1";
break;
800 case 0xF1: mnem =
"fyl2x";
break;
801 case 0xF4: mnem =
"fxtract";
break;
802 case 0xF5: mnem =
"fprem1";
break;
803 case 0xF7: mnem =
"fincstp";
break;
804 case 0xF8: mnem =
"fprem";
break;
805 case 0xFC: mnem =
"frndint";
break;
806 case 0xFD: mnem =
"fscale";
break;
807 case 0xFE: mnem =
"fsin";
break;
808 case 0xFF: mnem =
"fcos";
break;
809 default: UnimplementedInstruction();
815 if (modrm_byte == 0xE9) {
818 UnimplementedInstruction();
823 if ((modrm_byte & 0xF8) == 0xE8) {
826 }
else if (modrm_byte == 0xE2) {
828 }
else if (modrm_byte == 0xE3) {
831 UnimplementedInstruction();
837 switch (modrm_byte & 0xF8) {
838 case 0xC0: mnem =
"fadd";
break;
839 case 0xE8: mnem =
"fsub";
break;
840 case 0xC8: mnem =
"fmul";
break;
841 case 0xF8: mnem =
"fdiv";
break;
842 default: UnimplementedInstruction();
848 switch (modrm_byte & 0xF8) {
849 case 0xC0: mnem =
"ffree";
break;
850 case 0xD0: mnem =
"fst";
break;
851 case 0xD8: mnem =
"fstp";
break;
852 default: UnimplementedInstruction();
857 if (modrm_byte == 0xD9) {
861 switch (modrm_byte & 0xF8) {
862 case 0xC0: mnem =
"faddp";
break;
863 case 0xE8: mnem =
"fsubp";
break;
864 case 0xC8: mnem =
"fmulp";
break;
865 case 0xF8: mnem =
"fdivp";
break;
866 default: UnimplementedInstruction();
872 if (modrm_byte == 0xE0) {
874 }
else if ((modrm_byte & 0xF8) == 0xE8) {
880 default: UnimplementedInstruction();
884 AppendToBuffer(
"%s st%d", mnem, modrm_byte & 0x7);
886 AppendToBuffer(
"%s", mnem);
894 static const char* F0Mnem(
byte f0byte) {
896 case 0x18:
return "prefetch";
897 case 0xA2:
return "cpuid";
898 case 0xBE:
return "movsx_b";
899 case 0xBF:
return "movsx_w";
900 case 0xB6:
return "movzx_b";
901 case 0xB7:
return "movzx_w";
902 case 0xAF:
return "imul";
903 case 0xA5:
return "shld";
904 case 0xAD:
return "shrd";
905 case 0xAC:
return "shrd";
906 case 0xAB:
return "bts";
907 case 0xBD:
return "bsr";
908 default:
return NULL;
919 const char* branch_hint =
NULL;
921 if (*data == 0x3E ) {
922 branch_hint =
"predicted taken";
924 }
else if (*data == 0x2E ) {
925 branch_hint =
"predicted not taken";
928 bool processed =
true;
930 const InstructionDesc& idesc = instruction_table_->Get(*data);
931 switch (idesc.type) {
932 case ZERO_OPERANDS_INSTR:
933 AppendToBuffer(idesc.mnem);
937 case TWO_OPERANDS_INSTR:
939 data += PrintOperands(idesc.mnem, idesc.op_order_, data);
942 case JUMP_CONDITIONAL_SHORT_INSTR:
943 data += JumpConditionalShort(data, branch_hint);
947 AppendToBuffer(
"%s %s", idesc.mnem, NameOfCPURegister(*data & 0x07));
951 case MOVE_REG_INSTR: {
952 byte* addr =
reinterpret_cast<byte*
>(*
reinterpret_cast<int32_t*
>(data+1));
953 AppendToBuffer(
"mov %s,%s",
954 NameOfCPURegister(*data & 0x07),
955 NameOfAddress(addr));
960 case CALL_JUMP_INSTR: {
961 byte* addr = data + *
reinterpret_cast<int32_t*
>(data+1) + 5;
962 AppendToBuffer(
"%s %s", idesc.mnem, NameOfAddress(addr));
967 case SHORT_IMMEDIATE_INSTR: {
968 byte* addr =
reinterpret_cast<byte*
>(*
reinterpret_cast<int32_t*
>(data+1));
969 AppendToBuffer(
"%s eax,%s", idesc.mnem, NameOfAddress(addr));
974 case BYTE_IMMEDIATE_INSTR: {
975 AppendToBuffer(
"%s al,0x%x", idesc.mnem, data[1]);
991 AppendToBuffer(
"ret 0x%x", *
reinterpret_cast<uint16_t*
>(data+1));
997 data += PrintOperands(
"imul", REG_OPER_OP_ORDER, data);
998 AppendToBuffer(
",%d", *data);
1004 data += PrintOperands(
"imul", REG_OPER_OP_ORDER, data);
1005 AppendToBuffer(
",%d", *
reinterpret_cast<int32_t*
>(data));
1013 get_modrm(*data, &mod, ®op, &rm);
1015 AppendToBuffer(
"test_b ");
1016 data += PrintRightByteOperand(data);
1018 AppendToBuffer(
",0x%x", imm);
1021 UnimplementedInstruction();
1028 data += PrintImmediateOp(data);
1032 {
byte f0byte = data[1];
1033 const char* f0mnem = F0Mnem(f0byte);
1034 if (f0byte == 0x18) {
1037 get_modrm(*data, &mod, ®op, &rm);
1038 const char* suffix[] = {
"nta",
"1",
"2",
"3"};
1039 AppendToBuffer(
"%s%s ", f0mnem, suffix[regop & 0x03]);
1040 data += PrintRightOperand(data);
1041 }
else if (f0byte == 0x1F && data[2] == 0) {
1042 AppendToBuffer(
"nop");
1044 }
else if (f0byte == 0x1F && data[2] == 0x40 && data[3] == 0) {
1045 AppendToBuffer(
"nop");
1047 }
else if (f0byte == 0x1F && data[2] == 0x44 && data[3] == 0 &&
1049 AppendToBuffer(
"nop");
1051 }
else if (f0byte == 0x1F && data[2] == 0x80 && data[3] == 0 &&
1052 data[4] == 0 && data[5] == 0 && data[6] == 0) {
1053 AppendToBuffer(
"nop");
1055 }
else if (f0byte == 0x1F && data[2] == 0x84 && data[3] == 0 &&
1056 data[4] == 0 && data[5] == 0 && data[6] == 0 &&
1058 AppendToBuffer(
"nop");
1060 }
else if (f0byte == 0xA2 || f0byte == 0x31) {
1061 AppendToBuffer(
"%s", f0mnem);
1063 }
else if (f0byte == 0x28) {
1066 get_modrm(*data, &mod, ®op, &rm);
1067 AppendToBuffer(
"movaps %s,%s",
1068 NameOfXMMRegister(regop),
1069 NameOfXMMRegister(rm));
1071 }
else if (f0byte >= 0x53 && f0byte <= 0x5F) {
1072 const char*
const pseudo_op[] = {
1090 get_modrm(*data, &mod, ®op, &rm);
1091 AppendToBuffer(
"%s %s,",
1092 pseudo_op[f0byte - 0x53],
1093 NameOfXMMRegister(regop));
1094 data += PrintRightXMMOperand(data);
1095 }
else if (f0byte == 0x50) {
1098 get_modrm(*data, &mod, ®op, &rm);
1099 AppendToBuffer(
"movmskps %s,%s",
1100 NameOfCPURegister(regop),
1101 NameOfXMMRegister(rm));
1103 }
else if (f0byte== 0xC6) {
1107 get_modrm(*data, &mod, ®op, &rm);
1108 int8_t imm8 =
static_cast<int8_t
>(data[1]);
1109 AppendToBuffer(
"shufps %s,%s,%d",
1110 NameOfXMMRegister(rm),
1111 NameOfXMMRegister(regop),
1112 static_cast<int>(imm8));
1114 }
else if ((f0byte & 0xF0) == 0x80) {
1115 data += JumpConditional(data, branch_hint);
1116 }
else if (f0byte == 0xBE || f0byte == 0xBF || f0byte == 0xB6 ||
1117 f0byte == 0xB7 || f0byte == 0xAF) {
1119 data += PrintOperands(f0mnem, REG_OPER_OP_ORDER, data);
1120 }
else if ((f0byte & 0xF0) == 0x90) {
1121 data +=
SetCC(data);
1122 }
else if ((f0byte & 0xF0) == 0x40) {
1124 }
else if (f0byte == 0xAB || f0byte == 0xA5 || f0byte == 0xAD) {
1127 AppendToBuffer(
"%s ", f0mnem);
1129 get_modrm(*data, &mod, ®op, &rm);
1130 data += PrintRightOperand(data);
1131 if (f0byte == 0xAB) {
1132 AppendToBuffer(
",%s", NameOfCPURegister(regop));
1134 AppendToBuffer(
",%s,cl", NameOfCPURegister(regop));
1136 }
else if (f0byte == 0xBD) {
1139 get_modrm(*data, &mod, ®op, &rm);
1140 AppendToBuffer(
"%s %s,", f0mnem, NameOfCPURegister(regop));
1141 data += PrintRightOperand(data);
1143 UnimplementedInstruction();
1151 get_modrm(*data, &mod, ®op, &rm);
1153 AppendToBuffer(
"pop ");
1154 data += PrintRightOperand(data);
1162 get_modrm(*data, &mod, ®op, &rm);
1163 const char* mnem =
NULL;
1165 case esi: mnem =
"push";
break;
1166 case eax: mnem =
"inc";
break;
1167 case ecx: mnem =
"dec";
break;
1168 case edx: mnem =
"call";
break;
1169 case esp: mnem =
"jmp";
break;
1170 default: mnem =
"???";
1172 AppendToBuffer(
"%s ", mnem);
1173 data += PrintRightOperand(data);
1179 {
bool is_byte = *data == 0xC6;
1182 AppendToBuffer(
"%s ",
"mov_b");
1183 data += PrintRightByteOperand(data);
1185 AppendToBuffer(
",0x%x", imm);
1188 AppendToBuffer(
"%s ",
"mov");
1189 data += PrintRightOperand(data);
1191 AppendToBuffer(
",0x%x", imm);
1200 get_modrm(*data, &mod, ®op, &rm);
1201 const char* mnem =
NULL;
1203 case 5: mnem =
"subb";
break;
1204 case 7: mnem =
"cmpb";
break;
1205 default: UnimplementedInstruction();
1207 AppendToBuffer(
"%s ", mnem);
1208 data += PrintRightByteOperand(data);
1210 AppendToBuffer(
",0x%x", imm);
1217 {
bool is_byte = *data == 0x88;
1220 get_modrm(*data, &mod, ®op, &rm);
1222 AppendToBuffer(
"%s ",
"mov_b");
1223 data += PrintRightByteOperand(data);
1224 AppendToBuffer(
",%s", NameOfByteCPURegister(regop));
1226 AppendToBuffer(
"%s ",
"mov");
1227 data += PrintRightOperand(data);
1228 AppendToBuffer(
",%s", NameOfCPURegister(regop));
1234 while (*data == 0x66) data++;
1235 if (*data == 0xf && data[1] == 0x1f) {
1236 AppendToBuffer(
"nop");
1237 }
else if (*data == 0x90) {
1238 AppendToBuffer(
"nop");
1239 }
else if (*data == 0x8B) {
1241 data += PrintOperands(
"mov_w", REG_OPER_OP_ORDER, data);
1242 }
else if (*data == 0x89) {
1245 get_modrm(*data, &mod, ®op, &rm);
1246 AppendToBuffer(
"mov_w ");
1247 data += PrintRightOperand(data);
1248 AppendToBuffer(
",%s", NameOfCPURegister(regop));
1249 }
else if (*data == 0xC7) {
1251 AppendToBuffer(
"%s ",
"mov_w");
1252 data += PrintRightOperand(data);
1253 int imm = *
reinterpret_cast<int16_t*
>(data);
1254 AppendToBuffer(
",0x%x", imm);
1256 }
else if (*data == 0x0F) {
1258 if (*data == 0x38) {
1260 if (*data == 0x17) {
1263 get_modrm(*data, &mod, ®op, &rm);
1264 AppendToBuffer(
"ptest %s,%s",
1265 NameOfXMMRegister(regop),
1266 NameOfXMMRegister(rm));
1268 }
else if (*data == 0x2A) {
1272 get_modrm(*data, &mod, ®op, &rm);
1273 AppendToBuffer(
"movntdqa %s,", NameOfXMMRegister(regop));
1274 data += PrintRightOperand(data);
1276 UnimplementedInstruction();
1278 }
else if (*data == 0x3A) {
1280 if (*data == 0x0B) {
1283 get_modrm(*data, &mod, ®op, &rm);
1284 int8_t imm8 =
static_cast<int8_t
>(data[1]);
1285 AppendToBuffer(
"roundsd %s,%s,%d",
1286 NameOfXMMRegister(regop),
1287 NameOfXMMRegister(rm),
1288 static_cast<int>(imm8));
1290 }
else if (*data == 0x16) {
1293 get_modrm(*data, &mod, ®op, &rm);
1294 int8_t imm8 =
static_cast<int8_t
>(data[1]);
1295 AppendToBuffer(
"pextrd %s,%s,%d",
1296 NameOfCPURegister(regop),
1297 NameOfXMMRegister(rm),
1298 static_cast<int>(imm8));
1300 }
else if (*data == 0x17) {
1303 get_modrm(*data, &mod, ®op, &rm);
1304 int8_t imm8 =
static_cast<int8_t
>(data[1]);
1305 AppendToBuffer(
"extractps %s,%s,%d",
1306 NameOfCPURegister(rm),
1307 NameOfXMMRegister(regop),
1308 static_cast<int>(imm8));
1310 }
else if (*data == 0x22) {
1313 get_modrm(*data, &mod, ®op, &rm);
1314 int8_t imm8 =
static_cast<int8_t
>(data[1]);
1315 AppendToBuffer(
"pinsrd %s,%s,%d",
1316 NameOfXMMRegister(regop),
1317 NameOfCPURegister(rm),
1318 static_cast<int>(imm8));
1321 UnimplementedInstruction();
1323 }
else if (*data == 0x2E || *data == 0x2F) {
1324 const char* mnem = (*data == 0x2E) ?
"ucomisd" :
"comisd";
1327 get_modrm(*data, &mod, ®op, &rm);
1329 AppendToBuffer(
"%s %s,%s", mnem,
1330 NameOfXMMRegister(regop),
1331 NameOfXMMRegister(rm));
1334 AppendToBuffer(
"%s %s,", mnem, NameOfXMMRegister(regop));
1335 data += PrintRightOperand(data);
1337 }
else if (*data == 0x50) {
1340 get_modrm(*data, &mod, ®op, &rm);
1341 AppendToBuffer(
"movmskpd %s,%s",
1342 NameOfCPURegister(regop),
1343 NameOfXMMRegister(rm));
1345 }
else if (*data == 0x54) {
1348 get_modrm(*data, &mod, ®op, &rm);
1349 AppendToBuffer(
"andpd %s,%s",
1350 NameOfXMMRegister(regop),
1351 NameOfXMMRegister(rm));
1353 }
else if (*data == 0x56) {
1356 get_modrm(*data, &mod, ®op, &rm);
1357 AppendToBuffer(
"orpd %s,%s",
1358 NameOfXMMRegister(regop),
1359 NameOfXMMRegister(rm));
1361 }
else if (*data == 0x57) {
1364 get_modrm(*data, &mod, ®op, &rm);
1365 AppendToBuffer(
"xorpd %s,%s",
1366 NameOfXMMRegister(regop),
1367 NameOfXMMRegister(rm));
1369 }
else if (*data == 0x6E) {
1372 get_modrm(*data, &mod, ®op, &rm);
1373 AppendToBuffer(
"movd %s,", NameOfXMMRegister(regop));
1374 data += PrintRightOperand(data);
1375 }
else if (*data == 0x6F) {
1378 get_modrm(*data, &mod, ®op, &rm);
1379 AppendToBuffer(
"movdqa %s,", NameOfXMMRegister(regop));
1380 data += PrintRightXMMOperand(data);
1381 }
else if (*data == 0x70) {
1384 get_modrm(*data, &mod, ®op, &rm);
1385 int8_t imm8 =
static_cast<int8_t
>(data[1]);
1386 AppendToBuffer(
"pshufd %s,%s,%d",
1387 NameOfXMMRegister(regop),
1388 NameOfXMMRegister(rm),
1389 static_cast<int>(imm8));
1391 }
else if (*data == 0x76) {
1394 get_modrm(*data, &mod, ®op, &rm);
1395 AppendToBuffer(
"pcmpeqd %s,%s",
1396 NameOfXMMRegister(regop),
1397 NameOfXMMRegister(rm));
1399 }
else if (*data == 0x90) {
1401 AppendToBuffer(
"nop");
1402 }
else if (*data == 0xF3) {
1405 get_modrm(*data, &mod, ®op, &rm);
1406 AppendToBuffer(
"psllq %s,%s",
1407 NameOfXMMRegister(regop),
1408 NameOfXMMRegister(rm));
1410 }
else if (*data == 0x73) {
1413 get_modrm(*data, &mod, ®op, &rm);
1414 int8_t imm8 =
static_cast<int8_t
>(data[1]);
1416 AppendToBuffer(
"%s %s,%d",
1417 (regop ==
esi) ?
"psllq" :
"psrlq",
1418 NameOfXMMRegister(rm),
1419 static_cast<int>(imm8));
1421 }
else if (*data == 0xD3) {
1424 get_modrm(*data, &mod, ®op, &rm);
1425 AppendToBuffer(
"psrlq %s,%s",
1426 NameOfXMMRegister(regop),
1427 NameOfXMMRegister(rm));
1429 }
else if (*data == 0x7F) {
1430 AppendToBuffer(
"movdqa ");
1433 get_modrm(*data, &mod, ®op, &rm);
1434 data += PrintRightXMMOperand(data);
1435 AppendToBuffer(
",%s", NameOfXMMRegister(regop));
1436 }
else if (*data == 0x7E) {
1439 get_modrm(*data, &mod, ®op, &rm);
1440 AppendToBuffer(
"movd ");
1441 data += PrintRightOperand(data);
1442 AppendToBuffer(
",%s", NameOfXMMRegister(regop));
1443 }
else if (*data == 0xDB) {
1446 get_modrm(*data, &mod, ®op, &rm);
1447 AppendToBuffer(
"pand %s,%s",
1448 NameOfXMMRegister(regop),
1449 NameOfXMMRegister(rm));
1451 }
else if (*data == 0xE7) {
1454 get_modrm(*data, &mod, ®op, &rm);
1456 AppendToBuffer(
"movntdq ");
1457 data += PrintRightOperand(data);
1458 AppendToBuffer(
",%s", NameOfXMMRegister(regop));
1460 UnimplementedInstruction();
1462 }
else if (*data == 0xEF) {
1465 get_modrm(*data, &mod, ®op, &rm);
1466 AppendToBuffer(
"pxor %s,%s",
1467 NameOfXMMRegister(regop),
1468 NameOfXMMRegister(rm));
1470 }
else if (*data == 0xEB) {
1473 get_modrm(*data, &mod, ®op, &rm);
1474 AppendToBuffer(
"por %s,%s",
1475 NameOfXMMRegister(regop),
1476 NameOfXMMRegister(rm));
1479 UnimplementedInstruction();
1482 UnimplementedInstruction();
1489 get_modrm(*data, &mod, ®op, &rm);
1491 AppendToBuffer(
"dec_b ");
1492 data += PrintRightOperand(data);
1494 UnimplementedInstruction();
1500 AppendToBuffer(
"push 0x%x", *
reinterpret_cast<int32_t*
>(data+1));
1505 AppendToBuffer(
"push 0x%x", *
reinterpret_cast<int8_t*
>(data + 1));
1510 AppendToBuffer(
"test al,0x%x", *
reinterpret_cast<uint8_t*
>(data+1));
1515 AppendToBuffer(
"test eax,0x%x", *
reinterpret_cast<int32_t*
>(data+1));
1522 data += D1D3C1Instruction(data);
1533 data += FPUInstruction(data);
1537 data += JumpShort(data);
1541 if (*(data+1) == 0x0F) {
1542 byte b2 = *(data+2);
1544 AppendToBuffer(
"movsd ");
1547 get_modrm(*data, &mod, ®op, &rm);
1548 data += PrintRightXMMOperand(data);
1549 AppendToBuffer(
",%s", NameOfXMMRegister(regop));
1550 }
else if (b2 == 0x10) {
1553 get_modrm(*data, &mod, ®op, &rm);
1554 AppendToBuffer(
"movsd %s,", NameOfXMMRegister(regop));
1555 data += PrintRightXMMOperand(data);
1556 }
else if (b2 == 0x5A) {
1559 get_modrm(*data, &mod, ®op, &rm);
1560 AppendToBuffer(
"cvtsd2ss %s,", NameOfXMMRegister(regop));
1561 data += PrintRightXMMOperand(data);
1563 const char* mnem =
"?";
1565 case 0x2A: mnem =
"cvtsi2sd";
break;
1566 case 0x2C: mnem =
"cvttsd2si";
break;
1567 case 0x2D: mnem =
"cvtsd2si";
break;
1568 case 0x51: mnem =
"sqrtsd";
break;
1569 case 0x58: mnem =
"addsd";
break;
1570 case 0x59: mnem =
"mulsd";
break;
1571 case 0x5C: mnem =
"subsd";
break;
1572 case 0x5E: mnem =
"divsd";
break;
1576 get_modrm(*data, &mod, ®op, &rm);
1578 AppendToBuffer(
"%s %s,", mnem, NameOfXMMRegister(regop));
1579 data += PrintRightOperand(data);
1580 }
else if (b2 == 0x2C || b2 == 0x2D) {
1581 AppendToBuffer(
"%s %s,", mnem, NameOfCPURegister(regop));
1582 data += PrintRightXMMOperand(data);
1583 }
else if (b2 == 0xC2) {
1585 const char*
const pseudo_op[] = {
1595 AppendToBuffer(
"%s %s,%s",
1597 NameOfXMMRegister(regop),
1598 NameOfXMMRegister(rm));
1601 AppendToBuffer(
"%s %s,", mnem, NameOfXMMRegister(regop));
1602 data += PrintRightXMMOperand(data);
1606 UnimplementedInstruction();
1611 if (*(data+1) == 0x0F) {
1612 byte b2 = *(data+2);
1614 AppendToBuffer(
"movss ");
1617 get_modrm(*data, &mod, ®op, &rm);
1618 data += PrintRightXMMOperand(data);
1619 AppendToBuffer(
",%s", NameOfXMMRegister(regop));
1620 }
else if (b2 == 0x10) {
1623 get_modrm(*data, &mod, ®op, &rm);
1624 AppendToBuffer(
"movss %s,", NameOfXMMRegister(regop));
1625 data += PrintRightXMMOperand(data);
1626 }
else if (b2 == 0x2C) {
1629 get_modrm(*data, &mod, ®op, &rm);
1630 AppendToBuffer(
"cvttss2si %s,", NameOfCPURegister(regop));
1631 data += PrintRightXMMOperand(data);
1632 }
else if (b2 == 0x5A) {
1635 get_modrm(*data, &mod, ®op, &rm);
1636 AppendToBuffer(
"cvtss2sd %s,", NameOfXMMRegister(regop));
1637 data += PrintRightXMMOperand(data);
1638 }
else if (b2 == 0x6F) {
1641 get_modrm(*data, &mod, ®op, &rm);
1642 AppendToBuffer(
"movdqu %s,", NameOfXMMRegister(regop));
1643 data += PrintRightXMMOperand(data);
1644 }
else if (b2 == 0x7F) {
1645 AppendToBuffer(
"movdqu ");
1648 get_modrm(*data, &mod, ®op, &rm);
1649 data += PrintRightXMMOperand(data);
1650 AppendToBuffer(
",%s", NameOfXMMRegister(regop));
1652 UnimplementedInstruction();
1654 }
else if (*(data+1) == 0xA5) {
1656 AppendToBuffer(
"rep_movs");
1657 }
else if (*(data+1) == 0xAB) {
1659 AppendToBuffer(
"rep_stos");
1661 UnimplementedInstruction();
1666 data += F7Instruction(data);
1670 UnimplementedInstruction();
1674 if (tmp_buffer_pos_ <
sizeof tmp_buffer_) {
1675 tmp_buffer_[tmp_buffer_pos_] =
'\0';
1678 int instr_len = data - instr;
1679 if (instr_len == 0) {
1680 printf(
"%02x", *data);
1686 for (
byte* bp = instr; bp < data; bp++) {
1689 for (
int i = 6 - instr_len;
i >= 0;
i--) {
1701 static const char* cpu_regs[8] = {
1702 "eax",
"ecx",
"edx",
"ebx",
"esp",
"ebp",
"esi",
"edi"
1706 static const char* byte_cpu_regs[8] = {
1707 "al",
"cl",
"dl",
"bl",
"ah",
"ch",
"dh",
"bh"
1711 static const char* xmm_regs[8] = {
1712 "xmm0",
"xmm1",
"xmm2",
"xmm3",
"xmm4",
"xmm5",
"xmm6",
"xmm7"
1728 if (0 <= reg && reg < 8)
return cpu_regs[reg];
1734 if (0 <= reg && reg < 8)
return byte_cpu_regs[reg];
1740 if (0 <= reg && reg < 8)
return xmm_regs[reg];
1755 : converter_(converter) {}
1758 Disassembler::~Disassembler() {}
1762 byte* instruction) {
1763 DisassemblerX87 d(converter_,
false );
1764 return d.InstructionDecode(buffer, instruction);
1769 int Disassembler::ConstantPoolSizeAt(
byte* instruction) {
return -1; }
1772 void Disassembler::Disassemble(FILE* f,
byte* begin,
byte* end) {
1773 NameConverter converter;
1774 Disassembler d(converter);
1775 for (
byte*
pc = begin;
pc < end;) {
1779 pc += d.InstructionDecode(buffer,
pc);
1780 fprintf(f,
"%p", prev_pc);
1783 for (
byte* bp = prev_pc; bp <
pc; bp++) {
1784 fprintf(f,
"%02x", *bp);
1786 for (
int i = 6 - (
pc - prev_pc);
i >= 0;
i--) {
1789 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)