| OLD | NEW |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 |
| OLD | NEW |