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

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

Issue 15899010: Implement a few more features on ARM. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 7 years, 6 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_compiler_arm.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 "lib/error.h" 10 #include "lib/error.h"
(...skipping 1117 matching lines...) Expand 10 before | Expand all | Expand 10 after
1128 UNREACHABLE(); 1128 UNREACHABLE();
1129 } 1129 }
1130 __ AddImmediate(index.reg(), 1130 __ AddImmediate(index.reg(),
1131 FlowGraphCompiler::DataOffsetFor(class_id()) - kHeapObjectTag); 1131 FlowGraphCompiler::DataOffsetFor(class_id()) - kHeapObjectTag);
1132 element_address = Address(array, index.reg(), LSL, 0); 1132 element_address = Address(array, index.reg(), LSL, 0);
1133 } 1133 }
1134 1134
1135 if ((representation() == kUnboxedDouble) || 1135 if ((representation() == kUnboxedDouble) ||
1136 (representation() == kUnboxedMint) || 1136 (representation() == kUnboxedMint) ||
1137 (representation() == kUnboxedFloat32x4)) { 1137 (representation() == kUnboxedFloat32x4)) {
1138 UNIMPLEMENTED(); 1138 DRegister result = locs()->out().fpu_reg();
1139 switch (class_id()) {
1140 case kTypedDataInt32ArrayCid:
1141 UNIMPLEMENTED();
1142 break;
1143 case kTypedDataUint32ArrayCid:
1144 UNIMPLEMENTED();
1145 break;
1146 case kTypedDataFloat32ArrayCid:
1147 // Load single precision float and promote to double.
1148 // vldrs does not support indexed addressing.
1149 __ add(index.reg(), index.reg(), ShifterOperand(array));
1150 element_address = Address(index.reg(), 0);
1151 __ vldrs(S0, element_address);
1152 __ vcvtds(result, S0);
1153 break;
1154 case kTypedDataFloat64ArrayCid:
1155 // vldrd does not support indexed addressing.
1156 __ add(index.reg(), index.reg(), ShifterOperand(array));
1157 element_address = Address(index.reg(), 0);
1158 __ vldrd(result, element_address);
1159 break;
1160 case kTypedDataFloat32x4ArrayCid:
1161 UNIMPLEMENTED();
1162 break;
1163 }
1164 return;
1139 } 1165 }
1140 1166
1141 Register result = locs()->out().reg(); 1167 Register result = locs()->out().reg();
1142 switch (class_id()) { 1168 switch (class_id()) {
1143 case kTypedDataInt8ArrayCid: 1169 case kTypedDataInt8ArrayCid:
1144 ASSERT(index_scale() == 1); 1170 ASSERT(index_scale() == 1);
1145 __ ldrsb(result, element_address); 1171 __ ldrsb(result, element_address);
1146 __ SmiTag(result); 1172 __ SmiTag(result);
1147 break; 1173 break;
1148 case kTypedDataUint8ArrayCid: 1174 case kTypedDataUint8ArrayCid:
(...skipping 900 matching lines...) Expand 10 before | Expand all | Expand 10 after
2049 __ cmp(left, ShifterOperand(IP, ASR, right)); 2075 __ cmp(left, ShifterOperand(IP, ASR, right));
2050 __ b(deopt, NE); // Overflow. 2076 __ b(deopt, NE); // Overflow.
2051 // Shift for result now we know there is no overflow. 2077 // Shift for result now we know there is no overflow.
2052 __ Lsl(result, left, right); 2078 __ Lsl(result, left, right);
2053 } 2079 }
2054 } 2080 }
2055 2081
2056 2082
2057 LocationSummary* BinarySmiOpInstr::MakeLocationSummary() const { 2083 LocationSummary* BinarySmiOpInstr::MakeLocationSummary() const {
2058 const intptr_t kNumInputs = 2; 2084 const intptr_t kNumInputs = 2;
2085 const intptr_t kNumTemps = 0;
2086 LocationSummary* summary =
2087 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
2059 if (op_kind() == Token::kTRUNCDIV) { 2088 if (op_kind() == Token::kTRUNCDIV) {
2060 UNIMPLEMENTED(); 2089 if (RightIsPowerOfTwoConstant()) {
2061 return NULL; 2090 summary->set_in(0, Location::RequiresRegister());
2062 } else { 2091 ConstantInstr* right_constant = right()->definition()->AsConstant();
2063 const intptr_t kNumTemps = 0; 2092 summary->set_in(1, Location::Constant(right_constant->value()));
2064 LocationSummary* summary = 2093 summary->set_out(Location::RequiresRegister());
2065 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); 2094 } else {
2066 summary->set_in(0, Location::RequiresRegister()); 2095 // Both inputs must be writable because they will be untagged.
2067 summary->set_in(1, Location::RegisterOrSmiConstant(right())); 2096 summary->set_in(0, Location::WritableRegister());
2068 // We make use of 3-operand instructions by not requiring result register 2097 summary->set_in(1, Location::WritableRegister());
2069 // to be identical to first input register as on Intel. 2098 summary->set_out(Location::RequiresRegister());
2070 summary->set_out(Location::RequiresRegister()); 2099 }
2071 return summary; 2100 return summary;
2072 } 2101 }
2102 summary->set_in(0, Location::RequiresRegister());
2103 summary->set_in(1, Location::RegisterOrSmiConstant(right()));
2104 // We make use of 3-operand instructions by not requiring result register
2105 // to be identical to first input register as on Intel.
2106 summary->set_out(Location::RequiresRegister());
2107 return summary;
2073 } 2108 }
2074 2109
2075 2110
2076 void BinarySmiOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 2111 void BinarySmiOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
2077 if (op_kind() == Token::kSHL) { 2112 if (op_kind() == Token::kSHL) {
2078 EmitSmiShiftLeft(compiler, this); 2113 EmitSmiShiftLeft(compiler, this);
2079 return; 2114 return;
2080 } 2115 }
2081 2116
2082 ASSERT(!is_truncating()); 2117 ASSERT(!is_truncating());
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
2123 __ LoadImmediate(IP, value); 2158 __ LoadImmediate(IP, value);
2124 __ smull(result, IP, left, IP); 2159 __ smull(result, IP, left, IP);
2125 } 2160 }
2126 // IP: result bits 32..63. 2161 // IP: result bits 32..63.
2127 __ cmp(IP, ShifterOperand(result, ASR, 31)); 2162 __ cmp(IP, ShifterOperand(result, ASR, 31));
2128 __ b(deopt, NE); 2163 __ b(deopt, NE);
2129 } 2164 }
2130 break; 2165 break;
2131 } 2166 }
2132 case Token::kTRUNCDIV: { 2167 case Token::kTRUNCDIV: {
2133 UNIMPLEMENTED(); 2168 const intptr_t value = Smi::Cast(constant).Value();
2169 if (value == 1) {
2170 // Do nothing.
2171 break;
2172 } else if (value == -1) {
2173 // Check the corner case of dividing the 'MIN_SMI' with -1, in which
2174 // case we cannot negate the result.
2175 __ CompareImmediate(left, 0x80000000);
2176 __ b(deopt, EQ);
2177 __ rsb(result, left, ShifterOperand(0));
2178 break;
2179 }
2180 ASSERT((value != 0) && Utils::IsPowerOfTwo(Utils::Abs(value)));
2181 const intptr_t shift_count =
2182 Utils::ShiftForPowerOfTwo(Utils::Abs(value)) + kSmiTagSize;
2183 ASSERT(kSmiTagSize == 1);
2184 __ mov(IP, ShifterOperand(left, ASR, 31));
2185 ASSERT(shift_count > 1); // 1, -1 case handled above.
2186 __ add(left, left, ShifterOperand(IP, LSR, 32 - shift_count));
2187 ASSERT(shift_count > 0);
2188 __ mov(result, ShifterOperand(left, ASR, shift_count));
2189 if (value < 0) {
2190 __ rsb(result, result, ShifterOperand(0));
2191 }
2192 __ SmiTag(result);
2134 break; 2193 break;
2135 } 2194 }
2136 case Token::kBIT_AND: { 2195 case Token::kBIT_AND: {
2137 // No overflow check. 2196 // No overflow check.
2138 ShifterOperand shifter_op; 2197 ShifterOperand shifter_op;
2139 if (ShifterOperand::CanHold(imm, &shifter_op)) { 2198 if (ShifterOperand::CanHold(imm, &shifter_op)) {
2140 __ and_(result, left, shifter_op); 2199 __ and_(result, left, shifter_op);
2141 } else { 2200 } else {
2142 // TODO(regis): Try to use bic. 2201 // TODO(regis): Try to use bic.
2143 __ LoadImmediate(IP, imm); 2202 __ LoadImmediate(IP, imm);
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after
2238 // No overflow check. 2297 // No overflow check.
2239 __ orr(result, left, ShifterOperand(right)); 2298 __ orr(result, left, ShifterOperand(right));
2240 break; 2299 break;
2241 } 2300 }
2242 case Token::kBIT_XOR: { 2301 case Token::kBIT_XOR: {
2243 // No overflow check. 2302 // No overflow check.
2244 __ eor(result, left, ShifterOperand(right)); 2303 __ eor(result, left, ShifterOperand(right));
2245 break; 2304 break;
2246 } 2305 }
2247 case Token::kTRUNCDIV: { 2306 case Token::kTRUNCDIV: {
2248 UNIMPLEMENTED(); 2307 // Handle divide by zero in runtime.
2308 __ cmp(right, ShifterOperand(0));
2309 __ b(deopt, EQ);
2310 __ SmiUntag(left);
2311 __ SmiUntag(right);
2312 if (!CPUFeatures::integer_division_supported()) {
2313 UNIMPLEMENTED();
2314 }
2315 __ sdiv(result, left, right);
2316 // Check the corner case of dividing the 'MIN_SMI' with -1, in which
2317 // case we cannot tag the result.
2318 __ CompareImmediate(result, 0x40000000);
2319 __ b(deopt, EQ);
2320 __ SmiTag(result);
2249 break; 2321 break;
2250 } 2322 }
2251 case Token::kSHR: { 2323 case Token::kSHR: {
2252 UNIMPLEMENTED(); 2324 UNIMPLEMENTED();
2253 break; 2325 break;
2254 } 2326 }
2255 case Token::kDIV: { 2327 case Token::kDIV: {
2256 // Dispatches to 'Double./'. 2328 // Dispatches to 'Double./'.
2257 // TODO(srdjan): Implement as conversion to double and double division. 2329 // TODO(srdjan): Implement as conversion to double and double division.
2258 UNREACHABLE(); 2330 UNREACHABLE();
(...skipping 12 matching lines...) Expand all
2271 break; 2343 break;
2272 } 2344 }
2273 default: 2345 default:
2274 UNREACHABLE(); 2346 UNREACHABLE();
2275 break; 2347 break;
2276 } 2348 }
2277 } 2349 }
2278 2350
2279 2351
2280 LocationSummary* CheckEitherNonSmiInstr::MakeLocationSummary() const { 2352 LocationSummary* CheckEitherNonSmiInstr::MakeLocationSummary() const {
2281 UNIMPLEMENTED(); 2353 intptr_t left_cid = left()->Type()->ToCid();
2282 return NULL; 2354 intptr_t right_cid = right()->Type()->ToCid();
2355 ASSERT((left_cid != kDoubleCid) && (right_cid != kDoubleCid));
2356 const intptr_t kNumInputs = 2;
2357 const intptr_t kNumTemps = 0;
2358 LocationSummary* summary =
2359 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
2360 summary->set_in(0, Location::RequiresRegister());
2361 summary->set_in(1, Location::RequiresRegister());
2362 return summary;
2283 } 2363 }
2284 2364
2285 2365
2286 void CheckEitherNonSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 2366 void CheckEitherNonSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
2287 UNIMPLEMENTED(); 2367 Label* deopt = compiler->AddDeoptStub(deopt_id(), kDeoptBinaryDoubleOp);
2368 intptr_t left_cid = left()->Type()->ToCid();
2369 intptr_t right_cid = right()->Type()->ToCid();
2370 Register left = locs()->in(0).reg();
2371 Register right = locs()->in(1).reg();
2372 if (left_cid == kSmiCid) {
2373 __ tst(right, ShifterOperand(kSmiTagMask));
2374 } else if (right_cid == kSmiCid) {
2375 __ tst(left, ShifterOperand(kSmiTagMask));
2376 } else {
2377 __ orr(IP, left, ShifterOperand(right));
2378 __ tst(IP, ShifterOperand(kSmiTagMask));
2379 }
2380 __ b(deopt, EQ);
2288 } 2381 }
2289 2382
2290 2383
2291 LocationSummary* BoxDoubleInstr::MakeLocationSummary() const { 2384 LocationSummary* BoxDoubleInstr::MakeLocationSummary() const {
2292 UNIMPLEMENTED(); 2385 const intptr_t kNumInputs = 1;
2293 return NULL; 2386 const intptr_t kNumTemps = 0;
2387 LocationSummary* summary =
2388 new LocationSummary(kNumInputs,
2389 kNumTemps,
2390 LocationSummary::kCallOnSlowPath);
2391 summary->set_in(0, Location::RequiresFpuRegister());
2392 summary->set_out(Location::RequiresRegister());
2393 return summary;
2294 } 2394 }
2295 2395
2296 2396
2397 class BoxDoubleSlowPath : public SlowPathCode {
2398 public:
2399 explicit BoxDoubleSlowPath(BoxDoubleInstr* instruction)
2400 : instruction_(instruction) { }
2401
2402 virtual void EmitNativeCode(FlowGraphCompiler* compiler) {
2403 __ Comment("BoxDoubleSlowPath");
2404 __ Bind(entry_label());
2405 const Class& double_class = compiler->double_class();
2406 const Code& stub =
2407 Code::Handle(StubCode::GetAllocationStubForClass(double_class));
2408 const ExternalLabel label(double_class.ToCString(), stub.EntryPoint());
2409
2410 LocationSummary* locs = instruction_->locs();
2411 locs->live_registers()->Remove(locs->out());
2412
2413 compiler->SaveLiveRegisters(locs);
2414 compiler->GenerateCall(Scanner::kDummyTokenIndex, // No token position.
2415 &label,
2416 PcDescriptors::kOther,
2417 locs);
2418 __ MoveRegister(locs->out().reg(), R0);
2419 compiler->RestoreLiveRegisters(locs);
2420
2421 __ b(exit_label());
2422 }
2423
2424 private:
2425 BoxDoubleInstr* instruction_;
2426 };
2427
2428
2297 void BoxDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 2429 void BoxDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
2298 UNIMPLEMENTED(); 2430 BoxDoubleSlowPath* slow_path = new BoxDoubleSlowPath(this);
2431 compiler->AddSlowPathCode(slow_path);
2432
2433 Register out_reg = locs()->out().reg();
2434 DRegister value = locs()->in(0).fpu_reg();
2435
2436 __ TryAllocate(compiler->double_class(),
2437 slow_path->entry_label(),
2438 out_reg);
2439 __ Bind(slow_path->exit_label());
2440 __ StoreDToOffset(value, out_reg, Double::value_offset() - kHeapObjectTag);
2299 } 2441 }
2300 2442
2301 2443
2302 LocationSummary* UnboxDoubleInstr::MakeLocationSummary() const { 2444 LocationSummary* UnboxDoubleInstr::MakeLocationSummary() const {
2303 UNIMPLEMENTED(); 2445 const intptr_t kNumInputs = 1;
2304 return NULL; 2446 const intptr_t value_cid = value()->Type()->ToCid();
2447 const bool needs_temp = ((value_cid != kSmiCid) && (value_cid != kDoubleCid));
2448 const bool needs_writable_input = (value_cid == kSmiCid);
2449 const intptr_t kNumTemps = needs_temp ? 1 : 0;
2450 LocationSummary* summary =
2451 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
2452 summary->set_in(0, needs_writable_input
2453 ? Location::WritableRegister()
2454 : Location::RequiresRegister());
2455 if (needs_temp) summary->set_temp(0, Location::RequiresRegister());
2456 summary->set_out(Location::RequiresFpuRegister());
2457 return summary;
2305 } 2458 }
2306 2459
2307 2460
2308 void UnboxDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 2461 void UnboxDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
2309 UNIMPLEMENTED(); 2462 const intptr_t value_cid = value()->Type()->ToCid();
2463 const Register value = locs()->in(0).reg();
2464 const DRegister result = locs()->out().fpu_reg();
2465
2466 if (value_cid == kDoubleCid) {
2467 __ LoadDFromOffset(result, value, Double::value_offset() - kHeapObjectTag);
2468 } else if (value_cid == kSmiCid) {
2469 __ SmiUntag(value); // Untag input before conversion.
2470 __ vmovsr(S0, value);
2471 __ vcvtdi(result, S0);
2472 } else {
2473 Label* deopt = compiler->AddDeoptStub(deopt_id_, kDeoptBinaryDoubleOp);
2474 Register temp = locs()->temp(0).reg();
2475 Label is_smi, done;
2476 __ tst(value, ShifterOperand(kSmiTagMask));
2477 __ b(&is_smi, EQ);
2478 __ CompareClassId(value, kDoubleCid, temp);
2479 __ b(deopt, NE);
2480 __ LoadDFromOffset(result, value, Double::value_offset() - kHeapObjectTag);
2481 __ b(&done);
2482 __ Bind(&is_smi);
2483 // TODO(regis): Why do we preserve value here but not above?
2484 __ mov(IP, ShifterOperand(value, ASR, 1)); // Copy and untag.
2485 __ vmovsr(S0, IP);
2486 __ vcvtdi(result, S0);
2487 __ Bind(&done);
2488 }
2310 } 2489 }
2311 2490
2312 2491
2313 LocationSummary* BoxFloat32x4Instr::MakeLocationSummary() const { 2492 LocationSummary* BoxFloat32x4Instr::MakeLocationSummary() const {
2314 UNIMPLEMENTED(); 2493 UNIMPLEMENTED();
2315 return NULL; 2494 return NULL;
2316 } 2495 }
2317 2496
2318 2497
2319 void BoxFloat32x4Instr::EmitNativeCode(FlowGraphCompiler* compiler) { 2498 void BoxFloat32x4Instr::EmitNativeCode(FlowGraphCompiler* compiler) {
(...skipping 28 matching lines...) Expand all
2348 return NULL; 2527 return NULL;
2349 } 2528 }
2350 2529
2351 2530
2352 void UnboxUint32x4Instr::EmitNativeCode(FlowGraphCompiler* compiler) { 2531 void UnboxUint32x4Instr::EmitNativeCode(FlowGraphCompiler* compiler) {
2353 UNIMPLEMENTED(); 2532 UNIMPLEMENTED();
2354 } 2533 }
2355 2534
2356 2535
2357 LocationSummary* BinaryDoubleOpInstr::MakeLocationSummary() const { 2536 LocationSummary* BinaryDoubleOpInstr::MakeLocationSummary() const {
2358 UNIMPLEMENTED(); 2537 const intptr_t kNumInputs = 2;
2359 return NULL; 2538 const intptr_t kNumTemps = 0;
2539 LocationSummary* summary =
2540 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
2541 summary->set_in(0, Location::RequiresFpuRegister());
2542 summary->set_in(1, Location::RequiresFpuRegister());
2543 summary->set_out(Location::RequiresFpuRegister());
2544 return summary;
2360 } 2545 }
2361 2546
2362 2547
2363 void BinaryDoubleOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 2548 void BinaryDoubleOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
2364 UNIMPLEMENTED(); 2549 DRegister left = locs()->in(0).fpu_reg();
2550 DRegister right = locs()->in(1).fpu_reg();
2551 DRegister result = locs()->out().fpu_reg();
2552 switch (op_kind()) {
2553 case Token::kADD: __ vaddd(result, left, right); break;
2554 case Token::kSUB: __ vsubd(result, left, right); break;
2555 case Token::kMUL: __ vmuld(result, left, right); break;
2556 case Token::kDIV: __ vdivd(result, left, right); break;
2557 default: UNREACHABLE();
2558 }
2365 } 2559 }
2366 2560
2367 2561
2368 LocationSummary* BinaryFloat32x4OpInstr::MakeLocationSummary() const { 2562 LocationSummary* BinaryFloat32x4OpInstr::MakeLocationSummary() const {
2369 UNIMPLEMENTED(); 2563 UNIMPLEMENTED();
2370 return NULL; 2564 return NULL;
2371 } 2565 }
2372 2566
2373 2567
2374 void BinaryFloat32x4OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 2568 void BinaryFloat32x4OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
(...skipping 203 matching lines...) Expand 10 before | Expand all | Expand 10 after
2578 return NULL; 2772 return NULL;
2579 } 2773 }
2580 2774
2581 2775
2582 void MathSqrtInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 2776 void MathSqrtInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
2583 UNIMPLEMENTED(); 2777 UNIMPLEMENTED();
2584 } 2778 }
2585 2779
2586 2780
2587 LocationSummary* UnarySmiOpInstr::MakeLocationSummary() const { 2781 LocationSummary* UnarySmiOpInstr::MakeLocationSummary() const {
2588 UNIMPLEMENTED(); 2782 const intptr_t kNumInputs = 1;
2589 return NULL; 2783 const intptr_t kNumTemps = 0;
2784 LocationSummary* summary =
2785 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
2786 summary->set_in(0, Location::RequiresRegister());
2787 // We make use of 3-operand instructions by not requiring result register
2788 // to be identical to first input register as on Intel.
2789 summary->set_out(Location::RequiresRegister());
2790 return summary;
2590 } 2791 }
2591 2792
2592 2793
2593 void UnarySmiOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 2794 void UnarySmiOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
2594 UNIMPLEMENTED(); 2795 Register value = locs()->in(0).reg();
2796 Register result = locs()->out().reg();
2797 switch (op_kind()) {
2798 case Token::kNEGATE: {
2799 Label* deopt = compiler->AddDeoptStub(deopt_id(),
2800 kDeoptUnaryOp);
2801 __ rsbs(result, value, ShifterOperand(0));
2802 __ b(deopt, VS);
2803 break;
2804 }
2805 case Token::kBIT_NOT:
2806 __ mvn(result, ShifterOperand(value));
2807 // Remove inverted smi-tag.
2808 __ bic(result, result, ShifterOperand(kSmiTagMask));
2809 break;
2810 default:
2811 UNREACHABLE();
2812 }
2595 } 2813 }
2596 2814
2597 2815
2598 LocationSummary* SmiToDoubleInstr::MakeLocationSummary() const { 2816 LocationSummary* SmiToDoubleInstr::MakeLocationSummary() const {
2599 UNIMPLEMENTED(); 2817 UNIMPLEMENTED();
2600 return NULL; 2818 return NULL;
2601 } 2819 }
2602 2820
2603 2821
2604 void SmiToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 2822 void SmiToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
(...skipping 544 matching lines...) Expand 10 before | Expand all | Expand 10 after
3149 compiler->GenerateCall(token_pos(), 3367 compiler->GenerateCall(token_pos(),
3150 &label, 3368 &label,
3151 PcDescriptors::kOther, 3369 PcDescriptors::kOther,
3152 locs()); 3370 locs());
3153 __ Drop(2); // Discard type arguments and receiver. 3371 __ Drop(2); // Discard type arguments and receiver.
3154 } 3372 }
3155 3373
3156 } // namespace dart 3374 } // namespace dart
3157 3375
3158 #endif // defined TARGET_ARCH_ARM 3376 #endif // defined TARGET_ARCH_ARM
OLDNEW
« no previous file with comments | « runtime/vm/flow_graph_compiler_arm.cc ('k') | runtime/vm/intrinsifier_arm.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698