OLD | NEW |
1 // Copyright 2009 the V8 project authors. All rights reserved. | 1 // Copyright 2009 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
70 XMMRegister xmm12 = { 12 }; | 70 XMMRegister xmm12 = { 12 }; |
71 XMMRegister xmm13 = { 13 }; | 71 XMMRegister xmm13 = { 13 }; |
72 XMMRegister xmm14 = { 14 }; | 72 XMMRegister xmm14 = { 14 }; |
73 XMMRegister xmm15 = { 15 }; | 73 XMMRegister xmm15 = { 15 }; |
74 | 74 |
75 // Safe default is no features. | 75 // Safe default is no features. |
76 uint64_t CpuFeatures::supported_ = 0; | 76 uint64_t CpuFeatures::supported_ = 0; |
77 uint64_t CpuFeatures::enabled_ = 0; | 77 uint64_t CpuFeatures::enabled_ = 0; |
78 | 78 |
79 void CpuFeatures::Probe() { | 79 void CpuFeatures::Probe() { |
80 // TODO(X64): UNIMPLEMENTED | 80 ASSERT(Heap::HasBeenSetup()); |
| 81 ASSERT(supported_ == 0); |
| 82 if (Serializer::enabled()) return; // No features if we might serialize. |
| 83 |
| 84 Assembler assm(NULL, 0); |
| 85 Label cpuid, done; |
| 86 #define __ assm. |
| 87 // Save old esp, since we are going to modify the stack. |
| 88 __ push(rbp); |
| 89 __ pushfq(); |
| 90 __ push(rcx); |
| 91 __ push(rbx); |
| 92 __ movq(rbp, rsp); |
| 93 |
| 94 // If we can modify bit 21 of the EFLAGS register, then CPUID is supported. |
| 95 __ pushfq(); |
| 96 __ pop(rax); |
| 97 __ movq(rdx, rax); |
| 98 __ xor_(rax, Immediate(0x200000)); // Flip bit 21. |
| 99 __ push(rax); |
| 100 __ popfq(); |
| 101 __ pushfq(); |
| 102 __ pop(rax); |
| 103 __ xor_(rax, rdx); // Different if CPUID is supported. |
| 104 __ j(not_zero, &cpuid); |
| 105 |
| 106 // CPUID not supported. Clear the supported features in edx:eax. |
| 107 __ xor_(rax, rax); |
| 108 __ jmp(&done); |
| 109 |
| 110 // Invoke CPUID with 1 in eax to get feature information in |
| 111 // ecx:edx. Temporarily enable CPUID support because we know it's |
| 112 // safe here. |
| 113 __ bind(&cpuid); |
| 114 __ movq(rax, Immediate(1)); |
| 115 supported_ = (1 << CPUID); |
| 116 { Scope fscope(CPUID); |
| 117 __ cpuid(); |
| 118 } |
| 119 supported_ = 0; |
| 120 |
| 121 // Move the result from ecx:edx to rax and make sure to mark the |
| 122 // CPUID feature as supported. |
| 123 __ movl(rax, rdx); // Zero-extended to 64 bits. |
| 124 __ shl(rcx, Immediate(32)); |
| 125 __ or_(rax, rcx); |
| 126 __ or_(rax, Immediate(1 << CPUID)); |
| 127 |
| 128 // Done. |
| 129 __ bind(&done); |
| 130 __ movq(rsp, rbp); |
| 131 __ pop(rbx); |
| 132 __ pop(rcx); |
| 133 __ popfq(); |
| 134 __ pop(rbp); |
| 135 __ ret(0); |
| 136 #undef __ |
| 137 |
| 138 CodeDesc desc; |
| 139 assm.GetCode(&desc); |
| 140 Object* code = |
| 141 Heap::CreateCode(desc, NULL, Code::ComputeFlags(Code::STUB), NULL); |
| 142 if (!code->IsCode()) return; |
| 143 LOG(CodeCreateEvent("Builtin", Code::cast(code), "CpuFeatures::Probe")); |
| 144 typedef uint64_t (*F0)(); |
| 145 F0 probe = FUNCTION_CAST<F0>(Code::cast(code)->entry()); |
| 146 supported_ = probe(); |
81 } | 147 } |
82 | 148 |
83 // ----------------------------------------------------------------------------- | 149 // ----------------------------------------------------------------------------- |
84 // Implementation of Assembler | 150 // Implementation of Assembler |
85 | 151 |
86 #ifdef GENERATED_CODE_COVERAGE | 152 #ifdef GENERATED_CODE_COVERAGE |
87 static void InitCoverageLog(); | 153 static void InitCoverageLog(); |
88 #endif | 154 #endif |
89 | 155 |
90 byte* Assembler::spare_buffer_ = NULL; | 156 byte* Assembler::spare_buffer_ = NULL; |
(...skipping 270 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
361 | 427 |
362 void Assembler::shift(Register dst, int subcode) { | 428 void Assembler::shift(Register dst, int subcode) { |
363 EnsureSpace ensure_space(this); | 429 EnsureSpace ensure_space(this); |
364 last_pc_ = pc_; | 430 last_pc_ = pc_; |
365 emit_rex_64(dst); | 431 emit_rex_64(dst); |
366 emit(0xD3); | 432 emit(0xD3); |
367 emit(0xC0 | (subcode << 3) | (dst.code() & 0x7)); | 433 emit(0xC0 | (subcode << 3) | (dst.code() & 0x7)); |
368 } | 434 } |
369 | 435 |
370 | 436 |
| 437 void Assembler::bt(const Operand& dst, Register src) { |
| 438 EnsureSpace ensure_space(this); |
| 439 last_pc_ = pc_; |
| 440 emit_rex_64(src, dst); |
| 441 emit(0x0F); |
| 442 emit(0xA3); |
| 443 emit_operand(src, dst); |
| 444 } |
| 445 |
| 446 |
| 447 void Assembler::bts(const Operand& dst, Register src) { |
| 448 EnsureSpace ensure_space(this); |
| 449 last_pc_ = pc_; |
| 450 emit_rex_64(src, dst); |
| 451 emit(0x0F); |
| 452 emit(0xAB); |
| 453 emit_operand(src, dst); |
| 454 } |
| 455 |
| 456 |
371 void Assembler::call(Label* L) { | 457 void Assembler::call(Label* L) { |
372 EnsureSpace ensure_space(this); | 458 EnsureSpace ensure_space(this); |
373 last_pc_ = pc_; | 459 last_pc_ = pc_; |
374 // 1110 1000 #32-bit disp | 460 // 1110 1000 #32-bit disp |
375 emit(0xE8); | 461 emit(0xE8); |
376 if (L->is_bound()) { | 462 if (L->is_bound()) { |
377 int offset = L->pos() - pc_offset() - sizeof(int32_t); | 463 int offset = L->pos() - pc_offset() - sizeof(int32_t); |
378 ASSERT(offset <= 0); | 464 ASSERT(offset <= 0); |
379 emitl(offset); | 465 emitl(offset); |
380 } else if (L->is_linked()) { | 466 } else if (L->is_linked()) { |
(...skipping 13 matching lines...) Expand all Loading... |
394 last_pc_ = pc_; | 480 last_pc_ = pc_; |
395 // Opcode: FF /2 r64 | 481 // Opcode: FF /2 r64 |
396 if (!is_uint3(adr.code())) { | 482 if (!is_uint3(adr.code())) { |
397 emit_rex_64(adr); | 483 emit_rex_64(adr); |
398 } | 484 } |
399 emit(0xFF); | 485 emit(0xFF); |
400 emit(0xD0 | (adr.code() & 0x07)); | 486 emit(0xD0 | (adr.code() & 0x07)); |
401 } | 487 } |
402 | 488 |
403 | 489 |
| 490 void Assembler::cpuid() { |
| 491 ASSERT(CpuFeatures::IsEnabled(CpuFeatures::CPUID)); |
| 492 EnsureSpace ensure_space(this); |
| 493 last_pc_ = pc_; |
| 494 emit(0x0F); |
| 495 emit(0xA2); |
| 496 } |
| 497 |
| 498 |
| 499 void Assembler::cqo() { |
| 500 EnsureSpace ensure_space(this); |
| 501 last_pc_ = pc_; |
| 502 emit_rex_64(); |
| 503 emit(0x99); |
| 504 } |
| 505 |
| 506 |
404 void Assembler::dec(Register dst) { | 507 void Assembler::dec(Register dst) { |
405 EnsureSpace ensure_space(this); | 508 EnsureSpace ensure_space(this); |
406 last_pc_ = pc_; | 509 last_pc_ = pc_; |
407 emit_rex_64(dst); | 510 emit_rex_64(dst); |
408 emit(0xFF); | 511 emit(0xFF); |
409 emit(0xC8 | (dst.code() & 0x7)); | 512 emit(0xC8 | (dst.code() & 0x7)); |
410 } | 513 } |
411 | 514 |
412 | 515 |
413 void Assembler::dec(const Operand& dst) { | 516 void Assembler::dec(const Operand& dst) { |
414 EnsureSpace ensure_space(this); | 517 EnsureSpace ensure_space(this); |
415 last_pc_ = pc_; | 518 last_pc_ = pc_; |
416 emit_rex_64(dst); | 519 emit_rex_64(dst); |
417 emit(0xFF); | 520 emit(0xFF); |
418 emit_operand(1, dst); | 521 emit_operand(1, dst); |
419 } | 522 } |
420 | 523 |
421 | 524 |
| 525 void Assembler::enter(Immediate size) { |
| 526 EnsureSpace ensure_space(this); |
| 527 last_pc_ = pc_; |
| 528 emit(0xC8); |
| 529 emitw(size.value_); // 16 bit operand, always. |
| 530 emit(0); |
| 531 } |
| 532 |
| 533 |
422 void Assembler::hlt() { | 534 void Assembler::hlt() { |
423 EnsureSpace ensure_space(this); | 535 EnsureSpace ensure_space(this); |
424 last_pc_ = pc_; | 536 last_pc_ = pc_; |
425 emit(0xF4); | 537 emit(0xF4); |
426 } | 538 } |
427 | 539 |
428 | 540 |
429 void Assembler::inc(Register dst) { | 541 void Assembler::inc(Register dst) { |
430 EnsureSpace ensure_space(this); | 542 EnsureSpace ensure_space(this); |
431 last_pc_ = pc_; | 543 last_pc_ = pc_; |
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
523 last_pc_ = pc_; | 635 last_pc_ = pc_; |
524 // Opcode FF/4 r64 | 636 // Opcode FF/4 r64 |
525 if (!is_uint3(target.code())) { | 637 if (!is_uint3(target.code())) { |
526 emit_rex_64(target); | 638 emit_rex_64(target); |
527 } | 639 } |
528 emit(0xFF); | 640 emit(0xFF); |
529 emit(0xE0 | target.code() & 0x07); | 641 emit(0xE0 | target.code() & 0x07); |
530 } | 642 } |
531 | 643 |
532 | 644 |
| 645 void Assembler::lea(Register dst, const Operand& src) { |
| 646 EnsureSpace ensure_space(this); |
| 647 last_pc_ = pc_; |
| 648 emit_rex_64(dst, src); |
| 649 emit(0x8D); |
| 650 emit_operand(dst, src); |
| 651 } |
| 652 |
| 653 |
| 654 void Assembler::leave() { |
| 655 EnsureSpace ensure_space(this); |
| 656 last_pc_ = pc_; |
| 657 emit(0xC9); |
| 658 } |
| 659 |
| 660 |
| 661 void Assembler::movl(Register dst, const Operand& src) { |
| 662 EnsureSpace ensure_space(this); |
| 663 last_pc_ = pc_; |
| 664 emit_optional_rex_32(dst, src); |
| 665 emit(0x8B); |
| 666 emit_operand(dst, src); |
| 667 } |
| 668 |
| 669 |
| 670 void Assembler::movl(Register dst, Register src) { |
| 671 EnsureSpace ensure_space(this); |
| 672 last_pc_ = pc_; |
| 673 emit_optional_rex_32(dst, src); |
| 674 emit(0x8B); |
| 675 emit(0xC0 | (dst.code() & 0x7) << 3 | (src.code() & 0x7)); |
| 676 } |
| 677 |
| 678 |
| 679 void Assembler::movl(const Operand& dst, Register src) { |
| 680 EnsureSpace ensure_space(this); |
| 681 last_pc_ = pc_; |
| 682 emit_optional_rex_32(src, dst); |
| 683 emit(0x89); |
| 684 emit_operand(src, dst); |
| 685 } |
| 686 |
| 687 |
533 void Assembler::movq(Register dst, const Operand& src) { | 688 void Assembler::movq(Register dst, const Operand& src) { |
534 EnsureSpace ensure_space(this); | 689 EnsureSpace ensure_space(this); |
535 last_pc_ = pc_; | 690 last_pc_ = pc_; |
536 emit_rex_64(dst, src); | 691 emit_rex_64(dst, src); |
537 emit(0x8B); | 692 emit(0x8B); |
538 emit_operand(dst, src); | 693 emit_operand(dst, src); |
539 } | 694 } |
540 | 695 |
541 | 696 |
542 void Assembler::movq(Register dst, Register src) { | 697 void Assembler::movq(Register dst, Register src) { |
543 EnsureSpace ensure_space(this); | 698 EnsureSpace ensure_space(this); |
544 last_pc_ = pc_; | 699 last_pc_ = pc_; |
545 emit_rex_64(dst, src); | 700 emit_rex_64(dst, src); |
546 emit(0x8B); | 701 emit(0x8B); |
547 emit(0xC0 | (dst.code() & 0x7) << 3 | (src.code() & 0x7)); | 702 emit(0xC0 | (dst.code() & 0x7) << 3 | (src.code() & 0x7)); |
548 } | 703 } |
549 | 704 |
550 | 705 |
| 706 void Assembler::movq(const Operand& dst, Register src) { |
| 707 EnsureSpace ensure_space(this); |
| 708 last_pc_ = pc_; |
| 709 emit_rex_64(src, dst); |
| 710 emit(0x89); |
| 711 emit_operand(src, dst); |
| 712 } |
| 713 |
| 714 |
551 void Assembler::movq(Register dst, Immediate value) { | 715 void Assembler::movq(Register dst, Immediate value) { |
552 EnsureSpace ensure_space(this); | 716 EnsureSpace ensure_space(this); |
553 last_pc_ = pc_; | 717 last_pc_ = pc_; |
554 emit_rex_64(dst); | 718 emit_rex_64(dst); |
555 emit(0xC7); | 719 emit(0xC7); |
556 emit(0xC0 | (dst.code() & 0x7)); | 720 emit(0xC0 | (dst.code() & 0x7)); |
557 emit(value); // Only 32-bit immediates are possible, not 8-bit immediates. | 721 emit(value); // Only 32-bit immediates are possible, not 8-bit immediates. |
558 } | 722 } |
559 | 723 |
560 | 724 |
(...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
709 | 873 |
710 void Assembler::pop(const Operand& dst) { | 874 void Assembler::pop(const Operand& dst) { |
711 EnsureSpace ensure_space(this); | 875 EnsureSpace ensure_space(this); |
712 last_pc_ = pc_; | 876 last_pc_ = pc_; |
713 emit_rex_64(dst); // Could be omitted in some cases. | 877 emit_rex_64(dst); // Could be omitted in some cases. |
714 emit(0x8F); | 878 emit(0x8F); |
715 emit_operand(0, dst); | 879 emit_operand(0, dst); |
716 } | 880 } |
717 | 881 |
718 | 882 |
| 883 void Assembler::popfq() { |
| 884 EnsureSpace ensure_space(this); |
| 885 last_pc_ = pc_; |
| 886 emit(0x9D); |
| 887 } |
| 888 |
| 889 |
719 void Assembler::push(Register src) { | 890 void Assembler::push(Register src) { |
720 EnsureSpace ensure_space(this); | 891 EnsureSpace ensure_space(this); |
721 last_pc_ = pc_; | 892 last_pc_ = pc_; |
722 if (src.code() & 0x8) { | 893 if (src.code() & 0x8) { |
723 emit_rex_64(src); | 894 emit_rex_64(src); |
724 } | 895 } |
725 emit(0x50 | (src.code() & 0x7)); | 896 emit(0x50 | (src.code() & 0x7)); |
726 } | 897 } |
727 | 898 |
728 | 899 |
729 void Assembler::push(const Operand& src) { | 900 void Assembler::push(const Operand& src) { |
730 EnsureSpace ensure_space(this); | 901 EnsureSpace ensure_space(this); |
731 last_pc_ = pc_; | 902 last_pc_ = pc_; |
732 emit_rex_64(src); // Could be omitted in some cases. | 903 emit_rex_64(src); // Could be omitted in some cases. |
733 emit(0xFF); | 904 emit(0xFF); |
734 emit_operand(6, src); | 905 emit_operand(6, src); |
735 } | 906 } |
736 | 907 |
737 | 908 |
| 909 void Assembler::push(Immediate value) { |
| 910 EnsureSpace ensure_space(this); |
| 911 last_pc_ = pc_; |
| 912 if (is_int8(value.value_)) { |
| 913 emit(0x6A); |
| 914 emit(value.value_); // Emit low byte of value. |
| 915 } else { |
| 916 emit(0x68); |
| 917 emitl(value.value_); |
| 918 } |
| 919 } |
| 920 |
| 921 |
| 922 void Assembler::pushfq() { |
| 923 EnsureSpace ensure_space(this); |
| 924 last_pc_ = pc_; |
| 925 emit(0x9C); |
| 926 } |
| 927 |
| 928 |
| 929 void Assembler::rcl(Register dst, uint8_t imm8) { |
| 930 EnsureSpace ensure_space(this); |
| 931 last_pc_ = pc_; |
| 932 ASSERT(is_uint6(imm8)); // illegal shift count |
| 933 if (imm8 == 1) { |
| 934 emit_rex_64(dst); |
| 935 emit(0xD1); |
| 936 emit(0xD0 | (dst.code() & 0x7)); |
| 937 } else { |
| 938 emit_rex_64(dst); |
| 939 emit(0xC1); |
| 940 emit(0xD0 | (dst.code() & 0x7)); |
| 941 emit(imm8); |
| 942 } |
| 943 } |
| 944 |
| 945 |
738 void Assembler::ret(int imm16) { | 946 void Assembler::ret(int imm16) { |
739 EnsureSpace ensure_space(this); | 947 EnsureSpace ensure_space(this); |
740 last_pc_ = pc_; | 948 last_pc_ = pc_; |
741 ASSERT(is_uint16(imm16)); | 949 ASSERT(is_uint16(imm16)); |
742 if (imm16 == 0) { | 950 if (imm16 == 0) { |
743 emit(0xC3); | 951 emit(0xC3); |
744 } else { | 952 } else { |
745 emit(0xC2); | 953 emit(0xC2); |
746 emit(imm16 & 0xFF); | 954 emit(imm16 & 0xFF); |
747 emit((imm16 >> 8) & 0xFF); | 955 emit((imm16 >> 8) & 0xFF); |
748 } | 956 } |
749 } | 957 } |
750 | 958 |
751 | 959 |
| 960 void Assembler::xchg(Register dst, Register src) { |
| 961 EnsureSpace ensure_space(this); |
| 962 last_pc_ = pc_; |
| 963 if (src.is(rax) || dst.is(rax)) { // Single-byte encoding |
| 964 Register other = src.is(rax) ? dst : src; |
| 965 emit_rex_64(other); |
| 966 emit(0x90 | (other.code() & 0x7)); |
| 967 } else { |
| 968 emit_rex_64(src, dst); |
| 969 emit(0x87); |
| 970 emit(0xC0 | (src.code() & 0x7) << 3 | (dst.code() & 0x7)); |
| 971 } |
| 972 } |
| 973 |
| 974 |
752 void Assembler::testb(Register reg, Immediate mask) { | 975 void Assembler::testb(Register reg, Immediate mask) { |
753 EnsureSpace ensure_space(this); | 976 EnsureSpace ensure_space(this); |
754 last_pc_ = pc_; | 977 last_pc_ = pc_; |
755 if (reg.is(rax)) { | 978 if (reg.is(rax)) { |
756 emit(0xA8); | 979 emit(0xA8); |
757 emit(mask); | 980 emit(mask); |
758 } else { | 981 } else { |
759 if (reg.code() & 0x8) { | 982 if (reg.code() & 0x8) { |
760 emit_rex_32(rax, reg); | 983 emit_rex_32(rax, reg); |
761 } | 984 } |
(...skipping 379 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1141 UNIMPLEMENTED(); | 1364 UNIMPLEMENTED(); |
1142 return NULL; | 1365 return NULL; |
1143 } | 1366 } |
1144 | 1367 |
1145 byte* JavaScriptFrame::GetCallerStackPointer() const { | 1368 byte* JavaScriptFrame::GetCallerStackPointer() const { |
1146 UNIMPLEMENTED(); | 1369 UNIMPLEMENTED(); |
1147 return NULL; | 1370 return NULL; |
1148 } | 1371 } |
1149 | 1372 |
1150 } } // namespace v8::internal | 1373 } } // namespace v8::internal |
OLD | NEW |