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