| 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_MIPS. | 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_MIPS. |
| 6 #if defined(TARGET_ARCH_MIPS) | 6 #if defined(TARGET_ARCH_MIPS) |
| 7 | 7 |
| 8 #include "vm/intermediate_language.h" | 8 #include "vm/intermediate_language.h" |
| 9 | 9 |
| 10 #include "vm/dart_entry.h" | 10 #include "vm/dart_entry.h" |
| (...skipping 2464 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2475 } | 2475 } |
| 2476 | 2476 |
| 2477 default: | 2477 default: |
| 2478 UNREACHABLE(); | 2478 UNREACHABLE(); |
| 2479 break; | 2479 break; |
| 2480 } | 2480 } |
| 2481 return; | 2481 return; |
| 2482 } | 2482 } |
| 2483 | 2483 |
| 2484 Register right = locs()->in(1).reg(); | 2484 Register right = locs()->in(1).reg(); |
| 2485 Range* right_range = this->right()->definition()->range(); |
| 2485 switch (op_kind()) { | 2486 switch (op_kind()) { |
| 2486 case Token::kADD: { | 2487 case Token::kADD: { |
| 2487 if (deopt == NULL) { | 2488 if (deopt == NULL) { |
| 2488 __ addu(result, left, right); | 2489 __ addu(result, left, right); |
| 2489 } else { | 2490 } else { |
| 2490 Register temp = locs()->temp(0).reg(); | 2491 Register temp = locs()->temp(0).reg(); |
| 2491 __ AdduDetectOverflow(result, left, right, CMPRES1, temp); | 2492 __ AdduDetectOverflow(result, left, right, CMPRES1, temp); |
| 2492 __ bltz(CMPRES1, deopt); | 2493 __ bltz(CMPRES1, deopt); |
| 2493 } | 2494 } |
| 2494 break; | 2495 break; |
| (...skipping 29 matching lines...) Expand all Loading... |
| 2524 // No overflow check. | 2525 // No overflow check. |
| 2525 __ or_(result, left, right); | 2526 __ or_(result, left, right); |
| 2526 break; | 2527 break; |
| 2527 } | 2528 } |
| 2528 case Token::kBIT_XOR: { | 2529 case Token::kBIT_XOR: { |
| 2529 // No overflow check. | 2530 // No overflow check. |
| 2530 __ xor_(result, left, right); | 2531 __ xor_(result, left, right); |
| 2531 break; | 2532 break; |
| 2532 } | 2533 } |
| 2533 case Token::kTRUNCDIV: { | 2534 case Token::kTRUNCDIV: { |
| 2534 // Handle divide by zero in runtime. | 2535 if ((right_range == NULL) || right_range->Overlaps(0, 0)) { |
| 2535 __ beq(right, ZR, deopt); | 2536 // Handle divide by zero in runtime. |
| 2537 __ beq(right, ZR, deopt); |
| 2538 } |
| 2536 Register temp = locs()->temp(0).reg(); | 2539 Register temp = locs()->temp(0).reg(); |
| 2537 __ sra(temp, left, kSmiTagSize); // SmiUntag left into temp. | 2540 __ sra(temp, left, kSmiTagSize); // SmiUntag left into temp. |
| 2538 __ sra(TMP, right, kSmiTagSize); // SmiUntag right into TMP. | 2541 __ sra(TMP, right, kSmiTagSize); // SmiUntag right into TMP. |
| 2539 __ div(temp, TMP); | 2542 __ div(temp, TMP); |
| 2540 __ mflo(result); | 2543 __ mflo(result); |
| 2541 // Check the corner case of dividing the 'MIN_SMI' with -1, in which | 2544 // Check the corner case of dividing the 'MIN_SMI' with -1, in which |
| 2542 // case we cannot tag the result. | 2545 // case we cannot tag the result. |
| 2543 __ BranchEqual(result, 0x40000000, deopt); | 2546 __ BranchEqual(result, 0x40000000, deopt); |
| 2544 __ SmiTag(result); | 2547 __ SmiTag(result); |
| 2545 break; | 2548 break; |
| 2546 } | 2549 } |
| 2547 case Token::kMOD: { | 2550 case Token::kMOD: { |
| 2548 // Handle divide by zero in runtime. | 2551 if ((right_range == NULL) || right_range->Overlaps(0, 0)) { |
| 2549 __ beq(right, ZR, deopt); | 2552 // Handle divide by zero in runtime. |
| 2553 __ beq(right, ZR, deopt); |
| 2554 } |
| 2550 Register temp = locs()->temp(0).reg(); | 2555 Register temp = locs()->temp(0).reg(); |
| 2551 __ sra(temp, left, kSmiTagSize); // SmiUntag left into temp. | 2556 __ sra(temp, left, kSmiTagSize); // SmiUntag left into temp. |
| 2552 __ sra(TMP, right, kSmiTagSize); // SmiUntag right into TMP. | 2557 __ sra(TMP, right, kSmiTagSize); // SmiUntag right into TMP. |
| 2553 __ div(temp, TMP); | 2558 __ div(temp, TMP); |
| 2554 __ mfhi(result); | 2559 __ mfhi(result); |
| 2555 // res = left % right; | 2560 // res = left % right; |
| 2556 // if (res < 0) { | 2561 // if (res < 0) { |
| 2557 // if (right < 0) { | 2562 // if (right < 0) { |
| 2558 // res = res - right; | 2563 // res = res - right; |
| 2559 // } else { | 2564 // } else { |
| 2560 // res = res + right; | 2565 // res = res + right; |
| 2561 // } | 2566 // } |
| 2562 // } | 2567 // } |
| 2563 Label done, subtract; | 2568 Label done; |
| 2564 __ bgez(result, &done); | 2569 __ bgez(result, &done); |
| 2565 __ bltz(right, &subtract); | 2570 if ((right_range == NULL) || right_range->Overlaps(-1, 1)) { |
| 2566 __ addu(result, result, TMP); | 2571 Label subtract; |
| 2567 __ b(&done); | 2572 __ bltz(right, &subtract); |
| 2568 __ Bind(&subtract); | 2573 __ addu(result, result, TMP); |
| 2569 __ subu(result, result, TMP); | 2574 __ b(&done); |
| 2575 __ Bind(&subtract); |
| 2576 __ subu(result, result, TMP); |
| 2577 } else if (right_range->IsWithin(0, RangeBoundary::kPlusInfinity)) { |
| 2578 // Right is positive. |
| 2579 __ addu(result, result, TMP); |
| 2580 } else { |
| 2581 // Right is negative. |
| 2582 __ subu(result, result, TMP); |
| 2583 } |
| 2570 __ Bind(&done); | 2584 __ Bind(&done); |
| 2571 __ SmiTag(result); | 2585 __ SmiTag(result); |
| 2572 break; | 2586 break; |
| 2573 } | 2587 } |
| 2574 case Token::kSHR: { | 2588 case Token::kSHR: { |
| 2575 Register temp = locs()->temp(0).reg(); | 2589 Register temp = locs()->temp(0).reg(); |
| 2576 if (CanDeoptimize()) { | 2590 if (CanDeoptimize()) { |
| 2577 __ bltz(right, deopt); | 2591 __ bltz(right, deopt); |
| 2578 } | 2592 } |
| 2579 __ sra(temp, right, kSmiTagSize); // SmiUntag right into temp. | 2593 __ sra(temp, right, kSmiTagSize); // SmiUntag right into temp. |
| 2580 // sra operation masks the count to 5 bits. | 2594 // sra operation masks the count to 5 bits. |
| 2581 const intptr_t kCountLimit = 0x1F; | 2595 const intptr_t kCountLimit = 0x1F; |
| 2582 Range* right_range = this->right()->definition()->range(); | |
| 2583 if ((right_range == NULL) || | 2596 if ((right_range == NULL) || |
| 2584 !right_range->IsWithin(RangeBoundary::kMinusInfinity, kCountLimit)) { | 2597 !right_range->IsWithin(RangeBoundary::kMinusInfinity, kCountLimit)) { |
| 2585 Label ok; | 2598 Label ok; |
| 2586 __ BranchSignedLessEqual(temp, kCountLimit, &ok); | 2599 __ BranchSignedLessEqual(temp, kCountLimit, &ok); |
| 2587 __ LoadImmediate(temp, kCountLimit); | 2600 __ LoadImmediate(temp, kCountLimit); |
| 2588 __ Bind(&ok); | 2601 __ Bind(&ok); |
| 2589 } | 2602 } |
| 2590 | 2603 |
| 2591 __ sra(CMPRES1, left, kSmiTagSize); // SmiUntag left into CMPRES1. | 2604 __ sra(CMPRES1, left, kSmiTagSize); // SmiUntag left into CMPRES1. |
| 2592 __ srav(result, CMPRES1, temp); | 2605 __ srav(result, CMPRES1, temp); |
| (...skipping 831 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3424 if (CanDeoptimize()) { | 3437 if (CanDeoptimize()) { |
| 3425 deopt = compiler->AddDeoptStub(deopt_id(), kDeoptBinarySmiOp); | 3438 deopt = compiler->AddDeoptStub(deopt_id(), kDeoptBinarySmiOp); |
| 3426 } | 3439 } |
| 3427 if (kind() == MergedMathInstr::kTruncDivMod) { | 3440 if (kind() == MergedMathInstr::kTruncDivMod) { |
| 3428 Register left = locs()->in(0).reg(); | 3441 Register left = locs()->in(0).reg(); |
| 3429 Register right = locs()->in(1).reg(); | 3442 Register right = locs()->in(1).reg(); |
| 3430 Register result = locs()->out().reg(); | 3443 Register result = locs()->out().reg(); |
| 3431 Register temp = locs()->temp(0).reg(); | 3444 Register temp = locs()->temp(0).reg(); |
| 3432 Register result_div = locs()->temp(1).reg(); | 3445 Register result_div = locs()->temp(1).reg(); |
| 3433 Register result_mod = locs()->temp(2).reg(); | 3446 Register result_mod = locs()->temp(2).reg(); |
| 3434 // Handle divide by zero in runtime. | 3447 Range* right_range = InputAt(1)->definition()->range(); |
| 3435 __ beq(right, ZR, deopt); | 3448 if ((right_range == NULL) || right_range->Overlaps(0, 0)) { |
| 3449 // Handle divide by zero in runtime. |
| 3450 __ beq(right, ZR, deopt); |
| 3451 } |
| 3436 __ sra(temp, left, kSmiTagSize); // SmiUntag left into temp. | 3452 __ sra(temp, left, kSmiTagSize); // SmiUntag left into temp. |
| 3437 __ sra(TMP, right, kSmiTagSize); // SmiUntag right into TMP. | 3453 __ sra(TMP, right, kSmiTagSize); // SmiUntag right into TMP. |
| 3438 __ div(temp, TMP); | 3454 __ div(temp, TMP); |
| 3439 __ mflo(result_div); | 3455 __ mflo(result_div); |
| 3440 __ mfhi(result_mod); | 3456 __ mfhi(result_mod); |
| 3441 // Check the corner case of dividing the 'MIN_SMI' with -1, in which | 3457 // Check the corner case of dividing the 'MIN_SMI' with -1, in which |
| 3442 // case we cannot tag the result. | 3458 // case we cannot tag the result. |
| 3443 __ BranchEqual(result_div, 0x40000000, deopt); | 3459 __ BranchEqual(result_div, 0x40000000, deopt); |
| 3444 // res = left % right; | 3460 // res = left % right; |
| 3445 // if (res < 0) { | 3461 // if (res < 0) { |
| 3446 // if (right < 0) { | 3462 // if (right < 0) { |
| 3447 // res = res - right; | 3463 // res = res - right; |
| 3448 // } else { | 3464 // } else { |
| 3449 // res = res + right; | 3465 // res = res + right; |
| 3450 // } | 3466 // } |
| 3451 // } | 3467 // } |
| 3452 Label done, subtract; | 3468 Label done; |
| 3453 __ bgez(result_mod, &done); | 3469 __ bgez(result_mod, &done); |
| 3454 __ bltz(right, &subtract); | 3470 if ((right_range == NULL) || right_range->Overlaps(-1, 1)) { |
| 3455 __ addu(result_mod, result_mod, TMP); | 3471 Label subtract; |
| 3456 __ b(&done); | 3472 __ bltz(right, &subtract); |
| 3457 __ Bind(&subtract); | 3473 __ addu(result_mod, result_mod, TMP); |
| 3458 __ subu(result_mod, result_mod, TMP); | 3474 __ b(&done); |
| 3475 __ Bind(&subtract); |
| 3476 __ subu(result_mod, result_mod, TMP); |
| 3477 } else if (right_range->IsWithin(0, RangeBoundary::kPlusInfinity)) { |
| 3478 // Right is positive. |
| 3479 __ addu(result_mod, result_mod, TMP); |
| 3480 } else { |
| 3481 // Right is negative. |
| 3482 __ subu(result_mod, result_mod, TMP); |
| 3483 } |
| 3459 __ Bind(&done); | 3484 __ Bind(&done); |
| 3460 | 3485 |
| 3461 __ SmiTag(result_div); | 3486 __ SmiTag(result_div); |
| 3462 __ SmiTag(result_mod); | 3487 __ SmiTag(result_mod); |
| 3463 __ LoadObject(result, Array::ZoneHandle(Array::New(2, Heap::kOld))); | 3488 __ LoadObject(result, Array::ZoneHandle(Array::New(2, Heap::kOld))); |
| 3464 // Note that index is expected smi-tagged, (i.e, times 2) for all arrays. | 3489 // Note that index is expected smi-tagged, (i.e, times 2) for all arrays. |
| 3465 // [0]: divide resut, [1]: mod result. | 3490 // [0]: divide resut, [1]: mod result. |
| 3466 __ LoadImmediate(temp, | 3491 __ LoadImmediate(temp, |
| 3467 FlowGraphCompiler::DataOffsetFor(kArrayCid) - kHeapObjectTag); | 3492 FlowGraphCompiler::DataOffsetFor(kArrayCid) - kHeapObjectTag); |
| 3468 __ addu(temp, result, temp); | 3493 __ addu(temp, result, temp); |
| (...skipping 500 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3969 compiler->GenerateCall(token_pos(), | 3994 compiler->GenerateCall(token_pos(), |
| 3970 &label, | 3995 &label, |
| 3971 PcDescriptors::kOther, | 3996 PcDescriptors::kOther, |
| 3972 locs()); | 3997 locs()); |
| 3973 __ Drop(2); // Discard type arguments and receiver. | 3998 __ Drop(2); // Discard type arguments and receiver. |
| 3974 } | 3999 } |
| 3975 | 4000 |
| 3976 } // namespace dart | 4001 } // namespace dart |
| 3977 | 4002 |
| 3978 #endif // defined TARGET_ARCH_MIPS | 4003 #endif // defined TARGET_ARCH_MIPS |
| OLD | NEW |