OLD | NEW |
1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include <assert.h> | 5 #include <assert.h> |
6 #include <stdio.h> | 6 #include <stdio.h> |
7 #include <stdarg.h> | 7 #include <stdarg.h> |
8 | 8 |
9 #include "v8.h" | 9 #include "v8.h" |
10 | 10 |
11 #if V8_TARGET_ARCH_IA32 | 11 #if V8_TARGET_ARCH_X87 |
12 | 12 |
13 #include "disasm.h" | 13 #include "disasm.h" |
14 | 14 |
15 namespace disasm { | 15 namespace disasm { |
16 | 16 |
17 enum OperandOrder { | 17 enum OperandOrder { |
18 UNSET_OP_ORDER = 0, | 18 UNSET_OP_ORDER = 0, |
19 REG_OPER_OP_ORDER, | 19 REG_OPER_OP_ORDER, |
20 OPER_REG_OP_ORDER | 20 OPER_REG_OP_ORDER |
21 }; | 21 }; |
(...skipping 211 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
233 void InstructionTable::AddJumpConditionalShort() { | 233 void InstructionTable::AddJumpConditionalShort() { |
234 for (byte b = 0x70; b <= 0x7F; b++) { | 234 for (byte b = 0x70; b <= 0x7F; b++) { |
235 InstructionDesc* id = &instructions_[b]; | 235 InstructionDesc* id = &instructions_[b]; |
236 ASSERT_EQ(NO_INSTR, id->type); // Information not already entered. | 236 ASSERT_EQ(NO_INSTR, id->type); // Information not already entered. |
237 id->mnem = jump_conditional_mnem[b & 0x0F]; | 237 id->mnem = jump_conditional_mnem[b & 0x0F]; |
238 id->type = JUMP_CONDITIONAL_SHORT_INSTR; | 238 id->type = JUMP_CONDITIONAL_SHORT_INSTR; |
239 } | 239 } |
240 } | 240 } |
241 | 241 |
242 | 242 |
243 // The IA32 disassembler implementation. | 243 // The X87 disassembler implementation. |
244 class DisassemblerIA32 { | 244 class DisassemblerX87 { |
245 public: | 245 public: |
246 DisassemblerIA32(const NameConverter& converter, | 246 DisassemblerX87(const NameConverter& converter, |
247 bool abort_on_unimplemented = true) | 247 bool abort_on_unimplemented = true) |
248 : converter_(converter), | 248 : converter_(converter), |
249 instruction_table_(InstructionTable::get_instance()), | 249 instruction_table_(InstructionTable::get_instance()), |
250 tmp_buffer_pos_(0), | 250 tmp_buffer_pos_(0), |
251 abort_on_unimplemented_(abort_on_unimplemented) { | 251 abort_on_unimplemented_(abort_on_unimplemented) { |
252 tmp_buffer_[0] = '\0'; | 252 tmp_buffer_[0] = '\0'; |
253 } | 253 } |
254 | 254 |
255 virtual ~DisassemblerIA32() {} | 255 virtual ~DisassemblerX87() {} |
256 | 256 |
257 // Writes one disassembled instruction into 'buffer' (0-terminated). | 257 // Writes one disassembled instruction into 'buffer' (0-terminated). |
258 // Returns the length of the disassembled machine instruction in bytes. | 258 // Returns the length of the disassembled machine instruction in bytes. |
259 int InstructionDecode(v8::internal::Vector<char> buffer, byte* instruction); | 259 int InstructionDecode(v8::internal::Vector<char> buffer, byte* instruction); |
260 | 260 |
261 private: | 261 private: |
262 const NameConverter& converter_; | 262 const NameConverter& converter_; |
263 InstructionTable* instruction_table_; | 263 InstructionTable* instruction_table_; |
264 v8::internal::EmbeddedVector<char, 128> tmp_buffer_; | 264 v8::internal::EmbeddedVector<char, 128> tmp_buffer_; |
265 unsigned int tmp_buffer_pos_; | 265 unsigned int tmp_buffer_pos_; |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
315 *rm = data & 7; | 315 *rm = data & 7; |
316 } | 316 } |
317 | 317 |
318 | 318 |
319 static void get_sib(byte data, int* scale, int* index, int* base) { | 319 static void get_sib(byte data, int* scale, int* index, int* base) { |
320 *scale = (data >> 6) & 3; | 320 *scale = (data >> 6) & 3; |
321 *index = (data >> 3) & 7; | 321 *index = (data >> 3) & 7; |
322 *base = data & 7; | 322 *base = data & 7; |
323 } | 323 } |
324 | 324 |
325 typedef const char* (DisassemblerIA32::*RegisterNameMapping)(int reg) const; | 325 typedef const char* (DisassemblerX87::*RegisterNameMapping)(int reg) const; |
326 | 326 |
327 int PrintRightOperandHelper(byte* modrmp, RegisterNameMapping register_name); | 327 int PrintRightOperandHelper(byte* modrmp, RegisterNameMapping register_name); |
328 int PrintRightOperand(byte* modrmp); | 328 int PrintRightOperand(byte* modrmp); |
329 int PrintRightByteOperand(byte* modrmp); | 329 int PrintRightByteOperand(byte* modrmp); |
330 int PrintRightXMMOperand(byte* modrmp); | 330 int PrintRightXMMOperand(byte* modrmp); |
331 int PrintOperands(const char* mnem, OperandOrder op_order, byte* data); | 331 int PrintOperands(const char* mnem, OperandOrder op_order, byte* data); |
332 int PrintImmediateOp(byte* data); | 332 int PrintImmediateOp(byte* data); |
333 int F7Instruction(byte* data); | 333 int F7Instruction(byte* data); |
334 int D1D3C1Instruction(byte* data); | 334 int D1D3C1Instruction(byte* data); |
335 int JumpShort(byte* data); | 335 int JumpShort(byte* data); |
(...skipping 10 matching lines...) Expand all Loading... |
346 void UnimplementedInstruction() { | 346 void UnimplementedInstruction() { |
347 if (abort_on_unimplemented_) { | 347 if (abort_on_unimplemented_) { |
348 UNIMPLEMENTED(); | 348 UNIMPLEMENTED(); |
349 } else { | 349 } else { |
350 AppendToBuffer("'Unimplemented Instruction'"); | 350 AppendToBuffer("'Unimplemented Instruction'"); |
351 } | 351 } |
352 } | 352 } |
353 }; | 353 }; |
354 | 354 |
355 | 355 |
356 void DisassemblerIA32::AppendToBuffer(const char* format, ...) { | 356 void DisassemblerX87::AppendToBuffer(const char* format, ...) { |
357 v8::internal::Vector<char> buf = tmp_buffer_ + tmp_buffer_pos_; | 357 v8::internal::Vector<char> buf = tmp_buffer_ + tmp_buffer_pos_; |
358 va_list args; | 358 va_list args; |
359 va_start(args, format); | 359 va_start(args, format); |
360 int result = v8::internal::OS::VSNPrintF(buf, format, args); | 360 int result = v8::internal::OS::VSNPrintF(buf, format, args); |
361 va_end(args); | 361 va_end(args); |
362 tmp_buffer_pos_ += result; | 362 tmp_buffer_pos_ += result; |
363 } | 363 } |
364 | 364 |
365 int DisassemblerIA32::PrintRightOperandHelper( | 365 int DisassemblerX87::PrintRightOperandHelper( |
366 byte* modrmp, | 366 byte* modrmp, |
367 RegisterNameMapping direct_register_name) { | 367 RegisterNameMapping direct_register_name) { |
368 int mod, regop, rm; | 368 int mod, regop, rm; |
369 get_modrm(*modrmp, &mod, ®op, &rm); | 369 get_modrm(*modrmp, &mod, ®op, &rm); |
370 RegisterNameMapping register_name = (mod == 3) ? direct_register_name : | 370 RegisterNameMapping register_name = (mod == 3) ? direct_register_name : |
371 &DisassemblerIA32::NameOfCPURegister; | 371 &DisassemblerX87::NameOfCPURegister; |
372 switch (mod) { | 372 switch (mod) { |
373 case 0: | 373 case 0: |
374 if (rm == ebp) { | 374 if (rm == ebp) { |
375 int32_t disp = *reinterpret_cast<int32_t*>(modrmp+1); | 375 int32_t disp = *reinterpret_cast<int32_t*>(modrmp+1); |
376 AppendToBuffer("[0x%x]", disp); | 376 AppendToBuffer("[0x%x]", disp); |
377 return 5; | 377 return 5; |
378 } else if (rm == esp) { | 378 } else if (rm == esp) { |
379 byte sib = *(modrmp + 1); | 379 byte sib = *(modrmp + 1); |
380 int scale, index, base; | 380 int scale, index, base; |
381 get_sib(sib, &scale, &index, &base); | 381 get_sib(sib, &scale, &index, &base); |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
443 AppendToBuffer("%s", (this->*register_name)(rm)); | 443 AppendToBuffer("%s", (this->*register_name)(rm)); |
444 return 1; | 444 return 1; |
445 default: | 445 default: |
446 UnimplementedInstruction(); | 446 UnimplementedInstruction(); |
447 return 1; | 447 return 1; |
448 } | 448 } |
449 UNREACHABLE(); | 449 UNREACHABLE(); |
450 } | 450 } |
451 | 451 |
452 | 452 |
453 int DisassemblerIA32::PrintRightOperand(byte* modrmp) { | 453 int DisassemblerX87::PrintRightOperand(byte* modrmp) { |
454 return PrintRightOperandHelper(modrmp, &DisassemblerIA32::NameOfCPURegister); | 454 return PrintRightOperandHelper(modrmp, &DisassemblerX87::NameOfCPURegister); |
455 } | 455 } |
456 | 456 |
457 | 457 |
458 int DisassemblerIA32::PrintRightByteOperand(byte* modrmp) { | 458 int DisassemblerX87::PrintRightByteOperand(byte* modrmp) { |
459 return PrintRightOperandHelper(modrmp, | 459 return PrintRightOperandHelper(modrmp, |
460 &DisassemblerIA32::NameOfByteCPURegister); | 460 &DisassemblerX87::NameOfByteCPURegister); |
461 } | 461 } |
462 | 462 |
463 | 463 |
464 int DisassemblerIA32::PrintRightXMMOperand(byte* modrmp) { | 464 int DisassemblerX87::PrintRightXMMOperand(byte* modrmp) { |
465 return PrintRightOperandHelper(modrmp, | 465 return PrintRightOperandHelper(modrmp, |
466 &DisassemblerIA32::NameOfXMMRegister); | 466 &DisassemblerX87::NameOfXMMRegister); |
467 } | 467 } |
468 | 468 |
469 | 469 |
470 // Returns number of bytes used including the current *data. | 470 // Returns number of bytes used including the current *data. |
471 // Writes instruction's mnemonic, left and right operands to 'tmp_buffer_'. | 471 // Writes instruction's mnemonic, left and right operands to 'tmp_buffer_'. |
472 int DisassemblerIA32::PrintOperands(const char* mnem, | 472 int DisassemblerX87::PrintOperands(const char* mnem, |
473 OperandOrder op_order, | 473 OperandOrder op_order, |
474 byte* data) { | 474 byte* data) { |
475 byte modrm = *data; | 475 byte modrm = *data; |
476 int mod, regop, rm; | 476 int mod, regop, rm; |
477 get_modrm(modrm, &mod, ®op, &rm); | 477 get_modrm(modrm, &mod, ®op, &rm); |
478 int advance = 0; | 478 int advance = 0; |
479 switch (op_order) { | 479 switch (op_order) { |
480 case REG_OPER_OP_ORDER: { | 480 case REG_OPER_OP_ORDER: { |
481 AppendToBuffer("%s %s,", mnem, NameOfCPURegister(regop)); | 481 AppendToBuffer("%s %s,", mnem, NameOfCPURegister(regop)); |
482 advance = PrintRightOperand(data); | 482 advance = PrintRightOperand(data); |
483 break; | 483 break; |
484 } | 484 } |
485 case OPER_REG_OP_ORDER: { | 485 case OPER_REG_OP_ORDER: { |
486 AppendToBuffer("%s ", mnem); | 486 AppendToBuffer("%s ", mnem); |
487 advance = PrintRightOperand(data); | 487 advance = PrintRightOperand(data); |
488 AppendToBuffer(",%s", NameOfCPURegister(regop)); | 488 AppendToBuffer(",%s", NameOfCPURegister(regop)); |
489 break; | 489 break; |
490 } | 490 } |
491 default: | 491 default: |
492 UNREACHABLE(); | 492 UNREACHABLE(); |
493 break; | 493 break; |
494 } | 494 } |
495 return advance; | 495 return advance; |
496 } | 496 } |
497 | 497 |
498 | 498 |
499 // Returns number of bytes used by machine instruction, including *data byte. | 499 // Returns number of bytes used by machine instruction, including *data byte. |
500 // Writes immediate instructions to 'tmp_buffer_'. | 500 // Writes immediate instructions to 'tmp_buffer_'. |
501 int DisassemblerIA32::PrintImmediateOp(byte* data) { | 501 int DisassemblerX87::PrintImmediateOp(byte* data) { |
502 bool sign_extension_bit = (*data & 0x02) != 0; | 502 bool sign_extension_bit = (*data & 0x02) != 0; |
503 byte modrm = *(data+1); | 503 byte modrm = *(data+1); |
504 int mod, regop, rm; | 504 int mod, regop, rm; |
505 get_modrm(modrm, &mod, ®op, &rm); | 505 get_modrm(modrm, &mod, ®op, &rm); |
506 const char* mnem = "Imm???"; | 506 const char* mnem = "Imm???"; |
507 switch (regop) { | 507 switch (regop) { |
508 case 0: mnem = "add"; break; | 508 case 0: mnem = "add"; break; |
509 case 1: mnem = "or"; break; | 509 case 1: mnem = "or"; break; |
510 case 2: mnem = "adc"; break; | 510 case 2: mnem = "adc"; break; |
511 case 4: mnem = "and"; break; | 511 case 4: mnem = "and"; break; |
512 case 5: mnem = "sub"; break; | 512 case 5: mnem = "sub"; break; |
513 case 6: mnem = "xor"; break; | 513 case 6: mnem = "xor"; break; |
514 case 7: mnem = "cmp"; break; | 514 case 7: mnem = "cmp"; break; |
515 default: UnimplementedInstruction(); | 515 default: UnimplementedInstruction(); |
516 } | 516 } |
517 AppendToBuffer("%s ", mnem); | 517 AppendToBuffer("%s ", mnem); |
518 int count = PrintRightOperand(data+1); | 518 int count = PrintRightOperand(data+1); |
519 if (sign_extension_bit) { | 519 if (sign_extension_bit) { |
520 AppendToBuffer(",0x%x", *(data + 1 + count)); | 520 AppendToBuffer(",0x%x", *(data + 1 + count)); |
521 return 1 + count + 1 /*int8*/; | 521 return 1 + count + 1 /*int8*/; |
522 } else { | 522 } else { |
523 AppendToBuffer(",0x%x", *reinterpret_cast<int32_t*>(data + 1 + count)); | 523 AppendToBuffer(",0x%x", *reinterpret_cast<int32_t*>(data + 1 + count)); |
524 return 1 + count + 4 /*int32_t*/; | 524 return 1 + count + 4 /*int32_t*/; |
525 } | 525 } |
526 } | 526 } |
527 | 527 |
528 | 528 |
529 // Returns number of bytes used, including *data. | 529 // Returns number of bytes used, including *data. |
530 int DisassemblerIA32::F7Instruction(byte* data) { | 530 int DisassemblerX87::F7Instruction(byte* data) { |
531 ASSERT_EQ(0xF7, *data); | 531 ASSERT_EQ(0xF7, *data); |
532 byte modrm = *(data+1); | 532 byte modrm = *(data+1); |
533 int mod, regop, rm; | 533 int mod, regop, rm; |
534 get_modrm(modrm, &mod, ®op, &rm); | 534 get_modrm(modrm, &mod, ®op, &rm); |
535 if (mod == 3 && regop != 0) { | 535 if (mod == 3 && regop != 0) { |
536 const char* mnem = NULL; | 536 const char* mnem = NULL; |
537 switch (regop) { | 537 switch (regop) { |
538 case 2: mnem = "not"; break; | 538 case 2: mnem = "not"; break; |
539 case 3: mnem = "neg"; break; | 539 case 3: mnem = "neg"; break; |
540 case 4: mnem = "mul"; break; | 540 case 4: mnem = "mul"; break; |
(...skipping 13 matching lines...) Expand all Loading... |
554 int32_t imm = *reinterpret_cast<int32_t*>(data+1+count); | 554 int32_t imm = *reinterpret_cast<int32_t*>(data+1+count); |
555 AppendToBuffer(",0x%x", imm); | 555 AppendToBuffer(",0x%x", imm); |
556 return 1+count+4 /*int32_t*/; | 556 return 1+count+4 /*int32_t*/; |
557 } else { | 557 } else { |
558 UnimplementedInstruction(); | 558 UnimplementedInstruction(); |
559 return 2; | 559 return 2; |
560 } | 560 } |
561 } | 561 } |
562 | 562 |
563 | 563 |
564 int DisassemblerIA32::D1D3C1Instruction(byte* data) { | 564 int DisassemblerX87::D1D3C1Instruction(byte* data) { |
565 byte op = *data; | 565 byte op = *data; |
566 ASSERT(op == 0xD1 || op == 0xD3 || op == 0xC1); | 566 ASSERT(op == 0xD1 || op == 0xD3 || op == 0xC1); |
567 byte modrm = *(data+1); | 567 byte modrm = *(data+1); |
568 int mod, regop, rm; | 568 int mod, regop, rm; |
569 get_modrm(modrm, &mod, ®op, &rm); | 569 get_modrm(modrm, &mod, ®op, &rm); |
570 int imm8 = -1; | 570 int imm8 = -1; |
571 int num_bytes = 2; | 571 int num_bytes = 2; |
572 if (mod == 3) { | 572 if (mod == 3) { |
573 const char* mnem = NULL; | 573 const char* mnem = NULL; |
574 switch (regop) { | 574 switch (regop) { |
(...skipping 22 matching lines...) Expand all Loading... |
597 AppendToBuffer("cl"); | 597 AppendToBuffer("cl"); |
598 } | 598 } |
599 } else { | 599 } else { |
600 UnimplementedInstruction(); | 600 UnimplementedInstruction(); |
601 } | 601 } |
602 return num_bytes; | 602 return num_bytes; |
603 } | 603 } |
604 | 604 |
605 | 605 |
606 // Returns number of bytes used, including *data. | 606 // Returns number of bytes used, including *data. |
607 int DisassemblerIA32::JumpShort(byte* data) { | 607 int DisassemblerX87::JumpShort(byte* data) { |
608 ASSERT_EQ(0xEB, *data); | 608 ASSERT_EQ(0xEB, *data); |
609 byte b = *(data+1); | 609 byte b = *(data+1); |
610 byte* dest = data + static_cast<int8_t>(b) + 2; | 610 byte* dest = data + static_cast<int8_t>(b) + 2; |
611 AppendToBuffer("jmp %s", NameOfAddress(dest)); | 611 AppendToBuffer("jmp %s", NameOfAddress(dest)); |
612 return 2; | 612 return 2; |
613 } | 613 } |
614 | 614 |
615 | 615 |
616 // Returns number of bytes used, including *data. | 616 // Returns number of bytes used, including *data. |
617 int DisassemblerIA32::JumpConditional(byte* data, const char* comment) { | 617 int DisassemblerX87::JumpConditional(byte* data, const char* comment) { |
618 ASSERT_EQ(0x0F, *data); | 618 ASSERT_EQ(0x0F, *data); |
619 byte cond = *(data+1) & 0x0F; | 619 byte cond = *(data+1) & 0x0F; |
620 byte* dest = data + *reinterpret_cast<int32_t*>(data+2) + 6; | 620 byte* dest = data + *reinterpret_cast<int32_t*>(data+2) + 6; |
621 const char* mnem = jump_conditional_mnem[cond]; | 621 const char* mnem = jump_conditional_mnem[cond]; |
622 AppendToBuffer("%s %s", mnem, NameOfAddress(dest)); | 622 AppendToBuffer("%s %s", mnem, NameOfAddress(dest)); |
623 if (comment != NULL) { | 623 if (comment != NULL) { |
624 AppendToBuffer(", %s", comment); | 624 AppendToBuffer(", %s", comment); |
625 } | 625 } |
626 return 6; // includes 0x0F | 626 return 6; // includes 0x0F |
627 } | 627 } |
628 | 628 |
629 | 629 |
630 // Returns number of bytes used, including *data. | 630 // Returns number of bytes used, including *data. |
631 int DisassemblerIA32::JumpConditionalShort(byte* data, const char* comment) { | 631 int DisassemblerX87::JumpConditionalShort(byte* data, const char* comment) { |
632 byte cond = *data & 0x0F; | 632 byte cond = *data & 0x0F; |
633 byte b = *(data+1); | 633 byte b = *(data+1); |
634 byte* dest = data + static_cast<int8_t>(b) + 2; | 634 byte* dest = data + static_cast<int8_t>(b) + 2; |
635 const char* mnem = jump_conditional_mnem[cond]; | 635 const char* mnem = jump_conditional_mnem[cond]; |
636 AppendToBuffer("%s %s", mnem, NameOfAddress(dest)); | 636 AppendToBuffer("%s %s", mnem, NameOfAddress(dest)); |
637 if (comment != NULL) { | 637 if (comment != NULL) { |
638 AppendToBuffer(", %s", comment); | 638 AppendToBuffer(", %s", comment); |
639 } | 639 } |
640 return 2; | 640 return 2; |
641 } | 641 } |
642 | 642 |
643 | 643 |
644 // Returns number of bytes used, including *data. | 644 // Returns number of bytes used, including *data. |
645 int DisassemblerIA32::SetCC(byte* data) { | 645 int DisassemblerX87::SetCC(byte* data) { |
646 ASSERT_EQ(0x0F, *data); | 646 ASSERT_EQ(0x0F, *data); |
647 byte cond = *(data+1) & 0x0F; | 647 byte cond = *(data+1) & 0x0F; |
648 const char* mnem = set_conditional_mnem[cond]; | 648 const char* mnem = set_conditional_mnem[cond]; |
649 AppendToBuffer("%s ", mnem); | 649 AppendToBuffer("%s ", mnem); |
650 PrintRightByteOperand(data+2); | 650 PrintRightByteOperand(data+2); |
651 return 3; // Includes 0x0F. | 651 return 3; // Includes 0x0F. |
652 } | 652 } |
653 | 653 |
654 | 654 |
655 // Returns number of bytes used, including *data. | 655 // Returns number of bytes used, including *data. |
656 int DisassemblerIA32::CMov(byte* data) { | 656 int DisassemblerX87::CMov(byte* data) { |
657 ASSERT_EQ(0x0F, *data); | 657 ASSERT_EQ(0x0F, *data); |
658 byte cond = *(data + 1) & 0x0F; | 658 byte cond = *(data + 1) & 0x0F; |
659 const char* mnem = conditional_move_mnem[cond]; | 659 const char* mnem = conditional_move_mnem[cond]; |
660 int op_size = PrintOperands(mnem, REG_OPER_OP_ORDER, data + 2); | 660 int op_size = PrintOperands(mnem, REG_OPER_OP_ORDER, data + 2); |
661 return 2 + op_size; // includes 0x0F | 661 return 2 + op_size; // includes 0x0F |
662 } | 662 } |
663 | 663 |
664 | 664 |
665 // Returns number of bytes used, including *data. | 665 // Returns number of bytes used, including *data. |
666 int DisassemblerIA32::FPUInstruction(byte* data) { | 666 int DisassemblerX87::FPUInstruction(byte* data) { |
667 byte escape_opcode = *data; | 667 byte escape_opcode = *data; |
668 ASSERT_EQ(0xD8, escape_opcode & 0xF8); | 668 ASSERT_EQ(0xD8, escape_opcode & 0xF8); |
669 byte modrm_byte = *(data+1); | 669 byte modrm_byte = *(data+1); |
670 | 670 |
671 if (modrm_byte >= 0xC0) { | 671 if (modrm_byte >= 0xC0) { |
672 return RegisterFPUInstruction(escape_opcode, modrm_byte); | 672 return RegisterFPUInstruction(escape_opcode, modrm_byte); |
673 } else { | 673 } else { |
674 return MemoryFPUInstruction(escape_opcode, modrm_byte, data+1); | 674 return MemoryFPUInstruction(escape_opcode, modrm_byte, data+1); |
675 } | 675 } |
676 } | 676 } |
677 | 677 |
678 int DisassemblerIA32::MemoryFPUInstruction(int escape_opcode, | 678 int DisassemblerX87::MemoryFPUInstruction(int escape_opcode, |
679 int modrm_byte, | 679 int modrm_byte, |
680 byte* modrm_start) { | 680 byte* modrm_start) { |
681 const char* mnem = "?"; | 681 const char* mnem = "?"; |
682 int regop = (modrm_byte >> 3) & 0x7; // reg/op field of modrm byte. | 682 int regop = (modrm_byte >> 3) & 0x7; // reg/op field of modrm byte. |
683 switch (escape_opcode) { | 683 switch (escape_opcode) { |
684 case 0xD9: switch (regop) { | 684 case 0xD9: switch (regop) { |
685 case 0: mnem = "fld_s"; break; | 685 case 0: mnem = "fld_s"; break; |
686 case 2: mnem = "fst_s"; break; | 686 case 2: mnem = "fst_s"; break; |
687 case 3: mnem = "fstp_s"; break; | 687 case 3: mnem = "fstp_s"; break; |
688 case 7: mnem = "fstcw"; break; | 688 case 7: mnem = "fstcw"; break; |
(...skipping 26 matching lines...) Expand all Loading... |
715 } | 715 } |
716 break; | 716 break; |
717 | 717 |
718 default: UnimplementedInstruction(); | 718 default: UnimplementedInstruction(); |
719 } | 719 } |
720 AppendToBuffer("%s ", mnem); | 720 AppendToBuffer("%s ", mnem); |
721 int count = PrintRightOperand(modrm_start); | 721 int count = PrintRightOperand(modrm_start); |
722 return count + 1; | 722 return count + 1; |
723 } | 723 } |
724 | 724 |
725 int DisassemblerIA32::RegisterFPUInstruction(int escape_opcode, | 725 int DisassemblerX87::RegisterFPUInstruction(int escape_opcode, |
726 byte modrm_byte) { | 726 byte modrm_byte) { |
727 bool has_register = false; // Is the FPU register encoded in modrm_byte? | 727 bool has_register = false; // Is the FPU register encoded in modrm_byte? |
728 const char* mnem = "?"; | 728 const char* mnem = "?"; |
729 | 729 |
730 switch (escape_opcode) { | 730 switch (escape_opcode) { |
731 case 0xD8: | 731 case 0xD8: |
732 has_register = true; | 732 has_register = true; |
733 switch (modrm_byte & 0xF8) { | 733 switch (modrm_byte & 0xF8) { |
734 case 0xC0: mnem = "fadd_i"; break; | 734 case 0xC0: mnem = "fadd_i"; break; |
735 case 0xE0: mnem = "fsub_i"; break; | 735 case 0xE0: mnem = "fsub_i"; break; |
(...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
866 case 0xAD: return "shrd"; | 866 case 0xAD: return "shrd"; |
867 case 0xAC: return "shrd"; // 3-operand version. | 867 case 0xAC: return "shrd"; // 3-operand version. |
868 case 0xAB: return "bts"; | 868 case 0xAB: return "bts"; |
869 case 0xBD: return "bsr"; | 869 case 0xBD: return "bsr"; |
870 default: return NULL; | 870 default: return NULL; |
871 } | 871 } |
872 } | 872 } |
873 | 873 |
874 | 874 |
875 // Disassembled instruction '*instr' and writes it into 'out_buffer'. | 875 // Disassembled instruction '*instr' and writes it into 'out_buffer'. |
876 int DisassemblerIA32::InstructionDecode(v8::internal::Vector<char> out_buffer, | 876 int DisassemblerX87::InstructionDecode(v8::internal::Vector<char> out_buffer, |
877 byte* instr) { | 877 byte* instr) { |
878 tmp_buffer_pos_ = 0; // starting to write as position 0 | 878 tmp_buffer_pos_ = 0; // starting to write as position 0 |
879 byte* data = instr; | 879 byte* data = instr; |
880 // Check for hints. | 880 // Check for hints. |
881 const char* branch_hint = NULL; | 881 const char* branch_hint = NULL; |
882 // We use these two prefixes only with branch prediction | 882 // We use these two prefixes only with branch prediction |
883 if (*data == 0x3E /*ds*/) { | 883 if (*data == 0x3E /*ds*/) { |
884 branch_hint = "predicted taken"; | 884 branch_hint = "predicted taken"; |
885 data++; | 885 data++; |
886 } else if (*data == 0x2E /*cs*/) { | 886 } else if (*data == 0x2E /*cs*/) { |
(...skipping 815 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1702 } | 1702 } |
1703 | 1703 |
1704 | 1704 |
1705 const char* NameConverter::NameOfXMMRegister(int reg) const { | 1705 const char* NameConverter::NameOfXMMRegister(int reg) const { |
1706 if (0 <= reg && reg < 8) return xmm_regs[reg]; | 1706 if (0 <= reg && reg < 8) return xmm_regs[reg]; |
1707 return "noxmmreg"; | 1707 return "noxmmreg"; |
1708 } | 1708 } |
1709 | 1709 |
1710 | 1710 |
1711 const char* NameConverter::NameInCode(byte* addr) const { | 1711 const char* NameConverter::NameInCode(byte* addr) const { |
1712 // IA32 does not embed debug strings at the moment. | 1712 // X87 does not embed debug strings at the moment. |
1713 UNREACHABLE(); | 1713 UNREACHABLE(); |
1714 return ""; | 1714 return ""; |
1715 } | 1715 } |
1716 | 1716 |
1717 | 1717 |
1718 //------------------------------------------------------------------------------ | 1718 //------------------------------------------------------------------------------ |
1719 | 1719 |
1720 Disassembler::Disassembler(const NameConverter& converter) | 1720 Disassembler::Disassembler(const NameConverter& converter) |
1721 : converter_(converter) {} | 1721 : converter_(converter) {} |
1722 | 1722 |
1723 | 1723 |
1724 Disassembler::~Disassembler() {} | 1724 Disassembler::~Disassembler() {} |
1725 | 1725 |
1726 | 1726 |
1727 int Disassembler::InstructionDecode(v8::internal::Vector<char> buffer, | 1727 int Disassembler::InstructionDecode(v8::internal::Vector<char> buffer, |
1728 byte* instruction) { | 1728 byte* instruction) { |
1729 DisassemblerIA32 d(converter_, false /*do not crash if unimplemented*/); | 1729 DisassemblerX87 d(converter_, false /*do not crash if unimplemented*/); |
1730 return d.InstructionDecode(buffer, instruction); | 1730 return d.InstructionDecode(buffer, instruction); |
1731 } | 1731 } |
1732 | 1732 |
1733 | 1733 |
1734 // The IA-32 assembler does not currently use constant pools. | 1734 // The IA-32 assembler does not currently use constant pools. |
1735 int Disassembler::ConstantPoolSizeAt(byte* instruction) { return -1; } | 1735 int Disassembler::ConstantPoolSizeAt(byte* instruction) { return -1; } |
1736 | 1736 |
1737 | 1737 |
1738 /*static*/ void Disassembler::Disassemble(FILE* f, byte* begin, byte* end) { | 1738 /*static*/ void Disassembler::Disassemble(FILE* f, byte* begin, byte* end) { |
1739 NameConverter converter; | 1739 NameConverter converter; |
(...skipping 12 matching lines...) Expand all Loading... |
1752 for (int i = 6 - (pc - prev_pc); i >= 0; i--) { | 1752 for (int i = 6 - (pc - prev_pc); i >= 0; i--) { |
1753 fprintf(f, " "); | 1753 fprintf(f, " "); |
1754 } | 1754 } |
1755 fprintf(f, " %s\n", buffer.start()); | 1755 fprintf(f, " %s\n", buffer.start()); |
1756 } | 1756 } |
1757 } | 1757 } |
1758 | 1758 |
1759 | 1759 |
1760 } // namespace disasm | 1760 } // namespace disasm |
1761 | 1761 |
1762 #endif // V8_TARGET_ARCH_IA32 | 1762 #endif // V8_TARGET_ARCH_X87 |
OLD | NEW |