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

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