11 #if V8_TARGET_ARCH_X64
21 REG_OPER_OP_ORDER = 1,
22 OPER_REG_OP_ORDER = 2,
24 BYTE_SIZE_OPERAND_FLAG = 4,
25 BYTE_REG_OPER_OP_ORDER = REG_OPER_OP_ORDER | BYTE_SIZE_OPERAND_FLAG,
26 BYTE_OPER_REG_OP_ORDER = OPER_REG_OP_ORDER | BYTE_SIZE_OPERAND_FLAG
35 OperandType op_order_;
40 static const ByteMnemonic two_operands_instr[] = {
41 { 0x00, BYTE_OPER_REG_OP_ORDER,
"add" },
42 { 0x01, OPER_REG_OP_ORDER,
"add" },
43 { 0x02, BYTE_REG_OPER_OP_ORDER,
"add" },
44 { 0x03, REG_OPER_OP_ORDER,
"add" },
45 { 0x08, BYTE_OPER_REG_OP_ORDER,
"or" },
46 { 0x09, OPER_REG_OP_ORDER,
"or" },
47 { 0x0A, BYTE_REG_OPER_OP_ORDER,
"or" },
48 { 0x0B, REG_OPER_OP_ORDER,
"or" },
49 { 0x10, BYTE_OPER_REG_OP_ORDER,
"adc" },
50 { 0x11, OPER_REG_OP_ORDER,
"adc" },
51 { 0x12, BYTE_REG_OPER_OP_ORDER,
"adc" },
52 { 0x13, REG_OPER_OP_ORDER,
"adc" },
53 { 0x18, BYTE_OPER_REG_OP_ORDER,
"sbb" },
54 { 0x19, OPER_REG_OP_ORDER,
"sbb" },
55 { 0x1A, BYTE_REG_OPER_OP_ORDER,
"sbb" },
56 { 0x1B, REG_OPER_OP_ORDER,
"sbb" },
57 { 0x20, BYTE_OPER_REG_OP_ORDER,
"and" },
58 { 0x21, OPER_REG_OP_ORDER,
"and" },
59 { 0x22, BYTE_REG_OPER_OP_ORDER,
"and" },
60 { 0x23, REG_OPER_OP_ORDER,
"and" },
61 { 0x28, BYTE_OPER_REG_OP_ORDER,
"sub" },
62 { 0x29, OPER_REG_OP_ORDER,
"sub" },
63 { 0x2A, BYTE_REG_OPER_OP_ORDER,
"sub" },
64 { 0x2B, REG_OPER_OP_ORDER,
"sub" },
65 { 0x30, BYTE_OPER_REG_OP_ORDER,
"xor" },
66 { 0x31, OPER_REG_OP_ORDER,
"xor" },
67 { 0x32, BYTE_REG_OPER_OP_ORDER,
"xor" },
68 { 0x33, REG_OPER_OP_ORDER,
"xor" },
69 { 0x38, BYTE_OPER_REG_OP_ORDER,
"cmp" },
70 { 0x39, OPER_REG_OP_ORDER,
"cmp" },
71 { 0x3A, BYTE_REG_OPER_OP_ORDER,
"cmp" },
72 { 0x3B, REG_OPER_OP_ORDER,
"cmp" },
73 { 0x63, REG_OPER_OP_ORDER,
"movsxl" },
74 { 0x84, BYTE_REG_OPER_OP_ORDER,
"test" },
75 { 0x85, REG_OPER_OP_ORDER,
"test" },
76 { 0x86, BYTE_REG_OPER_OP_ORDER,
"xchg" },
77 { 0x87, REG_OPER_OP_ORDER,
"xchg" },
78 { 0x88, BYTE_OPER_REG_OP_ORDER,
"mov" },
79 { 0x89, OPER_REG_OP_ORDER,
"mov" },
80 { 0x8A, BYTE_REG_OPER_OP_ORDER,
"mov" },
81 { 0x8B, REG_OPER_OP_ORDER,
"mov" },
82 { 0x8D, REG_OPER_OP_ORDER,
"lea" },
83 { -1, UNSET_OP_ORDER,
"" }
87 static const ByteMnemonic zero_operands_instr[] = {
88 { 0xC3, UNSET_OP_ORDER,
"ret" },
89 { 0xC9, UNSET_OP_ORDER,
"leave" },
90 { 0xF4, UNSET_OP_ORDER,
"hlt" },
91 { 0xFC, UNSET_OP_ORDER,
"cld" },
92 { 0xCC, UNSET_OP_ORDER,
"int3" },
93 { 0x60, UNSET_OP_ORDER,
"pushad" },
94 { 0x61, UNSET_OP_ORDER,
"popad" },
95 { 0x9C, UNSET_OP_ORDER,
"pushfd" },
96 { 0x9D, UNSET_OP_ORDER,
"popfd" },
97 { 0x9E, UNSET_OP_ORDER,
"sahf" },
98 { 0x99, UNSET_OP_ORDER,
"cdq" },
99 { 0x9B, UNSET_OP_ORDER,
"fwait" },
100 { 0xA4, UNSET_OP_ORDER,
"movs" },
101 { 0xA5, UNSET_OP_ORDER,
"movs" },
102 { 0xA6, UNSET_OP_ORDER,
"cmps" },
103 { 0xA7, UNSET_OP_ORDER,
"cmps" },
104 { -1, UNSET_OP_ORDER,
"" }
108 static const ByteMnemonic call_jump_instr[] = {
109 { 0xE8, UNSET_OP_ORDER,
"call" },
110 { 0xE9, UNSET_OP_ORDER,
"jmp" },
111 { -1, UNSET_OP_ORDER,
"" }
115 static const ByteMnemonic short_immediate_instr[] = {
116 { 0x05, UNSET_OP_ORDER,
"add" },
117 { 0x0D, UNSET_OP_ORDER,
"or" },
118 { 0x15, UNSET_OP_ORDER,
"adc" },
119 { 0x1D, UNSET_OP_ORDER,
"sbb" },
120 { 0x25, UNSET_OP_ORDER,
"and" },
121 { 0x2D, UNSET_OP_ORDER,
"sub" },
122 { 0x35, UNSET_OP_ORDER,
"xor" },
123 { 0x3D, UNSET_OP_ORDER,
"cmp" },
124 { -1, UNSET_OP_ORDER,
"" }
128 static const char*
const conditional_code_suffix[] = {
129 "o",
"no",
"c",
"nc",
"z",
"nz",
"na",
"a",
130 "s",
"ns",
"pe",
"po",
"l",
"ge",
"le",
"g"
134 enum InstructionType {
138 JUMP_CONDITIONAL_SHORT_INSTR,
143 SHORT_IMMEDIATE_INSTR
148 ESCAPE_PREFIX = 0x0F,
149 OPERAND_SIZE_OVERRIDE_PREFIX = 0x66,
150 ADDRESS_SIZE_OVERRIDE_PREFIX = 0x67,
153 REPEQ_PREFIX = REP_PREFIX
157 struct InstructionDesc {
159 InstructionType type;
160 OperandType op_order_;
161 bool byte_size_operation;
165 class InstructionTable {
168 const InstructionDesc& Get(
byte x)
const {
169 return instructions_[x];
173 InstructionDesc instructions_[256];
176 void CopyTable(
const ByteMnemonic bm[], InstructionType type);
177 void SetTableRange(InstructionType type,
byte start,
byte end,
bool byte_size,
179 void AddJumpConditionalShort();
183 InstructionTable::InstructionTable() {
189 void InstructionTable::Clear() {
190 for (
int i = 0;
i < 256;
i++) {
191 instructions_[
i].mnem =
"(bad)";
192 instructions_[
i].type = NO_INSTR;
193 instructions_[
i].op_order_ = UNSET_OP_ORDER;
194 instructions_[
i].byte_size_operation =
false;
199 void InstructionTable::Init() {
200 CopyTable(two_operands_instr, TWO_OPERANDS_INSTR);
201 CopyTable(zero_operands_instr, ZERO_OPERANDS_INSTR);
202 CopyTable(call_jump_instr, CALL_JUMP_INSTR);
203 CopyTable(short_immediate_instr, SHORT_IMMEDIATE_INSTR);
204 AddJumpConditionalShort();
205 SetTableRange(PUSHPOP_INSTR, 0x50, 0x57,
false,
"push");
206 SetTableRange(PUSHPOP_INSTR, 0x58, 0x5F,
false,
"pop");
207 SetTableRange(MOVE_REG_INSTR, 0xB8, 0xBF,
false,
"mov");
211 void InstructionTable::CopyTable(
const ByteMnemonic bm[],
212 InstructionType type) {
213 for (
int i = 0; bm[
i].b >= 0;
i++) {
214 InstructionDesc*
id = &instructions_[bm[
i].b];
215 id->mnem = bm[
i].mnem;
216 OperandType op_order = bm[
i].op_order_;
218 static_cast<OperandType
>(op_order & ~BYTE_SIZE_OPERAND_FLAG);
221 id->byte_size_operation = ((op_order & BYTE_SIZE_OPERAND_FLAG) != 0);
226 void InstructionTable::SetTableRange(InstructionType type,
231 for (
byte b = start; b <= end; b++) {
232 InstructionDesc*
id = &instructions_[b];
236 id->byte_size_operation = byte_size;
241 void InstructionTable::AddJumpConditionalShort() {
242 for (
byte b = 0x70; b <= 0x7F; b++) {
243 InstructionDesc*
id = &instructions_[b];
246 id->type = JUMP_CONDITIONAL_SHORT_INSTR;
255 static InstructionDesc cmov_instructions[16] = {
256 {
"cmovo", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER,
false},
257 {
"cmovno", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER,
false},
258 {
"cmovc", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER,
false},
259 {
"cmovnc", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER,
false},
260 {
"cmovz", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER,
false},
261 {
"cmovnz", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER,
false},
262 {
"cmovna", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER,
false},
263 {
"cmova", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER,
false},
264 {
"cmovs", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER,
false},
265 {
"cmovns", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER,
false},
266 {
"cmovpe", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER,
false},
267 {
"cmovpo", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER,
false},
268 {
"cmovl", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER,
false},
269 {
"cmovge", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER,
false},
270 {
"cmovle", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER,
false},
271 {
"cmovg", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER,
false}
278 enum UnimplementedOpcodeAction {
279 CONTINUE_ON_UNIMPLEMENTED_OPCODE,
280 ABORT_ON_UNIMPLEMENTED_OPCODE
286 class DisassemblerX64 {
288 DisassemblerX64(
const NameConverter& converter,
289 UnimplementedOpcodeAction unimplemented_action =
290 ABORT_ON_UNIMPLEMENTED_OPCODE)
291 : converter_(converter),
293 abort_on_unimplemented_(
294 unimplemented_action == ABORT_ON_UNIMPLEMENTED_OPCODE),
298 byte_size_operand_(
false),
299 instruction_table_(instruction_table.Pointer()) {
300 tmp_buffer_[0] =
'\0';
303 virtual ~DisassemblerX64() {
312 OPERAND_BYTE_SIZE = 0,
313 OPERAND_WORD_SIZE = 1,
314 OPERAND_DOUBLEWORD_SIZE = 2,
315 OPERAND_QUADWORD_SIZE = 3
318 const NameConverter& converter_;
320 unsigned int tmp_buffer_pos_;
321 bool abort_on_unimplemented_;
325 byte group_1_prefix_;
327 bool byte_size_operand_;
328 const InstructionTable*
const instruction_table_;
330 void setRex(
byte rex) {
335 bool rex() {
return rex_ != 0; }
337 bool rex_b() {
return (rex_ & 0x01) != 0; }
340 int base_reg(
int low_bits) {
return low_bits | ((rex_ & 0x01) << 3); }
342 bool rex_x() {
return (rex_ & 0x02) != 0; }
344 bool rex_r() {
return (rex_ & 0x04) != 0; }
346 bool rex_w() {
return (rex_ & 0x08) != 0; }
348 OperandSize operand_size() {
349 if (byte_size_operand_)
return OPERAND_BYTE_SIZE;
350 if (rex_w())
return OPERAND_QUADWORD_SIZE;
351 if (operand_size_ != 0)
return OPERAND_WORD_SIZE;
352 return OPERAND_DOUBLEWORD_SIZE;
355 char operand_size_code() {
356 return "bwlq"[operand_size()];
359 const char* NameOfCPURegister(
int reg)
const {
360 return converter_.NameOfCPURegister(reg);
363 const char* NameOfByteCPURegister(
int reg)
const {
364 return converter_.NameOfByteCPURegister(reg);
367 const char* NameOfXMMRegister(
int reg)
const {
368 return converter_.NameOfXMMRegister(reg);
371 const char* NameOfAddress(
byte* addr)
const {
372 return converter_.NameOfAddress(addr);
376 void get_modrm(
byte data,
380 *mod = (data >> 6) & 3;
381 *regop = ((data & 0x38) >> 3) | (rex_r() ? 8 : 0);
382 *rm = (data & 7) | (rex_b() ? 8 : 0);
385 void get_sib(
byte data,
389 *scale = (data >> 6) & 3;
390 *index = ((data >> 3) & 7) | (rex_x() ? 8 : 0);
391 *base = (data & 7) | (rex_b() ? 8 : 0);
394 typedef const char* (DisassemblerX64::*RegisterNameMapping)(
int reg)
const;
396 int PrintRightOperandHelper(
byte* modrmp,
397 RegisterNameMapping register_name);
398 int PrintRightOperand(
byte* modrmp);
399 int PrintRightByteOperand(
byte* modrmp);
400 int PrintRightXMMOperand(
byte* modrmp);
401 int PrintOperands(
const char* mnem,
402 OperandType op_order,
404 int PrintImmediate(
byte* data, OperandSize
size);
405 int PrintImmediateOp(
byte* data);
406 const char* TwoByteMnemonic(
byte opcode);
407 int TwoByteOpcodeInstruction(
byte* data);
408 int F6F7Instruction(
byte* data);
409 int ShiftInstruction(
byte* data);
410 int JumpShort(
byte* data);
411 int JumpConditional(
byte* data);
412 int JumpConditionalShort(
byte* data);
413 int SetCC(
byte* data);
414 int FPUInstruction(
byte* data);
415 int MemoryFPUInstruction(
int escape_opcode,
int regop,
byte* modrm_start);
416 int RegisterFPUInstruction(
int escape_opcode,
byte modrm_byte);
417 void AppendToBuffer(
const char* format, ...);
419 void UnimplementedInstruction() {
420 if (abort_on_unimplemented_) {
423 AppendToBuffer(
"'Unimplemented Instruction'");
429 void DisassemblerX64::AppendToBuffer(
const char* format, ...) {
432 va_start(args, format);
435 tmp_buffer_pos_ += result;
439 int DisassemblerX64::PrintRightOperandHelper(
441 RegisterNameMapping direct_register_name) {
443 get_modrm(*modrmp, &mod, ®op, &rm);
444 RegisterNameMapping register_name = (mod == 3) ? direct_register_name :
445 &DisassemblerX64::NameOfCPURegister;
450 AppendToBuffer(
"[0x%x]", disp);
452 }
else if ((rm & 7) == 4) {
454 byte sib = *(modrmp + 1);
455 int scale, index, base;
456 get_sib(sib, &scale, &index, &base);
457 if (index == 4 && (base & 7) == 4 && scale == 0 ) {
460 AppendToBuffer(
"[%s]", NameOfCPURegister(base));
462 }
else if (base == 5) {
465 AppendToBuffer(
"[%s*%d%s0x%x]",
466 NameOfCPURegister(index),
468 disp < 0 ?
"-" :
"+",
469 disp < 0 ? -disp : disp);
471 }
else if (index != 4 && base != 5) {
473 AppendToBuffer(
"[%s+%s*%d]",
474 NameOfCPURegister(base),
475 NameOfCPURegister(index),
479 UnimplementedInstruction();
483 AppendToBuffer(
"[%s]", NameOfCPURegister(rm));
490 byte sib = *(modrmp + 1);
491 int scale, index, base;
492 get_sib(sib, &scale, &index, &base);
493 int disp = (mod == 2) ? *
reinterpret_cast<int32_t*
>(modrmp + 2)
494 : *
reinterpret_cast<int8_t*
>(modrmp + 2);
495 if (index == 4 && (base & 7) == 4 && scale == 0 ) {
496 AppendToBuffer(
"[%s%s0x%x]",
497 NameOfCPURegister(base),
498 disp < 0 ?
"-" :
"+",
499 disp < 0 ? -disp : disp);
501 AppendToBuffer(
"[%s+%s*%d%s0x%x]",
502 NameOfCPURegister(base),
503 NameOfCPURegister(index),
505 disp < 0 ?
"-" :
"+",
506 disp < 0 ? -disp : disp);
508 return mod == 2 ? 6 : 3;
511 int disp = (mod == 2) ? *
reinterpret_cast<int32_t*
>(modrmp + 1)
512 : *
reinterpret_cast<int8_t*
>(modrmp + 1);
513 AppendToBuffer(
"[%s%s0x%x]",
514 NameOfCPURegister(rm),
515 disp < 0 ?
"-" :
"+",
516 disp < 0 ? -disp : disp);
517 return (mod == 2) ? 5 : 2;
521 AppendToBuffer(
"%s", (this->*register_name)(rm));
524 UnimplementedInstruction();
531 int DisassemblerX64::PrintImmediate(
byte* data, OperandSize
size) {
535 case OPERAND_BYTE_SIZE:
539 case OPERAND_WORD_SIZE:
540 value = *
reinterpret_cast<int16_t*
>(data);
543 case OPERAND_DOUBLEWORD_SIZE:
544 value = *
reinterpret_cast<uint32_t*
>(data);
547 case OPERAND_QUADWORD_SIZE:
548 value = *
reinterpret_cast<int32_t*
>(data);
561 int DisassemblerX64::PrintRightOperand(
byte* modrmp) {
562 return PrintRightOperandHelper(modrmp,
563 &DisassemblerX64::NameOfCPURegister);
567 int DisassemblerX64::PrintRightByteOperand(
byte* modrmp) {
568 return PrintRightOperandHelper(modrmp,
569 &DisassemblerX64::NameOfByteCPURegister);
573 int DisassemblerX64::PrintRightXMMOperand(
byte* modrmp) {
574 return PrintRightOperandHelper(modrmp,
575 &DisassemblerX64::NameOfXMMRegister);
581 int DisassemblerX64::PrintOperands(
const char* mnem,
582 OperandType op_order,
586 get_modrm(modrm, &mod, ®op, &rm);
588 const char* register_name =
589 byte_size_operand_ ? NameOfByteCPURegister(regop)
590 : NameOfCPURegister(regop);
592 case REG_OPER_OP_ORDER: {
593 AppendToBuffer(
"%s%c %s,",
597 advance = byte_size_operand_ ? PrintRightByteOperand(data)
598 : PrintRightOperand(data);
601 case OPER_REG_OP_ORDER: {
602 AppendToBuffer(
"%s%c ", mnem, operand_size_code());
603 advance = byte_size_operand_ ? PrintRightByteOperand(data)
604 : PrintRightOperand(data);
605 AppendToBuffer(
",%s", register_name);
618 int DisassemblerX64::PrintImmediateOp(
byte* data) {
619 bool byte_size_immediate = (*data & 0x02) != 0;
620 byte modrm = *(data + 1);
622 get_modrm(modrm, &mod, ®op, &rm);
623 const char* mnem =
"Imm???";
650 UnimplementedInstruction();
652 AppendToBuffer(
"%s%c ", mnem, operand_size_code());
653 int count = PrintRightOperand(data + 1);
654 AppendToBuffer(
",0x");
655 OperandSize immediate_size =
656 byte_size_immediate ? OPERAND_BYTE_SIZE : operand_size();
657 count += PrintImmediate(data + 1 + count, immediate_size);
663 int DisassemblerX64::F6F7Instruction(
byte* data) {
664 DCHECK(*data == 0xF7 || *data == 0xF6);
665 byte modrm = *(data + 1);
667 get_modrm(modrm, &mod, ®op, &rm);
668 if (mod == 3 && regop != 0) {
669 const char* mnem =
NULL;
690 UnimplementedInstruction();
692 AppendToBuffer(
"%s%c %s",
695 NameOfCPURegister(rm));
697 }
else if (regop == 0) {
698 AppendToBuffer(
"test%c ", operand_size_code());
699 int count = PrintRightOperand(data + 1);
700 AppendToBuffer(
",0x");
701 count += PrintImmediate(data + 1 + count, operand_size());
704 UnimplementedInstruction();
710 int DisassemblerX64::ShiftInstruction(
byte* data) {
711 byte op = *data & (~1);
712 if (op != 0xD0 && op != 0xD2 && op != 0xC0) {
713 UnimplementedInstruction();
716 byte modrm = *(data + 1);
718 get_modrm(modrm, &mod, ®op, &rm);
723 UnimplementedInstruction();
726 const char* mnem =
NULL;
750 UnimplementedInstruction();
756 }
else if (op == 0xC0) {
760 AppendToBuffer(
"%s%c %s,",
763 byte_size_operand_ ? NameOfByteCPURegister(rm)
764 : NameOfCPURegister(rm));
766 AppendToBuffer(
"cl");
768 AppendToBuffer(
"%d", imm8);
775 int DisassemblerX64::JumpShort(
byte* data) {
777 byte b = *(data + 1);
778 byte* dest = data +
static_cast<int8_t
>(b) + 2;
779 AppendToBuffer(
"jmp %s", NameOfAddress(dest));
785 int DisassemblerX64::JumpConditional(
byte* data) {
787 byte cond = *(data + 1) & 0x0F;
788 byte* dest = data + *
reinterpret_cast<int32_t*
>(data + 2) + 6;
789 const char* mnem = conditional_code_suffix[cond];
790 AppendToBuffer(
"j%s %s", mnem, NameOfAddress(dest));
796 int DisassemblerX64::JumpConditionalShort(
byte* data) {
797 byte cond = *data & 0x0F;
798 byte b = *(data + 1);
799 byte* dest = data +
static_cast<int8_t
>(b) + 2;
800 const char* mnem = conditional_code_suffix[cond];
801 AppendToBuffer(
"j%s %s", mnem, NameOfAddress(dest));
809 byte cond = *(data + 1) & 0x0F;
810 const char* mnem = conditional_code_suffix[cond];
811 AppendToBuffer(
"set%s%c ", mnem, operand_size_code());
812 PrintRightByteOperand(data + 2);
818 int DisassemblerX64::FPUInstruction(
byte* data) {
819 byte escape_opcode = *data;
821 byte modrm_byte = *(data+1);
823 if (modrm_byte >= 0xC0) {
824 return RegisterFPUInstruction(escape_opcode, modrm_byte);
826 return MemoryFPUInstruction(escape_opcode, modrm_byte, data+1);
830 int DisassemblerX64::MemoryFPUInstruction(
int escape_opcode,
833 const char* mnem =
"?";
834 int regop = (modrm_byte >> 3) & 0x7;
835 switch (escape_opcode) {
836 case 0xD9:
switch (regop) {
837 case 0: mnem =
"fld_s";
break;
838 case 3: mnem =
"fstp_s";
break;
839 case 7: mnem =
"fstcw";
break;
840 default: UnimplementedInstruction();
844 case 0xDB:
switch (regop) {
845 case 0: mnem =
"fild_s";
break;
846 case 1: mnem =
"fisttp_s";
break;
847 case 2: mnem =
"fist_s";
break;
848 case 3: mnem =
"fistp_s";
break;
849 default: UnimplementedInstruction();
853 case 0xDD:
switch (regop) {
854 case 0: mnem =
"fld_d";
break;
855 case 3: mnem =
"fstp_d";
break;
856 default: UnimplementedInstruction();
860 case 0xDF:
switch (regop) {
861 case 5: mnem =
"fild_d";
break;
862 case 7: mnem =
"fistp_d";
break;
863 default: UnimplementedInstruction();
867 default: UnimplementedInstruction();
869 AppendToBuffer(
"%s ", mnem);
870 int count = PrintRightOperand(modrm_start);
874 int DisassemblerX64::RegisterFPUInstruction(
int escape_opcode,
876 bool has_register =
false;
877 const char* mnem =
"?";
879 switch (escape_opcode) {
881 UnimplementedInstruction();
885 switch (modrm_byte & 0xF8) {
895 switch (modrm_byte) {
896 case 0xE0: mnem =
"fchs";
break;
897 case 0xE1: mnem =
"fabs";
break;
898 case 0xE3: mnem =
"fninit";
break;
899 case 0xE4: mnem =
"ftst";
break;
900 case 0xE8: mnem =
"fld1";
break;
901 case 0xEB: mnem =
"fldpi";
break;
902 case 0xED: mnem =
"fldln2";
break;
903 case 0xEE: mnem =
"fldz";
break;
904 case 0xF0: mnem =
"f2xm1";
break;
905 case 0xF1: mnem =
"fyl2x";
break;
906 case 0xF2: mnem =
"fptan";
break;
907 case 0xF5: mnem =
"fprem1";
break;
908 case 0xF7: mnem =
"fincstp";
break;
909 case 0xF8: mnem =
"fprem";
break;
910 case 0xFC: mnem =
"frndint";
break;
911 case 0xFD: mnem =
"fscale";
break;
912 case 0xFE: mnem =
"fsin";
break;
913 case 0xFF: mnem =
"fcos";
break;
914 default: UnimplementedInstruction();
920 if (modrm_byte == 0xE9) {
923 UnimplementedInstruction();
928 if ((modrm_byte & 0xF8) == 0xE8) {
931 }
else if (modrm_byte == 0xE2) {
933 }
else if (modrm_byte == 0xE3) {
936 UnimplementedInstruction();
942 switch (modrm_byte & 0xF8) {
943 case 0xC0: mnem =
"fadd";
break;
944 case 0xE8: mnem =
"fsub";
break;
945 case 0xC8: mnem =
"fmul";
break;
946 case 0xF8: mnem =
"fdiv";
break;
947 default: UnimplementedInstruction();
953 switch (modrm_byte & 0xF8) {
954 case 0xC0: mnem =
"ffree";
break;
955 case 0xD8: mnem =
"fstp";
break;
956 default: UnimplementedInstruction();
961 if (modrm_byte == 0xD9) {
965 switch (modrm_byte & 0xF8) {
966 case 0xC0: mnem =
"faddp";
break;
967 case 0xE8: mnem =
"fsubp";
break;
968 case 0xC8: mnem =
"fmulp";
break;
969 case 0xF8: mnem =
"fdivp";
break;
970 default: UnimplementedInstruction();
976 if (modrm_byte == 0xE0) {
978 }
else if ((modrm_byte & 0xF8) == 0xE8) {
984 default: UnimplementedInstruction();
988 AppendToBuffer(
"%s st%d", mnem, modrm_byte & 0x7);
990 AppendToBuffer(
"%s", mnem);
1000 int DisassemblerX64::TwoByteOpcodeInstruction(
byte* data) {
1001 byte opcode = *(data + 1);
1002 byte* current = data + 2;
1004 const char* mnemonic = TwoByteMnemonic(opcode);
1005 if (operand_size_ == 0x66) {
1008 if (opcode == 0x3A) {
1009 byte third_byte = *current;
1011 if (third_byte == 0x17) {
1012 get_modrm(*current, &mod, ®op, &rm);
1013 AppendToBuffer(
"extractps ");
1014 current += PrintRightOperand(current);
1015 AppendToBuffer(
",%s,%d", NameOfXMMRegister(regop), (*current) & 3);
1017 }
else if (third_byte == 0x0b) {
1018 get_modrm(*current, &mod, ®op, &rm);
1020 AppendToBuffer(
"roundsd %s,", NameOfXMMRegister(regop));
1021 current += PrintRightXMMOperand(current);
1022 AppendToBuffer(
",%d", (*current) & 3);
1025 UnimplementedInstruction();
1028 get_modrm(*current, &mod, ®op, &rm);
1029 if (opcode == 0x1f) {
1036 }
else if (mod == 2) {
1039 AppendToBuffer(
"nop");
1040 }
else if (opcode == 0x28) {
1041 AppendToBuffer(
"movapd %s,", NameOfXMMRegister(regop));
1042 current += PrintRightXMMOperand(current);
1043 }
else if (opcode == 0x29) {
1044 AppendToBuffer(
"movapd ");
1045 current += PrintRightXMMOperand(current);
1046 AppendToBuffer(
",%s", NameOfXMMRegister(regop));
1047 }
else if (opcode == 0x6E) {
1048 AppendToBuffer(
"mov%c %s,",
1049 rex_w() ?
'q' :
'd',
1050 NameOfXMMRegister(regop));
1051 current += PrintRightOperand(current);
1052 }
else if (opcode == 0x6F) {
1053 AppendToBuffer(
"movdqa %s,",
1054 NameOfXMMRegister(regop));
1055 current += PrintRightXMMOperand(current);
1056 }
else if (opcode == 0x7E) {
1057 AppendToBuffer(
"mov%c ",
1058 rex_w() ?
'q' :
'd');
1059 current += PrintRightOperand(current);
1060 AppendToBuffer(
",%s", NameOfXMMRegister(regop));
1061 }
else if (opcode == 0x7F) {
1062 AppendToBuffer(
"movdqa ");
1063 current += PrintRightXMMOperand(current);
1064 AppendToBuffer(
",%s", NameOfXMMRegister(regop));
1065 }
else if (opcode == 0xD6) {
1066 AppendToBuffer(
"movq ");
1067 current += PrintRightXMMOperand(current);
1068 AppendToBuffer(
",%s", NameOfXMMRegister(regop));
1069 }
else if (opcode == 0x50) {
1070 AppendToBuffer(
"movmskpd %s,", NameOfCPURegister(regop));
1071 current += PrintRightXMMOperand(current);
1072 }
else if (opcode == 0x73) {
1075 AppendToBuffer(
"psllq,%s,%d", NameOfXMMRegister(rm), *current & 0x7f);
1078 const char* mnemonic =
"?";
1079 if (opcode == 0x54) {
1081 }
else if (opcode == 0x56) {
1083 }
else if (opcode == 0x57) {
1085 }
else if (opcode == 0x2E) {
1086 mnemonic =
"ucomisd";
1087 }
else if (opcode == 0x2F) {
1088 mnemonic =
"comisd";
1090 UnimplementedInstruction();
1092 AppendToBuffer(
"%s %s,", mnemonic, NameOfXMMRegister(regop));
1093 current += PrintRightXMMOperand(current);
1096 }
else if (group_1_prefix_ == 0xF2) {
1099 if (opcode == 0x11 || opcode == 0x10) {
1101 AppendToBuffer(
"movsd ");
1103 get_modrm(*current, &mod, ®op, &rm);
1104 if (opcode == 0x11) {
1105 current += PrintRightXMMOperand(current);
1106 AppendToBuffer(
",%s", NameOfXMMRegister(regop));
1108 AppendToBuffer(
"%s,", NameOfXMMRegister(regop));
1109 current += PrintRightXMMOperand(current);
1111 }
else if (opcode == 0x2A) {
1114 get_modrm(*current, &mod, ®op, &rm);
1115 AppendToBuffer(
"%sd %s,", mnemonic, NameOfXMMRegister(regop));
1116 current += PrintRightOperand(current);
1117 }
else if (opcode == 0x2C) {
1121 get_modrm(*current, &mod, ®op, &rm);
1122 AppendToBuffer(
"cvttsd2si%c %s,",
1123 operand_size_code(), NameOfCPURegister(regop));
1124 current += PrintRightXMMOperand(current);
1125 }
else if (opcode == 0x2D) {
1128 get_modrm(*current, &mod, ®op, &rm);
1129 AppendToBuffer(
"cvtsd2si%c %s,",
1130 operand_size_code(), NameOfCPURegister(regop));
1131 current += PrintRightXMMOperand(current);
1132 }
else if ((opcode & 0xF8) == 0x58 || opcode == 0x51) {
1135 get_modrm(*current, &mod, ®op, &rm);
1136 AppendToBuffer(
"%s %s,", mnemonic, NameOfXMMRegister(regop));
1137 current += PrintRightXMMOperand(current);
1138 }
else if (opcode == 0xC2) {
1141 get_modrm(*current, &mod, ®op, &rm);
1142 const char*
const pseudo_op[] = {
1152 AppendToBuffer(
"%s %s,%s",
1153 pseudo_op[current[1]],
1154 NameOfXMMRegister(regop),
1155 NameOfXMMRegister(rm));
1158 UnimplementedInstruction();
1160 }
else if (group_1_prefix_ == 0xF3) {
1162 if (opcode == 0x11 || opcode == 0x10) {
1164 AppendToBuffer(
"movss ");
1166 get_modrm(*current, &mod, ®op, &rm);
1167 if (opcode == 0x11) {
1168 current += PrintRightOperand(current);
1169 AppendToBuffer(
",%s", NameOfXMMRegister(regop));
1171 AppendToBuffer(
"%s,", NameOfXMMRegister(regop));
1172 current += PrintRightOperand(current);
1174 }
else if (opcode == 0x2A) {
1177 get_modrm(*current, &mod, ®op, &rm);
1178 AppendToBuffer(
"%ss %s,", mnemonic, NameOfXMMRegister(regop));
1179 current += PrintRightOperand(current);
1180 }
else if (opcode == 0x2C) {
1184 get_modrm(*current, &mod, ®op, &rm);
1185 AppendToBuffer(
"cvttss2si%c %s,",
1186 operand_size_code(), NameOfCPURegister(regop));
1187 current += PrintRightXMMOperand(current);
1188 }
else if (opcode == 0x5A) {
1192 get_modrm(*current, &mod, ®op, &rm);
1193 AppendToBuffer(
"cvtss2sd %s,", NameOfXMMRegister(regop));
1194 current += PrintRightXMMOperand(current);
1195 }
else if (opcode == 0x7E) {
1197 get_modrm(*current, &mod, ®op, &rm);
1198 AppendToBuffer(
"movq %s,", NameOfXMMRegister(regop));
1199 current += PrintRightXMMOperand(current);
1201 UnimplementedInstruction();
1203 }
else if (opcode == 0x1F) {
1206 get_modrm(*current, &mod, ®op, &rm);
1213 }
else if (mod == 2) {
1216 AppendToBuffer(
"nop");
1218 }
else if (opcode == 0x28) {
1221 get_modrm(*current, &mod, ®op, &rm);
1222 AppendToBuffer(
"movaps %s,", NameOfXMMRegister(regop));
1223 current += PrintRightXMMOperand(current);
1225 }
else if (opcode == 0x29) {
1228 get_modrm(*current, &mod, ®op, &rm);
1229 AppendToBuffer(
"movaps ");
1230 current += PrintRightXMMOperand(current);
1231 AppendToBuffer(
",%s", NameOfXMMRegister(regop));
1233 }
else if (opcode == 0xA2) {
1235 AppendToBuffer(
"%s", mnemonic);
1237 }
else if ((opcode & 0xF0) == 0x40) {
1239 int condition = opcode & 0x0F;
1240 const InstructionDesc& idesc = cmov_instructions[condition];
1241 byte_size_operand_ = idesc.byte_size_operation;
1242 current += PrintOperands(idesc.mnem, idesc.op_order_, current);
1244 }
else if (opcode >= 0x53 && opcode <= 0x5F) {
1245 const char*
const pseudo_op[] = {
1261 get_modrm(*current, &mod, ®op, &rm);
1262 AppendToBuffer(
"%s %s,",
1263 pseudo_op[opcode - 0x53],
1264 NameOfXMMRegister(regop));
1265 current += PrintRightXMMOperand(current);
1267 }
else if (opcode == 0xC6) {
1270 get_modrm(*current, &mod, ®op, &rm);
1271 AppendToBuffer(
"shufps %s, ", NameOfXMMRegister(regop));
1272 current += PrintRightXMMOperand(current);
1273 AppendToBuffer(
", %d", (*current) & 3);
1276 }
else if (opcode == 0x50) {
1279 get_modrm(*current, &mod, ®op, &rm);
1280 AppendToBuffer(
"movmskps %s,", NameOfCPURegister(regop));
1281 current += PrintRightXMMOperand(current);
1283 }
else if ((opcode & 0xF0) == 0x80) {
1285 current = data + JumpConditional(data);
1287 }
else if (opcode == 0xBE || opcode == 0xBF || opcode == 0xB6 ||
1288 opcode == 0xB7 || opcode == 0xAF) {
1290 current += PrintOperands(mnemonic, REG_OPER_OP_ORDER, current);
1292 }
else if ((opcode & 0xF0) == 0x90) {
1294 current = data +
SetCC(data);
1296 }
else if (opcode == 0xAB || opcode == 0xA5 || opcode == 0xAD) {
1298 AppendToBuffer(
"%s ", mnemonic);
1300 get_modrm(*current, &mod, ®op, &rm);
1301 current += PrintRightOperand(current);
1302 if (opcode == 0xAB) {
1303 AppendToBuffer(
",%s", NameOfCPURegister(regop));
1305 AppendToBuffer(
",%s,cl", NameOfCPURegister(regop));
1307 }
else if (opcode == 0xBD) {
1308 AppendToBuffer(
"%s%c ", mnemonic, operand_size_code());
1310 get_modrm(*current, &mod, ®op, &rm);
1311 AppendToBuffer(
"%s,", NameOfCPURegister(regop));
1312 current += PrintRightOperand(current);
1314 UnimplementedInstruction();
1316 return static_cast<int>(current - data);
1323 const char* DisassemblerX64::TwoByteMnemonic(
byte opcode) {
1370 tmp_buffer_pos_ = 0;
1372 bool processed =
true;
1379 if (current == OPERAND_SIZE_OVERRIDE_PREFIX) {
1380 operand_size_ = current;
1381 }
else if ((current & 0xF0) == 0x40) {
1383 if (rex_w()) AppendToBuffer(
"REX.W ");
1384 }
else if ((current & 0xFE) == 0xF2) {
1385 group_1_prefix_ = current;
1392 const InstructionDesc& idesc = instruction_table_->Get(current);
1393 byte_size_operand_ = idesc.byte_size_operation;
1394 switch (idesc.type) {
1395 case ZERO_OPERANDS_INSTR:
1396 if (current >= 0xA4 && current <= 0xA7) {
1398 if (group_1_prefix_ == REP_PREFIX) {
1400 AppendToBuffer(
"rep ");
1402 if (rex_w()) AppendToBuffer(
"REX.W ");
1403 AppendToBuffer(
"%s%c", idesc.mnem, operand_size_code());
1405 AppendToBuffer(
"%s", idesc.mnem, operand_size_code());
1410 case TWO_OPERANDS_INSTR:
1412 data += PrintOperands(idesc.mnem, idesc.op_order_, data);
1415 case JUMP_CONDITIONAL_SHORT_INSTR:
1416 data += JumpConditionalShort(data);
1419 case REGISTER_INSTR:
1420 AppendToBuffer(
"%s%c %s",
1422 operand_size_code(),
1423 NameOfCPURegister(base_reg(current & 0x07)));
1427 AppendToBuffer(
"%s %s",
1429 NameOfCPURegister(base_reg(current & 0x07)));
1432 case MOVE_REG_INSTR: {
1434 switch (operand_size()) {
1435 case OPERAND_WORD_SIZE:
1436 addr =
reinterpret_cast<byte*
>(*
reinterpret_cast<int16_t*
>(data + 1));
1439 case OPERAND_DOUBLEWORD_SIZE:
1441 reinterpret_cast<byte*
>(*
reinterpret_cast<uint32_t*
>(data + 1));
1444 case OPERAND_QUADWORD_SIZE:
1445 addr =
reinterpret_cast<byte*
>(*
reinterpret_cast<int64_t*
>(data + 1));
1451 AppendToBuffer(
"mov%c %s,%s",
1452 operand_size_code(),
1453 NameOfCPURegister(base_reg(current & 0x07)),
1454 NameOfAddress(addr));
1458 case CALL_JUMP_INSTR: {
1459 byte* addr = data + *
reinterpret_cast<int32_t*
>(data + 1) + 5;
1460 AppendToBuffer(
"%s %s", idesc.mnem, NameOfAddress(addr));
1465 case SHORT_IMMEDIATE_INSTR: {
1467 reinterpret_cast<byte*
>(*
reinterpret_cast<int32_t*
>(data + 1));
1468 AppendToBuffer(
"%s rax,%s", idesc.mnem, NameOfAddress(addr));
1486 AppendToBuffer(
"ret 0x%x", *
reinterpret_cast<uint16_t*
>(data + 1));
1493 get_modrm(*(data + 1), &mod, ®op, &rm);
1494 int32_t imm = *data == 0x6B ? *(data + 2)
1495 : *
reinterpret_cast<int32_t*
>(data + 2);
1496 AppendToBuffer(
"imul%c %s,%s,0x%x",
1497 operand_size_code(),
1498 NameOfCPURegister(regop),
1499 NameOfCPURegister(rm), imm);
1500 data += 2 + (*data == 0x6B ? 1 : 4);
1506 data += PrintImmediateOp(data);
1510 data += TwoByteOpcodeInstruction(data);
1516 get_modrm(*data, &mod, ®op, &rm);
1518 AppendToBuffer(
"pop ");
1519 data += PrintRightOperand(data);
1527 get_modrm(*data, &mod, ®op, &rm);
1528 const char* mnem =
NULL;
1548 AppendToBuffer(((regop <= 1) ?
"%s%c " :
"%s "),
1550 operand_size_code());
1551 data += PrintRightOperand(data);
1558 bool is_byte = *data == 0xC6;
1561 AppendToBuffer(
"movb ");
1562 data += PrintRightByteOperand(data);
1564 AppendToBuffer(
",0x%x", imm);
1567 AppendToBuffer(
"mov%c ", operand_size_code());
1568 data += PrintRightOperand(data);
1569 if (operand_size() == OPERAND_WORD_SIZE) {
1571 AppendToBuffer(
",0x%x", imm);
1575 AppendToBuffer(
",0x%x", imm);
1584 AppendToBuffer(
"cmpb ");
1585 data += PrintRightByteOperand(data);
1587 AppendToBuffer(
",0x%x", imm);
1595 bool is_byte = *data == 0x88;
1598 get_modrm(*data, &mod, ®op, &rm);
1600 AppendToBuffer(
"movb ");
1601 data += PrintRightByteOperand(data);
1602 AppendToBuffer(
",%s", NameOfByteCPURegister(regop));
1604 AppendToBuffer(
"mov%c ", operand_size_code());
1605 data += PrintRightOperand(data);
1606 AppendToBuffer(
",%s", NameOfCPURegister(regop));
1619 int reg = (*data & 0x7) | (rex_b() ? 8 : 0);
1621 AppendToBuffer(
"nop");
1623 AppendToBuffer(
"xchg%c rax,%s",
1624 operand_size_code(),
1625 NameOfCPURegister(reg));
1647 byte opcode = *data;
1649 bool is_32bit = (opcode >= 0xB8);
1650 int reg = (opcode & 0x7) | (rex_b() ? 8 : 0);
1652 AppendToBuffer(
"mov%c %s,",
1653 operand_size_code(),
1654 NameOfCPURegister(reg));
1655 data += PrintImmediate(data, OPERAND_DOUBLEWORD_SIZE);
1657 AppendToBuffer(
"movb %s,",
1658 NameOfByteCPURegister(reg));
1659 data += PrintImmediate(data, OPERAND_BYTE_SIZE);
1666 get_modrm(*data, &mod, ®op, &rm);
1668 AppendToBuffer(
"decb ");
1669 data += PrintRightByteOperand(data);
1671 UnimplementedInstruction();
1676 AppendToBuffer(
"push 0x%x", *
reinterpret_cast<int32_t*
>(data + 1));
1681 AppendToBuffer(
"push 0x%x", *
reinterpret_cast<int8_t*
>(data + 1));
1687 switch (operand_size()) {
1688 case OPERAND_DOUBLEWORD_SIZE: {
1689 const char* memory_location = NameOfAddress(
1690 reinterpret_cast<byte*
>(
1691 *
reinterpret_cast<int32_t*
>(data + 1)));
1692 if (*data == 0xA1) {
1693 AppendToBuffer(
"movzxlq rax,(%s)", memory_location);
1695 AppendToBuffer(
"movzxlq (%s),rax", memory_location);
1700 case OPERAND_QUADWORD_SIZE: {
1702 const char* memory_location = NameOfAddress(
1703 *
reinterpret_cast<byte**
>(data + 1));
1704 if (*data == 0xA1) {
1705 AppendToBuffer(
"movq rax,(%s)", memory_location);
1707 AppendToBuffer(
"movq (%s),rax", memory_location);
1713 UnimplementedInstruction();
1719 AppendToBuffer(
"test al,0x%x", *
reinterpret_cast<uint8_t*
>(data + 1));
1725 switch (operand_size()) {
1726 case OPERAND_WORD_SIZE:
1727 value = *
reinterpret_cast<uint16_t*
>(data + 1);
1730 case OPERAND_DOUBLEWORD_SIZE:
1731 value = *
reinterpret_cast<uint32_t*
>(data + 1);
1734 case OPERAND_QUADWORD_SIZE:
1735 value = *
reinterpret_cast<int32_t*
>(data + 1);
1742 operand_size_code(),
1749 data += ShiftInstruction(data);
1754 byte_size_operand_ =
true;
1755 data += ShiftInstruction(data);
1765 data += FPUInstruction(data);
1769 data += JumpShort(data);
1773 byte_size_operand_ =
true;
1775 data += F6F7Instruction(data);
1779 AppendToBuffer(
"cmp al,0x%x", *
reinterpret_cast<int8_t*
>(data + 1));
1784 UnimplementedInstruction();
1789 if (tmp_buffer_pos_ <
sizeof tmp_buffer_) {
1790 tmp_buffer_[tmp_buffer_pos_] =
'\0';
1793 int instr_len =
static_cast<int>(data - instr);
1798 for (
byte* bp = instr; bp < data; bp++) {
1801 for (
int i = 6 - instr_len;
i >= 0;
i--) {
1806 tmp_buffer_.
start());
1814 static const char* cpu_regs[16] = {
1815 "rax",
"rcx",
"rdx",
"rbx",
"rsp",
"rbp",
"rsi",
"rdi",
1816 "r8",
"r9",
"r10",
"r11",
"r12",
"r13",
"r14",
"r15"
1820 static const char* byte_cpu_regs[16] = {
1821 "al",
"cl",
"dl",
"bl",
"spl",
"bpl",
"sil",
"dil",
1822 "r8l",
"r9l",
"r10l",
"r11l",
"r12l",
"r13l",
"r14l",
"r15l"
1826 static const char* xmm_regs[16] = {
1827 "xmm0",
"xmm1",
"xmm2",
"xmm3",
"xmm4",
"xmm5",
"xmm6",
"xmm7",
1828 "xmm8",
"xmm9",
"xmm10",
"xmm11",
"xmm12",
"xmm13",
"xmm14",
"xmm15"
1844 if (0 <= reg && reg < 16)
1845 return cpu_regs[reg];
1851 if (0 <= reg && reg < 16)
1852 return byte_cpu_regs[reg];
1858 if (0 <= reg && reg < 16)
1859 return xmm_regs[reg];
1874 : converter_(converter) { }
1876 Disassembler::~Disassembler() { }
1880 byte* instruction) {
1881 DisassemblerX64 d(converter_, CONTINUE_ON_UNIMPLEMENTED_OPCODE);
1882 return d.InstructionDecode(buffer, instruction);
1887 int Disassembler::ConstantPoolSizeAt(
byte* instruction) {
1892 void Disassembler::Disassemble(FILE* f,
byte* begin,
byte* end) {
1893 NameConverter converter;
1894 Disassembler d(converter);
1895 for (
byte*
pc = begin;
pc < end;) {
1899 pc += d.InstructionDecode(buffer,
pc);
1900 fprintf(f,
"%p", prev_pc);
1903 for (
byte* bp = prev_pc; bp <
pc; bp++) {
1904 fprintf(f,
"%02x", *bp);
1906 for (
int i = 6 -
static_cast<int>(
pc - prev_pc);
i >= 0;
i--) {
1909 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 size
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 LAZY_INSTANCE_INITIALIZER
#define DCHECK_NE(v1, v2)
#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)