| 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 2958 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3875 __ StoreToOffset(kWord, | 3875 __ StoreToOffset(kWord, |
| 3876 temp, | 3876 temp, |
| 3877 out, | 3877 out, |
| 3878 Mint::value_offset() - kHeapObjectTag + kWordSize); | 3878 Mint::value_offset() - kHeapObjectTag + kWordSize); |
| 3879 __ Bind(&done); | 3879 __ Bind(&done); |
| 3880 } | 3880 } |
| 3881 } | 3881 } |
| 3882 | 3882 |
| 3883 | 3883 |
| 3884 LocationSummary* BoxInt64Instr::MakeLocationSummary(Isolate* isolate, | 3884 LocationSummary* BoxInt64Instr::MakeLocationSummary(Isolate* isolate, |
| 3885 bool opt) const { | 3885 bool opt) const { |
| 3886 const intptr_t kNumInputs = 1; | 3886 const intptr_t kNumInputs = 1; |
| 3887 const intptr_t kNumTemps = ValueFitsSmi() ? 0 : 1; | 3887 const intptr_t kNumTemps = ValueFitsSmi() ? 0 : 1; |
| 3888 LocationSummary* summary = new(isolate) LocationSummary( | 3888 LocationSummary* summary = new(isolate) LocationSummary( |
| 3889 isolate, | 3889 isolate, |
| 3890 kNumInputs, | 3890 kNumInputs, |
| 3891 kNumTemps, | 3891 kNumTemps, |
| 3892 ValueFitsSmi() ? LocationSummary::kNoCall | 3892 ValueFitsSmi() ? LocationSummary::kNoCall |
| 3893 : LocationSummary::kCallOnSlowPath); | 3893 : LocationSummary::kCallOnSlowPath); |
| 3894 summary->set_in(0, Location::Pair(Location::RequiresRegister(), | 3894 summary->set_in(0, Location::Pair(Location::RequiresRegister(), |
| 3895 Location::RequiresRegister())); | 3895 Location::RequiresRegister())); |
| (...skipping 2422 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6318 if (shift == 32) { | 6318 if (shift == 32) { |
| 6319 __ mov(out_hi, Operand(left_lo)); | 6319 __ mov(out_hi, Operand(left_lo)); |
| 6320 } else { | 6320 } else { |
| 6321 __ Lsl(out_hi, left_lo, Operand(shift - 32)); | 6321 __ Lsl(out_hi, left_lo, Operand(shift - 32)); |
| 6322 } | 6322 } |
| 6323 __ mov(out_lo, Operand(0)); | 6323 __ mov(out_lo, Operand(0)); |
| 6324 } | 6324 } |
| 6325 // Check for overflow. | 6325 // Check for overflow. |
| 6326 if (can_overflow()) { | 6326 if (can_overflow()) { |
| 6327 // Compare high word from input with shifted high word from output. | 6327 // Compare high word from input with shifted high word from output. |
| 6328 if (shift > 31) { | 6328 // If shift > 32, also compare low word from input with high word from |
| 6329 __ cmp(left_hi, Operand(out_hi)); | 6329 // output shifted back shift - 32. |
| 6330 if (shift > 32) { |
| 6331 __ cmp(left_lo, Operand(out_hi, ASR, shift - 32)); |
| 6332 __ cmp(left_hi, Operand(out_hi, ASR, 31), EQ); |
| 6333 } else if (shift == 32) { |
| 6334 __ cmp(left_hi, Operand(out_hi, ASR, 31)); |
| 6330 } else { | 6335 } else { |
| 6331 __ cmp(left_hi, Operand(out_hi, ASR, shift)); | 6336 __ cmp(left_hi, Operand(out_hi, ASR, shift)); |
| 6332 } | 6337 } |
| 6333 // Overflow if they aren't equal. | 6338 // Overflow if they aren't equal. |
| 6334 __ b(deopt, NE); | 6339 __ b(deopt, NE); |
| 6335 } | 6340 } |
| 6336 break; | 6341 break; |
| 6337 } | 6342 } |
| 6338 default: | 6343 default: |
| 6339 UNREACHABLE(); | 6344 UNREACHABLE(); |
| 6340 } | 6345 } |
| 6341 } else { | 6346 } else { |
| 6342 // Code for a variable shift amount. | 6347 // Code for a variable shift amount. |
| 6343 Register shift = locs()->in(1).reg(); | 6348 Register shift = locs()->in(1).reg(); |
| 6344 | 6349 |
| 6345 // Untag shift count. | 6350 // Untag shift count. |
| 6346 __ SmiUntag(shift); | 6351 __ SmiUntag(shift); |
| 6347 | 6352 |
| 6348 // Deopt if shift is larger than 63 or less than 0. | 6353 // Deopt if shift is larger than 63 or less than 0. |
| 6349 if (has_shift_count_check()) { | 6354 if (has_shift_count_check()) { |
| 6350 __ CompareImmediate(shift, kMintShiftCountLimit); | 6355 __ CompareImmediate(shift, kMintShiftCountLimit); |
| 6351 __ b(deopt, HI); | 6356 __ b(deopt, HI); |
| 6352 } | 6357 } |
| 6353 | 6358 |
| 6354 __ mov(out_lo, Operand(left_lo)); | |
| 6355 __ mov(out_hi, Operand(left_hi)); | |
| 6356 | |
| 6357 switch (op_kind()) { | 6359 switch (op_kind()) { |
| 6358 case Token::kSHR: { | 6360 case Token::kSHR: { |
| 6359 __ cmp(shift, Operand(32)); | 6361 __ rsbs(IP, shift, Operand(32)); |
| 6360 | 6362 __ sub(IP, shift, Operand(32), MI); |
| 6361 __ mov(out_lo, Operand(out_hi), HI); | 6363 __ mov(out_lo, Operand(left_hi, ASR, IP), MI); |
| 6362 __ Asr(out_hi, out_hi, Operand(31), HI); | 6364 __ mov(out_lo, Operand(left_lo, LSR, shift), PL); |
| 6363 __ sub(shift, shift, Operand(32), HI); | 6365 __ orr(out_lo, out_lo, Operand(left_hi, LSL, IP), PL); |
| 6364 | 6366 __ mov(out_hi, Operand(left_hi, ASR, shift)); |
| 6365 __ rsb(IP, shift, Operand(32)); | |
| 6366 __ mov(IP, Operand(out_hi, LSL, IP)); | |
| 6367 __ orr(out_lo, IP, Operand(out_lo, LSR, shift)); | |
| 6368 __ Asr(out_hi, out_hi, shift); | |
| 6369 break; | 6367 break; |
| 6370 } | 6368 } |
| 6371 case Token::kSHL: { | 6369 case Token::kSHL: { |
| 6372 __ rsbs(IP, shift, Operand(32)); | 6370 __ rsbs(IP, shift, Operand(32)); |
| 6373 __ sub(IP, shift, Operand(32), MI); | 6371 __ sub(IP, shift, Operand(32), MI); |
| 6374 __ mov(out_hi, Operand(out_lo, LSL, IP), MI); | 6372 __ mov(out_hi, Operand(left_lo, LSL, IP), MI); |
| 6375 __ mov(out_hi, Operand(out_hi, LSL, shift), PL); | 6373 __ mov(out_hi, Operand(left_hi, LSL, shift), PL); |
| 6376 __ orr(out_hi, out_hi, Operand(out_lo, LSR, IP), PL); | 6374 __ orr(out_hi, out_hi, Operand(left_lo, LSR, IP), PL); |
| 6377 __ mov(out_lo, Operand(out_lo, LSL, shift)); | 6375 __ mov(out_lo, Operand(left_lo, LSL, shift)); |
| 6378 | 6376 |
| 6379 // Check for overflow. | 6377 // Check for overflow. |
| 6380 if (can_overflow()) { | 6378 if (can_overflow()) { |
| 6379 // If shift > 32, compare low word from input with high word from |
| 6380 // output shifted back shift - 32. |
| 6381 __ mov(IP, Operand(out_hi, ASR, IP), MI); |
| 6382 __ mov(IP, Operand(left_lo), PL); // No test if shift <= 32. |
| 6383 __ cmp(left_lo, Operand(IP)); |
| 6381 // Compare high word from input with shifted high word from output. | 6384 // Compare high word from input with shifted high word from output. |
| 6382 __ cmp(left_hi, Operand(out_hi, ASR, shift)); | 6385 __ cmp(left_hi, Operand(out_hi, ASR, shift), EQ); |
| 6383 // Overflow if they aren't equal. | 6386 // Overflow if they aren't equal. |
| 6384 __ b(deopt, NE); | 6387 __ b(deopt, NE); |
| 6385 } | 6388 } |
| 6386 break; | 6389 break; |
| 6387 } | 6390 } |
| 6388 default: | 6391 default: |
| 6389 UNREACHABLE(); | 6392 UNREACHABLE(); |
| 6390 } | 6393 } |
| 6391 } | 6394 } |
| 6392 | 6395 |
| (...skipping 507 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6900 compiler->GenerateCall(token_pos(), &label, stub_kind_, locs()); | 6903 compiler->GenerateCall(token_pos(), &label, stub_kind_, locs()); |
| 6901 #if defined(DEBUG) | 6904 #if defined(DEBUG) |
| 6902 __ LoadImmediate(R4, kInvalidObjectPointer); | 6905 __ LoadImmediate(R4, kInvalidObjectPointer); |
| 6903 __ LoadImmediate(R5, kInvalidObjectPointer); | 6906 __ LoadImmediate(R5, kInvalidObjectPointer); |
| 6904 #endif | 6907 #endif |
| 6905 } | 6908 } |
| 6906 | 6909 |
| 6907 } // namespace dart | 6910 } // namespace dart |
| 6908 | 6911 |
| 6909 #endif // defined TARGET_ARCH_ARM | 6912 #endif // defined TARGET_ARCH_ARM |
| OLD | NEW |