Chromium Code Reviews| 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/dart_entry.h" | 10 #include "vm/dart_entry.h" |
| (...skipping 2221 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2232 summary->set_in(1, Location::Constant(right_constant->value())); | 2232 summary->set_in(1, Location::Constant(right_constant->value())); |
| 2233 summary->AddTemp(Location::RequiresRegister()); | 2233 summary->AddTemp(Location::RequiresRegister()); |
| 2234 } else { | 2234 } else { |
| 2235 summary->set_in(1, Location::RequiresRegister()); | 2235 summary->set_in(1, Location::RequiresRegister()); |
| 2236 summary->AddTemp(Location::RequiresRegister()); | 2236 summary->AddTemp(Location::RequiresRegister()); |
| 2237 summary->AddTemp(Location::RequiresFpuRegister()); | 2237 summary->AddTemp(Location::RequiresFpuRegister()); |
| 2238 } | 2238 } |
| 2239 summary->set_out(Location::RequiresRegister()); | 2239 summary->set_out(Location::RequiresRegister()); |
| 2240 return summary; | 2240 return summary; |
| 2241 } | 2241 } |
| 2242 if (op_kind() == Token::kMOD) { | |
| 2243 summary->set_in(0, Location::RequiresRegister()); | |
| 2244 summary->set_in(1, Location::RequiresRegister()); | |
| 2245 summary->AddTemp(Location::RequiresRegister()); | |
| 2246 summary->AddTemp(Location::RequiresFpuRegister()); | |
| 2247 summary->set_out(Location::RequiresRegister()); | |
| 2248 return summary; | |
| 2249 } | |
| 2242 summary->set_in(0, Location::RequiresRegister()); | 2250 summary->set_in(0, Location::RequiresRegister()); |
| 2243 summary->set_in(1, Location::RegisterOrSmiConstant(right())); | 2251 summary->set_in(1, Location::RegisterOrSmiConstant(right())); |
| 2244 if (((op_kind() == Token::kSHL) && !is_truncating()) || | 2252 if (((op_kind() == Token::kSHL) && !is_truncating()) || |
| 2245 (op_kind() == Token::kSHR)) { | 2253 (op_kind() == Token::kSHR)) { |
| 2246 summary->AddTemp(Location::RequiresRegister()); | 2254 summary->AddTemp(Location::RequiresRegister()); |
| 2247 } | 2255 } |
| 2248 // We make use of 3-operand instructions by not requiring result register | 2256 // We make use of 3-operand instructions by not requiring result register |
| 2249 // to be identical to first input register as on Intel. | 2257 // to be identical to first input register as on Intel. |
| 2250 summary->set_out(Location::RequiresRegister()); | 2258 summary->set_out(Location::RequiresRegister()); |
| 2251 return summary; | 2259 return summary; |
| (...skipping 208 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2460 | 2468 |
| 2461 __ IntegerDivide(result, temp, IP, dtemp, DTMP); | 2469 __ IntegerDivide(result, temp, IP, dtemp, DTMP); |
| 2462 | 2470 |
| 2463 // Check the corner case of dividing the 'MIN_SMI' with -1, in which | 2471 // Check the corner case of dividing the 'MIN_SMI' with -1, in which |
| 2464 // case we cannot tag the result. | 2472 // case we cannot tag the result. |
| 2465 __ CompareImmediate(result, 0x40000000); | 2473 __ CompareImmediate(result, 0x40000000); |
| 2466 __ b(deopt, EQ); | 2474 __ b(deopt, EQ); |
| 2467 __ SmiTag(result); | 2475 __ SmiTag(result); |
| 2468 break; | 2476 break; |
| 2469 } | 2477 } |
| 2478 case Token::kMOD: { | |
| 2479 // Handle divide by zero in runtime. | |
| 2480 __ cmp(right, ShifterOperand(0)); | |
| 2481 __ b(deopt, EQ); | |
| 2482 Register temp = locs()->temp(0).reg(); | |
| 2483 DRegister dtemp = EvenDRegisterOf(locs()->temp(1).fpu_reg()); | |
| 2484 __ Asr(temp, left, kSmiTagSize); // SmiUntag left into temp. | |
| 2485 __ Asr(IP, right, kSmiTagSize); // SmiUntag right into IP. | |
| 2486 | |
| 2487 __ IntegerDivide(result, temp, IP, dtemp, DTMP); | |
| 2488 | |
| 2489 __ Asr(IP, right, kSmiTagSize); // SmiUntag right into IP. | |
|
zra
2013/11/07 16:40:06
IntegerDivide doesn't clobber temp and IP here, so
srdjan
2013/11/07 21:26:10
I think it is safe to assume that IP is not guaran
| |
| 2490 __ mls(result, IP, result, temp); // result <- left - right * result | |
| 2491 __ SmiTag(result); | |
| 2492 // res = left % right; | |
| 2493 // if (res < 0) { | |
| 2494 // if (right < 0) { | |
| 2495 // res = res - right; | |
| 2496 // } else { | |
| 2497 // res = res + right; | |
| 2498 // } | |
| 2499 // } | |
| 2500 Label done; | |
| 2501 __ cmp(result, ShifterOperand(0)); | |
| 2502 __ b(&done, GE); | |
| 2503 // Result is negative, adjust it. | |
| 2504 __ cmp(right, ShifterOperand(0)); | |
| 2505 __ sub(result, result, ShifterOperand(right), LT); | |
| 2506 __ add(result, result, ShifterOperand(right), GE); | |
| 2507 __ Bind(&done); | |
| 2508 break; | |
| 2509 } | |
| 2470 case Token::kSHR: { | 2510 case Token::kSHR: { |
| 2471 if (CanDeoptimize()) { | 2511 if (CanDeoptimize()) { |
| 2472 __ CompareImmediate(right, 0); | 2512 __ CompareImmediate(right, 0); |
| 2473 __ b(deopt, LT); | 2513 __ b(deopt, LT); |
| 2474 } | 2514 } |
| 2475 __ Asr(IP, right, kSmiTagSize); // SmiUntag right into IP. | 2515 __ Asr(IP, right, kSmiTagSize); // SmiUntag right into IP. |
| 2476 // sarl operation masks the count to 5 bits. | 2516 // sarl operation masks the count to 5 bits. |
| 2477 const intptr_t kCountLimit = 0x1F; | 2517 const intptr_t kCountLimit = 0x1F; |
| 2478 Range* right_range = this->right()->definition()->range(); | 2518 Range* right_range = this->right()->definition()->range(); |
| 2479 if ((right_range == NULL) || | 2519 if ((right_range == NULL) || |
| 2480 !right_range->IsWithin(RangeBoundary::kMinusInfinity, kCountLimit)) { | 2520 !right_range->IsWithin(RangeBoundary::kMinusInfinity, kCountLimit)) { |
| 2481 __ CompareImmediate(IP, kCountLimit); | 2521 __ CompareImmediate(IP, kCountLimit); |
| 2482 __ LoadImmediate(IP, kCountLimit, GT); | 2522 __ LoadImmediate(IP, kCountLimit, GT); |
| 2483 } | 2523 } |
| 2484 Register temp = locs()->temp(0).reg(); | 2524 Register temp = locs()->temp(0).reg(); |
| 2485 __ Asr(temp, left, kSmiTagSize); // SmiUntag left into temp. | 2525 __ Asr(temp, left, kSmiTagSize); // SmiUntag left into temp. |
| 2486 __ Asr(result, temp, IP); | 2526 __ Asr(result, temp, IP); |
| 2487 __ SmiTag(result); | 2527 __ SmiTag(result); |
| 2488 break; | 2528 break; |
| 2489 } | 2529 } |
| 2490 case Token::kDIV: { | 2530 case Token::kDIV: { |
| 2491 // Dispatches to 'Double./'. | 2531 // Dispatches to 'Double./'. |
| 2492 // TODO(srdjan): Implement as conversion to double and double division. | 2532 // TODO(srdjan): Implement as conversion to double and double division. |
| 2493 UNREACHABLE(); | 2533 UNREACHABLE(); |
| 2494 break; | 2534 break; |
| 2495 } | 2535 } |
| 2496 case Token::kMOD: { | |
| 2497 // TODO(srdjan): Implement. | |
| 2498 UNREACHABLE(); | |
| 2499 break; | |
| 2500 } | |
| 2501 case Token::kOR: | 2536 case Token::kOR: |
| 2502 case Token::kAND: { | 2537 case Token::kAND: { |
| 2503 // Flow graph builder has dissected this operation to guarantee correct | 2538 // Flow graph builder has dissected this operation to guarantee correct |
| 2504 // behavior (short-circuit evaluation). | 2539 // behavior (short-circuit evaluation). |
| 2505 UNREACHABLE(); | 2540 UNREACHABLE(); |
| 2506 break; | 2541 break; |
| 2507 } | 2542 } |
| 2508 default: | 2543 default: |
| 2509 UNREACHABLE(); | 2544 UNREACHABLE(); |
| 2510 break; | 2545 break; |
| (...skipping 2067 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4578 compiler->GenerateCall(token_pos(), | 4613 compiler->GenerateCall(token_pos(), |
| 4579 &label, | 4614 &label, |
| 4580 PcDescriptors::kOther, | 4615 PcDescriptors::kOther, |
| 4581 locs()); | 4616 locs()); |
| 4582 __ Drop(2); // Discard type arguments and receiver. | 4617 __ Drop(2); // Discard type arguments and receiver. |
| 4583 } | 4618 } |
| 4584 | 4619 |
| 4585 } // namespace dart | 4620 } // namespace dart |
| 4586 | 4621 |
| 4587 #endif // defined TARGET_ARCH_ARM | 4622 #endif // defined TARGET_ARCH_ARM |
| OLD | NEW |