OLD | NEW |
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, 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_IA32. | 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_IA32. |
6 #if defined(TARGET_ARCH_IA32) | 6 #if defined(TARGET_ARCH_IA32) |
7 | 7 |
8 #include "vm/intermediate_language.h" | 8 #include "vm/intermediate_language.h" |
9 | 9 |
10 #include "lib/error.h" | 10 #include "lib/error.h" |
(...skipping 2377 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2388 __ Bind(&done); | 2388 __ Bind(&done); |
2389 break; | 2389 break; |
2390 } | 2390 } |
2391 default: UNREACHABLE(); | 2391 default: UNREACHABLE(); |
2392 } | 2392 } |
2393 } | 2393 } |
2394 | 2394 |
2395 | 2395 |
2396 LocationSummary* ShiftMintOpInstr::MakeLocationSummary() const { | 2396 LocationSummary* ShiftMintOpInstr::MakeLocationSummary() const { |
2397 const intptr_t kNumInputs = 2; | 2397 const intptr_t kNumInputs = 2; |
2398 const intptr_t kNumTemps = 1; | 2398 const intptr_t kNumTemps = op_kind() == Token::kSHL ? 2 : 1; |
2399 LocationSummary* summary = | 2399 LocationSummary* summary = |
2400 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 2400 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
2401 summary->set_in(0, Location::RequiresXmmRegister()); | 2401 summary->set_in(0, Location::RequiresXmmRegister()); |
2402 summary->set_in(1, Location::RegisterLocation(ECX)); | 2402 summary->set_in(1, Location::RegisterLocation(ECX)); |
2403 summary->set_temp(0, Location::RequiresRegister()); | 2403 summary->set_temp(0, Location::RequiresRegister()); |
| 2404 if (op_kind() == Token::kSHL) { |
| 2405 summary->set_temp(1, Location::RequiresRegister()); |
| 2406 } |
2404 summary->set_out(Location::SameAsFirstInput()); | 2407 summary->set_out(Location::SameAsFirstInput()); |
2405 return summary; | 2408 return summary; |
2406 } | 2409 } |
2407 | 2410 |
2408 | 2411 |
2409 void ShiftMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2412 void ShiftMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
2410 XmmRegister left = locs()->in(0).xmm_reg(); | 2413 XmmRegister left = locs()->in(0).xmm_reg(); |
2411 Register temp = locs()->temp(0).reg(); | |
2412 ASSERT(locs()->in(1).reg() == ECX); | 2414 ASSERT(locs()->in(1).reg() == ECX); |
2413 ASSERT(locs()->out().xmm_reg() == left); | 2415 ASSERT(locs()->out().xmm_reg() == left); |
2414 | 2416 |
| 2417 Label* deopt = compiler->AddDeoptStub(deopt_id(), |
| 2418 kDeoptShiftMintOp); |
| 2419 Label done; |
| 2420 __ testl(ECX, ECX); |
| 2421 __ j(ZERO, &done); // Shift by 0 is a nop. |
| 2422 __ subl(ESP, Immediate(2 * kWordSize)); |
| 2423 __ movq(Address(ESP, 0), left); |
| 2424 // Deoptimize if shift count is > 31. |
| 2425 // sarl operation masks the count to 5 bits and |
| 2426 // shrd is undefined with count > operand size (32) |
| 2427 // TODO(fschneider): Support shift counts > 31 without deoptimization. |
| 2428 __ SmiUntag(ECX); |
| 2429 const Immediate kCountLimit = Immediate(31); |
| 2430 __ cmpl(ECX, kCountLimit); |
| 2431 __ j(ABOVE, deopt); |
2415 switch (op_kind()) { | 2432 switch (op_kind()) { |
2416 case Token::kSHR: { | 2433 case Token::kSHR: { |
2417 Label* deopt = compiler->AddDeoptStub(deopt_id(), | 2434 Register temp = locs()->temp(0).reg(); |
2418 kDeoptShiftMintOp); | 2435 __ movl(temp, Address(ESP, 1 * kWordSize)); // High half. |
2419 __ subl(ESP, Immediate(2 * kWordSize)); | |
2420 __ movq(Address(ESP, 0), left); | |
2421 // Deoptimize if shift count is > 31. | |
2422 // sarl operation masks the count to 5 bits and | |
2423 // shrd is undefined with count > operand size (32) | |
2424 // TODO(fschneider): Support shift counts > 31 without deoptimization. | |
2425 __ SmiUntag(ECX); | |
2426 const Immediate kCountLimit = Immediate(31); | |
2427 __ cmpl(ECX, kCountLimit); | |
2428 __ j(ABOVE, deopt); | |
2429 __ movl(temp, Address(ESP, 1 * kWordSize)); | |
2430 __ shrd(Address(ESP, 0), temp); // Shift count in CL. | 2436 __ shrd(Address(ESP, 0), temp); // Shift count in CL. |
2431 __ sarl(Address(ESP, 1 * kWordSize), ECX); // Shift count in CL. | 2437 __ sarl(Address(ESP, 1 * kWordSize), ECX); // Shift count in CL. |
2432 __ movq(left, Address(ESP, 0)); | |
2433 __ addl(ESP, Immediate(2 * kWordSize)); | |
2434 break; | 2438 break; |
2435 } | 2439 } |
2436 case Token::kSHL: | 2440 case Token::kSHL: { |
2437 UNIMPLEMENTED(); | 2441 Register temp1 = locs()->temp(0).reg(); |
| 2442 Register temp2 = locs()->temp(1).reg(); |
| 2443 __ movl(temp1, Address(ESP, 0 * kWordSize)); // Low 32 bits. |
| 2444 __ movl(temp2, Address(ESP, 1 * kWordSize)); // High 32 bits. |
| 2445 __ shll(Address(ESP, 0 * kWordSize), ECX); // Shift count in CL. |
| 2446 __ shld(Address(ESP, 1 * kWordSize), temp1); // Shift count in CL. |
| 2447 // Check for overflow by shifting back the high 32 bits |
| 2448 // and comparing with the input. |
| 2449 __ movl(temp1, temp2); |
| 2450 __ movl(temp2, Address(ESP, 1 * kWordSize)); |
| 2451 __ sarl(temp2, ECX); |
| 2452 __ cmpl(temp1, temp2); |
| 2453 __ j(NOT_EQUAL, deopt); |
2438 break; | 2454 break; |
| 2455 } |
2439 default: | 2456 default: |
2440 UNREACHABLE(); | 2457 UNREACHABLE(); |
2441 break; | 2458 break; |
2442 } | 2459 } |
| 2460 __ movq(left, Address(ESP, 0)); |
| 2461 __ addl(ESP, Immediate(2 * kWordSize)); |
| 2462 __ Bind(&done); |
2443 } | 2463 } |
2444 | 2464 |
2445 | 2465 |
2446 LocationSummary* UnaryMintOpInstr::MakeLocationSummary() const { | 2466 LocationSummary* UnaryMintOpInstr::MakeLocationSummary() const { |
2447 const intptr_t kNumInputs = 1; | 2467 const intptr_t kNumInputs = 1; |
2448 const intptr_t kNumTemps = 0; | 2468 const intptr_t kNumTemps = 0; |
2449 LocationSummary* summary = | 2469 LocationSummary* summary = |
2450 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 2470 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
2451 summary->set_in(0, Location::RequiresXmmRegister()); | 2471 summary->set_in(0, Location::RequiresXmmRegister()); |
2452 summary->set_out(Location::SameAsFirstInput()); | 2472 summary->set_out(Location::SameAsFirstInput()); |
2453 return summary; | 2473 return summary; |
2454 } | 2474 } |
2455 | 2475 |
2456 | 2476 |
2457 void UnaryMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2477 void UnaryMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
2458 ASSERT(op_kind() == Token::kBIT_NOT); | 2478 ASSERT(op_kind() == Token::kBIT_NOT); |
2459 XmmRegister value = locs()->in(0).xmm_reg(); | 2479 XmmRegister value = locs()->in(0).xmm_reg(); |
2460 ASSERT(value == locs()->out().xmm_reg()); | 2480 ASSERT(value == locs()->out().xmm_reg()); |
2461 __ pcmpeqq(XMM0, XMM0); // Generate all 1's. | 2481 __ pcmpeqq(XMM0, XMM0); // Generate all 1's. |
2462 __ pxor(value, XMM0); | 2482 __ pxor(value, XMM0); |
2463 } | 2483 } |
2464 | 2484 |
2465 | 2485 |
2466 } // namespace dart | 2486 } // namespace dart |
2467 | 2487 |
2468 #undef __ | 2488 #undef __ |
2469 | 2489 |
2470 #endif // defined TARGET_ARCH_X64 | 2490 #endif // defined TARGET_ARCH_X64 |
OLD | NEW |