Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(349)

Side by Side Diff: runtime/vm/intermediate_language_arm.cc

Issue 1043943002: A few fixes for ARMv5TE. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 5 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « runtime/vm/flow_graph_optimizer.cc ('k') | runtime/vm/intrinsifier_arm.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 3036 matching lines...) Expand 10 before | Expand all | Expand 10 after
3047 if (RightIsPowerOfTwoConstant()) { 3047 if (RightIsPowerOfTwoConstant()) {
3048 num_temps = 1; 3048 num_temps = 1;
3049 } else { 3049 } else {
3050 num_temps = 2; 3050 num_temps = 2;
3051 } 3051 }
3052 } else if (op_kind() == Token::kMOD) { 3052 } else if (op_kind() == Token::kMOD) {
3053 num_temps = 2; 3053 num_temps = 2;
3054 } else if (((op_kind() == Token::kSHL) && can_overflow()) || 3054 } else if (((op_kind() == Token::kSHL) && can_overflow()) ||
3055 (op_kind() == Token::kSHR)) { 3055 (op_kind() == Token::kSHR)) {
3056 num_temps = 1; 3056 num_temps = 1;
3057 } else if ((op_kind() == Token::kMUL) &&
3058 (TargetCPUFeatures::arm_version() != ARMv7)) {
3059 num_temps = 1;
3060 } 3057 }
3061 LocationSummary* summary = new(zone) LocationSummary( 3058 LocationSummary* summary = new(zone) LocationSummary(
3062 zone, kNumInputs, num_temps, LocationSummary::kNoCall); 3059 zone, kNumInputs, num_temps, LocationSummary::kNoCall);
3063 if (op_kind() == Token::kTRUNCDIV) { 3060 if (op_kind() == Token::kTRUNCDIV) {
3064 summary->set_in(0, Location::RequiresRegister()); 3061 summary->set_in(0, Location::RequiresRegister());
3065 if (RightIsPowerOfTwoConstant()) { 3062 if (RightIsPowerOfTwoConstant()) {
3066 ConstantInstr* right_constant = right()->definition()->AsConstant(); 3063 ConstantInstr* right_constant = right()->definition()->AsConstant();
3067 summary->set_in(1, Location::Constant(right_constant)); 3064 summary->set_in(1, Location::Constant(right_constant));
3068 summary->set_temp(0, Location::RequiresRegister()); 3065 summary->set_temp(0, Location::RequiresRegister());
3069 } else { 3066 } else {
(...skipping 11 matching lines...) Expand all
3081 summary->set_temp(1, Location::RequiresFpuRegister()); 3078 summary->set_temp(1, Location::RequiresFpuRegister());
3082 summary->set_out(0, Location::RequiresRegister()); 3079 summary->set_out(0, Location::RequiresRegister());
3083 return summary; 3080 return summary;
3084 } 3081 }
3085 summary->set_in(0, Location::RequiresRegister()); 3082 summary->set_in(0, Location::RequiresRegister());
3086 summary->set_in(1, Location::RegisterOrSmiConstant(right())); 3083 summary->set_in(1, Location::RegisterOrSmiConstant(right()));
3087 if (((op_kind() == Token::kSHL) && can_overflow()) || 3084 if (((op_kind() == Token::kSHL) && can_overflow()) ||
3088 (op_kind() == Token::kSHR)) { 3085 (op_kind() == Token::kSHR)) {
3089 summary->set_temp(0, Location::RequiresRegister()); 3086 summary->set_temp(0, Location::RequiresRegister());
3090 } 3087 }
3091 if (op_kind() == Token::kMUL) {
3092 if (TargetCPUFeatures::arm_version() != ARMv7) {
3093 summary->set_temp(0, Location::RequiresFpuRegister());
3094 }
3095 }
3096 // We make use of 3-operand instructions by not requiring result register 3088 // We make use of 3-operand instructions by not requiring result register
3097 // to be identical to first input register as on Intel. 3089 // to be identical to first input register as on Intel.
3098 summary->set_out(0, Location::RequiresRegister()); 3090 summary->set_out(0, Location::RequiresRegister());
3099 return summary; 3091 return summary;
3100 } 3092 }
3101 3093
3102 3094
3103 void BinarySmiOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 3095 void BinarySmiOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
3104 if (op_kind() == Token::kSHL) { 3096 if (op_kind() == Token::kSHL) {
3105 EmitSmiShiftLeft(compiler, this); 3097 EmitSmiShiftLeft(compiler, this);
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
3138 } 3130 }
3139 break; 3131 break;
3140 } 3132 }
3141 case Token::kMUL: { 3133 case Token::kMUL: {
3142 // Keep left value tagged and untag right value. 3134 // Keep left value tagged and untag right value.
3143 const intptr_t value = Smi::Cast(constant).Value(); 3135 const intptr_t value = Smi::Cast(constant).Value();
3144 if (deopt == NULL) { 3136 if (deopt == NULL) {
3145 __ LoadImmediate(IP, value); 3137 __ LoadImmediate(IP, value);
3146 __ mul(result, left, IP); 3138 __ mul(result, left, IP);
3147 } else { 3139 } else {
3148 if (TargetCPUFeatures::arm_version() == ARMv7) { 3140 __ LoadImmediate(IP, value);
3149 __ LoadImmediate(IP, value); 3141 __ smull(result, IP, left, IP);
3150 __ smull(result, IP, left, IP); 3142 // IP: result bits 32..63.
3151 // IP: result bits 32..63. 3143 __ cmp(IP, Operand(result, ASR, 31));
3152 __ cmp(IP, Operand(result, ASR, 31)); 3144 __ b(deopt, NE);
3153 __ b(deopt, NE);
3154 } else if (TargetCPUFeatures::can_divide()) {
3155 const QRegister qtmp = locs()->temp(0).fpu_reg();
3156 const DRegister dtmp0 = EvenDRegisterOf(qtmp);
3157 const DRegister dtmp1 = OddDRegisterOf(qtmp);
3158 __ LoadImmediate(IP, value);
3159 __ CheckMultSignedOverflow(left, IP, result, dtmp0, dtmp1, deopt);
3160 __ mul(result, left, IP);
3161 } else {
3162 // TODO(vegorov): never emit this instruction if hardware does not
3163 // support it! This will lead to deopt cycle penalizing the code.
3164 __ b(deopt);
3165 }
3166 } 3145 }
3167 break; 3146 break;
3168 } 3147 }
3169 case Token::kTRUNCDIV: { 3148 case Token::kTRUNCDIV: {
3170 const intptr_t value = Smi::Cast(constant).Value(); 3149 const intptr_t value = Smi::Cast(constant).Value();
3171 ASSERT(Utils::IsPowerOfTwo(Utils::Abs(value))); 3150 ASSERT(Utils::IsPowerOfTwo(Utils::Abs(value)));
3172 const intptr_t shift_count = 3151 const intptr_t shift_count =
3173 Utils::ShiftForPowerOfTwo(Utils::Abs(value)) + kSmiTagSize; 3152 Utils::ShiftForPowerOfTwo(Utils::Abs(value)) + kSmiTagSize;
3174 ASSERT(kSmiTagSize == 1); 3153 ASSERT(kSmiTagSize == 1);
3175 __ mov(IP, Operand(left, ASR, 31)); 3154 __ mov(IP, Operand(left, ASR, 31));
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after
3255 __ subs(result, left, Operand(right)); 3234 __ subs(result, left, Operand(right));
3256 __ b(deopt, VS); 3235 __ b(deopt, VS);
3257 } 3236 }
3258 break; 3237 break;
3259 } 3238 }
3260 case Token::kMUL: { 3239 case Token::kMUL: {
3261 __ SmiUntag(IP, left); 3240 __ SmiUntag(IP, left);
3262 if (deopt == NULL) { 3241 if (deopt == NULL) {
3263 __ mul(result, IP, right); 3242 __ mul(result, IP, right);
3264 } else { 3243 } else {
3265 if (TargetCPUFeatures::arm_version() == ARMv7) { 3244 __ smull(result, IP, IP, right);
3266 __ smull(result, IP, IP, right); 3245 // IP: result bits 32..63.
3267 // IP: result bits 32..63. 3246 __ cmp(IP, Operand(result, ASR, 31));
3268 __ cmp(IP, Operand(result, ASR, 31)); 3247 __ b(deopt, NE);
3269 __ b(deopt, NE);
3270 } else if (TargetCPUFeatures::can_divide()) {
3271 const QRegister qtmp = locs()->temp(0).fpu_reg();
3272 const DRegister dtmp0 = EvenDRegisterOf(qtmp);
3273 const DRegister dtmp1 = OddDRegisterOf(qtmp);
3274 __ CheckMultSignedOverflow(IP, right, result, dtmp0, dtmp1, deopt);
3275 __ mul(result, IP, right);
3276 } else {
3277 // TODO(vegorov): never emit this instruction if hardware does not
3278 // support it! This will lead to deopt cycle penalizing the code.
3279 __ b(deopt);
3280 }
3281 } 3248 }
3282 break; 3249 break;
3283 } 3250 }
3284 case Token::kBIT_AND: { 3251 case Token::kBIT_AND: {
3285 // No overflow check. 3252 // No overflow check.
3286 __ and_(result, left, Operand(right)); 3253 __ and_(result, left, Operand(right));
3287 break; 3254 break;
3288 } 3255 }
3289 case Token::kBIT_OR: { 3256 case Token::kBIT_OR: {
3290 // No overflow check. 3257 // No overflow check.
3291 __ orr(result, left, Operand(right)); 3258 __ orr(result, left, Operand(right));
3292 break; 3259 break;
3293 } 3260 }
3294 case Token::kBIT_XOR: { 3261 case Token::kBIT_XOR: {
3295 // No overflow check. 3262 // No overflow check.
3296 __ eor(result, left, Operand(right)); 3263 __ eor(result, left, Operand(right));
3297 break; 3264 break;
3298 } 3265 }
3299 case Token::kTRUNCDIV: { 3266 case Token::kTRUNCDIV: {
3267 ASSERT(TargetCPUFeatures::can_divide());
3300 if ((right_range == NULL) || right_range->Overlaps(0, 0)) { 3268 if ((right_range == NULL) || right_range->Overlaps(0, 0)) {
3301 // Handle divide by zero in runtime. 3269 // Handle divide by zero in runtime.
3302 __ cmp(right, Operand(0)); 3270 __ cmp(right, Operand(0));
3303 __ b(deopt, EQ); 3271 __ b(deopt, EQ);
3304 } 3272 }
3305 const Register temp = locs()->temp(0).reg(); 3273 const Register temp = locs()->temp(0).reg();
3306 if (TargetCPUFeatures::can_divide()) { 3274 const DRegister dtemp = EvenDRegisterOf(locs()->temp(1).fpu_reg());
3307 const DRegister dtemp = EvenDRegisterOf(locs()->temp(1).fpu_reg()); 3275 __ SmiUntag(temp, left);
3308 __ SmiUntag(temp, left); 3276 __ SmiUntag(IP, right);
3309 __ SmiUntag(IP, right); 3277 __ IntegerDivide(result, temp, IP, dtemp, DTMP);
3310 __ IntegerDivide(result, temp, IP, dtemp, DTMP);
3311 } else {
3312 // TODO(vegorov): never emit this instruction if hardware does not
3313 // support it! This will lead to deopt cycle penalizing the code.
3314 __ b(deopt);
3315 }
3316 3278
3317 // Check the corner case of dividing the 'MIN_SMI' with -1, in which 3279 // Check the corner case of dividing the 'MIN_SMI' with -1, in which
3318 // case we cannot tag the result. 3280 // case we cannot tag the result.
3319 __ CompareImmediate(result, 0x40000000); 3281 __ CompareImmediate(result, 0x40000000);
3320 __ b(deopt, EQ); 3282 __ b(deopt, EQ);
3321 __ SmiTag(result); 3283 __ SmiTag(result);
3322 break; 3284 break;
3323 } 3285 }
3324 case Token::kMOD: { 3286 case Token::kMOD: {
3287 ASSERT(TargetCPUFeatures::can_divide());
3325 if ((right_range == NULL) || right_range->Overlaps(0, 0)) { 3288 if ((right_range == NULL) || right_range->Overlaps(0, 0)) {
3326 // Handle divide by zero in runtime. 3289 // Handle divide by zero in runtime.
3327 __ cmp(right, Operand(0)); 3290 __ cmp(right, Operand(0));
3328 __ b(deopt, EQ); 3291 __ b(deopt, EQ);
3329 } 3292 }
3330 const Register temp = locs()->temp(0).reg(); 3293 const Register temp = locs()->temp(0).reg();
3331 if (TargetCPUFeatures::can_divide()) { 3294 const DRegister dtemp = EvenDRegisterOf(locs()->temp(1).fpu_reg());
3332 const DRegister dtemp = EvenDRegisterOf(locs()->temp(1).fpu_reg()); 3295 __ SmiUntag(temp, left);
3333 __ SmiUntag(temp, left); 3296 __ SmiUntag(IP, right);
3334 __ SmiUntag(IP, right); 3297 __ IntegerDivide(result, temp, IP, dtemp, DTMP);
3335 __ IntegerDivide(result, temp, IP, dtemp, DTMP);
3336 } else {
3337 // TODO(vegorov): never emit this instruction if hardware does not
3338 // support it! This will lead to deopt cycle penalizing the code.
3339 __ b(deopt);
3340 }
3341 __ SmiUntag(IP, right); 3298 __ SmiUntag(IP, right);
3342 __ mls(result, IP, result, temp); // result <- left - right * result 3299 __ mls(result, IP, result, temp); // result <- left - right * result
3343 __ SmiTag(result); 3300 __ SmiTag(result);
3344 // res = left % right; 3301 // res = left % right;
3345 // if (res < 0) { 3302 // if (res < 0) {
3346 // if (right < 0) { 3303 // if (right < 0) {
3347 // res = res - right; 3304 // res = res - right;
3348 // } else { 3305 // } else {
3349 // res = res + right; 3306 // res = res + right;
3350 // } 3307 // }
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after
3425 3382
3426 3383
3427 LocationSummary* BinaryInt32OpInstr::MakeLocationSummary(Zone* zone, 3384 LocationSummary* BinaryInt32OpInstr::MakeLocationSummary(Zone* zone,
3428 bool opt) const { 3385 bool opt) const {
3429 const intptr_t kNumInputs = 2; 3386 const intptr_t kNumInputs = 2;
3430 // Calculate number of temporaries. 3387 // Calculate number of temporaries.
3431 intptr_t num_temps = 0; 3388 intptr_t num_temps = 0;
3432 if (((op_kind() == Token::kSHL) && can_overflow()) || 3389 if (((op_kind() == Token::kSHL) && can_overflow()) ||
3433 (op_kind() == Token::kSHR)) { 3390 (op_kind() == Token::kSHR)) {
3434 num_temps = 1; 3391 num_temps = 1;
3435 } else if ((op_kind() == Token::kMUL) &&
3436 (TargetCPUFeatures::arm_version() != ARMv7)) {
3437 num_temps = 1;
3438 } 3392 }
3439 LocationSummary* summary = new(zone) LocationSummary( 3393 LocationSummary* summary = new(zone) LocationSummary(
3440 zone, kNumInputs, num_temps, LocationSummary::kNoCall); 3394 zone, kNumInputs, num_temps, LocationSummary::kNoCall);
3441 summary->set_in(0, Location::RequiresRegister()); 3395 summary->set_in(0, Location::RequiresRegister());
3442 summary->set_in(1, Location::RegisterOrSmiConstant(right())); 3396 summary->set_in(1, Location::RegisterOrSmiConstant(right()));
3443 if (((op_kind() == Token::kSHL) && can_overflow()) || 3397 if (((op_kind() == Token::kSHL) && can_overflow()) ||
3444 (op_kind() == Token::kSHR)) { 3398 (op_kind() == Token::kSHR)) {
3445 summary->set_temp(0, Location::RequiresRegister()); 3399 summary->set_temp(0, Location::RequiresRegister());
3446 } 3400 }
3447 if (op_kind() == Token::kMUL) {
3448 if (TargetCPUFeatures::arm_version() != ARMv7) {
3449 summary->set_temp(0, Location::RequiresFpuRegister());
3450 }
3451 }
3452 // We make use of 3-operand instructions by not requiring result register 3401 // We make use of 3-operand instructions by not requiring result register
3453 // to be identical to first input register as on Intel. 3402 // to be identical to first input register as on Intel.
3454 summary->set_out(0, Location::RequiresRegister()); 3403 summary->set_out(0, Location::RequiresRegister());
3455 return summary; 3404 return summary;
3456 } 3405 }
3457 3406
3458 3407
3459 void BinaryInt32OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 3408 void BinaryInt32OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
3460 if (op_kind() == Token::kSHL) { 3409 if (op_kind() == Token::kSHL) {
3461 EmitInt32ShiftLeft(compiler, this); 3410 EmitInt32ShiftLeft(compiler, this);
(...skipping 30 matching lines...) Expand all
3492 __ SubImmediateSetFlags(result, left, value); 3441 __ SubImmediateSetFlags(result, left, value);
3493 __ b(deopt, VS); 3442 __ b(deopt, VS);
3494 } 3443 }
3495 break; 3444 break;
3496 } 3445 }
3497 case Token::kMUL: { 3446 case Token::kMUL: {
3498 if (deopt == NULL) { 3447 if (deopt == NULL) {
3499 __ LoadImmediate(IP, value); 3448 __ LoadImmediate(IP, value);
3500 __ mul(result, left, IP); 3449 __ mul(result, left, IP);
3501 } else { 3450 } else {
3502 if (TargetCPUFeatures::arm_version() == ARMv7) { 3451 __ LoadImmediate(IP, value);
3503 __ LoadImmediate(IP, value); 3452 __ smull(result, IP, left, IP);
3504 __ smull(result, IP, left, IP); 3453 // IP: result bits 32..63.
3505 // IP: result bits 32..63. 3454 __ cmp(IP, Operand(result, ASR, 31));
3506 __ cmp(IP, Operand(result, ASR, 31)); 3455 __ b(deopt, NE);
3507 __ b(deopt, NE);
3508 } else if (TargetCPUFeatures::can_divide()) {
3509 const QRegister qtmp = locs()->temp(0).fpu_reg();
3510 const DRegister dtmp0 = EvenDRegisterOf(qtmp);
3511 const DRegister dtmp1 = OddDRegisterOf(qtmp);
3512 __ LoadImmediate(IP, value);
3513 __ CheckMultSignedOverflow(left, IP, result, dtmp0, dtmp1, deopt);
3514 __ mul(result, left, IP);
3515 } else {
3516 // TODO(vegorov): never emit this instruction if hardware does not
3517 // support it! This will lead to deopt cycle penalizing the code.
3518 __ b(deopt);
3519 }
3520 } 3456 }
3521 break; 3457 break;
3522 } 3458 }
3523 case Token::kBIT_AND: { 3459 case Token::kBIT_AND: {
3524 // No overflow check. 3460 // No overflow check.
3525 Operand o; 3461 Operand o;
3526 if (Operand::CanHold(value, &o)) { 3462 if (Operand::CanHold(value, &o)) {
3527 __ and_(result, left, o); 3463 __ and_(result, left, o);
3528 } else if (Operand::CanHold(~value, &o)) { 3464 } else if (Operand::CanHold(~value, &o)) {
3529 __ bic(result, left, o); 3465 __ bic(result, left, o);
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
3586 } else { 3522 } else {
3587 __ subs(result, left, Operand(right)); 3523 __ subs(result, left, Operand(right));
3588 __ b(deopt, VS); 3524 __ b(deopt, VS);
3589 } 3525 }
3590 break; 3526 break;
3591 } 3527 }
3592 case Token::kMUL: { 3528 case Token::kMUL: {
3593 if (deopt == NULL) { 3529 if (deopt == NULL) {
3594 __ mul(result, left, right); 3530 __ mul(result, left, right);
3595 } else { 3531 } else {
3596 if (TargetCPUFeatures::arm_version() == ARMv7) { 3532 __ smull(result, IP, left, right);
3597 __ smull(result, IP, left, right); 3533 // IP: result bits 32..63.
3598 // IP: result bits 32..63. 3534 __ cmp(IP, Operand(result, ASR, 31));
3599 __ cmp(IP, Operand(result, ASR, 31)); 3535 __ b(deopt, NE);
3600 __ b(deopt, NE);
3601 } else if (TargetCPUFeatures::can_divide()) {
3602 const QRegister qtmp = locs()->temp(0).fpu_reg();
3603 const DRegister dtmp0 = EvenDRegisterOf(qtmp);
3604 const DRegister dtmp1 = OddDRegisterOf(qtmp);
3605 __ CheckMultSignedOverflow(left, right, result, dtmp0, dtmp1, deopt);
3606 __ mul(result, left, right);
3607 } else {
3608 // TODO(vegorov): never emit this instruction if hardware does not
3609 // support it! This will lead to deopt cycle penalizing the code.
3610 __ b(deopt);
3611 }
3612 } 3536 }
3613 break; 3537 break;
3614 } 3538 }
3615 case Token::kBIT_AND: { 3539 case Token::kBIT_AND: {
3616 // No overflow check. 3540 // No overflow check.
3617 __ and_(result, left, Operand(right)); 3541 __ and_(result, left, Operand(right));
3618 break; 3542 break;
3619 } 3543 }
3620 case Token::kBIT_OR: { 3544 case Token::kBIT_OR: {
3621 // No overflow check. 3545 // No overflow check.
(...skipping 2251 matching lines...) Expand 10 before | Expand all | Expand 10 after
5873 return NULL; 5797 return NULL;
5874 } 5798 }
5875 5799
5876 5800
5877 void MergedMathInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 5801 void MergedMathInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
5878 Label* deopt = NULL; 5802 Label* deopt = NULL;
5879 if (CanDeoptimize()) { 5803 if (CanDeoptimize()) {
5880 deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinarySmiOp); 5804 deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinarySmiOp);
5881 } 5805 }
5882 if (kind() == MergedMathInstr::kTruncDivMod) { 5806 if (kind() == MergedMathInstr::kTruncDivMod) {
5807 ASSERT(TargetCPUFeatures::can_divide());
5883 const Register left = locs()->in(0).reg(); 5808 const Register left = locs()->in(0).reg();
5884 const Register right = locs()->in(1).reg(); 5809 const Register right = locs()->in(1).reg();
5885 ASSERT(locs()->out(0).IsPairLocation()); 5810 ASSERT(locs()->out(0).IsPairLocation());
5886 PairLocation* pair = locs()->out(0).AsPairLocation(); 5811 PairLocation* pair = locs()->out(0).AsPairLocation();
5887 const Register result_div = pair->At(0).reg(); 5812 const Register result_div = pair->At(0).reg();
5888 const Register result_mod = pair->At(1).reg(); 5813 const Register result_mod = pair->At(1).reg();
5889 Range* right_range = InputAt(1)->definition()->range(); 5814 Range* right_range = InputAt(1)->definition()->range();
5890 if ((right_range == NULL) || right_range->Overlaps(0, 0)) { 5815 if ((right_range == NULL) || right_range->Overlaps(0, 0)) {
5891 // Handle divide by zero in runtime. 5816 // Handle divide by zero in runtime.
5892 __ cmp(right, Operand(0)); 5817 __ cmp(right, Operand(0));
5893 __ b(deopt, EQ); 5818 __ b(deopt, EQ);
5894 } 5819 }
5895 const Register temp = locs()->temp(0).reg(); 5820 const Register temp = locs()->temp(0).reg();
5896 if (TargetCPUFeatures::can_divide()) { 5821 const DRegister dtemp = EvenDRegisterOf(locs()->temp(1).fpu_reg());
5897 const DRegister dtemp = EvenDRegisterOf(locs()->temp(1).fpu_reg()); 5822 __ SmiUntag(temp, left);
5898 __ SmiUntag(temp, left); 5823 __ SmiUntag(IP, right);
5899 __ SmiUntag(IP, right); 5824 __ IntegerDivide(result_div, temp, IP, dtemp, DTMP);
5900 __ IntegerDivide(result_div, temp, IP, dtemp, DTMP);
5901 } else {
5902 // TODO(vegorov): never emit this instruction if hardware does not
5903 // support it! This will lead to deopt cycle penalizing the code.
5904 __ b(deopt);
5905 }
5906 5825
5907 // Check the corner case of dividing the 'MIN_SMI' with -1, in which 5826 // Check the corner case of dividing the 'MIN_SMI' with -1, in which
5908 // case we cannot tag the result. 5827 // case we cannot tag the result.
5909 __ CompareImmediate(result_div, 0x40000000); 5828 __ CompareImmediate(result_div, 0x40000000);
5910 __ b(deopt, EQ); 5829 __ b(deopt, EQ);
5911 __ SmiUntag(IP, right); 5830 __ SmiUntag(IP, right);
5912 // result_mod <- left - right * result_div. 5831 // result_mod <- left - right * result_div.
5913 __ mls(result_mod, IP, result_div, temp); 5832 __ mls(result_mod, IP, result_div, temp);
5914 __ SmiTag(result_div); 5833 __ SmiTag(result_div);
5915 __ SmiTag(result_mod); 5834 __ SmiTag(result_mod);
(...skipping 338 matching lines...) Expand 10 before | Expand all | Expand 10 after
6254 // Deopt on overflow. 6173 // Deopt on overflow.
6255 __ b(deopt, VS); 6174 __ b(deopt, VS);
6256 } 6175 }
6257 break; 6176 break;
6258 } 6177 }
6259 case Token::kMUL: { 6178 case Token::kMUL: {
6260 // The product of two signed 32-bit integers fits in a signed 64-bit 6179 // The product of two signed 32-bit integers fits in a signed 64-bit
6261 // result without causing overflow. 6180 // result without causing overflow.
6262 // We deopt on larger inputs. 6181 // We deopt on larger inputs.
6263 // TODO(regis): Range analysis may eliminate the deopt check. 6182 // TODO(regis): Range analysis may eliminate the deopt check.
6264 if (TargetCPUFeatures::arm_version() == ARMv7) { 6183 __ cmp(left_hi, Operand(left_lo, ASR, 31));
6265 __ cmp(left_hi, Operand(left_lo, ASR, 31)); 6184 __ cmp(right_hi, Operand(right_lo, ASR, 31), EQ);
6266 __ cmp(right_hi, Operand(right_lo, ASR, 31), EQ); 6185 __ b(deopt, NE);
6267 __ b(deopt, NE); 6186 __ smull(out_lo, out_hi, left_lo, right_lo);
6268 __ smull(out_lo, out_hi, left_lo, right_lo);
6269 } else {
6270 // TODO(vegorov): never emit this instruction if hardware does not
6271 // support it! This will lead to deopt cycle penalizing the code.
6272 __ b(deopt);
6273 }
6274 break; 6187 break;
6275 } 6188 }
6276 default: 6189 default:
6277 UNREACHABLE(); 6190 UNREACHABLE();
6278 } 6191 }
6279 if (FLAG_throw_on_javascript_int_overflow) { 6192 if (FLAG_throw_on_javascript_int_overflow) {
6280 EmitJavascriptIntOverflowCheck(compiler, deopt, out_lo, out_hi); 6193 EmitJavascriptIntOverflowCheck(compiler, deopt, out_lo, out_hi);
6281 } 6194 }
6282 } 6195 }
6283 6196
(...skipping 681 matching lines...) Expand 10 before | Expand all | Expand 10 after
6965 1, 6878 1,
6966 locs()); 6879 locs());
6967 __ Drop(1); 6880 __ Drop(1);
6968 __ Pop(result); 6881 __ Pop(result);
6969 } 6882 }
6970 6883
6971 6884
6972 } // namespace dart 6885 } // namespace dart
6973 6886
6974 #endif // defined TARGET_ARCH_ARM 6887 #endif // defined TARGET_ARCH_ARM
OLDNEW
« no previous file with comments | « runtime/vm/flow_graph_optimizer.cc ('k') | runtime/vm/intrinsifier_arm.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698