34 #if V8_TARGET_ARCH_X64
44 REG_OPER_OP_ORDER = 1,
45 OPER_REG_OP_ORDER = 2,
47 BYTE_SIZE_OPERAND_FLAG = 4,
48 BYTE_REG_OPER_OP_ORDER = REG_OPER_OP_ORDER | BYTE_SIZE_OPERAND_FLAG,
49 BYTE_OPER_REG_OP_ORDER = OPER_REG_OP_ORDER | BYTE_SIZE_OPERAND_FLAG
58 OperandType op_order_;
63 static const ByteMnemonic two_operands_instr[] = {
64 { 0x00, BYTE_OPER_REG_OP_ORDER,
"add" },
65 { 0x01, OPER_REG_OP_ORDER,
"add" },
66 { 0x02, BYTE_REG_OPER_OP_ORDER,
"add" },
67 { 0x03, REG_OPER_OP_ORDER,
"add" },
68 { 0x08, BYTE_OPER_REG_OP_ORDER,
"or" },
69 { 0x09, OPER_REG_OP_ORDER,
"or" },
70 { 0x0A, BYTE_REG_OPER_OP_ORDER,
"or" },
71 { 0x0B, REG_OPER_OP_ORDER,
"or" },
72 { 0x10, BYTE_OPER_REG_OP_ORDER,
"adc" },
73 { 0x11, OPER_REG_OP_ORDER,
"adc" },
74 { 0x12, BYTE_REG_OPER_OP_ORDER,
"adc" },
75 { 0x13, REG_OPER_OP_ORDER,
"adc" },
76 { 0x18, BYTE_OPER_REG_OP_ORDER,
"sbb" },
77 { 0x19, OPER_REG_OP_ORDER,
"sbb" },
78 { 0x1A, BYTE_REG_OPER_OP_ORDER,
"sbb" },
79 { 0x1B, REG_OPER_OP_ORDER,
"sbb" },
80 { 0x20, BYTE_OPER_REG_OP_ORDER,
"and" },
81 { 0x21, OPER_REG_OP_ORDER,
"and" },
82 { 0x22, BYTE_REG_OPER_OP_ORDER,
"and" },
83 { 0x23, REG_OPER_OP_ORDER,
"and" },
84 { 0x28, BYTE_OPER_REG_OP_ORDER,
"sub" },
85 { 0x29, OPER_REG_OP_ORDER,
"sub" },
86 { 0x2A, BYTE_REG_OPER_OP_ORDER,
"sub" },
87 { 0x2B, REG_OPER_OP_ORDER,
"sub" },
88 { 0x30, BYTE_OPER_REG_OP_ORDER,
"xor" },
89 { 0x31, OPER_REG_OP_ORDER,
"xor" },
90 { 0x32, BYTE_REG_OPER_OP_ORDER,
"xor" },
91 { 0x33, REG_OPER_OP_ORDER,
"xor" },
92 { 0x38, BYTE_OPER_REG_OP_ORDER,
"cmp" },
93 { 0x39, OPER_REG_OP_ORDER,
"cmp" },
94 { 0x3A, BYTE_REG_OPER_OP_ORDER,
"cmp" },
95 { 0x3B, REG_OPER_OP_ORDER,
"cmp" },
96 { 0x63, REG_OPER_OP_ORDER,
"movsxl" },
97 { 0x84, BYTE_REG_OPER_OP_ORDER,
"test" },
98 { 0x85, REG_OPER_OP_ORDER,
"test" },
99 { 0x86, BYTE_REG_OPER_OP_ORDER,
"xchg" },
100 { 0x87, REG_OPER_OP_ORDER,
"xchg" },
101 { 0x88, BYTE_OPER_REG_OP_ORDER,
"mov" },
102 { 0x89, OPER_REG_OP_ORDER,
"mov" },
103 { 0x8A, BYTE_REG_OPER_OP_ORDER,
"mov" },
104 { 0x8B, REG_OPER_OP_ORDER,
"mov" },
105 { 0x8D, REG_OPER_OP_ORDER,
"lea" },
106 { -1, UNSET_OP_ORDER,
"" }
110 static const ByteMnemonic zero_operands_instr[] = {
111 { 0xC3, UNSET_OP_ORDER,
"ret" },
112 { 0xC9, UNSET_OP_ORDER,
"leave" },
113 { 0xF4, UNSET_OP_ORDER,
"hlt" },
114 { 0xFC, UNSET_OP_ORDER,
"cld" },
115 { 0xCC, UNSET_OP_ORDER,
"int3" },
116 { 0x60, UNSET_OP_ORDER,
"pushad" },
117 { 0x61, UNSET_OP_ORDER,
"popad" },
118 { 0x9C, UNSET_OP_ORDER,
"pushfd" },
119 { 0x9D, UNSET_OP_ORDER,
"popfd" },
120 { 0x9E, UNSET_OP_ORDER,
"sahf" },
121 { 0x99, UNSET_OP_ORDER,
"cdq" },
122 { 0x9B, UNSET_OP_ORDER,
"fwait" },
123 { 0xA4, UNSET_OP_ORDER,
"movs" },
124 { 0xA5, UNSET_OP_ORDER,
"movs" },
125 { 0xA6, UNSET_OP_ORDER,
"cmps" },
126 { 0xA7, UNSET_OP_ORDER,
"cmps" },
127 { -1, UNSET_OP_ORDER,
"" }
131 static const ByteMnemonic call_jump_instr[] = {
132 { 0xE8, UNSET_OP_ORDER,
"call" },
133 { 0xE9, UNSET_OP_ORDER,
"jmp" },
134 { -1, UNSET_OP_ORDER,
"" }
138 static const ByteMnemonic short_immediate_instr[] = {
139 { 0x05, UNSET_OP_ORDER,
"add" },
140 { 0x0D, UNSET_OP_ORDER,
"or" },
141 { 0x15, UNSET_OP_ORDER,
"adc" },
142 { 0x1D, UNSET_OP_ORDER,
"sbb" },
143 { 0x25, UNSET_OP_ORDER,
"and" },
144 { 0x2D, UNSET_OP_ORDER,
"sub" },
145 { 0x35, UNSET_OP_ORDER,
"xor" },
146 { 0x3D, UNSET_OP_ORDER,
"cmp" },
147 { -1, UNSET_OP_ORDER,
"" }
151 static const char*
const conditional_code_suffix[] = {
152 "o",
"no",
"c",
"nc",
"z",
"nz",
"na",
"a",
153 "s",
"ns",
"pe",
"po",
"l",
"ge",
"le",
"g"
157 enum InstructionType {
161 JUMP_CONDITIONAL_SHORT_INSTR,
166 SHORT_IMMEDIATE_INSTR
171 ESCAPE_PREFIX = 0x0F,
172 OPERAND_SIZE_OVERRIDE_PREFIX = 0x66,
173 ADDRESS_SIZE_OVERRIDE_PREFIX = 0x67,
176 REPEQ_PREFIX = REP_PREFIX
180 struct InstructionDesc {
182 InstructionType type;
183 OperandType op_order_;
184 bool byte_size_operation;
188 class InstructionTable {
191 const InstructionDesc& Get(
byte x)
const {
192 return instructions_[x];
196 InstructionDesc instructions_[256];
199 void CopyTable(
const ByteMnemonic bm[], InstructionType type);
200 void SetTableRange(InstructionType type,
byte start,
byte end,
bool byte_size,
202 void AddJumpConditionalShort();
206 InstructionTable::InstructionTable() {
212 void InstructionTable::Clear() {
213 for (
int i = 0; i < 256; i++) {
214 instructions_[i].mnem =
"(bad)";
215 instructions_[i].type = NO_INSTR;
216 instructions_[i].op_order_ = UNSET_OP_ORDER;
217 instructions_[i].byte_size_operation =
false;
222 void InstructionTable::Init() {
223 CopyTable(two_operands_instr, TWO_OPERANDS_INSTR);
224 CopyTable(zero_operands_instr, ZERO_OPERANDS_INSTR);
225 CopyTable(call_jump_instr, CALL_JUMP_INSTR);
226 CopyTable(short_immediate_instr, SHORT_IMMEDIATE_INSTR);
227 AddJumpConditionalShort();
228 SetTableRange(PUSHPOP_INSTR, 0x50, 0x57,
false,
"push");
229 SetTableRange(PUSHPOP_INSTR, 0x58, 0x5F,
false,
"pop");
230 SetTableRange(MOVE_REG_INSTR, 0xB8, 0xBF,
false,
"mov");
234 void InstructionTable::CopyTable(
const ByteMnemonic bm[],
235 InstructionType type) {
236 for (
int i = 0; bm[i].b >= 0; i++) {
237 InstructionDesc*
id = &instructions_[bm[i].b];
238 id->mnem = bm[i].mnem;
239 OperandType op_order = bm[i].op_order_;
241 static_cast<OperandType
>(op_order & ~BYTE_SIZE_OPERAND_FLAG);
244 id->byte_size_operation = ((op_order & BYTE_SIZE_OPERAND_FLAG) != 0);
249 void InstructionTable::SetTableRange(InstructionType type,
254 for (
byte b = start; b <= end; b++) {
255 InstructionDesc*
id = &instructions_[b];
259 id->byte_size_operation = byte_size;
264 void InstructionTable::AddJumpConditionalShort() {
265 for (
byte b = 0x70; b <= 0x7F; b++) {
266 InstructionDesc*
id = &instructions_[b];
269 id->type = JUMP_CONDITIONAL_SHORT_INSTR;
278 static InstructionDesc cmov_instructions[16] = {
279 {
"cmovo", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER,
false},
280 {
"cmovno", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER,
false},
281 {
"cmovc", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER,
false},
282 {
"cmovnc", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER,
false},
283 {
"cmovz", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER,
false},
284 {
"cmovnz", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER,
false},
285 {
"cmovna", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER,
false},
286 {
"cmova", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER,
false},
287 {
"cmovs", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER,
false},
288 {
"cmovns", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER,
false},
289 {
"cmovpe", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER,
false},
290 {
"cmovpo", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER,
false},
291 {
"cmovl", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER,
false},
292 {
"cmovge", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER,
false},
293 {
"cmovle", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER,
false},
294 {
"cmovg", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER,
false}
301 enum UnimplementedOpcodeAction {
302 CONTINUE_ON_UNIMPLEMENTED_OPCODE,
303 ABORT_ON_UNIMPLEMENTED_OPCODE
309 class DisassemblerX64 {
311 DisassemblerX64(
const NameConverter& converter,
312 UnimplementedOpcodeAction unimplemented_action =
313 ABORT_ON_UNIMPLEMENTED_OPCODE)
314 : converter_(converter),
316 abort_on_unimplemented_(
317 unimplemented_action == ABORT_ON_UNIMPLEMENTED_OPCODE),
321 byte_size_operand_(
false),
322 instruction_table_(instruction_table.Pointer()) {
323 tmp_buffer_[0] =
'\0';
326 virtual ~DisassemblerX64() {
335 OPERAND_BYTE_SIZE = 0,
336 OPERAND_WORD_SIZE = 1,
337 OPERAND_DOUBLEWORD_SIZE = 2,
338 OPERAND_QUADWORD_SIZE = 3
341 const NameConverter& converter_;
343 unsigned int tmp_buffer_pos_;
344 bool abort_on_unimplemented_;
348 byte group_1_prefix_;
350 bool byte_size_operand_;
351 const InstructionTable*
const instruction_table_;
353 void setRex(
byte rex) {
358 bool rex() {
return rex_ != 0; }
360 bool rex_b() {
return (rex_ & 0x01) != 0; }
363 int base_reg(
int low_bits) {
return low_bits | ((rex_ & 0x01) << 3); }
365 bool rex_x() {
return (rex_ & 0x02) != 0; }
367 bool rex_r() {
return (rex_ & 0x04) != 0; }
369 bool rex_w() {
return (rex_ & 0x08) != 0; }
371 OperandSize operand_size() {
372 if (byte_size_operand_)
return OPERAND_BYTE_SIZE;
373 if (rex_w())
return OPERAND_QUADWORD_SIZE;
374 if (operand_size_ != 0)
return OPERAND_WORD_SIZE;
375 return OPERAND_DOUBLEWORD_SIZE;
378 char operand_size_code() {
379 return "bwlq"[operand_size()];
382 const char* NameOfCPURegister(
int reg)
const {
383 return converter_.NameOfCPURegister(reg);
386 const char* NameOfByteCPURegister(
int reg)
const {
387 return converter_.NameOfByteCPURegister(reg);
390 const char* NameOfXMMRegister(
int reg)
const {
391 return converter_.NameOfXMMRegister(reg);
394 const char* NameOfAddress(
byte* addr)
const {
395 return converter_.NameOfAddress(addr);
399 void get_modrm(
byte data,
403 *mod = (data >> 6) & 3;
404 *regop = ((data & 0x38) >> 3) | (rex_r() ? 8 : 0);
405 *rm = (data & 7) | (rex_b() ? 8 : 0);
408 void get_sib(
byte data,
412 *scale = (data >> 6) & 3;
413 *index = ((data >> 3) & 7) | (rex_x() ? 8 : 0);
414 *base = (data & 7) | (rex_b() ? 8 : 0);
417 typedef const char* (DisassemblerX64::*RegisterNameMapping)(
int reg)
const;
419 int PrintRightOperandHelper(
byte* modrmp,
420 RegisterNameMapping register_name);
421 int PrintRightOperand(
byte* modrmp);
422 int PrintRightByteOperand(
byte* modrmp);
423 int PrintRightXMMOperand(
byte* modrmp);
424 int PrintOperands(
const char* mnem,
425 OperandType op_order,
427 int PrintImmediate(
byte* data, OperandSize
size);
428 int PrintImmediateOp(
byte* data);
429 const char* TwoByteMnemonic(
byte opcode);
430 int TwoByteOpcodeInstruction(
byte* data);
431 int F6F7Instruction(
byte* data);
432 int ShiftInstruction(
byte* data);
433 int JumpShort(
byte* data);
434 int JumpConditional(
byte* data);
435 int JumpConditionalShort(
byte* data);
437 int FPUInstruction(
byte* data);
438 int MemoryFPUInstruction(
int escape_opcode,
int regop,
byte* modrm_start);
439 int RegisterFPUInstruction(
int escape_opcode,
byte modrm_byte);
440 void AppendToBuffer(
const char* format, ...);
442 void UnimplementedInstruction() {
443 if (abort_on_unimplemented_) {
446 AppendToBuffer(
"'Unimplemented Instruction'");
452 void DisassemblerX64::AppendToBuffer(
const char* format, ...) {
455 va_start(args, format);
458 tmp_buffer_pos_ += result;
462 int DisassemblerX64::PrintRightOperandHelper(
464 RegisterNameMapping direct_register_name) {
466 get_modrm(*modrmp, &mod, ®op, &rm);
467 RegisterNameMapping register_name = (mod == 3) ? direct_register_name :
468 &DisassemblerX64::NameOfCPURegister;
473 AppendToBuffer(
"[0x%x]", disp);
475 }
else if ((rm & 7) == 4) {
477 byte sib = *(modrmp + 1);
478 int scale, index, base;
479 get_sib(sib, &scale, &index, &base);
480 if (index == 4 && (base & 7) == 4 && scale == 0 ) {
483 AppendToBuffer(
"[%s]", NameOfCPURegister(base));
485 }
else if (base == 5) {
488 AppendToBuffer(
"[%s*%d%s0x%x]",
489 NameOfCPURegister(index),
491 disp < 0 ?
"-" :
"+",
492 disp < 0 ? -disp : disp);
494 }
else if (index != 4 && base != 5) {
496 AppendToBuffer(
"[%s+%s*%d]",
497 NameOfCPURegister(base),
498 NameOfCPURegister(index),
502 UnimplementedInstruction();
506 AppendToBuffer(
"[%s]", NameOfCPURegister(rm));
513 byte sib = *(modrmp + 1);
514 int scale, index, base;
515 get_sib(sib, &scale, &index, &base);
516 int disp = (mod == 2) ? *reinterpret_cast<int32_t*>(modrmp + 2)
517 : *
reinterpret_cast<int8_t*
>(modrmp + 2);
518 if (index == 4 && (base & 7) == 4 && scale == 0 ) {
519 AppendToBuffer(
"[%s%s0x%x]",
520 NameOfCPURegister(base),
521 disp < 0 ?
"-" :
"+",
522 disp < 0 ? -disp : disp);
524 AppendToBuffer(
"[%s+%s*%d%s0x%x]",
525 NameOfCPURegister(base),
526 NameOfCPURegister(index),
528 disp < 0 ?
"-" :
"+",
529 disp < 0 ? -disp : disp);
531 return mod == 2 ? 6 : 3;
534 int disp = (mod == 2) ? *reinterpret_cast<int32_t*>(modrmp + 1)
535 : *
reinterpret_cast<int8_t*
>(modrmp + 1);
536 AppendToBuffer(
"[%s%s0x%x]",
537 NameOfCPURegister(rm),
538 disp < 0 ?
"-" :
"+",
539 disp < 0 ? -disp : disp);
540 return (mod == 2) ? 5 : 2;
544 AppendToBuffer(
"%s", (this->*register_name)(rm));
547 UnimplementedInstruction();
554 int DisassemblerX64::PrintImmediate(
byte* data, OperandSize
size) {
558 case OPERAND_BYTE_SIZE:
562 case OPERAND_WORD_SIZE:
563 value = *
reinterpret_cast<int16_t*
>(data);
566 case OPERAND_DOUBLEWORD_SIZE:
567 value = *
reinterpret_cast<uint32_t*
>(data);
570 case OPERAND_QUADWORD_SIZE:
571 value = *
reinterpret_cast<int32_t*
>(data);
584 int DisassemblerX64::PrintRightOperand(
byte* modrmp) {
585 return PrintRightOperandHelper(modrmp,
586 &DisassemblerX64::NameOfCPURegister);
590 int DisassemblerX64::PrintRightByteOperand(
byte* modrmp) {
591 return PrintRightOperandHelper(modrmp,
592 &DisassemblerX64::NameOfByteCPURegister);
596 int DisassemblerX64::PrintRightXMMOperand(
byte* modrmp) {
597 return PrintRightOperandHelper(modrmp,
598 &DisassemblerX64::NameOfXMMRegister);
604 int DisassemblerX64::PrintOperands(
const char* mnem,
605 OperandType op_order,
609 get_modrm(modrm, &mod, ®op, &rm);
611 const char* register_name =
612 byte_size_operand_ ? NameOfByteCPURegister(regop)
613 : NameOfCPURegister(regop);
615 case REG_OPER_OP_ORDER: {
616 AppendToBuffer(
"%s%c %s,",
620 advance = byte_size_operand_ ? PrintRightByteOperand(data)
621 : PrintRightOperand(data);
624 case OPER_REG_OP_ORDER: {
625 AppendToBuffer(
"%s%c ", mnem, operand_size_code());
626 advance = byte_size_operand_ ? PrintRightByteOperand(data)
627 : PrintRightOperand(data);
628 AppendToBuffer(
",%s", register_name);
641 int DisassemblerX64::PrintImmediateOp(
byte* data) {
642 bool byte_size_immediate = (*data & 0x02) != 0;
643 byte modrm = *(data + 1);
645 get_modrm(modrm, &mod, ®op, &rm);
646 const char* mnem =
"Imm???";
673 UnimplementedInstruction();
675 AppendToBuffer(
"%s%c ", mnem, operand_size_code());
676 int count = PrintRightOperand(data + 1);
677 AppendToBuffer(
",0x");
678 OperandSize immediate_size =
679 byte_size_immediate ? OPERAND_BYTE_SIZE : operand_size();
680 count += PrintImmediate(data + 1 + count, immediate_size);
686 int DisassemblerX64::F6F7Instruction(
byte* data) {
687 ASSERT(*data == 0xF7 || *data == 0xF6);
688 byte modrm = *(data + 1);
690 get_modrm(modrm, &mod, ®op, &rm);
691 if (mod == 3 && regop != 0) {
692 const char* mnem =
NULL;
710 UnimplementedInstruction();
712 AppendToBuffer(
"%s%c %s",
715 NameOfCPURegister(rm));
717 }
else if (regop == 0) {
718 AppendToBuffer(
"test%c ", operand_size_code());
719 int count = PrintRightOperand(data + 1);
720 AppendToBuffer(
",0x");
721 count += PrintImmediate(data + 1 + count, operand_size());
724 UnimplementedInstruction();
730 int DisassemblerX64::ShiftInstruction(
byte* data) {
731 byte op = *data & (~1);
732 if (op != 0xD0 && op != 0xD2 && op != 0xC0) {
733 UnimplementedInstruction();
736 byte modrm = *(data + 1);
738 get_modrm(modrm, &mod, ®op, &rm);
743 UnimplementedInstruction();
746 const char* mnem =
NULL;
770 UnimplementedInstruction();
776 }
else if (op == 0xC0) {
780 AppendToBuffer(
"%s%c %s,",
783 byte_size_operand_ ? NameOfByteCPURegister(rm)
784 : NameOfCPURegister(rm));
786 AppendToBuffer(
"cl");
788 AppendToBuffer(
"%d", imm8);
795 int DisassemblerX64::JumpShort(
byte* data) {
797 byte b = *(data + 1);
798 byte* dest = data +
static_cast<int8_t
>(b) + 2;
799 AppendToBuffer(
"jmp %s", NameOfAddress(dest));
805 int DisassemblerX64::JumpConditional(
byte* data) {
807 byte cond = *(data + 1) & 0x0F;
808 byte* dest = data + *
reinterpret_cast<int32_t*
>(data + 2) + 6;
809 const char* mnem = conditional_code_suffix[cond];
810 AppendToBuffer(
"j%s %s", mnem, NameOfAddress(dest));
816 int DisassemblerX64::JumpConditionalShort(
byte* data) {
817 byte cond = *data & 0x0F;
818 byte b = *(data + 1);
819 byte* dest = data +
static_cast<int8_t
>(b) + 2;
820 const char* mnem = conditional_code_suffix[cond];
821 AppendToBuffer(
"j%s %s", mnem, NameOfAddress(dest));
829 byte cond = *(data + 1) & 0x0F;
830 const char* mnem = conditional_code_suffix[cond];
831 AppendToBuffer(
"set%s%c ", mnem, operand_size_code());
832 PrintRightByteOperand(data + 2);
838 int DisassemblerX64::FPUInstruction(
byte* data) {
839 byte escape_opcode = *data;
841 byte modrm_byte = *(data+1);
843 if (modrm_byte >= 0xC0) {
844 return RegisterFPUInstruction(escape_opcode, modrm_byte);
846 return MemoryFPUInstruction(escape_opcode, modrm_byte, data+1);
850 int DisassemblerX64::MemoryFPUInstruction(
int escape_opcode,
853 const char* mnem =
"?";
854 int regop = (modrm_byte >> 3) & 0x7;
855 switch (escape_opcode) {
856 case 0xD9:
switch (regop) {
857 case 0: mnem =
"fld_s";
break;
858 case 3: mnem =
"fstp_s";
break;
859 case 7: mnem =
"fstcw";
break;
860 default: UnimplementedInstruction();
864 case 0xDB:
switch (regop) {
865 case 0: mnem =
"fild_s";
break;
866 case 1: mnem =
"fisttp_s";
break;
867 case 2: mnem =
"fist_s";
break;
868 case 3: mnem =
"fistp_s";
break;
869 default: UnimplementedInstruction();
873 case 0xDD:
switch (regop) {
874 case 0: mnem =
"fld_d";
break;
875 case 3: mnem =
"fstp_d";
break;
876 default: UnimplementedInstruction();
880 case 0xDF:
switch (regop) {
881 case 5: mnem =
"fild_d";
break;
882 case 7: mnem =
"fistp_d";
break;
883 default: UnimplementedInstruction();
887 default: UnimplementedInstruction();
889 AppendToBuffer(
"%s ", mnem);
890 int count = PrintRightOperand(modrm_start);
894 int DisassemblerX64::RegisterFPUInstruction(
int escape_opcode,
896 bool has_register =
false;
897 const char* mnem =
"?";
899 switch (escape_opcode) {
901 UnimplementedInstruction();
905 switch (modrm_byte & 0xF8) {
915 switch (modrm_byte) {
916 case 0xE0: mnem =
"fchs";
break;
917 case 0xE1: mnem =
"fabs";
break;
918 case 0xE3: mnem =
"fninit";
break;
919 case 0xE4: mnem =
"ftst";
break;
920 case 0xE8: mnem =
"fld1";
break;
921 case 0xEB: mnem =
"fldpi";
break;
922 case 0xED: mnem =
"fldln2";
break;
923 case 0xEE: mnem =
"fldz";
break;
924 case 0xF0: mnem =
"f2xm1";
break;
925 case 0xF1: mnem =
"fyl2x";
break;
926 case 0xF2: mnem =
"fptan";
break;
927 case 0xF5: mnem =
"fprem1";
break;
928 case 0xF7: mnem =
"fincstp";
break;
929 case 0xF8: mnem =
"fprem";
break;
930 case 0xFC: mnem =
"frndint";
break;
931 case 0xFD: mnem =
"fscale";
break;
932 case 0xFE: mnem =
"fsin";
break;
933 case 0xFF: mnem =
"fcos";
break;
934 default: UnimplementedInstruction();
940 if (modrm_byte == 0xE9) {
943 UnimplementedInstruction();
948 if ((modrm_byte & 0xF8) == 0xE8) {
951 }
else if (modrm_byte == 0xE2) {
953 }
else if (modrm_byte == 0xE3) {
956 UnimplementedInstruction();
962 switch (modrm_byte & 0xF8) {
963 case 0xC0: mnem =
"fadd";
break;
964 case 0xE8: mnem =
"fsub";
break;
965 case 0xC8: mnem =
"fmul";
break;
966 case 0xF8: mnem =
"fdiv";
break;
967 default: UnimplementedInstruction();
973 switch (modrm_byte & 0xF8) {
974 case 0xC0: mnem =
"ffree";
break;
975 case 0xD8: mnem =
"fstp";
break;
976 default: UnimplementedInstruction();
981 if (modrm_byte == 0xD9) {
985 switch (modrm_byte & 0xF8) {
986 case 0xC0: mnem =
"faddp";
break;
987 case 0xE8: mnem =
"fsubp";
break;
988 case 0xC8: mnem =
"fmulp";
break;
989 case 0xF8: mnem =
"fdivp";
break;
990 default: UnimplementedInstruction();
996 if (modrm_byte == 0xE0) {
998 }
else if ((modrm_byte & 0xF8) == 0xE8) {
1000 has_register =
true;
1004 default: UnimplementedInstruction();
1008 AppendToBuffer(
"%s st%d", mnem, modrm_byte & 0x7);
1010 AppendToBuffer(
"%s", mnem);
1020 int DisassemblerX64::TwoByteOpcodeInstruction(
byte* data) {
1021 byte opcode = *(data + 1);
1022 byte* current = data + 2;
1024 const char* mnemonic = TwoByteMnemonic(opcode);
1025 if (operand_size_ == 0x66) {
1028 if (opcode == 0x3A) {
1029 byte third_byte = *current;
1031 if (third_byte == 0x17) {
1032 get_modrm(*current, &mod, ®op, &rm);
1033 AppendToBuffer(
"extractps ");
1034 current += PrintRightOperand(current);
1035 AppendToBuffer(
",%s,%d", NameOfXMMRegister(regop), (*current) & 3);
1037 }
else if (third_byte == 0x0b) {
1038 get_modrm(*current, &mod, ®op, &rm);
1040 AppendToBuffer(
"roundsd %s,", NameOfXMMRegister(regop));
1041 current += PrintRightXMMOperand(current);
1042 AppendToBuffer(
",%d", (*current) & 3);
1045 UnimplementedInstruction();
1048 get_modrm(*current, &mod, ®op, &rm);
1049 if (opcode == 0x1f) {
1056 }
else if (mod == 2) {
1059 AppendToBuffer(
"nop");
1060 }
else if (opcode == 0x28) {
1061 AppendToBuffer(
"movapd %s,", NameOfXMMRegister(regop));
1062 current += PrintRightXMMOperand(current);
1063 }
else if (opcode == 0x29) {
1064 AppendToBuffer(
"movapd ");
1065 current += PrintRightXMMOperand(current);
1066 AppendToBuffer(
",%s", NameOfXMMRegister(regop));
1067 }
else if (opcode == 0x6E) {
1068 AppendToBuffer(
"mov%c %s,",
1069 rex_w() ?
'q' :
'd',
1070 NameOfXMMRegister(regop));
1071 current += PrintRightOperand(current);
1072 }
else if (opcode == 0x6F) {
1073 AppendToBuffer(
"movdqa %s,",
1074 NameOfXMMRegister(regop));
1075 current += PrintRightXMMOperand(current);
1076 }
else if (opcode == 0x7E) {
1077 AppendToBuffer(
"mov%c ",
1078 rex_w() ?
'q' :
'd');
1079 current += PrintRightOperand(current);
1080 AppendToBuffer(
",%s", NameOfXMMRegister(regop));
1081 }
else if (opcode == 0x7F) {
1082 AppendToBuffer(
"movdqa ");
1083 current += PrintRightXMMOperand(current);
1084 AppendToBuffer(
",%s", NameOfXMMRegister(regop));
1085 }
else if (opcode == 0xD6) {
1086 AppendToBuffer(
"movq ");
1087 current += PrintRightXMMOperand(current);
1088 AppendToBuffer(
",%s", NameOfXMMRegister(regop));
1089 }
else if (opcode == 0x50) {
1090 AppendToBuffer(
"movmskpd %s,", NameOfCPURegister(regop));
1091 current += PrintRightXMMOperand(current);
1092 }
else if (opcode == 0x73) {
1095 AppendToBuffer(
"psllq,%s,%d", NameOfXMMRegister(rm), *current & 0x7f);
1098 const char* mnemonic =
"?";
1099 if (opcode == 0x54) {
1101 }
else if (opcode == 0x56) {
1103 }
else if (opcode == 0x57) {
1105 }
else if (opcode == 0x2E) {
1106 mnemonic =
"ucomisd";
1107 }
else if (opcode == 0x2F) {
1108 mnemonic =
"comisd";
1110 UnimplementedInstruction();
1112 AppendToBuffer(
"%s %s,", mnemonic, NameOfXMMRegister(regop));
1113 current += PrintRightXMMOperand(current);
1116 }
else if (group_1_prefix_ == 0xF2) {
1119 if (opcode == 0x11 || opcode == 0x10) {
1121 AppendToBuffer(
"movsd ");
1123 get_modrm(*current, &mod, ®op, &rm);
1124 if (opcode == 0x11) {
1125 current += PrintRightXMMOperand(current);
1126 AppendToBuffer(
",%s", NameOfXMMRegister(regop));
1128 AppendToBuffer(
"%s,", NameOfXMMRegister(regop));
1129 current += PrintRightXMMOperand(current);
1131 }
else if (opcode == 0x2A) {
1134 get_modrm(*current, &mod, ®op, &rm);
1135 AppendToBuffer(
"%sd %s,", mnemonic, NameOfXMMRegister(regop));
1136 current += PrintRightOperand(current);
1137 }
else if (opcode == 0x2C) {
1141 get_modrm(*current, &mod, ®op, &rm);
1142 AppendToBuffer(
"cvttsd2si%c %s,",
1143 operand_size_code(), NameOfCPURegister(regop));
1144 current += PrintRightXMMOperand(current);
1145 }
else if (opcode == 0x2D) {
1148 get_modrm(*current, &mod, ®op, &rm);
1149 AppendToBuffer(
"cvtsd2si%c %s,",
1150 operand_size_code(), NameOfCPURegister(regop));
1151 current += PrintRightXMMOperand(current);
1152 }
else if ((opcode & 0xF8) == 0x58 || opcode == 0x51) {
1155 get_modrm(*current, &mod, ®op, &rm);
1156 AppendToBuffer(
"%s %s,", mnemonic, NameOfXMMRegister(regop));
1157 current += PrintRightXMMOperand(current);
1158 }
else if (opcode == 0xC2) {
1161 get_modrm(*current, &mod, ®op, &rm);
1162 const char*
const pseudo_op[] = {
1172 AppendToBuffer(
"%s %s,%s",
1173 pseudo_op[current[1]],
1174 NameOfXMMRegister(regop),
1175 NameOfXMMRegister(rm));
1178 UnimplementedInstruction();
1180 }
else if (group_1_prefix_ == 0xF3) {
1182 if (opcode == 0x11 || opcode == 0x10) {
1184 AppendToBuffer(
"movss ");
1186 get_modrm(*current, &mod, ®op, &rm);
1187 if (opcode == 0x11) {
1188 current += PrintRightOperand(current);
1189 AppendToBuffer(
",%s", NameOfXMMRegister(regop));
1191 AppendToBuffer(
"%s,", NameOfXMMRegister(regop));
1192 current += PrintRightOperand(current);
1194 }
else if (opcode == 0x2A) {
1197 get_modrm(*current, &mod, ®op, &rm);
1198 AppendToBuffer(
"%ss %s,", mnemonic, NameOfXMMRegister(regop));
1199 current += PrintRightOperand(current);
1200 }
else if (opcode == 0x2C) {
1204 get_modrm(*current, &mod, ®op, &rm);
1205 AppendToBuffer(
"cvttss2si%c %s,",
1206 operand_size_code(), NameOfCPURegister(regop));
1207 current += PrintRightXMMOperand(current);
1208 }
else if (opcode == 0x5A) {
1212 get_modrm(*current, &mod, ®op, &rm);
1213 AppendToBuffer(
"cvtss2sd %s,", NameOfXMMRegister(regop));
1214 current += PrintRightXMMOperand(current);
1215 }
else if (opcode == 0x7E) {
1217 get_modrm(*current, &mod, ®op, &rm);
1218 AppendToBuffer(
"movq %s,", NameOfXMMRegister(regop));
1219 current += PrintRightXMMOperand(current);
1221 UnimplementedInstruction();
1223 }
else if (opcode == 0x1F) {
1226 get_modrm(*current, &mod, ®op, &rm);
1233 }
else if (mod == 2) {
1236 AppendToBuffer(
"nop");
1238 }
else if (opcode == 0x28) {
1241 get_modrm(*current, &mod, ®op, &rm);
1242 AppendToBuffer(
"movaps %s,", NameOfXMMRegister(regop));
1243 current += PrintRightXMMOperand(current);
1245 }
else if (opcode == 0x29) {
1248 get_modrm(*current, &mod, ®op, &rm);
1249 AppendToBuffer(
"movaps ");
1250 current += PrintRightXMMOperand(current);
1251 AppendToBuffer(
",%s", NameOfXMMRegister(regop));
1253 }
else if (opcode == 0xA2) {
1255 AppendToBuffer(
"%s", mnemonic);
1257 }
else if ((opcode & 0xF0) == 0x40) {
1259 int condition = opcode & 0x0F;
1260 const InstructionDesc& idesc = cmov_instructions[condition];
1261 byte_size_operand_ = idesc.byte_size_operation;
1262 current += PrintOperands(idesc.mnem, idesc.op_order_, current);
1264 }
else if (opcode >= 0x53 && opcode <= 0x5F) {
1265 const char*
const pseudo_op[] = {
1281 get_modrm(*current, &mod, ®op, &rm);
1282 AppendToBuffer(
"%s %s,",
1283 pseudo_op[opcode - 0x53],
1284 NameOfXMMRegister(regop));
1285 current += PrintRightXMMOperand(current);
1287 }
else if (opcode == 0xC6) {
1290 get_modrm(*current, &mod, ®op, &rm);
1291 AppendToBuffer(
"shufps %s, ", NameOfXMMRegister(regop));
1292 current += PrintRightXMMOperand(current);
1293 AppendToBuffer(
", %d", (*current) & 3);
1296 }
else if (opcode == 0x50) {
1299 get_modrm(*current, &mod, ®op, &rm);
1300 AppendToBuffer(
"movmskps %s,", NameOfCPURegister(regop));
1301 current += PrintRightXMMOperand(current);
1303 }
else if ((opcode & 0xF0) == 0x80) {
1305 current = data + JumpConditional(data);
1307 }
else if (opcode == 0xBE || opcode == 0xBF || opcode == 0xB6 ||
1308 opcode == 0xB7 || opcode == 0xAF) {
1310 current += PrintOperands(mnemonic, REG_OPER_OP_ORDER, current);
1312 }
else if ((opcode & 0xF0) == 0x90) {
1314 current = data +
SetCC(data);
1316 }
else if (opcode == 0xAB || opcode == 0xA5 || opcode == 0xAD) {
1318 AppendToBuffer(
"%s ", mnemonic);
1320 get_modrm(*current, &mod, ®op, &rm);
1321 current += PrintRightOperand(current);
1322 if (opcode == 0xAB) {
1323 AppendToBuffer(
",%s", NameOfCPURegister(regop));
1325 AppendToBuffer(
",%s,cl", NameOfCPURegister(regop));
1327 }
else if (opcode == 0xBD) {
1328 AppendToBuffer(
"%s%c ", mnemonic, operand_size_code());
1330 get_modrm(*current, &mod, ®op, &rm);
1331 AppendToBuffer(
"%s,", NameOfCPURegister(regop));
1332 current += PrintRightOperand(current);
1334 UnimplementedInstruction();
1336 return static_cast<int>(current - data);
1343 const char* DisassemblerX64::TwoByteMnemonic(
byte opcode) {
1390 tmp_buffer_pos_ = 0;
1392 bool processed =
true;
1399 if (current == OPERAND_SIZE_OVERRIDE_PREFIX) {
1400 operand_size_ = current;
1401 }
else if ((current & 0xF0) == 0x40) {
1403 if (rex_w()) AppendToBuffer(
"REX.W ");
1404 }
else if ((current & 0xFE) == 0xF2) {
1405 group_1_prefix_ = current;
1412 const InstructionDesc& idesc = instruction_table_->Get(current);
1413 byte_size_operand_ = idesc.byte_size_operation;
1414 switch (idesc.type) {
1415 case ZERO_OPERANDS_INSTR:
1416 if (current >= 0xA4 && current <= 0xA7) {
1418 if (group_1_prefix_ == REP_PREFIX) {
1420 AppendToBuffer(
"rep ");
1422 if (rex_w()) AppendToBuffer(
"REX.W ");
1423 AppendToBuffer(
"%s%c", idesc.mnem, operand_size_code());
1425 AppendToBuffer(
"%s", idesc.mnem, operand_size_code());
1430 case TWO_OPERANDS_INSTR:
1432 data += PrintOperands(idesc.mnem, idesc.op_order_, data);
1435 case JUMP_CONDITIONAL_SHORT_INSTR:
1436 data += JumpConditionalShort(data);
1439 case REGISTER_INSTR:
1440 AppendToBuffer(
"%s%c %s",
1442 operand_size_code(),
1443 NameOfCPURegister(base_reg(current & 0x07)));
1447 AppendToBuffer(
"%s %s",
1449 NameOfCPURegister(base_reg(current & 0x07)));
1452 case MOVE_REG_INSTR: {
1454 switch (operand_size()) {
1455 case OPERAND_WORD_SIZE:
1456 addr =
reinterpret_cast<byte*
>(*
reinterpret_cast<int16_t*
>(data + 1));
1459 case OPERAND_DOUBLEWORD_SIZE:
1461 reinterpret_cast<byte*
>(*
reinterpret_cast<uint32_t*
>(data + 1));
1464 case OPERAND_QUADWORD_SIZE:
1465 addr =
reinterpret_cast<byte*
>(*
reinterpret_cast<int64_t*
>(data + 1));
1471 AppendToBuffer(
"mov%c %s,%s",
1472 operand_size_code(),
1473 NameOfCPURegister(base_reg(current & 0x07)),
1474 NameOfAddress(addr));
1478 case CALL_JUMP_INSTR: {
1479 byte* addr = data + *
reinterpret_cast<int32_t*
>(data + 1) + 5;
1480 AppendToBuffer(
"%s %s", idesc.mnem, NameOfAddress(addr));
1485 case SHORT_IMMEDIATE_INSTR: {
1487 reinterpret_cast<byte*
>(*
reinterpret_cast<int32_t*
>(data + 1));
1488 AppendToBuffer(
"%s rax,%s", idesc.mnem, NameOfAddress(addr));
1506 AppendToBuffer(
"ret 0x%x", *reinterpret_cast<uint16_t*>(data + 1));
1513 get_modrm(*(data + 1), &mod, ®op, &rm);
1514 int32_t imm = *data == 0x6B ? *(data + 2)
1515 : *reinterpret_cast<int32_t*>(data + 2);
1516 AppendToBuffer(
"imul%c %s,%s,0x%x",
1517 operand_size_code(),
1518 NameOfCPURegister(regop),
1519 NameOfCPURegister(rm), imm);
1520 data += 2 + (*data == 0x6B ? 1 : 4);
1526 data += PrintImmediateOp(data);
1530 data += TwoByteOpcodeInstruction(data);
1536 get_modrm(*data, &mod, ®op, &rm);
1538 AppendToBuffer(
"pop ");
1539 data += PrintRightOperand(data);
1547 get_modrm(*data, &mod, ®op, &rm);
1548 const char* mnem =
NULL;
1568 AppendToBuffer(((regop <= 1) ?
"%s%c " :
"%s "),
1570 operand_size_code());
1571 data += PrintRightOperand(data);
1578 bool is_byte = *data == 0xC6;
1581 AppendToBuffer(
"movb ");
1582 data += PrintRightByteOperand(data);
1584 AppendToBuffer(
",0x%x", imm);
1587 AppendToBuffer(
"mov%c ", operand_size_code());
1588 data += PrintRightOperand(data);
1589 if (operand_size() == OPERAND_WORD_SIZE) {
1591 AppendToBuffer(
",0x%x", imm);
1595 AppendToBuffer(
",0x%x", imm);
1604 AppendToBuffer(
"cmpb ");
1605 data += PrintRightByteOperand(data);
1607 AppendToBuffer(
",0x%x", imm);
1615 bool is_byte = *data == 0x88;
1618 get_modrm(*data, &mod, ®op, &rm);
1620 AppendToBuffer(
"movb ");
1621 data += PrintRightByteOperand(data);
1622 AppendToBuffer(
",%s", NameOfByteCPURegister(regop));
1624 AppendToBuffer(
"mov%c ", operand_size_code());
1625 data += PrintRightOperand(data);
1626 AppendToBuffer(
",%s", NameOfCPURegister(regop));
1639 int reg = (*data & 0x7) | (rex_b() ? 8 : 0);
1641 AppendToBuffer(
"nop");
1643 AppendToBuffer(
"xchg%c rax,%s",
1644 operand_size_code(),
1645 NameOfCPURegister(reg));
1667 byte opcode = *data;
1669 bool is_32bit = (opcode >= 0xB8);
1670 int reg = (opcode & 0x7) | (rex_b() ? 8 : 0);
1672 AppendToBuffer(
"mov%c %s,",
1673 operand_size_code(),
1674 NameOfCPURegister(reg));
1675 data += PrintImmediate(data, OPERAND_DOUBLEWORD_SIZE);
1677 AppendToBuffer(
"movb %s,",
1678 NameOfByteCPURegister(reg));
1679 data += PrintImmediate(data, OPERAND_BYTE_SIZE);
1686 get_modrm(*data, &mod, ®op, &rm);
1688 AppendToBuffer(
"decb ");
1689 data += PrintRightByteOperand(data);
1691 UnimplementedInstruction();
1696 AppendToBuffer(
"push 0x%x", *reinterpret_cast<int32_t*>(data + 1));
1701 AppendToBuffer(
"push 0x%x", *reinterpret_cast<int8_t*>(data + 1));
1707 switch (operand_size()) {
1708 case OPERAND_DOUBLEWORD_SIZE: {
1709 const char* memory_location = NameOfAddress(
1710 reinterpret_cast<byte*>(
1711 *reinterpret_cast<int32_t*>(data + 1)));
1712 if (*data == 0xA1) {
1713 AppendToBuffer(
"movzxlq rax,(%s)", memory_location);
1715 AppendToBuffer(
"movzxlq (%s),rax", memory_location);
1720 case OPERAND_QUADWORD_SIZE: {
1722 const char* memory_location = NameOfAddress(
1723 *reinterpret_cast<byte**>(data + 1));
1724 if (*data == 0xA1) {
1725 AppendToBuffer(
"movq rax,(%s)", memory_location);
1727 AppendToBuffer(
"movq (%s),rax", memory_location);
1733 UnimplementedInstruction();
1739 AppendToBuffer(
"test al,0x%x", *reinterpret_cast<uint8_t*>(data + 1));
1745 switch (operand_size()) {
1746 case OPERAND_WORD_SIZE:
1747 value = *
reinterpret_cast<uint16_t*
>(data + 1);
1750 case OPERAND_DOUBLEWORD_SIZE:
1751 value = *
reinterpret_cast<uint32_t*
>(data + 1);
1754 case OPERAND_QUADWORD_SIZE:
1755 value = *
reinterpret_cast<int32_t*
>(data + 1);
1762 operand_size_code(),
1769 data += ShiftInstruction(data);
1774 byte_size_operand_ =
true;
1775 data += ShiftInstruction(data);
1785 data += FPUInstruction(data);
1789 data += JumpShort(data);
1793 byte_size_operand_ =
true;
1795 data += F6F7Instruction(data);
1799 AppendToBuffer(
"cmp al,0x%x", *reinterpret_cast<int8_t*>(data + 1));
1804 UnimplementedInstruction();
1809 if (tmp_buffer_pos_ <
sizeof tmp_buffer_) {
1810 tmp_buffer_[tmp_buffer_pos_] =
'\0';
1813 int instr_len =
static_cast<int>(data - instr);
1818 for (
byte* bp = instr; bp < data; bp++) {
1821 for (
int i = 6 - instr_len; i >= 0; i--) {
1826 tmp_buffer_.
start());
1834 static const char* cpu_regs[16] = {
1835 "rax",
"rcx",
"rdx",
"rbx",
"rsp",
"rbp",
"rsi",
"rdi",
1836 "r8",
"r9",
"r10",
"r11",
"r12",
"r13",
"r14",
"r15"
1840 static const char* byte_cpu_regs[16] = {
1841 "al",
"cl",
"dl",
"bl",
"spl",
"bpl",
"sil",
"dil",
1842 "r8l",
"r9l",
"r10l",
"r11l",
"r12l",
"r13l",
"r14l",
"r15l"
1846 static const char* xmm_regs[16] = {
1847 "xmm0",
"xmm1",
"xmm2",
"xmm3",
"xmm4",
"xmm5",
"xmm6",
"xmm7",
1848 "xmm8",
"xmm9",
"xmm10",
"xmm11",
"xmm12",
"xmm13",
"xmm14",
"xmm15"
1864 if (0 <= reg && reg < 16)
1865 return cpu_regs[reg];
1871 if (0 <= reg && reg < 16)
1872 return byte_cpu_regs[reg];
1878 if (0 <= reg && reg < 16)
1879 return xmm_regs[reg];
1894 : converter_(converter) { }
1900 byte* instruction) {
1901 DisassemblerX64 d(converter_, CONTINUE_ON_UNIMPLEMENTED_OPCODE);
1902 return d.InstructionDecode(buffer, instruction);
1907 int Disassembler::ConstantPoolSizeAt(
byte* instruction) {
1912 void Disassembler::Disassemble(FILE* f,
byte* begin,
byte* end) {
1913 NameConverter converter;
1915 for (
byte*
pc = begin;
pc < end;) {
1919 pc += d.InstructionDecode(buffer,
pc);
1920 fprintf(f,
"%p", prev_pc);
1923 for (
byte* bp = prev_pc; bp <
pc; bp++) {
1924 fprintf(f,
"%02x", *bp);
1926 for (
int i = 6 - static_cast<int>(pc - prev_pc); i >= 0; i--) {
1929 fprintf(f,
" %s\n", buffer.
start());
1935 #endif // V8_TARGET_ARCH_X64
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)
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 size
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)
#define LAZY_INSTANCE_INITIALIZER