| 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 #if V8_TARGET_ARCH_MIPS64 | 10 #if V8_TARGET_ARCH_MIPS64 |
| (...skipping 1608 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1619 // TODO(plind): refactor this messy debug code when we do unaligned access. | 1619 // TODO(plind): refactor this messy debug code when we do unaligned access. |
| 1620 void Simulator::DieOrDebug() { | 1620 void Simulator::DieOrDebug() { |
| 1621 if (1) { // Flag for this was removed. | 1621 if (1) { // Flag for this was removed. |
| 1622 MipsDebugger dbg(this); | 1622 MipsDebugger dbg(this); |
| 1623 dbg.Debug(); | 1623 dbg.Debug(); |
| 1624 } else { | 1624 } else { |
| 1625 base::OS::Abort(); | 1625 base::OS::Abort(); |
| 1626 } | 1626 } |
| 1627 } | 1627 } |
| 1628 | 1628 |
| 1629 void Simulator::TraceRegWr(int64_t value, TraceType t) { |
| 1630 if (::v8::internal::FLAG_trace_sim) { |
| 1631 union { |
| 1632 int64_t fmt_int64; |
| 1633 int32_t fmt_int32[2]; |
| 1634 float fmt_float[2]; |
| 1635 double fmt_double; |
| 1636 } v; |
| 1637 v.fmt_int64 = value; |
| 1629 | 1638 |
| 1630 void Simulator::TraceRegWr(int64_t value) { | 1639 switch (t) { |
| 1631 if (::v8::internal::FLAG_trace_sim) { | 1640 case WORD: |
| 1632 SNPrintF(trace_buf_, "%016" PRIx64 " ", value); | 1641 SNPrintF(trace_buf_, "%016" PRIx64 " (%" PRId64 ") int32:%" PRId32 |
| 1642 " uint32:%" PRIu32, |
| 1643 v.fmt_int64, icount_, v.fmt_int32[0], v.fmt_int32[0]); |
| 1644 break; |
| 1645 case DWORD: |
| 1646 SNPrintF(trace_buf_, "%016" PRIx64 " (%" PRId64 ") int64:%" PRId64 |
| 1647 " uint64:%" PRIu64, |
| 1648 value, icount_, value, value); |
| 1649 break; |
| 1650 case FLOAT: |
| 1651 SNPrintF(trace_buf_, "%016" PRIx64 " (%" PRId64 ") flt:%e", |
| 1652 v.fmt_int64, icount_, v.fmt_float[0]); |
| 1653 break; |
| 1654 case DOUBLE: |
| 1655 SNPrintF(trace_buf_, "%016" PRIx64 " (%" PRId64 ") dbl:%e", |
| 1656 v.fmt_int64, icount_, v.fmt_double); |
| 1657 break; |
| 1658 case FLOAT_DOUBLE: |
| 1659 SNPrintF(trace_buf_, "%016" PRIx64 " (%" PRId64 ") flt:%e dbl:%e", |
| 1660 v.fmt_int64, icount_, v.fmt_float[0], v.fmt_double); |
| 1661 break; |
| 1662 case WORD_DWORD: |
| 1663 SNPrintF(trace_buf_, |
| 1664 "%016" PRIx64 " (%" PRId64 ") int32:%" PRId32 |
| 1665 " uint32:%" PRIu32 " int64:%" PRId64 " uint64:%" PRIu64, |
| 1666 v.fmt_int64, icount_, v.fmt_int32[0], v.fmt_int32[0], |
| 1667 v.fmt_int64, v.fmt_int64); |
| 1668 break; |
| 1669 default: |
| 1670 UNREACHABLE(); |
| 1671 } |
| 1633 } | 1672 } |
| 1634 } | 1673 } |
| 1635 | 1674 |
| 1675 // TODO(plind): consider making icount_ printing a flag option. |
| 1676 void Simulator::TraceMemRd(int64_t addr, int64_t value, TraceType t) { |
| 1677 if (::v8::internal::FLAG_trace_sim) { |
| 1678 union { |
| 1679 int64_t fmt_int64; |
| 1680 int32_t fmt_int32[2]; |
| 1681 float fmt_float[2]; |
| 1682 double fmt_double; |
| 1683 } v; |
| 1684 v.fmt_int64 = value; |
| 1636 | 1685 |
| 1637 // TODO(plind): consider making icount_ printing a flag option. | 1686 switch (t) { |
| 1638 void Simulator::TraceMemRd(int64_t addr, int64_t value) { | 1687 case WORD: |
| 1639 if (::v8::internal::FLAG_trace_sim) { | 1688 SNPrintF(trace_buf_, "%016" PRIx64 " <-- [%016" PRIx64 "] (%" PRId64 |
| 1640 SNPrintF(trace_buf_, | 1689 ") int32:%" PRId32 " uint32:%" PRIu32, |
| 1641 "%016" PRIx64 " <-- [%016" PRIx64 " ] (%" PRId64 " )", value, | 1690 v.fmt_int64, addr, icount_, v.fmt_int32[0], v.fmt_int32[0]); |
| 1642 addr, icount_); | 1691 break; |
| 1692 case DWORD: |
| 1693 SNPrintF(trace_buf_, "%016" PRIx64 " <-- [%016" PRIx64 "] (%" PRId64 |
| 1694 ") int64:%" PRId64 " uint64:%" PRIu64, |
| 1695 value, addr, icount_, value, value); |
| 1696 break; |
| 1697 case FLOAT: |
| 1698 SNPrintF(trace_buf_, "%016" PRIx64 " <-- [%016" PRIx64 "] (%" PRId64 |
| 1699 ") flt:%e", |
| 1700 v.fmt_int64, addr, icount_, v.fmt_float[0]); |
| 1701 break; |
| 1702 case DOUBLE: |
| 1703 SNPrintF(trace_buf_, "%016" PRIx64 " <-- [%016" PRIx64 "] (%" PRId64 |
| 1704 ") dbl:%e", |
| 1705 v.fmt_int64, addr, icount_, v.fmt_double); |
| 1706 break; |
| 1707 case FLOAT_DOUBLE: |
| 1708 SNPrintF(trace_buf_, "%016" PRIx64 " <-- [%016" PRIx64 "] (%" PRId64 |
| 1709 ") flt:%e dbl:%e", |
| 1710 v.fmt_int64, addr, icount_, v.fmt_float[0], v.fmt_double); |
| 1711 break; |
| 1712 default: |
| 1713 UNREACHABLE(); |
| 1714 } |
| 1643 } | 1715 } |
| 1644 } | 1716 } |
| 1645 | 1717 |
| 1646 | 1718 |
| 1647 void Simulator::TraceMemWr(int64_t addr, int64_t value, TraceType t) { | 1719 void Simulator::TraceMemWr(int64_t addr, int64_t value, TraceType t) { |
| 1648 if (::v8::internal::FLAG_trace_sim) { | 1720 if (::v8::internal::FLAG_trace_sim) { |
| 1649 switch (t) { | 1721 switch (t) { |
| 1650 case BYTE: | 1722 case BYTE: |
| 1651 SNPrintF(trace_buf_, " %02x --> [%016" PRIx64 " ]", | 1723 SNPrintF(trace_buf_, " %02" PRIx8 " --> [%016" PRIx64 |
| 1652 static_cast<int8_t>(value), addr); | 1724 "] (%" PRId64 ")", |
| 1725 static_cast<uint8_t>(value), addr, icount_); |
| 1653 break; | 1726 break; |
| 1654 case HALF: | 1727 case HALF: |
| 1655 SNPrintF(trace_buf_, " %04x --> [%016" PRIx64 " ]", | 1728 SNPrintF(trace_buf_, " %04" PRIx16 " --> [%016" PRIx64 |
| 1656 static_cast<int16_t>(value), addr); | 1729 "] (%" PRId64 ")", |
| 1730 static_cast<uint16_t>(value), addr, icount_); |
| 1657 break; | 1731 break; |
| 1658 case WORD: | 1732 case WORD: |
| 1659 SNPrintF(trace_buf_, " %08x --> [%016" PRIx64 " ]", | 1733 SNPrintF(trace_buf_, |
| 1660 static_cast<int32_t>(value), addr); | 1734 " %08" PRIx32 " --> [%016" PRIx64 "] (%" PRId64 ")", |
| 1735 static_cast<uint32_t>(value), addr, icount_); |
| 1661 break; | 1736 break; |
| 1662 case DWORD: | 1737 case DWORD: |
| 1663 SNPrintF(trace_buf_, | 1738 SNPrintF(trace_buf_, |
| 1664 "%016" PRIx64 " --> [%016" PRIx64 " ] (%" PRId64 " )", | 1739 "%016" PRIx64 " --> [%016" PRIx64 "] (%" PRId64 " )", |
| 1665 value, addr, icount_); | 1740 value, addr, icount_); |
| 1666 break; | 1741 break; |
| 1742 default: |
| 1743 UNREACHABLE(); |
| 1667 } | 1744 } |
| 1668 } | 1745 } |
| 1669 } | 1746 } |
| 1670 | 1747 |
| 1671 | 1748 |
| 1672 // TODO(plind): sign-extend and zero-extend not implmented properly | 1749 // TODO(plind): sign-extend and zero-extend not implmented properly |
| 1673 // on all the ReadXX functions, I don't think re-interpret cast does it. | 1750 // on all the ReadXX functions, I don't think re-interpret cast does it. |
| 1674 int32_t Simulator::ReadW(int64_t addr, Instruction* instr) { | 1751 int32_t Simulator::ReadW(int64_t addr, Instruction* instr, TraceType t) { |
| 1675 if (addr >=0 && addr < 0x400) { | 1752 if (addr >=0 && addr < 0x400) { |
| 1676 // This has to be a NULL-dereference, drop into debugger. | 1753 // This has to be a NULL-dereference, drop into debugger. |
| 1677 PrintF("Memory read from bad address: 0x%08" PRIx64 " , pc=0x%08" PRIxPTR | 1754 PrintF("Memory read from bad address: 0x%08" PRIx64 " , pc=0x%08" PRIxPTR |
| 1678 " \n", | 1755 " \n", |
| 1679 addr, reinterpret_cast<intptr_t>(instr)); | 1756 addr, reinterpret_cast<intptr_t>(instr)); |
| 1680 DieOrDebug(); | 1757 DieOrDebug(); |
| 1681 } | 1758 } |
| 1682 if ((addr & 0x3) == 0 || kArchVariant == kMips64r6) { | 1759 if ((addr & 0x3) == 0 || kArchVariant == kMips64r6) { |
| 1683 int32_t* ptr = reinterpret_cast<int32_t*>(addr); | 1760 int32_t* ptr = reinterpret_cast<int32_t*>(addr); |
| 1684 TraceMemRd(addr, static_cast<int64_t>(*ptr)); | 1761 TraceMemRd(addr, static_cast<int64_t>(*ptr), t); |
| 1685 return *ptr; | 1762 return *ptr; |
| 1686 } | 1763 } |
| 1687 PrintF("Unaligned read at 0x%08" PRIx64 " , pc=0x%08" V8PRIxPTR "\n", addr, | 1764 PrintF("Unaligned read at 0x%08" PRIx64 " , pc=0x%08" V8PRIxPTR "\n", addr, |
| 1688 reinterpret_cast<intptr_t>(instr)); | 1765 reinterpret_cast<intptr_t>(instr)); |
| 1689 DieOrDebug(); | 1766 DieOrDebug(); |
| 1690 return 0; | 1767 return 0; |
| 1691 } | 1768 } |
| 1692 | 1769 |
| 1693 | 1770 |
| 1694 uint32_t Simulator::ReadWU(int64_t addr, Instruction* instr) { | 1771 uint32_t Simulator::ReadWU(int64_t addr, Instruction* instr) { |
| 1695 if (addr >=0 && addr < 0x400) { | 1772 if (addr >=0 && addr < 0x400) { |
| 1696 // This has to be a NULL-dereference, drop into debugger. | 1773 // This has to be a NULL-dereference, drop into debugger. |
| 1697 PrintF("Memory read from bad address: 0x%08" PRIx64 " , pc=0x%08" PRIxPTR | 1774 PrintF("Memory read from bad address: 0x%08" PRIx64 " , pc=0x%08" PRIxPTR |
| 1698 " \n", | 1775 " \n", |
| 1699 addr, reinterpret_cast<intptr_t>(instr)); | 1776 addr, reinterpret_cast<intptr_t>(instr)); |
| 1700 DieOrDebug(); | 1777 DieOrDebug(); |
| 1701 } | 1778 } |
| 1702 if ((addr & 0x3) == 0 || kArchVariant == kMips64r6) { | 1779 if ((addr & 0x3) == 0 || kArchVariant == kMips64r6) { |
| 1703 uint32_t* ptr = reinterpret_cast<uint32_t*>(addr); | 1780 uint32_t* ptr = reinterpret_cast<uint32_t*>(addr); |
| 1704 TraceMemRd(addr, static_cast<int64_t>(*ptr)); | 1781 TraceMemRd(addr, static_cast<int64_t>(*ptr), WORD); |
| 1705 return *ptr; | 1782 return *ptr; |
| 1706 } | 1783 } |
| 1707 PrintF("Unaligned read at 0x%08" PRIx64 " , pc=0x%08" V8PRIxPTR "\n", addr, | 1784 PrintF("Unaligned read at 0x%08" PRIx64 " , pc=0x%08" V8PRIxPTR "\n", addr, |
| 1708 reinterpret_cast<intptr_t>(instr)); | 1785 reinterpret_cast<intptr_t>(instr)); |
| 1709 DieOrDebug(); | 1786 DieOrDebug(); |
| 1710 return 0; | 1787 return 0; |
| 1711 } | 1788 } |
| 1712 | 1789 |
| 1713 | 1790 |
| 1714 void Simulator::WriteW(int64_t addr, int32_t value, Instruction* instr) { | 1791 void Simulator::WriteW(int64_t addr, int32_t value, Instruction* instr) { |
| (...skipping 733 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2448 case kRoundToZero: | 2525 case kRoundToZero: |
| 2449 result = (fs > 0 ? lower : upper); | 2526 result = (fs > 0 ? lower : upper); |
| 2450 break; | 2527 break; |
| 2451 case kRoundToPlusInf: | 2528 case kRoundToPlusInf: |
| 2452 result = upper; | 2529 result = upper; |
| 2453 break; | 2530 break; |
| 2454 case kRoundToMinusInf: | 2531 case kRoundToMinusInf: |
| 2455 result = lower; | 2532 result = lower; |
| 2456 break; | 2533 break; |
| 2457 } | 2534 } |
| 2458 set_fpu_register_float(fd_reg(), result); | 2535 SetFPUFloatResult(fd_reg(), result); |
| 2459 if (result != fs) { | 2536 if (result != fs) { |
| 2460 set_fcsr_bit(kFCSRInexactFlagBit, true); | 2537 set_fcsr_bit(kFCSRInexactFlagBit, true); |
| 2461 } | 2538 } |
| 2462 break; | 2539 break; |
| 2463 } | 2540 } |
| 2464 case ADD_S: | 2541 case ADD_S: |
| 2465 set_fpu_register_float( | 2542 SetFPUFloatResult( |
| 2466 fd_reg(), | 2543 fd_reg(), |
| 2467 FPUCanonalizeOperation([](float lhs, float rhs) { return lhs + rhs; }, | 2544 FPUCanonalizeOperation([](float lhs, float rhs) { return lhs + rhs; }, |
| 2468 fs, ft)); | 2545 fs, ft)); |
| 2469 break; | 2546 break; |
| 2470 case SUB_S: | 2547 case SUB_S: |
| 2471 set_fpu_register_float( | 2548 SetFPUFloatResult( |
| 2472 fd_reg(), | 2549 fd_reg(), |
| 2473 FPUCanonalizeOperation([](float lhs, float rhs) { return lhs - rhs; }, | 2550 FPUCanonalizeOperation([](float lhs, float rhs) { return lhs - rhs; }, |
| 2474 fs, ft)); | 2551 fs, ft)); |
| 2475 break; | 2552 break; |
| 2476 case MADDF_S: | 2553 case MADDF_S: |
| 2477 DCHECK(kArchVariant == kMips64r6); | 2554 DCHECK(kArchVariant == kMips64r6); |
| 2478 set_fpu_register_float(fd_reg(), std::fma(fs, ft, fd)); | 2555 SetFPUFloatResult(fd_reg(), std::fma(fs, ft, fd)); |
| 2479 break; | 2556 break; |
| 2480 case MSUBF_S: | 2557 case MSUBF_S: |
| 2481 DCHECK(kArchVariant == kMips64r6); | 2558 DCHECK(kArchVariant == kMips64r6); |
| 2482 set_fpu_register_float(fd_reg(), std::fma(-fs, ft, fd)); | 2559 SetFPUFloatResult(fd_reg(), std::fma(-fs, ft, fd)); |
| 2483 break; | 2560 break; |
| 2484 case MUL_S: | 2561 case MUL_S: |
| 2485 set_fpu_register_float( | 2562 SetFPUFloatResult( |
| 2486 fd_reg(), | 2563 fd_reg(), |
| 2487 FPUCanonalizeOperation([](float lhs, float rhs) { return lhs * rhs; }, | 2564 FPUCanonalizeOperation([](float lhs, float rhs) { return lhs * rhs; }, |
| 2488 fs, ft)); | 2565 fs, ft)); |
| 2489 break; | 2566 break; |
| 2490 case DIV_S: | 2567 case DIV_S: |
| 2491 set_fpu_register_float( | 2568 SetFPUFloatResult( |
| 2492 fd_reg(), | 2569 fd_reg(), |
| 2493 FPUCanonalizeOperation([](float lhs, float rhs) { return lhs / rhs; }, | 2570 FPUCanonalizeOperation([](float lhs, float rhs) { return lhs / rhs; }, |
| 2494 fs, ft)); | 2571 fs, ft)); |
| 2495 break; | 2572 break; |
| 2496 case ABS_S: | 2573 case ABS_S: |
| 2497 set_fpu_register_float( | 2574 SetFPUFloatResult(fd_reg(), FPUCanonalizeOperation( |
| 2498 fd_reg(), | 2575 [](float fs) { return FPAbs(fs); }, fs)); |
| 2499 FPUCanonalizeOperation([](float fs) { return FPAbs(fs); }, fs)); | |
| 2500 break; | 2576 break; |
| 2501 case MOV_S: | 2577 case MOV_S: |
| 2502 set_fpu_register_float(fd_reg(), fs); | 2578 SetFPUFloatResult(fd_reg(), fs); |
| 2503 break; | 2579 break; |
| 2504 case NEG_S: | 2580 case NEG_S: |
| 2505 set_fpu_register_float( | 2581 SetFPUFloatResult(fd_reg(), |
| 2506 fd_reg(), FPUCanonalizeOperation([](float src) { return -src; }, | 2582 FPUCanonalizeOperation([](float src) { return -src; }, |
| 2507 KeepSign::yes, fs)); | 2583 KeepSign::yes, fs)); |
| 2508 break; | 2584 break; |
| 2509 case SQRT_S: | 2585 case SQRT_S: |
| 2510 set_fpu_register_float( | 2586 SetFPUFloatResult( |
| 2511 fd_reg(), | 2587 fd_reg(), |
| 2512 FPUCanonalizeOperation([](float src) { return std::sqrt(src); }, fs)); | 2588 FPUCanonalizeOperation([](float src) { return std::sqrt(src); }, fs)); |
| 2513 break; | 2589 break; |
| 2514 case RSQRT_S: | 2590 case RSQRT_S: |
| 2515 set_fpu_register_float( | 2591 SetFPUFloatResult( |
| 2516 fd_reg(), FPUCanonalizeOperation( | 2592 fd_reg(), FPUCanonalizeOperation( |
| 2517 [](float src) { return 1.0 / std::sqrt(src); }, fs)); | 2593 [](float src) { return 1.0 / std::sqrt(src); }, fs)); |
| 2518 break; | 2594 break; |
| 2519 case RECIP_S: | 2595 case RECIP_S: |
| 2520 set_fpu_register_float( | 2596 SetFPUFloatResult(fd_reg(), FPUCanonalizeOperation( |
| 2521 fd_reg(), | 2597 [](float src) { return 1.0 / src; }, fs)); |
| 2522 FPUCanonalizeOperation([](float src) { return 1.0 / src; }, fs)); | |
| 2523 break; | 2598 break; |
| 2524 case C_F_D: | 2599 case C_F_D: |
| 2525 set_fcsr_bit(fcsr_cc, false); | 2600 set_fcsr_bit(fcsr_cc, false); |
| 2601 TraceRegWr(test_fcsr_bit(fcsr_cc)); |
| 2526 break; | 2602 break; |
| 2527 case C_UN_D: | 2603 case C_UN_D: |
| 2528 set_fcsr_bit(fcsr_cc, std::isnan(fs) || std::isnan(ft)); | 2604 set_fcsr_bit(fcsr_cc, std::isnan(fs) || std::isnan(ft)); |
| 2605 TraceRegWr(test_fcsr_bit(fcsr_cc)); |
| 2529 break; | 2606 break; |
| 2530 case C_EQ_D: | 2607 case C_EQ_D: |
| 2531 set_fcsr_bit(fcsr_cc, (fs == ft)); | 2608 set_fcsr_bit(fcsr_cc, (fs == ft)); |
| 2609 TraceRegWr(test_fcsr_bit(fcsr_cc)); |
| 2532 break; | 2610 break; |
| 2533 case C_UEQ_D: | 2611 case C_UEQ_D: |
| 2534 set_fcsr_bit(fcsr_cc, (fs == ft) || (std::isnan(fs) || std::isnan(ft))); | 2612 set_fcsr_bit(fcsr_cc, (fs == ft) || (std::isnan(fs) || std::isnan(ft))); |
| 2613 TraceRegWr(test_fcsr_bit(fcsr_cc)); |
| 2535 break; | 2614 break; |
| 2536 case C_OLT_D: | 2615 case C_OLT_D: |
| 2537 set_fcsr_bit(fcsr_cc, (fs < ft)); | 2616 set_fcsr_bit(fcsr_cc, (fs < ft)); |
| 2617 TraceRegWr(test_fcsr_bit(fcsr_cc)); |
| 2538 break; | 2618 break; |
| 2539 case C_ULT_D: | 2619 case C_ULT_D: |
| 2540 set_fcsr_bit(fcsr_cc, (fs < ft) || (std::isnan(fs) || std::isnan(ft))); | 2620 set_fcsr_bit(fcsr_cc, (fs < ft) || (std::isnan(fs) || std::isnan(ft))); |
| 2621 TraceRegWr(test_fcsr_bit(fcsr_cc)); |
| 2541 break; | 2622 break; |
| 2542 case C_OLE_D: | 2623 case C_OLE_D: |
| 2543 set_fcsr_bit(fcsr_cc, (fs <= ft)); | 2624 set_fcsr_bit(fcsr_cc, (fs <= ft)); |
| 2625 TraceRegWr(test_fcsr_bit(fcsr_cc)); |
| 2544 break; | 2626 break; |
| 2545 case C_ULE_D: | 2627 case C_ULE_D: |
| 2546 set_fcsr_bit(fcsr_cc, (fs <= ft) || (std::isnan(fs) || std::isnan(ft))); | 2628 set_fcsr_bit(fcsr_cc, (fs <= ft) || (std::isnan(fs) || std::isnan(ft))); |
| 2629 TraceRegWr(test_fcsr_bit(fcsr_cc)); |
| 2547 break; | 2630 break; |
| 2548 case CVT_D_S: | 2631 case CVT_D_S: |
| 2549 set_fpu_register_double(fd_reg(), static_cast<double>(fs)); | 2632 SetFPUDoubleResult(fd_reg(), static_cast<double>(fs)); |
| 2550 break; | 2633 break; |
| 2551 case CLASS_S: { // Mips64r6 instruction | 2634 case CLASS_S: { // Mips64r6 instruction |
| 2552 // Convert float input to uint32_t for easier bit manipulation | 2635 // Convert float input to uint32_t for easier bit manipulation |
| 2553 uint32_t classed = bit_cast<uint32_t>(fs); | 2636 uint32_t classed = bit_cast<uint32_t>(fs); |
| 2554 | 2637 |
| 2555 // Extracting sign, exponent and mantissa from the input float | 2638 // Extracting sign, exponent and mantissa from the input float |
| 2556 uint32_t sign = (classed >> 31) & 1; | 2639 uint32_t sign = (classed >> 31) & 1; |
| 2557 uint32_t exponent = (classed >> 23) & 0x000000ff; | 2640 uint32_t exponent = (classed >> 23) & 0x000000ff; |
| 2558 uint32_t mantissa = classed & 0x007fffff; | 2641 uint32_t mantissa = classed & 0x007fffff; |
| 2559 uint32_t result; | 2642 uint32_t result; |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2602 } | 2685 } |
| 2603 | 2686 |
| 2604 // Calculating result according to description of CLASS.S instruction | 2687 // Calculating result according to description of CLASS.S instruction |
| 2605 result = (posZero << 9) | (posSubnorm << 8) | (posNorm << 7) | | 2688 result = (posZero << 9) | (posSubnorm << 8) | (posNorm << 7) | |
| 2606 (posInf << 6) | (negZero << 5) | (negSubnorm << 4) | | 2689 (posInf << 6) | (negZero << 5) | (negSubnorm << 4) | |
| 2607 (negNorm << 3) | (negInf << 2) | (quietNan << 1) | signalingNan; | 2690 (negNorm << 3) | (negInf << 2) | (quietNan << 1) | signalingNan; |
| 2608 | 2691 |
| 2609 DCHECK(result != 0); | 2692 DCHECK(result != 0); |
| 2610 | 2693 |
| 2611 fResult = bit_cast<float>(result); | 2694 fResult = bit_cast<float>(result); |
| 2612 set_fpu_register_float(fd_reg(), fResult); | 2695 SetFPUFloatResult(fd_reg(), fResult); |
| 2613 | |
| 2614 break; | 2696 break; |
| 2615 } | 2697 } |
| 2616 case CVT_L_S: { | 2698 case CVT_L_S: { |
| 2617 float rounded; | 2699 float rounded; |
| 2618 int64_t result; | 2700 int64_t result; |
| 2619 round64_according_to_fcsr(fs, rounded, result, fs); | 2701 round64_according_to_fcsr(fs, rounded, result, fs); |
| 2620 set_fpu_register(fd_reg(), result); | 2702 SetFPUResult(fd_reg(), result); |
| 2621 if (set_fcsr_round64_error(fs, rounded)) { | 2703 if (set_fcsr_round64_error(fs, rounded)) { |
| 2622 set_fpu_register_invalid_result64(fs, rounded); | 2704 set_fpu_register_invalid_result64(fs, rounded); |
| 2623 } | 2705 } |
| 2624 break; | 2706 break; |
| 2625 } | 2707 } |
| 2626 case CVT_W_S: { | 2708 case CVT_W_S: { |
| 2627 float rounded; | 2709 float rounded; |
| 2628 int32_t result; | 2710 int32_t result; |
| 2629 round_according_to_fcsr(fs, rounded, result, fs); | 2711 round_according_to_fcsr(fs, rounded, result, fs); |
| 2630 set_fpu_register_word(fd_reg(), result); | 2712 SetFPUWordResult(fd_reg(), result); |
| 2631 if (set_fcsr_round_error(fs, rounded)) { | 2713 if (set_fcsr_round_error(fs, rounded)) { |
| 2632 set_fpu_register_word_invalid_result(fs, rounded); | 2714 set_fpu_register_word_invalid_result(fs, rounded); |
| 2633 } | 2715 } |
| 2634 break; | 2716 break; |
| 2635 } | 2717 } |
| 2636 case TRUNC_W_S: { // Truncate single to word (round towards 0). | 2718 case TRUNC_W_S: { // Truncate single to word (round towards 0). |
| 2637 float rounded = trunc(fs); | 2719 float rounded = trunc(fs); |
| 2638 int32_t result = static_cast<int32_t>(rounded); | 2720 int32_t result = static_cast<int32_t>(rounded); |
| 2639 set_fpu_register_word(fd_reg(), result); | 2721 SetFPUWordResult(fd_reg(), result); |
| 2640 if (set_fcsr_round_error(fs, rounded)) { | 2722 if (set_fcsr_round_error(fs, rounded)) { |
| 2641 set_fpu_register_word_invalid_result(fs, rounded); | 2723 set_fpu_register_word_invalid_result(fs, rounded); |
| 2642 } | 2724 } |
| 2643 } break; | 2725 } break; |
| 2644 case TRUNC_L_S: { // Mips64r2 instruction. | 2726 case TRUNC_L_S: { // Mips64r2 instruction. |
| 2645 float rounded = trunc(fs); | 2727 float rounded = trunc(fs); |
| 2646 int64_t result = static_cast<int64_t>(rounded); | 2728 int64_t result = static_cast<int64_t>(rounded); |
| 2647 set_fpu_register(fd_reg(), result); | 2729 SetFPUResult(fd_reg(), result); |
| 2648 if (set_fcsr_round64_error(fs, rounded)) { | 2730 if (set_fcsr_round64_error(fs, rounded)) { |
| 2649 set_fpu_register_invalid_result64(fs, rounded); | 2731 set_fpu_register_invalid_result64(fs, rounded); |
| 2650 } | 2732 } |
| 2651 break; | 2733 break; |
| 2652 } | 2734 } |
| 2653 case ROUND_W_S: { | 2735 case ROUND_W_S: { |
| 2654 float rounded = std::floor(fs + 0.5); | 2736 float rounded = std::floor(fs + 0.5); |
| 2655 int32_t result = static_cast<int32_t>(rounded); | 2737 int32_t result = static_cast<int32_t>(rounded); |
| 2656 if ((result & 1) != 0 && result - fs == 0.5) { | 2738 if ((result & 1) != 0 && result - fs == 0.5) { |
| 2657 // If the number is halfway between two integers, | 2739 // If the number is halfway between two integers, |
| 2658 // round to the even one. | 2740 // round to the even one. |
| 2659 result--; | 2741 result--; |
| 2660 } | 2742 } |
| 2661 set_fpu_register_word(fd_reg(), result); | 2743 SetFPUWordResult(fd_reg(), result); |
| 2662 if (set_fcsr_round_error(fs, rounded)) { | 2744 if (set_fcsr_round_error(fs, rounded)) { |
| 2663 set_fpu_register_word_invalid_result(fs, rounded); | 2745 set_fpu_register_word_invalid_result(fs, rounded); |
| 2664 } | 2746 } |
| 2665 break; | 2747 break; |
| 2666 } | 2748 } |
| 2667 case ROUND_L_S: { // Mips64r2 instruction. | 2749 case ROUND_L_S: { // Mips64r2 instruction. |
| 2668 float rounded = std::floor(fs + 0.5); | 2750 float rounded = std::floor(fs + 0.5); |
| 2669 int64_t result = static_cast<int64_t>(rounded); | 2751 int64_t result = static_cast<int64_t>(rounded); |
| 2670 if ((result & 1) != 0 && result - fs == 0.5) { | 2752 if ((result & 1) != 0 && result - fs == 0.5) { |
| 2671 // If the number is halfway between two integers, | 2753 // If the number is halfway between two integers, |
| 2672 // round to the even one. | 2754 // round to the even one. |
| 2673 result--; | 2755 result--; |
| 2674 } | 2756 } |
| 2675 int64_t i64 = static_cast<int64_t>(result); | 2757 int64_t i64 = static_cast<int64_t>(result); |
| 2676 set_fpu_register(fd_reg(), i64); | 2758 SetFPUResult(fd_reg(), i64); |
| 2677 if (set_fcsr_round64_error(fs, rounded)) { | 2759 if (set_fcsr_round64_error(fs, rounded)) { |
| 2678 set_fpu_register_invalid_result64(fs, rounded); | 2760 set_fpu_register_invalid_result64(fs, rounded); |
| 2679 } | 2761 } |
| 2680 break; | 2762 break; |
| 2681 } | 2763 } |
| 2682 case FLOOR_L_S: { // Mips64r2 instruction. | 2764 case FLOOR_L_S: { // Mips64r2 instruction. |
| 2683 float rounded = floor(fs); | 2765 float rounded = floor(fs); |
| 2684 int64_t result = static_cast<int64_t>(rounded); | 2766 int64_t result = static_cast<int64_t>(rounded); |
| 2685 set_fpu_register(fd_reg(), result); | 2767 SetFPUResult(fd_reg(), result); |
| 2686 if (set_fcsr_round64_error(fs, rounded)) { | 2768 if (set_fcsr_round64_error(fs, rounded)) { |
| 2687 set_fpu_register_invalid_result64(fs, rounded); | 2769 set_fpu_register_invalid_result64(fs, rounded); |
| 2688 } | 2770 } |
| 2689 break; | 2771 break; |
| 2690 } | 2772 } |
| 2691 case FLOOR_W_S: // Round double to word towards negative infinity. | 2773 case FLOOR_W_S: // Round double to word towards negative infinity. |
| 2692 { | 2774 { |
| 2693 float rounded = std::floor(fs); | 2775 float rounded = std::floor(fs); |
| 2694 int32_t result = static_cast<int32_t>(rounded); | 2776 int32_t result = static_cast<int32_t>(rounded); |
| 2695 set_fpu_register_word(fd_reg(), result); | 2777 SetFPUWordResult(fd_reg(), result); |
| 2696 if (set_fcsr_round_error(fs, rounded)) { | 2778 if (set_fcsr_round_error(fs, rounded)) { |
| 2697 set_fpu_register_word_invalid_result(fs, rounded); | 2779 set_fpu_register_word_invalid_result(fs, rounded); |
| 2698 } | 2780 } |
| 2699 } break; | 2781 } break; |
| 2700 case CEIL_W_S: // Round double to word towards positive infinity. | 2782 case CEIL_W_S: // Round double to word towards positive infinity. |
| 2701 { | 2783 { |
| 2702 float rounded = std::ceil(fs); | 2784 float rounded = std::ceil(fs); |
| 2703 int32_t result = static_cast<int32_t>(rounded); | 2785 int32_t result = static_cast<int32_t>(rounded); |
| 2704 set_fpu_register_word(fd_reg(), result); | 2786 SetFPUWordResult(fd_reg(), result); |
| 2705 if (set_fcsr_round_error(fs, rounded)) { | 2787 if (set_fcsr_round_error(fs, rounded)) { |
| 2706 set_fpu_register_invalid_result(fs, rounded); | 2788 set_fpu_register_invalid_result(fs, rounded); |
| 2707 } | 2789 } |
| 2708 } break; | 2790 } break; |
| 2709 case CEIL_L_S: { // Mips64r2 instruction. | 2791 case CEIL_L_S: { // Mips64r2 instruction. |
| 2710 float rounded = ceil(fs); | 2792 float rounded = ceil(fs); |
| 2711 int64_t result = static_cast<int64_t>(rounded); | 2793 int64_t result = static_cast<int64_t>(rounded); |
| 2712 set_fpu_register(fd_reg(), result); | 2794 SetFPUResult(fd_reg(), result); |
| 2713 if (set_fcsr_round64_error(fs, rounded)) { | 2795 if (set_fcsr_round64_error(fs, rounded)) { |
| 2714 set_fpu_register_invalid_result64(fs, rounded); | 2796 set_fpu_register_invalid_result64(fs, rounded); |
| 2715 } | 2797 } |
| 2716 break; | 2798 break; |
| 2717 } | 2799 } |
| 2718 case MINA: | 2800 case MINA: |
| 2719 DCHECK(kArchVariant == kMips64r6); | 2801 DCHECK(kArchVariant == kMips64r6); |
| 2720 set_fpu_register_float(fd_reg(), FPUMinA(ft, fs)); | 2802 SetFPUFloatResult(fd_reg(), FPUMinA(ft, fs)); |
| 2721 break; | 2803 break; |
| 2722 case MAXA: | 2804 case MAXA: |
| 2723 DCHECK(kArchVariant == kMips64r6); | 2805 DCHECK(kArchVariant == kMips64r6); |
| 2724 set_fpu_register_float(fd_reg(), FPUMaxA(ft, fs)); | 2806 SetFPUFloatResult(fd_reg(), FPUMaxA(ft, fs)); |
| 2725 break; | 2807 break; |
| 2726 case MIN: | 2808 case MIN: |
| 2727 DCHECK(kArchVariant == kMips64r6); | 2809 DCHECK(kArchVariant == kMips64r6); |
| 2728 set_fpu_register_float(fd_reg(), FPUMin(ft, fs)); | 2810 SetFPUFloatResult(fd_reg(), FPUMin(ft, fs)); |
| 2729 break; | 2811 break; |
| 2730 case MAX: | 2812 case MAX: |
| 2731 DCHECK(kArchVariant == kMips64r6); | 2813 DCHECK(kArchVariant == kMips64r6); |
| 2732 set_fpu_register_float(fd_reg(), FPUMax(ft, fs)); | 2814 SetFPUFloatResult(fd_reg(), FPUMax(ft, fs)); |
| 2733 break; | 2815 break; |
| 2734 case SEL: | 2816 case SEL: |
| 2735 DCHECK(kArchVariant == kMips64r6); | 2817 DCHECK(kArchVariant == kMips64r6); |
| 2736 set_fpu_register_float(fd_reg(), (fd_int & 0x1) == 0 ? fs : ft); | 2818 SetFPUFloatResult(fd_reg(), (fd_int & 0x1) == 0 ? fs : ft); |
| 2737 break; | 2819 break; |
| 2738 case SELEQZ_C: | 2820 case SELEQZ_C: |
| 2739 DCHECK(kArchVariant == kMips64r6); | 2821 DCHECK(kArchVariant == kMips64r6); |
| 2740 set_fpu_register_float(fd_reg(), (ft_int & 0x1) == 0 | 2822 SetFPUFloatResult( |
| 2741 ? get_fpu_register_float(fs_reg()) | 2823 fd_reg(), |
| 2742 : 0.0); | 2824 (ft_int & 0x1) == 0 ? get_fpu_register_float(fs_reg()) : 0.0); |
| 2743 break; | 2825 break; |
| 2744 case SELNEZ_C: | 2826 case SELNEZ_C: |
| 2745 DCHECK(kArchVariant == kMips64r6); | 2827 DCHECK(kArchVariant == kMips64r6); |
| 2746 set_fpu_register_float(fd_reg(), (ft_int & 0x1) != 0 | 2828 SetFPUFloatResult( |
| 2747 ? get_fpu_register_float(fs_reg()) | 2829 fd_reg(), |
| 2748 : 0.0); | 2830 (ft_int & 0x1) != 0 ? get_fpu_register_float(fs_reg()) : 0.0); |
| 2749 break; | 2831 break; |
| 2750 case MOVZ_C: { | 2832 case MOVZ_C: { |
| 2751 DCHECK(kArchVariant == kMips64r2); | 2833 DCHECK(kArchVariant == kMips64r2); |
| 2752 if (rt() == 0) { | 2834 if (rt() == 0) { |
| 2753 set_fpu_register_float(fd_reg(), fs); | 2835 SetFPUFloatResult(fd_reg(), fs); |
| 2754 } | 2836 } |
| 2755 break; | 2837 break; |
| 2756 } | 2838 } |
| 2757 case MOVN_C: { | 2839 case MOVN_C: { |
| 2758 DCHECK(kArchVariant == kMips64r2); | 2840 DCHECK(kArchVariant == kMips64r2); |
| 2759 if (rt() != 0) { | 2841 if (rt() != 0) { |
| 2760 set_fpu_register_float(fd_reg(), fs); | 2842 SetFPUFloatResult(fd_reg(), fs); |
| 2761 } | 2843 } |
| 2762 break; | 2844 break; |
| 2763 } | 2845 } |
| 2764 case MOVF: { | 2846 case MOVF: { |
| 2765 // Same function field for MOVT.D and MOVF.D | 2847 // Same function field for MOVT.D and MOVF.D |
| 2766 uint32_t ft_cc = (ft_reg() >> 2) & 0x7; | 2848 uint32_t ft_cc = (ft_reg() >> 2) & 0x7; |
| 2767 ft_cc = get_fcsr_condition_bit(ft_cc); | 2849 ft_cc = get_fcsr_condition_bit(ft_cc); |
| 2768 | 2850 |
| 2769 if (instr_.Bit(16)) { // Read Tf bit. | 2851 if (instr_.Bit(16)) { // Read Tf bit. |
| 2770 // MOVT.D | 2852 // MOVT.D |
| 2771 if (test_fcsr_bit(ft_cc)) set_fpu_register_float(fd_reg(), fs); | 2853 if (test_fcsr_bit(ft_cc)) SetFPUFloatResult(fd_reg(), fs); |
| 2772 } else { | 2854 } else { |
| 2773 // MOVF.D | 2855 // MOVF.D |
| 2774 if (!test_fcsr_bit(ft_cc)) set_fpu_register_float(fd_reg(), fs); | 2856 if (!test_fcsr_bit(ft_cc)) SetFPUFloatResult(fd_reg(), fs); |
| 2775 } | 2857 } |
| 2776 break; | 2858 break; |
| 2777 } | 2859 } |
| 2778 default: | 2860 default: |
| 2779 // TRUNC_W_S ROUND_W_S ROUND_L_S FLOOR_W_S FLOOR_L_S | 2861 // TRUNC_W_S ROUND_W_S ROUND_L_S FLOOR_W_S FLOOR_L_S |
| 2780 // CEIL_W_S CEIL_L_S CVT_PS_S are unimplemented. | 2862 // CEIL_W_S CEIL_L_S CVT_PS_S are unimplemented. |
| 2781 UNREACHABLE(); | 2863 UNREACHABLE(); |
| 2782 } | 2864 } |
| 2783 } | 2865 } |
| 2784 | 2866 |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2819 case kRoundToZero: | 2901 case kRoundToZero: |
| 2820 result = (fs > 0 ? lower : upper); | 2902 result = (fs > 0 ? lower : upper); |
| 2821 break; | 2903 break; |
| 2822 case kRoundToPlusInf: | 2904 case kRoundToPlusInf: |
| 2823 result = upper; | 2905 result = upper; |
| 2824 break; | 2906 break; |
| 2825 case kRoundToMinusInf: | 2907 case kRoundToMinusInf: |
| 2826 result = lower; | 2908 result = lower; |
| 2827 break; | 2909 break; |
| 2828 } | 2910 } |
| 2829 set_fpu_register_double(fd_reg(), result); | 2911 SetFPUDoubleResult(fd_reg(), result); |
| 2830 if (result != fs) { | 2912 if (result != fs) { |
| 2831 set_fcsr_bit(kFCSRInexactFlagBit, true); | 2913 set_fcsr_bit(kFCSRInexactFlagBit, true); |
| 2832 } | 2914 } |
| 2833 break; | 2915 break; |
| 2834 } | 2916 } |
| 2835 case SEL: | 2917 case SEL: |
| 2836 DCHECK(kArchVariant == kMips64r6); | 2918 DCHECK(kArchVariant == kMips64r6); |
| 2837 set_fpu_register_double(fd_reg(), (fd_int & 0x1) == 0 ? fs : ft); | 2919 SetFPUDoubleResult(fd_reg(), (fd_int & 0x1) == 0 ? fs : ft); |
| 2838 break; | 2920 break; |
| 2839 case SELEQZ_C: | 2921 case SELEQZ_C: |
| 2840 DCHECK(kArchVariant == kMips64r6); | 2922 DCHECK(kArchVariant == kMips64r6); |
| 2841 set_fpu_register_double(fd_reg(), (ft_int & 0x1) == 0 ? fs : 0.0); | 2923 SetFPUDoubleResult(fd_reg(), (ft_int & 0x1) == 0 ? fs : 0.0); |
| 2842 break; | 2924 break; |
| 2843 case SELNEZ_C: | 2925 case SELNEZ_C: |
| 2844 DCHECK(kArchVariant == kMips64r6); | 2926 DCHECK(kArchVariant == kMips64r6); |
| 2845 set_fpu_register_double(fd_reg(), (ft_int & 0x1) != 0 ? fs : 0.0); | 2927 SetFPUDoubleResult(fd_reg(), (ft_int & 0x1) != 0 ? fs : 0.0); |
| 2846 break; | 2928 break; |
| 2847 case MOVZ_C: { | 2929 case MOVZ_C: { |
| 2848 DCHECK(kArchVariant == kMips64r2); | 2930 DCHECK(kArchVariant == kMips64r2); |
| 2849 if (rt() == 0) { | 2931 if (rt() == 0) { |
| 2850 set_fpu_register_double(fd_reg(), fs); | 2932 SetFPUDoubleResult(fd_reg(), fs); |
| 2851 } | 2933 } |
| 2852 break; | 2934 break; |
| 2853 } | 2935 } |
| 2854 case MOVN_C: { | 2936 case MOVN_C: { |
| 2855 DCHECK(kArchVariant == kMips64r2); | 2937 DCHECK(kArchVariant == kMips64r2); |
| 2856 if (rt() != 0) { | 2938 if (rt() != 0) { |
| 2857 set_fpu_register_double(fd_reg(), fs); | 2939 SetFPUDoubleResult(fd_reg(), fs); |
| 2858 } | 2940 } |
| 2859 break; | 2941 break; |
| 2860 } | 2942 } |
| 2861 case MOVF: { | 2943 case MOVF: { |
| 2862 // Same function field for MOVT.D and MOVF.D | 2944 // Same function field for MOVT.D and MOVF.D |
| 2863 uint32_t ft_cc = (ft_reg() >> 2) & 0x7; | 2945 uint32_t ft_cc = (ft_reg() >> 2) & 0x7; |
| 2864 ft_cc = get_fcsr_condition_bit(ft_cc); | 2946 ft_cc = get_fcsr_condition_bit(ft_cc); |
| 2865 if (instr_.Bit(16)) { // Read Tf bit. | 2947 if (instr_.Bit(16)) { // Read Tf bit. |
| 2866 // MOVT.D | 2948 // MOVT.D |
| 2867 if (test_fcsr_bit(ft_cc)) set_fpu_register_double(fd_reg(), fs); | 2949 if (test_fcsr_bit(ft_cc)) SetFPUDoubleResult(fd_reg(), fs); |
| 2868 } else { | 2950 } else { |
| 2869 // MOVF.D | 2951 // MOVF.D |
| 2870 if (!test_fcsr_bit(ft_cc)) set_fpu_register_double(fd_reg(), fs); | 2952 if (!test_fcsr_bit(ft_cc)) SetFPUDoubleResult(fd_reg(), fs); |
| 2871 } | 2953 } |
| 2872 break; | 2954 break; |
| 2873 } | 2955 } |
| 2874 case MINA: | 2956 case MINA: |
| 2875 DCHECK(kArchVariant == kMips64r6); | 2957 DCHECK(kArchVariant == kMips64r6); |
| 2876 set_fpu_register_double(fd_reg(), FPUMinA(ft, fs)); | 2958 SetFPUDoubleResult(fd_reg(), FPUMinA(ft, fs)); |
| 2877 break; | 2959 break; |
| 2878 case MAXA: | 2960 case MAXA: |
| 2879 DCHECK(kArchVariant == kMips64r6); | 2961 DCHECK(kArchVariant == kMips64r6); |
| 2880 set_fpu_register_double(fd_reg(), FPUMaxA(ft, fs)); | 2962 SetFPUDoubleResult(fd_reg(), FPUMaxA(ft, fs)); |
| 2881 break; | 2963 break; |
| 2882 case MIN: | 2964 case MIN: |
| 2883 DCHECK(kArchVariant == kMips64r6); | 2965 DCHECK(kArchVariant == kMips64r6); |
| 2884 set_fpu_register_double(fd_reg(), FPUMin(ft, fs)); | 2966 SetFPUDoubleResult(fd_reg(), FPUMin(ft, fs)); |
| 2885 break; | 2967 break; |
| 2886 case MAX: | 2968 case MAX: |
| 2887 DCHECK(kArchVariant == kMips64r6); | 2969 DCHECK(kArchVariant == kMips64r6); |
| 2888 set_fpu_register_double(fd_reg(), FPUMax(ft, fs)); | 2970 SetFPUDoubleResult(fd_reg(), FPUMax(ft, fs)); |
| 2889 break; | 2971 break; |
| 2890 case ADD_D: | 2972 case ADD_D: |
| 2891 set_fpu_register_double( | 2973 SetFPUDoubleResult( |
| 2892 fd_reg(), | 2974 fd_reg(), |
| 2893 FPUCanonalizeOperation( | 2975 FPUCanonalizeOperation( |
| 2894 [](double lhs, double rhs) { return lhs + rhs; }, fs, ft)); | 2976 [](double lhs, double rhs) { return lhs + rhs; }, fs, ft)); |
| 2895 break; | 2977 break; |
| 2896 case SUB_D: | 2978 case SUB_D: |
| 2897 set_fpu_register_double( | 2979 SetFPUDoubleResult( |
| 2898 fd_reg(), | 2980 fd_reg(), |
| 2899 FPUCanonalizeOperation( | 2981 FPUCanonalizeOperation( |
| 2900 [](double lhs, double rhs) { return lhs - rhs; }, fs, ft)); | 2982 [](double lhs, double rhs) { return lhs - rhs; }, fs, ft)); |
| 2901 break; | 2983 break; |
| 2902 case MADDF_D: | 2984 case MADDF_D: |
| 2903 DCHECK(kArchVariant == kMips64r6); | 2985 DCHECK(kArchVariant == kMips64r6); |
| 2904 set_fpu_register_double(fd_reg(), std::fma(fs, ft, fd)); | 2986 SetFPUDoubleResult(fd_reg(), std::fma(fs, ft, fd)); |
| 2905 break; | 2987 break; |
| 2906 case MSUBF_D: | 2988 case MSUBF_D: |
| 2907 DCHECK(kArchVariant == kMips64r6); | 2989 DCHECK(kArchVariant == kMips64r6); |
| 2908 set_fpu_register_double(fd_reg(), std::fma(-fs, ft, fd)); | 2990 SetFPUDoubleResult(fd_reg(), std::fma(-fs, ft, fd)); |
| 2909 break; | 2991 break; |
| 2910 case MUL_D: | 2992 case MUL_D: |
| 2911 set_fpu_register_double( | 2993 SetFPUDoubleResult( |
| 2912 fd_reg(), | 2994 fd_reg(), |
| 2913 FPUCanonalizeOperation( | 2995 FPUCanonalizeOperation( |
| 2914 [](double lhs, double rhs) { return lhs * rhs; }, fs, ft)); | 2996 [](double lhs, double rhs) { return lhs * rhs; }, fs, ft)); |
| 2915 break; | 2997 break; |
| 2916 case DIV_D: | 2998 case DIV_D: |
| 2917 set_fpu_register_double( | 2999 SetFPUDoubleResult( |
| 2918 fd_reg(), | 3000 fd_reg(), |
| 2919 FPUCanonalizeOperation( | 3001 FPUCanonalizeOperation( |
| 2920 [](double lhs, double rhs) { return lhs / rhs; }, fs, ft)); | 3002 [](double lhs, double rhs) { return lhs / rhs; }, fs, ft)); |
| 2921 break; | 3003 break; |
| 2922 case ABS_D: | 3004 case ABS_D: |
| 2923 set_fpu_register_double( | 3005 SetFPUDoubleResult( |
| 2924 fd_reg(), | 3006 fd_reg(), |
| 2925 FPUCanonalizeOperation([](double fs) { return FPAbs(fs); }, fs)); | 3007 FPUCanonalizeOperation([](double fs) { return FPAbs(fs); }, fs)); |
| 2926 break; | 3008 break; |
| 2927 case MOV_D: | 3009 case MOV_D: |
| 2928 set_fpu_register_double(fd_reg(), fs); | 3010 SetFPUDoubleResult(fd_reg(), fs); |
| 2929 break; | 3011 break; |
| 2930 case NEG_D: | 3012 case NEG_D: |
| 2931 set_fpu_register_double( | 3013 SetFPUDoubleResult(fd_reg(), |
| 2932 fd_reg(), FPUCanonalizeOperation([](double src) { return -src; }, | 3014 FPUCanonalizeOperation([](double src) { return -src; }, |
| 2933 KeepSign::yes, fs)); | 3015 KeepSign::yes, fs)); |
| 2934 break; | 3016 break; |
| 2935 case SQRT_D: | 3017 case SQRT_D: |
| 2936 set_fpu_register_double( | 3018 SetFPUDoubleResult( |
| 2937 fd_reg(), | 3019 fd_reg(), |
| 2938 FPUCanonalizeOperation([](double fs) { return std::sqrt(fs); }, fs)); | 3020 FPUCanonalizeOperation([](double fs) { return std::sqrt(fs); }, fs)); |
| 2939 break; | 3021 break; |
| 2940 case RSQRT_D: | 3022 case RSQRT_D: |
| 2941 set_fpu_register_double( | 3023 SetFPUDoubleResult( |
| 2942 fd_reg(), FPUCanonalizeOperation( | 3024 fd_reg(), FPUCanonalizeOperation( |
| 2943 [](double fs) { return 1.0 / std::sqrt(fs); }, fs)); | 3025 [](double fs) { return 1.0 / std::sqrt(fs); }, fs)); |
| 2944 break; | 3026 break; |
| 2945 case RECIP_D: | 3027 case RECIP_D: |
| 2946 set_fpu_register_double( | 3028 SetFPUDoubleResult(fd_reg(), FPUCanonalizeOperation( |
| 2947 fd_reg(), | 3029 [](double fs) { return 1.0 / fs; }, fs)); |
| 2948 FPUCanonalizeOperation([](double fs) { return 1.0 / fs; }, fs)); | |
| 2949 break; | 3030 break; |
| 2950 case C_UN_D: | 3031 case C_UN_D: |
| 2951 set_fcsr_bit(fcsr_cc, std::isnan(fs) || std::isnan(ft)); | 3032 set_fcsr_bit(fcsr_cc, std::isnan(fs) || std::isnan(ft)); |
| 3033 TraceRegWr(test_fcsr_bit(fcsr_cc)); |
| 2952 break; | 3034 break; |
| 2953 case C_EQ_D: | 3035 case C_EQ_D: |
| 2954 set_fcsr_bit(fcsr_cc, (fs == ft)); | 3036 set_fcsr_bit(fcsr_cc, (fs == ft)); |
| 3037 TraceRegWr(test_fcsr_bit(fcsr_cc)); |
| 2955 break; | 3038 break; |
| 2956 case C_UEQ_D: | 3039 case C_UEQ_D: |
| 2957 set_fcsr_bit(fcsr_cc, (fs == ft) || (std::isnan(fs) || std::isnan(ft))); | 3040 set_fcsr_bit(fcsr_cc, (fs == ft) || (std::isnan(fs) || std::isnan(ft))); |
| 3041 TraceRegWr(test_fcsr_bit(fcsr_cc)); |
| 2958 break; | 3042 break; |
| 2959 case C_OLT_D: | 3043 case C_OLT_D: |
| 2960 set_fcsr_bit(fcsr_cc, (fs < ft)); | 3044 set_fcsr_bit(fcsr_cc, (fs < ft)); |
| 3045 TraceRegWr(test_fcsr_bit(fcsr_cc)); |
| 2961 break; | 3046 break; |
| 2962 case C_ULT_D: | 3047 case C_ULT_D: |
| 2963 set_fcsr_bit(fcsr_cc, (fs < ft) || (std::isnan(fs) || std::isnan(ft))); | 3048 set_fcsr_bit(fcsr_cc, (fs < ft) || (std::isnan(fs) || std::isnan(ft))); |
| 3049 TraceRegWr(test_fcsr_bit(fcsr_cc)); |
| 2964 break; | 3050 break; |
| 2965 case C_OLE_D: | 3051 case C_OLE_D: |
| 2966 set_fcsr_bit(fcsr_cc, (fs <= ft)); | 3052 set_fcsr_bit(fcsr_cc, (fs <= ft)); |
| 3053 TraceRegWr(test_fcsr_bit(fcsr_cc)); |
| 2967 break; | 3054 break; |
| 2968 case C_ULE_D: | 3055 case C_ULE_D: |
| 2969 set_fcsr_bit(fcsr_cc, (fs <= ft) || (std::isnan(fs) || std::isnan(ft))); | 3056 set_fcsr_bit(fcsr_cc, (fs <= ft) || (std::isnan(fs) || std::isnan(ft))); |
| 3057 TraceRegWr(test_fcsr_bit(fcsr_cc)); |
| 2970 break; | 3058 break; |
| 2971 case CVT_W_D: { // Convert double to word. | 3059 case CVT_W_D: { // Convert double to word. |
| 2972 double rounded; | 3060 double rounded; |
| 2973 int32_t result; | 3061 int32_t result; |
| 2974 round_according_to_fcsr(fs, rounded, result, fs); | 3062 round_according_to_fcsr(fs, rounded, result, fs); |
| 2975 set_fpu_register_word(fd_reg(), result); | 3063 SetFPUWordResult(fd_reg(), result); |
| 2976 if (set_fcsr_round_error(fs, rounded)) { | 3064 if (set_fcsr_round_error(fs, rounded)) { |
| 2977 set_fpu_register_word_invalid_result(fs, rounded); | 3065 set_fpu_register_word_invalid_result(fs, rounded); |
| 2978 } | 3066 } |
| 2979 break; | 3067 break; |
| 2980 } | 3068 } |
| 2981 case ROUND_W_D: // Round double to word (round half to even). | 3069 case ROUND_W_D: // Round double to word (round half to even). |
| 2982 { | 3070 { |
| 2983 double rounded = std::floor(fs + 0.5); | 3071 double rounded = std::floor(fs + 0.5); |
| 2984 int32_t result = static_cast<int32_t>(rounded); | 3072 int32_t result = static_cast<int32_t>(rounded); |
| 2985 if ((result & 1) != 0 && result - fs == 0.5) { | 3073 if ((result & 1) != 0 && result - fs == 0.5) { |
| 2986 // If the number is halfway between two integers, | 3074 // If the number is halfway between two integers, |
| 2987 // round to the even one. | 3075 // round to the even one. |
| 2988 result--; | 3076 result--; |
| 2989 } | 3077 } |
| 2990 set_fpu_register_word(fd_reg(), result); | 3078 SetFPUWordResult(fd_reg(), result); |
| 2991 if (set_fcsr_round_error(fs, rounded)) { | 3079 if (set_fcsr_round_error(fs, rounded)) { |
| 2992 set_fpu_register_invalid_result(fs, rounded); | 3080 set_fpu_register_invalid_result(fs, rounded); |
| 2993 } | 3081 } |
| 2994 } break; | 3082 } break; |
| 2995 case TRUNC_W_D: // Truncate double to word (round towards 0). | 3083 case TRUNC_W_D: // Truncate double to word (round towards 0). |
| 2996 { | 3084 { |
| 2997 double rounded = trunc(fs); | 3085 double rounded = trunc(fs); |
| 2998 int32_t result = static_cast<int32_t>(rounded); | 3086 int32_t result = static_cast<int32_t>(rounded); |
| 2999 set_fpu_register_word(fd_reg(), result); | 3087 SetFPUWordResult(fd_reg(), result); |
| 3000 if (set_fcsr_round_error(fs, rounded)) { | 3088 if (set_fcsr_round_error(fs, rounded)) { |
| 3001 set_fpu_register_invalid_result(fs, rounded); | 3089 set_fpu_register_invalid_result(fs, rounded); |
| 3002 } | 3090 } |
| 3003 } break; | 3091 } break; |
| 3004 case FLOOR_W_D: // Round double to word towards negative infinity. | 3092 case FLOOR_W_D: // Round double to word towards negative infinity. |
| 3005 { | 3093 { |
| 3006 double rounded = std::floor(fs); | 3094 double rounded = std::floor(fs); |
| 3007 int32_t result = static_cast<int32_t>(rounded); | 3095 int32_t result = static_cast<int32_t>(rounded); |
| 3008 set_fpu_register_word(fd_reg(), result); | 3096 SetFPUWordResult(fd_reg(), result); |
| 3009 if (set_fcsr_round_error(fs, rounded)) { | 3097 if (set_fcsr_round_error(fs, rounded)) { |
| 3010 set_fpu_register_invalid_result(fs, rounded); | 3098 set_fpu_register_invalid_result(fs, rounded); |
| 3011 } | 3099 } |
| 3012 } break; | 3100 } break; |
| 3013 case CEIL_W_D: // Round double to word towards positive infinity. | 3101 case CEIL_W_D: // Round double to word towards positive infinity. |
| 3014 { | 3102 { |
| 3015 double rounded = std::ceil(fs); | 3103 double rounded = std::ceil(fs); |
| 3016 int32_t result = static_cast<int32_t>(rounded); | 3104 int32_t result = static_cast<int32_t>(rounded); |
| 3017 set_fpu_register_word(fd_reg(), result); | 3105 SetFPUWordResult2(fd_reg(), result); |
| 3018 if (set_fcsr_round_error(fs, rounded)) { | 3106 if (set_fcsr_round_error(fs, rounded)) { |
| 3019 set_fpu_register_invalid_result(fs, rounded); | 3107 set_fpu_register_invalid_result(fs, rounded); |
| 3020 } | 3108 } |
| 3021 } break; | 3109 } break; |
| 3022 case CVT_S_D: // Convert double to float (single). | 3110 case CVT_S_D: // Convert double to float (single). |
| 3023 set_fpu_register_float(fd_reg(), static_cast<float>(fs)); | 3111 SetFPUFloatResult(fd_reg(), static_cast<float>(fs)); |
| 3024 break; | 3112 break; |
| 3025 case CVT_L_D: { // Mips64r2: Truncate double to 64-bit long-word. | 3113 case CVT_L_D: { // Mips64r2: Truncate double to 64-bit long-word. |
| 3026 double rounded; | 3114 double rounded; |
| 3027 int64_t result; | 3115 int64_t result; |
| 3028 round64_according_to_fcsr(fs, rounded, result, fs); | 3116 round64_according_to_fcsr(fs, rounded, result, fs); |
| 3029 set_fpu_register(fd_reg(), result); | 3117 SetFPUResult(fd_reg(), result); |
| 3030 if (set_fcsr_round64_error(fs, rounded)) { | 3118 if (set_fcsr_round64_error(fs, rounded)) { |
| 3031 set_fpu_register_invalid_result64(fs, rounded); | 3119 set_fpu_register_invalid_result64(fs, rounded); |
| 3032 } | 3120 } |
| 3033 break; | 3121 break; |
| 3034 } | 3122 } |
| 3035 case ROUND_L_D: { // Mips64r2 instruction. | 3123 case ROUND_L_D: { // Mips64r2 instruction. |
| 3036 double rounded = std::floor(fs + 0.5); | 3124 double rounded = std::floor(fs + 0.5); |
| 3037 int64_t result = static_cast<int64_t>(rounded); | 3125 int64_t result = static_cast<int64_t>(rounded); |
| 3038 if ((result & 1) != 0 && result - fs == 0.5) { | 3126 if ((result & 1) != 0 && result - fs == 0.5) { |
| 3039 // If the number is halfway between two integers, | 3127 // If the number is halfway between two integers, |
| 3040 // round to the even one. | 3128 // round to the even one. |
| 3041 result--; | 3129 result--; |
| 3042 } | 3130 } |
| 3043 int64_t i64 = static_cast<int64_t>(result); | 3131 int64_t i64 = static_cast<int64_t>(result); |
| 3044 set_fpu_register(fd_reg(), i64); | 3132 SetFPUResult(fd_reg(), i64); |
| 3045 if (set_fcsr_round64_error(fs, rounded)) { | 3133 if (set_fcsr_round64_error(fs, rounded)) { |
| 3046 set_fpu_register_invalid_result64(fs, rounded); | 3134 set_fpu_register_invalid_result64(fs, rounded); |
| 3047 } | 3135 } |
| 3048 break; | 3136 break; |
| 3049 } | 3137 } |
| 3050 case TRUNC_L_D: { // Mips64r2 instruction. | 3138 case TRUNC_L_D: { // Mips64r2 instruction. |
| 3051 double rounded = trunc(fs); | 3139 double rounded = trunc(fs); |
| 3052 int64_t result = static_cast<int64_t>(rounded); | 3140 int64_t result = static_cast<int64_t>(rounded); |
| 3053 set_fpu_register(fd_reg(), result); | 3141 SetFPUResult(fd_reg(), result); |
| 3054 if (set_fcsr_round64_error(fs, rounded)) { | 3142 if (set_fcsr_round64_error(fs, rounded)) { |
| 3055 set_fpu_register_invalid_result64(fs, rounded); | 3143 set_fpu_register_invalid_result64(fs, rounded); |
| 3056 } | 3144 } |
| 3057 break; | 3145 break; |
| 3058 } | 3146 } |
| 3059 case FLOOR_L_D: { // Mips64r2 instruction. | 3147 case FLOOR_L_D: { // Mips64r2 instruction. |
| 3060 double rounded = floor(fs); | 3148 double rounded = floor(fs); |
| 3061 int64_t result = static_cast<int64_t>(rounded); | 3149 int64_t result = static_cast<int64_t>(rounded); |
| 3062 set_fpu_register(fd_reg(), result); | 3150 SetFPUResult(fd_reg(), result); |
| 3063 if (set_fcsr_round64_error(fs, rounded)) { | 3151 if (set_fcsr_round64_error(fs, rounded)) { |
| 3064 set_fpu_register_invalid_result64(fs, rounded); | 3152 set_fpu_register_invalid_result64(fs, rounded); |
| 3065 } | 3153 } |
| 3066 break; | 3154 break; |
| 3067 } | 3155 } |
| 3068 case CEIL_L_D: { // Mips64r2 instruction. | 3156 case CEIL_L_D: { // Mips64r2 instruction. |
| 3069 double rounded = ceil(fs); | 3157 double rounded = ceil(fs); |
| 3070 int64_t result = static_cast<int64_t>(rounded); | 3158 int64_t result = static_cast<int64_t>(rounded); |
| 3071 set_fpu_register(fd_reg(), result); | 3159 SetFPUResult(fd_reg(), result); |
| 3072 if (set_fcsr_round64_error(fs, rounded)) { | 3160 if (set_fcsr_round64_error(fs, rounded)) { |
| 3073 set_fpu_register_invalid_result64(fs, rounded); | 3161 set_fpu_register_invalid_result64(fs, rounded); |
| 3074 } | 3162 } |
| 3075 break; | 3163 break; |
| 3076 } | 3164 } |
| 3077 case CLASS_D: { // Mips64r6 instruction | 3165 case CLASS_D: { // Mips64r6 instruction |
| 3078 // Convert double input to uint64_t for easier bit manipulation | 3166 // Convert double input to uint64_t for easier bit manipulation |
| 3079 uint64_t classed = bit_cast<uint64_t>(fs); | 3167 uint64_t classed = bit_cast<uint64_t>(fs); |
| 3080 | 3168 |
| 3081 // Extracting sign, exponent and mantissa from the input double | 3169 // Extracting sign, exponent and mantissa from the input double |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3128 } | 3216 } |
| 3129 | 3217 |
| 3130 // Calculating result according to description of CLASS.D instruction | 3218 // Calculating result according to description of CLASS.D instruction |
| 3131 result = (posZero << 9) | (posSubnorm << 8) | (posNorm << 7) | | 3219 result = (posZero << 9) | (posSubnorm << 8) | (posNorm << 7) | |
| 3132 (posInf << 6) | (negZero << 5) | (negSubnorm << 4) | | 3220 (posInf << 6) | (negZero << 5) | (negSubnorm << 4) | |
| 3133 (negNorm << 3) | (negInf << 2) | (quietNan << 1) | signalingNan; | 3221 (negNorm << 3) | (negInf << 2) | (quietNan << 1) | signalingNan; |
| 3134 | 3222 |
| 3135 DCHECK(result != 0); | 3223 DCHECK(result != 0); |
| 3136 | 3224 |
| 3137 dResult = bit_cast<double>(result); | 3225 dResult = bit_cast<double>(result); |
| 3138 set_fpu_register_double(fd_reg(), dResult); | 3226 SetFPUDoubleResult(fd_reg(), dResult); |
| 3139 | |
| 3140 break; | 3227 break; |
| 3141 } | 3228 } |
| 3142 case C_F_D: { | 3229 case C_F_D: { |
| 3143 set_fcsr_bit(fcsr_cc, false); | 3230 set_fcsr_bit(fcsr_cc, false); |
| 3231 TraceRegWr(test_fcsr_bit(fcsr_cc)); |
| 3144 break; | 3232 break; |
| 3145 } | 3233 } |
| 3146 default: | 3234 default: |
| 3147 UNREACHABLE(); | 3235 UNREACHABLE(); |
| 3148 } | 3236 } |
| 3149 } | 3237 } |
| 3150 | 3238 |
| 3151 | 3239 |
| 3152 void Simulator::DecodeTypeRegisterWRsType() { | 3240 void Simulator::DecodeTypeRegisterWRsType() { |
| 3153 float fs = get_fpu_register_float(fs_reg()); | 3241 float fs = get_fpu_register_float(fs_reg()); |
| 3154 float ft = get_fpu_register_float(ft_reg()); | 3242 float ft = get_fpu_register_float(ft_reg()); |
| 3155 int64_t alu_out = 0x12345678; | 3243 int64_t alu_out = 0x12345678; |
| 3156 switch (instr_.FunctionFieldRaw()) { | 3244 switch (instr_.FunctionFieldRaw()) { |
| 3157 case CVT_S_W: // Convert word to float (single). | 3245 case CVT_S_W: // Convert word to float (single). |
| 3158 alu_out = get_fpu_register_signed_word(fs_reg()); | 3246 alu_out = get_fpu_register_signed_word(fs_reg()); |
| 3159 set_fpu_register_float(fd_reg(), static_cast<float>(alu_out)); | 3247 SetFPUFloatResult(fd_reg(), static_cast<float>(alu_out)); |
| 3160 break; | 3248 break; |
| 3161 case CVT_D_W: // Convert word to double. | 3249 case CVT_D_W: // Convert word to double. |
| 3162 alu_out = get_fpu_register_signed_word(fs_reg()); | 3250 alu_out = get_fpu_register_signed_word(fs_reg()); |
| 3163 set_fpu_register_double(fd_reg(), static_cast<double>(alu_out)); | 3251 SetFPUDoubleResult(fd_reg(), static_cast<double>(alu_out)); |
| 3164 break; | 3252 break; |
| 3165 case CMP_AF: | 3253 case CMP_AF: |
| 3166 set_fpu_register_word(fd_reg(), 0); | 3254 SetFPUWordResult2(fd_reg(), 0); |
| 3167 break; | 3255 break; |
| 3168 case CMP_UN: | 3256 case CMP_UN: |
| 3169 if (std::isnan(fs) || std::isnan(ft)) { | 3257 if (std::isnan(fs) || std::isnan(ft)) { |
| 3170 set_fpu_register_word(fd_reg(), -1); | 3258 SetFPUWordResult2(fd_reg(), -1); |
| 3171 } else { | 3259 } else { |
| 3172 set_fpu_register_word(fd_reg(), 0); | 3260 SetFPUWordResult2(fd_reg(), 0); |
| 3173 } | 3261 } |
| 3174 break; | 3262 break; |
| 3175 case CMP_EQ: | 3263 case CMP_EQ: |
| 3176 if (fs == ft) { | 3264 if (fs == ft) { |
| 3177 set_fpu_register_word(fd_reg(), -1); | 3265 SetFPUWordResult2(fd_reg(), -1); |
| 3178 } else { | 3266 } else { |
| 3179 set_fpu_register_word(fd_reg(), 0); | 3267 SetFPUWordResult2(fd_reg(), 0); |
| 3180 } | 3268 } |
| 3181 break; | 3269 break; |
| 3182 case CMP_UEQ: | 3270 case CMP_UEQ: |
| 3183 if ((fs == ft) || (std::isnan(fs) || std::isnan(ft))) { | 3271 if ((fs == ft) || (std::isnan(fs) || std::isnan(ft))) { |
| 3184 set_fpu_register_word(fd_reg(), -1); | 3272 SetFPUWordResult2(fd_reg(), -1); |
| 3185 } else { | 3273 } else { |
| 3186 set_fpu_register_word(fd_reg(), 0); | 3274 SetFPUWordResult2(fd_reg(), 0); |
| 3187 } | 3275 } |
| 3188 break; | 3276 break; |
| 3189 case CMP_LT: | 3277 case CMP_LT: |
| 3190 if (fs < ft) { | 3278 if (fs < ft) { |
| 3191 set_fpu_register_word(fd_reg(), -1); | 3279 SetFPUWordResult2(fd_reg(), -1); |
| 3192 } else { | 3280 } else { |
| 3193 set_fpu_register_word(fd_reg(), 0); | 3281 SetFPUWordResult2(fd_reg(), 0); |
| 3194 } | 3282 } |
| 3195 break; | 3283 break; |
| 3196 case CMP_ULT: | 3284 case CMP_ULT: |
| 3197 if ((fs < ft) || (std::isnan(fs) || std::isnan(ft))) { | 3285 if ((fs < ft) || (std::isnan(fs) || std::isnan(ft))) { |
| 3198 set_fpu_register_word(fd_reg(), -1); | 3286 SetFPUWordResult2(fd_reg(), -1); |
| 3199 } else { | 3287 } else { |
| 3200 set_fpu_register_word(fd_reg(), 0); | 3288 SetFPUWordResult2(fd_reg(), 0); |
| 3201 } | 3289 } |
| 3202 break; | 3290 break; |
| 3203 case CMP_LE: | 3291 case CMP_LE: |
| 3204 if (fs <= ft) { | 3292 if (fs <= ft) { |
| 3205 set_fpu_register_word(fd_reg(), -1); | 3293 SetFPUWordResult2(fd_reg(), -1); |
| 3206 } else { | 3294 } else { |
| 3207 set_fpu_register_word(fd_reg(), 0); | 3295 SetFPUWordResult2(fd_reg(), 0); |
| 3208 } | 3296 } |
| 3209 break; | 3297 break; |
| 3210 case CMP_ULE: | 3298 case CMP_ULE: |
| 3211 if ((fs <= ft) || (std::isnan(fs) || std::isnan(ft))) { | 3299 if ((fs <= ft) || (std::isnan(fs) || std::isnan(ft))) { |
| 3212 set_fpu_register_word(fd_reg(), -1); | 3300 SetFPUWordResult2(fd_reg(), -1); |
| 3213 } else { | 3301 } else { |
| 3214 set_fpu_register_word(fd_reg(), 0); | 3302 SetFPUWordResult2(fd_reg(), 0); |
| 3215 } | 3303 } |
| 3216 break; | 3304 break; |
| 3217 case CMP_OR: | 3305 case CMP_OR: |
| 3218 if (!std::isnan(fs) && !std::isnan(ft)) { | 3306 if (!std::isnan(fs) && !std::isnan(ft)) { |
| 3219 set_fpu_register_word(fd_reg(), -1); | 3307 SetFPUWordResult2(fd_reg(), -1); |
| 3220 } else { | 3308 } else { |
| 3221 set_fpu_register_word(fd_reg(), 0); | 3309 SetFPUWordResult2(fd_reg(), 0); |
| 3222 } | 3310 } |
| 3223 break; | 3311 break; |
| 3224 case CMP_UNE: | 3312 case CMP_UNE: |
| 3225 if ((fs != ft) || (std::isnan(fs) || std::isnan(ft))) { | 3313 if ((fs != ft) || (std::isnan(fs) || std::isnan(ft))) { |
| 3226 set_fpu_register_word(fd_reg(), -1); | 3314 SetFPUWordResult2(fd_reg(), -1); |
| 3227 } else { | 3315 } else { |
| 3228 set_fpu_register_word(fd_reg(), 0); | 3316 SetFPUWordResult2(fd_reg(), 0); |
| 3229 } | 3317 } |
| 3230 break; | 3318 break; |
| 3231 case CMP_NE: | 3319 case CMP_NE: |
| 3232 if (fs != ft) { | 3320 if (fs != ft) { |
| 3233 set_fpu_register_word(fd_reg(), -1); | 3321 SetFPUWordResult2(fd_reg(), -1); |
| 3234 } else { | 3322 } else { |
| 3235 set_fpu_register_word(fd_reg(), 0); | 3323 SetFPUWordResult2(fd_reg(), 0); |
| 3236 } | 3324 } |
| 3237 break; | 3325 break; |
| 3238 default: | 3326 default: |
| 3239 UNREACHABLE(); | 3327 UNREACHABLE(); |
| 3240 } | 3328 } |
| 3241 } | 3329 } |
| 3242 | 3330 |
| 3243 | 3331 |
| 3244 void Simulator::DecodeTypeRegisterLRsType() { | 3332 void Simulator::DecodeTypeRegisterLRsType() { |
| 3245 double fs = get_fpu_register_double(fs_reg()); | 3333 double fs = get_fpu_register_double(fs_reg()); |
| 3246 double ft = get_fpu_register_double(ft_reg()); | 3334 double ft = get_fpu_register_double(ft_reg()); |
| 3247 int64_t i64; | 3335 int64_t i64; |
| 3248 switch (instr_.FunctionFieldRaw()) { | 3336 switch (instr_.FunctionFieldRaw()) { |
| 3249 case CVT_D_L: // Mips32r2 instruction. | 3337 case CVT_D_L: // Mips32r2 instruction. |
| 3250 i64 = get_fpu_register(fs_reg()); | 3338 i64 = get_fpu_register(fs_reg()); |
| 3251 set_fpu_register_double(fd_reg(), static_cast<double>(i64)); | 3339 SetFPUDoubleResult(fd_reg(), static_cast<double>(i64)); |
| 3252 break; | 3340 break; |
| 3253 case CVT_S_L: | 3341 case CVT_S_L: |
| 3254 i64 = get_fpu_register(fs_reg()); | 3342 i64 = get_fpu_register(fs_reg()); |
| 3255 set_fpu_register_float(fd_reg(), static_cast<float>(i64)); | 3343 SetFPUFloatResult(fd_reg(), static_cast<float>(i64)); |
| 3256 break; | 3344 break; |
| 3257 case CMP_AF: | 3345 case CMP_AF: |
| 3258 set_fpu_register(fd_reg(), 0); | 3346 SetFPUResult(fd_reg(), 0); |
| 3259 break; | 3347 break; |
| 3260 case CMP_UN: | 3348 case CMP_UN: |
| 3261 if (std::isnan(fs) || std::isnan(ft)) { | 3349 if (std::isnan(fs) || std::isnan(ft)) { |
| 3262 set_fpu_register(fd_reg(), -1); | 3350 SetFPUResult(fd_reg(), -1); |
| 3263 } else { | 3351 } else { |
| 3264 set_fpu_register(fd_reg(), 0); | 3352 SetFPUResult(fd_reg(), 0); |
| 3265 } | 3353 } |
| 3266 break; | 3354 break; |
| 3267 case CMP_EQ: | 3355 case CMP_EQ: |
| 3268 if (fs == ft) { | 3356 if (fs == ft) { |
| 3269 set_fpu_register(fd_reg(), -1); | 3357 SetFPUResult(fd_reg(), -1); |
| 3270 } else { | 3358 } else { |
| 3271 set_fpu_register(fd_reg(), 0); | 3359 SetFPUResult(fd_reg(), 0); |
| 3272 } | 3360 } |
| 3273 break; | 3361 break; |
| 3274 case CMP_UEQ: | 3362 case CMP_UEQ: |
| 3275 if ((fs == ft) || (std::isnan(fs) || std::isnan(ft))) { | 3363 if ((fs == ft) || (std::isnan(fs) || std::isnan(ft))) { |
| 3276 set_fpu_register(fd_reg(), -1); | 3364 SetFPUResult(fd_reg(), -1); |
| 3277 } else { | 3365 } else { |
| 3278 set_fpu_register(fd_reg(), 0); | 3366 SetFPUResult(fd_reg(), 0); |
| 3279 } | 3367 } |
| 3280 break; | 3368 break; |
| 3281 case CMP_LT: | 3369 case CMP_LT: |
| 3282 if (fs < ft) { | 3370 if (fs < ft) { |
| 3283 set_fpu_register(fd_reg(), -1); | 3371 SetFPUResult(fd_reg(), -1); |
| 3284 } else { | 3372 } else { |
| 3285 set_fpu_register(fd_reg(), 0); | 3373 SetFPUResult(fd_reg(), 0); |
| 3286 } | 3374 } |
| 3287 break; | 3375 break; |
| 3288 case CMP_ULT: | 3376 case CMP_ULT: |
| 3289 if ((fs < ft) || (std::isnan(fs) || std::isnan(ft))) { | 3377 if ((fs < ft) || (std::isnan(fs) || std::isnan(ft))) { |
| 3290 set_fpu_register(fd_reg(), -1); | 3378 SetFPUResult(fd_reg(), -1); |
| 3291 } else { | 3379 } else { |
| 3292 set_fpu_register(fd_reg(), 0); | 3380 SetFPUResult(fd_reg(), 0); |
| 3293 } | 3381 } |
| 3294 break; | 3382 break; |
| 3295 case CMP_LE: | 3383 case CMP_LE: |
| 3296 if (fs <= ft) { | 3384 if (fs <= ft) { |
| 3297 set_fpu_register(fd_reg(), -1); | 3385 SetFPUResult(fd_reg(), -1); |
| 3298 } else { | 3386 } else { |
| 3299 set_fpu_register(fd_reg(), 0); | 3387 SetFPUResult(fd_reg(), 0); |
| 3300 } | 3388 } |
| 3301 break; | 3389 break; |
| 3302 case CMP_ULE: | 3390 case CMP_ULE: |
| 3303 if ((fs <= ft) || (std::isnan(fs) || std::isnan(ft))) { | 3391 if ((fs <= ft) || (std::isnan(fs) || std::isnan(ft))) { |
| 3304 set_fpu_register(fd_reg(), -1); | 3392 SetFPUResult(fd_reg(), -1); |
| 3305 } else { | 3393 } else { |
| 3306 set_fpu_register(fd_reg(), 0); | 3394 SetFPUResult(fd_reg(), 0); |
| 3307 } | 3395 } |
| 3308 break; | 3396 break; |
| 3309 case CMP_OR: | 3397 case CMP_OR: |
| 3310 if (!std::isnan(fs) && !std::isnan(ft)) { | 3398 if (!std::isnan(fs) && !std::isnan(ft)) { |
| 3311 set_fpu_register(fd_reg(), -1); | 3399 SetFPUResult(fd_reg(), -1); |
| 3312 } else { | 3400 } else { |
| 3313 set_fpu_register(fd_reg(), 0); | 3401 SetFPUResult(fd_reg(), 0); |
| 3314 } | 3402 } |
| 3315 break; | 3403 break; |
| 3316 case CMP_UNE: | 3404 case CMP_UNE: |
| 3317 if ((fs != ft) || (std::isnan(fs) || std::isnan(ft))) { | 3405 if ((fs != ft) || (std::isnan(fs) || std::isnan(ft))) { |
| 3318 set_fpu_register(fd_reg(), -1); | 3406 SetFPUResult(fd_reg(), -1); |
| 3319 } else { | 3407 } else { |
| 3320 set_fpu_register(fd_reg(), 0); | 3408 SetFPUResult(fd_reg(), 0); |
| 3321 } | 3409 } |
| 3322 break; | 3410 break; |
| 3323 case CMP_NE: | 3411 case CMP_NE: |
| 3324 if (fs != ft && (!std::isnan(fs) && !std::isnan(ft))) { | 3412 if (fs != ft && (!std::isnan(fs) && !std::isnan(ft))) { |
| 3325 set_fpu_register(fd_reg(), -1); | 3413 SetFPUResult(fd_reg(), -1); |
| 3326 } else { | 3414 } else { |
| 3327 set_fpu_register(fd_reg(), 0); | 3415 SetFPUResult(fd_reg(), 0); |
| 3328 } | 3416 } |
| 3329 break; | 3417 break; |
| 3330 default: | 3418 default: |
| 3331 UNREACHABLE(); | 3419 UNREACHABLE(); |
| 3332 } | 3420 } |
| 3333 } | 3421 } |
| 3334 | 3422 |
| 3335 | 3423 |
| 3336 void Simulator::DecodeTypeRegisterCOP1() { | 3424 void Simulator::DecodeTypeRegisterCOP1() { |
| 3337 switch (instr_.RsFieldRaw()) { | 3425 switch (instr_.RsFieldRaw()) { |
| 3338 case BC1: // Branch on coprocessor condition. | 3426 case BC1: // Branch on coprocessor condition. |
| 3339 case BC1EQZ: | 3427 case BC1EQZ: |
| 3340 case BC1NEZ: | 3428 case BC1NEZ: |
| 3341 UNREACHABLE(); | 3429 UNREACHABLE(); |
| 3342 break; | 3430 break; |
| 3343 case CFC1: | 3431 case CFC1: |
| 3344 // At the moment only FCSR is supported. | 3432 // At the moment only FCSR is supported. |
| 3345 DCHECK(fs_reg() == kFCSRRegister); | 3433 DCHECK(fs_reg() == kFCSRRegister); |
| 3346 set_register(rt_reg(), FCSR_); | 3434 SetResult(rt_reg(), FCSR_); |
| 3347 break; | 3435 break; |
| 3348 case MFC1: | 3436 case MFC1: |
| 3349 set_register(rt_reg(), | 3437 set_register(rt_reg(), |
| 3350 static_cast<int64_t>(get_fpu_register_word(fs_reg()))); | 3438 static_cast<int64_t>(get_fpu_register_word(fs_reg()))); |
| 3439 TraceRegWr(get_register(rt_reg()), WORD_DWORD); |
| 3351 break; | 3440 break; |
| 3352 case DMFC1: | 3441 case DMFC1: |
| 3353 set_register(rt_reg(), get_fpu_register(fs_reg())); | 3442 SetResult(rt_reg(), get_fpu_register(fs_reg())); |
| 3354 break; | 3443 break; |
| 3355 case MFHC1: | 3444 case MFHC1: |
| 3356 set_register(rt_reg(), get_fpu_register_hi_word(fs_reg())); | 3445 SetResult(rt_reg(), get_fpu_register_hi_word(fs_reg())); |
| 3357 break; | 3446 break; |
| 3358 case CTC1: { | 3447 case CTC1: { |
| 3359 // At the moment only FCSR is supported. | 3448 // At the moment only FCSR is supported. |
| 3360 DCHECK(fs_reg() == kFCSRRegister); | 3449 DCHECK(fs_reg() == kFCSRRegister); |
| 3361 uint32_t reg = static_cast<uint32_t>(rt()); | 3450 uint32_t reg = static_cast<uint32_t>(rt()); |
| 3362 if (kArchVariant == kMips64r6) { | 3451 if (kArchVariant == kMips64r6) { |
| 3363 FCSR_ = reg | kFCSRNaN2008FlagMask; | 3452 FCSR_ = reg | kFCSRNaN2008FlagMask; |
| 3364 } else { | 3453 } else { |
| 3365 DCHECK(kArchVariant == kMips64r2); | 3454 DCHECK(kArchVariant == kMips64r2); |
| 3366 FCSR_ = reg & ~kFCSRNaN2008FlagMask; | 3455 FCSR_ = reg & ~kFCSRNaN2008FlagMask; |
| 3367 } | 3456 } |
| 3457 TraceRegWr(FCSR_); |
| 3368 break; | 3458 break; |
| 3369 } | 3459 } |
| 3370 case MTC1: | 3460 case MTC1: |
| 3371 // Hardware writes upper 32-bits to zero on mtc1. | 3461 // Hardware writes upper 32-bits to zero on mtc1. |
| 3372 set_fpu_register_hi_word(fs_reg(), 0); | 3462 set_fpu_register_hi_word(fs_reg(), 0); |
| 3373 set_fpu_register_word(fs_reg(), static_cast<int32_t>(rt())); | 3463 set_fpu_register_word(fs_reg(), static_cast<int32_t>(rt())); |
| 3464 TraceRegWr(get_fpu_register(fs_reg()), FLOAT_DOUBLE); |
| 3374 break; | 3465 break; |
| 3375 case DMTC1: | 3466 case DMTC1: |
| 3376 set_fpu_register(fs_reg(), rt()); | 3467 SetFPUResult2(fs_reg(), rt()); |
| 3377 break; | 3468 break; |
| 3378 case MTHC1: | 3469 case MTHC1: |
| 3379 set_fpu_register_hi_word(fs_reg(), static_cast<int32_t>(rt())); | 3470 set_fpu_register_hi_word(fs_reg(), static_cast<int32_t>(rt())); |
| 3471 TraceRegWr(get_fpu_register(fs_reg()), DOUBLE); |
| 3380 break; | 3472 break; |
| 3381 case S: | 3473 case S: |
| 3382 DecodeTypeRegisterSRsType(); | 3474 DecodeTypeRegisterSRsType(); |
| 3383 break; | 3475 break; |
| 3384 case D: | 3476 case D: |
| 3385 DecodeTypeRegisterDRsType(); | 3477 DecodeTypeRegisterDRsType(); |
| 3386 break; | 3478 break; |
| 3387 case W: | 3479 case W: |
| 3388 DecodeTypeRegisterWRsType(); | 3480 DecodeTypeRegisterWRsType(); |
| 3389 break; | 3481 break; |
| 3390 case L: | 3482 case L: |
| 3391 DecodeTypeRegisterLRsType(); | 3483 DecodeTypeRegisterLRsType(); |
| 3392 break; | 3484 break; |
| 3393 default: | 3485 default: |
| 3394 UNREACHABLE(); | 3486 UNREACHABLE(); |
| 3395 } | 3487 } |
| 3396 } | 3488 } |
| 3397 | 3489 |
| 3398 | 3490 |
| 3399 void Simulator::DecodeTypeRegisterCOP1X() { | 3491 void Simulator::DecodeTypeRegisterCOP1X() { |
| 3400 switch (instr_.FunctionFieldRaw()) { | 3492 switch (instr_.FunctionFieldRaw()) { |
| 3401 case MADD_S: { | 3493 case MADD_S: { |
| 3402 DCHECK(kArchVariant == kMips64r2); | 3494 DCHECK(kArchVariant == kMips64r2); |
| 3403 float fr, ft, fs; | 3495 float fr, ft, fs; |
| 3404 fr = get_fpu_register_float(fr_reg()); | 3496 fr = get_fpu_register_float(fr_reg()); |
| 3405 fs = get_fpu_register_float(fs_reg()); | 3497 fs = get_fpu_register_float(fs_reg()); |
| 3406 ft = get_fpu_register_float(ft_reg()); | 3498 ft = get_fpu_register_float(ft_reg()); |
| 3407 set_fpu_register_float(fd_reg(), fs * ft + fr); | 3499 SetFPUFloatResult(fd_reg(), fs * ft + fr); |
| 3408 break; | 3500 break; |
| 3409 } | 3501 } |
| 3410 case MSUB_S: { | 3502 case MSUB_S: { |
| 3411 DCHECK(kArchVariant == kMips64r2); | 3503 DCHECK(kArchVariant == kMips64r2); |
| 3412 float fr, ft, fs; | 3504 float fr, ft, fs; |
| 3413 fr = get_fpu_register_float(fr_reg()); | 3505 fr = get_fpu_register_float(fr_reg()); |
| 3414 fs = get_fpu_register_float(fs_reg()); | 3506 fs = get_fpu_register_float(fs_reg()); |
| 3415 ft = get_fpu_register_float(ft_reg()); | 3507 ft = get_fpu_register_float(ft_reg()); |
| 3416 set_fpu_register_float(fd_reg(), fs * ft - fr); | 3508 SetFPUFloatResult(fd_reg(), fs * ft - fr); |
| 3417 break; | 3509 break; |
| 3418 } | 3510 } |
| 3419 case MADD_D: { | 3511 case MADD_D: { |
| 3420 DCHECK(kArchVariant == kMips64r2); | 3512 DCHECK(kArchVariant == kMips64r2); |
| 3421 double fr, ft, fs; | 3513 double fr, ft, fs; |
| 3422 fr = get_fpu_register_double(fr_reg()); | 3514 fr = get_fpu_register_double(fr_reg()); |
| 3423 fs = get_fpu_register_double(fs_reg()); | 3515 fs = get_fpu_register_double(fs_reg()); |
| 3424 ft = get_fpu_register_double(ft_reg()); | 3516 ft = get_fpu_register_double(ft_reg()); |
| 3425 set_fpu_register_double(fd_reg(), fs * ft + fr); | 3517 SetFPUDoubleResult(fd_reg(), fs * ft + fr); |
| 3426 break; | 3518 break; |
| 3427 } | 3519 } |
| 3428 case MSUB_D: { | 3520 case MSUB_D: { |
| 3429 DCHECK(kArchVariant == kMips64r2); | 3521 DCHECK(kArchVariant == kMips64r2); |
| 3430 double fr, ft, fs; | 3522 double fr, ft, fs; |
| 3431 fr = get_fpu_register_double(fr_reg()); | 3523 fr = get_fpu_register_double(fr_reg()); |
| 3432 fs = get_fpu_register_double(fs_reg()); | 3524 fs = get_fpu_register_double(fs_reg()); |
| 3433 ft = get_fpu_register_double(ft_reg()); | 3525 ft = get_fpu_register_double(ft_reg()); |
| 3434 set_fpu_register_double(fd_reg(), fs * ft - fr); | 3526 SetFPUDoubleResult(fd_reg(), fs * ft - fr); |
| 3435 break; | 3527 break; |
| 3436 } | 3528 } |
| 3437 default: | 3529 default: |
| 3438 UNREACHABLE(); | 3530 UNREACHABLE(); |
| 3439 } | 3531 } |
| 3440 } | 3532 } |
| 3441 | 3533 |
| 3442 | 3534 |
| 3443 void Simulator::DecodeTypeRegisterSPECIAL() { | 3535 void Simulator::DecodeTypeRegisterSPECIAL() { |
| 3444 int64_t i64hilo; | 3536 int64_t i64hilo; |
| 3445 uint64_t u64hilo; | 3537 uint64_t u64hilo; |
| 3446 int64_t alu_out; | 3538 int64_t alu_out; |
| 3447 bool do_interrupt = false; | 3539 bool do_interrupt = false; |
| 3448 | 3540 |
| 3449 switch (instr_.FunctionFieldRaw()) { | 3541 switch (instr_.FunctionFieldRaw()) { |
| 3450 case SELEQZ_S: | 3542 case SELEQZ_S: |
| 3451 DCHECK(kArchVariant == kMips64r6); | 3543 DCHECK(kArchVariant == kMips64r6); |
| 3452 set_register(rd_reg(), rt() == 0 ? rs() : 0); | 3544 SetResult(rd_reg(), rt() == 0 ? rs() : 0); |
| 3453 break; | 3545 break; |
| 3454 case SELNEZ_S: | 3546 case SELNEZ_S: |
| 3455 DCHECK(kArchVariant == kMips64r6); | 3547 DCHECK(kArchVariant == kMips64r6); |
| 3456 set_register(rd_reg(), rt() != 0 ? rs() : 0); | 3548 SetResult(rd_reg(), rt() != 0 ? rs() : 0); |
| 3457 break; | 3549 break; |
| 3458 case JR: { | 3550 case JR: { |
| 3459 int64_t next_pc = rs(); | 3551 int64_t next_pc = rs(); |
| 3460 int64_t current_pc = get_pc(); | 3552 int64_t current_pc = get_pc(); |
| 3461 Instruction* branch_delay_instr = | 3553 Instruction* branch_delay_instr = |
| 3462 reinterpret_cast<Instruction*>(current_pc + Instruction::kInstrSize); | 3554 reinterpret_cast<Instruction*>(current_pc + Instruction::kInstrSize); |
| 3463 BranchDelayInstructionDecode(branch_delay_instr); | 3555 BranchDelayInstructionDecode(branch_delay_instr); |
| 3464 set_pc(next_pc); | 3556 set_pc(next_pc); |
| 3465 pc_modified_ = true; | 3557 pc_modified_ = true; |
| 3466 break; | 3558 break; |
| (...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3629 case MULT: { // MULT == D_MUL_MUH. | 3721 case MULT: { // MULT == D_MUL_MUH. |
| 3630 int32_t rs_lo = static_cast<int32_t>(rs()); | 3722 int32_t rs_lo = static_cast<int32_t>(rs()); |
| 3631 int32_t rt_lo = static_cast<int32_t>(rt()); | 3723 int32_t rt_lo = static_cast<int32_t>(rt()); |
| 3632 i64hilo = static_cast<int64_t>(rs_lo) * static_cast<int64_t>(rt_lo); | 3724 i64hilo = static_cast<int64_t>(rs_lo) * static_cast<int64_t>(rt_lo); |
| 3633 if (kArchVariant != kMips64r6) { | 3725 if (kArchVariant != kMips64r6) { |
| 3634 set_register(LO, static_cast<int32_t>(i64hilo & 0xffffffff)); | 3726 set_register(LO, static_cast<int32_t>(i64hilo & 0xffffffff)); |
| 3635 set_register(HI, static_cast<int32_t>(i64hilo >> 32)); | 3727 set_register(HI, static_cast<int32_t>(i64hilo >> 32)); |
| 3636 } else { | 3728 } else { |
| 3637 switch (sa()) { | 3729 switch (sa()) { |
| 3638 case MUL_OP: | 3730 case MUL_OP: |
| 3639 set_register(rd_reg(), static_cast<int32_t>(i64hilo & 0xffffffff)); | 3731 SetResult(rd_reg(), static_cast<int32_t>(i64hilo & 0xffffffff)); |
| 3640 break; | 3732 break; |
| 3641 case MUH_OP: | 3733 case MUH_OP: |
| 3642 set_register(rd_reg(), static_cast<int32_t>(i64hilo >> 32)); | 3734 SetResult(rd_reg(), static_cast<int32_t>(i64hilo >> 32)); |
| 3643 break; | 3735 break; |
| 3644 default: | 3736 default: |
| 3645 UNIMPLEMENTED_MIPS(); | 3737 UNIMPLEMENTED_MIPS(); |
| 3646 break; | 3738 break; |
| 3647 } | 3739 } |
| 3648 } | 3740 } |
| 3649 break; | 3741 break; |
| 3650 } | 3742 } |
| 3651 case MULTU: | 3743 case MULTU: |
| 3652 u64hilo = static_cast<uint64_t>(rs_u() & 0xffffffff) * | 3744 u64hilo = static_cast<uint64_t>(rs_u() & 0xffffffff) * |
| 3653 static_cast<uint64_t>(rt_u() & 0xffffffff); | 3745 static_cast<uint64_t>(rt_u() & 0xffffffff); |
| 3654 if (kArchVariant != kMips64r6) { | 3746 if (kArchVariant != kMips64r6) { |
| 3655 set_register(LO, static_cast<int32_t>(u64hilo & 0xffffffff)); | 3747 set_register(LO, static_cast<int32_t>(u64hilo & 0xffffffff)); |
| 3656 set_register(HI, static_cast<int32_t>(u64hilo >> 32)); | 3748 set_register(HI, static_cast<int32_t>(u64hilo >> 32)); |
| 3657 } else { | 3749 } else { |
| 3658 switch (sa()) { | 3750 switch (sa()) { |
| 3659 case MUL_OP: | 3751 case MUL_OP: |
| 3660 set_register(rd_reg(), static_cast<int32_t>(u64hilo & 0xffffffff)); | 3752 SetResult(rd_reg(), static_cast<int32_t>(u64hilo & 0xffffffff)); |
| 3661 break; | 3753 break; |
| 3662 case MUH_OP: | 3754 case MUH_OP: |
| 3663 set_register(rd_reg(), static_cast<int32_t>(u64hilo >> 32)); | 3755 SetResult(rd_reg(), static_cast<int32_t>(u64hilo >> 32)); |
| 3664 break; | 3756 break; |
| 3665 default: | 3757 default: |
| 3666 UNIMPLEMENTED_MIPS(); | 3758 UNIMPLEMENTED_MIPS(); |
| 3667 break; | 3759 break; |
| 3668 } | 3760 } |
| 3669 } | 3761 } |
| 3670 break; | 3762 break; |
| 3671 case DMULT: // DMULT == D_MUL_MUH. | 3763 case DMULT: // DMULT == D_MUL_MUH. |
| 3672 if (kArchVariant != kMips64r6) { | 3764 if (kArchVariant != kMips64r6) { |
| 3673 set_register(LO, rs() * rt()); | 3765 set_register(LO, rs() * rt()); |
| 3674 set_register(HI, MultiplyHighSigned(rs(), rt())); | 3766 set_register(HI, MultiplyHighSigned(rs(), rt())); |
| 3675 } else { | 3767 } else { |
| 3676 switch (sa()) { | 3768 switch (sa()) { |
| 3677 case MUL_OP: | 3769 case MUL_OP: |
| 3678 set_register(rd_reg(), rs() * rt()); | 3770 SetResult(rd_reg(), rs() * rt()); |
| 3679 break; | 3771 break; |
| 3680 case MUH_OP: | 3772 case MUH_OP: |
| 3681 set_register(rd_reg(), MultiplyHighSigned(rs(), rt())); | 3773 SetResult(rd_reg(), MultiplyHighSigned(rs(), rt())); |
| 3682 break; | 3774 break; |
| 3683 default: | 3775 default: |
| 3684 UNIMPLEMENTED_MIPS(); | 3776 UNIMPLEMENTED_MIPS(); |
| 3685 break; | 3777 break; |
| 3686 } | 3778 } |
| 3687 } | 3779 } |
| 3688 break; | 3780 break; |
| 3689 case DMULTU: | 3781 case DMULTU: |
| 3690 UNIMPLEMENTED_MIPS(); | 3782 UNIMPLEMENTED_MIPS(); |
| 3691 break; | 3783 break; |
| (...skipping 12 matching lines...) Expand all Loading... |
| 3704 set_register(HI, 0); | 3796 set_register(HI, 0); |
| 3705 } else if (rt() != 0) { | 3797 } else if (rt() != 0) { |
| 3706 set_register(LO, rs() / rt()); | 3798 set_register(LO, rs() / rt()); |
| 3707 set_register(HI, rs() % rt()); | 3799 set_register(HI, rs() % rt()); |
| 3708 } | 3800 } |
| 3709 break; | 3801 break; |
| 3710 case kMips64r6: | 3802 case kMips64r6: |
| 3711 switch (sa()) { | 3803 switch (sa()) { |
| 3712 case DIV_OP: | 3804 case DIV_OP: |
| 3713 if (rs() == int_min_value && rt() == -1) { | 3805 if (rs() == int_min_value && rt() == -1) { |
| 3714 set_register(rd_reg(), int_min_value); | 3806 SetResult(rd_reg(), int_min_value); |
| 3715 } else if (rt() != 0) { | 3807 } else if (rt() != 0) { |
| 3716 set_register(rd_reg(), rs() / rt()); | 3808 SetResult(rd_reg(), rs() / rt()); |
| 3717 } | 3809 } |
| 3718 break; | 3810 break; |
| 3719 case MOD_OP: | 3811 case MOD_OP: |
| 3720 if (rs() == int_min_value && rt() == -1) { | 3812 if (rs() == int_min_value && rt() == -1) { |
| 3721 set_register(rd_reg(), 0); | 3813 SetResult(rd_reg(), 0); |
| 3722 } else if (rt() != 0) { | 3814 } else if (rt() != 0) { |
| 3723 set_register(rd_reg(), rs() % rt()); | 3815 SetResult(rd_reg(), rs() % rt()); |
| 3724 } | 3816 } |
| 3725 break; | 3817 break; |
| 3726 default: | 3818 default: |
| 3727 UNIMPLEMENTED_MIPS(); | 3819 UNIMPLEMENTED_MIPS(); |
| 3728 break; | 3820 break; |
| 3729 } | 3821 } |
| 3730 break; | 3822 break; |
| 3731 default: | 3823 default: |
| 3732 break; | 3824 break; |
| 3733 } | 3825 } |
| 3734 break; | 3826 break; |
| 3735 } | 3827 } |
| 3736 case DIVU: | 3828 case DIVU: |
| 3737 switch (kArchVariant) { | 3829 switch (kArchVariant) { |
| 3738 case kMips64r6: { | 3830 case kMips64r6: { |
| 3739 uint32_t rt_u_32 = static_cast<uint32_t>(rt_u()); | 3831 uint32_t rt_u_32 = static_cast<uint32_t>(rt_u()); |
| 3740 uint32_t rs_u_32 = static_cast<uint32_t>(rs_u()); | 3832 uint32_t rs_u_32 = static_cast<uint32_t>(rs_u()); |
| 3741 switch (sa()) { | 3833 switch (sa()) { |
| 3742 case DIV_OP: | 3834 case DIV_OP: |
| 3743 if (rt_u_32 != 0) { | 3835 if (rt_u_32 != 0) { |
| 3744 set_register(rd_reg(), rs_u_32 / rt_u_32); | 3836 SetResult(rd_reg(), rs_u_32 / rt_u_32); |
| 3745 } | 3837 } |
| 3746 break; | 3838 break; |
| 3747 case MOD_OP: | 3839 case MOD_OP: |
| 3748 if (rt_u() != 0) { | 3840 if (rt_u() != 0) { |
| 3749 set_register(rd_reg(), rs_u_32 % rt_u_32); | 3841 SetResult(rd_reg(), rs_u_32 % rt_u_32); |
| 3750 } | 3842 } |
| 3751 break; | 3843 break; |
| 3752 default: | 3844 default: |
| 3753 UNIMPLEMENTED_MIPS(); | 3845 UNIMPLEMENTED_MIPS(); |
| 3754 break; | 3846 break; |
| 3755 } | 3847 } |
| 3756 } break; | 3848 } break; |
| 3757 default: { | 3849 default: { |
| 3758 if (rt_u() != 0) { | 3850 if (rt_u() != 0) { |
| 3759 uint32_t rt_u_32 = static_cast<uint32_t>(rt_u()); | 3851 uint32_t rt_u_32 = static_cast<uint32_t>(rt_u()); |
| 3760 uint32_t rs_u_32 = static_cast<uint32_t>(rs_u()); | 3852 uint32_t rs_u_32 = static_cast<uint32_t>(rs_u()); |
| 3761 set_register(LO, rs_u_32 / rt_u_32); | 3853 set_register(LO, rs_u_32 / rt_u_32); |
| 3762 set_register(HI, rs_u_32 % rt_u_32); | 3854 set_register(HI, rs_u_32 % rt_u_32); |
| 3763 } | 3855 } |
| 3764 } | 3856 } |
| 3765 } | 3857 } |
| 3766 break; | 3858 break; |
| 3767 case DDIVU: | 3859 case DDIVU: |
| 3768 switch (kArchVariant) { | 3860 switch (kArchVariant) { |
| 3769 case kMips64r6: { | 3861 case kMips64r6: { |
| 3770 switch (instr_.SaValue()) { | 3862 switch (instr_.SaValue()) { |
| 3771 case DIV_OP: | 3863 case DIV_OP: |
| 3772 if (rt_u() != 0) { | 3864 if (rt_u() != 0) { |
| 3773 set_register(rd_reg(), rs_u() / rt_u()); | 3865 SetResult(rd_reg(), rs_u() / rt_u()); |
| 3774 } | 3866 } |
| 3775 break; | 3867 break; |
| 3776 case MOD_OP: | 3868 case MOD_OP: |
| 3777 if (rt_u() != 0) { | 3869 if (rt_u() != 0) { |
| 3778 set_register(rd_reg(), rs_u() % rt_u()); | 3870 SetResult(rd_reg(), rs_u() % rt_u()); |
| 3779 } | 3871 } |
| 3780 break; | 3872 break; |
| 3781 default: | 3873 default: |
| 3782 UNIMPLEMENTED_MIPS(); | 3874 UNIMPLEMENTED_MIPS(); |
| 3783 break; | 3875 break; |
| 3784 } | 3876 } |
| 3785 } break; | 3877 } break; |
| 3786 default: { | 3878 default: { |
| 3787 if (rt_u() != 0) { | 3879 if (rt_u() != 0) { |
| 3788 set_register(LO, rs_u() / rt_u()); | 3880 set_register(LO, rs_u() / rt_u()); |
| (...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3885 // Conditional moves. | 3977 // Conditional moves. |
| 3886 case MOVN: | 3978 case MOVN: |
| 3887 if (rt()) { | 3979 if (rt()) { |
| 3888 SetResult(rd_reg(), rs()); | 3980 SetResult(rd_reg(), rs()); |
| 3889 } | 3981 } |
| 3890 break; | 3982 break; |
| 3891 case MOVCI: { | 3983 case MOVCI: { |
| 3892 uint32_t cc = instr_.FBccValue(); | 3984 uint32_t cc = instr_.FBccValue(); |
| 3893 uint32_t fcsr_cc = get_fcsr_condition_bit(cc); | 3985 uint32_t fcsr_cc = get_fcsr_condition_bit(cc); |
| 3894 if (instr_.Bit(16)) { // Read Tf bit. | 3986 if (instr_.Bit(16)) { // Read Tf bit. |
| 3895 if (test_fcsr_bit(fcsr_cc)) set_register(rd_reg(), rs()); | 3987 if (test_fcsr_bit(fcsr_cc)) SetResult(rd_reg(), rs()); |
| 3896 } else { | 3988 } else { |
| 3897 if (!test_fcsr_bit(fcsr_cc)) set_register(rd_reg(), rs()); | 3989 if (!test_fcsr_bit(fcsr_cc)) SetResult(rd_reg(), rs()); |
| 3898 } | 3990 } |
| 3899 break; | 3991 break; |
| 3900 } | 3992 } |
| 3901 case MOVZ: | 3993 case MOVZ: |
| 3902 if (!rt()) { | 3994 if (!rt()) { |
| 3903 SetResult(rd_reg(), rs()); | 3995 SetResult(rd_reg(), rs()); |
| 3904 } | 3996 } |
| 3905 break; | 3997 break; |
| 3906 default: | 3998 default: |
| 3907 UNREACHABLE(); | 3999 UNREACHABLE(); |
| (...skipping 774 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4682 uint8_t al_offset = (rs + se_imm16) & kInt64AlignmentMask; | 4774 uint8_t al_offset = (rs + se_imm16) & kInt64AlignmentMask; |
| 4683 uint64_t mask = (1UL << al_offset * 8) - 1; | 4775 uint64_t mask = (1UL << al_offset * 8) - 1; |
| 4684 addr = rs + se_imm16 - al_offset; | 4776 addr = rs + se_imm16 - al_offset; |
| 4685 uint64_t mem_value = Read2W(addr, instr_.instr()); | 4777 uint64_t mem_value = Read2W(addr, instr_.instr()); |
| 4686 mem_value = (rt << al_offset * 8) | (mem_value & mask); | 4778 mem_value = (rt << al_offset * 8) | (mem_value & mask); |
| 4687 Write2W(addr, mem_value, instr_.instr()); | 4779 Write2W(addr, mem_value, instr_.instr()); |
| 4688 break; | 4780 break; |
| 4689 } | 4781 } |
| 4690 case LWC1: | 4782 case LWC1: |
| 4691 set_fpu_register(ft_reg, kFPUInvalidResult); // Trash upper 32 bits. | 4783 set_fpu_register(ft_reg, kFPUInvalidResult); // Trash upper 32 bits. |
| 4692 set_fpu_register_word(ft_reg, ReadW(rs + se_imm16, instr_.instr())); | 4784 set_fpu_register_word(ft_reg, |
| 4785 ReadW(rs + se_imm16, instr_.instr(), FLOAT_DOUBLE)); |
| 4693 break; | 4786 break; |
| 4694 case LDC1: | 4787 case LDC1: |
| 4695 set_fpu_register_double(ft_reg, ReadD(rs + se_imm16, instr_.instr())); | 4788 set_fpu_register_double(ft_reg, ReadD(rs + se_imm16, instr_.instr())); |
| 4789 TraceMemRd(addr, get_fpu_register(ft_reg), DOUBLE); |
| 4696 break; | 4790 break; |
| 4697 case SWC1: { | 4791 case SWC1: { |
| 4698 int32_t alu_out_32 = static_cast<int32_t>(get_fpu_register(ft_reg)); | 4792 int32_t alu_out_32 = static_cast<int32_t>(get_fpu_register(ft_reg)); |
| 4699 WriteW(rs + se_imm16, alu_out_32, instr_.instr()); | 4793 WriteW(rs + se_imm16, alu_out_32, instr_.instr()); |
| 4700 break; | 4794 break; |
| 4701 } | 4795 } |
| 4702 case SDC1: | 4796 case SDC1: |
| 4703 WriteD(rs + se_imm16, get_fpu_register_double(ft_reg), instr_.instr()); | 4797 WriteD(rs + se_imm16, get_fpu_register_double(ft_reg), instr_.instr()); |
| 4798 TraceMemWr(rs + se_imm16, get_fpu_register(ft_reg), DWORD); |
| 4704 break; | 4799 break; |
| 4705 // ------------- PC-Relative instructions. | 4800 // ------------- PC-Relative instructions. |
| 4706 case PCREL: { | 4801 case PCREL: { |
| 4707 // rt field: checking 5-bits. | 4802 // rt field: checking 5-bits. |
| 4708 int32_t imm21 = instr_.Imm21Value(); | 4803 int32_t imm21 = instr_.Imm21Value(); |
| 4709 int64_t current_pc = get_pc(); | 4804 int64_t current_pc = get_pc(); |
| 4710 uint8_t rt = (imm21 >> kImm16Bits); | 4805 uint8_t rt = (imm21 >> kImm16Bits); |
| 4711 switch (rt) { | 4806 switch (rt) { |
| 4712 case ALUIPC: | 4807 case ALUIPC: |
| 4713 addr = current_pc + (se_imm16 << 16); | 4808 addr = current_pc + (se_imm16 << 16); |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4757 default: | 4852 default: |
| 4758 UNREACHABLE(); | 4853 UNREACHABLE(); |
| 4759 break; | 4854 break; |
| 4760 } | 4855 } |
| 4761 break; | 4856 break; |
| 4762 } | 4857 } |
| 4763 } | 4858 } |
| 4764 break; | 4859 break; |
| 4765 } | 4860 } |
| 4766 } | 4861 } |
| 4767 set_register(rs_reg, alu_out); | 4862 SetResult(rs_reg, alu_out); |
| 4768 break; | 4863 break; |
| 4769 } | 4864 } |
| 4770 default: | 4865 default: |
| 4771 UNREACHABLE(); | 4866 UNREACHABLE(); |
| 4772 } | 4867 } |
| 4773 | 4868 |
| 4774 if (execute_branch_delay_instruction) { | 4869 if (execute_branch_delay_instruction) { |
| 4775 // Execute branch delay slot | 4870 // Execute branch delay slot |
| 4776 // We don't check for end_sim_pc. First it should not be met as the current | 4871 // We don't check for end_sim_pc. First it should not be met as the current |
| 4777 // pc is valid. Secondly a jump should always execute its branch delay slot. | 4872 // pc is valid. Secondly a jump should always execute its branch delay slot. |
| (...skipping 274 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5052 } | 5147 } |
| 5053 | 5148 |
| 5054 | 5149 |
| 5055 #undef UNSUPPORTED | 5150 #undef UNSUPPORTED |
| 5056 } // namespace internal | 5151 } // namespace internal |
| 5057 } // namespace v8 | 5152 } // namespace v8 |
| 5058 | 5153 |
| 5059 #endif // USE_SIMULATOR | 5154 #endif // USE_SIMULATOR |
| 5060 | 5155 |
| 5061 #endif // V8_TARGET_ARCH_MIPS64 | 5156 #endif // V8_TARGET_ARCH_MIPS64 |
| OLD | NEW |