34 #if V8_TARGET_ARCH_IA32
53 OperandOrder op_order_;
57 static const ByteMnemonic two_operands_instr[] = {
58 {0x01,
"add", OPER_REG_OP_ORDER},
59 {0x03,
"add", REG_OPER_OP_ORDER},
60 {0x09,
"or", OPER_REG_OP_ORDER},
61 {0x0B,
"or", REG_OPER_OP_ORDER},
62 {0x1B,
"sbb", REG_OPER_OP_ORDER},
63 {0x21,
"and", OPER_REG_OP_ORDER},
64 {0x23,
"and", REG_OPER_OP_ORDER},
65 {0x29,
"sub", OPER_REG_OP_ORDER},
66 {0x2A,
"subb", REG_OPER_OP_ORDER},
67 {0x2B,
"sub", REG_OPER_OP_ORDER},
68 {0x31,
"xor", OPER_REG_OP_ORDER},
69 {0x33,
"xor", REG_OPER_OP_ORDER},
70 {0x38,
"cmpb", OPER_REG_OP_ORDER},
71 {0x3A,
"cmpb", REG_OPER_OP_ORDER},
72 {0x3B,
"cmp", REG_OPER_OP_ORDER},
73 {0x84,
"test_b", REG_OPER_OP_ORDER},
74 {0x85,
"test", REG_OPER_OP_ORDER},
75 {0x87,
"xchg", REG_OPER_OP_ORDER},
76 {0x8A,
"mov_b", REG_OPER_OP_ORDER},
77 {0x8B,
"mov", REG_OPER_OP_ORDER},
78 {0x8D,
"lea", REG_OPER_OP_ORDER},
79 {-1,
"", UNSET_OP_ORDER}
83 static const ByteMnemonic zero_operands_instr[] = {
84 {0xC3,
"ret", UNSET_OP_ORDER},
85 {0xC9,
"leave", UNSET_OP_ORDER},
86 {0x90,
"nop", UNSET_OP_ORDER},
87 {0xF4,
"hlt", UNSET_OP_ORDER},
88 {0xCC,
"int3", UNSET_OP_ORDER},
89 {0x60,
"pushad", UNSET_OP_ORDER},
90 {0x61,
"popad", UNSET_OP_ORDER},
91 {0x9C,
"pushfd", UNSET_OP_ORDER},
92 {0x9D,
"popfd", UNSET_OP_ORDER},
93 {0x9E,
"sahf", UNSET_OP_ORDER},
94 {0x99,
"cdq", UNSET_OP_ORDER},
95 {0x9B,
"fwait", UNSET_OP_ORDER},
96 {0xFC,
"cld", UNSET_OP_ORDER},
97 {0xAB,
"stos", UNSET_OP_ORDER},
98 {-1,
"", UNSET_OP_ORDER}
102 static const ByteMnemonic call_jump_instr[] = {
103 {0xE8,
"call", UNSET_OP_ORDER},
104 {0xE9,
"jmp", UNSET_OP_ORDER},
105 {-1,
"", UNSET_OP_ORDER}
109 static const ByteMnemonic short_immediate_instr[] = {
110 {0x05,
"add", UNSET_OP_ORDER},
111 {0x0D,
"or", UNSET_OP_ORDER},
112 {0x15,
"adc", UNSET_OP_ORDER},
113 {0x25,
"and", UNSET_OP_ORDER},
114 {0x2D,
"sub", UNSET_OP_ORDER},
115 {0x35,
"xor", UNSET_OP_ORDER},
116 {0x3D,
"cmp", UNSET_OP_ORDER},
117 {-1,
"", UNSET_OP_ORDER}
125 static ByteMnemonic byte_immediate_instr[] = {
126 {0x0c,
"or", UNSET_OP_ORDER},
127 {0x24,
"and", UNSET_OP_ORDER},
128 {0x34,
"xor", UNSET_OP_ORDER},
129 {0x3c,
"cmp", UNSET_OP_ORDER},
130 {-1,
"", UNSET_OP_ORDER}
134 static const char*
const jump_conditional_mnem[] = {
135 "jo",
"jno",
"jc",
"jnc",
136 "jz",
"jnz",
"jna",
"ja",
137 "js",
"jns",
"jpe",
"jpo",
138 "jl",
"jnl",
"jng",
"jg"
142 static const char*
const set_conditional_mnem[] = {
143 "seto",
"setno",
"setc",
"setnc",
144 "setz",
"setnz",
"setna",
"seta",
145 "sets",
"setns",
"setpe",
"setpo",
146 "setl",
"setnl",
"setng",
"setg"
150 static const char*
const conditional_move_mnem[] = {
151 "cmovo",
"cmovno",
"cmovc",
"cmovnc",
152 "cmovz",
"cmovnz",
"cmovna",
"cmova",
153 "cmovs",
"cmovns",
"cmovpe",
"cmovpo",
154 "cmovl",
"cmovnl",
"cmovng",
"cmovg"
158 enum InstructionType {
162 JUMP_CONDITIONAL_SHORT_INSTR,
166 SHORT_IMMEDIATE_INSTR,
171 struct InstructionDesc {
173 InstructionType type;
174 OperandOrder op_order_;
178 class InstructionTable {
181 const InstructionDesc& Get(
byte x)
const {
return instructions_[x]; }
182 static InstructionTable* get_instance() {
183 static InstructionTable table;
188 InstructionDesc instructions_[256];
191 void CopyTable(
const ByteMnemonic bm[], InstructionType type);
192 void SetTableRange(InstructionType type,
196 void AddJumpConditionalShort();
200 InstructionTable::InstructionTable() {
206 void InstructionTable::Clear() {
207 for (
int i = 0; i < 256; i++) {
208 instructions_[i].mnem =
"";
209 instructions_[i].type = NO_INSTR;
210 instructions_[i].op_order_ = UNSET_OP_ORDER;
215 void InstructionTable::Init() {
216 CopyTable(two_operands_instr, TWO_OPERANDS_INSTR);
217 CopyTable(zero_operands_instr, ZERO_OPERANDS_INSTR);
218 CopyTable(call_jump_instr, CALL_JUMP_INSTR);
219 CopyTable(short_immediate_instr, SHORT_IMMEDIATE_INSTR);
220 CopyTable(byte_immediate_instr, BYTE_IMMEDIATE_INSTR);
221 AddJumpConditionalShort();
222 SetTableRange(REGISTER_INSTR, 0x40, 0x47,
"inc");
223 SetTableRange(REGISTER_INSTR, 0x48, 0x4F,
"dec");
224 SetTableRange(REGISTER_INSTR, 0x50, 0x57,
"push");
225 SetTableRange(REGISTER_INSTR, 0x58, 0x5F,
"pop");
226 SetTableRange(REGISTER_INSTR, 0x91, 0x97,
"xchg eax,");
227 SetTableRange(MOVE_REG_INSTR, 0xB8, 0xBF,
"mov");
231 void InstructionTable::CopyTable(
const ByteMnemonic bm[],
232 InstructionType type) {
233 for (
int i = 0; bm[i].b >= 0; i++) {
234 InstructionDesc*
id = &instructions_[bm[i].b];
235 id->mnem = bm[i].mnem;
236 id->op_order_ = bm[i].op_order_;
243 void InstructionTable::SetTableRange(InstructionType type,
247 for (
byte b = start; b <= end; b++) {
248 InstructionDesc*
id = &instructions_[b];
256 void InstructionTable::AddJumpConditionalShort() {
257 for (
byte b = 0x70; b <= 0x7F; b++) {
258 InstructionDesc*
id = &instructions_[b];
260 id->mnem = jump_conditional_mnem[b & 0x0F];
261 id->type = JUMP_CONDITIONAL_SHORT_INSTR;
267 class DisassemblerIA32 {
269 DisassemblerIA32(
const NameConverter& converter,
270 bool abort_on_unimplemented =
true)
271 : converter_(converter),
272 instruction_table_(InstructionTable::get_instance()),
274 abort_on_unimplemented_(abort_on_unimplemented) {
275 tmp_buffer_[0] =
'\0';
278 virtual ~DisassemblerIA32() {}
285 const NameConverter& converter_;
286 InstructionTable* instruction_table_;
288 unsigned int tmp_buffer_pos_;
289 bool abort_on_unimplemented_;
303 enum ShiftOpcodeExtension {
314 const char* NameOfCPURegister(
int reg)
const {
315 return converter_.NameOfCPURegister(reg);
319 const char* NameOfByteCPURegister(
int reg)
const {
320 return converter_.NameOfByteCPURegister(reg);
324 const char* NameOfXMMRegister(
int reg)
const {
325 return converter_.NameOfXMMRegister(reg);
329 const char* NameOfAddress(
byte* addr)
const {
330 return converter_.NameOfAddress(addr);
335 static void get_modrm(
byte data,
int* mod,
int* regop,
int* rm) {
336 *mod = (data >> 6) & 3;
337 *regop = (data & 0x38) >> 3;
342 static void get_sib(
byte data,
int* scale,
int* index,
int* base) {
343 *scale = (data >> 6) & 3;
344 *index = (data >> 3) & 7;
348 typedef const char* (DisassemblerIA32::*RegisterNameMapping)(
int reg)
const;
350 int PrintRightOperandHelper(
byte* modrmp, RegisterNameMapping register_name);
351 int PrintRightOperand(
byte* modrmp);
352 int PrintRightByteOperand(
byte* modrmp);
353 int PrintRightXMMOperand(
byte* modrmp);
354 int PrintOperands(
const char* mnem, OperandOrder op_order,
byte* data);
355 int PrintImmediateOp(
byte* data);
356 int F7Instruction(
byte* data);
357 int D1D3C1Instruction(
byte* data);
358 int JumpShort(
byte* data);
359 int JumpConditional(
byte* data,
const char* comment);
360 int JumpConditionalShort(
byte* data,
const char* comment);
362 int CMov(
byte* data);
363 int FPUInstruction(
byte* data);
364 int MemoryFPUInstruction(
int escape_opcode,
int regop,
byte* modrm_start);
365 int RegisterFPUInstruction(
int escape_opcode,
byte modrm_byte);
366 void AppendToBuffer(
const char* format, ...);
369 void UnimplementedInstruction() {
370 if (abort_on_unimplemented_) {
373 AppendToBuffer(
"'Unimplemented Instruction'");
379 void DisassemblerIA32::AppendToBuffer(
const char* format, ...) {
382 va_start(args, format);
385 tmp_buffer_pos_ += result;
388 int DisassemblerIA32::PrintRightOperandHelper(
390 RegisterNameMapping direct_register_name) {
392 get_modrm(*modrmp, &mod, ®op, &rm);
393 RegisterNameMapping register_name = (mod == 3) ? direct_register_name :
394 &DisassemblerIA32::NameOfCPURegister;
399 AppendToBuffer(
"[0x%x]", disp);
401 }
else if (rm ==
esp) {
402 byte sib = *(modrmp + 1);
403 int scale, index, base;
404 get_sib(sib, &scale, &index, &base);
405 if (index ==
esp && base ==
esp && scale == 0 ) {
406 AppendToBuffer(
"[%s]", (this->*register_name)(rm));
408 }
else if (base ==
ebp) {
410 AppendToBuffer(
"[%s*%d%s0x%x]",
411 (this->*register_name)(index),
413 disp < 0 ?
"-" :
"+",
414 disp < 0 ? -disp : disp);
416 }
else if (index !=
esp && base !=
ebp) {
418 AppendToBuffer(
"[%s+%s*%d]",
419 (this->*register_name)(base),
420 (this->*register_name)(index),
424 UnimplementedInstruction();
428 AppendToBuffer(
"[%s]", (this->*register_name)(rm));
435 byte sib = *(modrmp + 1);
436 int scale, index, base;
437 get_sib(sib, &scale, &index, &base);
438 int disp = mod == 2 ? *
reinterpret_cast<int32_t*
>(modrmp + 2)
439 : *reinterpret_cast<int8_t*>(modrmp + 2);
440 if (index == base && index == rm && scale == 0 ) {
441 AppendToBuffer(
"[%s%s0x%x]",
442 (this->*register_name)(rm),
443 disp < 0 ?
"-" :
"+",
444 disp < 0 ? -disp : disp);
446 AppendToBuffer(
"[%s+%s*%d%s0x%x]",
447 (this->*register_name)(base),
448 (this->*register_name)(index),
450 disp < 0 ?
"-" :
"+",
451 disp < 0 ? -disp : disp);
453 return mod == 2 ? 6 : 3;
456 int disp = mod == 2 ? *
reinterpret_cast<int32_t*
>(modrmp + 1)
457 : *reinterpret_cast<int8_t*>(modrmp + 1);
458 AppendToBuffer(
"[%s%s0x%x]",
459 (this->*register_name)(rm),
460 disp < 0 ?
"-" :
"+",
461 disp < 0 ? -disp : disp);
462 return mod == 2 ? 5 : 2;
466 AppendToBuffer(
"%s", (this->*register_name)(rm));
469 UnimplementedInstruction();
476 int DisassemblerIA32::PrintRightOperand(
byte* modrmp) {
477 return PrintRightOperandHelper(modrmp, &DisassemblerIA32::NameOfCPURegister);
481 int DisassemblerIA32::PrintRightByteOperand(
byte* modrmp) {
482 return PrintRightOperandHelper(modrmp,
483 &DisassemblerIA32::NameOfByteCPURegister);
487 int DisassemblerIA32::PrintRightXMMOperand(
byte* modrmp) {
488 return PrintRightOperandHelper(modrmp,
489 &DisassemblerIA32::NameOfXMMRegister);
495 int DisassemblerIA32::PrintOperands(
const char* mnem,
496 OperandOrder op_order,
500 get_modrm(modrm, &mod, ®op, &rm);
503 case REG_OPER_OP_ORDER: {
504 AppendToBuffer(
"%s %s,", mnem, NameOfCPURegister(regop));
505 advance = PrintRightOperand(data);
508 case OPER_REG_OP_ORDER: {
509 AppendToBuffer(
"%s ", mnem);
510 advance = PrintRightOperand(data);
511 AppendToBuffer(
",%s", NameOfCPURegister(regop));
524 int DisassemblerIA32::PrintImmediateOp(
byte* data) {
525 bool sign_extension_bit = (*data & 0x02) != 0;
526 byte modrm = *(data+1);
528 get_modrm(modrm, &mod, ®op, &rm);
529 const char* mnem =
"Imm???";
531 case 0: mnem =
"add";
break;
532 case 1: mnem =
"or";
break;
533 case 2: mnem =
"adc";
break;
534 case 4: mnem =
"and";
break;
535 case 5: mnem =
"sub";
break;
536 case 6: mnem =
"xor";
break;
537 case 7: mnem =
"cmp";
break;
538 default: UnimplementedInstruction();
540 AppendToBuffer(
"%s ", mnem);
541 int count = PrintRightOperand(data+1);
542 if (sign_extension_bit) {
543 AppendToBuffer(
",0x%x", *(data + 1 + count));
544 return 1 + count + 1 ;
546 AppendToBuffer(
",0x%x", *reinterpret_cast<int32_t*>(data + 1 + count));
547 return 1 + count + 4 ;
553 int DisassemblerIA32::F7Instruction(
byte* data) {
555 byte modrm = *(data+1);
557 get_modrm(modrm, &mod, ®op, &rm);
558 if (mod == 3 && regop != 0) {
559 const char* mnem =
NULL;
561 case 2: mnem =
"not";
break;
562 case 3: mnem =
"neg";
break;
563 case 4: mnem =
"mul";
break;
564 case 5: mnem =
"imul";
break;
565 case 7: mnem =
"idiv";
break;
566 default: UnimplementedInstruction();
568 AppendToBuffer(
"%s %s", mnem, NameOfCPURegister(rm));
570 }
else if (mod == 3 && regop ==
eax) {
572 AppendToBuffer(
"test %s,0x%x", NameOfCPURegister(rm), imm);
574 }
else if (regop ==
eax) {
575 AppendToBuffer(
"test ");
576 int count = PrintRightOperand(data+1);
578 AppendToBuffer(
",0x%x", imm);
581 UnimplementedInstruction();
587 int DisassemblerIA32::D1D3C1Instruction(
byte* data) {
589 ASSERT(op == 0xD1 || op == 0xD3 || op == 0xC1);
590 byte modrm = *(data+1);
592 get_modrm(modrm, &mod, ®op, &rm);
596 const char* mnem =
NULL;
598 case kROL: mnem =
"rol";
break;
599 case kROR: mnem =
"ror";
break;
600 case kRCL: mnem =
"rcl";
break;
601 case kRCR: mnem =
"rcr";
break;
602 case kSHL: mnem =
"shl";
break;
603 case KSHR: mnem =
"shr";
break;
604 case kSAR: mnem =
"sar";
break;
605 default: UnimplementedInstruction();
609 }
else if (op == 0xC1) {
612 }
else if (op == 0xD3) {
616 AppendToBuffer(
"%s %s,", mnem, NameOfCPURegister(rm));
618 AppendToBuffer(
"%d", imm8);
620 AppendToBuffer(
"cl");
623 UnimplementedInstruction();
630 int DisassemblerIA32::JumpShort(
byte* data) {
633 byte* dest = data +
static_cast<int8_t
>(b) + 2;
634 AppendToBuffer(
"jmp %s", NameOfAddress(dest));
640 int DisassemblerIA32::JumpConditional(
byte* data,
const char* comment) {
642 byte cond = *(data+1) & 0x0F;
643 byte* dest = data + *
reinterpret_cast<int32_t*
>(data+2) + 6;
644 const char* mnem = jump_conditional_mnem[cond];
645 AppendToBuffer(
"%s %s", mnem, NameOfAddress(dest));
646 if (comment !=
NULL) {
647 AppendToBuffer(
", %s", comment);
654 int DisassemblerIA32::JumpConditionalShort(
byte* data,
const char* comment) {
655 byte cond = *data & 0x0F;
657 byte* dest = data +
static_cast<int8_t
>(b) + 2;
658 const char* mnem = jump_conditional_mnem[cond];
659 AppendToBuffer(
"%s %s", mnem, NameOfAddress(dest));
660 if (comment !=
NULL) {
661 AppendToBuffer(
", %s", comment);
670 byte cond = *(data+1) & 0x0F;
671 const char* mnem = set_conditional_mnem[cond];
672 AppendToBuffer(
"%s ", mnem);
673 PrintRightByteOperand(data+2);
679 int DisassemblerIA32::CMov(
byte* data) {
681 byte cond = *(data + 1) & 0x0F;
682 const char* mnem = conditional_move_mnem[cond];
683 int op_size = PrintOperands(mnem, REG_OPER_OP_ORDER, data + 2);
689 int DisassemblerIA32::FPUInstruction(
byte* data) {
690 byte escape_opcode = *data;
692 byte modrm_byte = *(data+1);
694 if (modrm_byte >= 0xC0) {
695 return RegisterFPUInstruction(escape_opcode, modrm_byte);
697 return MemoryFPUInstruction(escape_opcode, modrm_byte, data+1);
701 int DisassemblerIA32::MemoryFPUInstruction(
int escape_opcode,
704 const char* mnem =
"?";
705 int regop = (modrm_byte >> 3) & 0x7;
706 switch (escape_opcode) {
707 case 0xD9:
switch (regop) {
708 case 0: mnem =
"fld_s";
break;
709 case 2: mnem =
"fst_s";
break;
710 case 3: mnem =
"fstp_s";
break;
711 case 7: mnem =
"fstcw";
break;
712 default: UnimplementedInstruction();
716 case 0xDB:
switch (regop) {
717 case 0: mnem =
"fild_s";
break;
718 case 1: mnem =
"fisttp_s";
break;
719 case 2: mnem =
"fist_s";
break;
720 case 3: mnem =
"fistp_s";
break;
721 default: UnimplementedInstruction();
725 case 0xDD:
switch (regop) {
726 case 0: mnem =
"fld_d";
break;
727 case 1: mnem =
"fisttp_d";
break;
728 case 2: mnem =
"fst_d";
break;
729 case 3: mnem =
"fstp_d";
break;
730 default: UnimplementedInstruction();
734 case 0xDF:
switch (regop) {
735 case 5: mnem =
"fild_d";
break;
736 case 7: mnem =
"fistp_d";
break;
737 default: UnimplementedInstruction();
741 default: UnimplementedInstruction();
743 AppendToBuffer(
"%s ", mnem);
744 int count = PrintRightOperand(modrm_start);
748 int DisassemblerIA32::RegisterFPUInstruction(
int escape_opcode,
750 bool has_register =
false;
751 const char* mnem =
"?";
753 switch (escape_opcode) {
756 switch (modrm_byte & 0xF8) {
757 case 0xC0: mnem =
"fadd_i";
break;
758 case 0xE0: mnem =
"fsub_i";
break;
759 case 0xC8: mnem =
"fmul_i";
break;
760 case 0xF0: mnem =
"fdiv_i";
break;
761 default: UnimplementedInstruction();
766 switch (modrm_byte & 0xF8) {
776 switch (modrm_byte) {
777 case 0xE0: mnem =
"fchs";
break;
778 case 0xE1: mnem =
"fabs";
break;
779 case 0xE4: mnem =
"ftst";
break;
780 case 0xE8: mnem =
"fld1";
break;
781 case 0xEB: mnem =
"fldpi";
break;
782 case 0xED: mnem =
"fldln2";
break;
783 case 0xEE: mnem =
"fldz";
break;
784 case 0xF0: mnem =
"f2xm1";
break;
785 case 0xF1: mnem =
"fyl2x";
break;
786 case 0xF4: mnem =
"fxtract";
break;
787 case 0xF5: mnem =
"fprem1";
break;
788 case 0xF7: mnem =
"fincstp";
break;
789 case 0xF8: mnem =
"fprem";
break;
790 case 0xFC: mnem =
"frndint";
break;
791 case 0xFD: mnem =
"fscale";
break;
792 case 0xFE: mnem =
"fsin";
break;
793 case 0xFF: mnem =
"fcos";
break;
794 default: UnimplementedInstruction();
800 if (modrm_byte == 0xE9) {
803 UnimplementedInstruction();
808 if ((modrm_byte & 0xF8) == 0xE8) {
811 }
else if (modrm_byte == 0xE2) {
813 }
else if (modrm_byte == 0xE3) {
816 UnimplementedInstruction();
822 switch (modrm_byte & 0xF8) {
823 case 0xC0: mnem =
"fadd";
break;
824 case 0xE8: mnem =
"fsub";
break;
825 case 0xC8: mnem =
"fmul";
break;
826 case 0xF8: mnem =
"fdiv";
break;
827 default: UnimplementedInstruction();
833 switch (modrm_byte & 0xF8) {
834 case 0xC0: mnem =
"ffree";
break;
835 case 0xD0: mnem =
"fst";
break;
836 case 0xD8: mnem =
"fstp";
break;
837 default: UnimplementedInstruction();
842 if (modrm_byte == 0xD9) {
846 switch (modrm_byte & 0xF8) {
847 case 0xC0: mnem =
"faddp";
break;
848 case 0xE8: mnem =
"fsubp";
break;
849 case 0xC8: mnem =
"fmulp";
break;
850 case 0xF8: mnem =
"fdivp";
break;
851 default: UnimplementedInstruction();
857 if (modrm_byte == 0xE0) {
859 }
else if ((modrm_byte & 0xF8) == 0xE8) {
865 default: UnimplementedInstruction();
869 AppendToBuffer(
"%s st%d", mnem, modrm_byte & 0x7);
871 AppendToBuffer(
"%s", mnem);
879 static const char* F0Mnem(
byte f0byte) {
881 case 0x18:
return "prefetch";
882 case 0xA2:
return "cpuid";
883 case 0xBE:
return "movsx_b";
884 case 0xBF:
return "movsx_w";
885 case 0xB6:
return "movzx_b";
886 case 0xB7:
return "movzx_w";
887 case 0xAF:
return "imul";
888 case 0xA5:
return "shld";
889 case 0xAD:
return "shrd";
890 case 0xAC:
return "shrd";
891 case 0xAB:
return "bts";
892 case 0xBD:
return "bsr";
893 default:
return NULL;
904 const char* branch_hint =
NULL;
906 if (*data == 0x3E ) {
907 branch_hint =
"predicted taken";
909 }
else if (*data == 0x2E ) {
910 branch_hint =
"predicted not taken";
913 bool processed =
true;
915 const InstructionDesc& idesc = instruction_table_->Get(*data);
916 switch (idesc.type) {
917 case ZERO_OPERANDS_INSTR:
918 AppendToBuffer(idesc.mnem);
922 case TWO_OPERANDS_INSTR:
924 data += PrintOperands(idesc.mnem, idesc.op_order_, data);
927 case JUMP_CONDITIONAL_SHORT_INSTR:
928 data += JumpConditionalShort(data, branch_hint);
932 AppendToBuffer(
"%s %s", idesc.mnem, NameOfCPURegister(*data & 0x07));
936 case MOVE_REG_INSTR: {
937 byte* addr =
reinterpret_cast<byte*
>(*
reinterpret_cast<int32_t*
>(data+1));
938 AppendToBuffer(
"mov %s,%s",
939 NameOfCPURegister(*data & 0x07),
940 NameOfAddress(addr));
945 case CALL_JUMP_INSTR: {
946 byte* addr = data + *
reinterpret_cast<int32_t*
>(data+1) + 5;
947 AppendToBuffer(
"%s %s", idesc.mnem, NameOfAddress(addr));
952 case SHORT_IMMEDIATE_INSTR: {
953 byte* addr =
reinterpret_cast<byte*
>(*
reinterpret_cast<int32_t*
>(data+1));
954 AppendToBuffer(
"%s eax,%s", idesc.mnem, NameOfAddress(addr));
959 case BYTE_IMMEDIATE_INSTR: {
960 AppendToBuffer(
"%s al,0x%x", idesc.mnem, data[1]);
976 AppendToBuffer(
"ret 0x%x", *reinterpret_cast<uint16_t*>(data+1));
982 {
int mod, regop, rm;
983 get_modrm(*(data+1), &mod, ®op, &rm);
985 *data == 0x6B ? *(data+2) : *reinterpret_cast<int32_t*>(data+2);
986 AppendToBuffer(
"imul %s,%s,0x%x",
987 NameOfCPURegister(regop),
988 NameOfCPURegister(rm),
990 data += 2 + (*data == 0x6B ? 1 : 4);
997 get_modrm(*data, &mod, ®op, &rm);
999 AppendToBuffer(
"test_b ");
1000 data += PrintRightByteOperand(data);
1002 AppendToBuffer(
",0x%x", imm);
1005 UnimplementedInstruction();
1012 data += PrintImmediateOp(data);
1016 {
byte f0byte = data[1];
1017 const char* f0mnem = F0Mnem(f0byte);
1018 if (f0byte == 0x18) {
1021 get_modrm(*data, &mod, ®op, &rm);
1022 const char* suffix[] = {
"nta",
"1",
"2",
"3"};
1023 AppendToBuffer(
"%s%s ", f0mnem, suffix[regop & 0x03]);
1024 data += PrintRightOperand(data);
1025 }
else if (f0byte == 0x1F && data[2] == 0) {
1026 AppendToBuffer(
"nop");
1028 }
else if (f0byte == 0x1F && data[2] == 0x40 && data[3] == 0) {
1029 AppendToBuffer(
"nop");
1031 }
else if (f0byte == 0x1F && data[2] == 0x44 && data[3] == 0 &&
1033 AppendToBuffer(
"nop");
1035 }
else if (f0byte == 0x1F && data[2] == 0x80 && data[3] == 0 &&
1036 data[4] == 0 && data[5] == 0 && data[6] == 0) {
1037 AppendToBuffer(
"nop");
1039 }
else if (f0byte == 0x1F && data[2] == 0x84 && data[3] == 0 &&
1040 data[4] == 0 && data[5] == 0 && data[6] == 0 &&
1042 AppendToBuffer(
"nop");
1044 }
else if (f0byte == 0xA2 || f0byte == 0x31) {
1045 AppendToBuffer(
"%s", f0mnem);
1047 }
else if (f0byte == 0x28) {
1050 get_modrm(*data, &mod, ®op, &rm);
1051 AppendToBuffer(
"movaps %s,%s",
1052 NameOfXMMRegister(regop),
1053 NameOfXMMRegister(rm));
1055 }
else if (f0byte >= 0x53 && f0byte <= 0x5F) {
1056 const char*
const pseudo_op[] = {
1074 get_modrm(*data, &mod, ®op, &rm);
1075 AppendToBuffer(
"%s %s,",
1076 pseudo_op[f0byte - 0x53],
1077 NameOfXMMRegister(regop));
1078 data += PrintRightXMMOperand(data);
1079 }
else if (f0byte == 0x50) {
1082 get_modrm(*data, &mod, ®op, &rm);
1083 AppendToBuffer(
"movmskps %s,%s",
1084 NameOfCPURegister(regop),
1085 NameOfXMMRegister(rm));
1087 }
else if (f0byte== 0xC6) {
1091 get_modrm(*data, &mod, ®op, &rm);
1092 int8_t imm8 =
static_cast<int8_t
>(data[1]);
1093 AppendToBuffer(
"shufps %s,%s,%d",
1094 NameOfXMMRegister(rm),
1095 NameOfXMMRegister(regop),
1096 static_cast<int>(imm8));
1098 }
else if ((f0byte & 0xF0) == 0x80) {
1099 data += JumpConditional(data, branch_hint);
1100 }
else if (f0byte == 0xBE || f0byte == 0xBF || f0byte == 0xB6 ||
1101 f0byte == 0xB7 || f0byte == 0xAF) {
1103 data += PrintOperands(f0mnem, REG_OPER_OP_ORDER, data);
1104 }
else if ((f0byte & 0xF0) == 0x90) {
1105 data +=
SetCC(data);
1106 }
else if ((f0byte & 0xF0) == 0x40) {
1108 }
else if (f0byte == 0xAB || f0byte == 0xA5 || f0byte == 0xAD) {
1111 AppendToBuffer(
"%s ", f0mnem);
1113 get_modrm(*data, &mod, ®op, &rm);
1114 data += PrintRightOperand(data);
1115 if (f0byte == 0xAB) {
1116 AppendToBuffer(
",%s", NameOfCPURegister(regop));
1118 AppendToBuffer(
",%s,cl", NameOfCPURegister(regop));
1120 }
else if (f0byte == 0xBD) {
1123 get_modrm(*data, &mod, ®op, &rm);
1124 AppendToBuffer(
"%s %s,", f0mnem, NameOfCPURegister(regop));
1125 data += PrintRightOperand(data);
1127 UnimplementedInstruction();
1135 get_modrm(*data, &mod, ®op, &rm);
1137 AppendToBuffer(
"pop ");
1138 data += PrintRightOperand(data);
1146 get_modrm(*data, &mod, ®op, &rm);
1147 const char* mnem =
NULL;
1149 case esi: mnem =
"push";
break;
1150 case eax: mnem =
"inc";
break;
1151 case ecx: mnem =
"dec";
break;
1152 case edx: mnem =
"call";
break;
1153 case esp: mnem =
"jmp";
break;
1154 default: mnem =
"???";
1156 AppendToBuffer(
"%s ", mnem);
1157 data += PrintRightOperand(data);
1163 {
bool is_byte = *data == 0xC6;
1166 AppendToBuffer(
"%s ",
"mov_b");
1167 data += PrintRightByteOperand(data);
1169 AppendToBuffer(
",0x%x", imm);
1172 AppendToBuffer(
"%s ",
"mov");
1173 data += PrintRightOperand(data);
1175 AppendToBuffer(
",0x%x", imm);
1184 get_modrm(*data, &mod, ®op, &rm);
1185 const char* mnem =
NULL;
1187 case 5: mnem =
"subb";
break;
1188 case 7: mnem =
"cmpb";
break;
1189 default: UnimplementedInstruction();
1191 AppendToBuffer(
"%s ", mnem);
1192 data += PrintRightByteOperand(data);
1194 AppendToBuffer(
",0x%x", imm);
1201 {
bool is_byte = *data == 0x88;
1204 get_modrm(*data, &mod, ®op, &rm);
1206 AppendToBuffer(
"%s ",
"mov_b");
1207 data += PrintRightByteOperand(data);
1208 AppendToBuffer(
",%s", NameOfByteCPURegister(regop));
1210 AppendToBuffer(
"%s ",
"mov");
1211 data += PrintRightOperand(data);
1212 AppendToBuffer(
",%s", NameOfCPURegister(regop));
1218 while (*data == 0x66) data++;
1219 if (*data == 0xf && data[1] == 0x1f) {
1220 AppendToBuffer(
"nop");
1221 }
else if (*data == 0x90) {
1222 AppendToBuffer(
"nop");
1223 }
else if (*data == 0x8B) {
1225 data += PrintOperands(
"mov_w", REG_OPER_OP_ORDER, data);
1226 }
else if (*data == 0x89) {
1229 get_modrm(*data, &mod, ®op, &rm);
1230 AppendToBuffer(
"mov_w ");
1231 data += PrintRightOperand(data);
1232 AppendToBuffer(
",%s", NameOfCPURegister(regop));
1233 }
else if (*data == 0xC7) {
1235 AppendToBuffer(
"%s ",
"mov_w");
1236 data += PrintRightOperand(data);
1237 int imm = *
reinterpret_cast<int16_t*
>(data);
1238 AppendToBuffer(
",0x%x", imm);
1240 }
else if (*data == 0x0F) {
1242 if (*data == 0x38) {
1244 if (*data == 0x17) {
1247 get_modrm(*data, &mod, ®op, &rm);
1248 AppendToBuffer(
"ptest %s,%s",
1249 NameOfXMMRegister(regop),
1250 NameOfXMMRegister(rm));
1252 }
else if (*data == 0x2A) {
1256 get_modrm(*data, &mod, ®op, &rm);
1257 AppendToBuffer(
"movntdqa %s,", NameOfXMMRegister(regop));
1258 data += PrintRightOperand(data);
1260 UnimplementedInstruction();
1262 }
else if (*data == 0x3A) {
1264 if (*data == 0x0B) {
1267 get_modrm(*data, &mod, ®op, &rm);
1268 int8_t imm8 =
static_cast<int8_t
>(data[1]);
1269 AppendToBuffer(
"roundsd %s,%s,%d",
1270 NameOfXMMRegister(regop),
1271 NameOfXMMRegister(rm),
1272 static_cast<int>(imm8));
1274 }
else if (*data == 0x16) {
1277 get_modrm(*data, &mod, ®op, &rm);
1278 int8_t imm8 =
static_cast<int8_t
>(data[1]);
1279 AppendToBuffer(
"pextrd %s,%s,%d",
1280 NameOfCPURegister(regop),
1281 NameOfXMMRegister(rm),
1282 static_cast<int>(imm8));
1284 }
else if (*data == 0x17) {
1287 get_modrm(*data, &mod, ®op, &rm);
1288 int8_t imm8 =
static_cast<int8_t
>(data[1]);
1289 AppendToBuffer(
"extractps %s,%s,%d",
1290 NameOfCPURegister(rm),
1291 NameOfXMMRegister(regop),
1292 static_cast<int>(imm8));
1294 }
else if (*data == 0x22) {
1297 get_modrm(*data, &mod, ®op, &rm);
1298 int8_t imm8 =
static_cast<int8_t
>(data[1]);
1299 AppendToBuffer(
"pinsrd %s,%s,%d",
1300 NameOfXMMRegister(regop),
1301 NameOfCPURegister(rm),
1302 static_cast<int>(imm8));
1305 UnimplementedInstruction();
1307 }
else if (*data == 0x2E || *data == 0x2F) {
1308 const char* mnem = (*data == 0x2E) ?
"ucomisd" :
"comisd";
1311 get_modrm(*data, &mod, ®op, &rm);
1313 AppendToBuffer(
"%s %s,%s", mnem,
1314 NameOfXMMRegister(regop),
1315 NameOfXMMRegister(rm));
1318 AppendToBuffer(
"%s %s,", mnem, NameOfXMMRegister(regop));
1319 data += PrintRightOperand(data);
1321 }
else if (*data == 0x50) {
1324 get_modrm(*data, &mod, ®op, &rm);
1325 AppendToBuffer(
"movmskpd %s,%s",
1326 NameOfCPURegister(regop),
1327 NameOfXMMRegister(rm));
1329 }
else if (*data == 0x54) {
1332 get_modrm(*data, &mod, ®op, &rm);
1333 AppendToBuffer(
"andpd %s,%s",
1334 NameOfXMMRegister(regop),
1335 NameOfXMMRegister(rm));
1337 }
else if (*data == 0x56) {
1340 get_modrm(*data, &mod, ®op, &rm);
1341 AppendToBuffer(
"orpd %s,%s",
1342 NameOfXMMRegister(regop),
1343 NameOfXMMRegister(rm));
1345 }
else if (*data == 0x57) {
1348 get_modrm(*data, &mod, ®op, &rm);
1349 AppendToBuffer(
"xorpd %s,%s",
1350 NameOfXMMRegister(regop),
1351 NameOfXMMRegister(rm));
1353 }
else if (*data == 0x6E) {
1356 get_modrm(*data, &mod, ®op, &rm);
1357 AppendToBuffer(
"movd %s,", NameOfXMMRegister(regop));
1358 data += PrintRightOperand(data);
1359 }
else if (*data == 0x6F) {
1362 get_modrm(*data, &mod, ®op, &rm);
1363 AppendToBuffer(
"movdqa %s,", NameOfXMMRegister(regop));
1364 data += PrintRightXMMOperand(data);
1365 }
else if (*data == 0x70) {
1368 get_modrm(*data, &mod, ®op, &rm);
1369 int8_t imm8 =
static_cast<int8_t
>(data[1]);
1370 AppendToBuffer(
"pshufd %s,%s,%d",
1371 NameOfXMMRegister(regop),
1372 NameOfXMMRegister(rm),
1373 static_cast<int>(imm8));
1375 }
else if (*data == 0x76) {
1378 get_modrm(*data, &mod, ®op, &rm);
1379 AppendToBuffer(
"pcmpeqd %s,%s",
1380 NameOfXMMRegister(regop),
1381 NameOfXMMRegister(rm));
1383 }
else if (*data == 0x90) {
1385 AppendToBuffer(
"nop");
1386 }
else if (*data == 0xF3) {
1389 get_modrm(*data, &mod, ®op, &rm);
1390 AppendToBuffer(
"psllq %s,%s",
1391 NameOfXMMRegister(regop),
1392 NameOfXMMRegister(rm));
1394 }
else if (*data == 0x73) {
1397 get_modrm(*data, &mod, ®op, &rm);
1398 int8_t imm8 =
static_cast<int8_t
>(data[1]);
1400 AppendToBuffer(
"%s %s,%d",
1401 (regop ==
esi) ?
"psllq" :
"psrlq",
1402 NameOfXMMRegister(rm),
1403 static_cast<int>(imm8));
1405 }
else if (*data == 0xD3) {
1408 get_modrm(*data, &mod, ®op, &rm);
1409 AppendToBuffer(
"psrlq %s,%s",
1410 NameOfXMMRegister(regop),
1411 NameOfXMMRegister(rm));
1413 }
else if (*data == 0x7F) {
1414 AppendToBuffer(
"movdqa ");
1417 get_modrm(*data, &mod, ®op, &rm);
1418 data += PrintRightXMMOperand(data);
1419 AppendToBuffer(
",%s", NameOfXMMRegister(regop));
1420 }
else if (*data == 0x7E) {
1423 get_modrm(*data, &mod, ®op, &rm);
1424 AppendToBuffer(
"movd ");
1425 data += PrintRightOperand(data);
1426 AppendToBuffer(
",%s", NameOfXMMRegister(regop));
1427 }
else if (*data == 0xDB) {
1430 get_modrm(*data, &mod, ®op, &rm);
1431 AppendToBuffer(
"pand %s,%s",
1432 NameOfXMMRegister(regop),
1433 NameOfXMMRegister(rm));
1435 }
else if (*data == 0xE7) {
1438 get_modrm(*data, &mod, ®op, &rm);
1440 AppendToBuffer(
"movntdq ");
1441 data += PrintRightOperand(data);
1442 AppendToBuffer(
",%s", NameOfXMMRegister(regop));
1444 UnimplementedInstruction();
1446 }
else if (*data == 0xEF) {
1449 get_modrm(*data, &mod, ®op, &rm);
1450 AppendToBuffer(
"pxor %s,%s",
1451 NameOfXMMRegister(regop),
1452 NameOfXMMRegister(rm));
1454 }
else if (*data == 0xEB) {
1457 get_modrm(*data, &mod, ®op, &rm);
1458 AppendToBuffer(
"por %s,%s",
1459 NameOfXMMRegister(regop),
1460 NameOfXMMRegister(rm));
1463 UnimplementedInstruction();
1466 UnimplementedInstruction();
1473 get_modrm(*data, &mod, ®op, &rm);
1475 AppendToBuffer(
"dec_b ");
1476 data += PrintRightOperand(data);
1478 UnimplementedInstruction();
1484 AppendToBuffer(
"push 0x%x", *reinterpret_cast<int32_t*>(data+1));
1489 AppendToBuffer(
"push 0x%x", *reinterpret_cast<int8_t*>(data + 1));
1494 AppendToBuffer(
"test al,0x%x", *reinterpret_cast<uint8_t*>(data+1));
1499 AppendToBuffer(
"test eax,0x%x", *reinterpret_cast<int32_t*>(data+1));
1506 data += D1D3C1Instruction(data);
1517 data += FPUInstruction(data);
1521 data += JumpShort(data);
1525 if (*(data+1) == 0x0F) {
1526 byte b2 = *(data+2);
1528 AppendToBuffer(
"movsd ");
1531 get_modrm(*data, &mod, ®op, &rm);
1532 data += PrintRightXMMOperand(data);
1533 AppendToBuffer(
",%s", NameOfXMMRegister(regop));
1534 }
else if (b2 == 0x10) {
1537 get_modrm(*data, &mod, ®op, &rm);
1538 AppendToBuffer(
"movsd %s,", NameOfXMMRegister(regop));
1539 data += PrintRightXMMOperand(data);
1540 }
else if (b2 == 0x5A) {
1543 get_modrm(*data, &mod, ®op, &rm);
1544 AppendToBuffer(
"cvtsd2ss %s,", NameOfXMMRegister(regop));
1545 data += PrintRightXMMOperand(data);
1547 const char* mnem =
"?";
1549 case 0x2A: mnem =
"cvtsi2sd";
break;
1550 case 0x2C: mnem =
"cvttsd2si";
break;
1551 case 0x2D: mnem =
"cvtsd2si";
break;
1552 case 0x51: mnem =
"sqrtsd";
break;
1553 case 0x58: mnem =
"addsd";
break;
1554 case 0x59: mnem =
"mulsd";
break;
1555 case 0x5C: mnem =
"subsd";
break;
1556 case 0x5E: mnem =
"divsd";
break;
1560 get_modrm(*data, &mod, ®op, &rm);
1562 AppendToBuffer(
"%s %s,", mnem, NameOfXMMRegister(regop));
1563 data += PrintRightOperand(data);
1564 }
else if (b2 == 0x2C || b2 == 0x2D) {
1565 AppendToBuffer(
"%s %s,", mnem, NameOfCPURegister(regop));
1566 data += PrintRightXMMOperand(data);
1567 }
else if (b2 == 0xC2) {
1569 const char*
const pseudo_op[] = {
1579 AppendToBuffer(
"%s %s,%s",
1581 NameOfXMMRegister(regop),
1582 NameOfXMMRegister(rm));
1585 AppendToBuffer(
"%s %s,", mnem, NameOfXMMRegister(regop));
1586 data += PrintRightXMMOperand(data);
1590 UnimplementedInstruction();
1595 if (*(data+1) == 0x0F) {
1596 byte b2 = *(data+2);
1598 AppendToBuffer(
"movss ");
1601 get_modrm(*data, &mod, ®op, &rm);
1602 data += PrintRightXMMOperand(data);
1603 AppendToBuffer(
",%s", NameOfXMMRegister(regop));
1604 }
else if (b2 == 0x10) {
1607 get_modrm(*data, &mod, ®op, &rm);
1608 AppendToBuffer(
"movss %s,", NameOfXMMRegister(regop));
1609 data += PrintRightXMMOperand(data);
1610 }
else if (b2 == 0x2C) {
1613 get_modrm(*data, &mod, ®op, &rm);
1614 AppendToBuffer(
"cvttss2si %s,", NameOfCPURegister(regop));
1615 data += PrintRightXMMOperand(data);
1616 }
else if (b2 == 0x5A) {
1619 get_modrm(*data, &mod, ®op, &rm);
1620 AppendToBuffer(
"cvtss2sd %s,", NameOfXMMRegister(regop));
1621 data += PrintRightXMMOperand(data);
1622 }
else if (b2 == 0x6F) {
1625 get_modrm(*data, &mod, ®op, &rm);
1626 AppendToBuffer(
"movdqu %s,", NameOfXMMRegister(regop));
1627 data += PrintRightXMMOperand(data);
1628 }
else if (b2 == 0x7F) {
1629 AppendToBuffer(
"movdqu ");
1632 get_modrm(*data, &mod, ®op, &rm);
1633 data += PrintRightXMMOperand(data);
1634 AppendToBuffer(
",%s", NameOfXMMRegister(regop));
1636 UnimplementedInstruction();
1638 }
else if (*(data+1) == 0xA5) {
1640 AppendToBuffer(
"rep_movs");
1641 }
else if (*(data+1) == 0xAB) {
1643 AppendToBuffer(
"rep_stos");
1645 UnimplementedInstruction();
1650 data += F7Instruction(data);
1654 UnimplementedInstruction();
1658 if (tmp_buffer_pos_ <
sizeof tmp_buffer_) {
1659 tmp_buffer_[tmp_buffer_pos_] =
'\0';
1662 int instr_len = data - instr;
1663 if (instr_len == 0) {
1664 printf(
"%02x", *data);
1670 for (
byte* bp = instr; bp < data; bp++) {
1675 for (
int i = 6 - instr_len; i >= 0; i--) {
1682 tmp_buffer_.
start());
1690 static const char* cpu_regs[8] = {
1691 "eax",
"ecx",
"edx",
"ebx",
"esp",
"ebp",
"esi",
"edi"
1695 static const char* byte_cpu_regs[8] = {
1696 "al",
"cl",
"dl",
"bl",
"ah",
"ch",
"dh",
"bh"
1700 static const char* xmm_regs[8] = {
1701 "xmm0",
"xmm1",
"xmm2",
"xmm3",
"xmm4",
"xmm5",
"xmm6",
"xmm7"
1717 if (0 <= reg && reg < 8)
return cpu_regs[reg];
1723 if (0 <= reg && reg < 8)
return byte_cpu_regs[reg];
1729 if (0 <= reg && reg < 8)
return xmm_regs[reg];
1744 : converter_(converter) {}
1751 byte* instruction) {
1752 DisassemblerIA32 d(converter_,
false );
1753 return d.InstructionDecode(buffer, instruction);
1758 int Disassembler::ConstantPoolSizeAt(
byte* instruction) {
return -1; }
1761 void Disassembler::Disassemble(FILE* f,
byte* begin,
byte* end) {
1762 NameConverter converter;
1764 for (
byte*
pc = begin;
pc < end;) {
1768 pc += d.InstructionDecode(buffer,
pc);
1769 fprintf(f,
"%p", prev_pc);
1772 for (
byte* bp = prev_pc; bp <
pc; bp++) {
1773 fprintf(f,
"%02x", *bp);
1775 for (
int i = 6 - (pc - prev_pc); i >= 0; i--) {
1778 fprintf(f,
" %s\n", buffer.
start());
1785 #endif // V8_TARGET_ARCH_IA32
enable upcoming ES6 features enable harmony block scoping enable harmony enable harmony proxies enable harmony generators enable harmony numeric enable harmony string enable harmony math functions harmony_scoping harmony_symbols harmony_collections harmony_iteration harmony_strings harmony_scoping harmony_maths tracks arrays with only smi values Optimize object Array DOM strings and string pretenure call new trace pretenuring decisions of HAllocate instructions track fields with only smi values track fields with heap values track_fields track_fields Enables optimizations which favor memory size over execution speed use string slices optimization filter maximum number of GVN fix point iterations use function inlining use allocation folding eliminate write barriers targeting allocations in optimized code maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining crankshaft harvests type feedback from stub cache trace check elimination phase hydrogen tracing filter NULL
Disassembler(const NameConverter &converter)
static int VSNPrintF(Vector< char > str, const char *format, va_list args)
virtual const char * NameOfXMMRegister(int reg) const
v8::internal::EmbeddedVector< char, 128 > tmp_buffer_
virtual const char * NameOfConstant(byte *addr) const
#define ASSERT(condition)
virtual const char * NameInCode(byte *addr) const
virtual const char * NameOfByteCPURegister(int reg) const
virtual const char * NameOfCPURegister(int reg) const
virtual const char * NameOfAddress(byte *addr) const
static int SNPrintF(Vector< char > str, const char *format,...)
#define ASSERT_EQ(v1, v2)
#define ASSERT_NE(v1, v2)