OLD | NEW |
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, 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_ARM. | 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_ARM. |
6 #if defined(TARGET_ARCH_ARM) | 6 #if defined(TARGET_ARCH_ARM) |
7 | 7 |
8 #include "vm/intermediate_language.h" | 8 #include "vm/intermediate_language.h" |
9 | 9 |
10 #include "vm/cpu.h" | 10 #include "vm/cpu.h" |
(...skipping 536 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
547 return VS; | 547 return VS; |
548 } | 548 } |
549 } | 549 } |
550 | 550 |
551 | 551 |
552 static Condition EmitUnboxedMintEqualityOp(FlowGraphCompiler* compiler, | 552 static Condition EmitUnboxedMintEqualityOp(FlowGraphCompiler* compiler, |
553 LocationSummary* locs, | 553 LocationSummary* locs, |
554 Token::Kind kind) { | 554 Token::Kind kind) { |
555 ASSERT(Token::IsEqualityOperator(kind)); | 555 ASSERT(Token::IsEqualityOperator(kind)); |
556 PairLocation* left_pair = locs->in(0).AsPairLocation(); | 556 PairLocation* left_pair = locs->in(0).AsPairLocation(); |
557 Register left1 = left_pair->At(0).reg(); | 557 Register left_lo = left_pair->At(0).reg(); |
558 Register left2 = left_pair->At(1).reg(); | 558 Register left_hi = left_pair->At(1).reg(); |
559 PairLocation* right_pair = locs->in(1).AsPairLocation(); | 559 PairLocation* right_pair = locs->in(1).AsPairLocation(); |
560 Register right1 = right_pair->At(0).reg(); | 560 Register right_lo = right_pair->At(0).reg(); |
561 Register right2 = right_pair->At(1).reg(); | 561 Register right_hi = right_pair->At(1).reg(); |
562 | 562 |
563 // Compare lower. | 563 // Compare lower. |
564 __ cmp(left1, Operand(right1)); | 564 __ cmp(left_lo, Operand(right_lo)); |
565 // Compare upper if lower is equal. | 565 // Compare upper if lower is equal. |
566 __ cmp(left2, Operand(right2), EQ); | 566 __ cmp(left_hi, Operand(right_hi), EQ); |
567 return TokenKindToMintCondition(kind); | 567 return TokenKindToMintCondition(kind); |
568 } | 568 } |
569 | 569 |
570 | 570 |
571 static Condition EmitUnboxedMintComparisonOp(FlowGraphCompiler* compiler, | 571 static Condition EmitUnboxedMintComparisonOp(FlowGraphCompiler* compiler, |
572 LocationSummary* locs, | 572 LocationSummary* locs, |
573 Token::Kind kind) { | 573 Token::Kind kind) { |
574 PairLocation* left_pair = locs->in(0).AsPairLocation(); | 574 PairLocation* left_pair = locs->in(0).AsPairLocation(); |
575 Register left1 = left_pair->At(0).reg(); | 575 Register left_lo = left_pair->At(0).reg(); |
576 Register left2 = left_pair->At(1).reg(); | 576 Register left_hi = left_pair->At(1).reg(); |
577 PairLocation* right_pair = locs->in(1).AsPairLocation(); | 577 PairLocation* right_pair = locs->in(1).AsPairLocation(); |
578 Register right1 = right_pair->At(0).reg(); | 578 Register right_lo = right_pair->At(0).reg(); |
579 Register right2 = right_pair->At(1).reg(); | 579 Register right_hi = right_pair->At(1).reg(); |
580 | 580 |
581 Register out = locs->temp(0).reg(); | 581 Register out = locs->temp(0).reg(); |
582 | 582 |
583 // 64-bit comparison | 583 // 64-bit comparison |
584 Condition hi_true_cond, hi_false_cond, lo_false_cond; | 584 Condition hi_true_cond, hi_false_cond, lo_false_cond; |
585 switch (kind) { | 585 switch (kind) { |
586 case Token::kLT: | 586 case Token::kLT: |
587 case Token::kLTE: | 587 case Token::kLTE: |
588 hi_true_cond = LT; | 588 hi_true_cond = LT; |
589 hi_false_cond = GT; | 589 hi_false_cond = GT; |
590 lo_false_cond = (kind == Token::kLT) ? CS : HI; | 590 lo_false_cond = (kind == Token::kLT) ? CS : HI; |
591 break; | 591 break; |
592 case Token::kGT: | 592 case Token::kGT: |
593 case Token::kGTE: | 593 case Token::kGTE: |
594 hi_true_cond = GT; | 594 hi_true_cond = GT; |
595 hi_false_cond = LT; | 595 hi_false_cond = LT; |
596 lo_false_cond = (kind == Token::kGT) ? LS : CC; | 596 lo_false_cond = (kind == Token::kGT) ? LS : CC; |
597 break; | 597 break; |
598 default: | 598 default: |
599 UNREACHABLE(); | 599 UNREACHABLE(); |
600 hi_true_cond = hi_false_cond = lo_false_cond = VS; | 600 hi_true_cond = hi_false_cond = lo_false_cond = VS; |
601 } | 601 } |
602 | 602 |
603 Label is_true, is_false, done; | 603 Label done; |
604 // Compare upper halves first. | 604 // Compare upper halves first. |
605 __ cmp(left2, Operand(right2)); | 605 __ cmp(left_hi, Operand(right_hi)); |
606 __ LoadImmediate(out, 0, hi_false_cond); | 606 __ LoadImmediate(out, 0, hi_false_cond); |
607 __ LoadImmediate(out, 1, hi_true_cond); | 607 __ LoadImmediate(out, 1, hi_true_cond); |
608 // If higher words aren't equal, skip comparing lower words. | 608 // If higher words aren't equal, skip comparing lower words. |
609 __ b(&done, NE); | 609 __ b(&done, NE); |
610 | 610 |
611 __ cmp(left1, Operand(right1)); | 611 __ cmp(left_lo, Operand(right_lo)); |
612 __ LoadImmediate(out, 1); | 612 __ LoadImmediate(out, 1); |
613 __ LoadImmediate(out, 0, lo_false_cond); | 613 __ LoadImmediate(out, 0, lo_false_cond); |
614 __ Bind(&done); | 614 __ Bind(&done); |
615 | 615 |
616 return NegateCondition(lo_false_cond); | 616 return NegateCondition(lo_false_cond); |
617 } | 617 } |
618 | 618 |
619 | 619 |
620 static Condition TokenKindToDoubleCondition(Token::Kind kind) { | 620 static Condition TokenKindToDoubleCondition(Token::Kind kind) { |
621 switch (kind) { | 621 switch (kind) { |
(...skipping 200 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
822 const intptr_t kNumInputs = 2; | 822 const intptr_t kNumInputs = 2; |
823 const intptr_t kNumTemps = 0; | 823 const intptr_t kNumTemps = 0; |
824 if (operation_cid() == kMintCid) { | 824 if (operation_cid() == kMintCid) { |
825 const intptr_t kNumTemps = 1; | 825 const intptr_t kNumTemps = 1; |
826 LocationSummary* locs = new(isolate) LocationSummary( | 826 LocationSummary* locs = new(isolate) LocationSummary( |
827 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 827 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
828 locs->set_in(0, Location::Pair(Location::RequiresRegister(), | 828 locs->set_in(0, Location::Pair(Location::RequiresRegister(), |
829 Location::RequiresRegister())); | 829 Location::RequiresRegister())); |
830 locs->set_in(1, Location::Pair(Location::RequiresRegister(), | 830 locs->set_in(1, Location::Pair(Location::RequiresRegister(), |
831 Location::RequiresRegister())); | 831 Location::RequiresRegister())); |
832 locs->set_temp(0, Location::RequiresRegister()); | 832 locs->set_temp(0, Location::RequiresRegister()); // TODO(regis): Improve. |
833 locs->set_out(0, Location::RequiresRegister()); | 833 locs->set_out(0, Location::RequiresRegister()); |
834 return locs; | 834 return locs; |
835 } | 835 } |
836 if (operation_cid() == kDoubleCid) { | 836 if (operation_cid() == kDoubleCid) { |
837 LocationSummary* summary = new(isolate) LocationSummary( | 837 LocationSummary* summary = new(isolate) LocationSummary( |
838 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 838 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
839 summary->set_in(0, Location::RequiresFpuRegister()); | 839 summary->set_in(0, Location::RequiresFpuRegister()); |
840 summary->set_in(1, Location::RequiresFpuRegister()); | 840 summary->set_in(1, Location::RequiresFpuRegister()); |
841 summary->set_out(0, Location::RequiresRegister()); | 841 summary->set_out(0, Location::RequiresRegister()); |
842 return summary; | 842 return summary; |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
896 | 896 |
897 | 897 |
898 void RelationalOpInstr::EmitBranchCode(FlowGraphCompiler* compiler, | 898 void RelationalOpInstr::EmitBranchCode(FlowGraphCompiler* compiler, |
899 BranchInstr* branch) { | 899 BranchInstr* branch) { |
900 BranchLabels labels = compiler->CreateBranchLabels(branch); | 900 BranchLabels labels = compiler->CreateBranchLabels(branch); |
901 Condition true_condition = EmitComparisonCode(compiler, labels); | 901 Condition true_condition = EmitComparisonCode(compiler, labels); |
902 | 902 |
903 if (operation_cid() == kSmiCid) { | 903 if (operation_cid() == kSmiCid) { |
904 EmitBranchOnCondition(compiler, true_condition, labels); | 904 EmitBranchOnCondition(compiler, true_condition, labels); |
905 } else if (operation_cid() == kMintCid) { | 905 } else if (operation_cid() == kMintCid) { |
906 const Register result = locs()->temp(0).reg(); | 906 const Register result = locs()->temp(0).reg(); // TODO(regis): Improve. |
907 __ CompareImmediate(result, 1); | 907 __ CompareImmediate(result, 1); |
908 __ b(labels.true_label, EQ); | 908 __ b(labels.true_label, EQ); |
909 __ b(labels.false_label, NE); | 909 __ b(labels.false_label, NE); |
910 } else if (operation_cid() == kDoubleCid) { | 910 } else if (operation_cid() == kDoubleCid) { |
911 Label* nan_result = (true_condition == NE) ? | 911 Label* nan_result = (true_condition == NE) ? |
912 labels.true_label : labels.false_label; | 912 labels.true_label : labels.false_label; |
913 __ b(nan_result, VS); | 913 __ b(nan_result, VS); |
914 EmitBranchOnCondition(compiler, true_condition, labels); | 914 EmitBranchOnCondition(compiler, true_condition, labels); |
915 } | 915 } |
916 } | 916 } |
(...skipping 2862 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3779 __ StoreToOffset(kWord, | 3779 __ StoreToOffset(kWord, |
3780 temp, | 3780 temp, |
3781 out, | 3781 out, |
3782 Mint::value_offset() - kHeapObjectTag + kWordSize); | 3782 Mint::value_offset() - kHeapObjectTag + kWordSize); |
3783 __ Bind(&done); | 3783 __ Bind(&done); |
3784 } | 3784 } |
3785 } | 3785 } |
3786 | 3786 |
3787 | 3787 |
3788 LocationSummary* BoxInt64Instr::MakeLocationSummary(Isolate* isolate, | 3788 LocationSummary* BoxInt64Instr::MakeLocationSummary(Isolate* isolate, |
3789 bool opt) const { | 3789 bool opt) const { |
3790 const intptr_t kNumInputs = 1; | 3790 const intptr_t kNumInputs = 1; |
3791 const intptr_t kNumTemps = ValueFitsSmi() ? 0 : 1; | 3791 const intptr_t kNumTemps = ValueFitsSmi() ? 0 : 1; |
3792 LocationSummary* summary = new(isolate) LocationSummary( | 3792 LocationSummary* summary = new(isolate) LocationSummary( |
3793 isolate, | 3793 isolate, |
3794 kNumInputs, | 3794 kNumInputs, |
3795 kNumTemps, | 3795 kNumTemps, |
3796 ValueFitsSmi() ? LocationSummary::kNoCall | 3796 ValueFitsSmi() ? LocationSummary::kNoCall |
3797 : LocationSummary::kCallOnSlowPath); | 3797 : LocationSummary::kCallOnSlowPath); |
3798 summary->set_in(0, Location::Pair(Location::RequiresRegister(), | 3798 summary->set_in(0, Location::Pair(Location::RequiresRegister(), |
3799 Location::RequiresRegister())); | 3799 Location::RequiresRegister())); |
(...skipping 2400 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6200 if (shift == 32) { | 6200 if (shift == 32) { |
6201 __ mov(out_hi, Operand(left_lo)); | 6201 __ mov(out_hi, Operand(left_lo)); |
6202 } else { | 6202 } else { |
6203 __ Lsl(out_hi, left_lo, Operand(shift - 32)); | 6203 __ Lsl(out_hi, left_lo, Operand(shift - 32)); |
6204 } | 6204 } |
6205 __ mov(out_lo, Operand(0)); | 6205 __ mov(out_lo, Operand(0)); |
6206 } | 6206 } |
6207 // Check for overflow. | 6207 // Check for overflow. |
6208 if (can_overflow()) { | 6208 if (can_overflow()) { |
6209 // Compare high word from input with shifted high word from output. | 6209 // Compare high word from input with shifted high word from output. |
6210 if (shift > 31) { | 6210 // If shift > 32, also compare low word from input with high word from |
6211 __ cmp(left_hi, Operand(out_hi)); | 6211 // output shifted back shift - 32. |
| 6212 if (shift > 32) { |
| 6213 __ cmp(left_lo, Operand(out_hi, ASR, shift - 32)); |
| 6214 __ cmp(left_hi, Operand(out_hi, ASR, 31), EQ); |
| 6215 } else if (shift == 32) { |
| 6216 __ cmp(left_hi, Operand(out_hi, ASR, 31)); |
6212 } else { | 6217 } else { |
6213 __ cmp(left_hi, Operand(out_hi, ASR, shift)); | 6218 __ cmp(left_hi, Operand(out_hi, ASR, shift)); |
6214 } | 6219 } |
6215 // Overflow if they aren't equal. | 6220 // Overflow if they aren't equal. |
6216 __ b(deopt, NE); | 6221 __ b(deopt, NE); |
6217 } | 6222 } |
6218 break; | 6223 break; |
6219 } | 6224 } |
6220 default: | 6225 default: |
6221 UNREACHABLE(); | 6226 UNREACHABLE(); |
6222 } | 6227 } |
6223 } else { | 6228 } else { |
6224 // Code for a variable shift amount. | 6229 // Code for a variable shift amount. |
6225 Register shift = locs()->in(1).reg(); | 6230 Register shift = locs()->in(1).reg(); |
6226 | 6231 |
6227 // Untag shift count. | 6232 // Untag shift count. |
6228 __ SmiUntag(shift); | 6233 __ SmiUntag(shift); |
6229 | 6234 |
6230 // Deopt if shift is larger than 63 or less than 0. | 6235 // Deopt if shift is larger than 63 or less than 0. |
6231 if (has_shift_count_check()) { | 6236 if (has_shift_count_check()) { |
6232 __ CompareImmediate(shift, kMintShiftCountLimit); | 6237 __ CompareImmediate(shift, kMintShiftCountLimit); |
6233 __ b(deopt, HI); | 6238 __ b(deopt, HI); |
6234 } | 6239 } |
6235 | 6240 |
6236 __ mov(out_lo, Operand(left_lo)); | |
6237 __ mov(out_hi, Operand(left_hi)); | |
6238 | |
6239 switch (op_kind()) { | 6241 switch (op_kind()) { |
6240 case Token::kSHR: { | 6242 case Token::kSHR: { |
6241 __ cmp(shift, Operand(32)); | 6243 __ rsbs(IP, shift, Operand(32)); |
6242 | 6244 __ sub(IP, shift, Operand(32), MI); |
6243 __ mov(out_lo, Operand(out_hi), HI); | 6245 __ mov(out_lo, Operand(left_hi, ASR, IP), MI); |
6244 __ Asr(out_hi, out_hi, Operand(31), HI); | 6246 __ mov(out_lo, Operand(left_lo, LSR, shift), PL); |
6245 __ sub(shift, shift, Operand(32), HI); | 6247 __ orr(out_lo, out_lo, Operand(left_hi, LSL, IP), PL); |
6246 | 6248 __ mov(out_hi, Operand(left_hi, ASR, shift)); |
6247 __ rsb(IP, shift, Operand(32)); | |
6248 __ mov(IP, Operand(out_hi, LSL, IP)); | |
6249 __ orr(out_lo, IP, Operand(out_lo, LSR, shift)); | |
6250 __ Asr(out_hi, out_hi, shift); | |
6251 break; | 6249 break; |
6252 } | 6250 } |
6253 case Token::kSHL: { | 6251 case Token::kSHL: { |
6254 __ rsbs(IP, shift, Operand(32)); | 6252 __ rsbs(IP, shift, Operand(32)); |
6255 __ sub(IP, shift, Operand(32), MI); | 6253 __ sub(IP, shift, Operand(32), MI); |
6256 __ mov(out_hi, Operand(out_lo, LSL, IP), MI); | 6254 __ mov(out_hi, Operand(left_lo, LSL, IP), MI); |
6257 __ mov(out_hi, Operand(out_hi, LSL, shift), PL); | 6255 __ mov(out_hi, Operand(left_hi, LSL, shift), PL); |
6258 __ orr(out_hi, out_hi, Operand(out_lo, LSR, IP), PL); | 6256 __ orr(out_hi, out_hi, Operand(left_lo, LSR, IP), PL); |
6259 __ mov(out_lo, Operand(out_lo, LSL, shift)); | 6257 __ mov(out_lo, Operand(left_lo, LSL, shift)); |
6260 | 6258 |
6261 // Check for overflow. | 6259 // Check for overflow. |
6262 if (can_overflow()) { | 6260 if (can_overflow()) { |
| 6261 // If shift > 32, compare low word from input with high word from |
| 6262 // output shifted back shift - 32. |
| 6263 __ mov(IP, Operand(out_hi, ASR, IP), MI); |
| 6264 __ mov(IP, Operand(left_lo), PL); // No test if shift <= 32. |
| 6265 __ cmp(left_lo, Operand(IP)); |
6263 // Compare high word from input with shifted high word from output. | 6266 // Compare high word from input with shifted high word from output. |
6264 __ cmp(left_hi, Operand(out_hi, ASR, shift)); | 6267 __ cmp(left_hi, Operand(out_hi, ASR, shift), EQ); |
6265 // Overflow if they aren't equal. | 6268 // Overflow if they aren't equal. |
6266 __ b(deopt, NE); | 6269 __ b(deopt, NE); |
6267 } | 6270 } |
6268 break; | 6271 break; |
6269 } | 6272 } |
6270 default: | 6273 default: |
6271 UNREACHABLE(); | 6274 UNREACHABLE(); |
6272 } | 6275 } |
6273 } | 6276 } |
6274 | 6277 |
(...skipping 475 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6750 compiler->GenerateCall(token_pos(), &label, stub_kind_, locs()); | 6753 compiler->GenerateCall(token_pos(), &label, stub_kind_, locs()); |
6751 #if defined(DEBUG) | 6754 #if defined(DEBUG) |
6752 __ LoadImmediate(R4, kInvalidObjectPointer); | 6755 __ LoadImmediate(R4, kInvalidObjectPointer); |
6753 __ LoadImmediate(R5, kInvalidObjectPointer); | 6756 __ LoadImmediate(R5, kInvalidObjectPointer); |
6754 #endif | 6757 #endif |
6755 } | 6758 } |
6756 | 6759 |
6757 } // namespace dart | 6760 } // namespace dart |
6758 | 6761 |
6759 #endif // defined TARGET_ARCH_ARM | 6762 #endif // defined TARGET_ARCH_ARM |
OLD | NEW |