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

Side by Side Diff: src/mips64/simulator-mips64.cc

Issue 1046873004: MIPS: Refactor simulator and add selection instructions for r6. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 5 years, 8 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
OLDNEW
1 // Copyright 2011 the V8 project authors. All rights reserved. 1 // Copyright 2011 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include <limits.h> 5 #include <limits.h>
6 #include <stdarg.h> 6 #include <stdarg.h>
7 #include <stdlib.h> 7 #include <stdlib.h>
8 #include <cmath> 8 #include <cmath>
9 9
10 #include "src/v8.h" 10 #include "src/v8.h"
(...skipping 2188 matching lines...) Expand 10 before | Expand all | Expand 10 after
2199 case MOVZ: 2199 case MOVZ:
2200 case MOVCI: 2200 case MOVCI:
2201 // No action taken on decode. 2201 // No action taken on decode.
2202 break; 2202 break;
2203 case DIV: 2203 case DIV:
2204 case DIVU: 2204 case DIVU:
2205 case DDIV: 2205 case DDIV:
2206 case DDIVU: 2206 case DDIVU:
2207 // div and divu never raise exceptions. 2207 // div and divu never raise exceptions.
2208 break; 2208 break;
2209 case SELEQZ_S:
2210 case SELNEZ_S:
2211 break;
2209 default: 2212 default:
2210 UNREACHABLE(); 2213 UNREACHABLE();
2211 } 2214 }
2212 break; 2215 break;
2213 case SPECIAL2: 2216 case SPECIAL2:
2214 switch (instr->FunctionFieldRaw()) { 2217 switch (instr->FunctionFieldRaw()) {
2215 case MUL: 2218 case MUL:
2216 // Only the lower 32 bits are kept. 2219 // Only the lower 32 bits are kept.
2217 *alu_out = (int32_t)rs_u * (int32_t)rt_u; 2220 *alu_out = (int32_t)rs_u * (int32_t)rt_u;
2218 break; 2221 break;
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
2260 default: 2263 default:
2261 UNREACHABLE(); 2264 UNREACHABLE();
2262 } 2265 }
2263 break; 2266 break;
2264 default: 2267 default:
2265 UNREACHABLE(); 2268 UNREACHABLE();
2266 } 2269 }
2267 } 2270 }
2268 2271
2269 2272
2273 void Simulator::DecodeTypeRegisterSRsType(Instruction* instr,
2274 const int32_t& fs_reg,
2275 const int64_t& fd_reg) {
2276 float f;
2277 switch (instr->FunctionFieldRaw()) {
2278 case CVT_D_S:
2279 f = get_fpu_register_float(fs_reg);
2280 set_fpu_register_double(fd_reg, static_cast<double>(f));
2281 break;
2282 default:
2283 // CVT_W_S CVT_L_S TRUNC_W_S ROUND_W_S ROUND_L_S FLOOR_W_S FLOOR_L_S
2284 // CEIL_W_S CEIL_L_S CVT_PS_S are unimplemented.
2285 UNREACHABLE();
2286 }
2287 }
2288
2289
2290 void Simulator::DecodeTypeRegisterDRsType(Instruction* instr,
2291 const int32_t& fs_reg,
2292 const int64_t& ft_reg,
2293 const int32_t& fd_reg) {
2294 double ft, fs;
2295 uint32_t cc, fcsr_cc;
2296 fs = get_fpu_register_double(fs_reg);
2297 ft = get_fpu_register_double(ft_reg);
2298 cc = instr->FCccValue();
2299 fcsr_cc = get_fcsr_condition_bit(cc);
2300 int64_t ft_int = static_cast<int64_t>(ft);
2301 switch (instr->FunctionFieldRaw()) {
2302 case SELEQZ_C:
2303 DCHECK(kArchVariant == kMips64r6);
2304 set_fpu_register_double(fd_reg, (ft_int & 0x1) == 0 ? fs : 0.0);
2305 break;
2306 case SELNEZ_C:
2307 DCHECK(kArchVariant == kMips64r6);
2308 set_fpu_register_double(fd_reg, (ft_int & 0x1) != 0 ? fs : 0.0);
2309 break;
2310 case ADD_D:
2311 set_fpu_register_double(fd_reg, fs + ft);
2312 break;
2313 case SUB_D:
2314 set_fpu_register_double(fd_reg, fs - ft);
2315 break;
2316 case MUL_D:
2317 set_fpu_register_double(fd_reg, fs * ft);
2318 break;
2319 case DIV_D:
2320 set_fpu_register_double(fd_reg, fs / ft);
2321 break;
2322 case ABS_D:
2323 set_fpu_register_double(fd_reg, fabs(fs));
2324 break;
2325 case MOV_D:
2326 set_fpu_register_double(fd_reg, fs);
2327 break;
2328 case NEG_D:
2329 set_fpu_register_double(fd_reg, -fs);
2330 break;
2331 case SQRT_D:
2332 set_fpu_register_double(fd_reg, fast_sqrt(fs));
2333 break;
2334 case C_UN_D:
2335 set_fcsr_bit(fcsr_cc, std::isnan(fs) || std::isnan(ft));
2336 break;
2337 case C_EQ_D:
2338 set_fcsr_bit(fcsr_cc, (fs == ft));
2339 break;
2340 case C_UEQ_D:
2341 set_fcsr_bit(fcsr_cc, (fs == ft) || (std::isnan(fs) || std::isnan(ft)));
2342 break;
2343 case C_OLT_D:
2344 set_fcsr_bit(fcsr_cc, (fs < ft));
2345 break;
2346 case C_ULT_D:
2347 set_fcsr_bit(fcsr_cc, (fs < ft) || (std::isnan(fs) || std::isnan(ft)));
2348 break;
2349 case C_OLE_D:
2350 set_fcsr_bit(fcsr_cc, (fs <= ft));
2351 break;
2352 case C_ULE_D:
2353 set_fcsr_bit(fcsr_cc, (fs <= ft) || (std::isnan(fs) || std::isnan(ft)));
2354 break;
2355 case CVT_W_D: // Convert double to word.
2356 // Rounding modes are not yet supported.
2357 DCHECK((FCSR_ & 3) == 0);
2358 // In rounding mode 0 it should behave like ROUND.
2359 // No break.
2360 case ROUND_W_D: // Round double to word (round half to even).
2361 {
2362 double rounded = std::floor(fs + 0.5);
2363 int32_t result = static_cast<int32_t>(rounded);
2364 if ((result & 1) != 0 && result - fs == 0.5) {
2365 // If the number is halfway between two integers,
2366 // round to the even one.
2367 result--;
2368 }
2369 set_fpu_register_word(fd_reg, result);
2370 if (set_fcsr_round_error(fs, rounded)) {
2371 set_fpu_register(fd_reg, kFPUInvalidResult);
2372 }
2373 } break;
2374 case TRUNC_W_D: // Truncate double to word (round towards 0).
2375 {
2376 double rounded = trunc(fs);
2377 int32_t result = static_cast<int32_t>(rounded);
2378 set_fpu_register_word(fd_reg, result);
2379 if (set_fcsr_round_error(fs, rounded)) {
2380 set_fpu_register(fd_reg, kFPUInvalidResult);
2381 }
2382 } break;
2383 case FLOOR_W_D: // Round double to word towards negative infinity.
2384 {
2385 double rounded = std::floor(fs);
2386 int32_t result = static_cast<int32_t>(rounded);
2387 set_fpu_register_word(fd_reg, result);
2388 if (set_fcsr_round_error(fs, rounded)) {
2389 set_fpu_register(fd_reg, kFPUInvalidResult);
2390 }
2391 } break;
2392 case CEIL_W_D: // Round double to word towards positive infinity.
2393 {
2394 double rounded = std::ceil(fs);
2395 int32_t result = static_cast<int32_t>(rounded);
2396 set_fpu_register_word(fd_reg, result);
2397 if (set_fcsr_round_error(fs, rounded)) {
2398 set_fpu_register(fd_reg, kFPUInvalidResult);
2399 }
2400 } break;
2401 case CVT_S_D: // Convert double to float (single).
2402 set_fpu_register_float(fd_reg, static_cast<float>(fs));
2403 break;
2404 case CVT_L_D: // Mips64r2: Truncate double to 64-bit long-word.
2405 // Rounding modes are not yet supported.
2406 DCHECK((FCSR_ & 3) == 0);
2407 // In rounding mode 0 it should behave like ROUND.
2408 // No break.
2409 case ROUND_L_D: { // Mips64r2 instruction.
paul.l... 2015/03/31 04:02:01 As mentioned in simulator-mips.cc: this is for mip
2410 // check error cases
2411 double rounded = fs > 0 ? floor(fs + 0.5) : ceil(fs - 0.5);
2412 int64_t result = static_cast<int64_t>(rounded);
2413 set_fpu_register(fd_reg, result);
2414 if (set_fcsr_round64_error(fs, rounded)) {
2415 set_fpu_register(fd_reg, kFPU64InvalidResult);
2416 }
2417 break;
2418 }
2419 case TRUNC_L_D: { // Mips64r2 instruction.
2420 double rounded = trunc(fs);
2421 int64_t result = static_cast<int64_t>(rounded);
2422 set_fpu_register(fd_reg, result);
2423 if (set_fcsr_round64_error(fs, rounded)) {
2424 set_fpu_register(fd_reg, kFPU64InvalidResult);
2425 }
2426 break;
2427 }
2428 case FLOOR_L_D: { // Mips64r2 instruction.
2429 double rounded = floor(fs);
2430 int64_t result = static_cast<int64_t>(rounded);
2431 set_fpu_register(fd_reg, result);
2432 if (set_fcsr_round64_error(fs, rounded)) {
2433 set_fpu_register(fd_reg, kFPU64InvalidResult);
2434 }
2435 break;
2436 }
2437 case CEIL_L_D: { // Mips64r2 instruction.
2438 double rounded = ceil(fs);
2439 int64_t result = static_cast<int64_t>(rounded);
2440 set_fpu_register(fd_reg, result);
2441 if (set_fcsr_round64_error(fs, rounded)) {
2442 set_fpu_register(fd_reg, kFPU64InvalidResult);
2443 }
2444 break;
2445 }
2446 case C_F_D:
2447 UNIMPLEMENTED_MIPS();
2448 break;
2449 default:
2450 UNREACHABLE();
2451 }
2452 }
2453
2454
2455 void Simulator::DecodeTypeRegisterWRsType(Instruction* instr,
2456 const int32_t& fs_reg,
2457 const int32_t& fd_reg,
2458 int64_t& alu_out) {
2459 switch (instr->FunctionFieldRaw()) {
2460 case CVT_S_W: // Convert word to float (single).
2461 alu_out = get_fpu_register_signed_word(fs_reg);
2462 set_fpu_register_float(fd_reg, static_cast<float>(alu_out));
2463 break;
2464 case CVT_D_W: // Convert word to double.
2465 alu_out = get_fpu_register_signed_word(fs_reg);
2466 set_fpu_register_double(fd_reg, static_cast<double>(alu_out));
2467 break;
2468 default: // Mips64r6 CMP.S instructions unimplemented.
2469 UNREACHABLE();
2470 }
2471 }
2472
2473
2474 void Simulator::DecodeTypeRegisterLRsType(Instruction* instr,
2475 const int32_t& fs_reg,
2476 const int32_t& fd_reg,
2477 const int32_t& ft_reg) {
2478 double fs = get_fpu_register_double(fs_reg);
2479 double ft = get_fpu_register_double(ft_reg);
2480 int64_t i64;
2481 switch (instr->FunctionFieldRaw()) {
2482 case CVT_D_L: // Mips32r2 instruction.
2483 i64 = get_fpu_register(fs_reg);
2484 set_fpu_register_double(fd_reg, static_cast<double>(i64));
2485 break;
2486 case CVT_S_L:
2487 UNIMPLEMENTED_MIPS();
2488 break;
2489 case CMP_AF: // Mips64r6 CMP.D instructions.
2490 UNIMPLEMENTED_MIPS();
2491 break;
2492 case CMP_UN:
2493 if (std::isnan(fs) || std::isnan(ft)) {
2494 set_fpu_register(fd_reg, -1);
2495 } else {
2496 set_fpu_register(fd_reg, 0);
2497 }
2498 break;
2499 case CMP_EQ:
2500 if (fs == ft) {
2501 set_fpu_register(fd_reg, -1);
2502 } else {
2503 set_fpu_register(fd_reg, 0);
2504 }
2505 break;
2506 case CMP_UEQ:
2507 if ((fs == ft) || (std::isnan(fs) || std::isnan(ft))) {
2508 set_fpu_register(fd_reg, -1);
2509 } else {
2510 set_fpu_register(fd_reg, 0);
2511 }
2512 break;
2513 case CMP_LT:
2514 if (fs < ft) {
2515 set_fpu_register(fd_reg, -1);
2516 } else {
2517 set_fpu_register(fd_reg, 0);
2518 }
2519 break;
2520 case CMP_ULT:
2521 if ((fs < ft) || (std::isnan(fs) || std::isnan(ft))) {
2522 set_fpu_register(fd_reg, -1);
2523 } else {
2524 set_fpu_register(fd_reg, 0);
2525 }
2526 break;
2527 case CMP_LE:
2528 if (fs <= ft) {
2529 set_fpu_register(fd_reg, -1);
2530 } else {
2531 set_fpu_register(fd_reg, 0);
2532 }
2533 break;
2534 case CMP_ULE:
2535 if ((fs <= ft) || (std::isnan(fs) || std::isnan(ft))) {
2536 set_fpu_register(fd_reg, -1);
2537 } else {
2538 set_fpu_register(fd_reg, 0);
2539 }
2540 break;
2541 default: // CMP_OR CMP_UNE CMP_NE UNIMPLEMENTED
2542 UNREACHABLE();
2543 }
2544 }
2545
2546
2547 void Simulator::DecodeTypeRegisterCOP1(
2548 Instruction* instr, const int64_t& rs_reg, const int64_t& rs,
2549 const uint64_t& rs_u, const int64_t& rt_reg, const int64_t& rt,
2550 const uint64_t& rt_u, const int64_t& rd_reg, const int32_t& fr_reg,
2551 const int32_t& fs_reg, const int32_t& ft_reg, const int64_t& fd_reg,
2552 int64_t& alu_out) {
2553 switch (instr->RsFieldRaw()) {
2554 case BC1: // Branch on coprocessor condition.
2555 case BC1EQZ:
2556 case BC1NEZ:
2557 UNREACHABLE();
2558 break;
2559 case CFC1:
2560 set_register(rt_reg, alu_out);
2561 break;
2562 case MFC1:
2563 case DMFC1:
2564 case MFHC1:
2565 set_register(rt_reg, alu_out);
2566 break;
2567 case CTC1:
2568 // At the moment only FCSR is supported.
2569 DCHECK(fs_reg == kFCSRRegister);
2570 FCSR_ = registers_[rt_reg];
2571 break;
2572 case MTC1:
2573 // Hardware writes upper 32-bits to zero on mtc1.
2574 set_fpu_register_hi_word(fs_reg, 0);
2575 set_fpu_register_word(fs_reg, registers_[rt_reg]);
2576 break;
2577 case DMTC1:
2578 set_fpu_register(fs_reg, registers_[rt_reg]);
2579 break;
2580 case MTHC1:
2581 set_fpu_register_hi_word(fs_reg, registers_[rt_reg]);
2582 break;
2583 case S:
2584 DecodeTypeRegisterSRsType(instr, fs_reg, fd_reg);
2585 break;
2586 case D:
2587 DecodeTypeRegisterDRsType(instr, fs_reg, ft_reg, fd_reg);
2588 break;
2589 case W:
2590 DecodeTypeRegisterWRsType(instr, fs_reg, fd_reg, alu_out);
2591 break;
2592 case L:
2593 DecodeTypeRegisterLRsType(instr, fs_reg, fd_reg, ft_reg);
2594 break;
2595 default:
2596 UNREACHABLE();
2597 }
2598 }
2599
2600
2601 void Simulator::DecodeTypeRegisterCOP1X(Instruction* instr,
2602 const int32_t& fr_reg,
2603 const int32_t& fs_reg,
2604 const int32_t& ft_reg,
2605 const int64_t& fd_reg) {
2606 switch (instr->FunctionFieldRaw()) {
2607 case MADD_D:
2608 double fr, ft, fs;
2609 fr = get_fpu_register_double(fr_reg);
2610 fs = get_fpu_register_double(fs_reg);
2611 ft = get_fpu_register_double(ft_reg);
2612 set_fpu_register_double(fd_reg, fs * ft + fr);
2613 break;
2614 default:
2615 UNREACHABLE();
2616 }
2617 }
2618
2619
2620 void Simulator::DecodeTypeRegisterSPECIAL(
2621 Instruction* instr, const int64_t& rs_reg, const int64_t& rs,
2622 const uint64_t& rs_u, const int64_t& rt_reg, const int64_t& rt,
2623 const uint64_t& rt_u, const int64_t& rd_reg, const int32_t& fr_reg,
2624 const int32_t& fs_reg, const int32_t& ft_reg, const int64_t& fd_reg,
2625 int64_t& i64hilo, uint64_t& u64hilo, int64_t& alu_out, bool& do_interrupt,
2626 int64_t& current_pc, int64_t& next_pc, int64_t& return_addr_reg,
2627 int64_t& i128resultH, int64_t& i128resultL) {
2628 switch (instr->FunctionFieldRaw()) {
2629 case SELEQZ_S:
2630 DCHECK(kArchVariant == kMips64r6);
2631 set_register(rd_reg, rt == 0 ? rs : 0);
2632 break;
2633 case SELNEZ_S:
2634 DCHECK(kArchVariant == kMips64r6);
2635 set_register(rd_reg, rt != 0 ? rs : 0);
2636 break;
2637 case JR: {
2638 Instruction* branch_delay_instr =
2639 reinterpret_cast<Instruction*>(current_pc + Instruction::kInstrSize);
2640 BranchDelayInstructionDecode(branch_delay_instr);
2641 set_pc(next_pc);
2642 pc_modified_ = true;
2643 break;
2644 }
2645 case JALR: {
2646 Instruction* branch_delay_instr =
2647 reinterpret_cast<Instruction*>(current_pc + Instruction::kInstrSize);
2648 BranchDelayInstructionDecode(branch_delay_instr);
2649 set_register(return_addr_reg, current_pc + 2 * Instruction::kInstrSize);
2650 set_pc(next_pc);
2651 pc_modified_ = true;
2652 break;
2653 }
2654 // Instructions using HI and LO registers.
2655 case MULT:
2656 if (kArchVariant != kMips64r6) {
2657 set_register(LO, static_cast<int32_t>(i64hilo & 0xffffffff));
2658 set_register(HI, static_cast<int32_t>(i64hilo >> 32));
2659 } else {
2660 switch (instr->SaValue()) {
2661 case MUL_OP:
2662 set_register(rd_reg, static_cast<int32_t>(i64hilo & 0xffffffff));
2663 break;
2664 case MUH_OP:
2665 set_register(rd_reg, static_cast<int32_t>(i64hilo >> 32));
2666 break;
2667 default:
2668 UNIMPLEMENTED_MIPS();
2669 break;
2670 }
2671 }
2672 break;
2673 case MULTU:
2674 set_register(LO, static_cast<int32_t>(u64hilo & 0xffffffff));
2675 set_register(HI, static_cast<int32_t>(u64hilo >> 32));
2676 break;
2677 case DMULT: // DMULT == D_MUL_MUH.
2678 if (kArchVariant != kMips64r6) {
2679 set_register(LO, static_cast<int64_t>(i128resultL));
2680 set_register(HI, static_cast<int64_t>(i128resultH));
2681 } else {
2682 switch (instr->SaValue()) {
2683 case MUL_OP:
2684 set_register(rd_reg, static_cast<int64_t>(i128resultL));
2685 break;
2686 case MUH_OP:
2687 set_register(rd_reg, static_cast<int64_t>(i128resultH));
2688 break;
2689 default:
2690 UNIMPLEMENTED_MIPS();
2691 break;
2692 }
2693 }
2694 break;
2695 case DMULTU:
2696 UNIMPLEMENTED_MIPS();
2697 break;
2698 case DSLL:
2699 set_register(rd_reg, alu_out);
2700 break;
2701 case DIV:
2702 case DDIV:
2703 switch (kArchVariant) {
2704 case kMips64r2:
2705 // Divide by zero and overflow was not checked in the
2706 // configuration step - div and divu do not raise exceptions. On
2707 // division by 0 the result will be UNPREDICTABLE. On overflow
2708 // (INT_MIN/-1), return INT_MIN which is what the hardware does.
2709 if (rs == INT_MIN && rt == -1) {
2710 set_register(LO, INT_MIN);
2711 set_register(HI, 0);
2712 } else if (rt != 0) {
2713 set_register(LO, rs / rt);
2714 set_register(HI, rs % rt);
2715 }
2716 break;
2717 case kMips64r6:
2718 switch (instr->SaValue()) {
2719 case DIV_OP:
2720 if (rs == INT_MIN && rt == -1) {
2721 set_register(rd_reg, INT_MIN);
2722 } else if (rt != 0) {
2723 set_register(rd_reg, rs / rt);
2724 }
2725 break;
2726 case MOD_OP:
2727 if (rs == INT_MIN && rt == -1) {
2728 set_register(rd_reg, 0);
2729 } else if (rt != 0) {
2730 set_register(rd_reg, rs % rt);
2731 }
2732 break;
2733 default:
2734 UNIMPLEMENTED_MIPS();
2735 break;
2736 }
2737 break;
2738 default:
2739 break;
2740 }
2741 break;
2742 case DIVU:
2743 if (rt_u != 0) {
2744 set_register(LO, rs_u / rt_u);
2745 set_register(HI, rs_u % rt_u);
2746 }
2747 break;
2748 // Break and trap instructions.
2749 case BREAK:
2750 case TGE:
2751 case TGEU:
2752 case TLT:
2753 case TLTU:
2754 case TEQ:
2755 case TNE:
2756 if (do_interrupt) {
2757 SoftwareInterrupt(instr);
2758 }
2759 break;
2760 // Conditional moves.
2761 case MOVN:
2762 if (rt) {
2763 set_register(rd_reg, rs);
2764 TraceRegWr(rs);
2765 }
2766 break;
2767 case MOVCI: {
2768 uint32_t cc = instr->FBccValue();
2769 uint32_t fcsr_cc = get_fcsr_condition_bit(cc);
2770 if (instr->Bit(16)) { // Read Tf bit.
2771 if (test_fcsr_bit(fcsr_cc)) set_register(rd_reg, rs);
2772 } else {
2773 if (!test_fcsr_bit(fcsr_cc)) set_register(rd_reg, rs);
2774 }
2775 break;
2776 }
2777 case MOVZ:
2778 if (!rt) {
2779 set_register(rd_reg, rs);
2780 TraceRegWr(rs);
2781 }
2782 break;
2783 default: // For other special opcodes we do the default operation.
2784 set_register(rd_reg, alu_out);
2785 TraceRegWr(alu_out);
2786 }
2787 }
2788
2789
2790 void Simulator::DecodeTypeRegisterSPECIAL2(Instruction* instr,
2791 const int64_t& rd_reg,
2792 int64_t& alu_out) {
2793 switch (instr->FunctionFieldRaw()) {
2794 case MUL:
2795 set_register(rd_reg, alu_out);
2796 TraceRegWr(alu_out);
2797 // HI and LO are UNPREDICTABLE after the operation.
2798 set_register(LO, Unpredictable);
2799 set_register(HI, Unpredictable);
2800 break;
2801 default: // For other special2 opcodes we do the default operation.
2802 set_register(rd_reg, alu_out);
2803 }
2804 }
2805
2806
2807 void Simulator::DecodeTypeRegisterSPECIAL3(Instruction* instr,
2808 const int64_t& rt_reg,
2809 int64_t& alu_out) {
2810 switch (instr->FunctionFieldRaw()) {
2811 case INS:
2812 // Ins instr leaves result in Rt, rather than Rd.
2813 set_register(rt_reg, alu_out);
2814 TraceRegWr(alu_out);
2815 break;
2816 case EXT:
2817 case DEXT:
2818 // Dext/Ext instr leaves result in Rt, rather than Rd.
2819 set_register(rt_reg, alu_out);
2820 TraceRegWr(alu_out);
2821 break;
2822 default:
2823 UNREACHABLE();
2824 }
2825 }
2826
2827
2270 void Simulator::DecodeTypeRegister(Instruction* instr) { 2828 void Simulator::DecodeTypeRegister(Instruction* instr) {
2271 // Instruction fields. 2829 // Instruction fields.
2272 const Opcode op = instr->OpcodeFieldRaw(); 2830 const Opcode op = instr->OpcodeFieldRaw();
2273 const int64_t rs_reg = instr->RsValue(); 2831 const int64_t rs_reg = instr->RsValue();
2274 const int64_t rs = get_register(rs_reg); 2832 const int64_t rs = get_register(rs_reg);
2275 const uint64_t rs_u = static_cast<uint32_t>(rs); 2833 const uint64_t rs_u = static_cast<uint32_t>(rs);
2276 const int64_t rt_reg = instr->RtValue(); 2834 const int64_t rt_reg = instr->RtValue();
2277 const int64_t rt = get_register(rt_reg); 2835 const int64_t rt = get_register(rt_reg);
2278 const uint64_t rt_u = static_cast<uint32_t>(rt); 2836 const uint64_t rt_u = static_cast<uint32_t>(rt);
2279 const int64_t rd_reg = instr->RdValue(); 2837 const int64_t rd_reg = instr->RdValue();
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
2313 &do_interrupt, 2871 &do_interrupt,
2314 &i128resultH, 2872 &i128resultH,
2315 &i128resultL); 2873 &i128resultL);
2316 2874
2317 // ---------- Raise exceptions triggered. 2875 // ---------- Raise exceptions triggered.
2318 SignalExceptions(); 2876 SignalExceptions();
2319 2877
2320 // ---------- Execution. 2878 // ---------- Execution.
2321 switch (op) { 2879 switch (op) {
2322 case COP1: 2880 case COP1:
2323 switch (instr->RsFieldRaw()) { 2881 DecodeTypeRegisterCOP1(instr, rs_reg, rs, rs_u, rt_reg, rt, rt_u, rd_reg,
2324 case BC1: // Branch on coprocessor condition. 2882 fr_reg, fs_reg, ft_reg, fd_reg, alu_out);
2325 case BC1EQZ:
2326 case BC1NEZ:
2327 UNREACHABLE();
2328 break;
2329 case CFC1:
2330 set_register(rt_reg, alu_out);
2331 break;
2332 case MFC1:
2333 case DMFC1:
2334 case MFHC1:
2335 set_register(rt_reg, alu_out);
2336 break;
2337 case CTC1:
2338 // At the moment only FCSR is supported.
2339 DCHECK(fs_reg == kFCSRRegister);
2340 FCSR_ = registers_[rt_reg];
2341 break;
2342 case MTC1:
2343 // Hardware writes upper 32-bits to zero on mtc1.
2344 set_fpu_register_hi_word(fs_reg, 0);
2345 set_fpu_register_word(fs_reg, registers_[rt_reg]);
2346 break;
2347 case DMTC1:
2348 set_fpu_register(fs_reg, registers_[rt_reg]);
2349 break;
2350 case MTHC1:
2351 set_fpu_register_hi_word(fs_reg, registers_[rt_reg]);
2352 break;
2353 case S:
2354 float f;
2355 switch (instr->FunctionFieldRaw()) {
2356 case CVT_D_S:
2357 f = get_fpu_register_float(fs_reg);
2358 set_fpu_register_double(fd_reg, static_cast<double>(f));
2359 break;
2360 default:
2361 // CVT_W_S CVT_L_S TRUNC_W_S ROUND_W_S ROUND_L_S FLOOR_W_S FLOOR_L_S
2362 // CEIL_W_S CEIL_L_S CVT_PS_S are unimplemented.
2363 UNREACHABLE();
2364 }
2365 break;
2366 case D:
2367 double ft, fs;
2368 uint32_t cc, fcsr_cc;
2369 int64_t i64;
2370 fs = get_fpu_register_double(fs_reg);
2371 ft = get_fpu_register_double(ft_reg);
2372 cc = instr->FCccValue();
2373 fcsr_cc = get_fcsr_condition_bit(cc);
2374 switch (instr->FunctionFieldRaw()) {
2375 case ADD_D:
2376 set_fpu_register_double(fd_reg, fs + ft);
2377 break;
2378 case SUB_D:
2379 set_fpu_register_double(fd_reg, fs - ft);
2380 break;
2381 case MUL_D:
2382 set_fpu_register_double(fd_reg, fs * ft);
2383 break;
2384 case DIV_D:
2385 set_fpu_register_double(fd_reg, fs / ft);
2386 break;
2387 case ABS_D:
2388 set_fpu_register_double(fd_reg, fabs(fs));
2389 break;
2390 case MOV_D:
2391 set_fpu_register_double(fd_reg, fs);
2392 break;
2393 case NEG_D:
2394 set_fpu_register_double(fd_reg, -fs);
2395 break;
2396 case SQRT_D:
2397 set_fpu_register_double(fd_reg, fast_sqrt(fs));
2398 break;
2399 case C_UN_D:
2400 set_fcsr_bit(fcsr_cc, std::isnan(fs) || std::isnan(ft));
2401 break;
2402 case C_EQ_D:
2403 set_fcsr_bit(fcsr_cc, (fs == ft));
2404 break;
2405 case C_UEQ_D:
2406 set_fcsr_bit(fcsr_cc,
2407 (fs == ft) || (std::isnan(fs) || std::isnan(ft)));
2408 break;
2409 case C_OLT_D:
2410 set_fcsr_bit(fcsr_cc, (fs < ft));
2411 break;
2412 case C_ULT_D:
2413 set_fcsr_bit(fcsr_cc,
2414 (fs < ft) || (std::isnan(fs) || std::isnan(ft)));
2415 break;
2416 case C_OLE_D:
2417 set_fcsr_bit(fcsr_cc, (fs <= ft));
2418 break;
2419 case C_ULE_D:
2420 set_fcsr_bit(fcsr_cc,
2421 (fs <= ft) || (std::isnan(fs) || std::isnan(ft)));
2422 break;
2423 case CVT_W_D: // Convert double to word.
2424 // Rounding modes are not yet supported.
2425 DCHECK((FCSR_ & 3) == 0);
2426 // In rounding mode 0 it should behave like ROUND.
2427 // No break.
2428 case ROUND_W_D: // Round double to word (round half to even).
2429 {
2430 double rounded = std::floor(fs + 0.5);
2431 int32_t result = static_cast<int32_t>(rounded);
2432 if ((result & 1) != 0 && result - fs == 0.5) {
2433 // If the number is halfway between two integers,
2434 // round to the even one.
2435 result--;
2436 }
2437 set_fpu_register_word(fd_reg, result);
2438 if (set_fcsr_round_error(fs, rounded)) {
2439 set_fpu_register(fd_reg, kFPUInvalidResult);
2440 }
2441 }
2442 break;
2443 case TRUNC_W_D: // Truncate double to word (round towards 0).
2444 {
2445 double rounded = trunc(fs);
2446 int32_t result = static_cast<int32_t>(rounded);
2447 set_fpu_register_word(fd_reg, result);
2448 if (set_fcsr_round_error(fs, rounded)) {
2449 set_fpu_register(fd_reg, kFPUInvalidResult);
2450 }
2451 }
2452 break;
2453 case FLOOR_W_D: // Round double to word towards negative infinity.
2454 {
2455 double rounded = std::floor(fs);
2456 int32_t result = static_cast<int32_t>(rounded);
2457 set_fpu_register_word(fd_reg, result);
2458 if (set_fcsr_round_error(fs, rounded)) {
2459 set_fpu_register(fd_reg, kFPUInvalidResult);
2460 }
2461 }
2462 break;
2463 case CEIL_W_D: // Round double to word towards positive infinity.
2464 {
2465 double rounded = std::ceil(fs);
2466 int32_t result = static_cast<int32_t>(rounded);
2467 set_fpu_register_word(fd_reg, result);
2468 if (set_fcsr_round_error(fs, rounded)) {
2469 set_fpu_register(fd_reg, kFPUInvalidResult);
2470 }
2471 }
2472 break;
2473 case CVT_S_D: // Convert double to float (single).
2474 set_fpu_register_float(fd_reg, static_cast<float>(fs));
2475 break;
2476 case CVT_L_D: // Mips64r2: Truncate double to 64-bit long-word.
2477 // Rounding modes are not yet supported.
2478 DCHECK((FCSR_ & 3) == 0);
2479 // In rounding mode 0 it should behave like ROUND.
2480 // No break.
2481 case ROUND_L_D: { // Mips64r2 instruction.
2482 // check error cases
2483 double rounded = fs > 0 ? floor(fs + 0.5) : ceil(fs - 0.5);
2484 int64_t result = static_cast<int64_t>(rounded);
2485 set_fpu_register(fd_reg, result);
2486 if (set_fcsr_round64_error(fs, rounded)) {
2487 set_fpu_register(fd_reg, kFPU64InvalidResult);
2488 }
2489 break;
2490 }
2491 case TRUNC_L_D: { // Mips64r2 instruction.
2492 double rounded = trunc(fs);
2493 int64_t result = static_cast<int64_t>(rounded);
2494 set_fpu_register(fd_reg, result);
2495 if (set_fcsr_round64_error(fs, rounded)) {
2496 set_fpu_register(fd_reg, kFPU64InvalidResult);
2497 }
2498 break;
2499 }
2500 case FLOOR_L_D: { // Mips64r2 instruction.
2501 double rounded = floor(fs);
2502 int64_t result = static_cast<int64_t>(rounded);
2503 set_fpu_register(fd_reg, result);
2504 if (set_fcsr_round64_error(fs, rounded)) {
2505 set_fpu_register(fd_reg, kFPU64InvalidResult);
2506 }
2507 break;
2508 }
2509 case CEIL_L_D: { // Mips64r2 instruction.
2510 double rounded = ceil(fs);
2511 int64_t result = static_cast<int64_t>(rounded);
2512 set_fpu_register(fd_reg, result);
2513 if (set_fcsr_round64_error(fs, rounded)) {
2514 set_fpu_register(fd_reg, kFPU64InvalidResult);
2515 }
2516 break;
2517 }
2518 case C_F_D:
2519 UNIMPLEMENTED_MIPS();
2520 break;
2521 default:
2522 UNREACHABLE();
2523 }
2524 break;
2525 case W:
2526 switch (instr->FunctionFieldRaw()) {
2527 case CVT_S_W: // Convert word to float (single).
2528 alu_out = get_fpu_register_signed_word(fs_reg);
2529 set_fpu_register_float(fd_reg, static_cast<float>(alu_out));
2530 break;
2531 case CVT_D_W: // Convert word to double.
2532 alu_out = get_fpu_register_signed_word(fs_reg);
2533 set_fpu_register_double(fd_reg, static_cast<double>(alu_out));
2534 break;
2535 default: // Mips64r6 CMP.S instructions unimplemented.
2536 UNREACHABLE();
2537 }
2538 break;
2539 case L:
2540 fs = get_fpu_register_double(fs_reg);
2541 ft = get_fpu_register_double(ft_reg);
2542 switch (instr->FunctionFieldRaw()) {
2543 case CVT_D_L: // Mips32r2 instruction.
2544 i64 = get_fpu_register(fs_reg);
2545 set_fpu_register_double(fd_reg, static_cast<double>(i64));
2546 break;
2547 case CVT_S_L:
2548 UNIMPLEMENTED_MIPS();
2549 break;
2550 case CMP_AF: // Mips64r6 CMP.D instructions.
2551 UNIMPLEMENTED_MIPS();
2552 break;
2553 case CMP_UN:
2554 if (std::isnan(fs) || std::isnan(ft)) {
2555 set_fpu_register(fd_reg, -1);
2556 } else {
2557 set_fpu_register(fd_reg, 0);
2558 }
2559 break;
2560 case CMP_EQ:
2561 if (fs == ft) {
2562 set_fpu_register(fd_reg, -1);
2563 } else {
2564 set_fpu_register(fd_reg, 0);
2565 }
2566 break;
2567 case CMP_UEQ:
2568 if ((fs == ft) || (std::isnan(fs) || std::isnan(ft))) {
2569 set_fpu_register(fd_reg, -1);
2570 } else {
2571 set_fpu_register(fd_reg, 0);
2572 }
2573 break;
2574 case CMP_LT:
2575 if (fs < ft) {
2576 set_fpu_register(fd_reg, -1);
2577 } else {
2578 set_fpu_register(fd_reg, 0);
2579 }
2580 break;
2581 case CMP_ULT:
2582 if ((fs < ft) || (std::isnan(fs) || std::isnan(ft))) {
2583 set_fpu_register(fd_reg, -1);
2584 } else {
2585 set_fpu_register(fd_reg, 0);
2586 }
2587 break;
2588 case CMP_LE:
2589 if (fs <= ft) {
2590 set_fpu_register(fd_reg, -1);
2591 } else {
2592 set_fpu_register(fd_reg, 0);
2593 }
2594 break;
2595 case CMP_ULE:
2596 if ((fs <= ft) || (std::isnan(fs) || std::isnan(ft))) {
2597 set_fpu_register(fd_reg, -1);
2598 } else {
2599 set_fpu_register(fd_reg, 0);
2600 }
2601 break;
2602 default: // CMP_OR CMP_UNE CMP_NE UNIMPLEMENTED
2603 UNREACHABLE();
2604 }
2605 break;
2606 default:
2607 UNREACHABLE();
2608 }
2609 break; 2883 break;
2610 case COP1X: 2884 case COP1X:
2611 switch (instr->FunctionFieldRaw()) { 2885 DecodeTypeRegisterCOP1X(instr, fr_reg, fs_reg, ft_reg, fd_reg);
2612 case MADD_D:
2613 double fr, ft, fs;
2614 fr = get_fpu_register_double(fr_reg);
2615 fs = get_fpu_register_double(fs_reg);
2616 ft = get_fpu_register_double(ft_reg);
2617 set_fpu_register_double(fd_reg, fs * ft + fr);
2618 break;
2619 default:
2620 UNREACHABLE();
2621 }
2622 break; 2886 break;
2623 case SPECIAL: 2887 case SPECIAL:
2624 switch (instr->FunctionFieldRaw()) { 2888 DecodeTypeRegisterSPECIAL(
2625 case JR: { 2889 instr, rs_reg, rs, rs_u, rt_reg, rt, rt_u, rd_reg, fr_reg, fs_reg,
2626 Instruction* branch_delay_instr = reinterpret_cast<Instruction*>( 2890 ft_reg, fd_reg, i64hilo, u64hilo, alu_out, do_interrupt, current_pc,
2627 current_pc+Instruction::kInstrSize); 2891 next_pc, return_addr_reg, i128resultH, i128resultL);
2628 BranchDelayInstructionDecode(branch_delay_instr);
2629 set_pc(next_pc);
2630 pc_modified_ = true;
2631 break;
2632 }
2633 case JALR: {
2634 Instruction* branch_delay_instr = reinterpret_cast<Instruction*>(
2635 current_pc+Instruction::kInstrSize);
2636 BranchDelayInstructionDecode(branch_delay_instr);
2637 set_register(return_addr_reg,
2638 current_pc + 2 * Instruction::kInstrSize);
2639 set_pc(next_pc);
2640 pc_modified_ = true;
2641 break;
2642 }
2643 // Instructions using HI and LO registers.
2644 case MULT:
2645 if (kArchVariant != kMips64r6) {
2646 set_register(LO, static_cast<int32_t>(i64hilo & 0xffffffff));
2647 set_register(HI, static_cast<int32_t>(i64hilo >> 32));
2648 } else {
2649 switch (instr->SaValue()) {
2650 case MUL_OP:
2651 set_register(rd_reg,
2652 static_cast<int32_t>(i64hilo & 0xffffffff));
2653 break;
2654 case MUH_OP:
2655 set_register(rd_reg, static_cast<int32_t>(i64hilo >> 32));
2656 break;
2657 default:
2658 UNIMPLEMENTED_MIPS();
2659 break;
2660 }
2661 }
2662 break;
2663 case MULTU:
2664 set_register(LO, static_cast<int32_t>(u64hilo & 0xffffffff));
2665 set_register(HI, static_cast<int32_t>(u64hilo >> 32));
2666 break;
2667 case DMULT: // DMULT == D_MUL_MUH.
2668 if (kArchVariant != kMips64r6) {
2669 set_register(LO, static_cast<int64_t>(i128resultL));
2670 set_register(HI, static_cast<int64_t>(i128resultH));
2671 } else {
2672 switch (instr->SaValue()) {
2673 case MUL_OP:
2674 set_register(rd_reg, static_cast<int64_t>(i128resultL));
2675 break;
2676 case MUH_OP:
2677 set_register(rd_reg, static_cast<int64_t>(i128resultH));
2678 break;
2679 default:
2680 UNIMPLEMENTED_MIPS();
2681 break;
2682 }
2683 }
2684 break;
2685 case DMULTU:
2686 UNIMPLEMENTED_MIPS();
2687 break;
2688 case DSLL:
2689 set_register(rd_reg, alu_out);
2690 break;
2691 case DIV:
2692 case DDIV:
2693 switch (kArchVariant) {
2694 case kMips64r2:
2695 // Divide by zero and overflow was not checked in the
2696 // configuration step - div and divu do not raise exceptions. On
2697 // division by 0 the result will be UNPREDICTABLE. On overflow
2698 // (INT_MIN/-1), return INT_MIN which is what the hardware does.
2699 if (rs == INT_MIN && rt == -1) {
2700 set_register(LO, INT_MIN);
2701 set_register(HI, 0);
2702 } else if (rt != 0) {
2703 set_register(LO, rs / rt);
2704 set_register(HI, rs % rt);
2705 }
2706 break;
2707 case kMips64r6:
2708 switch (instr->SaValue()) {
2709 case DIV_OP:
2710 if (rs == INT_MIN && rt == -1) {
2711 set_register(rd_reg, INT_MIN);
2712 } else if (rt != 0) {
2713 set_register(rd_reg, rs / rt);
2714 }
2715 break;
2716 case MOD_OP:
2717 if (rs == INT_MIN && rt == -1) {
2718 set_register(rd_reg, 0);
2719 } else if (rt != 0) {
2720 set_register(rd_reg, rs % rt);
2721 }
2722 break;
2723 default:
2724 UNIMPLEMENTED_MIPS();
2725 break;
2726 }
2727 break;
2728 default:
2729 break;
2730 }
2731 break;
2732 case DIVU:
2733 if (rt_u != 0) {
2734 set_register(LO, rs_u / rt_u);
2735 set_register(HI, rs_u % rt_u);
2736 }
2737 break;
2738 // Break and trap instructions.
2739 case BREAK:
2740 case TGE:
2741 case TGEU:
2742 case TLT:
2743 case TLTU:
2744 case TEQ:
2745 case TNE:
2746 if (do_interrupt) {
2747 SoftwareInterrupt(instr);
2748 }
2749 break;
2750 // Conditional moves.
2751 case MOVN:
2752 if (rt) {
2753 set_register(rd_reg, rs);
2754 TraceRegWr(rs);
2755 }
2756 break;
2757 case MOVCI: {
2758 uint32_t cc = instr->FBccValue();
2759 uint32_t fcsr_cc = get_fcsr_condition_bit(cc);
2760 if (instr->Bit(16)) { // Read Tf bit.
2761 if (test_fcsr_bit(fcsr_cc)) set_register(rd_reg, rs);
2762 } else {
2763 if (!test_fcsr_bit(fcsr_cc)) set_register(rd_reg, rs);
2764 }
2765 break;
2766 }
2767 case MOVZ:
2768 if (!rt) {
2769 set_register(rd_reg, rs);
2770 TraceRegWr(rs);
2771 }
2772 break;
2773 default: // For other special opcodes we do the default operation.
2774 set_register(rd_reg, alu_out);
2775 TraceRegWr(alu_out);
2776 }
2777 break; 2892 break;
2778 case SPECIAL2: 2893 case SPECIAL2:
2779 switch (instr->FunctionFieldRaw()) { 2894 DecodeTypeRegisterSPECIAL2(instr, rd_reg, alu_out);
2780 case MUL:
2781 set_register(rd_reg, alu_out);
2782 TraceRegWr(alu_out);
2783 // HI and LO are UNPREDICTABLE after the operation.
2784 set_register(LO, Unpredictable);
2785 set_register(HI, Unpredictable);
2786 break;
2787 default: // For other special2 opcodes we do the default operation.
2788 set_register(rd_reg, alu_out);
2789 }
2790 break; 2895 break;
2791 case SPECIAL3: 2896 case SPECIAL3:
2792 switch (instr->FunctionFieldRaw()) { 2897 DecodeTypeRegisterSPECIAL3(instr, rt_reg, alu_out);
2793 case INS:
2794 // Ins instr leaves result in Rt, rather than Rd.
2795 set_register(rt_reg, alu_out);
2796 TraceRegWr(alu_out);
2797 break;
2798 case EXT:
2799 case DEXT:
2800 // Dext/Ext instr leaves result in Rt, rather than Rd.
2801 set_register(rt_reg, alu_out);
2802 TraceRegWr(alu_out);
2803 break;
2804 default:
2805 UNREACHABLE();
2806 }
2807 break; 2898 break;
2808 // Unimplemented opcodes raised an error in the configuration step before, 2899 // Unimplemented opcodes raised an error in the configuration step before,
2809 // so we can use the default here to set the destination register in common 2900 // so we can use the default here to set the destination register in common
2810 // cases. 2901 // cases.
2811 default: 2902 default:
2812 set_register(rd_reg, alu_out); 2903 set_register(rd_reg, alu_out);
2813 TraceRegWr(alu_out); 2904 TraceRegWr(alu_out);
2814 } 2905 }
2815 } 2906 }
2816 2907
(...skipping 633 matching lines...) Expand 10 before | Expand all | Expand 10 after
3450 } 3541 }
3451 3542
3452 3543
3453 #undef UNSUPPORTED 3544 #undef UNSUPPORTED
3454 3545
3455 } } // namespace v8::internal 3546 } } // namespace v8::internal
3456 3547
3457 #endif // USE_SIMULATOR 3548 #endif // USE_SIMULATOR
3458 3549
3459 #endif // V8_TARGET_ARCH_MIPS64 3550 #endif // V8_TARGET_ARCH_MIPS64
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698