| 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 "lib/error.h" | 10 #include "lib/error.h" |
| (...skipping 1117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 |
| OLD | NEW |