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