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_MIPS | 10 #if V8_TARGET_ARCH_MIPS |
(...skipping 1111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1122 // Read the bits from the unsigned integer register_[] array | 1122 // Read the bits from the unsigned integer register_[] array |
1123 // into the double precision floating point value and return it. | 1123 // into the double precision floating point value and return it. |
1124 char buffer[2 * sizeof(registers_[0])]; | 1124 char buffer[2 * sizeof(registers_[0])]; |
1125 memcpy(buffer, ®isters_[reg], 2 * sizeof(registers_[0])); | 1125 memcpy(buffer, ®isters_[reg], 2 * sizeof(registers_[0])); |
1126 memcpy(&dm_val, buffer, 2 * sizeof(registers_[0])); | 1126 memcpy(&dm_val, buffer, 2 * sizeof(registers_[0])); |
1127 return(dm_val); | 1127 return(dm_val); |
1128 } | 1128 } |
1129 | 1129 |
1130 | 1130 |
1131 int64_t Simulator::get_fpu_register(int fpureg) const { | 1131 int64_t Simulator::get_fpu_register(int fpureg) const { |
1132 DCHECK(IsFp64Mode()); | 1132 if (IsFp64Mode()) { |
1133 DCHECK((fpureg >= 0) && (fpureg < kNumFPURegisters)); | 1133 DCHECK((fpureg >= 0) && (fpureg < kNumFPURegisters)); |
1134 return FPUregisters_[fpureg]; | 1134 return FPUregisters_[fpureg]; |
| 1135 } else { |
| 1136 DCHECK((fpureg >= 0) && (fpureg < kNumFPURegisters) && ((fpureg % 2) == 0)); |
| 1137 uint64_t i64; |
| 1138 i64 = static_cast<uint32_t>(get_fpu_register_word(fpureg)); |
| 1139 i64 |= static_cast<uint64_t>(get_fpu_register_word(fpureg + 1)) << 32; |
| 1140 return static_cast<int64_t>(i64); |
| 1141 } |
1135 } | 1142 } |
1136 | 1143 |
1137 | 1144 |
1138 int32_t Simulator::get_fpu_register_word(int fpureg) const { | 1145 int32_t Simulator::get_fpu_register_word(int fpureg) const { |
1139 DCHECK((fpureg >= 0) && (fpureg < kNumFPURegisters)); | 1146 DCHECK((fpureg >= 0) && (fpureg < kNumFPURegisters)); |
1140 return static_cast<int32_t>(FPUregisters_[fpureg] & 0xffffffff); | 1147 return static_cast<int32_t>(FPUregisters_[fpureg] & 0xffffffff); |
1141 } | 1148 } |
1142 | 1149 |
1143 | 1150 |
1144 int32_t Simulator::get_fpu_register_signed_word(int fpureg) const { | 1151 int32_t Simulator::get_fpu_register_signed_word(int fpureg) const { |
(...skipping 536 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1681 | 1688 |
1682 | 1689 |
1683 // The MIPS cannot do unaligned reads and writes. On some MIPS platforms an | 1690 // The MIPS cannot do unaligned reads and writes. On some MIPS platforms an |
1684 // interrupt is caused. On others it does a funky rotation thing. For now we | 1691 // interrupt is caused. On others it does a funky rotation thing. For now we |
1685 // simply disallow unaligned reads, but at some point we may want to move to | 1692 // simply disallow unaligned reads, but at some point we may want to move to |
1686 // emulating the rotate behaviour. Note that simulator runs have the runtime | 1693 // emulating the rotate behaviour. Note that simulator runs have the runtime |
1687 // system running directly on the host system and only generated code is | 1694 // system running directly on the host system and only generated code is |
1688 // executed in the simulator. Since the host is typically IA32 we will not | 1695 // executed in the simulator. Since the host is typically IA32 we will not |
1689 // get the correct MIPS-like behaviour on unaligned accesses. | 1696 // get the correct MIPS-like behaviour on unaligned accesses. |
1690 | 1697 |
1691 void Simulator::TraceRegWr(int32_t value) { | 1698 void Simulator::TraceRegWr(int32_t value, TraceType t) { |
1692 if (::v8::internal::FLAG_trace_sim) { | 1699 if (::v8::internal::FLAG_trace_sim) { |
1693 SNPrintF(trace_buf_, "%08x", value); | 1700 union { |
| 1701 int32_t fmt_int32; |
| 1702 float fmt_float; |
| 1703 } v; |
| 1704 v.fmt_int32 = value; |
| 1705 |
| 1706 switch (t) { |
| 1707 case WORD: |
| 1708 SNPrintF(trace_buf_, "%08" PRIx32 " (%" PRIu64 ") int32:%" PRId32 |
| 1709 " uint32:%" PRIu32, |
| 1710 value, icount_, value, value); |
| 1711 break; |
| 1712 case FLOAT: |
| 1713 SNPrintF(trace_buf_, "%08" PRIx32 " (%" PRIu64 ") flt:%e", |
| 1714 v.fmt_int32, icount_, v.fmt_float); |
| 1715 break; |
| 1716 default: |
| 1717 UNREACHABLE(); |
| 1718 } |
1694 } | 1719 } |
1695 } | 1720 } |
1696 | 1721 |
| 1722 void Simulator::TraceRegWr(int64_t value, TraceType t) { |
| 1723 if (::v8::internal::FLAG_trace_sim) { |
| 1724 union { |
| 1725 int64_t fmt_int64; |
| 1726 double fmt_double; |
| 1727 } v; |
| 1728 v.fmt_int64 = value; |
1697 | 1729 |
1698 // TODO(plind): consider making icount_ printing a flag option. | 1730 switch (t) { |
1699 void Simulator::TraceMemRd(int32_t addr, int32_t value) { | 1731 case DWORD: |
1700 if (::v8::internal::FLAG_trace_sim) { | 1732 SNPrintF(trace_buf_, "%016" PRIx64 " (%" PRIu64 ") int64:%" PRId64 |
1701 SNPrintF(trace_buf_, "%08x <-- [%08x] (%" PRIu64 ")", value, addr, | 1733 " uint64:%" PRIu64, |
1702 icount_); | 1734 value, icount_, value, value); |
| 1735 break; |
| 1736 case DOUBLE: |
| 1737 SNPrintF(trace_buf_, "%016" PRIx64 " (%" PRIu64 ") dbl:%e", |
| 1738 v.fmt_int64, icount_, v.fmt_double); |
| 1739 break; |
| 1740 default: |
| 1741 UNREACHABLE(); |
| 1742 } |
1703 } | 1743 } |
1704 } | 1744 } |
1705 | 1745 |
| 1746 // TODO(plind): consider making icount_ printing a flag option. |
| 1747 void Simulator::TraceMemRd(int32_t addr, int32_t value, TraceType t) { |
| 1748 if (::v8::internal::FLAG_trace_sim) { |
| 1749 union { |
| 1750 int32_t fmt_int32; |
| 1751 float fmt_float; |
| 1752 } v; |
| 1753 v.fmt_int32 = value; |
| 1754 |
| 1755 switch (t) { |
| 1756 case WORD: |
| 1757 SNPrintF(trace_buf_, "%08" PRIx32 " <-- [%08" PRIx32 "] (%" PRIu64 |
| 1758 ") int32:%" PRId32 " uint32:%" PRIu32, |
| 1759 value, addr, icount_, value, value); |
| 1760 break; |
| 1761 case FLOAT: |
| 1762 SNPrintF(trace_buf_, |
| 1763 "%08" PRIx32 " <-- [%08" PRIx32 "] (%" PRIu64 ") flt:%e", |
| 1764 v.fmt_int32, addr, icount_, v.fmt_float); |
| 1765 break; |
| 1766 default: |
| 1767 UNREACHABLE(); |
| 1768 } |
| 1769 } |
| 1770 } |
| 1771 |
1706 | 1772 |
1707 void Simulator::TraceMemWr(int32_t addr, int32_t value, TraceType t) { | 1773 void Simulator::TraceMemWr(int32_t addr, int32_t value, TraceType t) { |
1708 if (::v8::internal::FLAG_trace_sim) { | 1774 if (::v8::internal::FLAG_trace_sim) { |
1709 switch (t) { | 1775 switch (t) { |
1710 case BYTE: | 1776 case BYTE: |
1711 SNPrintF(trace_buf_, " %02x --> [%08x]", | 1777 SNPrintF(trace_buf_, |
1712 static_cast<int8_t>(value), addr); | 1778 " %02" PRIx8 " --> [%08" PRIx32 "] (%" PRIu64 ")", |
| 1779 static_cast<uint8_t>(value), addr, icount_); |
1713 break; | 1780 break; |
1714 case HALF: | 1781 case HALF: |
1715 SNPrintF(trace_buf_, " %04x --> [%08x]", static_cast<int16_t>(value), | 1782 SNPrintF(trace_buf_, |
1716 addr); | 1783 " %04" PRIx16 " --> [%08" PRIx32 "] (%" PRIu64 ")", |
| 1784 static_cast<uint16_t>(value), addr, icount_); |
1717 break; | 1785 break; |
1718 case WORD: | 1786 case WORD: |
1719 SNPrintF(trace_buf_, "%08x --> [%08x]", value, addr); | 1787 SNPrintF(trace_buf_, |
| 1788 "%08" PRIx32 " --> [%08" PRIx32 "] (%" PRIu64 ")", value, |
| 1789 addr, icount_); |
1720 break; | 1790 break; |
| 1791 default: |
| 1792 UNREACHABLE(); |
1721 } | 1793 } |
1722 } | 1794 } |
1723 } | 1795 } |
1724 | 1796 |
| 1797 void Simulator::TraceMemRd(int32_t addr, int64_t value, TraceType t) { |
| 1798 if (::v8::internal::FLAG_trace_sim) { |
| 1799 union { |
| 1800 int64_t fmt_int64; |
| 1801 int32_t fmt_int32[2]; |
| 1802 float fmt_float[2]; |
| 1803 double fmt_double; |
| 1804 } v; |
| 1805 v.fmt_int64 = value; |
1725 | 1806 |
1726 int Simulator::ReadW(int32_t addr, Instruction* instr) { | 1807 switch (t) { |
| 1808 case DWORD: |
| 1809 SNPrintF(trace_buf_, "%016" PRIx64 " <-- [%08" PRIx32 "] (%" PRIu64 |
| 1810 ") int64:%" PRId64 " uint64:%" PRIu64, |
| 1811 v.fmt_int64, addr, icount_, v.fmt_int64, v.fmt_int64); |
| 1812 break; |
| 1813 case DOUBLE: |
| 1814 SNPrintF(trace_buf_, "%016" PRIx64 " <-- [%08" PRIx32 "] (%" PRIu64 |
| 1815 ") dbl:%e", |
| 1816 v.fmt_int64, addr, icount_, v.fmt_double); |
| 1817 break; |
| 1818 case FLOAT_DOUBLE: |
| 1819 SNPrintF(trace_buf_, "%08" PRIx32 " <-- [%08" PRIx32 "] (%" PRIu64 |
| 1820 ") flt:%e dbl:%e", |
| 1821 v.fmt_int32[1], addr, icount_, v.fmt_float[1], v.fmt_double); |
| 1822 break; |
| 1823 default: |
| 1824 UNREACHABLE(); |
| 1825 } |
| 1826 } |
| 1827 } |
| 1828 |
| 1829 void Simulator::TraceMemWr(int32_t addr, int64_t value, TraceType t) { |
| 1830 if (::v8::internal::FLAG_trace_sim) { |
| 1831 switch (t) { |
| 1832 case DWORD: |
| 1833 SNPrintF(trace_buf_, |
| 1834 "%016" PRIx64 " --> [%08" PRIx32 "] (%" PRIu64 ")", value, |
| 1835 addr, icount_); |
| 1836 break; |
| 1837 default: |
| 1838 UNREACHABLE(); |
| 1839 } |
| 1840 } |
| 1841 } |
| 1842 |
| 1843 int Simulator::ReadW(int32_t addr, Instruction* instr, TraceType t) { |
1727 if (addr >=0 && addr < 0x400) { | 1844 if (addr >=0 && addr < 0x400) { |
1728 // This has to be a NULL-dereference, drop into debugger. | 1845 // This has to be a NULL-dereference, drop into debugger. |
1729 PrintF("Memory read from bad address: 0x%08x, pc=0x%08" PRIxPTR "\n", addr, | 1846 PrintF("Memory read from bad address: 0x%08x, pc=0x%08" PRIxPTR "\n", addr, |
1730 reinterpret_cast<intptr_t>(instr)); | 1847 reinterpret_cast<intptr_t>(instr)); |
1731 MipsDebugger dbg(this); | 1848 MipsDebugger dbg(this); |
1732 dbg.Debug(); | 1849 dbg.Debug(); |
1733 } | 1850 } |
1734 if ((addr & kPointerAlignmentMask) == 0 || IsMipsArchVariant(kMips32r6)) { | 1851 if ((addr & kPointerAlignmentMask) == 0 || IsMipsArchVariant(kMips32r6)) { |
1735 intptr_t* ptr = reinterpret_cast<intptr_t*>(addr); | 1852 intptr_t* ptr = reinterpret_cast<intptr_t*>(addr); |
1736 TraceMemRd(addr, static_cast<int32_t>(*ptr)); | 1853 switch (t) { |
| 1854 case WORD: |
| 1855 TraceMemRd(addr, static_cast<int32_t>(*ptr), t); |
| 1856 break; |
| 1857 case FLOAT: |
| 1858 // This TraceType is allowed but tracing for this value will be omitted. |
| 1859 break; |
| 1860 default: |
| 1861 UNREACHABLE(); |
| 1862 } |
1737 return *ptr; | 1863 return *ptr; |
1738 } | 1864 } |
1739 PrintF("Unaligned read at 0x%08x, pc=0x%08" V8PRIxPTR "\n", | 1865 PrintF("Unaligned read at 0x%08x, pc=0x%08" V8PRIxPTR "\n", |
1740 addr, | 1866 addr, |
1741 reinterpret_cast<intptr_t>(instr)); | 1867 reinterpret_cast<intptr_t>(instr)); |
1742 MipsDebugger dbg(this); | 1868 MipsDebugger dbg(this); |
1743 dbg.Debug(); | 1869 dbg.Debug(); |
1744 return 0; | 1870 return 0; |
1745 } | 1871 } |
1746 | 1872 |
1747 | |
1748 void Simulator::WriteW(int32_t addr, int value, Instruction* instr) { | 1873 void Simulator::WriteW(int32_t addr, int value, Instruction* instr) { |
1749 if (addr >= 0 && addr < 0x400) { | 1874 if (addr >= 0 && addr < 0x400) { |
1750 // This has to be a NULL-dereference, drop into debugger. | 1875 // This has to be a NULL-dereference, drop into debugger. |
1751 PrintF("Memory write to bad address: 0x%08x, pc=0x%08" PRIxPTR "\n", addr, | 1876 PrintF("Memory write to bad address: 0x%08x, pc=0x%08" PRIxPTR "\n", addr, |
1752 reinterpret_cast<intptr_t>(instr)); | 1877 reinterpret_cast<intptr_t>(instr)); |
1753 MipsDebugger dbg(this); | 1878 MipsDebugger dbg(this); |
1754 dbg.Debug(); | 1879 dbg.Debug(); |
1755 } | 1880 } |
1756 if ((addr & kPointerAlignmentMask) == 0 || IsMipsArchVariant(kMips32r6)) { | 1881 if ((addr & kPointerAlignmentMask) == 0 || IsMipsArchVariant(kMips32r6)) { |
1757 intptr_t* ptr = reinterpret_cast<intptr_t*>(addr); | 1882 intptr_t* ptr = reinterpret_cast<intptr_t*>(addr); |
1758 TraceMemWr(addr, value, WORD); | 1883 TraceMemWr(addr, value, WORD); |
1759 *ptr = value; | 1884 *ptr = value; |
1760 return; | 1885 return; |
1761 } | 1886 } |
1762 PrintF("Unaligned write at 0x%08x, pc=0x%08" V8PRIxPTR "\n", | 1887 PrintF("Unaligned write at 0x%08x, pc=0x%08" V8PRIxPTR "\n", |
1763 addr, | 1888 addr, |
1764 reinterpret_cast<intptr_t>(instr)); | 1889 reinterpret_cast<intptr_t>(instr)); |
1765 MipsDebugger dbg(this); | 1890 MipsDebugger dbg(this); |
1766 dbg.Debug(); | 1891 dbg.Debug(); |
1767 } | 1892 } |
1768 | 1893 |
1769 | |
1770 double Simulator::ReadD(int32_t addr, Instruction* instr) { | 1894 double Simulator::ReadD(int32_t addr, Instruction* instr) { |
1771 if ((addr & kDoubleAlignmentMask) == 0 || IsMipsArchVariant(kMips32r6)) { | 1895 if ((addr & kDoubleAlignmentMask) == 0 || IsMipsArchVariant(kMips32r6)) { |
1772 double* ptr = reinterpret_cast<double*>(addr); | 1896 double* ptr = reinterpret_cast<double*>(addr); |
1773 return *ptr; | 1897 return *ptr; |
1774 } | 1898 } |
1775 PrintF("Unaligned (double) read at 0x%08x, pc=0x%08" V8PRIxPTR "\n", | 1899 PrintF("Unaligned (double) read at 0x%08x, pc=0x%08" V8PRIxPTR "\n", |
1776 addr, | 1900 addr, |
1777 reinterpret_cast<intptr_t>(instr)); | 1901 reinterpret_cast<intptr_t>(instr)); |
1778 base::OS::Abort(); | 1902 base::OS::Abort(); |
1779 return 0; | 1903 return 0; |
(...skipping 673 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2453 case kRoundToZero: | 2577 case kRoundToZero: |
2454 result = (fs > 0 ? lower : upper); | 2578 result = (fs > 0 ? lower : upper); |
2455 break; | 2579 break; |
2456 case kRoundToPlusInf: | 2580 case kRoundToPlusInf: |
2457 result = upper; | 2581 result = upper; |
2458 break; | 2582 break; |
2459 case kRoundToMinusInf: | 2583 case kRoundToMinusInf: |
2460 result = lower; | 2584 result = lower; |
2461 break; | 2585 break; |
2462 } | 2586 } |
2463 set_fpu_register_double(fd_reg(), result); | 2587 SetFPUDoubleResult(fd_reg(), result); |
2464 if (result != fs) { | 2588 if (result != fs) { |
2465 set_fcsr_bit(kFCSRInexactFlagBit, true); | 2589 set_fcsr_bit(kFCSRInexactFlagBit, true); |
2466 } | 2590 } |
2467 break; | 2591 break; |
2468 } | 2592 } |
2469 case SEL: | 2593 case SEL: |
2470 DCHECK(IsMipsArchVariant(kMips32r6)); | 2594 DCHECK(IsMipsArchVariant(kMips32r6)); |
2471 set_fpu_register_double(fd_reg(), (fd_int & 0x1) == 0 ? fs : ft); | 2595 SetFPUDoubleResult(fd_reg(), (fd_int & 0x1) == 0 ? fs : ft); |
2472 break; | 2596 break; |
2473 case SELEQZ_C: | 2597 case SELEQZ_C: |
2474 DCHECK(IsMipsArchVariant(kMips32r6)); | 2598 DCHECK(IsMipsArchVariant(kMips32r6)); |
2475 set_fpu_register_double(fd_reg(), (ft_int & 0x1) == 0 ? fs : 0.0); | 2599 SetFPUDoubleResult(fd_reg(), (ft_int & 0x1) == 0 ? fs : 0.0); |
2476 break; | 2600 break; |
2477 case SELNEZ_C: | 2601 case SELNEZ_C: |
2478 DCHECK(IsMipsArchVariant(kMips32r6)); | 2602 DCHECK(IsMipsArchVariant(kMips32r6)); |
2479 set_fpu_register_double(fd_reg(), (ft_int & 0x1) != 0 ? fs : 0.0); | 2603 SetFPUDoubleResult(fd_reg(), (ft_int & 0x1) != 0 ? fs : 0.0); |
2480 break; | 2604 break; |
2481 case MOVZ_C: { | 2605 case MOVZ_C: { |
2482 DCHECK(IsMipsArchVariant(kMips32r2)); | 2606 DCHECK(IsMipsArchVariant(kMips32r2)); |
2483 if (rt() == 0) { | 2607 if (rt() == 0) { |
2484 set_fpu_register_double(fd_reg(), fs); | 2608 SetFPUDoubleResult(fd_reg(), fs); |
2485 } | 2609 } |
2486 break; | 2610 break; |
2487 } | 2611 } |
2488 case MOVN_C: { | 2612 case MOVN_C: { |
2489 DCHECK(IsMipsArchVariant(kMips32r2)); | 2613 DCHECK(IsMipsArchVariant(kMips32r2)); |
2490 int32_t rt_reg = instr_.RtValue(); | 2614 int32_t rt_reg = instr_.RtValue(); |
2491 int32_t rt = get_register(rt_reg); | 2615 int32_t rt = get_register(rt_reg); |
2492 if (rt != 0) { | 2616 if (rt != 0) { |
2493 set_fpu_register_double(fd_reg(), fs); | 2617 SetFPUDoubleResult(fd_reg(), fs); |
2494 } | 2618 } |
2495 break; | 2619 break; |
2496 } | 2620 } |
2497 case MOVF: { | 2621 case MOVF: { |
2498 // Same function field for MOVT.D and MOVF.D | 2622 // Same function field for MOVT.D and MOVF.D |
2499 uint32_t ft_cc = (ft_reg() >> 2) & 0x7; | 2623 uint32_t ft_cc = (ft_reg() >> 2) & 0x7; |
2500 ft_cc = get_fcsr_condition_bit(ft_cc); | 2624 ft_cc = get_fcsr_condition_bit(ft_cc); |
2501 if (instr_.Bit(16)) { // Read Tf bit. | 2625 if (instr_.Bit(16)) { // Read Tf bit. |
2502 // MOVT.D | 2626 // MOVT.D |
2503 if (test_fcsr_bit(ft_cc)) set_fpu_register_double(fd_reg(), fs); | 2627 if (test_fcsr_bit(ft_cc)) SetFPUDoubleResult(fd_reg(), fs); |
2504 } else { | 2628 } else { |
2505 // MOVF.D | 2629 // MOVF.D |
2506 if (!test_fcsr_bit(ft_cc)) set_fpu_register_double(fd_reg(), fs); | 2630 if (!test_fcsr_bit(ft_cc)) SetFPUDoubleResult(fd_reg(), fs); |
2507 } | 2631 } |
2508 break; | 2632 break; |
2509 } | 2633 } |
2510 case MIN: | 2634 case MIN: |
2511 DCHECK(IsMipsArchVariant(kMips32r6)); | 2635 DCHECK(IsMipsArchVariant(kMips32r6)); |
2512 set_fpu_register_double(fd_reg(), FPUMin(ft, fs)); | 2636 SetFPUDoubleResult(fd_reg(), FPUMin(ft, fs)); |
2513 break; | 2637 break; |
2514 case MAX: | 2638 case MAX: |
2515 DCHECK(IsMipsArchVariant(kMips32r6)); | 2639 DCHECK(IsMipsArchVariant(kMips32r6)); |
2516 set_fpu_register_double(fd_reg(), FPUMax(ft, fs)); | 2640 SetFPUDoubleResult(fd_reg(), FPUMax(ft, fs)); |
2517 break; | 2641 break; |
2518 case MINA: | 2642 case MINA: |
2519 DCHECK(IsMipsArchVariant(kMips32r6)); | 2643 DCHECK(IsMipsArchVariant(kMips32r6)); |
2520 set_fpu_register_double(fd_reg(), FPUMinA(ft, fs)); | 2644 SetFPUDoubleResult(fd_reg(), FPUMinA(ft, fs)); |
2521 break; | 2645 break; |
2522 case MAXA: | 2646 case MAXA: |
2523 DCHECK(IsMipsArchVariant(kMips32r6)); | 2647 DCHECK(IsMipsArchVariant(kMips32r6)); |
2524 set_fpu_register_double(fd_reg(), FPUMaxA(ft, fs)); | 2648 SetFPUDoubleResult(fd_reg(), FPUMaxA(ft, fs)); |
2525 break; | 2649 break; |
2526 case ADD_D: | 2650 case ADD_D: |
2527 set_fpu_register_double( | 2651 SetFPUDoubleResult( |
2528 fd_reg(), | 2652 fd_reg(), |
2529 FPUCanonalizeOperation( | 2653 FPUCanonalizeOperation( |
2530 [](double lhs, double rhs) { return lhs + rhs; }, fs, ft)); | 2654 [](double lhs, double rhs) { return lhs + rhs; }, fs, ft)); |
2531 break; | 2655 break; |
2532 case SUB_D: | 2656 case SUB_D: |
2533 set_fpu_register_double( | 2657 SetFPUDoubleResult( |
2534 fd_reg(), | 2658 fd_reg(), |
2535 FPUCanonalizeOperation( | 2659 FPUCanonalizeOperation( |
2536 [](double lhs, double rhs) { return lhs - rhs; }, fs, ft)); | 2660 [](double lhs, double rhs) { return lhs - rhs; }, fs, ft)); |
2537 break; | 2661 break; |
2538 case MADDF_D: | 2662 case MADDF_D: |
2539 DCHECK(IsMipsArchVariant(kMips32r6)); | 2663 DCHECK(IsMipsArchVariant(kMips32r6)); |
2540 set_fpu_register_double(fd_reg(), std::fma(fs, ft, fd)); | 2664 SetFPUDoubleResult(fd_reg(), std::fma(fs, ft, fd)); |
2541 break; | 2665 break; |
2542 case MSUBF_D: | 2666 case MSUBF_D: |
2543 DCHECK(IsMipsArchVariant(kMips32r6)); | 2667 DCHECK(IsMipsArchVariant(kMips32r6)); |
2544 set_fpu_register_double(fd_reg(), std::fma(-fs, ft, fd)); | 2668 SetFPUDoubleResult(fd_reg(), std::fma(-fs, ft, fd)); |
2545 break; | 2669 break; |
2546 case MUL_D: | 2670 case MUL_D: |
2547 set_fpu_register_double( | 2671 SetFPUDoubleResult( |
2548 fd_reg(), | 2672 fd_reg(), |
2549 FPUCanonalizeOperation( | 2673 FPUCanonalizeOperation( |
2550 [](double lhs, double rhs) { return lhs * rhs; }, fs, ft)); | 2674 [](double lhs, double rhs) { return lhs * rhs; }, fs, ft)); |
2551 break; | 2675 break; |
2552 case DIV_D: | 2676 case DIV_D: |
2553 set_fpu_register_double( | 2677 SetFPUDoubleResult( |
2554 fd_reg(), | 2678 fd_reg(), |
2555 FPUCanonalizeOperation( | 2679 FPUCanonalizeOperation( |
2556 [](double lhs, double rhs) { return lhs / rhs; }, fs, ft)); | 2680 [](double lhs, double rhs) { return lhs / rhs; }, fs, ft)); |
2557 break; | 2681 break; |
2558 case ABS_D: | 2682 case ABS_D: |
2559 set_fpu_register_double( | 2683 SetFPUDoubleResult( |
2560 fd_reg(), | 2684 fd_reg(), |
2561 FPUCanonalizeOperation([](double fs) { return FPAbs(fs); }, fs)); | 2685 FPUCanonalizeOperation([](double fs) { return FPAbs(fs); }, fs)); |
2562 break; | 2686 break; |
2563 case MOV_D: | 2687 case MOV_D: |
2564 set_fpu_register_double(fd_reg(), fs); | 2688 SetFPUDoubleResult(fd_reg(), fs); |
2565 break; | 2689 break; |
2566 case NEG_D: | 2690 case NEG_D: |
2567 set_fpu_register_double( | 2691 SetFPUDoubleResult(fd_reg(), |
2568 fd_reg(), FPUCanonalizeOperation([](double src) { return -src; }, | 2692 FPUCanonalizeOperation([](double src) { return -src; }, |
2569 KeepSign::yes, fs)); | 2693 KeepSign::yes, fs)); |
2570 break; | 2694 break; |
2571 case SQRT_D: | 2695 case SQRT_D: |
2572 set_fpu_register_double( | 2696 SetFPUDoubleResult( |
2573 fd_reg(), | 2697 fd_reg(), |
2574 FPUCanonalizeOperation([](double fs) { return std::sqrt(fs); }, fs)); | 2698 FPUCanonalizeOperation([](double fs) { return std::sqrt(fs); }, fs)); |
2575 break; | 2699 break; |
2576 case RSQRT_D: | 2700 case RSQRT_D: |
2577 set_fpu_register_double( | 2701 SetFPUDoubleResult( |
2578 fd_reg(), FPUCanonalizeOperation( | 2702 fd_reg(), FPUCanonalizeOperation( |
2579 [](double fs) { return 1.0 / std::sqrt(fs); }, fs)); | 2703 [](double fs) { return 1.0 / std::sqrt(fs); }, fs)); |
2580 break; | 2704 break; |
2581 case RECIP_D: | 2705 case RECIP_D: |
2582 set_fpu_register_double( | 2706 SetFPUDoubleResult(fd_reg(), FPUCanonalizeOperation( |
2583 fd_reg(), | 2707 [](double fs) { return 1.0 / fs; }, fs)); |
2584 FPUCanonalizeOperation([](double fs) { return 1.0 / fs; }, fs)); | |
2585 break; | 2708 break; |
2586 case C_UN_D: | 2709 case C_UN_D: |
2587 set_fcsr_bit(fcsr_cc, std::isnan(fs) || std::isnan(ft)); | 2710 set_fcsr_bit(fcsr_cc, std::isnan(fs) || std::isnan(ft)); |
| 2711 TraceRegWr(test_fcsr_bit(fcsr_cc)); |
2588 break; | 2712 break; |
2589 case C_EQ_D: | 2713 case C_EQ_D: |
2590 set_fcsr_bit(fcsr_cc, (fs == ft)); | 2714 set_fcsr_bit(fcsr_cc, (fs == ft)); |
| 2715 TraceRegWr(test_fcsr_bit(fcsr_cc)); |
2591 break; | 2716 break; |
2592 case C_UEQ_D: | 2717 case C_UEQ_D: |
2593 set_fcsr_bit(fcsr_cc, (fs == ft) || (std::isnan(fs) || std::isnan(ft))); | 2718 set_fcsr_bit(fcsr_cc, (fs == ft) || (std::isnan(fs) || std::isnan(ft))); |
| 2719 TraceRegWr(test_fcsr_bit(fcsr_cc)); |
2594 break; | 2720 break; |
2595 case C_OLT_D: | 2721 case C_OLT_D: |
2596 set_fcsr_bit(fcsr_cc, (fs < ft)); | 2722 set_fcsr_bit(fcsr_cc, (fs < ft)); |
| 2723 TraceRegWr(test_fcsr_bit(fcsr_cc)); |
2597 break; | 2724 break; |
2598 case C_ULT_D: | 2725 case C_ULT_D: |
2599 set_fcsr_bit(fcsr_cc, (fs < ft) || (std::isnan(fs) || std::isnan(ft))); | 2726 set_fcsr_bit(fcsr_cc, (fs < ft) || (std::isnan(fs) || std::isnan(ft))); |
| 2727 TraceRegWr(test_fcsr_bit(fcsr_cc)); |
2600 break; | 2728 break; |
2601 case C_OLE_D: | 2729 case C_OLE_D: |
2602 set_fcsr_bit(fcsr_cc, (fs <= ft)); | 2730 set_fcsr_bit(fcsr_cc, (fs <= ft)); |
| 2731 TraceRegWr(test_fcsr_bit(fcsr_cc)); |
2603 break; | 2732 break; |
2604 case C_ULE_D: | 2733 case C_ULE_D: |
2605 set_fcsr_bit(fcsr_cc, (fs <= ft) || (std::isnan(fs) || std::isnan(ft))); | 2734 set_fcsr_bit(fcsr_cc, (fs <= ft) || (std::isnan(fs) || std::isnan(ft))); |
| 2735 TraceRegWr(test_fcsr_bit(fcsr_cc)); |
2606 break; | 2736 break; |
2607 case CVT_W_D: { // Convert double to word. | 2737 case CVT_W_D: { // Convert double to word. |
2608 double rounded; | 2738 double rounded; |
2609 int32_t result; | 2739 int32_t result; |
2610 round_according_to_fcsr(fs, rounded, result, fs); | 2740 round_according_to_fcsr(fs, rounded, result, fs); |
2611 set_fpu_register_word(fd_reg(), result); | 2741 SetFPUWordResult(fd_reg(), result); |
2612 if (set_fcsr_round_error(fs, rounded)) { | 2742 if (set_fcsr_round_error(fs, rounded)) { |
2613 set_fpu_register_word_invalid_result(fs, rounded); | 2743 set_fpu_register_word_invalid_result(fs, rounded); |
2614 } | 2744 } |
2615 } break; | 2745 } break; |
2616 case ROUND_W_D: // Round double to word (round half to even). | 2746 case ROUND_W_D: // Round double to word (round half to even). |
2617 { | 2747 { |
2618 double rounded = std::floor(fs + 0.5); | 2748 double rounded = std::floor(fs + 0.5); |
2619 int32_t result = static_cast<int32_t>(rounded); | 2749 int32_t result = static_cast<int32_t>(rounded); |
2620 if ((result & 1) != 0 && result - fs == 0.5) { | 2750 if ((result & 1) != 0 && result - fs == 0.5) { |
2621 // If the number is halfway between two integers, | 2751 // If the number is halfway between two integers, |
2622 // round to the even one. | 2752 // round to the even one. |
2623 result--; | 2753 result--; |
2624 } | 2754 } |
2625 set_fpu_register_word(fd_reg(), result); | 2755 SetFPUWordResult(fd_reg(), result); |
2626 if (set_fcsr_round_error(fs, rounded)) { | 2756 if (set_fcsr_round_error(fs, rounded)) { |
2627 set_fpu_register_word_invalid_result(fs, rounded); | 2757 set_fpu_register_word_invalid_result(fs, rounded); |
2628 } | 2758 } |
2629 } break; | 2759 } break; |
2630 case TRUNC_W_D: // Truncate double to word (round towards 0). | 2760 case TRUNC_W_D: // Truncate double to word (round towards 0). |
2631 { | 2761 { |
2632 double rounded = trunc(fs); | 2762 double rounded = trunc(fs); |
2633 int32_t result = static_cast<int32_t>(rounded); | 2763 int32_t result = static_cast<int32_t>(rounded); |
2634 set_fpu_register_word(fd_reg(), result); | 2764 SetFPUWordResult(fd_reg(), result); |
2635 if (set_fcsr_round_error(fs, rounded)) { | 2765 if (set_fcsr_round_error(fs, rounded)) { |
2636 set_fpu_register_word_invalid_result(fs, rounded); | 2766 set_fpu_register_word_invalid_result(fs, rounded); |
2637 } | 2767 } |
2638 } break; | 2768 } break; |
2639 case FLOOR_W_D: // Round double to word towards negative infinity. | 2769 case FLOOR_W_D: // Round double to word towards negative infinity. |
2640 { | 2770 { |
2641 double rounded = std::floor(fs); | 2771 double rounded = std::floor(fs); |
2642 int32_t result = static_cast<int32_t>(rounded); | 2772 int32_t result = static_cast<int32_t>(rounded); |
2643 set_fpu_register_word(fd_reg(), result); | 2773 SetFPUWordResult(fd_reg(), result); |
2644 if (set_fcsr_round_error(fs, rounded)) { | 2774 if (set_fcsr_round_error(fs, rounded)) { |
2645 set_fpu_register_word_invalid_result(fs, rounded); | 2775 set_fpu_register_word_invalid_result(fs, rounded); |
2646 } | 2776 } |
2647 } break; | 2777 } break; |
2648 case CEIL_W_D: // Round double to word towards positive infinity. | 2778 case CEIL_W_D: // Round double to word towards positive infinity. |
2649 { | 2779 { |
2650 double rounded = std::ceil(fs); | 2780 double rounded = std::ceil(fs); |
2651 int32_t result = static_cast<int32_t>(rounded); | 2781 int32_t result = static_cast<int32_t>(rounded); |
2652 set_fpu_register_word(fd_reg(), result); | 2782 SetFPUWordResult(fd_reg(), result); |
2653 if (set_fcsr_round_error(fs, rounded)) { | 2783 if (set_fcsr_round_error(fs, rounded)) { |
2654 set_fpu_register_word_invalid_result(fs, rounded); | 2784 set_fpu_register_word_invalid_result(fs, rounded); |
2655 } | 2785 } |
2656 } break; | 2786 } break; |
2657 case CVT_S_D: // Convert double to float (single). | 2787 case CVT_S_D: // Convert double to float (single). |
2658 set_fpu_register_float(fd_reg(), static_cast<float>(fs)); | 2788 SetFPUFloatResult(fd_reg(), static_cast<float>(fs)); |
2659 break; | 2789 break; |
2660 case CVT_L_D: { // Mips32r2: Truncate double to 64-bit long-word. | 2790 case CVT_L_D: { // Mips32r2: Truncate double to 64-bit long-word. |
2661 if (IsFp64Mode()) { | 2791 if (IsFp64Mode()) { |
2662 int64_t result; | 2792 int64_t result; |
2663 double rounded; | 2793 double rounded; |
2664 round64_according_to_fcsr(fs, rounded, result, fs); | 2794 round64_according_to_fcsr(fs, rounded, result, fs); |
2665 set_fpu_register(fd_reg(), result); | 2795 SetFPUResult(fd_reg(), result); |
2666 if (set_fcsr_round64_error(fs, rounded)) { | 2796 if (set_fcsr_round64_error(fs, rounded)) { |
2667 set_fpu_register_invalid_result64(fs, rounded); | 2797 set_fpu_register_invalid_result64(fs, rounded); |
2668 } | 2798 } |
2669 } else { | 2799 } else { |
2670 UNSUPPORTED(); | 2800 UNSUPPORTED(); |
2671 } | 2801 } |
2672 break; | 2802 break; |
2673 break; | 2803 break; |
2674 } | 2804 } |
2675 case TRUNC_L_D: { // Mips32r2 instruction. | 2805 case TRUNC_L_D: { // Mips32r2 instruction. |
2676 DCHECK(IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)); | 2806 DCHECK(IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)); |
2677 double rounded = trunc(fs); | 2807 double rounded = trunc(fs); |
2678 i64 = static_cast<int64_t>(rounded); | 2808 i64 = static_cast<int64_t>(rounded); |
2679 if (IsFp64Mode()) { | 2809 if (IsFp64Mode()) { |
2680 set_fpu_register(fd_reg(), i64); | 2810 SetFPUResult(fd_reg(), i64); |
2681 if (set_fcsr_round64_error(fs, rounded)) { | 2811 if (set_fcsr_round64_error(fs, rounded)) { |
2682 set_fpu_register_invalid_result64(fs, rounded); | 2812 set_fpu_register_invalid_result64(fs, rounded); |
2683 } | 2813 } |
2684 } else { | 2814 } else { |
2685 UNSUPPORTED(); | 2815 UNSUPPORTED(); |
2686 } | 2816 } |
2687 break; | 2817 break; |
2688 } | 2818 } |
2689 case ROUND_L_D: { // Mips32r2 instruction. | 2819 case ROUND_L_D: { // Mips32r2 instruction. |
2690 DCHECK(IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)); | 2820 DCHECK(IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)); |
2691 double rounded = std::floor(fs + 0.5); | 2821 double rounded = std::floor(fs + 0.5); |
2692 int64_t result = static_cast<int64_t>(rounded); | 2822 int64_t result = static_cast<int64_t>(rounded); |
2693 if ((result & 1) != 0 && result - fs == 0.5) { | 2823 if ((result & 1) != 0 && result - fs == 0.5) { |
2694 // If the number is halfway between two integers, | 2824 // If the number is halfway between two integers, |
2695 // round to the even one. | 2825 // round to the even one. |
2696 result--; | 2826 result--; |
2697 } | 2827 } |
2698 int64_t i64 = static_cast<int64_t>(result); | 2828 int64_t i64 = static_cast<int64_t>(result); |
2699 if (IsFp64Mode()) { | 2829 if (IsFp64Mode()) { |
2700 set_fpu_register(fd_reg(), i64); | 2830 SetFPUResult(fd_reg(), i64); |
2701 if (set_fcsr_round64_error(fs, rounded)) { | 2831 if (set_fcsr_round64_error(fs, rounded)) { |
2702 set_fpu_register_invalid_result64(fs, rounded); | 2832 set_fpu_register_invalid_result64(fs, rounded); |
2703 } | 2833 } |
2704 } else { | 2834 } else { |
2705 UNSUPPORTED(); | 2835 UNSUPPORTED(); |
2706 } | 2836 } |
2707 break; | 2837 break; |
2708 } | 2838 } |
2709 case FLOOR_L_D: { // Mips32r2 instruction. | 2839 case FLOOR_L_D: { // Mips32r2 instruction. |
2710 DCHECK(IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)); | 2840 DCHECK(IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)); |
2711 double rounded = std::floor(fs); | 2841 double rounded = std::floor(fs); |
2712 int64_t i64 = static_cast<int64_t>(rounded); | 2842 int64_t i64 = static_cast<int64_t>(rounded); |
2713 if (IsFp64Mode()) { | 2843 if (IsFp64Mode()) { |
2714 set_fpu_register(fd_reg(), i64); | 2844 SetFPUResult(fd_reg(), i64); |
2715 if (set_fcsr_round64_error(fs, rounded)) { | 2845 if (set_fcsr_round64_error(fs, rounded)) { |
2716 set_fpu_register_invalid_result64(fs, rounded); | 2846 set_fpu_register_invalid_result64(fs, rounded); |
2717 } | 2847 } |
2718 } else { | 2848 } else { |
2719 UNSUPPORTED(); | 2849 UNSUPPORTED(); |
2720 } | 2850 } |
2721 break; | 2851 break; |
2722 } | 2852 } |
2723 case CEIL_L_D: { // Mips32r2 instruction. | 2853 case CEIL_L_D: { // Mips32r2 instruction. |
2724 DCHECK(IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)); | 2854 DCHECK(IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)); |
2725 double rounded = std::ceil(fs); | 2855 double rounded = std::ceil(fs); |
2726 int64_t i64 = static_cast<int64_t>(rounded); | 2856 int64_t i64 = static_cast<int64_t>(rounded); |
2727 if (IsFp64Mode()) { | 2857 if (IsFp64Mode()) { |
2728 set_fpu_register(fd_reg(), i64); | 2858 SetFPUResult(fd_reg(), i64); |
2729 if (set_fcsr_round64_error(fs, rounded)) { | 2859 if (set_fcsr_round64_error(fs, rounded)) { |
2730 set_fpu_register_invalid_result64(fs, rounded); | 2860 set_fpu_register_invalid_result64(fs, rounded); |
2731 } | 2861 } |
2732 } else { | 2862 } else { |
2733 UNSUPPORTED(); | 2863 UNSUPPORTED(); |
2734 } | 2864 } |
2735 break; | 2865 break; |
2736 } | 2866 } |
2737 case CLASS_D: { // Mips32r6 instruction | 2867 case CLASS_D: { // Mips32r6 instruction |
2738 // Convert double input to uint64_t for easier bit manipulation | 2868 // Convert double input to uint64_t for easier bit manipulation |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2788 } | 2918 } |
2789 | 2919 |
2790 // Calculating result according to description of CLASS.D instruction | 2920 // Calculating result according to description of CLASS.D instruction |
2791 result = (posZero << 9) | (posSubnorm << 8) | (posNorm << 7) | | 2921 result = (posZero << 9) | (posSubnorm << 8) | (posNorm << 7) | |
2792 (posInf << 6) | (negZero << 5) | (negSubnorm << 4) | | 2922 (posInf << 6) | (negZero << 5) | (negSubnorm << 4) | |
2793 (negNorm << 3) | (negInf << 2) | (quietNan << 1) | signalingNan; | 2923 (negNorm << 3) | (negInf << 2) | (quietNan << 1) | signalingNan; |
2794 | 2924 |
2795 DCHECK(result != 0); | 2925 DCHECK(result != 0); |
2796 | 2926 |
2797 dResult = bit_cast<double>(result); | 2927 dResult = bit_cast<double>(result); |
2798 set_fpu_register_double(fd_reg(), dResult); | 2928 SetFPUDoubleResult(fd_reg(), dResult); |
2799 | 2929 |
2800 break; | 2930 break; |
2801 } | 2931 } |
2802 case C_F_D: { | 2932 case C_F_D: { |
2803 set_fcsr_bit(fcsr_cc, false); | 2933 set_fcsr_bit(fcsr_cc, false); |
| 2934 TraceRegWr(test_fcsr_bit(fcsr_cc)); |
2804 break; | 2935 break; |
2805 } | 2936 } |
2806 default: | 2937 default: |
2807 UNREACHABLE(); | 2938 UNREACHABLE(); |
2808 } | 2939 } |
2809 } | 2940 } |
2810 | 2941 |
2811 | 2942 |
2812 void Simulator::DecodeTypeRegisterWRsType() { | 2943 void Simulator::DecodeTypeRegisterWRsType() { |
2813 float fs = get_fpu_register_float(fs_reg()); | 2944 float fs = get_fpu_register_float(fs_reg()); |
2814 float ft = get_fpu_register_float(ft_reg()); | 2945 float ft = get_fpu_register_float(ft_reg()); |
2815 int32_t alu_out = 0x12345678; | 2946 int32_t alu_out = 0x12345678; |
2816 switch (instr_.FunctionFieldRaw()) { | 2947 switch (instr_.FunctionFieldRaw()) { |
2817 case CVT_S_W: // Convert word to float (single). | 2948 case CVT_S_W: // Convert word to float (single). |
2818 alu_out = get_fpu_register_signed_word(fs_reg()); | 2949 alu_out = get_fpu_register_signed_word(fs_reg()); |
2819 set_fpu_register_float(fd_reg(), static_cast<float>(alu_out)); | 2950 SetFPUFloatResult(fd_reg(), static_cast<float>(alu_out)); |
2820 break; | 2951 break; |
2821 case CVT_D_W: // Convert word to double. | 2952 case CVT_D_W: // Convert word to double. |
2822 alu_out = get_fpu_register_signed_word(fs_reg()); | 2953 alu_out = get_fpu_register_signed_word(fs_reg()); |
2823 set_fpu_register_double(fd_reg(), static_cast<double>(alu_out)); | 2954 SetFPUDoubleResult(fd_reg(), static_cast<double>(alu_out)); |
2824 break; | 2955 break; |
2825 case CMP_AF: | 2956 case CMP_AF: |
2826 set_fpu_register_word(fd_reg(), 0); | 2957 SetFPUWordResult(fd_reg(), 0); |
2827 break; | 2958 break; |
2828 case CMP_UN: | 2959 case CMP_UN: |
2829 if (std::isnan(fs) || std::isnan(ft)) { | 2960 if (std::isnan(fs) || std::isnan(ft)) { |
2830 set_fpu_register_word(fd_reg(), -1); | 2961 SetFPUWordResult(fd_reg(), -1); |
2831 } else { | 2962 } else { |
2832 set_fpu_register_word(fd_reg(), 0); | 2963 SetFPUWordResult(fd_reg(), 0); |
2833 } | 2964 } |
2834 break; | 2965 break; |
2835 case CMP_EQ: | 2966 case CMP_EQ: |
2836 if (fs == ft) { | 2967 if (fs == ft) { |
2837 set_fpu_register_word(fd_reg(), -1); | 2968 SetFPUWordResult(fd_reg(), -1); |
2838 } else { | 2969 } else { |
2839 set_fpu_register_word(fd_reg(), 0); | 2970 SetFPUWordResult(fd_reg(), 0); |
2840 } | 2971 } |
2841 break; | 2972 break; |
2842 case CMP_UEQ: | 2973 case CMP_UEQ: |
2843 if ((fs == ft) || (std::isnan(fs) || std::isnan(ft))) { | 2974 if ((fs == ft) || (std::isnan(fs) || std::isnan(ft))) { |
2844 set_fpu_register_word(fd_reg(), -1); | 2975 SetFPUWordResult(fd_reg(), -1); |
2845 } else { | 2976 } else { |
2846 set_fpu_register_word(fd_reg(), 0); | 2977 SetFPUWordResult(fd_reg(), 0); |
2847 } | 2978 } |
2848 break; | 2979 break; |
2849 case CMP_LT: | 2980 case CMP_LT: |
2850 if (fs < ft) { | 2981 if (fs < ft) { |
2851 set_fpu_register_word(fd_reg(), -1); | 2982 SetFPUWordResult(fd_reg(), -1); |
2852 } else { | 2983 } else { |
2853 set_fpu_register_word(fd_reg(), 0); | 2984 SetFPUWordResult(fd_reg(), 0); |
2854 } | 2985 } |
2855 break; | 2986 break; |
2856 case CMP_ULT: | 2987 case CMP_ULT: |
2857 if ((fs < ft) || (std::isnan(fs) || std::isnan(ft))) { | 2988 if ((fs < ft) || (std::isnan(fs) || std::isnan(ft))) { |
2858 set_fpu_register_word(fd_reg(), -1); | 2989 SetFPUWordResult(fd_reg(), -1); |
2859 } else { | 2990 } else { |
2860 set_fpu_register_word(fd_reg(), 0); | 2991 SetFPUWordResult(fd_reg(), 0); |
2861 } | 2992 } |
2862 break; | 2993 break; |
2863 case CMP_LE: | 2994 case CMP_LE: |
2864 if (fs <= ft) { | 2995 if (fs <= ft) { |
2865 set_fpu_register_word(fd_reg(), -1); | 2996 SetFPUWordResult(fd_reg(), -1); |
2866 } else { | 2997 } else { |
2867 set_fpu_register_word(fd_reg(), 0); | 2998 SetFPUWordResult(fd_reg(), 0); |
2868 } | 2999 } |
2869 break; | 3000 break; |
2870 case CMP_ULE: | 3001 case CMP_ULE: |
2871 if ((fs <= ft) || (std::isnan(fs) || std::isnan(ft))) { | 3002 if ((fs <= ft) || (std::isnan(fs) || std::isnan(ft))) { |
2872 set_fpu_register_word(fd_reg(), -1); | 3003 SetFPUWordResult(fd_reg(), -1); |
2873 } else { | 3004 } else { |
2874 set_fpu_register_word(fd_reg(), 0); | 3005 SetFPUWordResult(fd_reg(), 0); |
2875 } | 3006 } |
2876 break; | 3007 break; |
2877 case CMP_OR: | 3008 case CMP_OR: |
2878 if (!std::isnan(fs) && !std::isnan(ft)) { | 3009 if (!std::isnan(fs) && !std::isnan(ft)) { |
2879 set_fpu_register_word(fd_reg(), -1); | 3010 SetFPUWordResult(fd_reg(), -1); |
2880 } else { | 3011 } else { |
2881 set_fpu_register_word(fd_reg(), 0); | 3012 SetFPUWordResult(fd_reg(), 0); |
2882 } | 3013 } |
2883 break; | 3014 break; |
2884 case CMP_UNE: | 3015 case CMP_UNE: |
2885 if ((fs != ft) || (std::isnan(fs) || std::isnan(ft))) { | 3016 if ((fs != ft) || (std::isnan(fs) || std::isnan(ft))) { |
2886 set_fpu_register_word(fd_reg(), -1); | 3017 SetFPUWordResult(fd_reg(), -1); |
2887 } else { | 3018 } else { |
2888 set_fpu_register_word(fd_reg(), 0); | 3019 SetFPUWordResult(fd_reg(), 0); |
2889 } | 3020 } |
2890 break; | 3021 break; |
2891 case CMP_NE: | 3022 case CMP_NE: |
2892 if (fs != ft) { | 3023 if (fs != ft) { |
2893 set_fpu_register_word(fd_reg(), -1); | 3024 SetFPUWordResult(fd_reg(), -1); |
2894 } else { | 3025 } else { |
2895 set_fpu_register_word(fd_reg(), 0); | 3026 SetFPUWordResult(fd_reg(), 0); |
2896 } | 3027 } |
2897 break; | 3028 break; |
2898 default: | 3029 default: |
2899 UNREACHABLE(); | 3030 UNREACHABLE(); |
2900 } | 3031 } |
2901 } | 3032 } |
2902 | 3033 |
2903 | 3034 |
2904 void Simulator::DecodeTypeRegisterSRsType() { | 3035 void Simulator::DecodeTypeRegisterSRsType() { |
2905 float fs, ft, fd; | 3036 float fs, ft, fd; |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2937 case kRoundToZero: | 3068 case kRoundToZero: |
2938 result = (fs > 0 ? lower : upper); | 3069 result = (fs > 0 ? lower : upper); |
2939 break; | 3070 break; |
2940 case kRoundToPlusInf: | 3071 case kRoundToPlusInf: |
2941 result = upper; | 3072 result = upper; |
2942 break; | 3073 break; |
2943 case kRoundToMinusInf: | 3074 case kRoundToMinusInf: |
2944 result = lower; | 3075 result = lower; |
2945 break; | 3076 break; |
2946 } | 3077 } |
2947 set_fpu_register_float(fd_reg(), result); | 3078 SetFPUFloatResult(fd_reg(), result); |
2948 if (result != fs) { | 3079 if (result != fs) { |
2949 set_fcsr_bit(kFCSRInexactFlagBit, true); | 3080 set_fcsr_bit(kFCSRInexactFlagBit, true); |
2950 } | 3081 } |
2951 break; | 3082 break; |
2952 } | 3083 } |
2953 case ADD_S: | 3084 case ADD_S: |
2954 set_fpu_register_float( | 3085 SetFPUFloatResult( |
2955 fd_reg(), | 3086 fd_reg(), |
2956 FPUCanonalizeOperation([](float lhs, float rhs) { return lhs + rhs; }, | 3087 FPUCanonalizeOperation([](float lhs, float rhs) { return lhs + rhs; }, |
2957 fs, ft)); | 3088 fs, ft)); |
2958 break; | 3089 break; |
2959 case SUB_S: | 3090 case SUB_S: |
2960 set_fpu_register_float( | 3091 SetFPUFloatResult( |
2961 fd_reg(), | 3092 fd_reg(), |
2962 FPUCanonalizeOperation([](float lhs, float rhs) { return lhs - rhs; }, | 3093 FPUCanonalizeOperation([](float lhs, float rhs) { return lhs - rhs; }, |
2963 fs, ft)); | 3094 fs, ft)); |
2964 break; | 3095 break; |
2965 case MADDF_S: | 3096 case MADDF_S: |
2966 DCHECK(IsMipsArchVariant(kMips32r6)); | 3097 DCHECK(IsMipsArchVariant(kMips32r6)); |
2967 set_fpu_register_float(fd_reg(), std::fma(fs, ft, fd)); | 3098 SetFPUFloatResult(fd_reg(), std::fma(fs, ft, fd)); |
2968 break; | 3099 break; |
2969 case MSUBF_S: | 3100 case MSUBF_S: |
2970 DCHECK(IsMipsArchVariant(kMips32r6)); | 3101 DCHECK(IsMipsArchVariant(kMips32r6)); |
2971 set_fpu_register_float(fd_reg(), std::fma(-fs, ft, fd)); | 3102 SetFPUFloatResult(fd_reg(), std::fma(-fs, ft, fd)); |
2972 break; | 3103 break; |
2973 case MUL_S: | 3104 case MUL_S: |
2974 set_fpu_register_float( | 3105 SetFPUFloatResult( |
2975 fd_reg(), | 3106 fd_reg(), |
2976 FPUCanonalizeOperation([](float lhs, float rhs) { return lhs * rhs; }, | 3107 FPUCanonalizeOperation([](float lhs, float rhs) { return lhs * rhs; }, |
2977 fs, ft)); | 3108 fs, ft)); |
2978 break; | 3109 break; |
2979 case DIV_S: | 3110 case DIV_S: |
2980 set_fpu_register_float( | 3111 SetFPUFloatResult( |
2981 fd_reg(), | 3112 fd_reg(), |
2982 FPUCanonalizeOperation([](float lhs, float rhs) { return lhs / rhs; }, | 3113 FPUCanonalizeOperation([](float lhs, float rhs) { return lhs / rhs; }, |
2983 fs, ft)); | 3114 fs, ft)); |
2984 break; | 3115 break; |
2985 case ABS_S: | 3116 case ABS_S: |
2986 set_fpu_register_float( | 3117 SetFPUFloatResult(fd_reg(), FPUCanonalizeOperation( |
2987 fd_reg(), | 3118 [](float fs) { return FPAbs(fs); }, fs)); |
2988 FPUCanonalizeOperation([](float fs) { return FPAbs(fs); }, fs)); | |
2989 break; | 3119 break; |
2990 case MOV_S: | 3120 case MOV_S: |
2991 set_fpu_register_float(fd_reg(), fs); | 3121 SetFPUFloatResult(fd_reg(), fs); |
2992 break; | 3122 break; |
2993 case NEG_S: | 3123 case NEG_S: |
2994 set_fpu_register_float( | 3124 SetFPUFloatResult(fd_reg(), |
2995 fd_reg(), FPUCanonalizeOperation([](float src) { return -src; }, | 3125 FPUCanonalizeOperation([](float src) { return -src; }, |
2996 KeepSign::yes, fs)); | 3126 KeepSign::yes, fs)); |
2997 break; | 3127 break; |
2998 case SQRT_S: | 3128 case SQRT_S: |
2999 set_fpu_register_float( | 3129 SetFPUFloatResult( |
3000 fd_reg(), | 3130 fd_reg(), |
3001 FPUCanonalizeOperation([](float src) { return std::sqrt(src); }, fs)); | 3131 FPUCanonalizeOperation([](float src) { return std::sqrt(src); }, fs)); |
3002 break; | 3132 break; |
3003 case RSQRT_S: | 3133 case RSQRT_S: |
3004 set_fpu_register_float( | 3134 SetFPUFloatResult( |
3005 fd_reg(), FPUCanonalizeOperation( | 3135 fd_reg(), FPUCanonalizeOperation( |
3006 [](float src) { return 1.0 / std::sqrt(src); }, fs)); | 3136 [](float src) { return 1.0 / std::sqrt(src); }, fs)); |
3007 break; | 3137 break; |
3008 case RECIP_S: | 3138 case RECIP_S: |
3009 set_fpu_register_float( | 3139 SetFPUFloatResult(fd_reg(), FPUCanonalizeOperation( |
3010 fd_reg(), | 3140 [](float src) { return 1.0 / src; }, fs)); |
3011 FPUCanonalizeOperation([](float src) { return 1.0 / src; }, fs)); | |
3012 break; | 3141 break; |
3013 case C_F_D: | 3142 case C_F_D: |
3014 set_fcsr_bit(fcsr_cc, false); | 3143 set_fcsr_bit(fcsr_cc, false); |
| 3144 TraceRegWr(test_fcsr_bit(fcsr_cc)); |
3015 break; | 3145 break; |
3016 case C_UN_D: | 3146 case C_UN_D: |
3017 set_fcsr_bit(fcsr_cc, std::isnan(fs) || std::isnan(ft)); | 3147 set_fcsr_bit(fcsr_cc, std::isnan(fs) || std::isnan(ft)); |
| 3148 TraceRegWr(test_fcsr_bit(fcsr_cc)); |
3018 break; | 3149 break; |
3019 case C_EQ_D: | 3150 case C_EQ_D: |
3020 set_fcsr_bit(fcsr_cc, (fs == ft)); | 3151 set_fcsr_bit(fcsr_cc, (fs == ft)); |
| 3152 TraceRegWr(test_fcsr_bit(fcsr_cc)); |
3021 break; | 3153 break; |
3022 case C_UEQ_D: | 3154 case C_UEQ_D: |
3023 set_fcsr_bit(fcsr_cc, (fs == ft) || (std::isnan(fs) || std::isnan(ft))); | 3155 set_fcsr_bit(fcsr_cc, (fs == ft) || (std::isnan(fs) || std::isnan(ft))); |
| 3156 TraceRegWr(test_fcsr_bit(fcsr_cc)); |
3024 break; | 3157 break; |
3025 case C_OLT_D: | 3158 case C_OLT_D: |
3026 set_fcsr_bit(fcsr_cc, (fs < ft)); | 3159 set_fcsr_bit(fcsr_cc, (fs < ft)); |
| 3160 TraceRegWr(test_fcsr_bit(fcsr_cc)); |
3027 break; | 3161 break; |
3028 case C_ULT_D: | 3162 case C_ULT_D: |
3029 set_fcsr_bit(fcsr_cc, (fs < ft) || (std::isnan(fs) || std::isnan(ft))); | 3163 set_fcsr_bit(fcsr_cc, (fs < ft) || (std::isnan(fs) || std::isnan(ft))); |
| 3164 TraceRegWr(test_fcsr_bit(fcsr_cc)); |
3030 break; | 3165 break; |
3031 case C_OLE_D: | 3166 case C_OLE_D: |
3032 set_fcsr_bit(fcsr_cc, (fs <= ft)); | 3167 set_fcsr_bit(fcsr_cc, (fs <= ft)); |
| 3168 TraceRegWr(test_fcsr_bit(fcsr_cc)); |
3033 break; | 3169 break; |
3034 case C_ULE_D: | 3170 case C_ULE_D: |
3035 set_fcsr_bit(fcsr_cc, (fs <= ft) || (std::isnan(fs) || std::isnan(ft))); | 3171 set_fcsr_bit(fcsr_cc, (fs <= ft) || (std::isnan(fs) || std::isnan(ft))); |
| 3172 TraceRegWr(test_fcsr_bit(fcsr_cc)); |
3036 break; | 3173 break; |
3037 case CVT_D_S: | 3174 case CVT_D_S: |
3038 set_fpu_register_double(fd_reg(), static_cast<double>(fs)); | 3175 SetFPUDoubleResult(fd_reg(), static_cast<double>(fs)); |
3039 break; | 3176 break; |
3040 case SEL: | 3177 case SEL: |
3041 DCHECK(IsMipsArchVariant(kMips32r6)); | 3178 DCHECK(IsMipsArchVariant(kMips32r6)); |
3042 set_fpu_register_float(fd_reg(), (fd_int & 0x1) == 0 ? fs : ft); | 3179 SetFPUFloatResult(fd_reg(), (fd_int & 0x1) == 0 ? fs : ft); |
3043 break; | 3180 break; |
3044 case CLASS_S: { // Mips32r6 instruction | 3181 case CLASS_S: { // Mips32r6 instruction |
3045 // Convert float input to uint32_t for easier bit manipulation | 3182 // Convert float input to uint32_t for easier bit manipulation |
3046 float fs = get_fpu_register_float(fs_reg()); | 3183 float fs = get_fpu_register_float(fs_reg()); |
3047 uint32_t classed = bit_cast<uint32_t>(fs); | 3184 uint32_t classed = bit_cast<uint32_t>(fs); |
3048 | 3185 |
3049 // Extracting sign, exponent and mantissa from the input float | 3186 // Extracting sign, exponent and mantissa from the input float |
3050 uint32_t sign = (classed >> 31) & 1; | 3187 uint32_t sign = (classed >> 31) & 1; |
3051 uint32_t exponent = (classed >> 23) & 0x000000ff; | 3188 uint32_t exponent = (classed >> 23) & 0x000000ff; |
3052 uint32_t mantissa = classed & 0x007fffff; | 3189 uint32_t mantissa = classed & 0x007fffff; |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3096 } | 3233 } |
3097 | 3234 |
3098 // Calculating result according to description of CLASS.S instruction | 3235 // Calculating result according to description of CLASS.S instruction |
3099 result = (posZero << 9) | (posSubnorm << 8) | (posNorm << 7) | | 3236 result = (posZero << 9) | (posSubnorm << 8) | (posNorm << 7) | |
3100 (posInf << 6) | (negZero << 5) | (negSubnorm << 4) | | 3237 (posInf << 6) | (negZero << 5) | (negSubnorm << 4) | |
3101 (negNorm << 3) | (negInf << 2) | (quietNan << 1) | signalingNan; | 3238 (negNorm << 3) | (negInf << 2) | (quietNan << 1) | signalingNan; |
3102 | 3239 |
3103 DCHECK(result != 0); | 3240 DCHECK(result != 0); |
3104 | 3241 |
3105 fResult = bit_cast<float>(result); | 3242 fResult = bit_cast<float>(result); |
3106 set_fpu_register_float(fd_reg(), fResult); | 3243 SetFPUFloatResult(fd_reg(), fResult); |
3107 | 3244 |
3108 break; | 3245 break; |
3109 } | 3246 } |
3110 case SELEQZ_C: | 3247 case SELEQZ_C: |
3111 DCHECK(IsMipsArchVariant(kMips32r6)); | 3248 DCHECK(IsMipsArchVariant(kMips32r6)); |
3112 set_fpu_register_float(fd_reg(), (ft_int & 0x1) == 0 | 3249 SetFPUFloatResult( |
3113 ? get_fpu_register_float(fs_reg()) | 3250 fd_reg(), |
3114 : 0.0); | 3251 (ft_int & 0x1) == 0 ? get_fpu_register_float(fs_reg()) : 0.0); |
3115 break; | 3252 break; |
3116 case SELNEZ_C: | 3253 case SELNEZ_C: |
3117 DCHECK(IsMipsArchVariant(kMips32r6)); | 3254 DCHECK(IsMipsArchVariant(kMips32r6)); |
3118 set_fpu_register_float(fd_reg(), (ft_int & 0x1) != 0 | 3255 SetFPUFloatResult( |
3119 ? get_fpu_register_float(fs_reg()) | 3256 fd_reg(), |
3120 : 0.0); | 3257 (ft_int & 0x1) != 0 ? get_fpu_register_float(fs_reg()) : 0.0); |
3121 break; | 3258 break; |
3122 case MOVZ_C: { | 3259 case MOVZ_C: { |
3123 DCHECK(IsMipsArchVariant(kMips32r2)); | 3260 DCHECK(IsMipsArchVariant(kMips32r2)); |
3124 if (rt() == 0) { | 3261 if (rt() == 0) { |
3125 set_fpu_register_float(fd_reg(), fs); | 3262 SetFPUFloatResult(fd_reg(), fs); |
3126 } | 3263 } |
3127 break; | 3264 break; |
3128 } | 3265 } |
3129 case MOVN_C: { | 3266 case MOVN_C: { |
3130 DCHECK(IsMipsArchVariant(kMips32r2)); | 3267 DCHECK(IsMipsArchVariant(kMips32r2)); |
3131 if (rt() != 0) { | 3268 if (rt() != 0) { |
3132 set_fpu_register_float(fd_reg(), fs); | 3269 SetFPUFloatResult(fd_reg(), fs); |
3133 } | 3270 } |
3134 break; | 3271 break; |
3135 } | 3272 } |
3136 case MOVF: { | 3273 case MOVF: { |
3137 // Same function field for MOVT.D and MOVF.D | 3274 // Same function field for MOVT.D and MOVF.D |
3138 uint32_t ft_cc = (ft_reg() >> 2) & 0x7; | 3275 uint32_t ft_cc = (ft_reg() >> 2) & 0x7; |
3139 ft_cc = get_fcsr_condition_bit(ft_cc); | 3276 ft_cc = get_fcsr_condition_bit(ft_cc); |
3140 | 3277 |
3141 if (instr_.Bit(16)) { // Read Tf bit. | 3278 if (instr_.Bit(16)) { // Read Tf bit. |
3142 // MOVT.D | 3279 // MOVT.D |
3143 if (test_fcsr_bit(ft_cc)) set_fpu_register_float(fd_reg(), fs); | 3280 if (test_fcsr_bit(ft_cc)) SetFPUFloatResult(fd_reg(), fs); |
3144 } else { | 3281 } else { |
3145 // MOVF.D | 3282 // MOVF.D |
3146 if (!test_fcsr_bit(ft_cc)) set_fpu_register_float(fd_reg(), fs); | 3283 if (!test_fcsr_bit(ft_cc)) SetFPUFloatResult(fd_reg(), fs); |
3147 } | 3284 } |
3148 break; | 3285 break; |
3149 } | 3286 } |
3150 case TRUNC_W_S: { // Truncate single to word (round towards 0). | 3287 case TRUNC_W_S: { // Truncate single to word (round towards 0). |
3151 float rounded = trunc(fs); | 3288 float rounded = trunc(fs); |
3152 int32_t result = static_cast<int32_t>(rounded); | 3289 int32_t result = static_cast<int32_t>(rounded); |
3153 set_fpu_register_word(fd_reg(), result); | 3290 SetFPUWordResult(fd_reg(), result); |
3154 if (set_fcsr_round_error(fs, rounded)) { | 3291 if (set_fcsr_round_error(fs, rounded)) { |
3155 set_fpu_register_word_invalid_result(fs, rounded); | 3292 set_fpu_register_word_invalid_result(fs, rounded); |
3156 } | 3293 } |
3157 } break; | 3294 } break; |
3158 case TRUNC_L_S: { // Mips32r2 instruction. | 3295 case TRUNC_L_S: { // Mips32r2 instruction. |
3159 DCHECK(IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)); | 3296 DCHECK(IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)); |
3160 float rounded = trunc(fs); | 3297 float rounded = trunc(fs); |
3161 int64_t i64 = static_cast<int64_t>(rounded); | 3298 int64_t i64 = static_cast<int64_t>(rounded); |
3162 if (IsFp64Mode()) { | 3299 if (IsFp64Mode()) { |
3163 set_fpu_register(fd_reg(), i64); | 3300 SetFPUResult(fd_reg(), i64); |
3164 if (set_fcsr_round64_error(fs, rounded)) { | 3301 if (set_fcsr_round64_error(fs, rounded)) { |
3165 set_fpu_register_invalid_result64(fs, rounded); | 3302 set_fpu_register_invalid_result64(fs, rounded); |
3166 } | 3303 } |
3167 } else { | 3304 } else { |
3168 UNSUPPORTED(); | 3305 UNSUPPORTED(); |
3169 } | 3306 } |
3170 break; | 3307 break; |
3171 } | 3308 } |
3172 case FLOOR_W_S: // Round double to word towards negative infinity. | 3309 case FLOOR_W_S: // Round double to word towards negative infinity. |
3173 { | 3310 { |
3174 float rounded = std::floor(fs); | 3311 float rounded = std::floor(fs); |
3175 int32_t result = static_cast<int32_t>(rounded); | 3312 int32_t result = static_cast<int32_t>(rounded); |
3176 set_fpu_register_word(fd_reg(), result); | 3313 SetFPUWordResult(fd_reg(), result); |
3177 if (set_fcsr_round_error(fs, rounded)) { | 3314 if (set_fcsr_round_error(fs, rounded)) { |
3178 set_fpu_register_word_invalid_result(fs, rounded); | 3315 set_fpu_register_word_invalid_result(fs, rounded); |
3179 } | 3316 } |
3180 } break; | 3317 } break; |
3181 case FLOOR_L_S: { // Mips32r2 instruction. | 3318 case FLOOR_L_S: { // Mips32r2 instruction. |
3182 DCHECK(IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)); | 3319 DCHECK(IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)); |
3183 float rounded = std::floor(fs); | 3320 float rounded = std::floor(fs); |
3184 int64_t i64 = static_cast<int64_t>(rounded); | 3321 int64_t i64 = static_cast<int64_t>(rounded); |
3185 if (IsFp64Mode()) { | 3322 if (IsFp64Mode()) { |
3186 set_fpu_register(fd_reg(), i64); | 3323 SetFPUResult(fd_reg(), i64); |
3187 if (set_fcsr_round64_error(fs, rounded)) { | 3324 if (set_fcsr_round64_error(fs, rounded)) { |
3188 set_fpu_register_invalid_result64(fs, rounded); | 3325 set_fpu_register_invalid_result64(fs, rounded); |
3189 } | 3326 } |
3190 } else { | 3327 } else { |
3191 UNSUPPORTED(); | 3328 UNSUPPORTED(); |
3192 } | 3329 } |
3193 break; | 3330 break; |
3194 } | 3331 } |
3195 case ROUND_W_S: { | 3332 case ROUND_W_S: { |
3196 float rounded = std::floor(fs + 0.5); | 3333 float rounded = std::floor(fs + 0.5); |
3197 int32_t result = static_cast<int32_t>(rounded); | 3334 int32_t result = static_cast<int32_t>(rounded); |
3198 if ((result & 1) != 0 && result - fs == 0.5) { | 3335 if ((result & 1) != 0 && result - fs == 0.5) { |
3199 // If the number is halfway between two integers, | 3336 // If the number is halfway between two integers, |
3200 // round to the even one. | 3337 // round to the even one. |
3201 result--; | 3338 result--; |
3202 } | 3339 } |
3203 set_fpu_register_word(fd_reg(), result); | 3340 SetFPUWordResult(fd_reg(), result); |
3204 if (set_fcsr_round_error(fs, rounded)) { | 3341 if (set_fcsr_round_error(fs, rounded)) { |
3205 set_fpu_register_word_invalid_result(fs, rounded); | 3342 set_fpu_register_word_invalid_result(fs, rounded); |
3206 } | 3343 } |
3207 break; | 3344 break; |
3208 } | 3345 } |
3209 case ROUND_L_S: { // Mips32r2 instruction. | 3346 case ROUND_L_S: { // Mips32r2 instruction. |
3210 DCHECK(IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)); | 3347 DCHECK(IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)); |
3211 float rounded = std::floor(fs + 0.5); | 3348 float rounded = std::floor(fs + 0.5); |
3212 int64_t result = static_cast<int64_t>(rounded); | 3349 int64_t result = static_cast<int64_t>(rounded); |
3213 if ((result & 1) != 0 && result - fs == 0.5) { | 3350 if ((result & 1) != 0 && result - fs == 0.5) { |
3214 // If the number is halfway between two integers, | 3351 // If the number is halfway between two integers, |
3215 // round to the even one. | 3352 // round to the even one. |
3216 result--; | 3353 result--; |
3217 } | 3354 } |
3218 int64_t i64 = static_cast<int64_t>(result); | 3355 int64_t i64 = static_cast<int64_t>(result); |
3219 if (IsFp64Mode()) { | 3356 if (IsFp64Mode()) { |
3220 set_fpu_register(fd_reg(), i64); | 3357 SetFPUResult(fd_reg(), i64); |
3221 if (set_fcsr_round64_error(fs, rounded)) { | 3358 if (set_fcsr_round64_error(fs, rounded)) { |
3222 set_fpu_register_invalid_result64(fs, rounded); | 3359 set_fpu_register_invalid_result64(fs, rounded); |
3223 } | 3360 } |
3224 } else { | 3361 } else { |
3225 UNSUPPORTED(); | 3362 UNSUPPORTED(); |
3226 } | 3363 } |
3227 break; | 3364 break; |
3228 } | 3365 } |
3229 case CEIL_W_S: // Round double to word towards positive infinity. | 3366 case CEIL_W_S: // Round double to word towards positive infinity. |
3230 { | 3367 { |
3231 float rounded = std::ceil(fs); | 3368 float rounded = std::ceil(fs); |
3232 int32_t result = static_cast<int32_t>(rounded); | 3369 int32_t result = static_cast<int32_t>(rounded); |
3233 set_fpu_register_word(fd_reg(), result); | 3370 SetFPUWordResult(fd_reg(), result); |
3234 if (set_fcsr_round_error(fs, rounded)) { | 3371 if (set_fcsr_round_error(fs, rounded)) { |
3235 set_fpu_register_word_invalid_result(fs, rounded); | 3372 set_fpu_register_word_invalid_result(fs, rounded); |
3236 } | 3373 } |
3237 } break; | 3374 } break; |
3238 case CEIL_L_S: { // Mips32r2 instruction. | 3375 case CEIL_L_S: { // Mips32r2 instruction. |
3239 DCHECK(IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)); | 3376 DCHECK(IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)); |
3240 float rounded = std::ceil(fs); | 3377 float rounded = std::ceil(fs); |
3241 int64_t i64 = static_cast<int64_t>(rounded); | 3378 int64_t i64 = static_cast<int64_t>(rounded); |
3242 if (IsFp64Mode()) { | 3379 if (IsFp64Mode()) { |
3243 set_fpu_register(fd_reg(), i64); | 3380 SetFPUResult(fd_reg(), i64); |
3244 if (set_fcsr_round64_error(fs, rounded)) { | 3381 if (set_fcsr_round64_error(fs, rounded)) { |
3245 set_fpu_register_invalid_result64(fs, rounded); | 3382 set_fpu_register_invalid_result64(fs, rounded); |
3246 } | 3383 } |
3247 } else { | 3384 } else { |
3248 UNSUPPORTED(); | 3385 UNSUPPORTED(); |
3249 } | 3386 } |
3250 break; | 3387 break; |
3251 } | 3388 } |
3252 case MIN: | 3389 case MIN: |
3253 DCHECK(IsMipsArchVariant(kMips32r6)); | 3390 DCHECK(IsMipsArchVariant(kMips32r6)); |
3254 set_fpu_register_float(fd_reg(), FPUMin(ft, fs)); | 3391 SetFPUFloatResult(fd_reg(), FPUMin(ft, fs)); |
3255 break; | 3392 break; |
3256 case MAX: | 3393 case MAX: |
3257 DCHECK(IsMipsArchVariant(kMips32r6)); | 3394 DCHECK(IsMipsArchVariant(kMips32r6)); |
3258 set_fpu_register_float(fd_reg(), FPUMax(ft, fs)); | 3395 SetFPUFloatResult(fd_reg(), FPUMax(ft, fs)); |
3259 break; | 3396 break; |
3260 case MINA: | 3397 case MINA: |
3261 DCHECK(IsMipsArchVariant(kMips32r6)); | 3398 DCHECK(IsMipsArchVariant(kMips32r6)); |
3262 set_fpu_register_float(fd_reg(), FPUMinA(ft, fs)); | 3399 SetFPUFloatResult(fd_reg(), FPUMinA(ft, fs)); |
3263 break; | 3400 break; |
3264 case MAXA: | 3401 case MAXA: |
3265 DCHECK(IsMipsArchVariant(kMips32r6)); | 3402 DCHECK(IsMipsArchVariant(kMips32r6)); |
3266 set_fpu_register_float(fd_reg(), FPUMaxA(ft, fs)); | 3403 SetFPUFloatResult(fd_reg(), FPUMaxA(ft, fs)); |
3267 break; | 3404 break; |
3268 case CVT_L_S: { | 3405 case CVT_L_S: { |
3269 if (IsFp64Mode()) { | 3406 if (IsFp64Mode()) { |
3270 int64_t result; | 3407 int64_t result; |
3271 float rounded; | 3408 float rounded; |
3272 round64_according_to_fcsr(fs, rounded, result, fs); | 3409 round64_according_to_fcsr(fs, rounded, result, fs); |
3273 set_fpu_register(fd_reg(), result); | 3410 SetFPUResult(fd_reg(), result); |
3274 if (set_fcsr_round64_error(fs, rounded)) { | 3411 if (set_fcsr_round64_error(fs, rounded)) { |
3275 set_fpu_register_invalid_result64(fs, rounded); | 3412 set_fpu_register_invalid_result64(fs, rounded); |
3276 } | 3413 } |
3277 } else { | 3414 } else { |
3278 UNSUPPORTED(); | 3415 UNSUPPORTED(); |
3279 } | 3416 } |
3280 break; | 3417 break; |
3281 } | 3418 } |
3282 case CVT_W_S: { | 3419 case CVT_W_S: { |
3283 float rounded; | 3420 float rounded; |
3284 int32_t result; | 3421 int32_t result; |
3285 round_according_to_fcsr(fs, rounded, result, fs); | 3422 round_according_to_fcsr(fs, rounded, result, fs); |
3286 set_fpu_register_word(fd_reg(), result); | 3423 SetFPUWordResult(fd_reg(), result); |
3287 if (set_fcsr_round_error(fs, rounded)) { | 3424 if (set_fcsr_round_error(fs, rounded)) { |
3288 set_fpu_register_word_invalid_result(fs, rounded); | 3425 set_fpu_register_word_invalid_result(fs, rounded); |
3289 } | 3426 } |
3290 break; | 3427 break; |
3291 } | 3428 } |
3292 default: | 3429 default: |
3293 // CVT_W_S CVT_L_S ROUND_W_S ROUND_L_S FLOOR_W_S FLOOR_L_S | 3430 // CVT_W_S CVT_L_S ROUND_W_S ROUND_L_S FLOOR_W_S FLOOR_L_S |
3294 // CEIL_W_S CEIL_L_S CVT_PS_S are unimplemented. | 3431 // CEIL_W_S CEIL_L_S CVT_PS_S are unimplemented. |
3295 UNREACHABLE(); | 3432 UNREACHABLE(); |
3296 } | 3433 } |
3297 } | 3434 } |
3298 | 3435 |
3299 | 3436 |
3300 void Simulator::DecodeTypeRegisterLRsType() { | 3437 void Simulator::DecodeTypeRegisterLRsType() { |
3301 double fs = get_fpu_register_double(fs_reg()); | 3438 double fs = get_fpu_register_double(fs_reg()); |
3302 double ft = get_fpu_register_double(ft_reg()); | 3439 double ft = get_fpu_register_double(ft_reg()); |
3303 switch (instr_.FunctionFieldRaw()) { | 3440 switch (instr_.FunctionFieldRaw()) { |
3304 case CVT_D_L: // Mips32r2 instruction. | 3441 case CVT_D_L: // Mips32r2 instruction. |
3305 // Watch the signs here, we want 2 32-bit vals | 3442 // Watch the signs here, we want 2 32-bit vals |
3306 // to make a sign-64. | 3443 // to make a sign-64. |
3307 int64_t i64; | 3444 int64_t i64; |
3308 if (IsFp64Mode()) { | 3445 if (IsFp64Mode()) { |
3309 i64 = get_fpu_register(fs_reg()); | 3446 i64 = get_fpu_register(fs_reg()); |
3310 } else { | 3447 } else { |
3311 i64 = static_cast<uint32_t>(get_fpu_register_word(fs_reg())); | 3448 i64 = static_cast<uint32_t>(get_fpu_register_word(fs_reg())); |
3312 i64 |= static_cast<int64_t>(get_fpu_register_word(fs_reg() + 1)) << 32; | 3449 i64 |= static_cast<int64_t>(get_fpu_register_word(fs_reg() + 1)) << 32; |
3313 } | 3450 } |
3314 set_fpu_register_double(fd_reg(), static_cast<double>(i64)); | 3451 SetFPUDoubleResult(fd_reg(), static_cast<double>(i64)); |
3315 break; | 3452 break; |
3316 case CVT_S_L: | 3453 case CVT_S_L: |
3317 if (IsFp64Mode()) { | 3454 if (IsFp64Mode()) { |
3318 i64 = get_fpu_register(fs_reg()); | 3455 i64 = get_fpu_register(fs_reg()); |
3319 } else { | 3456 } else { |
3320 i64 = static_cast<uint32_t>(get_fpu_register_word(fs_reg())); | 3457 i64 = static_cast<uint32_t>(get_fpu_register_word(fs_reg())); |
3321 i64 |= static_cast<int64_t>(get_fpu_register_word(fs_reg() + 1)) << 32; | 3458 i64 |= static_cast<int64_t>(get_fpu_register_word(fs_reg() + 1)) << 32; |
3322 } | 3459 } |
3323 set_fpu_register_float(fd_reg(), static_cast<float>(i64)); | 3460 SetFPUFloatResult(fd_reg(), static_cast<float>(i64)); |
3324 break; | 3461 break; |
3325 case CMP_AF: // Mips64r6 CMP.D instructions. | 3462 case CMP_AF: // Mips64r6 CMP.D instructions. |
3326 set_fpu_register(fd_reg(), 0); | 3463 SetFPUResult(fd_reg(), 0); |
3327 break; | 3464 break; |
3328 case CMP_UN: | 3465 case CMP_UN: |
3329 if (std::isnan(fs) || std::isnan(ft)) { | 3466 if (std::isnan(fs) || std::isnan(ft)) { |
3330 set_fpu_register(fd_reg(), -1); | 3467 SetFPUResult(fd_reg(), -1); |
3331 } else { | 3468 } else { |
3332 set_fpu_register(fd_reg(), 0); | 3469 SetFPUResult(fd_reg(), 0); |
3333 } | 3470 } |
3334 break; | 3471 break; |
3335 case CMP_EQ: | 3472 case CMP_EQ: |
3336 if (fs == ft) { | 3473 if (fs == ft) { |
3337 set_fpu_register(fd_reg(), -1); | 3474 SetFPUResult(fd_reg(), -1); |
3338 } else { | 3475 } else { |
3339 set_fpu_register(fd_reg(), 0); | 3476 SetFPUResult(fd_reg(), 0); |
3340 } | 3477 } |
3341 break; | 3478 break; |
3342 case CMP_UEQ: | 3479 case CMP_UEQ: |
3343 if ((fs == ft) || (std::isnan(fs) || std::isnan(ft))) { | 3480 if ((fs == ft) || (std::isnan(fs) || std::isnan(ft))) { |
3344 set_fpu_register(fd_reg(), -1); | 3481 SetFPUResult(fd_reg(), -1); |
3345 } else { | 3482 } else { |
3346 set_fpu_register(fd_reg(), 0); | 3483 SetFPUResult(fd_reg(), 0); |
3347 } | 3484 } |
3348 break; | 3485 break; |
3349 case CMP_LT: | 3486 case CMP_LT: |
3350 if (fs < ft) { | 3487 if (fs < ft) { |
3351 set_fpu_register(fd_reg(), -1); | 3488 SetFPUResult(fd_reg(), -1); |
3352 } else { | 3489 } else { |
3353 set_fpu_register(fd_reg(), 0); | 3490 SetFPUResult(fd_reg(), 0); |
3354 } | 3491 } |
3355 break; | 3492 break; |
3356 case CMP_ULT: | 3493 case CMP_ULT: |
3357 if ((fs < ft) || (std::isnan(fs) || std::isnan(ft))) { | 3494 if ((fs < ft) || (std::isnan(fs) || std::isnan(ft))) { |
3358 set_fpu_register(fd_reg(), -1); | 3495 SetFPUResult(fd_reg(), -1); |
3359 } else { | 3496 } else { |
3360 set_fpu_register(fd_reg(), 0); | 3497 SetFPUResult(fd_reg(), 0); |
3361 } | 3498 } |
3362 break; | 3499 break; |
3363 case CMP_LE: | 3500 case CMP_LE: |
3364 if (fs <= ft) { | 3501 if (fs <= ft) { |
3365 set_fpu_register(fd_reg(), -1); | 3502 SetFPUResult(fd_reg(), -1); |
3366 } else { | 3503 } else { |
3367 set_fpu_register(fd_reg(), 0); | 3504 SetFPUResult(fd_reg(), 0); |
3368 } | 3505 } |
3369 break; | 3506 break; |
3370 case CMP_ULE: | 3507 case CMP_ULE: |
3371 if ((fs <= ft) || (std::isnan(fs) || std::isnan(ft))) { | 3508 if ((fs <= ft) || (std::isnan(fs) || std::isnan(ft))) { |
3372 set_fpu_register(fd_reg(), -1); | 3509 SetFPUResult(fd_reg(), -1); |
3373 } else { | 3510 } else { |
3374 set_fpu_register(fd_reg(), 0); | 3511 SetFPUResult(fd_reg(), 0); |
3375 } | 3512 } |
3376 break; | 3513 break; |
3377 case CMP_OR: | 3514 case CMP_OR: |
3378 if (!std::isnan(fs) && !std::isnan(ft)) { | 3515 if (!std::isnan(fs) && !std::isnan(ft)) { |
3379 set_fpu_register(fd_reg(), -1); | 3516 SetFPUResult(fd_reg(), -1); |
3380 } else { | 3517 } else { |
3381 set_fpu_register(fd_reg(), 0); | 3518 SetFPUResult(fd_reg(), 0); |
3382 } | 3519 } |
3383 break; | 3520 break; |
3384 case CMP_UNE: | 3521 case CMP_UNE: |
3385 if ((fs != ft) || (std::isnan(fs) || std::isnan(ft))) { | 3522 if ((fs != ft) || (std::isnan(fs) || std::isnan(ft))) { |
3386 set_fpu_register(fd_reg(), -1); | 3523 SetFPUResult(fd_reg(), -1); |
3387 } else { | 3524 } else { |
3388 set_fpu_register(fd_reg(), 0); | 3525 SetFPUResult(fd_reg(), 0); |
3389 } | 3526 } |
3390 break; | 3527 break; |
3391 case CMP_NE: | 3528 case CMP_NE: |
3392 if (fs != ft && (!std::isnan(fs) && !std::isnan(ft))) { | 3529 if (fs != ft && (!std::isnan(fs) && !std::isnan(ft))) { |
3393 set_fpu_register(fd_reg(), -1); | 3530 SetFPUResult(fd_reg(), -1); |
3394 } else { | 3531 } else { |
3395 set_fpu_register(fd_reg(), 0); | 3532 SetFPUResult(fd_reg(), 0); |
3396 } | 3533 } |
3397 break; | 3534 break; |
3398 default: | 3535 default: |
3399 UNREACHABLE(); | 3536 UNREACHABLE(); |
3400 } | 3537 } |
3401 } | 3538 } |
3402 | 3539 |
3403 | 3540 |
3404 void Simulator::DecodeTypeRegisterCOP1() { | 3541 void Simulator::DecodeTypeRegisterCOP1() { |
3405 switch (instr_.RsFieldRaw()) { | 3542 switch (instr_.RsFieldRaw()) { |
3406 case CFC1: | 3543 case CFC1: |
3407 // At the moment only FCSR is supported. | 3544 // At the moment only FCSR is supported. |
3408 DCHECK(fs_reg() == kFCSRRegister); | 3545 DCHECK(fs_reg() == kFCSRRegister); |
3409 set_register(rt_reg(), FCSR_); | 3546 SetResult(rt_reg(), FCSR_); |
3410 break; | 3547 break; |
3411 case MFC1: | 3548 case MFC1: |
3412 set_register(rt_reg(), get_fpu_register_word(fs_reg())); | 3549 SetResult(rt_reg(), get_fpu_register_word(fs_reg())); |
3413 break; | 3550 break; |
3414 case MFHC1: | 3551 case MFHC1: |
3415 if (IsFp64Mode()) { | 3552 if (IsFp64Mode()) { |
3416 set_register(rt_reg(), get_fpu_register_hi_word(fs_reg())); | 3553 SetResult(rt_reg(), get_fpu_register_hi_word(fs_reg())); |
3417 } else { | 3554 } else { |
3418 set_register(rt_reg(), get_fpu_register_word(fs_reg() + 1)); | 3555 SetResult(rt_reg(), get_fpu_register_word(fs_reg() + 1)); |
3419 } | 3556 } |
3420 break; | 3557 break; |
3421 case CTC1: { | 3558 case CTC1: { |
3422 // At the moment only FCSR is supported. | 3559 // At the moment only FCSR is supported. |
3423 DCHECK(fs_reg() == kFCSRRegister); | 3560 DCHECK(fs_reg() == kFCSRRegister); |
3424 int32_t reg = registers_[rt_reg()]; | 3561 int32_t reg = registers_[rt_reg()]; |
3425 if (IsMipsArchVariant(kMips32r6)) { | 3562 if (IsMipsArchVariant(kMips32r6)) { |
3426 FCSR_ = reg | kFCSRNaN2008FlagMask; | 3563 FCSR_ = reg | kFCSRNaN2008FlagMask; |
3427 } else { | 3564 } else { |
3428 DCHECK(IsMipsArchVariant(kMips32r1) || IsMipsArchVariant(kMips32r2)); | 3565 DCHECK(IsMipsArchVariant(kMips32r1) || IsMipsArchVariant(kMips32r2)); |
3429 FCSR_ = reg & ~kFCSRNaN2008FlagMask; | 3566 FCSR_ = reg & ~kFCSRNaN2008FlagMask; |
3430 } | 3567 } |
| 3568 TraceRegWr(static_cast<int32_t>(FCSR_)); |
3431 break; | 3569 break; |
3432 } | 3570 } |
3433 case MTC1: | 3571 case MTC1: |
3434 // Hardware writes upper 32-bits to zero on mtc1. | 3572 // Hardware writes upper 32-bits to zero on mtc1. |
3435 set_fpu_register_hi_word(fs_reg(), 0); | 3573 set_fpu_register_hi_word(fs_reg(), 0); |
3436 set_fpu_register_word(fs_reg(), registers_[rt_reg()]); | 3574 set_fpu_register_word(fs_reg(), registers_[rt_reg()]); |
| 3575 TraceRegWr(get_fpu_register_word(fs_reg()), FLOAT); |
3437 break; | 3576 break; |
3438 case MTHC1: | 3577 case MTHC1: |
3439 if (IsFp64Mode()) { | 3578 if (IsFp64Mode()) { |
3440 set_fpu_register_hi_word(fs_reg(), registers_[rt_reg()]); | 3579 set_fpu_register_hi_word(fs_reg(), registers_[rt_reg()]); |
| 3580 TraceRegWr(get_fpu_register(fs_reg()), DOUBLE); |
3441 } else { | 3581 } else { |
3442 set_fpu_register_word(fs_reg() + 1, registers_[rt_reg()]); | 3582 set_fpu_register_word(fs_reg() + 1, registers_[rt_reg()]); |
| 3583 if (fs_reg() % 2) { |
| 3584 TraceRegWr(get_fpu_register_word(fs_reg() + 1), FLOAT); |
| 3585 } else { |
| 3586 TraceRegWr(get_fpu_register(fs_reg()), DOUBLE); |
| 3587 } |
3443 } | 3588 } |
3444 break; | 3589 break; |
3445 case S: { | 3590 case S: { |
3446 DecodeTypeRegisterSRsType(); | 3591 DecodeTypeRegisterSRsType(); |
3447 break; | 3592 break; |
3448 } | 3593 } |
3449 case D: | 3594 case D: |
3450 DecodeTypeRegisterDRsType(); | 3595 DecodeTypeRegisterDRsType(); |
3451 break; | 3596 break; |
3452 case W: | 3597 case W: |
(...skipping 12 matching lines...) Expand all Loading... |
3465 | 3610 |
3466 | 3611 |
3467 void Simulator::DecodeTypeRegisterCOP1X() { | 3612 void Simulator::DecodeTypeRegisterCOP1X() { |
3468 switch (instr_.FunctionFieldRaw()) { | 3613 switch (instr_.FunctionFieldRaw()) { |
3469 case MADD_S: { | 3614 case MADD_S: { |
3470 DCHECK(IsMipsArchVariant(kMips32r2)); | 3615 DCHECK(IsMipsArchVariant(kMips32r2)); |
3471 float fr, ft, fs; | 3616 float fr, ft, fs; |
3472 fr = get_fpu_register_float(fr_reg()); | 3617 fr = get_fpu_register_float(fr_reg()); |
3473 fs = get_fpu_register_float(fs_reg()); | 3618 fs = get_fpu_register_float(fs_reg()); |
3474 ft = get_fpu_register_float(ft_reg()); | 3619 ft = get_fpu_register_float(ft_reg()); |
3475 set_fpu_register_float(fd_reg(), fs * ft + fr); | 3620 SetFPUFloatResult(fd_reg(), fs * ft + fr); |
3476 break; | 3621 break; |
3477 } | 3622 } |
3478 case MSUB_S: { | 3623 case MSUB_S: { |
3479 DCHECK(IsMipsArchVariant(kMips32r2)); | 3624 DCHECK(IsMipsArchVariant(kMips32r2)); |
3480 float fr, ft, fs; | 3625 float fr, ft, fs; |
3481 fr = get_fpu_register_float(fr_reg()); | 3626 fr = get_fpu_register_float(fr_reg()); |
3482 fs = get_fpu_register_float(fs_reg()); | 3627 fs = get_fpu_register_float(fs_reg()); |
3483 ft = get_fpu_register_float(ft_reg()); | 3628 ft = get_fpu_register_float(ft_reg()); |
3484 set_fpu_register_float(fd_reg(), fs * ft - fr); | 3629 SetFPUFloatResult(fd_reg(), fs * ft - fr); |
3485 break; | 3630 break; |
3486 } | 3631 } |
3487 case MADD_D: { | 3632 case MADD_D: { |
3488 DCHECK(IsMipsArchVariant(kMips32r2)); | 3633 DCHECK(IsMipsArchVariant(kMips32r2)); |
3489 double fr, ft, fs; | 3634 double fr, ft, fs; |
3490 fr = get_fpu_register_double(fr_reg()); | 3635 fr = get_fpu_register_double(fr_reg()); |
3491 fs = get_fpu_register_double(fs_reg()); | 3636 fs = get_fpu_register_double(fs_reg()); |
3492 ft = get_fpu_register_double(ft_reg()); | 3637 ft = get_fpu_register_double(ft_reg()); |
3493 set_fpu_register_double(fd_reg(), fs * ft + fr); | 3638 SetFPUDoubleResult(fd_reg(), fs * ft + fr); |
3494 break; | 3639 break; |
3495 } | 3640 } |
3496 case MSUB_D: { | 3641 case MSUB_D: { |
3497 DCHECK(IsMipsArchVariant(kMips32r2)); | 3642 DCHECK(IsMipsArchVariant(kMips32r2)); |
3498 double fr, ft, fs; | 3643 double fr, ft, fs; |
3499 fr = get_fpu_register_double(fr_reg()); | 3644 fr = get_fpu_register_double(fr_reg()); |
3500 fs = get_fpu_register_double(fs_reg()); | 3645 fs = get_fpu_register_double(fs_reg()); |
3501 ft = get_fpu_register_double(ft_reg()); | 3646 ft = get_fpu_register_double(ft_reg()); |
3502 set_fpu_register_double(fd_reg(), fs * ft - fr); | 3647 SetFPUDoubleResult(fd_reg(), fs * ft - fr); |
3503 break; | 3648 break; |
3504 } | 3649 } |
3505 default: | 3650 default: |
3506 UNREACHABLE(); | 3651 UNREACHABLE(); |
3507 } | 3652 } |
3508 } | 3653 } |
3509 | 3654 |
3510 | 3655 |
3511 void Simulator::DecodeTypeRegisterSPECIAL() { | 3656 void Simulator::DecodeTypeRegisterSPECIAL() { |
3512 int64_t alu_out = 0x12345678; | 3657 int64_t alu_out = 0x12345678; |
3513 int64_t i64hilo = 0; | 3658 int64_t i64hilo = 0; |
3514 uint64_t u64hilo = 0; | 3659 uint64_t u64hilo = 0; |
3515 bool do_interrupt = false; | 3660 bool do_interrupt = false; |
3516 | 3661 |
3517 switch (instr_.FunctionFieldRaw()) { | 3662 switch (instr_.FunctionFieldRaw()) { |
3518 case SELEQZ_S: | 3663 case SELEQZ_S: |
3519 DCHECK(IsMipsArchVariant(kMips32r6)); | 3664 DCHECK(IsMipsArchVariant(kMips32r6)); |
3520 set_register(rd_reg(), rt() == 0 ? rs() : 0); | 3665 SetResult(rd_reg(), rt() == 0 ? rs() : 0); |
3521 break; | 3666 break; |
3522 case SELNEZ_S: | 3667 case SELNEZ_S: |
3523 DCHECK(IsMipsArchVariant(kMips32r6)); | 3668 DCHECK(IsMipsArchVariant(kMips32r6)); |
3524 set_register(rd_reg(), rt() != 0 ? rs() : 0); | 3669 SetResult(rd_reg(), rt() != 0 ? rs() : 0); |
3525 break; | 3670 break; |
3526 case JR: { | 3671 case JR: { |
3527 int32_t next_pc = rs(); | 3672 int32_t next_pc = rs(); |
3528 int32_t current_pc = get_pc(); | 3673 int32_t current_pc = get_pc(); |
3529 Instruction* branch_delay_instr = | 3674 Instruction* branch_delay_instr = |
3530 reinterpret_cast<Instruction*>(current_pc + Instruction::kInstrSize); | 3675 reinterpret_cast<Instruction*>(current_pc + Instruction::kInstrSize); |
3531 BranchDelayInstructionDecode(branch_delay_instr); | 3676 BranchDelayInstructionDecode(branch_delay_instr); |
3532 set_pc(next_pc); | 3677 set_pc(next_pc); |
3533 pc_modified_ = true; | 3678 pc_modified_ = true; |
3534 break; | 3679 break; |
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3615 break; | 3760 break; |
3616 // Instructions using HI and LO registers. | 3761 // Instructions using HI and LO registers. |
3617 case MULT: | 3762 case MULT: |
3618 i64hilo = static_cast<int64_t>(rs()) * static_cast<int64_t>(rt()); | 3763 i64hilo = static_cast<int64_t>(rs()) * static_cast<int64_t>(rt()); |
3619 if (!IsMipsArchVariant(kMips32r6)) { | 3764 if (!IsMipsArchVariant(kMips32r6)) { |
3620 set_register(LO, static_cast<int32_t>(i64hilo & 0xffffffff)); | 3765 set_register(LO, static_cast<int32_t>(i64hilo & 0xffffffff)); |
3621 set_register(HI, static_cast<int32_t>(i64hilo >> 32)); | 3766 set_register(HI, static_cast<int32_t>(i64hilo >> 32)); |
3622 } else { | 3767 } else { |
3623 switch (sa()) { | 3768 switch (sa()) { |
3624 case MUL_OP: | 3769 case MUL_OP: |
3625 set_register(rd_reg(), static_cast<int32_t>(i64hilo & 0xffffffff)); | 3770 SetResult(rd_reg(), static_cast<int32_t>(i64hilo & 0xffffffff)); |
3626 break; | 3771 break; |
3627 case MUH_OP: | 3772 case MUH_OP: |
3628 set_register(rd_reg(), static_cast<int32_t>(i64hilo >> 32)); | 3773 SetResult(rd_reg(), static_cast<int32_t>(i64hilo >> 32)); |
3629 break; | 3774 break; |
3630 default: | 3775 default: |
3631 UNIMPLEMENTED_MIPS(); | 3776 UNIMPLEMENTED_MIPS(); |
3632 break; | 3777 break; |
3633 } | 3778 } |
3634 } | 3779 } |
3635 break; | 3780 break; |
3636 case MULTU: | 3781 case MULTU: |
3637 u64hilo = static_cast<uint64_t>(rs_u()) * static_cast<uint64_t>(rt_u()); | 3782 u64hilo = static_cast<uint64_t>(rs_u()) * static_cast<uint64_t>(rt_u()); |
3638 if (!IsMipsArchVariant(kMips32r6)) { | 3783 if (!IsMipsArchVariant(kMips32r6)) { |
3639 set_register(LO, static_cast<int32_t>(u64hilo & 0xffffffff)); | 3784 set_register(LO, static_cast<int32_t>(u64hilo & 0xffffffff)); |
3640 set_register(HI, static_cast<int32_t>(u64hilo >> 32)); | 3785 set_register(HI, static_cast<int32_t>(u64hilo >> 32)); |
3641 } else { | 3786 } else { |
3642 switch (sa()) { | 3787 switch (sa()) { |
3643 case MUL_OP: | 3788 case MUL_OP: |
3644 set_register(rd_reg(), static_cast<int32_t>(u64hilo & 0xffffffff)); | 3789 SetResult(rd_reg(), static_cast<int32_t>(u64hilo & 0xffffffff)); |
3645 break; | 3790 break; |
3646 case MUH_OP: | 3791 case MUH_OP: |
3647 set_register(rd_reg(), static_cast<int32_t>(u64hilo >> 32)); | 3792 SetResult(rd_reg(), static_cast<int32_t>(u64hilo >> 32)); |
3648 break; | 3793 break; |
3649 default: | 3794 default: |
3650 UNIMPLEMENTED_MIPS(); | 3795 UNIMPLEMENTED_MIPS(); |
3651 break; | 3796 break; |
3652 } | 3797 } |
3653 } | 3798 } |
3654 break; | 3799 break; |
3655 case DIV: | 3800 case DIV: |
3656 if (IsMipsArchVariant(kMips32r6)) { | 3801 if (IsMipsArchVariant(kMips32r6)) { |
3657 switch (sa()) { | 3802 switch (sa()) { |
3658 case DIV_OP: | 3803 case DIV_OP: |
3659 if (rs() == INT_MIN && rt() == -1) { | 3804 if (rs() == INT_MIN && rt() == -1) { |
3660 set_register(rd_reg(), INT_MIN); | 3805 SetResult(rd_reg(), INT_MIN); |
3661 } else if (rt() != 0) { | 3806 } else if (rt() != 0) { |
3662 set_register(rd_reg(), rs() / rt()); | 3807 SetResult(rd_reg(), rs() / rt()); |
3663 } | 3808 } |
3664 break; | 3809 break; |
3665 case MOD_OP: | 3810 case MOD_OP: |
3666 if (rs() == INT_MIN && rt() == -1) { | 3811 if (rs() == INT_MIN && rt() == -1) { |
3667 set_register(rd_reg(), 0); | 3812 SetResult(rd_reg(), 0); |
3668 } else if (rt() != 0) { | 3813 } else if (rt() != 0) { |
3669 set_register(rd_reg(), rs() % rt()); | 3814 SetResult(rd_reg(), rs() % rt()); |
3670 } | 3815 } |
3671 break; | 3816 break; |
3672 default: | 3817 default: |
3673 UNIMPLEMENTED_MIPS(); | 3818 UNIMPLEMENTED_MIPS(); |
3674 break; | 3819 break; |
3675 } | 3820 } |
3676 } else { | 3821 } else { |
3677 // Divide by zero and overflow was not checked in the | 3822 // Divide by zero and overflow was not checked in the |
3678 // configuration step - div and divu do not raise exceptions. On | 3823 // configuration step - div and divu do not raise exceptions. On |
3679 // division by 0 the result will be UNPREDICTABLE. On overflow | 3824 // division by 0 the result will be UNPREDICTABLE. On overflow |
3680 // (INT_MIN/-1), return INT_MIN which is what the hardware does. | 3825 // (INT_MIN/-1), return INT_MIN which is what the hardware does. |
3681 if (rs() == INT_MIN && rt() == -1) { | 3826 if (rs() == INT_MIN && rt() == -1) { |
3682 set_register(LO, INT_MIN); | 3827 set_register(LO, INT_MIN); |
3683 set_register(HI, 0); | 3828 set_register(HI, 0); |
3684 } else if (rt() != 0) { | 3829 } else if (rt() != 0) { |
3685 set_register(LO, rs() / rt()); | 3830 set_register(LO, rs() / rt()); |
3686 set_register(HI, rs() % rt()); | 3831 set_register(HI, rs() % rt()); |
3687 } | 3832 } |
3688 } | 3833 } |
3689 break; | 3834 break; |
3690 case DIVU: | 3835 case DIVU: |
3691 if (IsMipsArchVariant(kMips32r6)) { | 3836 if (IsMipsArchVariant(kMips32r6)) { |
3692 switch (sa()) { | 3837 switch (sa()) { |
3693 case DIV_OP: | 3838 case DIV_OP: |
3694 if (rt_u() != 0) { | 3839 if (rt_u() != 0) { |
3695 set_register(rd_reg(), rs_u() / rt_u()); | 3840 SetResult(rd_reg(), rs_u() / rt_u()); |
3696 } | 3841 } |
3697 break; | 3842 break; |
3698 case MOD_OP: | 3843 case MOD_OP: |
3699 if (rt_u() != 0) { | 3844 if (rt_u() != 0) { |
3700 set_register(rd_reg(), rs_u() % rt_u()); | 3845 SetResult(rd_reg(), rs_u() % rt_u()); |
3701 } | 3846 } |
3702 break; | 3847 break; |
3703 default: | 3848 default: |
3704 UNIMPLEMENTED_MIPS(); | 3849 UNIMPLEMENTED_MIPS(); |
3705 break; | 3850 break; |
3706 } | 3851 } |
3707 } else { | 3852 } else { |
3708 if (rt_u() != 0) { | 3853 if (rt_u() != 0) { |
3709 set_register(LO, rs_u() / rt_u()); | 3854 set_register(LO, rs_u() / rt_u()); |
3710 set_register(HI, rs_u() % rt_u()); | 3855 set_register(HI, rs_u() % rt_u()); |
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3784 break; | 3929 break; |
3785 case TNE: | 3930 case TNE: |
3786 do_interrupt = rs() != rt(); | 3931 do_interrupt = rs() != rt(); |
3787 break; | 3932 break; |
3788 case SYNC: | 3933 case SYNC: |
3789 // TODO(palfia): Ignore sync instruction for now. | 3934 // TODO(palfia): Ignore sync instruction for now. |
3790 break; | 3935 break; |
3791 // Conditional moves. | 3936 // Conditional moves. |
3792 case MOVN: | 3937 case MOVN: |
3793 if (rt()) { | 3938 if (rt()) { |
3794 set_register(rd_reg(), rs()); | 3939 SetResult(rd_reg(), rs()); |
3795 TraceRegWr(rs()); | |
3796 } | 3940 } |
3797 break; | 3941 break; |
3798 case MOVCI: { | 3942 case MOVCI: { |
3799 uint32_t cc = instr_.FBccValue(); | 3943 uint32_t cc = instr_.FBccValue(); |
3800 uint32_t fcsr_cc = get_fcsr_condition_bit(cc); | 3944 uint32_t fcsr_cc = get_fcsr_condition_bit(cc); |
3801 if (instr_.Bit(16)) { // Read Tf bit. | 3945 if (instr_.Bit(16)) { // Read Tf bit. |
3802 if (test_fcsr_bit(fcsr_cc)) set_register(rd_reg(), rs()); | 3946 if (test_fcsr_bit(fcsr_cc)) set_register(rd_reg(), rs()); |
3803 } else { | 3947 } else { |
3804 if (!test_fcsr_bit(fcsr_cc)) set_register(rd_reg(), rs()); | 3948 if (!test_fcsr_bit(fcsr_cc)) set_register(rd_reg(), rs()); |
3805 } | 3949 } |
3806 break; | 3950 break; |
3807 } | 3951 } |
3808 case MOVZ: | 3952 case MOVZ: |
3809 if (!rt()) { | 3953 if (!rt()) { |
3810 set_register(rd_reg(), rs()); | 3954 SetResult(rd_reg(), rs()); |
3811 TraceRegWr(rs()); | |
3812 } | 3955 } |
3813 break; | 3956 break; |
3814 default: | 3957 default: |
3815 UNREACHABLE(); | 3958 UNREACHABLE(); |
3816 } | 3959 } |
3817 if (do_interrupt) { | 3960 if (do_interrupt) { |
3818 SoftwareInterrupt(); | 3961 SoftwareInterrupt(); |
3819 } | 3962 } |
3820 } | 3963 } |
3821 | 3964 |
(...skipping 543 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4365 uint8_t al_offset = (rs + se_imm16) & kPointerAlignmentMask; | 4508 uint8_t al_offset = (rs + se_imm16) & kPointerAlignmentMask; |
4366 uint32_t mask = (1 << al_offset * 8) - 1; | 4509 uint32_t mask = (1 << al_offset * 8) - 1; |
4367 addr = rs + se_imm16 - al_offset; | 4510 addr = rs + se_imm16 - al_offset; |
4368 uint32_t mem_value = ReadW(addr, instr_.instr()); | 4511 uint32_t mem_value = ReadW(addr, instr_.instr()); |
4369 mem_value = (rt << al_offset * 8) | (mem_value & mask); | 4512 mem_value = (rt << al_offset * 8) | (mem_value & mask); |
4370 WriteW(addr, mem_value, instr_.instr()); | 4513 WriteW(addr, mem_value, instr_.instr()); |
4371 break; | 4514 break; |
4372 } | 4515 } |
4373 case LWC1: | 4516 case LWC1: |
4374 set_fpu_register_hi_word(ft_reg, 0); | 4517 set_fpu_register_hi_word(ft_reg, 0); |
4375 set_fpu_register_word(ft_reg, ReadW(rs + se_imm16, instr_.instr())); | 4518 set_fpu_register_word(ft_reg, |
| 4519 ReadW(rs + se_imm16, instr_.instr(), FLOAT)); |
| 4520 if (ft_reg % 2) { |
| 4521 TraceMemRd(rs + se_imm16, get_fpu_register(ft_reg - 1), FLOAT_DOUBLE); |
| 4522 } else { |
| 4523 TraceMemRd(rs + se_imm16, get_fpu_register_word(ft_reg), FLOAT); |
| 4524 } |
4376 break; | 4525 break; |
4377 case LDC1: | 4526 case LDC1: |
4378 set_fpu_register_double(ft_reg, ReadD(rs + se_imm16, instr_.instr())); | 4527 set_fpu_register_double(ft_reg, ReadD(rs + se_imm16, instr_.instr())); |
| 4528 TraceMemRd(rs + se_imm16, get_fpu_register(ft_reg), DOUBLE); |
4379 break; | 4529 break; |
4380 case SWC1: | 4530 case SWC1: |
4381 WriteW(rs + se_imm16, get_fpu_register_word(ft_reg), instr_.instr()); | 4531 WriteW(rs + se_imm16, get_fpu_register_word(ft_reg), instr_.instr()); |
| 4532 TraceMemWr(rs + se_imm16, get_fpu_register_word(ft_reg)); |
4382 break; | 4533 break; |
4383 case SDC1: | 4534 case SDC1: |
4384 WriteD(rs + se_imm16, get_fpu_register_double(ft_reg), instr_.instr()); | 4535 WriteD(rs + se_imm16, get_fpu_register_double(ft_reg), instr_.instr()); |
| 4536 TraceMemWr(rs + se_imm16, get_fpu_register(ft_reg)); |
4385 break; | 4537 break; |
4386 // ------------- PC-Relative instructions. | 4538 // ------------- PC-Relative instructions. |
4387 case PCREL: { | 4539 case PCREL: { |
4388 // rt field: checking 5-bits. | 4540 // rt field: checking 5-bits. |
4389 int32_t imm21 = instr_.Imm21Value(); | 4541 int32_t imm21 = instr_.Imm21Value(); |
4390 int32_t current_pc = get_pc(); | 4542 int32_t current_pc = get_pc(); |
4391 uint8_t rt = (imm21 >> kImm16Bits); | 4543 uint8_t rt = (imm21 >> kImm16Bits); |
4392 switch (rt) { | 4544 switch (rt) { |
4393 case ALUIPC: | 4545 case ALUIPC: |
4394 addr = current_pc + (se_imm16 << 16); | 4546 addr = current_pc + (se_imm16 << 16); |
(...skipping 20 matching lines...) Expand all Loading... |
4415 int32_t se_imm19 = imm19 | ((imm19 & 0x40000) ? 0xfff80000 : 0); | 4567 int32_t se_imm19 = imm19 | ((imm19 & 0x40000) ? 0xfff80000 : 0); |
4416 alu_out = current_pc + (se_imm19 << 2); | 4568 alu_out = current_pc + (se_imm19 << 2); |
4417 break; | 4569 break; |
4418 } | 4570 } |
4419 default: | 4571 default: |
4420 UNREACHABLE(); | 4572 UNREACHABLE(); |
4421 break; | 4573 break; |
4422 } | 4574 } |
4423 } | 4575 } |
4424 } | 4576 } |
4425 set_register(rs_reg, alu_out); | 4577 SetResult(rs_reg, alu_out); |
4426 break; | 4578 break; |
4427 } | 4579 } |
4428 default: | 4580 default: |
4429 UNREACHABLE(); | 4581 UNREACHABLE(); |
4430 } | 4582 } |
4431 | 4583 |
4432 if (execute_branch_delay_instruction) { | 4584 if (execute_branch_delay_instruction) { |
4433 // Execute branch delay slot | 4585 // Execute branch delay slot |
4434 // We don't check for end_sim_pc. First it should not be met as the current | 4586 // We don't check for end_sim_pc. First it should not be met as the current |
4435 // pc is valid. Secondly a jump should always execute its branch delay slot. | 4587 // pc is valid. Secondly a jump should always execute its branch delay slot. |
(...skipping 258 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4694 | 4846 |
4695 | 4847 |
4696 #undef UNSUPPORTED | 4848 #undef UNSUPPORTED |
4697 | 4849 |
4698 } // namespace internal | 4850 } // namespace internal |
4699 } // namespace v8 | 4851 } // namespace v8 |
4700 | 4852 |
4701 #endif // USE_SIMULATOR | 4853 #endif // USE_SIMULATOR |
4702 | 4854 |
4703 #endif // V8_TARGET_ARCH_MIPS | 4855 #endif // V8_TARGET_ARCH_MIPS |
OLD | NEW |