OLD | NEW |
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 #include "vm/globals.h" | 5 #include "vm/globals.h" |
6 #if defined(TARGET_ARCH_X64) | 6 #if defined(TARGET_ARCH_X64) |
7 | 7 |
8 #include "vm/assembler.h" | 8 #include "vm/assembler.h" |
9 #include "vm/os.h" | 9 #include "vm/os.h" |
10 #include "vm/unit_test.h" | 10 #include "vm/unit_test.h" |
(...skipping 368 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
379 __ ret(); | 379 __ ret(); |
380 } | 380 } |
381 | 381 |
382 | 382 |
383 ASSEMBLER_TEST_RUN(SignedMultiply, test) { | 383 ASSEMBLER_TEST_RUN(SignedMultiply, test) { |
384 typedef int (*SignedMultiply)(); | 384 typedef int (*SignedMultiply)(); |
385 EXPECT_EQ(8000, reinterpret_cast<SignedMultiply>(test->entry())()); | 385 EXPECT_EQ(8000, reinterpret_cast<SignedMultiply>(test->entry())()); |
386 } | 386 } |
387 | 387 |
388 | 388 |
| 389 ASSEMBLER_TEST_GENERATE(UnsignedMultiply, assembler) { |
| 390 __ movl(RAX, Immediate(-1)); // RAX = 0xFFFFFFFF |
| 391 __ movl(RCX, Immediate(16)); // RCX = 0x10 |
| 392 __ mull(RCX); // RDX:RAX = RAX * RCX = 0x0FFFFFFFF0 |
| 393 __ movq(RAX, RDX); // Return high32(0x0FFFFFFFF0) == 0x0F |
| 394 __ ret(); |
| 395 } |
| 396 |
| 397 |
| 398 ASSEMBLER_TEST_RUN(UnsignedMultiply, test) { |
| 399 typedef int (*UnsignedMultiply)(); |
| 400 EXPECT_EQ(15, reinterpret_cast<UnsignedMultiply>(test->entry())()); |
| 401 } |
| 402 |
| 403 |
389 ASSEMBLER_TEST_GENERATE(SignedMultiply64, assembler) { | 404 ASSEMBLER_TEST_GENERATE(SignedMultiply64, assembler) { |
390 __ pushq(R15); // Callee saved. | 405 __ pushq(R15); // Callee saved. |
391 __ movq(RAX, Immediate(2)); | 406 __ movq(RAX, Immediate(2)); |
392 __ movq(RCX, Immediate(4)); | 407 __ movq(RCX, Immediate(4)); |
393 __ imulq(RAX, RCX); | 408 __ imulq(RAX, RCX); |
394 | 409 |
395 __ movq(R8, Immediate(2)); | 410 __ movq(R8, Immediate(2)); |
396 __ movq(R9, Immediate(4)); | 411 __ movq(R9, Immediate(4)); |
397 __ pushq(R9); | 412 __ pushq(R9); |
398 __ imulq(R8, Address(RSP, 0)); | 413 __ imulq(R8, Address(RSP, 0)); |
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
501 __ ret(); | 516 __ ret(); |
502 } | 517 } |
503 | 518 |
504 | 519 |
505 ASSEMBLER_TEST_RUN(SignedDivide, test) { | 520 ASSEMBLER_TEST_RUN(SignedDivide, test) { |
506 typedef int32_t (*SignedDivide)(); | 521 typedef int32_t (*SignedDivide)(); |
507 EXPECT_EQ(-87 / 42, reinterpret_cast<SignedDivide>(test->entry())()); | 522 EXPECT_EQ(-87 / 42, reinterpret_cast<SignedDivide>(test->entry())()); |
508 } | 523 } |
509 | 524 |
510 | 525 |
| 526 ASSEMBLER_TEST_GENERATE(UnsignedDivide, assembler) { |
| 527 const int32_t low = 0; |
| 528 const int32_t high = 0xf0000000; |
| 529 const int32_t divisor = 0xffffffff; |
| 530 __ movl(RAX, Immediate(low)); |
| 531 __ movl(RDX, Immediate(high)); |
| 532 __ movl(RCX, Immediate(divisor)); |
| 533 __ divl(RCX); // RAX = RDX:RAX / RCX = |
| 534 // = 0xf000000000000000 / 0xffffffff = 0xf0000000 |
| 535 __ ret(); |
| 536 } |
| 537 |
| 538 |
| 539 ASSEMBLER_TEST_RUN(UnsignedDivide, test) { |
| 540 typedef uint32_t (*UnsignedDivide)(); |
| 541 EXPECT_EQ(0xf0000000, reinterpret_cast<UnsignedDivide>(test->entry())()); |
| 542 } |
| 543 |
| 544 |
511 ASSEMBLER_TEST_GENERATE(SignedDivideLong, assembler) { | 545 ASSEMBLER_TEST_GENERATE(SignedDivideLong, assembler) { |
512 __ movq(RAX, Immediate(kLargeConstant)); | 546 __ movq(RAX, Immediate(kLargeConstant)); |
513 __ movq(RDX, Immediate(123)); | 547 __ movq(RDX, Immediate(123)); |
514 __ cqo(); // Clear RDX. | 548 __ cqo(); // Clear RDX. |
515 __ movq(RCX, Immediate(42)); | 549 __ movq(RCX, Immediate(42)); |
516 __ idivq(RCX); | 550 __ idivq(RCX); |
517 __ ret(); | 551 __ ret(); |
518 } | 552 } |
519 | 553 |
520 | 554 |
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
642 __ ret(); | 676 __ ret(); |
643 } | 677 } |
644 | 678 |
645 | 679 |
646 ASSEMBLER_TEST_RUN(MoveWordRex, test) { | 680 ASSEMBLER_TEST_RUN(MoveWordRex, test) { |
647 typedef int (*MoveWordRex)(); | 681 typedef int (*MoveWordRex)(); |
648 EXPECT_EQ(0xffff, reinterpret_cast<MoveWordRex>(test->entry())()); | 682 EXPECT_EQ(0xffff, reinterpret_cast<MoveWordRex>(test->entry())()); |
649 } | 683 } |
650 | 684 |
651 | 685 |
| 686 ASSEMBLER_TEST_GENERATE(LongAddReg, assembler) { |
| 687 __ pushq(CallingConventions::kArg2Reg); |
| 688 __ pushq(CallingConventions::kArg1Reg); |
| 689 __ movl(RAX, Address(RSP, 0)); // left low. |
| 690 __ movl(RDX, Address(RSP, 4)); // left high. |
| 691 __ movl(RCX, Address(RSP, 8)); // right low. |
| 692 __ movl(RBX, Address(RSP, 12)); // right high |
| 693 __ addl(RAX, RCX); |
| 694 __ adcl(RDX, RBX); |
| 695 // Result is in RAX/RDX. |
| 696 __ movl(Address(RSP, 0), RAX); // result low. |
| 697 __ movl(Address(RSP, 4), RDX); // result high. |
| 698 __ popq(RAX); |
| 699 __ popq(RDX); |
| 700 __ ret(); |
| 701 } |
| 702 |
| 703 |
| 704 ASSEMBLER_TEST_RUN(LongAddReg, test) { |
| 705 typedef int64_t (*LongAddRegCode)(int64_t a, int64_t b); |
| 706 int64_t a = 12; |
| 707 int64_t b = 14; |
| 708 int64_t res = reinterpret_cast<LongAddRegCode>(test->entry())(a, b); |
| 709 EXPECT_EQ((a + b), res); |
| 710 a = 2147483647; |
| 711 b = 600000; |
| 712 res = reinterpret_cast<LongAddRegCode>(test->entry())(a, b); |
| 713 EXPECT_EQ((a + b), res); |
| 714 } |
| 715 |
| 716 |
| 717 ASSEMBLER_TEST_GENERATE(LongAddAddress, assembler) { |
| 718 __ pushq(CallingConventions::kArg2Reg); |
| 719 __ pushq(CallingConventions::kArg1Reg); |
| 720 __ movl(RAX, Address(RSP, 0)); // left low. |
| 721 __ movl(RDX, Address(RSP, 4)); // left high. |
| 722 __ addl(RAX, Address(RSP, 8)); // low. |
| 723 __ adcl(RDX, Address(RSP, 12)); // high. |
| 724 // Result is in RAX/RDX. |
| 725 __ movl(Address(RSP, 0), RAX); // result low. |
| 726 __ movl(Address(RSP, 4), RDX); // result high. |
| 727 __ popq(RAX); |
| 728 __ popq(RDX); |
| 729 __ ret(); |
| 730 } |
| 731 |
| 732 |
| 733 ASSEMBLER_TEST_RUN(LongAddAddress, test) { |
| 734 typedef int64_t (*LongAddAddressCode)(int64_t a, int64_t b); |
| 735 int64_t a = 12; |
| 736 int64_t b = 14; |
| 737 int64_t res = reinterpret_cast<LongAddAddressCode>(test->entry())(a, b); |
| 738 EXPECT_EQ((a + b), res); |
| 739 a = 2147483647; |
| 740 b = 600000; |
| 741 res = reinterpret_cast<LongAddAddressCode>(test->entry())(a, b); |
| 742 EXPECT_EQ((a + b), res); |
| 743 } |
| 744 |
| 745 |
| 746 ASSEMBLER_TEST_GENERATE(LongSubReg, assembler) { |
| 747 __ pushq(CallingConventions::kArg2Reg); |
| 748 __ pushq(CallingConventions::kArg1Reg); |
| 749 __ movl(RAX, Address(RSP, 0)); // left low. |
| 750 __ movl(RDX, Address(RSP, 4)); // left high. |
| 751 __ movl(RCX, Address(RSP, 8)); // right low. |
| 752 __ movl(RBX, Address(RSP, 12)); // right high |
| 753 __ subl(RAX, RCX); |
| 754 __ sbbl(RDX, RBX); |
| 755 // Result is in RAX/RDX. |
| 756 __ movl(Address(RSP, 0), RAX); // result low. |
| 757 __ movl(Address(RSP, 4), RDX); // result high. |
| 758 __ popq(RAX); |
| 759 __ popq(RDX); |
| 760 __ ret(); |
| 761 } |
| 762 |
| 763 |
| 764 ASSEMBLER_TEST_RUN(LongSubReg, test) { |
| 765 typedef int64_t (*LongSubRegCode)(int64_t a, int64_t b); |
| 766 int64_t a = 12; |
| 767 int64_t b = 14; |
| 768 int64_t res = reinterpret_cast<LongSubRegCode>(test->entry())(a, b); |
| 769 EXPECT_EQ((a - b), res); |
| 770 a = 600000; |
| 771 b = 2147483647; |
| 772 res = reinterpret_cast<LongSubRegCode>(test->entry())(a, b); |
| 773 EXPECT_EQ((a - b), res); |
| 774 } |
| 775 |
| 776 |
| 777 ASSEMBLER_TEST_GENERATE(LongSubAddress, assembler) { |
| 778 __ pushq(CallingConventions::kArg2Reg); |
| 779 __ pushq(CallingConventions::kArg1Reg); |
| 780 __ movl(RAX, Address(RSP, 0)); // left low. |
| 781 __ movl(RDX, Address(RSP, 4)); // left high. |
| 782 __ subl(RAX, Address(RSP, 8)); // low. |
| 783 __ sbbl(RDX, Address(RSP, 12)); // high. |
| 784 // Result is in RAX/RDX. |
| 785 __ movl(Address(RSP, 0), RAX); // result low. |
| 786 __ movl(Address(RSP, 4), RDX); // result high. |
| 787 __ popq(RAX); |
| 788 __ popq(RDX); |
| 789 __ ret(); |
| 790 } |
| 791 |
| 792 |
| 793 ASSEMBLER_TEST_RUN(LongSubAddress, test) { |
| 794 typedef int64_t (*LongSubAddressCode)(int64_t a, int64_t b); |
| 795 int64_t a = 12; |
| 796 int64_t b = 14; |
| 797 int64_t res = reinterpret_cast<LongSubAddressCode>(test->entry())(a, b); |
| 798 EXPECT_EQ((a - b), res); |
| 799 a = 600000; |
| 800 b = 2147483647; |
| 801 res = reinterpret_cast<LongSubAddressCode>(test->entry())(a, b); |
| 802 EXPECT_EQ((a - b), res); |
| 803 } |
| 804 |
| 805 |
652 ASSEMBLER_TEST_GENERATE(Bitwise, assembler) { | 806 ASSEMBLER_TEST_GENERATE(Bitwise, assembler) { |
653 __ movl(RCX, Immediate(42)); | 807 __ movl(RCX, Immediate(42)); |
654 __ xorl(RCX, RCX); | 808 __ xorl(RCX, RCX); |
655 __ orl(RCX, Immediate(256)); | 809 __ orl(RCX, Immediate(256)); |
656 __ movl(RAX, Immediate(4)); | 810 __ movl(RAX, Immediate(4)); |
657 __ orl(RCX, RAX); | 811 __ orl(RCX, RAX); |
658 __ movl(RAX, Immediate(0xfff0)); | 812 __ movl(RAX, Immediate(0xfff0)); |
659 __ andl(RCX, RAX); | 813 __ andl(RCX, RAX); |
660 __ movl(RAX, Immediate(1)); | 814 __ movl(RAX, Immediate(1)); |
661 __ orl(RCX, RAX); | 815 __ orl(RCX, RAX); |
(...skipping 236 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
898 __ movl(RCX, Immediate(3)); | 1052 __ movl(RCX, Immediate(3)); |
899 __ shlq(RAX, Immediate(31)); | 1053 __ shlq(RAX, Immediate(31)); |
900 __ sarl(RAX, RCX); | 1054 __ sarl(RAX, RCX); |
901 __ cmpl(RAX, Immediate(0xfffffffff0000000)); | 1055 __ cmpl(RAX, Immediate(0xfffffffff0000000)); |
902 __ j(EQUAL, &donetest13a); | 1056 __ j(EQUAL, &donetest13a); |
903 // Be sure to skip this crashing code. | 1057 // Be sure to skip this crashing code. |
904 __ movl(RAX, Immediate(0)); | 1058 __ movl(RAX, Immediate(0)); |
905 __ movl(Address(RAX, 0), RAX); | 1059 __ movl(Address(RAX, 0), RAX); |
906 __ Bind(&donetest13a); | 1060 __ Bind(&donetest13a); |
907 | 1061 |
| 1062 Label donetest15a; |
| 1063 const int32_t left = 0xff000000; |
| 1064 const int32_t right = 0xffffffff; |
| 1065 const int32_t shifted = 0xf0000003; |
| 1066 __ movl(RDX, Immediate(left)); |
| 1067 __ movl(RAX, Immediate(right)); |
| 1068 __ movl(RCX, Immediate(2)); |
| 1069 __ shll(RDX, RCX); // RDX = 0xff000000 << 2 == 0xfc000000 |
| 1070 __ shldl(RDX, RAX, Immediate(2)); // RDX = high32(0xfc000000:0xffffffff << 2) |
| 1071 // = 0xf0000003 |
| 1072 __ cmpl(RDX, Immediate(shifted)); |
| 1073 __ j(EQUAL, &donetest15a); |
| 1074 __ int3(); |
| 1075 __ Bind(&donetest15a); |
| 1076 |
908 __ movl(RAX, Immediate(0)); | 1077 __ movl(RAX, Immediate(0)); |
909 __ ret(); | 1078 __ ret(); |
910 } | 1079 } |
911 | 1080 |
912 | 1081 |
913 ASSEMBLER_TEST_RUN(LogicalOps, test) { | 1082 ASSEMBLER_TEST_RUN(LogicalOps, test) { |
914 typedef int (*LogicalOpsCode)(); | 1083 typedef int (*LogicalOpsCode)(); |
915 EXPECT_EQ(0, reinterpret_cast<LogicalOpsCode>(test->entry())()); | 1084 EXPECT_EQ(0, reinterpret_cast<LogicalOpsCode>(test->entry())()); |
916 } | 1085 } |
917 | 1086 |
(...skipping 2108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3026 int res = reinterpret_cast<ConditionalMovesNoOverflowCode>( | 3195 int res = reinterpret_cast<ConditionalMovesNoOverflowCode>( |
3027 test->entry())(0x7fffffffffffffff, 2); | 3196 test->entry())(0x7fffffffffffffff, 2); |
3028 EXPECT_EQ(1, res); | 3197 EXPECT_EQ(1, res); |
3029 res = reinterpret_cast<ConditionalMovesNoOverflowCode>(test->entry())(1, 1); | 3198 res = reinterpret_cast<ConditionalMovesNoOverflowCode>(test->entry())(1, 1); |
3030 EXPECT_EQ(0, res); | 3199 EXPECT_EQ(0, res); |
3031 } | 3200 } |
3032 | 3201 |
3033 } // namespace dart | 3202 } // namespace dart |
3034 | 3203 |
3035 #endif // defined TARGET_ARCH_X64 | 3204 #endif // defined TARGET_ARCH_X64 |
OLD | NEW |