Chromium Code Reviews| 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 901 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 |
| OLD | NEW |