| 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" // Needed here to get TARGET_ARCH_IA32. | 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_IA32. |
| 6 #if defined(TARGET_ARCH_IA32) | 6 #if defined(TARGET_ARCH_IA32) |
| 7 | 7 |
| 8 #include "vm/intermediate_language.h" | 8 #include "vm/intermediate_language.h" |
| 9 | 9 |
| 10 #include "lib/error.h" | 10 #include "lib/error.h" |
| (...skipping 627 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 638 __ LoadObject(result, compiler->bool_true()); | 638 __ LoadObject(result, compiler->bool_true()); |
| 639 __ Bind(&done); | 639 __ Bind(&done); |
| 640 } | 640 } |
| 641 } | 641 } |
| 642 | 642 |
| 643 | 643 |
| 644 static Condition TokenKindToMintCondition(Token::Kind kind) { | 644 static Condition TokenKindToMintCondition(Token::Kind kind) { |
| 645 switch (kind) { | 645 switch (kind) { |
| 646 case Token::kEQ: return EQUAL; | 646 case Token::kEQ: return EQUAL; |
| 647 case Token::kNE: return NOT_EQUAL; | 647 case Token::kNE: return NOT_EQUAL; |
| 648 case Token::kLT: return LESS; |
| 649 case Token::kGT: return GREATER; |
| 650 case Token::kLTE: return LESS_EQUAL; |
| 651 case Token::kGTE: return GREATER_EQUAL; |
| 648 default: | 652 default: |
| 649 UNIMPLEMENTED(); | 653 UNREACHABLE(); |
| 650 return OVERFLOW; | 654 return OVERFLOW; |
| 651 } | 655 } |
| 652 } | 656 } |
| 653 | 657 |
| 654 | 658 |
| 655 static void EmitUnboxedMintEqualityOp(FlowGraphCompiler* compiler, | 659 static void EmitUnboxedMintEqualityOp(FlowGraphCompiler* compiler, |
| 656 const LocationSummary& locs, | 660 const LocationSummary& locs, |
| 657 Token::Kind kind, | 661 Token::Kind kind, |
| 658 BranchInstr* branch) { | 662 BranchInstr* branch) { |
| 659 ASSERT(Token::IsEqualityOperator(kind)); | 663 ASSERT(Token::IsEqualityOperator(kind)); |
| (...skipping 15 matching lines...) Expand all Loading... |
| 675 __ j(true_condition, &is_true); | 679 __ j(true_condition, &is_true); |
| 676 __ LoadObject(result, compiler->bool_false()); | 680 __ LoadObject(result, compiler->bool_false()); |
| 677 __ jmp(&done); | 681 __ jmp(&done); |
| 678 __ Bind(&is_true); | 682 __ Bind(&is_true); |
| 679 __ LoadObject(result, compiler->bool_true()); | 683 __ LoadObject(result, compiler->bool_true()); |
| 680 __ Bind(&done); | 684 __ Bind(&done); |
| 681 } | 685 } |
| 682 } | 686 } |
| 683 | 687 |
| 684 | 688 |
| 689 static void EmitUnboxedMintComparisonOp(FlowGraphCompiler* compiler, |
| 690 const LocationSummary& locs, |
| 691 Token::Kind kind, |
| 692 BranchInstr* branch) { |
| 693 XmmRegister left = locs.in(0).xmm_reg(); |
| 694 XmmRegister right = locs.in(1).xmm_reg(); |
| 695 Register left_tmp = locs.temp(0).reg(); |
| 696 Register right_tmp = locs.temp(1).reg(); |
| 697 Register result = branch == NULL ? locs.out().reg() : kNoRegister; |
| 698 |
| 699 Condition hi_cond = OVERFLOW, lo_cond = OVERFLOW; |
| 700 switch (kind) { |
| 701 case Token::kLT: |
| 702 hi_cond = LESS; |
| 703 lo_cond = BELOW; |
| 704 break; |
| 705 case Token::kGT: |
| 706 hi_cond = GREATER; |
| 707 lo_cond = ABOVE; |
| 708 break; |
| 709 case Token::kLTE: |
| 710 hi_cond = LESS; |
| 711 lo_cond = BELOW_EQUAL; |
| 712 break; |
| 713 case Token::kGTE: |
| 714 hi_cond = GREATER; |
| 715 lo_cond = ABOVE_EQUAL; |
| 716 break; |
| 717 default: |
| 718 break; |
| 719 } |
| 720 ASSERT(hi_cond != OVERFLOW && lo_cond != OVERFLOW); |
| 721 Label is_true, is_false; |
| 722 // Compare upper halves first. |
| 723 __ pextrd(left_tmp, left, Immediate(1)); |
| 724 __ pextrd(right_tmp, right, Immediate(1)); |
| 725 __ cmpl(left_tmp, right_tmp); |
| 726 if (branch != NULL) { |
| 727 __ j(hi_cond, compiler->GetBlockLabel(branch->true_successor())); |
| 728 __ j(FlowGraphCompiler::FlipCondition(hi_cond), |
| 729 compiler->GetBlockLabel(branch->false_successor())); |
| 730 } else { |
| 731 __ j(hi_cond, &is_true); |
| 732 __ j(FlowGraphCompiler::FlipCondition(hi_cond), &is_false); |
| 733 } |
| 734 |
| 735 // If upper is equal, compare lower half. |
| 736 __ pextrd(left_tmp, left, Immediate(0)); |
| 737 __ pextrd(right_tmp, right, Immediate(0)); |
| 738 __ cmpl(left_tmp, right_tmp); |
| 739 if (branch != NULL) { |
| 740 branch->EmitBranchOnCondition(compiler, lo_cond); |
| 741 } else { |
| 742 Label done; |
| 743 __ j(lo_cond, &is_true); |
| 744 __ Bind(&is_false); |
| 745 __ LoadObject(result, compiler->bool_false()); |
| 746 __ jmp(&done); |
| 747 __ Bind(&is_true); |
| 748 __ LoadObject(result, compiler->bool_true()); |
| 749 __ Bind(&done); |
| 750 } |
| 751 } |
| 752 |
| 753 |
| 685 static Condition TokenKindToDoubleCondition(Token::Kind kind) { | 754 static Condition TokenKindToDoubleCondition(Token::Kind kind) { |
| 686 switch (kind) { | 755 switch (kind) { |
| 687 case Token::kEQ: return EQUAL; | 756 case Token::kEQ: return EQUAL; |
| 688 case Token::kNE: return NOT_EQUAL; | 757 case Token::kNE: return NOT_EQUAL; |
| 689 case Token::kLT: return BELOW; | 758 case Token::kLT: return BELOW; |
| 690 case Token::kGT: return ABOVE; | 759 case Token::kGT: return ABOVE; |
| 691 case Token::kLTE: return BELOW_EQUAL; | 760 case Token::kLTE: return BELOW_EQUAL; |
| 692 case Token::kGTE: return ABOVE_EQUAL; | 761 case Token::kGTE: return ABOVE_EQUAL; |
| 693 default: | 762 default: |
| 694 UNREACHABLE(); | 763 UNREACHABLE(); |
| (...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 794 } | 863 } |
| 795 Condition branch_condition = (kind() == Token::kNE) ? NOT_EQUAL : EQUAL; | 864 Condition branch_condition = (kind() == Token::kNE) ? NOT_EQUAL : EQUAL; |
| 796 __ CompareObject(EAX, compiler->bool_true()); | 865 __ CompareObject(EAX, compiler->bool_true()); |
| 797 branch->EmitBranchOnCondition(compiler, branch_condition); | 866 branch->EmitBranchOnCondition(compiler, branch_condition); |
| 798 } | 867 } |
| 799 | 868 |
| 800 | 869 |
| 801 LocationSummary* RelationalOpInstr::MakeLocationSummary() const { | 870 LocationSummary* RelationalOpInstr::MakeLocationSummary() const { |
| 802 const intptr_t kNumInputs = 2; | 871 const intptr_t kNumInputs = 2; |
| 803 const intptr_t kNumTemps = 0; | 872 const intptr_t kNumTemps = 0; |
| 873 if (operands_class_id() == kMintCid) { |
| 874 const intptr_t kNumTemps = 2; |
| 875 LocationSummary* locs = |
| 876 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 877 locs->set_in(0, Location::RequiresXmmRegister()); |
| 878 locs->set_in(1, Location::RequiresXmmRegister()); |
| 879 locs->set_temp(0, Location::RequiresRegister()); |
| 880 locs->set_temp(1, Location::RequiresRegister()); |
| 881 locs->set_out(Location::RequiresRegister()); |
| 882 return locs; |
| 883 } |
| 804 if (operands_class_id() == kDoubleCid) { | 884 if (operands_class_id() == kDoubleCid) { |
| 805 LocationSummary* summary = | 885 LocationSummary* summary = |
| 806 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 886 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 807 summary->set_in(0, Location::RequiresXmmRegister()); | 887 summary->set_in(0, Location::RequiresXmmRegister()); |
| 808 summary->set_in(1, Location::RequiresXmmRegister()); | 888 summary->set_in(1, Location::RequiresXmmRegister()); |
| 809 summary->set_out(Location::RequiresRegister()); | 889 summary->set_out(Location::RequiresRegister()); |
| 810 return summary; | 890 return summary; |
| 811 } else if (operands_class_id() == kSmiCid) { | 891 } else if (operands_class_id() == kSmiCid) { |
| 812 LocationSummary* summary = | 892 LocationSummary* summary = |
| 813 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 893 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| (...skipping 10 matching lines...) Expand all Loading... |
| 824 locs->set_out(Location::RegisterLocation(EAX)); | 904 locs->set_out(Location::RegisterLocation(EAX)); |
| 825 return locs; | 905 return locs; |
| 826 } | 906 } |
| 827 | 907 |
| 828 | 908 |
| 829 void RelationalOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 909 void RelationalOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 830 if (operands_class_id() == kSmiCid) { | 910 if (operands_class_id() == kSmiCid) { |
| 831 EmitSmiComparisonOp(compiler, *locs(), kind(), NULL); | 911 EmitSmiComparisonOp(compiler, *locs(), kind(), NULL); |
| 832 return; | 912 return; |
| 833 } | 913 } |
| 914 if (operands_class_id() == kMintCid) { |
| 915 EmitUnboxedMintComparisonOp(compiler, *locs(), kind(), NULL); |
| 916 return; |
| 917 } |
| 834 if (operands_class_id() == kDoubleCid) { | 918 if (operands_class_id() == kDoubleCid) { |
| 835 EmitDoubleComparisonOp(compiler, *locs(), kind(), NULL); | 919 EmitDoubleComparisonOp(compiler, *locs(), kind(), NULL); |
| 836 return; | 920 return; |
| 837 } | 921 } |
| 838 | 922 |
| 839 // Push arguments for the call. | 923 // Push arguments for the call. |
| 840 // TODO(fschneider): Split this instruction into different types to avoid | 924 // TODO(fschneider): Split this instruction into different types to avoid |
| 841 // explicitly pushing arguments to the call here. | 925 // explicitly pushing arguments to the call here. |
| 842 Register left = locs()->in(0).reg(); | 926 Register left = locs()->in(0).reg(); |
| 843 Register right = locs()->in(1).reg(); | 927 Register right = locs()->in(1).reg(); |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 883 locs()); | 967 locs()); |
| 884 } | 968 } |
| 885 | 969 |
| 886 | 970 |
| 887 void RelationalOpInstr::EmitBranchCode(FlowGraphCompiler* compiler, | 971 void RelationalOpInstr::EmitBranchCode(FlowGraphCompiler* compiler, |
| 888 BranchInstr* branch) { | 972 BranchInstr* branch) { |
| 889 if (operands_class_id() == kSmiCid) { | 973 if (operands_class_id() == kSmiCid) { |
| 890 EmitSmiComparisonOp(compiler, *locs(), kind(), branch); | 974 EmitSmiComparisonOp(compiler, *locs(), kind(), branch); |
| 891 return; | 975 return; |
| 892 } | 976 } |
| 977 if (operands_class_id() == kMintCid) { |
| 978 EmitUnboxedMintComparisonOp(compiler, *locs(), kind(), branch); |
| 979 return; |
| 980 } |
| 893 if (operands_class_id() == kDoubleCid) { | 981 if (operands_class_id() == kDoubleCid) { |
| 894 EmitDoubleComparisonOp(compiler, *locs(), kind(), branch); | 982 EmitDoubleComparisonOp(compiler, *locs(), kind(), branch); |
| 895 return; | 983 return; |
| 896 } | 984 } |
| 897 EmitNativeCode(compiler); | 985 EmitNativeCode(compiler); |
| 898 __ CompareObject(EAX, compiler->bool_true()); | 986 __ CompareObject(EAX, compiler->bool_true()); |
| 899 branch->EmitBranchOnCondition(compiler, EQUAL); | 987 branch->EmitBranchOnCondition(compiler, EQUAL); |
| 900 } | 988 } |
| 901 | 989 |
| 902 | 990 |
| (...skipping 1534 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2437 case Token::kBIT_AND: __ andpd(left, right); break; | 2525 case Token::kBIT_AND: __ andpd(left, right); break; |
| 2438 case Token::kBIT_OR: __ orpd(left, right); break; | 2526 case Token::kBIT_OR: __ orpd(left, right); break; |
| 2439 case Token::kBIT_XOR: __ xorpd(left, right); break; | 2527 case Token::kBIT_XOR: __ xorpd(left, right); break; |
| 2440 case Token::kADD: | 2528 case Token::kADD: |
| 2441 case Token::kSUB: { | 2529 case Token::kSUB: { |
| 2442 Register lo = locs()->temp(0).reg(); | 2530 Register lo = locs()->temp(0).reg(); |
| 2443 Register hi = locs()->temp(1).reg(); | 2531 Register hi = locs()->temp(1).reg(); |
| 2444 Label* deopt = compiler->AddDeoptStub(deopt_id(), | 2532 Label* deopt = compiler->AddDeoptStub(deopt_id(), |
| 2445 kDeoptBinaryMintOp); | 2533 kDeoptBinaryMintOp); |
| 2446 Label done, overflow; | 2534 Label done, overflow; |
| 2447 __ pextrd(lo, right, Immediate(0)); // Lower half left | 2535 __ pextrd(lo, right, Immediate(0)); // Lower half |
| 2448 __ pextrd(hi, right, Immediate(1)); // Upper half left | 2536 __ pextrd(hi, right, Immediate(1)); // Upper half |
| 2449 __ subl(ESP, Immediate(2 * kWordSize)); | 2537 __ subl(ESP, Immediate(2 * kWordSize)); |
| 2450 __ movq(Address(ESP, 0), left); | 2538 __ movq(Address(ESP, 0), left); |
| 2451 if (op_kind() == Token::kADD) { | 2539 if (op_kind() == Token::kADD) { |
| 2452 __ addl(Address(ESP, 0), lo); | 2540 __ addl(Address(ESP, 0), lo); |
| 2453 __ adcl(Address(ESP, 1 * kWordSize), hi); | 2541 __ adcl(Address(ESP, 1 * kWordSize), hi); |
| 2454 } else { | 2542 } else { |
| 2455 __ subl(Address(ESP, 0), lo); | 2543 __ subl(Address(ESP, 0), lo); |
| 2456 __ sbbl(Address(ESP, 1 * kWordSize), hi); | 2544 __ sbbl(Address(ESP, 1 * kWordSize), hi); |
| 2457 } | 2545 } |
| 2458 __ j(OVERFLOW, &overflow); | 2546 __ j(OVERFLOW, &overflow); |
| (...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2558 __ pcmpeqq(XMM0, XMM0); // Generate all 1's. | 2646 __ pcmpeqq(XMM0, XMM0); // Generate all 1's. |
| 2559 __ pxor(value, XMM0); | 2647 __ pxor(value, XMM0); |
| 2560 } | 2648 } |
| 2561 | 2649 |
| 2562 | 2650 |
| 2563 } // namespace dart | 2651 } // namespace dart |
| 2564 | 2652 |
| 2565 #undef __ | 2653 #undef __ |
| 2566 | 2654 |
| 2567 #endif // defined TARGET_ARCH_X64 | 2655 #endif // defined TARGET_ARCH_X64 |
| OLD | NEW |