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

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

Issue 307523002: Adds more ARM64 SIMD instructions. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 6 years, 7 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/intermediate_language_arm64.cc ('k') | no next file » | 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) 2014, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2014, 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 <math.h> // for isnan. 5 #include <math.h> // for isnan.
6 #include <setjmp.h> 6 #include <setjmp.h>
7 #include <stdlib.h> 7 #include <stdlib.h>
8 8
9 #include "vm/globals.h" 9 #include "vm/globals.h"
10 #if defined(TARGET_ARCH_ARM64) 10 #if defined(TARGET_ARCH_ARM64)
(...skipping 2301 matching lines...) Expand 10 before | Expand all | Expand 10 after
2312 } else { 2312 } else {
2313 // Format(instr, "vsub'vsz 'vd, 'vn, 'vm"); 2313 // Format(instr, "vsub'vsz 'vd, 'vn, 'vm");
2314 res = bit_cast<int32_t, float>(vn_flt - vm_flt); 2314 res = bit_cast<int32_t, float>(vn_flt - vm_flt);
2315 } 2315 }
2316 } else if ((U == 1) && (opcode == 0x1b)) { 2316 } else if ((U == 1) && (opcode == 0x1b)) {
2317 // Format(instr, "vmul'vsz 'vd, 'vn, 'vm"); 2317 // Format(instr, "vmul'vsz 'vd, 'vn, 'vm");
2318 res = bit_cast<int32_t, float>(vn_flt * vm_flt); 2318 res = bit_cast<int32_t, float>(vn_flt * vm_flt);
2319 } else if ((U == 1) && (opcode == 0x1f)) { 2319 } else if ((U == 1) && (opcode == 0x1f)) {
2320 // Format(instr, "vdiv'vsz 'vd, 'vn, 'vm"); 2320 // Format(instr, "vdiv'vsz 'vd, 'vn, 'vm");
2321 res = bit_cast<int32_t, float>(vn_flt / vm_flt); 2321 res = bit_cast<int32_t, float>(vn_flt / vm_flt);
2322 } else if ((U == 0) && (opcode == 0x1c)) {
2323 // Format(instr, "vceq'vsz 'vd, 'vn, 'vm");
2324 res = (vn_flt == vm_flt) ? 0xffffffff : 0;
2325 } else if ((U == 1) && (opcode == 0x1c)) {
2326 if (instr->Bit(23) == 1) {
2327 // Format(instr, "vcgt'vsz 'vd, 'vn, 'vm");
2328 res = (vn_flt > vm_flt) ? 0xffffffff : 0;
2329 } else {
2330 // Format(instr, "vcge'vsz 'vd, 'vn, 'vm");
2331 res = (vn_flt >= vm_flt) ? 0xffffffff : 0;
2332 }
2333 } else if ((U == 0) && (opcode == 0x1e)) {
2334 if (instr->Bit(23) == 1) {
2335 // Format(instr, "vmin'vsz 'vd, 'vn, 'vm");
2336 const float m = (vn_flt > vm_flt) ? vm_flt : vn_flt;
2337 res = bit_cast<int32_t, float>(m);
2338 } else {
2339 // Format(instr, "vmax'vsz 'vd, 'vn, 'vm");
2340 const float m = (vn_flt < vm_flt) ? vm_flt : vn_flt;
2341 res = bit_cast<int32_t, float>(m);
2342 }
2343 } else if ((U == 0) && (opcode == 0x1f)) {
2344 if (instr->Bit(23) == 0) {
2345 // Format(instr, "vrecps'vsz 'vd, 'vn, 'vm");
2346 res = bit_cast<int32_t, float>(2.0 - (vn_flt * vm_flt));
2347 } else {
2348 // Format(instr, "vrsqrt'vsz 'vd, 'vn, 'vm");
2349 res = bit_cast<int32_t, float>((3.0 - vn_flt * vm_flt) / 2.0);
2350 }
2322 } else { 2351 } else {
2323 UnimplementedInstruction(instr); 2352 UnimplementedInstruction(instr);
2324 return; 2353 return;
2325 } 2354 }
2326 set_vregisters(vd, idx, res); 2355 set_vregisters(vd, idx, res);
2327 } 2356 }
2328 } else { 2357 } else {
2329 // f64 case. 2358 // f64 case.
2330 for (int idx = 0; idx < 2; idx++) { 2359 for (int idx = 0; idx < 2; idx++) {
2331 const int64_t vn_val = get_vregisterd(vn, idx); 2360 const int64_t vn_val = get_vregisterd(vn, idx);
(...skipping 25 matching lines...) Expand all
2357 } else { 2386 } else {
2358 // Format(instr, "vsub'vsz 'vd, 'vn, 'vm"); 2387 // Format(instr, "vsub'vsz 'vd, 'vn, 'vm");
2359 res = bit_cast<int64_t, double>(vn_dbl - vm_dbl); 2388 res = bit_cast<int64_t, double>(vn_dbl - vm_dbl);
2360 } 2389 }
2361 } else if ((U == 1) && (opcode == 0x1b)) { 2390 } else if ((U == 1) && (opcode == 0x1b)) {
2362 // Format(instr, "vmul'vsz 'vd, 'vn, 'vm"); 2391 // Format(instr, "vmul'vsz 'vd, 'vn, 'vm");
2363 res = bit_cast<int64_t, double>(vn_dbl * vm_dbl); 2392 res = bit_cast<int64_t, double>(vn_dbl * vm_dbl);
2364 } else if ((U == 1) && (opcode == 0x1f)) { 2393 } else if ((U == 1) && (opcode == 0x1f)) {
2365 // Format(instr, "vdiv'vsz 'vd, 'vn, 'vm"); 2394 // Format(instr, "vdiv'vsz 'vd, 'vn, 'vm");
2366 res = bit_cast<int64_t, double>(vn_dbl / vm_dbl); 2395 res = bit_cast<int64_t, double>(vn_dbl / vm_dbl);
2396 } else if ((U == 0) && (opcode == 0x1c)) {
2397 // Format(instr, "vceq'vsz 'vd, 'vn, 'vm");
2398 res = (vn_dbl == vm_dbl) ? 0xffffffffffffffffLL : 0;
2399 } else if ((U == 1) && (opcode == 0x1c)) {
2400 if (instr->Bit(23) == 1) {
2401 // Format(instr, "vcgt'vsz 'vd, 'vn, 'vm");
2402 res = (vn_dbl > vm_dbl) ? 0xffffffffffffffffLL : 0;
2403 } else {
2404 // Format(instr, "vcge'vsz 'vd, 'vn, 'vm");
2405 res = (vn_dbl >= vm_dbl) ? 0xffffffffffffffffLL : 0;
2406 }
2407 } else if ((U == 0) && (opcode == 0x1e)) {
2408 if (instr->Bit(23) == 1) {
2409 // Format(instr, "vmin'vsz 'vd, 'vn, 'vm");
2410 const double m = (vn_dbl > vm_dbl) ? vm_dbl : vn_dbl;
2411 res = bit_cast<int64_t, double>(m);
2412 } else {
2413 // Format(instr, "vmax'vsz 'vd, 'vn, 'vm");
2414 const double m = (vn_dbl < vm_dbl) ? vm_dbl : vn_dbl;
2415 res = bit_cast<int64_t, double>(m);
2416 }
2367 } else { 2417 } else {
2368 UnimplementedInstruction(instr); 2418 UnimplementedInstruction(instr);
2369 return; 2419 return;
2370 } 2420 }
2371 set_vregisterd(vd, idx, res); 2421 set_vregisterd(vd, idx, res);
2372 } 2422 }
2373 } 2423 }
2374 } 2424 }
2375 2425
2376 2426
2427 static float arm_reciprocal_sqrt_estimate(float a) {
2428 // From the ARM Architecture Reference Manual A2-87.
2429 if (isinf(a) || (fabs(a) >= exp2f(126))) return 0.0;
2430 else if (a == 0.0) return INFINITY;
2431 else if (isnan(a)) return a;
2432
2433 uint32_t a_bits = bit_cast<uint32_t, float>(a);
2434 uint64_t scaled;
2435 if (((a_bits >> 23) & 1) != 0) {
2436 // scaled = '0 01111111101' : operand<22:0> : Zeros(29)
2437 scaled = (static_cast<uint64_t>(0x3fd) << 52) |
2438 ((static_cast<uint64_t>(a_bits) & 0x7fffff) << 29);
2439 } else {
2440 // scaled = '0 01111111110' : operand<22:0> : Zeros(29)
2441 scaled = (static_cast<uint64_t>(0x3fe) << 52) |
2442 ((static_cast<uint64_t>(a_bits) & 0x7fffff) << 29);
2443 }
2444 // result_exp = (380 - UInt(operand<30:23>) DIV 2;
2445 int32_t result_exp = (380 - ((a_bits >> 23) & 0xff)) / 2;
2446
2447 double scaled_d = bit_cast<double, uint64_t>(scaled);
2448 ASSERT((scaled_d >= 0.25) && (scaled_d < 1.0));
2449
2450 double r;
2451 if (scaled_d < 0.5) {
2452 // range 0.25 <= a < 0.5
2453
2454 // a in units of 1/512 rounded down.
2455 int32_t q0 = static_cast<int32_t>(scaled_d * 512.0);
2456 // reciprocal root r.
2457 r = 1.0 / sqrt((static_cast<double>(q0) + 0.5) / 512.0);
2458 } else {
2459 // range 0.5 <= a < 1.0
2460
2461 // a in units of 1/256 rounded down.
2462 int32_t q1 = static_cast<int32_t>(scaled_d * 256.0);
2463 // reciprocal root r.
2464 r = 1.0 / sqrt((static_cast<double>(q1) + 0.5) / 256.0);
2465 }
2466 // r in units of 1/256 rounded to nearest.
2467 int32_t s = static_cast<int>(256.0 * r + 0.5);
2468 double estimate = static_cast<double>(s) / 256.0;
2469 ASSERT((estimate >= 1.0) && (estimate <= (511.0/256.0)));
2470
2471 // result = 0 : result_exp<7:0> : estimate<51:29>
2472 int32_t result_bits = ((result_exp & 0xff) << 23) |
2473 ((bit_cast<uint64_t, double>(estimate) >> 29) & 0x7fffff);
2474 return bit_cast<float, int32_t>(result_bits);
2475 }
2476
2477
2478 static float arm_recip_estimate(float a) {
2479 // From the ARM Architecture Reference Manual A2-85.
2480 if (isinf(a) || (fabs(a) >= exp2f(126))) return 0.0;
2481 else if (a == 0.0) return INFINITY;
2482 else if (isnan(a)) return a;
2483
2484 uint32_t a_bits = bit_cast<uint32_t, float>(a);
2485 // scaled = '0011 1111 1110' : a<22:0> : Zeros(29)
2486 uint64_t scaled = (static_cast<uint64_t>(0x3fe) << 52) |
2487 ((static_cast<uint64_t>(a_bits) & 0x7fffff) << 29);
2488 // result_exp = 253 - UInt(a<30:23>)
2489 int32_t result_exp = 253 - ((a_bits >> 23) & 0xff);
2490 ASSERT((result_exp >= 1) && (result_exp <= 252));
2491
2492 double scaled_d = bit_cast<double, uint64_t>(scaled);
2493 ASSERT((scaled_d >= 0.5) && (scaled_d < 1.0));
2494
2495 // a in units of 1/512 rounded down.
2496 int32_t q = static_cast<int32_t>(scaled_d * 512.0);
2497 // reciprocal r.
2498 double r = 1.0 / ((static_cast<double>(q) + 0.5) / 512.0);
2499 // r in units of 1/256 rounded to nearest.
2500 int32_t s = static_cast<int32_t>(256.0 * r + 0.5);
2501 double estimate = static_cast<double>(s) / 256.0;
2502 ASSERT((estimate >= 1.0) && (estimate <= (511.0/256.0)));
2503
2504 // result = sign : result_exp<7:0> : estimate<51:29>
2505 int32_t result_bits =
2506 (a_bits & 0x80000000) | ((result_exp & 0xff) << 23) |
2507 ((bit_cast<uint64_t, double>(estimate) >> 29) & 0x7fffff);
2508 return bit_cast<float, int32_t>(result_bits);
2509 }
2510
2511
2377 void Simulator::DecodeSIMDTwoReg(Instr* instr) { 2512 void Simulator::DecodeSIMDTwoReg(Instr* instr) {
2378 const int32_t Q = instr->Bit(30); 2513 const int32_t Q = instr->Bit(30);
2379 const int32_t U = instr->Bit(29); 2514 const int32_t U = instr->Bit(29);
2380 const int32_t op = instr->Bits(12, 5); 2515 const int32_t op = instr->Bits(12, 5);
2381 const int32_t sz = instr->Bits(22, 2); 2516 const int32_t sz = instr->Bits(22, 2);
2382 const VRegister vd = instr->VdField(); 2517 const VRegister vd = instr->VdField();
2383 const VRegister vn = instr->VnField(); 2518 const VRegister vn = instr->VnField();
2384 2519
2385 if ((Q == 1) && (U == 1) && (op == 5)) { 2520 if (Q != 1) {
2521 UnimplementedInstruction(instr);
2522 return;
2523 }
2524
2525 if ((U == 1) && (op == 5)) {
2386 // Format(instr, "vnot 'vd, 'vn"); 2526 // Format(instr, "vnot 'vd, 'vn");
2387 for (int i = 0; i < 2; i++) { 2527 for (int i = 0; i < 2; i++) {
2388 set_vregisterd(vd, i, ~get_vregisterd(vn, i)); 2528 set_vregisterd(vd, i, ~get_vregisterd(vn, i));
2389 } 2529 }
2390 } else if ((U == 0) && (op == 0xf)) { 2530 } else if ((U == 0) && (op == 0xf)) {
2391 if (sz == 2) { 2531 if (sz == 2) {
2392 // Format(instr, "vabss 'vd, 'vn"); 2532 // Format(instr, "vabss 'vd, 'vn");
2393 for (int i = 0; i < 4; i++) { 2533 for (int i = 0; i < 4; i++) {
2394 const int32_t vn_val = get_vregisters(vn, i); 2534 const int32_t vn_val = get_vregisters(vn, i);
2395 const float vn_flt = bit_cast<float, int32_t>(vn_val); 2535 const float vn_flt = bit_cast<float, int32_t>(vn_val);
(...skipping 20 matching lines...) Expand all
2416 } else if (sz == 3) { 2556 } else if (sz == 3) {
2417 // Format(instr, "vnegd 'vd, 'vn"); 2557 // Format(instr, "vnegd 'vd, 'vn");
2418 for (int i = 0; i < 2; i++) { 2558 for (int i = 0; i < 2; i++) {
2419 const int64_t vn_val = get_vregisterd(vn, i); 2559 const int64_t vn_val = get_vregisterd(vn, i);
2420 const double vn_dbl = bit_cast<double, int64_t>(vn_val); 2560 const double vn_dbl = bit_cast<double, int64_t>(vn_val);
2421 set_vregisterd(vd, i, bit_cast<int64_t, double>(-vn_dbl)); 2561 set_vregisterd(vd, i, bit_cast<int64_t, double>(-vn_dbl));
2422 } 2562 }
2423 } else { 2563 } else {
2424 UnimplementedInstruction(instr); 2564 UnimplementedInstruction(instr);
2425 } 2565 }
2566 } else if ((U == 1) && (op == 0x1f)) {
2567 if (sz == 2) {
2568 // Format(instr, "vsqrts 'vd, 'vn");
2569 for (int i = 0; i < 4; i++) {
2570 const int32_t vn_val = get_vregisters(vn, i);
2571 const float vn_flt = bit_cast<float, int32_t>(vn_val);
2572 set_vregisters(vd, i, bit_cast<int32_t, float>(sqrtf(vn_flt)));
2573 }
2574 } else if (sz == 3) {
2575 // Format(instr, "vsqrtd 'vd, 'vn");
2576 for (int i = 0; i < 2; i++) {
2577 const int64_t vn_val = get_vregisterd(vn, i);
2578 const double vn_dbl = bit_cast<double, int64_t>(vn_val);
2579 set_vregisterd(vd, i, bit_cast<int64_t, double>(sqrt(vn_dbl)));
2580 }
2581 } else {
2582 UnimplementedInstruction(instr);
2583 }
2584 } else if ((U == 0) && (op == 0x1d)) {
2585 if (sz != 2) {
2586 UnimplementedInstruction(instr);
2587 return;
2588 }
2589 // Format(instr, "vrecpes 'vd, 'vn");
2590 for (int i = 0; i < 4; i++) {
2591 const int32_t vn_val = get_vregisters(vn, i);
2592 const float vn_flt = bit_cast<float, int32_t>(vn_val);
2593 const float re = arm_recip_estimate(vn_flt);
2594 set_vregisters(vd, i, bit_cast<int32_t, float>(re));
2595 }
2596 } else if ((U == 1) && (op == 0x1d)) {
2597 if (sz != 2) {
2598 UnimplementedInstruction(instr);
2599 return;
2600 }
2601 // Format(instr, "vrsqrtes 'vd, 'vn");
2602 for (int i = 0; i < 4; i++) {
2603 const int32_t vn_val = get_vregisters(vn, i);
2604 const float vn_flt = bit_cast<float, int32_t>(vn_val);
2605 const float re = arm_reciprocal_sqrt_estimate(vn_flt);
2606 set_vregisters(vd, i, bit_cast<int32_t, float>(re));
2607 }
2426 } else { 2608 } else {
2427 UnimplementedInstruction(instr); 2609 UnimplementedInstruction(instr);
2428 } 2610 }
2429 } 2611 }
2430 2612
2431 2613
2432 void Simulator::DecodeDPSimd1(Instr* instr) { 2614 void Simulator::DecodeDPSimd1(Instr* instr) {
2433 if (instr->IsSIMDCopyOp()) { 2615 if (instr->IsSIMDCopyOp()) {
2434 DecodeSIMDCopy(instr); 2616 DecodeSIMDCopy(instr);
2435 } else if (instr->IsSIMDThreeSameOp()) { 2617 } else if (instr->IsSIMDThreeSameOp()) {
(...skipping 418 matching lines...) Expand 10 before | Expand all | Expand 10 after
2854 set_register(kExceptionObjectReg, bit_cast<int64_t>(raw_exception)); 3036 set_register(kExceptionObjectReg, bit_cast<int64_t>(raw_exception));
2855 set_register(kStackTraceObjectReg, bit_cast<int64_t>(raw_stacktrace)); 3037 set_register(kStackTraceObjectReg, bit_cast<int64_t>(raw_stacktrace));
2856 buf->Longjmp(); 3038 buf->Longjmp();
2857 } 3039 }
2858 3040
2859 } // namespace dart 3041 } // namespace dart
2860 3042
2861 #endif // !defined(HOST_ARCH_ARM64) 3043 #endif // !defined(HOST_ARCH_ARM64)
2862 3044
2863 #endif // defined TARGET_ARCH_ARM64 3045 #endif // defined TARGET_ARCH_ARM64
OLDNEW
« no previous file with comments | « runtime/vm/intermediate_language_arm64.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698