Chromium Code Reviews| 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 int64_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; | |
|
ivica.bogosavljevic
2017/01/23 13:22:38
According to strict C/C++, bitwise operation shoul
Ilija.Pavlovic1
2017/01/27 09:09:16
Done.
| |
| 1140 return 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 default: | |
| 1716 break; | |
|
ivica.bogosavljevic
2017/01/23 13:22:38
this should be UNREACHABLE, right?
Ilija.Pavlovic1
2017/01/27 09:09:16
Yes, this should be UNREACHABLE(). Also, missing "
| |
| 1717 } | |
| 1694 } | 1718 } |
| 1695 } | 1719 } |
| 1696 | 1720 |
| 1721 void Simulator::TraceRegWr(int64_t value, TraceType t) { | |
| 1722 if (::v8::internal::FLAG_trace_sim) { | |
| 1723 union { | |
| 1724 int64_t fmt_int64; | |
| 1725 double fmt_double; | |
| 1726 } v; | |
| 1727 v.fmt_int64 = value; | |
| 1697 | 1728 |
| 1698 // TODO(plind): consider making icount_ printing a flag option. | 1729 switch (t) { |
| 1699 void Simulator::TraceMemRd(int32_t addr, int32_t value) { | 1730 case DWORD: |
| 1700 if (::v8::internal::FLAG_trace_sim) { | 1731 SNPrintF(trace_buf_, "%016" PRIx64 " (%" PRIu64 ") int64:%" PRId64 |
| 1701 SNPrintF(trace_buf_, "%08x <-- [%08x] (%" PRIu64 ")", value, addr, | 1732 " uint64:%" PRIu64, |
| 1702 icount_); | 1733 value, icount_, value, value); |
| 1734 break; | |
| 1735 case DOUBLE: | |
| 1736 SNPrintF(trace_buf_, "%016" PRIx64 " (%" PRIu64 ") dbl:%e", | |
| 1737 v.fmt_int64, icount_, v.fmt_double); | |
| 1738 default: | |
| 1739 break; | |
|
ivica.bogosavljevic
2017/01/23 13:22:38
UNREACHABLE!
Ilija.Pavlovic1
2017/01/27 09:09:16
Done.
| |
| 1740 } | |
| 1703 } | 1741 } |
| 1704 } | 1742 } |
| 1705 | 1743 |
| 1744 // TODO(plind): consider making icount_ printing a flag option. | |
| 1745 void Simulator::TraceMemRd(int32_t addr, int32_t value, TraceType t) { | |
| 1746 if (::v8::internal::FLAG_trace_sim) { | |
| 1747 union { | |
| 1748 int32_t fmt_int32; | |
| 1749 float fmt_float; | |
| 1750 } v; | |
| 1751 v.fmt_int32 = value; | |
| 1752 | |
| 1753 switch (t) { | |
| 1754 case WORD: | |
| 1755 SNPrintF(trace_buf_, "%08" PRIx32 " <-- [%08" PRIx32 "] (%" PRIu64 | |
| 1756 ") int32:%" PRId32 " uint32:%" PRIu32, | |
| 1757 value, addr, icount_, value, value); | |
| 1758 break; | |
| 1759 case FLOAT: | |
| 1760 SNPrintF(trace_buf_, | |
| 1761 "%08" PRIx32 " <-- [%08" PRIx32 "] (%" PRIu64 ") flt:%e", | |
| 1762 v.fmt_int32, addr, icount_, v.fmt_float); | |
| 1763 break; | |
| 1764 default: | |
| 1765 break; | |
|
ivica.bogosavljevic
2017/01/23 13:22:38
ibid here and all places bellow!
Ilija.Pavlovic1
2017/01/27 09:09:16
Done.
| |
| 1766 } | |
| 1767 } | |
| 1768 } | |
| 1769 | |
| 1706 | 1770 |
| 1707 void Simulator::TraceMemWr(int32_t addr, int32_t value, TraceType t) { | 1771 void Simulator::TraceMemWr(int32_t addr, int32_t value, TraceType t) { |
| 1708 if (::v8::internal::FLAG_trace_sim) { | 1772 if (::v8::internal::FLAG_trace_sim) { |
| 1709 switch (t) { | 1773 switch (t) { |
| 1710 case BYTE: | 1774 case BYTE: |
| 1711 SNPrintF(trace_buf_, " %02x --> [%08x]", | 1775 SNPrintF(trace_buf_, |
| 1712 static_cast<int8_t>(value), addr); | 1776 " %02" PRIx8 " --> [%08" PRIx32 "] (%" PRIu64 ")", |
| 1777 static_cast<uint8_t>(value), addr, icount_); | |
| 1713 break; | 1778 break; |
| 1714 case HALF: | 1779 case HALF: |
| 1715 SNPrintF(trace_buf_, " %04x --> [%08x]", static_cast<int16_t>(value), | 1780 SNPrintF(trace_buf_, |
| 1716 addr); | 1781 " %04" PRIx16 " --> [%08" PRIx32 "] (%" PRIu64 ")", |
| 1782 static_cast<uint16_t>(value), addr, icount_); | |
| 1717 break; | 1783 break; |
| 1718 case WORD: | 1784 case WORD: |
| 1719 SNPrintF(trace_buf_, "%08x --> [%08x]", value, addr); | 1785 SNPrintF(trace_buf_, |
| 1786 "%08" PRIx32 " --> [%08" PRIx32 "] (%" PRIu64 ")", value, | |
| 1787 addr, icount_); | |
| 1788 break; | |
| 1789 default: | |
| 1720 break; | 1790 break; |
| 1721 } | 1791 } |
| 1722 } | 1792 } |
| 1723 } | 1793 } |
| 1724 | 1794 |
| 1795 void Simulator::TraceMemRd(int32_t addr, int64_t value, TraceType t) { | |
| 1796 if (::v8::internal::FLAG_trace_sim) { | |
| 1797 union { | |
| 1798 int64_t fmt_int64; | |
| 1799 int32_t fmt_int32[2]; | |
| 1800 float fmt_float[2]; | |
| 1801 double fmt_double; | |
| 1802 } v; | |
| 1803 v.fmt_int64 = value; | |
| 1725 | 1804 |
| 1726 int Simulator::ReadW(int32_t addr, Instruction* instr) { | 1805 switch (t) { |
| 1806 case DWORD: | |
| 1807 SNPrintF(trace_buf_, "%016" PRIx64 " <-- [%08" PRIx32 "] (%" PRIu64 | |
| 1808 ") int64:%" PRId64 " uint64:%" PRIu64, | |
| 1809 v.fmt_int64, addr, icount_, v.fmt_int64, v.fmt_int64); | |
| 1810 break; | |
| 1811 case DOUBLE: | |
| 1812 SNPrintF(trace_buf_, "%016" PRIx64 " <-- [%08" PRIx32 "] (%" PRIu64 | |
| 1813 ") dbl:%e", | |
| 1814 v.fmt_int64, addr, icount_, v.fmt_double); | |
| 1815 break; | |
| 1816 case FLOAT_DOUBLE: | |
| 1817 SNPrintF(trace_buf_, "%08" PRIx32 " <-- [%08" PRIx32 "] (%" PRIu64 | |
| 1818 ") flt:%e dbl:%e", | |
| 1819 v.fmt_int32[1], addr, icount_, v.fmt_float[1], v.fmt_double); | |
| 1820 break; | |
| 1821 default: | |
| 1822 break; | |
| 1823 } | |
| 1824 } | |
| 1825 } | |
| 1826 | |
| 1827 void Simulator::TraceMemWr(int32_t addr, int64_t value, TraceType t) { | |
| 1828 if (::v8::internal::FLAG_trace_sim) { | |
| 1829 switch (t) { | |
| 1830 case DWORD: | |
| 1831 SNPrintF(trace_buf_, | |
| 1832 "%016" PRIx64 " --> [%08" PRIx32 "] (%" PRIu64 ")", value, | |
| 1833 addr, icount_); | |
| 1834 break; | |
| 1835 default: | |
| 1836 break; | |
| 1837 } | |
| 1838 } | |
| 1839 } | |
| 1840 | |
| 1841 int Simulator::ReadW(int32_t addr, Instruction* instr, TraceType t) { | |
| 1727 if (addr >=0 && addr < 0x400) { | 1842 if (addr >=0 && addr < 0x400) { |
| 1728 // This has to be a NULL-dereference, drop into debugger. | 1843 // 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, | 1844 PrintF("Memory read from bad address: 0x%08x, pc=0x%08" PRIxPTR "\n", addr, |
| 1730 reinterpret_cast<intptr_t>(instr)); | 1845 reinterpret_cast<intptr_t>(instr)); |
| 1731 MipsDebugger dbg(this); | 1846 MipsDebugger dbg(this); |
| 1732 dbg.Debug(); | 1847 dbg.Debug(); |
| 1733 } | 1848 } |
| 1734 if ((addr & kPointerAlignmentMask) == 0 || IsMipsArchVariant(kMips32r6)) { | 1849 if ((addr & kPointerAlignmentMask) == 0 || IsMipsArchVariant(kMips32r6)) { |
| 1735 intptr_t* ptr = reinterpret_cast<intptr_t*>(addr); | 1850 intptr_t* ptr = reinterpret_cast<intptr_t*>(addr); |
| 1736 TraceMemRd(addr, static_cast<int32_t>(*ptr)); | 1851 if (t == WORD) { |
| 1852 TraceMemRd(addr, static_cast<int32_t>(*ptr), t); | |
|
ivica.bogosavljevic
2017/01/23 13:22:38
What happens if t != WORD? Should it be unreachabl
Ilija.Pavlovic1
2017/01/27 09:09:16
For WORD, the trace should be visible.
For FLOAT,
| |
| 1853 } | |
| 1737 return *ptr; | 1854 return *ptr; |
| 1738 } | 1855 } |
| 1739 PrintF("Unaligned read at 0x%08x, pc=0x%08" V8PRIxPTR "\n", | 1856 PrintF("Unaligned read at 0x%08x, pc=0x%08" V8PRIxPTR "\n", |
| 1740 addr, | 1857 addr, |
| 1741 reinterpret_cast<intptr_t>(instr)); | 1858 reinterpret_cast<intptr_t>(instr)); |
| 1742 MipsDebugger dbg(this); | 1859 MipsDebugger dbg(this); |
| 1743 dbg.Debug(); | 1860 dbg.Debug(); |
| 1744 return 0; | 1861 return 0; |
| 1745 } | 1862 } |
| 1746 | 1863 |
| 1747 | |
| 1748 void Simulator::WriteW(int32_t addr, int value, Instruction* instr) { | 1864 void Simulator::WriteW(int32_t addr, int value, Instruction* instr) { |
| 1749 if (addr >= 0 && addr < 0x400) { | 1865 if (addr >= 0 && addr < 0x400) { |
| 1750 // This has to be a NULL-dereference, drop into debugger. | 1866 // 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, | 1867 PrintF("Memory write to bad address: 0x%08x, pc=0x%08" PRIxPTR "\n", addr, |
| 1752 reinterpret_cast<intptr_t>(instr)); | 1868 reinterpret_cast<intptr_t>(instr)); |
| 1753 MipsDebugger dbg(this); | 1869 MipsDebugger dbg(this); |
| 1754 dbg.Debug(); | 1870 dbg.Debug(); |
| 1755 } | 1871 } |
| 1756 if ((addr & kPointerAlignmentMask) == 0 || IsMipsArchVariant(kMips32r6)) { | 1872 if ((addr & kPointerAlignmentMask) == 0 || IsMipsArchVariant(kMips32r6)) { |
| 1757 intptr_t* ptr = reinterpret_cast<intptr_t*>(addr); | 1873 intptr_t* ptr = reinterpret_cast<intptr_t*>(addr); |
| 1758 TraceMemWr(addr, value, WORD); | 1874 TraceMemWr(addr, value, WORD); |
| 1759 *ptr = value; | 1875 *ptr = value; |
| 1760 return; | 1876 return; |
| 1761 } | 1877 } |
| 1762 PrintF("Unaligned write at 0x%08x, pc=0x%08" V8PRIxPTR "\n", | 1878 PrintF("Unaligned write at 0x%08x, pc=0x%08" V8PRIxPTR "\n", |
| 1763 addr, | 1879 addr, |
| 1764 reinterpret_cast<intptr_t>(instr)); | 1880 reinterpret_cast<intptr_t>(instr)); |
| 1765 MipsDebugger dbg(this); | 1881 MipsDebugger dbg(this); |
| 1766 dbg.Debug(); | 1882 dbg.Debug(); |
| 1767 } | 1883 } |
| 1768 | 1884 |
| 1769 | |
| 1770 double Simulator::ReadD(int32_t addr, Instruction* instr) { | 1885 double Simulator::ReadD(int32_t addr, Instruction* instr) { |
| 1771 if ((addr & kDoubleAlignmentMask) == 0 || IsMipsArchVariant(kMips32r6)) { | 1886 if ((addr & kDoubleAlignmentMask) == 0 || IsMipsArchVariant(kMips32r6)) { |
| 1772 double* ptr = reinterpret_cast<double*>(addr); | 1887 double* ptr = reinterpret_cast<double*>(addr); |
| 1773 return *ptr; | 1888 return *ptr; |
| 1774 } | 1889 } |
| 1775 PrintF("Unaligned (double) read at 0x%08x, pc=0x%08" V8PRIxPTR "\n", | 1890 PrintF("Unaligned (double) read at 0x%08x, pc=0x%08" V8PRIxPTR "\n", |
| 1776 addr, | 1891 addr, |
| 1777 reinterpret_cast<intptr_t>(instr)); | 1892 reinterpret_cast<intptr_t>(instr)); |
| 1778 base::OS::Abort(); | 1893 base::OS::Abort(); |
| 1779 return 0; | 1894 return 0; |
| (...skipping 677 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2457 result = upper; | 2572 result = upper; |
| 2458 break; | 2573 break; |
| 2459 case kRoundToMinusInf: | 2574 case kRoundToMinusInf: |
| 2460 result = lower; | 2575 result = lower; |
| 2461 break; | 2576 break; |
| 2462 } | 2577 } |
| 2463 set_fpu_register_double(fd_reg(), result); | 2578 set_fpu_register_double(fd_reg(), result); |
| 2464 if (result != fs) { | 2579 if (result != fs) { |
| 2465 set_fcsr_bit(kFCSRInexactFlagBit, true); | 2580 set_fcsr_bit(kFCSRInexactFlagBit, true); |
| 2466 } | 2581 } |
| 2582 TraceRegWr(get_fpu_register(fd_reg()), DOUBLE); | |
| 2467 break; | 2583 break; |
| 2468 } | 2584 } |
| 2469 case SEL: | 2585 case SEL: |
| 2470 DCHECK(IsMipsArchVariant(kMips32r6)); | 2586 DCHECK(IsMipsArchVariant(kMips32r6)); |
| 2471 set_fpu_register_double(fd_reg(), (fd_int & 0x1) == 0 ? fs : ft); | 2587 set_fpu_register_double(fd_reg(), (fd_int & 0x1) == 0 ? fs : ft); |
| 2588 TraceRegWr(get_fpu_register(fd_reg()), DOUBLE); | |
| 2472 break; | 2589 break; |
| 2473 case SELEQZ_C: | 2590 case SELEQZ_C: |
| 2474 DCHECK(IsMipsArchVariant(kMips32r6)); | 2591 DCHECK(IsMipsArchVariant(kMips32r6)); |
| 2475 set_fpu_register_double(fd_reg(), (ft_int & 0x1) == 0 ? fs : 0.0); | 2592 set_fpu_register_double(fd_reg(), (ft_int & 0x1) == 0 ? fs : 0.0); |
| 2593 TraceRegWr(get_fpu_register(fd_reg()), DOUBLE); | |
| 2476 break; | 2594 break; |
| 2477 case SELNEZ_C: | 2595 case SELNEZ_C: |
| 2478 DCHECK(IsMipsArchVariant(kMips32r6)); | 2596 DCHECK(IsMipsArchVariant(kMips32r6)); |
| 2479 set_fpu_register_double(fd_reg(), (ft_int & 0x1) != 0 ? fs : 0.0); | 2597 set_fpu_register_double(fd_reg(), (ft_int & 0x1) != 0 ? fs : 0.0); |
| 2598 TraceRegWr(get_fpu_register(fd_reg()), DOUBLE); | |
| 2480 break; | 2599 break; |
| 2481 case MOVZ_C: { | 2600 case MOVZ_C: { |
| 2482 DCHECK(IsMipsArchVariant(kMips32r2)); | 2601 DCHECK(IsMipsArchVariant(kMips32r2)); |
| 2483 if (rt() == 0) { | 2602 if (rt() == 0) { |
| 2484 set_fpu_register_double(fd_reg(), fs); | 2603 set_fpu_register_double(fd_reg(), fs); |
| 2485 } | 2604 } |
| 2605 TraceRegWr(get_fpu_register(fd_reg()), DOUBLE); | |
| 2486 break; | 2606 break; |
| 2487 } | 2607 } |
| 2488 case MOVN_C: { | 2608 case MOVN_C: { |
| 2489 DCHECK(IsMipsArchVariant(kMips32r2)); | 2609 DCHECK(IsMipsArchVariant(kMips32r2)); |
| 2490 int32_t rt_reg = instr_.RtValue(); | 2610 int32_t rt_reg = instr_.RtValue(); |
| 2491 int32_t rt = get_register(rt_reg); | 2611 int32_t rt = get_register(rt_reg); |
| 2492 if (rt != 0) { | 2612 if (rt != 0) { |
| 2493 set_fpu_register_double(fd_reg(), fs); | 2613 set_fpu_register_double(fd_reg(), fs); |
| 2494 } | 2614 } |
| 2615 TraceRegWr(get_fpu_register(fd_reg()), DOUBLE); | |
| 2495 break; | 2616 break; |
| 2496 } | 2617 } |
| 2497 case MOVF: { | 2618 case MOVF: { |
| 2498 // Same function field for MOVT.D and MOVF.D | 2619 // Same function field for MOVT.D and MOVF.D |
| 2499 uint32_t ft_cc = (ft_reg() >> 2) & 0x7; | 2620 uint32_t ft_cc = (ft_reg() >> 2) & 0x7; |
| 2500 ft_cc = get_fcsr_condition_bit(ft_cc); | 2621 ft_cc = get_fcsr_condition_bit(ft_cc); |
| 2501 if (instr_.Bit(16)) { // Read Tf bit. | 2622 if (instr_.Bit(16)) { // Read Tf bit. |
| 2502 // MOVT.D | 2623 // MOVT.D |
| 2503 if (test_fcsr_bit(ft_cc)) set_fpu_register_double(fd_reg(), fs); | 2624 if (test_fcsr_bit(ft_cc)) set_fpu_register_double(fd_reg(), fs); |
| 2504 } else { | 2625 } else { |
| 2505 // MOVF.D | 2626 // MOVF.D |
| 2506 if (!test_fcsr_bit(ft_cc)) set_fpu_register_double(fd_reg(), fs); | 2627 if (!test_fcsr_bit(ft_cc)) set_fpu_register_double(fd_reg(), fs); |
| 2507 } | 2628 } |
| 2629 TraceRegWr(get_fpu_register(fd_reg()), DOUBLE); | |
| 2508 break; | 2630 break; |
| 2509 } | 2631 } |
| 2510 case MIN: | 2632 case MIN: |
| 2511 DCHECK(IsMipsArchVariant(kMips32r6)); | 2633 DCHECK(IsMipsArchVariant(kMips32r6)); |
| 2512 set_fpu_register_double(fd_reg(), FPUMin(ft, fs)); | 2634 set_fpu_register_double(fd_reg(), FPUMin(ft, fs)); |
| 2635 TraceRegWr(get_fpu_register(fd_reg()), DOUBLE); | |
| 2513 break; | 2636 break; |
| 2514 case MAX: | 2637 case MAX: |
| 2515 DCHECK(IsMipsArchVariant(kMips32r6)); | 2638 DCHECK(IsMipsArchVariant(kMips32r6)); |
| 2516 set_fpu_register_double(fd_reg(), FPUMax(ft, fs)); | 2639 set_fpu_register_double(fd_reg(), FPUMax(ft, fs)); |
| 2640 TraceRegWr(get_fpu_register(fd_reg()), DOUBLE); | |
| 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 set_fpu_register_double(fd_reg(), FPUMinA(ft, fs)); |
| 2645 TraceRegWr(get_fpu_register(fd_reg()), DOUBLE); | |
| 2521 break; | 2646 break; |
| 2522 case MAXA: | 2647 case MAXA: |
| 2523 DCHECK(IsMipsArchVariant(kMips32r6)); | 2648 DCHECK(IsMipsArchVariant(kMips32r6)); |
| 2524 set_fpu_register_double(fd_reg(), FPUMaxA(ft, fs)); | 2649 set_fpu_register_double(fd_reg(), FPUMaxA(ft, fs)); |
| 2650 TraceRegWr(get_fpu_register(fd_reg()), DOUBLE); | |
| 2525 break; | 2651 break; |
| 2526 case ADD_D: | 2652 case ADD_D: |
| 2527 set_fpu_register_double( | 2653 set_fpu_register_double( |
| 2528 fd_reg(), | 2654 fd_reg(), |
| 2529 FPUCanonalizeOperation( | 2655 FPUCanonalizeOperation( |
| 2530 [](double lhs, double rhs) { return lhs + rhs; }, fs, ft)); | 2656 [](double lhs, double rhs) { return lhs + rhs; }, fs, ft)); |
| 2657 TraceRegWr(get_fpu_register(fd_reg()), DOUBLE); | |
| 2531 break; | 2658 break; |
| 2532 case SUB_D: | 2659 case SUB_D: |
| 2533 set_fpu_register_double( | 2660 set_fpu_register_double( |
| 2534 fd_reg(), | 2661 fd_reg(), |
| 2535 FPUCanonalizeOperation( | 2662 FPUCanonalizeOperation( |
| 2536 [](double lhs, double rhs) { return lhs - rhs; }, fs, ft)); | 2663 [](double lhs, double rhs) { return lhs - rhs; }, fs, ft)); |
| 2664 TraceRegWr(get_fpu_register(fd_reg()), DOUBLE); | |
| 2537 break; | 2665 break; |
| 2538 case MADDF_D: | 2666 case MADDF_D: |
| 2539 DCHECK(IsMipsArchVariant(kMips32r6)); | 2667 DCHECK(IsMipsArchVariant(kMips32r6)); |
| 2540 set_fpu_register_double(fd_reg(), std::fma(fs, ft, fd)); | 2668 set_fpu_register_double(fd_reg(), std::fma(fs, ft, fd)); |
| 2669 TraceRegWr(get_fpu_register(fd_reg()), DOUBLE); | |
| 2541 break; | 2670 break; |
| 2542 case MSUBF_D: | 2671 case MSUBF_D: |
| 2543 DCHECK(IsMipsArchVariant(kMips32r6)); | 2672 DCHECK(IsMipsArchVariant(kMips32r6)); |
| 2544 set_fpu_register_double(fd_reg(), std::fma(-fs, ft, fd)); | 2673 set_fpu_register_double(fd_reg(), std::fma(-fs, ft, fd)); |
| 2674 TraceRegWr(get_fpu_register(fd_reg()), DOUBLE); | |
| 2545 break; | 2675 break; |
| 2546 case MUL_D: | 2676 case MUL_D: |
| 2547 set_fpu_register_double( | 2677 set_fpu_register_double( |
| 2548 fd_reg(), | 2678 fd_reg(), |
| 2549 FPUCanonalizeOperation( | 2679 FPUCanonalizeOperation( |
| 2550 [](double lhs, double rhs) { return lhs * rhs; }, fs, ft)); | 2680 [](double lhs, double rhs) { return lhs * rhs; }, fs, ft)); |
| 2681 TraceRegWr(get_fpu_register(fd_reg()), DOUBLE); | |
| 2551 break; | 2682 break; |
| 2552 case DIV_D: | 2683 case DIV_D: |
| 2553 set_fpu_register_double( | 2684 set_fpu_register_double( |
| 2554 fd_reg(), | 2685 fd_reg(), |
| 2555 FPUCanonalizeOperation( | 2686 FPUCanonalizeOperation( |
| 2556 [](double lhs, double rhs) { return lhs / rhs; }, fs, ft)); | 2687 [](double lhs, double rhs) { return lhs / rhs; }, fs, ft)); |
| 2688 TraceRegWr(get_fpu_register(fd_reg()), DOUBLE); | |
| 2557 break; | 2689 break; |
| 2558 case ABS_D: | 2690 case ABS_D: |
| 2559 set_fpu_register_double( | 2691 set_fpu_register_double( |
| 2560 fd_reg(), | 2692 fd_reg(), |
| 2561 FPUCanonalizeOperation([](double fs) { return FPAbs(fs); }, fs)); | 2693 FPUCanonalizeOperation([](double fs) { return FPAbs(fs); }, fs)); |
| 2694 TraceRegWr(get_fpu_register(fd_reg()), DOUBLE); | |
| 2562 break; | 2695 break; |
| 2563 case MOV_D: | 2696 case MOV_D: |
| 2564 set_fpu_register_double(fd_reg(), fs); | 2697 set_fpu_register_double(fd_reg(), fs); |
| 2698 TraceRegWr(get_fpu_register(fd_reg()), DOUBLE); | |
| 2565 break; | 2699 break; |
| 2566 case NEG_D: | 2700 case NEG_D: |
| 2567 set_fpu_register_double( | 2701 set_fpu_register_double( |
| 2568 fd_reg(), FPUCanonalizeOperation([](double src) { return -src; }, | 2702 fd_reg(), FPUCanonalizeOperation([](double src) { return -src; }, |
| 2569 KeepSign::yes, fs)); | 2703 KeepSign::yes, fs)); |
| 2704 TraceRegWr(get_fpu_register(fd_reg()), DOUBLE); | |
| 2570 break; | 2705 break; |
| 2571 case SQRT_D: | 2706 case SQRT_D: |
| 2572 set_fpu_register_double( | 2707 set_fpu_register_double( |
| 2573 fd_reg(), | 2708 fd_reg(), |
| 2574 FPUCanonalizeOperation([](double fs) { return std::sqrt(fs); }, fs)); | 2709 FPUCanonalizeOperation([](double fs) { return std::sqrt(fs); }, fs)); |
| 2710 TraceRegWr(get_fpu_register(fd_reg()), DOUBLE); | |
| 2575 break; | 2711 break; |
| 2576 case RSQRT_D: | 2712 case RSQRT_D: |
| 2577 set_fpu_register_double( | 2713 set_fpu_register_double( |
| 2578 fd_reg(), FPUCanonalizeOperation( | 2714 fd_reg(), FPUCanonalizeOperation( |
| 2579 [](double fs) { return 1.0 / std::sqrt(fs); }, fs)); | 2715 [](double fs) { return 1.0 / std::sqrt(fs); }, fs)); |
| 2716 TraceRegWr(get_fpu_register(fd_reg()), DOUBLE); | |
| 2580 break; | 2717 break; |
| 2581 case RECIP_D: | 2718 case RECIP_D: |
| 2582 set_fpu_register_double( | 2719 set_fpu_register_double( |
| 2583 fd_reg(), | 2720 fd_reg(), |
| 2584 FPUCanonalizeOperation([](double fs) { return 1.0 / fs; }, fs)); | 2721 FPUCanonalizeOperation([](double fs) { return 1.0 / fs; }, fs)); |
| 2722 TraceRegWr(get_fpu_register(fd_reg()), DOUBLE); | |
| 2585 break; | 2723 break; |
| 2586 case C_UN_D: | 2724 case C_UN_D: |
| 2587 set_fcsr_bit(fcsr_cc, std::isnan(fs) || std::isnan(ft)); | 2725 set_fcsr_bit(fcsr_cc, std::isnan(fs) || std::isnan(ft)); |
| 2726 TraceRegWr(test_fcsr_bit(fcsr_cc)); | |
| 2588 break; | 2727 break; |
| 2589 case C_EQ_D: | 2728 case C_EQ_D: |
| 2590 set_fcsr_bit(fcsr_cc, (fs == ft)); | 2729 set_fcsr_bit(fcsr_cc, (fs == ft)); |
| 2730 TraceRegWr(test_fcsr_bit(fcsr_cc)); | |
| 2591 break; | 2731 break; |
| 2592 case C_UEQ_D: | 2732 case C_UEQ_D: |
| 2593 set_fcsr_bit(fcsr_cc, (fs == ft) || (std::isnan(fs) || std::isnan(ft))); | 2733 set_fcsr_bit(fcsr_cc, (fs == ft) || (std::isnan(fs) || std::isnan(ft))); |
| 2734 TraceRegWr(test_fcsr_bit(fcsr_cc)); | |
| 2594 break; | 2735 break; |
| 2595 case C_OLT_D: | 2736 case C_OLT_D: |
| 2596 set_fcsr_bit(fcsr_cc, (fs < ft)); | 2737 set_fcsr_bit(fcsr_cc, (fs < ft)); |
| 2738 TraceRegWr(test_fcsr_bit(fcsr_cc)); | |
| 2597 break; | 2739 break; |
| 2598 case C_ULT_D: | 2740 case C_ULT_D: |
| 2599 set_fcsr_bit(fcsr_cc, (fs < ft) || (std::isnan(fs) || std::isnan(ft))); | 2741 set_fcsr_bit(fcsr_cc, (fs < ft) || (std::isnan(fs) || std::isnan(ft))); |
| 2742 TraceRegWr(test_fcsr_bit(fcsr_cc)); | |
| 2600 break; | 2743 break; |
| 2601 case C_OLE_D: | 2744 case C_OLE_D: |
| 2602 set_fcsr_bit(fcsr_cc, (fs <= ft)); | 2745 set_fcsr_bit(fcsr_cc, (fs <= ft)); |
| 2746 TraceRegWr(test_fcsr_bit(fcsr_cc)); | |
| 2603 break; | 2747 break; |
| 2604 case C_ULE_D: | 2748 case C_ULE_D: |
| 2605 set_fcsr_bit(fcsr_cc, (fs <= ft) || (std::isnan(fs) || std::isnan(ft))); | 2749 set_fcsr_bit(fcsr_cc, (fs <= ft) || (std::isnan(fs) || std::isnan(ft))); |
| 2750 TraceRegWr(test_fcsr_bit(fcsr_cc)); | |
| 2606 break; | 2751 break; |
| 2607 case CVT_W_D: { // Convert double to word. | 2752 case CVT_W_D: { // Convert double to word. |
| 2608 double rounded; | 2753 double rounded; |
| 2609 int32_t result; | 2754 int32_t result; |
| 2610 round_according_to_fcsr(fs, rounded, result, fs); | 2755 round_according_to_fcsr(fs, rounded, result, fs); |
| 2611 set_fpu_register_word(fd_reg(), result); | 2756 set_fpu_register_word(fd_reg(), result); |
| 2612 if (set_fcsr_round_error(fs, rounded)) { | 2757 if (set_fcsr_round_error(fs, rounded)) { |
| 2613 set_fpu_register_word_invalid_result(fs, rounded); | 2758 set_fpu_register_word_invalid_result(fs, rounded); |
| 2614 } | 2759 } |
| 2760 TraceRegWr(get_fpu_register_word(fd_reg())); | |
| 2615 } break; | 2761 } break; |
| 2616 case ROUND_W_D: // Round double to word (round half to even). | 2762 case ROUND_W_D: // Round double to word (round half to even). |
| 2617 { | 2763 { |
| 2618 double rounded = std::floor(fs + 0.5); | 2764 double rounded = std::floor(fs + 0.5); |
| 2619 int32_t result = static_cast<int32_t>(rounded); | 2765 int32_t result = static_cast<int32_t>(rounded); |
| 2620 if ((result & 1) != 0 && result - fs == 0.5) { | 2766 if ((result & 1) != 0 && result - fs == 0.5) { |
| 2621 // If the number is halfway between two integers, | 2767 // If the number is halfway between two integers, |
| 2622 // round to the even one. | 2768 // round to the even one. |
| 2623 result--; | 2769 result--; |
| 2624 } | 2770 } |
| 2625 set_fpu_register_word(fd_reg(), result); | 2771 set_fpu_register_word(fd_reg(), result); |
| 2626 if (set_fcsr_round_error(fs, rounded)) { | 2772 if (set_fcsr_round_error(fs, rounded)) { |
| 2627 set_fpu_register_word_invalid_result(fs, rounded); | 2773 set_fpu_register_word_invalid_result(fs, rounded); |
| 2628 } | 2774 } |
| 2775 TraceRegWr(get_fpu_register_word(fd_reg())); | |
| 2629 } break; | 2776 } break; |
| 2630 case TRUNC_W_D: // Truncate double to word (round towards 0). | 2777 case TRUNC_W_D: // Truncate double to word (round towards 0). |
| 2631 { | 2778 { |
| 2632 double rounded = trunc(fs); | 2779 double rounded = trunc(fs); |
| 2633 int32_t result = static_cast<int32_t>(rounded); | 2780 int32_t result = static_cast<int32_t>(rounded); |
| 2634 set_fpu_register_word(fd_reg(), result); | 2781 set_fpu_register_word(fd_reg(), result); |
| 2635 if (set_fcsr_round_error(fs, rounded)) { | 2782 if (set_fcsr_round_error(fs, rounded)) { |
| 2636 set_fpu_register_word_invalid_result(fs, rounded); | 2783 set_fpu_register_word_invalid_result(fs, rounded); |
| 2637 } | 2784 } |
| 2785 TraceRegWr(get_fpu_register_word(fd_reg())); | |
| 2638 } break; | 2786 } break; |
| 2639 case FLOOR_W_D: // Round double to word towards negative infinity. | 2787 case FLOOR_W_D: // Round double to word towards negative infinity. |
| 2640 { | 2788 { |
| 2641 double rounded = std::floor(fs); | 2789 double rounded = std::floor(fs); |
| 2642 int32_t result = static_cast<int32_t>(rounded); | 2790 int32_t result = static_cast<int32_t>(rounded); |
| 2643 set_fpu_register_word(fd_reg(), result); | 2791 set_fpu_register_word(fd_reg(), result); |
| 2644 if (set_fcsr_round_error(fs, rounded)) { | 2792 if (set_fcsr_round_error(fs, rounded)) { |
| 2645 set_fpu_register_word_invalid_result(fs, rounded); | 2793 set_fpu_register_word_invalid_result(fs, rounded); |
| 2646 } | 2794 } |
| 2795 TraceRegWr(get_fpu_register_word(fd_reg())); | |
| 2647 } break; | 2796 } break; |
| 2648 case CEIL_W_D: // Round double to word towards positive infinity. | 2797 case CEIL_W_D: // Round double to word towards positive infinity. |
| 2649 { | 2798 { |
| 2650 double rounded = std::ceil(fs); | 2799 double rounded = std::ceil(fs); |
| 2651 int32_t result = static_cast<int32_t>(rounded); | 2800 int32_t result = static_cast<int32_t>(rounded); |
| 2652 set_fpu_register_word(fd_reg(), result); | 2801 set_fpu_register_word(fd_reg(), result); |
| 2653 if (set_fcsr_round_error(fs, rounded)) { | 2802 if (set_fcsr_round_error(fs, rounded)) { |
| 2654 set_fpu_register_word_invalid_result(fs, rounded); | 2803 set_fpu_register_word_invalid_result(fs, rounded); |
| 2655 } | 2804 } |
| 2805 TraceRegWr(get_fpu_register_word(fd_reg())); | |
| 2656 } break; | 2806 } break; |
| 2657 case CVT_S_D: // Convert double to float (single). | 2807 case CVT_S_D: // Convert double to float (single). |
| 2658 set_fpu_register_float(fd_reg(), static_cast<float>(fs)); | 2808 set_fpu_register_float(fd_reg(), static_cast<float>(fs)); |
| 2809 TraceRegWr(get_fpu_register_word(fd_reg()), FLOAT); | |
| 2659 break; | 2810 break; |
| 2660 case CVT_L_D: { // Mips32r2: Truncate double to 64-bit long-word. | 2811 case CVT_L_D: { // Mips32r2: Truncate double to 64-bit long-word. |
| 2661 if (IsFp64Mode()) { | 2812 if (IsFp64Mode()) { |
| 2662 int64_t result; | 2813 int64_t result; |
| 2663 double rounded; | 2814 double rounded; |
| 2664 round64_according_to_fcsr(fs, rounded, result, fs); | 2815 round64_according_to_fcsr(fs, rounded, result, fs); |
| 2665 set_fpu_register(fd_reg(), result); | 2816 set_fpu_register(fd_reg(), result); |
| 2666 if (set_fcsr_round64_error(fs, rounded)) { | 2817 if (set_fcsr_round64_error(fs, rounded)) { |
| 2667 set_fpu_register_invalid_result64(fs, rounded); | 2818 set_fpu_register_invalid_result64(fs, rounded); |
| 2668 } | 2819 } |
| 2820 TraceRegWr(get_fpu_register(fd_reg())); | |
| 2669 } else { | 2821 } else { |
| 2670 UNSUPPORTED(); | 2822 UNSUPPORTED(); |
| 2671 } | 2823 } |
| 2672 break; | 2824 break; |
| 2673 break; | 2825 break; |
| 2674 } | 2826 } |
| 2675 case TRUNC_L_D: { // Mips32r2 instruction. | 2827 case TRUNC_L_D: { // Mips32r2 instruction. |
| 2676 DCHECK(IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)); | 2828 DCHECK(IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)); |
| 2677 double rounded = trunc(fs); | 2829 double rounded = trunc(fs); |
| 2678 i64 = static_cast<int64_t>(rounded); | 2830 i64 = static_cast<int64_t>(rounded); |
| 2679 if (IsFp64Mode()) { | 2831 if (IsFp64Mode()) { |
| 2680 set_fpu_register(fd_reg(), i64); | 2832 set_fpu_register(fd_reg(), i64); |
| 2681 if (set_fcsr_round64_error(fs, rounded)) { | 2833 if (set_fcsr_round64_error(fs, rounded)) { |
| 2682 set_fpu_register_invalid_result64(fs, rounded); | 2834 set_fpu_register_invalid_result64(fs, rounded); |
| 2683 } | 2835 } |
| 2836 TraceRegWr(get_fpu_register(fd_reg())); | |
| 2684 } else { | 2837 } else { |
| 2685 UNSUPPORTED(); | 2838 UNSUPPORTED(); |
| 2686 } | 2839 } |
| 2687 break; | 2840 break; |
| 2688 } | 2841 } |
| 2689 case ROUND_L_D: { // Mips32r2 instruction. | 2842 case ROUND_L_D: { // Mips32r2 instruction. |
| 2690 DCHECK(IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)); | 2843 DCHECK(IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)); |
| 2691 double rounded = std::floor(fs + 0.5); | 2844 double rounded = std::floor(fs + 0.5); |
| 2692 int64_t result = static_cast<int64_t>(rounded); | 2845 int64_t result = static_cast<int64_t>(rounded); |
| 2693 if ((result & 1) != 0 && result - fs == 0.5) { | 2846 if ((result & 1) != 0 && result - fs == 0.5) { |
| 2694 // If the number is halfway between two integers, | 2847 // If the number is halfway between two integers, |
| 2695 // round to the even one. | 2848 // round to the even one. |
| 2696 result--; | 2849 result--; |
| 2697 } | 2850 } |
| 2698 int64_t i64 = static_cast<int64_t>(result); | 2851 int64_t i64 = static_cast<int64_t>(result); |
| 2699 if (IsFp64Mode()) { | 2852 if (IsFp64Mode()) { |
| 2700 set_fpu_register(fd_reg(), i64); | 2853 set_fpu_register(fd_reg(), i64); |
| 2701 if (set_fcsr_round64_error(fs, rounded)) { | 2854 if (set_fcsr_round64_error(fs, rounded)) { |
| 2702 set_fpu_register_invalid_result64(fs, rounded); | 2855 set_fpu_register_invalid_result64(fs, rounded); |
| 2703 } | 2856 } |
| 2857 TraceRegWr(get_fpu_register(fd_reg())); | |
| 2704 } else { | 2858 } else { |
| 2705 UNSUPPORTED(); | 2859 UNSUPPORTED(); |
| 2706 } | 2860 } |
| 2707 break; | 2861 break; |
| 2708 } | 2862 } |
| 2709 case FLOOR_L_D: { // Mips32r2 instruction. | 2863 case FLOOR_L_D: { // Mips32r2 instruction. |
| 2710 DCHECK(IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)); | 2864 DCHECK(IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)); |
| 2711 double rounded = std::floor(fs); | 2865 double rounded = std::floor(fs); |
| 2712 int64_t i64 = static_cast<int64_t>(rounded); | 2866 int64_t i64 = static_cast<int64_t>(rounded); |
| 2713 if (IsFp64Mode()) { | 2867 if (IsFp64Mode()) { |
| 2714 set_fpu_register(fd_reg(), i64); | 2868 set_fpu_register(fd_reg(), i64); |
| 2715 if (set_fcsr_round64_error(fs, rounded)) { | 2869 if (set_fcsr_round64_error(fs, rounded)) { |
| 2716 set_fpu_register_invalid_result64(fs, rounded); | 2870 set_fpu_register_invalid_result64(fs, rounded); |
| 2717 } | 2871 } |
| 2872 TraceRegWr(get_fpu_register(fd_reg())); | |
| 2718 } else { | 2873 } else { |
| 2719 UNSUPPORTED(); | 2874 UNSUPPORTED(); |
| 2720 } | 2875 } |
| 2721 break; | 2876 break; |
| 2722 } | 2877 } |
| 2723 case CEIL_L_D: { // Mips32r2 instruction. | 2878 case CEIL_L_D: { // Mips32r2 instruction. |
| 2724 DCHECK(IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)); | 2879 DCHECK(IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)); |
| 2725 double rounded = std::ceil(fs); | 2880 double rounded = std::ceil(fs); |
| 2726 int64_t i64 = static_cast<int64_t>(rounded); | 2881 int64_t i64 = static_cast<int64_t>(rounded); |
| 2727 if (IsFp64Mode()) { | 2882 if (IsFp64Mode()) { |
| 2728 set_fpu_register(fd_reg(), i64); | 2883 set_fpu_register(fd_reg(), i64); |
| 2729 if (set_fcsr_round64_error(fs, rounded)) { | 2884 if (set_fcsr_round64_error(fs, rounded)) { |
| 2730 set_fpu_register_invalid_result64(fs, rounded); | 2885 set_fpu_register_invalid_result64(fs, rounded); |
| 2731 } | 2886 } |
| 2887 TraceRegWr(get_fpu_register(fd_reg())); | |
| 2732 } else { | 2888 } else { |
| 2733 UNSUPPORTED(); | 2889 UNSUPPORTED(); |
| 2734 } | 2890 } |
| 2735 break; | 2891 break; |
| 2736 } | 2892 } |
| 2737 case CLASS_D: { // Mips32r6 instruction | 2893 case CLASS_D: { // Mips32r6 instruction |
| 2738 // Convert double input to uint64_t for easier bit manipulation | 2894 // Convert double input to uint64_t for easier bit manipulation |
| 2739 uint64_t classed = bit_cast<uint64_t>(fs); | 2895 uint64_t classed = bit_cast<uint64_t>(fs); |
| 2740 | 2896 |
| 2741 // Extracting sign, exponent and mantissa from the input double | 2897 // Extracting sign, exponent and mantissa from the input double |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2789 | 2945 |
| 2790 // Calculating result according to description of CLASS.D instruction | 2946 // Calculating result according to description of CLASS.D instruction |
| 2791 result = (posZero << 9) | (posSubnorm << 8) | (posNorm << 7) | | 2947 result = (posZero << 9) | (posSubnorm << 8) | (posNorm << 7) | |
| 2792 (posInf << 6) | (negZero << 5) | (negSubnorm << 4) | | 2948 (posInf << 6) | (negZero << 5) | (negSubnorm << 4) | |
| 2793 (negNorm << 3) | (negInf << 2) | (quietNan << 1) | signalingNan; | 2949 (negNorm << 3) | (negInf << 2) | (quietNan << 1) | signalingNan; |
| 2794 | 2950 |
| 2795 DCHECK(result != 0); | 2951 DCHECK(result != 0); |
| 2796 | 2952 |
| 2797 dResult = bit_cast<double>(result); | 2953 dResult = bit_cast<double>(result); |
| 2798 set_fpu_register_double(fd_reg(), dResult); | 2954 set_fpu_register_double(fd_reg(), dResult); |
| 2955 TraceRegWr(get_fpu_register(fd_reg()), DOUBLE); | |
| 2799 | 2956 |
| 2800 break; | 2957 break; |
| 2801 } | 2958 } |
| 2802 case C_F_D: { | 2959 case C_F_D: { |
| 2803 set_fcsr_bit(fcsr_cc, false); | 2960 set_fcsr_bit(fcsr_cc, false); |
| 2961 TraceRegWr(test_fcsr_bit(fcsr_cc)); | |
| 2804 break; | 2962 break; |
| 2805 } | 2963 } |
| 2806 default: | 2964 default: |
| 2807 UNREACHABLE(); | 2965 UNREACHABLE(); |
| 2808 } | 2966 } |
| 2809 } | 2967 } |
| 2810 | 2968 |
| 2811 | 2969 |
| 2812 void Simulator::DecodeTypeRegisterWRsType() { | 2970 void Simulator::DecodeTypeRegisterWRsType() { |
| 2813 float fs = get_fpu_register_float(fs_reg()); | 2971 float fs = get_fpu_register_float(fs_reg()); |
| 2814 float ft = get_fpu_register_float(ft_reg()); | 2972 float ft = get_fpu_register_float(ft_reg()); |
| 2815 int32_t alu_out = 0x12345678; | 2973 int32_t alu_out = 0x12345678; |
| 2816 switch (instr_.FunctionFieldRaw()) { | 2974 switch (instr_.FunctionFieldRaw()) { |
| 2817 case CVT_S_W: // Convert word to float (single). | 2975 case CVT_S_W: // Convert word to float (single). |
| 2818 alu_out = get_fpu_register_signed_word(fs_reg()); | 2976 alu_out = get_fpu_register_signed_word(fs_reg()); |
| 2819 set_fpu_register_float(fd_reg(), static_cast<float>(alu_out)); | 2977 set_fpu_register_float(fd_reg(), static_cast<float>(alu_out)); |
| 2978 TraceRegWr(get_fpu_register_word(fd_reg()), FLOAT); | |
| 2820 break; | 2979 break; |
| 2821 case CVT_D_W: // Convert word to double. | 2980 case CVT_D_W: // Convert word to double. |
| 2822 alu_out = get_fpu_register_signed_word(fs_reg()); | 2981 alu_out = get_fpu_register_signed_word(fs_reg()); |
| 2823 set_fpu_register_double(fd_reg(), static_cast<double>(alu_out)); | 2982 set_fpu_register_double(fd_reg(), static_cast<double>(alu_out)); |
| 2983 TraceRegWr(get_fpu_register(fd_reg()), DOUBLE); | |
| 2824 break; | 2984 break; |
| 2825 case CMP_AF: | 2985 case CMP_AF: |
| 2826 set_fpu_register_word(fd_reg(), 0); | 2986 set_fpu_register_word(fd_reg(), 0); |
| 2987 TraceRegWr(get_fpu_register_word(fd_reg())); | |
| 2827 break; | 2988 break; |
| 2828 case CMP_UN: | 2989 case CMP_UN: |
| 2829 if (std::isnan(fs) || std::isnan(ft)) { | 2990 if (std::isnan(fs) || std::isnan(ft)) { |
| 2830 set_fpu_register_word(fd_reg(), -1); | 2991 set_fpu_register_word(fd_reg(), -1); |
| 2831 } else { | 2992 } else { |
| 2832 set_fpu_register_word(fd_reg(), 0); | 2993 set_fpu_register_word(fd_reg(), 0); |
| 2833 } | 2994 } |
| 2995 TraceRegWr(get_fpu_register_word(fd_reg())); | |
| 2834 break; | 2996 break; |
| 2835 case CMP_EQ: | 2997 case CMP_EQ: |
| 2836 if (fs == ft) { | 2998 if (fs == ft) { |
| 2837 set_fpu_register_word(fd_reg(), -1); | 2999 set_fpu_register_word(fd_reg(), -1); |
| 2838 } else { | 3000 } else { |
| 2839 set_fpu_register_word(fd_reg(), 0); | 3001 set_fpu_register_word(fd_reg(), 0); |
| 2840 } | 3002 } |
| 3003 TraceRegWr(get_fpu_register_word(fd_reg())); | |
| 2841 break; | 3004 break; |
| 2842 case CMP_UEQ: | 3005 case CMP_UEQ: |
| 2843 if ((fs == ft) || (std::isnan(fs) || std::isnan(ft))) { | 3006 if ((fs == ft) || (std::isnan(fs) || std::isnan(ft))) { |
| 2844 set_fpu_register_word(fd_reg(), -1); | 3007 set_fpu_register_word(fd_reg(), -1); |
| 2845 } else { | 3008 } else { |
| 2846 set_fpu_register_word(fd_reg(), 0); | 3009 set_fpu_register_word(fd_reg(), 0); |
| 2847 } | 3010 } |
| 3011 TraceRegWr(get_fpu_register_word(fd_reg())); | |
| 2848 break; | 3012 break; |
| 2849 case CMP_LT: | 3013 case CMP_LT: |
| 2850 if (fs < ft) { | 3014 if (fs < ft) { |
| 2851 set_fpu_register_word(fd_reg(), -1); | 3015 set_fpu_register_word(fd_reg(), -1); |
| 2852 } else { | 3016 } else { |
| 2853 set_fpu_register_word(fd_reg(), 0); | 3017 set_fpu_register_word(fd_reg(), 0); |
| 2854 } | 3018 } |
| 3019 TraceRegWr(get_fpu_register_word(fd_reg())); | |
| 2855 break; | 3020 break; |
| 2856 case CMP_ULT: | 3021 case CMP_ULT: |
| 2857 if ((fs < ft) || (std::isnan(fs) || std::isnan(ft))) { | 3022 if ((fs < ft) || (std::isnan(fs) || std::isnan(ft))) { |
| 2858 set_fpu_register_word(fd_reg(), -1); | 3023 set_fpu_register_word(fd_reg(), -1); |
| 2859 } else { | 3024 } else { |
| 2860 set_fpu_register_word(fd_reg(), 0); | 3025 set_fpu_register_word(fd_reg(), 0); |
| 2861 } | 3026 } |
| 3027 TraceRegWr(get_fpu_register_word(fd_reg())); | |
| 2862 break; | 3028 break; |
| 2863 case CMP_LE: | 3029 case CMP_LE: |
| 2864 if (fs <= ft) { | 3030 if (fs <= ft) { |
| 2865 set_fpu_register_word(fd_reg(), -1); | 3031 set_fpu_register_word(fd_reg(), -1); |
| 2866 } else { | 3032 } else { |
| 2867 set_fpu_register_word(fd_reg(), 0); | 3033 set_fpu_register_word(fd_reg(), 0); |
| 2868 } | 3034 } |
| 3035 TraceRegWr(get_fpu_register_word(fd_reg())); | |
| 2869 break; | 3036 break; |
| 2870 case CMP_ULE: | 3037 case CMP_ULE: |
| 2871 if ((fs <= ft) || (std::isnan(fs) || std::isnan(ft))) { | 3038 if ((fs <= ft) || (std::isnan(fs) || std::isnan(ft))) { |
| 2872 set_fpu_register_word(fd_reg(), -1); | 3039 set_fpu_register_word(fd_reg(), -1); |
| 2873 } else { | 3040 } else { |
| 2874 set_fpu_register_word(fd_reg(), 0); | 3041 set_fpu_register_word(fd_reg(), 0); |
| 2875 } | 3042 } |
| 3043 TraceRegWr(get_fpu_register_word(fd_reg())); | |
| 2876 break; | 3044 break; |
| 2877 case CMP_OR: | 3045 case CMP_OR: |
| 2878 if (!std::isnan(fs) && !std::isnan(ft)) { | 3046 if (!std::isnan(fs) && !std::isnan(ft)) { |
| 2879 set_fpu_register_word(fd_reg(), -1); | 3047 set_fpu_register_word(fd_reg(), -1); |
| 2880 } else { | 3048 } else { |
| 2881 set_fpu_register_word(fd_reg(), 0); | 3049 set_fpu_register_word(fd_reg(), 0); |
| 2882 } | 3050 } |
| 3051 TraceRegWr(get_fpu_register_word(fd_reg())); | |
| 2883 break; | 3052 break; |
| 2884 case CMP_UNE: | 3053 case CMP_UNE: |
| 2885 if ((fs != ft) || (std::isnan(fs) || std::isnan(ft))) { | 3054 if ((fs != ft) || (std::isnan(fs) || std::isnan(ft))) { |
| 2886 set_fpu_register_word(fd_reg(), -1); | 3055 set_fpu_register_word(fd_reg(), -1); |
| 2887 } else { | 3056 } else { |
| 2888 set_fpu_register_word(fd_reg(), 0); | 3057 set_fpu_register_word(fd_reg(), 0); |
| 2889 } | 3058 } |
| 3059 TraceRegWr(get_fpu_register_word(fd_reg())); | |
| 2890 break; | 3060 break; |
| 2891 case CMP_NE: | 3061 case CMP_NE: |
| 2892 if (fs != ft) { | 3062 if (fs != ft) { |
| 2893 set_fpu_register_word(fd_reg(), -1); | 3063 set_fpu_register_word(fd_reg(), -1); |
| 2894 } else { | 3064 } else { |
| 2895 set_fpu_register_word(fd_reg(), 0); | 3065 set_fpu_register_word(fd_reg(), 0); |
| 2896 } | 3066 } |
| 3067 TraceRegWr(get_fpu_register_word(fd_reg())); | |
| 2897 break; | 3068 break; |
| 2898 default: | 3069 default: |
| 2899 UNREACHABLE(); | 3070 UNREACHABLE(); |
| 2900 } | 3071 } |
| 2901 } | 3072 } |
| 2902 | 3073 |
| 2903 | 3074 |
| 2904 void Simulator::DecodeTypeRegisterSRsType() { | 3075 void Simulator::DecodeTypeRegisterSRsType() { |
| 2905 float fs, ft, fd; | 3076 float fs, ft, fd; |
| 2906 fs = get_fpu_register_float(fs_reg()); | 3077 fs = get_fpu_register_float(fs_reg()); |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2941 result = upper; | 3112 result = upper; |
| 2942 break; | 3113 break; |
| 2943 case kRoundToMinusInf: | 3114 case kRoundToMinusInf: |
| 2944 result = lower; | 3115 result = lower; |
| 2945 break; | 3116 break; |
| 2946 } | 3117 } |
| 2947 set_fpu_register_float(fd_reg(), result); | 3118 set_fpu_register_float(fd_reg(), result); |
| 2948 if (result != fs) { | 3119 if (result != fs) { |
| 2949 set_fcsr_bit(kFCSRInexactFlagBit, true); | 3120 set_fcsr_bit(kFCSRInexactFlagBit, true); |
| 2950 } | 3121 } |
| 3122 TraceRegWr(get_fpu_register_word(fd_reg()), FLOAT); | |
| 2951 break; | 3123 break; |
| 2952 } | 3124 } |
| 2953 case ADD_S: | 3125 case ADD_S: |
| 2954 set_fpu_register_float( | 3126 set_fpu_register_float( |
| 2955 fd_reg(), | 3127 fd_reg(), |
| 2956 FPUCanonalizeOperation([](float lhs, float rhs) { return lhs + rhs; }, | 3128 FPUCanonalizeOperation([](float lhs, float rhs) { return lhs + rhs; }, |
| 2957 fs, ft)); | 3129 fs, ft)); |
| 3130 TraceRegWr(get_fpu_register_word(fd_reg()), FLOAT); | |
| 2958 break; | 3131 break; |
| 2959 case SUB_S: | 3132 case SUB_S: |
| 2960 set_fpu_register_float( | 3133 set_fpu_register_float( |
| 2961 fd_reg(), | 3134 fd_reg(), |
| 2962 FPUCanonalizeOperation([](float lhs, float rhs) { return lhs - rhs; }, | 3135 FPUCanonalizeOperation([](float lhs, float rhs) { return lhs - rhs; }, |
| 2963 fs, ft)); | 3136 fs, ft)); |
| 3137 TraceRegWr(get_fpu_register_word(fd_reg()), FLOAT); | |
| 2964 break; | 3138 break; |
| 2965 case MADDF_S: | 3139 case MADDF_S: |
| 2966 DCHECK(IsMipsArchVariant(kMips32r6)); | 3140 DCHECK(IsMipsArchVariant(kMips32r6)); |
| 2967 set_fpu_register_float(fd_reg(), std::fma(fs, ft, fd)); | 3141 set_fpu_register_float(fd_reg(), std::fma(fs, ft, fd)); |
| 3142 TraceRegWr(get_fpu_register_word(fd_reg()), FLOAT); | |
| 2968 break; | 3143 break; |
| 2969 case MSUBF_S: | 3144 case MSUBF_S: |
| 2970 DCHECK(IsMipsArchVariant(kMips32r6)); | 3145 DCHECK(IsMipsArchVariant(kMips32r6)); |
| 2971 set_fpu_register_float(fd_reg(), std::fma(-fs, ft, fd)); | 3146 set_fpu_register_float(fd_reg(), std::fma(-fs, ft, fd)); |
| 3147 TraceRegWr(get_fpu_register_word(fd_reg()), FLOAT); | |
| 2972 break; | 3148 break; |
| 2973 case MUL_S: | 3149 case MUL_S: |
| 2974 set_fpu_register_float( | 3150 set_fpu_register_float( |
| 2975 fd_reg(), | 3151 fd_reg(), |
| 2976 FPUCanonalizeOperation([](float lhs, float rhs) { return lhs * rhs; }, | 3152 FPUCanonalizeOperation([](float lhs, float rhs) { return lhs * rhs; }, |
| 2977 fs, ft)); | 3153 fs, ft)); |
| 3154 TraceRegWr(get_fpu_register_word(fd_reg()), FLOAT); | |
| 2978 break; | 3155 break; |
| 2979 case DIV_S: | 3156 case DIV_S: |
| 2980 set_fpu_register_float( | 3157 set_fpu_register_float( |
| 2981 fd_reg(), | 3158 fd_reg(), |
| 2982 FPUCanonalizeOperation([](float lhs, float rhs) { return lhs / rhs; }, | 3159 FPUCanonalizeOperation([](float lhs, float rhs) { return lhs / rhs; }, |
| 2983 fs, ft)); | 3160 fs, ft)); |
| 3161 TraceRegWr(get_fpu_register_word(fd_reg()), FLOAT); | |
| 2984 break; | 3162 break; |
| 2985 case ABS_S: | 3163 case ABS_S: |
| 2986 set_fpu_register_float( | 3164 set_fpu_register_float( |
| 2987 fd_reg(), | 3165 fd_reg(), |
| 2988 FPUCanonalizeOperation([](float fs) { return FPAbs(fs); }, fs)); | 3166 FPUCanonalizeOperation([](float fs) { return FPAbs(fs); }, fs)); |
| 3167 TraceRegWr(get_fpu_register_word(fd_reg()), FLOAT); | |
| 2989 break; | 3168 break; |
| 2990 case MOV_S: | 3169 case MOV_S: |
| 2991 set_fpu_register_float(fd_reg(), fs); | 3170 set_fpu_register_float(fd_reg(), fs); |
| 3171 TraceRegWr(get_fpu_register_word(fd_reg()), FLOAT); | |
| 2992 break; | 3172 break; |
| 2993 case NEG_S: | 3173 case NEG_S: |
| 2994 set_fpu_register_float( | 3174 set_fpu_register_float( |
| 2995 fd_reg(), FPUCanonalizeOperation([](float src) { return -src; }, | 3175 fd_reg(), FPUCanonalizeOperation([](float src) { return -src; }, |
| 2996 KeepSign::yes, fs)); | 3176 KeepSign::yes, fs)); |
| 3177 TraceRegWr(get_fpu_register_word(fd_reg()), FLOAT); | |
| 2997 break; | 3178 break; |
| 2998 case SQRT_S: | 3179 case SQRT_S: |
| 2999 set_fpu_register_float( | 3180 set_fpu_register_float( |
| 3000 fd_reg(), | 3181 fd_reg(), |
| 3001 FPUCanonalizeOperation([](float src) { return std::sqrt(src); }, fs)); | 3182 FPUCanonalizeOperation([](float src) { return std::sqrt(src); }, fs)); |
| 3183 TraceRegWr(get_fpu_register_word(fd_reg()), FLOAT); | |
| 3002 break; | 3184 break; |
| 3003 case RSQRT_S: | 3185 case RSQRT_S: |
| 3004 set_fpu_register_float( | 3186 set_fpu_register_float( |
| 3005 fd_reg(), FPUCanonalizeOperation( | 3187 fd_reg(), FPUCanonalizeOperation( |
| 3006 [](float src) { return 1.0 / std::sqrt(src); }, fs)); | 3188 [](float src) { return 1.0 / std::sqrt(src); }, fs)); |
| 3189 TraceRegWr(get_fpu_register_word(fd_reg()), FLOAT); | |
| 3007 break; | 3190 break; |
| 3008 case RECIP_S: | 3191 case RECIP_S: |
| 3009 set_fpu_register_float( | 3192 set_fpu_register_float( |
| 3010 fd_reg(), | 3193 fd_reg(), |
| 3011 FPUCanonalizeOperation([](float src) { return 1.0 / src; }, fs)); | 3194 FPUCanonalizeOperation([](float src) { return 1.0 / src; }, fs)); |
| 3195 TraceRegWr(get_fpu_register_word(fd_reg()), FLOAT); | |
| 3012 break; | 3196 break; |
| 3013 case C_F_D: | 3197 case C_F_D: |
| 3014 set_fcsr_bit(fcsr_cc, false); | 3198 set_fcsr_bit(fcsr_cc, false); |
| 3199 TraceRegWr(test_fcsr_bit(fcsr_cc)); | |
| 3015 break; | 3200 break; |
| 3016 case C_UN_D: | 3201 case C_UN_D: |
| 3017 set_fcsr_bit(fcsr_cc, std::isnan(fs) || std::isnan(ft)); | 3202 set_fcsr_bit(fcsr_cc, std::isnan(fs) || std::isnan(ft)); |
| 3203 TraceRegWr(test_fcsr_bit(fcsr_cc)); | |
| 3018 break; | 3204 break; |
| 3019 case C_EQ_D: | 3205 case C_EQ_D: |
| 3020 set_fcsr_bit(fcsr_cc, (fs == ft)); | 3206 set_fcsr_bit(fcsr_cc, (fs == ft)); |
| 3207 TraceRegWr(test_fcsr_bit(fcsr_cc)); | |
| 3021 break; | 3208 break; |
| 3022 case C_UEQ_D: | 3209 case C_UEQ_D: |
| 3023 set_fcsr_bit(fcsr_cc, (fs == ft) || (std::isnan(fs) || std::isnan(ft))); | 3210 set_fcsr_bit(fcsr_cc, (fs == ft) || (std::isnan(fs) || std::isnan(ft))); |
| 3211 TraceRegWr(test_fcsr_bit(fcsr_cc)); | |
| 3024 break; | 3212 break; |
| 3025 case C_OLT_D: | 3213 case C_OLT_D: |
| 3026 set_fcsr_bit(fcsr_cc, (fs < ft)); | 3214 set_fcsr_bit(fcsr_cc, (fs < ft)); |
| 3215 TraceRegWr(test_fcsr_bit(fcsr_cc)); | |
| 3027 break; | 3216 break; |
| 3028 case C_ULT_D: | 3217 case C_ULT_D: |
| 3029 set_fcsr_bit(fcsr_cc, (fs < ft) || (std::isnan(fs) || std::isnan(ft))); | 3218 set_fcsr_bit(fcsr_cc, (fs < ft) || (std::isnan(fs) || std::isnan(ft))); |
| 3219 TraceRegWr(test_fcsr_bit(fcsr_cc)); | |
| 3030 break; | 3220 break; |
| 3031 case C_OLE_D: | 3221 case C_OLE_D: |
| 3032 set_fcsr_bit(fcsr_cc, (fs <= ft)); | 3222 set_fcsr_bit(fcsr_cc, (fs <= ft)); |
| 3223 TraceRegWr(test_fcsr_bit(fcsr_cc)); | |
| 3033 break; | 3224 break; |
| 3034 case C_ULE_D: | 3225 case C_ULE_D: |
| 3035 set_fcsr_bit(fcsr_cc, (fs <= ft) || (std::isnan(fs) || std::isnan(ft))); | 3226 set_fcsr_bit(fcsr_cc, (fs <= ft) || (std::isnan(fs) || std::isnan(ft))); |
| 3227 TraceRegWr(test_fcsr_bit(fcsr_cc)); | |
| 3036 break; | 3228 break; |
| 3037 case CVT_D_S: | 3229 case CVT_D_S: |
| 3038 set_fpu_register_double(fd_reg(), static_cast<double>(fs)); | 3230 set_fpu_register_double(fd_reg(), static_cast<double>(fs)); |
| 3231 TraceRegWr(get_fpu_register(fd_reg()), DOUBLE); | |
| 3039 break; | 3232 break; |
| 3040 case SEL: | 3233 case SEL: |
| 3041 DCHECK(IsMipsArchVariant(kMips32r6)); | 3234 DCHECK(IsMipsArchVariant(kMips32r6)); |
| 3042 set_fpu_register_float(fd_reg(), (fd_int & 0x1) == 0 ? fs : ft); | 3235 set_fpu_register_float(fd_reg(), (fd_int & 0x1) == 0 ? fs : ft); |
| 3236 TraceRegWr(get_fpu_register_word(fd_reg()), FLOAT); | |
| 3043 break; | 3237 break; |
| 3044 case CLASS_S: { // Mips32r6 instruction | 3238 case CLASS_S: { // Mips32r6 instruction |
| 3045 // Convert float input to uint32_t for easier bit manipulation | 3239 // Convert float input to uint32_t for easier bit manipulation |
| 3046 float fs = get_fpu_register_float(fs_reg()); | 3240 float fs = get_fpu_register_float(fs_reg()); |
| 3047 uint32_t classed = bit_cast<uint32_t>(fs); | 3241 uint32_t classed = bit_cast<uint32_t>(fs); |
| 3048 | 3242 |
| 3049 // Extracting sign, exponent and mantissa from the input float | 3243 // Extracting sign, exponent and mantissa from the input float |
| 3050 uint32_t sign = (classed >> 31) & 1; | 3244 uint32_t sign = (classed >> 31) & 1; |
| 3051 uint32_t exponent = (classed >> 23) & 0x000000ff; | 3245 uint32_t exponent = (classed >> 23) & 0x000000ff; |
| 3052 uint32_t mantissa = classed & 0x007fffff; | 3246 uint32_t mantissa = classed & 0x007fffff; |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3097 | 3291 |
| 3098 // Calculating result according to description of CLASS.S instruction | 3292 // Calculating result according to description of CLASS.S instruction |
| 3099 result = (posZero << 9) | (posSubnorm << 8) | (posNorm << 7) | | 3293 result = (posZero << 9) | (posSubnorm << 8) | (posNorm << 7) | |
| 3100 (posInf << 6) | (negZero << 5) | (negSubnorm << 4) | | 3294 (posInf << 6) | (negZero << 5) | (negSubnorm << 4) | |
| 3101 (negNorm << 3) | (negInf << 2) | (quietNan << 1) | signalingNan; | 3295 (negNorm << 3) | (negInf << 2) | (quietNan << 1) | signalingNan; |
| 3102 | 3296 |
| 3103 DCHECK(result != 0); | 3297 DCHECK(result != 0); |
| 3104 | 3298 |
| 3105 fResult = bit_cast<float>(result); | 3299 fResult = bit_cast<float>(result); |
| 3106 set_fpu_register_float(fd_reg(), fResult); | 3300 set_fpu_register_float(fd_reg(), fResult); |
| 3301 TraceRegWr(get_fpu_register_word(fd_reg()), FLOAT); | |
| 3107 | 3302 |
| 3108 break; | 3303 break; |
| 3109 } | 3304 } |
| 3110 case SELEQZ_C: | 3305 case SELEQZ_C: |
| 3111 DCHECK(IsMipsArchVariant(kMips32r6)); | 3306 DCHECK(IsMipsArchVariant(kMips32r6)); |
| 3112 set_fpu_register_float(fd_reg(), (ft_int & 0x1) == 0 | 3307 set_fpu_register_float(fd_reg(), (ft_int & 0x1) == 0 |
| 3113 ? get_fpu_register_float(fs_reg()) | 3308 ? get_fpu_register_float(fs_reg()) |
| 3114 : 0.0); | 3309 : 0.0); |
| 3310 TraceRegWr(get_fpu_register_word(fd_reg()), FLOAT); | |
| 3115 break; | 3311 break; |
| 3116 case SELNEZ_C: | 3312 case SELNEZ_C: |
| 3117 DCHECK(IsMipsArchVariant(kMips32r6)); | 3313 DCHECK(IsMipsArchVariant(kMips32r6)); |
| 3118 set_fpu_register_float(fd_reg(), (ft_int & 0x1) != 0 | 3314 set_fpu_register_float(fd_reg(), (ft_int & 0x1) != 0 |
| 3119 ? get_fpu_register_float(fs_reg()) | 3315 ? get_fpu_register_float(fs_reg()) |
| 3120 : 0.0); | 3316 : 0.0); |
| 3317 TraceRegWr(get_fpu_register_word(fd_reg()), FLOAT); | |
| 3121 break; | 3318 break; |
| 3122 case MOVZ_C: { | 3319 case MOVZ_C: { |
| 3123 DCHECK(IsMipsArchVariant(kMips32r2)); | 3320 DCHECK(IsMipsArchVariant(kMips32r2)); |
| 3124 if (rt() == 0) { | 3321 if (rt() == 0) { |
| 3125 set_fpu_register_float(fd_reg(), fs); | 3322 set_fpu_register_float(fd_reg(), fs); |
| 3126 } | 3323 } |
| 3324 TraceRegWr(get_fpu_register_word(fd_reg()), FLOAT); | |
| 3127 break; | 3325 break; |
| 3128 } | 3326 } |
| 3129 case MOVN_C: { | 3327 case MOVN_C: { |
| 3130 DCHECK(IsMipsArchVariant(kMips32r2)); | 3328 DCHECK(IsMipsArchVariant(kMips32r2)); |
| 3131 if (rt() != 0) { | 3329 if (rt() != 0) { |
| 3132 set_fpu_register_float(fd_reg(), fs); | 3330 set_fpu_register_float(fd_reg(), fs); |
| 3133 } | 3331 } |
| 3332 TraceRegWr(get_fpu_register_word(fd_reg()), FLOAT); | |
| 3134 break; | 3333 break; |
| 3135 } | 3334 } |
| 3136 case MOVF: { | 3335 case MOVF: { |
| 3137 // Same function field for MOVT.D and MOVF.D | 3336 // Same function field for MOVT.D and MOVF.D |
| 3138 uint32_t ft_cc = (ft_reg() >> 2) & 0x7; | 3337 uint32_t ft_cc = (ft_reg() >> 2) & 0x7; |
| 3139 ft_cc = get_fcsr_condition_bit(ft_cc); | 3338 ft_cc = get_fcsr_condition_bit(ft_cc); |
| 3140 | 3339 |
| 3141 if (instr_.Bit(16)) { // Read Tf bit. | 3340 if (instr_.Bit(16)) { // Read Tf bit. |
| 3142 // MOVT.D | 3341 // MOVT.D |
| 3143 if (test_fcsr_bit(ft_cc)) set_fpu_register_float(fd_reg(), fs); | 3342 if (test_fcsr_bit(ft_cc)) set_fpu_register_float(fd_reg(), fs); |
| 3144 } else { | 3343 } else { |
| 3145 // MOVF.D | 3344 // MOVF.D |
| 3146 if (!test_fcsr_bit(ft_cc)) set_fpu_register_float(fd_reg(), fs); | 3345 if (!test_fcsr_bit(ft_cc)) set_fpu_register_float(fd_reg(), fs); |
| 3147 } | 3346 } |
| 3347 TraceRegWr(get_fpu_register_word(fd_reg()), FLOAT); | |
| 3148 break; | 3348 break; |
| 3149 } | 3349 } |
| 3150 case TRUNC_W_S: { // Truncate single to word (round towards 0). | 3350 case TRUNC_W_S: { // Truncate single to word (round towards 0). |
| 3151 float rounded = trunc(fs); | 3351 float rounded = trunc(fs); |
| 3152 int32_t result = static_cast<int32_t>(rounded); | 3352 int32_t result = static_cast<int32_t>(rounded); |
| 3153 set_fpu_register_word(fd_reg(), result); | 3353 set_fpu_register_word(fd_reg(), result); |
| 3154 if (set_fcsr_round_error(fs, rounded)) { | 3354 if (set_fcsr_round_error(fs, rounded)) { |
| 3155 set_fpu_register_word_invalid_result(fs, rounded); | 3355 set_fpu_register_word_invalid_result(fs, rounded); |
| 3156 } | 3356 } |
| 3357 TraceRegWr(get_fpu_register_word(fd_reg())); | |
| 3157 } break; | 3358 } break; |
| 3158 case TRUNC_L_S: { // Mips32r2 instruction. | 3359 case TRUNC_L_S: { // Mips32r2 instruction. |
| 3159 DCHECK(IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)); | 3360 DCHECK(IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)); |
| 3160 float rounded = trunc(fs); | 3361 float rounded = trunc(fs); |
| 3161 int64_t i64 = static_cast<int64_t>(rounded); | 3362 int64_t i64 = static_cast<int64_t>(rounded); |
| 3162 if (IsFp64Mode()) { | 3363 if (IsFp64Mode()) { |
| 3163 set_fpu_register(fd_reg(), i64); | 3364 set_fpu_register(fd_reg(), i64); |
| 3164 if (set_fcsr_round64_error(fs, rounded)) { | 3365 if (set_fcsr_round64_error(fs, rounded)) { |
| 3165 set_fpu_register_invalid_result64(fs, rounded); | 3366 set_fpu_register_invalid_result64(fs, rounded); |
| 3166 } | 3367 } |
| 3368 TraceRegWr(get_fpu_register(fd_reg())); | |
| 3167 } else { | 3369 } else { |
| 3168 UNSUPPORTED(); | 3370 UNSUPPORTED(); |
| 3169 } | 3371 } |
| 3170 break; | 3372 break; |
| 3171 } | 3373 } |
| 3172 case FLOOR_W_S: // Round double to word towards negative infinity. | 3374 case FLOOR_W_S: // Round double to word towards negative infinity. |
| 3173 { | 3375 { |
| 3174 float rounded = std::floor(fs); | 3376 float rounded = std::floor(fs); |
| 3175 int32_t result = static_cast<int32_t>(rounded); | 3377 int32_t result = static_cast<int32_t>(rounded); |
| 3176 set_fpu_register_word(fd_reg(), result); | 3378 set_fpu_register_word(fd_reg(), result); |
| 3177 if (set_fcsr_round_error(fs, rounded)) { | 3379 if (set_fcsr_round_error(fs, rounded)) { |
| 3178 set_fpu_register_word_invalid_result(fs, rounded); | 3380 set_fpu_register_word_invalid_result(fs, rounded); |
| 3179 } | 3381 } |
| 3382 TraceRegWr(get_fpu_register_word(fd_reg())); | |
| 3180 } break; | 3383 } break; |
| 3181 case FLOOR_L_S: { // Mips32r2 instruction. | 3384 case FLOOR_L_S: { // Mips32r2 instruction. |
| 3182 DCHECK(IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)); | 3385 DCHECK(IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)); |
| 3183 float rounded = std::floor(fs); | 3386 float rounded = std::floor(fs); |
| 3184 int64_t i64 = static_cast<int64_t>(rounded); | 3387 int64_t i64 = static_cast<int64_t>(rounded); |
| 3185 if (IsFp64Mode()) { | 3388 if (IsFp64Mode()) { |
| 3186 set_fpu_register(fd_reg(), i64); | 3389 set_fpu_register(fd_reg(), i64); |
| 3187 if (set_fcsr_round64_error(fs, rounded)) { | 3390 if (set_fcsr_round64_error(fs, rounded)) { |
| 3188 set_fpu_register_invalid_result64(fs, rounded); | 3391 set_fpu_register_invalid_result64(fs, rounded); |
| 3189 } | 3392 } |
| 3393 TraceRegWr(get_fpu_register(fd_reg())); | |
| 3190 } else { | 3394 } else { |
| 3191 UNSUPPORTED(); | 3395 UNSUPPORTED(); |
| 3192 } | 3396 } |
| 3193 break; | 3397 break; |
| 3194 } | 3398 } |
| 3195 case ROUND_W_S: { | 3399 case ROUND_W_S: { |
| 3196 float rounded = std::floor(fs + 0.5); | 3400 float rounded = std::floor(fs + 0.5); |
| 3197 int32_t result = static_cast<int32_t>(rounded); | 3401 int32_t result = static_cast<int32_t>(rounded); |
| 3198 if ((result & 1) != 0 && result - fs == 0.5) { | 3402 if ((result & 1) != 0 && result - fs == 0.5) { |
| 3199 // If the number is halfway between two integers, | 3403 // If the number is halfway between two integers, |
| 3200 // round to the even one. | 3404 // round to the even one. |
| 3201 result--; | 3405 result--; |
| 3202 } | 3406 } |
| 3203 set_fpu_register_word(fd_reg(), result); | 3407 set_fpu_register_word(fd_reg(), result); |
| 3204 if (set_fcsr_round_error(fs, rounded)) { | 3408 if (set_fcsr_round_error(fs, rounded)) { |
| 3205 set_fpu_register_word_invalid_result(fs, rounded); | 3409 set_fpu_register_word_invalid_result(fs, rounded); |
| 3206 } | 3410 } |
| 3411 TraceRegWr(get_fpu_register_word(fd_reg())); | |
| 3207 break; | 3412 break; |
| 3208 } | 3413 } |
| 3209 case ROUND_L_S: { // Mips32r2 instruction. | 3414 case ROUND_L_S: { // Mips32r2 instruction. |
| 3210 DCHECK(IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)); | 3415 DCHECK(IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)); |
| 3211 float rounded = std::floor(fs + 0.5); | 3416 float rounded = std::floor(fs + 0.5); |
| 3212 int64_t result = static_cast<int64_t>(rounded); | 3417 int64_t result = static_cast<int64_t>(rounded); |
| 3213 if ((result & 1) != 0 && result - fs == 0.5) { | 3418 if ((result & 1) != 0 && result - fs == 0.5) { |
| 3214 // If the number is halfway between two integers, | 3419 // If the number is halfway between two integers, |
| 3215 // round to the even one. | 3420 // round to the even one. |
| 3216 result--; | 3421 result--; |
| 3217 } | 3422 } |
| 3218 int64_t i64 = static_cast<int64_t>(result); | 3423 int64_t i64 = static_cast<int64_t>(result); |
| 3219 if (IsFp64Mode()) { | 3424 if (IsFp64Mode()) { |
| 3220 set_fpu_register(fd_reg(), i64); | 3425 set_fpu_register(fd_reg(), i64); |
| 3221 if (set_fcsr_round64_error(fs, rounded)) { | 3426 if (set_fcsr_round64_error(fs, rounded)) { |
| 3222 set_fpu_register_invalid_result64(fs, rounded); | 3427 set_fpu_register_invalid_result64(fs, rounded); |
| 3223 } | 3428 } |
| 3429 TraceRegWr(get_fpu_register(fd_reg())); | |
| 3224 } else { | 3430 } else { |
| 3225 UNSUPPORTED(); | 3431 UNSUPPORTED(); |
| 3226 } | 3432 } |
| 3227 break; | 3433 break; |
| 3228 } | 3434 } |
| 3229 case CEIL_W_S: // Round double to word towards positive infinity. | 3435 case CEIL_W_S: // Round double to word towards positive infinity. |
| 3230 { | 3436 { |
| 3231 float rounded = std::ceil(fs); | 3437 float rounded = std::ceil(fs); |
| 3232 int32_t result = static_cast<int32_t>(rounded); | 3438 int32_t result = static_cast<int32_t>(rounded); |
| 3233 set_fpu_register_word(fd_reg(), result); | 3439 set_fpu_register_word(fd_reg(), result); |
| 3234 if (set_fcsr_round_error(fs, rounded)) { | 3440 if (set_fcsr_round_error(fs, rounded)) { |
| 3235 set_fpu_register_word_invalid_result(fs, rounded); | 3441 set_fpu_register_word_invalid_result(fs, rounded); |
| 3236 } | 3442 } |
| 3443 TraceRegWr(get_fpu_register_word(fd_reg())); | |
| 3237 } break; | 3444 } break; |
| 3238 case CEIL_L_S: { // Mips32r2 instruction. | 3445 case CEIL_L_S: { // Mips32r2 instruction. |
| 3239 DCHECK(IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)); | 3446 DCHECK(IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)); |
| 3240 float rounded = std::ceil(fs); | 3447 float rounded = std::ceil(fs); |
| 3241 int64_t i64 = static_cast<int64_t>(rounded); | 3448 int64_t i64 = static_cast<int64_t>(rounded); |
| 3242 if (IsFp64Mode()) { | 3449 if (IsFp64Mode()) { |
| 3243 set_fpu_register(fd_reg(), i64); | 3450 set_fpu_register(fd_reg(), i64); |
| 3244 if (set_fcsr_round64_error(fs, rounded)) { | 3451 if (set_fcsr_round64_error(fs, rounded)) { |
| 3245 set_fpu_register_invalid_result64(fs, rounded); | 3452 set_fpu_register_invalid_result64(fs, rounded); |
| 3246 } | 3453 } |
| 3454 TraceRegWr(get_fpu_register(fd_reg())); | |
| 3247 } else { | 3455 } else { |
| 3248 UNSUPPORTED(); | 3456 UNSUPPORTED(); |
| 3249 } | 3457 } |
| 3250 break; | 3458 break; |
| 3251 } | 3459 } |
| 3252 case MIN: | 3460 case MIN: |
| 3253 DCHECK(IsMipsArchVariant(kMips32r6)); | 3461 DCHECK(IsMipsArchVariant(kMips32r6)); |
| 3254 set_fpu_register_float(fd_reg(), FPUMin(ft, fs)); | 3462 set_fpu_register_float(fd_reg(), FPUMin(ft, fs)); |
| 3463 TraceRegWr(get_fpu_register_word(fd_reg()), FLOAT); | |
| 3255 break; | 3464 break; |
| 3256 case MAX: | 3465 case MAX: |
| 3257 DCHECK(IsMipsArchVariant(kMips32r6)); | 3466 DCHECK(IsMipsArchVariant(kMips32r6)); |
| 3258 set_fpu_register_float(fd_reg(), FPUMax(ft, fs)); | 3467 set_fpu_register_float(fd_reg(), FPUMax(ft, fs)); |
| 3468 TraceRegWr(get_fpu_register_word(fd_reg()), FLOAT); | |
| 3259 break; | 3469 break; |
| 3260 case MINA: | 3470 case MINA: |
| 3261 DCHECK(IsMipsArchVariant(kMips32r6)); | 3471 DCHECK(IsMipsArchVariant(kMips32r6)); |
| 3262 set_fpu_register_float(fd_reg(), FPUMinA(ft, fs)); | 3472 set_fpu_register_float(fd_reg(), FPUMinA(ft, fs)); |
| 3473 TraceRegWr(get_fpu_register_word(fd_reg()), FLOAT); | |
| 3263 break; | 3474 break; |
| 3264 case MAXA: | 3475 case MAXA: |
| 3265 DCHECK(IsMipsArchVariant(kMips32r6)); | 3476 DCHECK(IsMipsArchVariant(kMips32r6)); |
| 3266 set_fpu_register_float(fd_reg(), FPUMaxA(ft, fs)); | 3477 set_fpu_register_float(fd_reg(), FPUMaxA(ft, fs)); |
| 3478 TraceRegWr(get_fpu_register_word(fd_reg()), FLOAT); | |
| 3267 break; | 3479 break; |
| 3268 case CVT_L_S: { | 3480 case CVT_L_S: { |
| 3269 if (IsFp64Mode()) { | 3481 if (IsFp64Mode()) { |
| 3270 int64_t result; | 3482 int64_t result; |
| 3271 float rounded; | 3483 float rounded; |
| 3272 round64_according_to_fcsr(fs, rounded, result, fs); | 3484 round64_according_to_fcsr(fs, rounded, result, fs); |
| 3273 set_fpu_register(fd_reg(), result); | 3485 set_fpu_register(fd_reg(), result); |
| 3274 if (set_fcsr_round64_error(fs, rounded)) { | 3486 if (set_fcsr_round64_error(fs, rounded)) { |
| 3275 set_fpu_register_invalid_result64(fs, rounded); | 3487 set_fpu_register_invalid_result64(fs, rounded); |
| 3276 } | 3488 } |
| 3489 TraceRegWr(get_fpu_register(fd_reg())); | |
| 3277 } else { | 3490 } else { |
| 3278 UNSUPPORTED(); | 3491 UNSUPPORTED(); |
| 3279 } | 3492 } |
| 3280 break; | 3493 break; |
| 3281 } | 3494 } |
| 3282 case CVT_W_S: { | 3495 case CVT_W_S: { |
| 3283 float rounded; | 3496 float rounded; |
| 3284 int32_t result; | 3497 int32_t result; |
| 3285 round_according_to_fcsr(fs, rounded, result, fs); | 3498 round_according_to_fcsr(fs, rounded, result, fs); |
| 3286 set_fpu_register_word(fd_reg(), result); | 3499 set_fpu_register_word(fd_reg(), result); |
| 3287 if (set_fcsr_round_error(fs, rounded)) { | 3500 if (set_fcsr_round_error(fs, rounded)) { |
| 3288 set_fpu_register_word_invalid_result(fs, rounded); | 3501 set_fpu_register_word_invalid_result(fs, rounded); |
| 3289 } | 3502 } |
| 3503 TraceRegWr(get_fpu_register_word(fd_reg())); | |
| 3290 break; | 3504 break; |
| 3291 } | 3505 } |
| 3292 default: | 3506 default: |
| 3293 // CVT_W_S CVT_L_S ROUND_W_S ROUND_L_S FLOOR_W_S FLOOR_L_S | 3507 // 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. | 3508 // CEIL_W_S CEIL_L_S CVT_PS_S are unimplemented. |
| 3295 UNREACHABLE(); | 3509 UNREACHABLE(); |
| 3296 } | 3510 } |
| 3297 } | 3511 } |
| 3298 | 3512 |
| 3299 | 3513 |
| 3300 void Simulator::DecodeTypeRegisterLRsType() { | 3514 void Simulator::DecodeTypeRegisterLRsType() { |
| 3301 double fs = get_fpu_register_double(fs_reg()); | 3515 double fs = get_fpu_register_double(fs_reg()); |
| 3302 double ft = get_fpu_register_double(ft_reg()); | 3516 double ft = get_fpu_register_double(ft_reg()); |
| 3303 switch (instr_.FunctionFieldRaw()) { | 3517 switch (instr_.FunctionFieldRaw()) { |
| 3304 case CVT_D_L: // Mips32r2 instruction. | 3518 case CVT_D_L: // Mips32r2 instruction. |
| 3305 // Watch the signs here, we want 2 32-bit vals | 3519 // Watch the signs here, we want 2 32-bit vals |
| 3306 // to make a sign-64. | 3520 // to make a sign-64. |
| 3307 int64_t i64; | 3521 int64_t i64; |
| 3308 if (IsFp64Mode()) { | 3522 if (IsFp64Mode()) { |
| 3309 i64 = get_fpu_register(fs_reg()); | 3523 i64 = get_fpu_register(fs_reg()); |
| 3310 } else { | 3524 } else { |
| 3311 i64 = static_cast<uint32_t>(get_fpu_register_word(fs_reg())); | 3525 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; | 3526 i64 |= static_cast<int64_t>(get_fpu_register_word(fs_reg() + 1)) << 32; |
| 3313 } | 3527 } |
| 3314 set_fpu_register_double(fd_reg(), static_cast<double>(i64)); | 3528 set_fpu_register_double(fd_reg(), static_cast<double>(i64)); |
| 3529 TraceRegWr(get_fpu_register(fd_reg()), DOUBLE); | |
| 3315 break; | 3530 break; |
| 3316 case CVT_S_L: | 3531 case CVT_S_L: |
| 3317 if (IsFp64Mode()) { | 3532 if (IsFp64Mode()) { |
| 3318 i64 = get_fpu_register(fs_reg()); | 3533 i64 = get_fpu_register(fs_reg()); |
| 3319 } else { | 3534 } else { |
| 3320 i64 = static_cast<uint32_t>(get_fpu_register_word(fs_reg())); | 3535 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; | 3536 i64 |= static_cast<int64_t>(get_fpu_register_word(fs_reg() + 1)) << 32; |
| 3322 } | 3537 } |
| 3323 set_fpu_register_float(fd_reg(), static_cast<float>(i64)); | 3538 set_fpu_register_float(fd_reg(), static_cast<float>(i64)); |
| 3539 TraceRegWr(get_fpu_register_word(fd_reg()), FLOAT); | |
| 3324 break; | 3540 break; |
| 3325 case CMP_AF: // Mips64r6 CMP.D instructions. | 3541 case CMP_AF: // Mips64r6 CMP.D instructions. |
| 3326 set_fpu_register(fd_reg(), 0); | 3542 set_fpu_register(fd_reg(), 0); |
| 3543 TraceRegWr(get_fpu_register(fd_reg())); | |
| 3327 break; | 3544 break; |
| 3328 case CMP_UN: | 3545 case CMP_UN: |
| 3329 if (std::isnan(fs) || std::isnan(ft)) { | 3546 if (std::isnan(fs) || std::isnan(ft)) { |
| 3330 set_fpu_register(fd_reg(), -1); | 3547 set_fpu_register(fd_reg(), -1); |
| 3331 } else { | 3548 } else { |
| 3332 set_fpu_register(fd_reg(), 0); | 3549 set_fpu_register(fd_reg(), 0); |
| 3333 } | 3550 } |
| 3551 TraceRegWr(get_fpu_register(fd_reg())); | |
| 3334 break; | 3552 break; |
| 3335 case CMP_EQ: | 3553 case CMP_EQ: |
| 3336 if (fs == ft) { | 3554 if (fs == ft) { |
| 3337 set_fpu_register(fd_reg(), -1); | 3555 set_fpu_register(fd_reg(), -1); |
| 3338 } else { | 3556 } else { |
| 3339 set_fpu_register(fd_reg(), 0); | 3557 set_fpu_register(fd_reg(), 0); |
| 3340 } | 3558 } |
| 3559 TraceRegWr(get_fpu_register(fd_reg())); | |
| 3341 break; | 3560 break; |
| 3342 case CMP_UEQ: | 3561 case CMP_UEQ: |
| 3343 if ((fs == ft) || (std::isnan(fs) || std::isnan(ft))) { | 3562 if ((fs == ft) || (std::isnan(fs) || std::isnan(ft))) { |
| 3344 set_fpu_register(fd_reg(), -1); | 3563 set_fpu_register(fd_reg(), -1); |
| 3345 } else { | 3564 } else { |
| 3346 set_fpu_register(fd_reg(), 0); | 3565 set_fpu_register(fd_reg(), 0); |
| 3347 } | 3566 } |
| 3567 TraceRegWr(get_fpu_register(fd_reg())); | |
| 3348 break; | 3568 break; |
| 3349 case CMP_LT: | 3569 case CMP_LT: |
| 3350 if (fs < ft) { | 3570 if (fs < ft) { |
| 3351 set_fpu_register(fd_reg(), -1); | 3571 set_fpu_register(fd_reg(), -1); |
| 3352 } else { | 3572 } else { |
| 3353 set_fpu_register(fd_reg(), 0); | 3573 set_fpu_register(fd_reg(), 0); |
| 3354 } | 3574 } |
| 3575 TraceRegWr(get_fpu_register(fd_reg())); | |
| 3355 break; | 3576 break; |
| 3356 case CMP_ULT: | 3577 case CMP_ULT: |
| 3357 if ((fs < ft) || (std::isnan(fs) || std::isnan(ft))) { | 3578 if ((fs < ft) || (std::isnan(fs) || std::isnan(ft))) { |
| 3358 set_fpu_register(fd_reg(), -1); | 3579 set_fpu_register(fd_reg(), -1); |
| 3359 } else { | 3580 } else { |
| 3360 set_fpu_register(fd_reg(), 0); | 3581 set_fpu_register(fd_reg(), 0); |
| 3361 } | 3582 } |
| 3583 TraceRegWr(get_fpu_register(fd_reg())); | |
| 3362 break; | 3584 break; |
| 3363 case CMP_LE: | 3585 case CMP_LE: |
| 3364 if (fs <= ft) { | 3586 if (fs <= ft) { |
| 3365 set_fpu_register(fd_reg(), -1); | 3587 set_fpu_register(fd_reg(), -1); |
| 3366 } else { | 3588 } else { |
| 3367 set_fpu_register(fd_reg(), 0); | 3589 set_fpu_register(fd_reg(), 0); |
| 3368 } | 3590 } |
| 3591 TraceRegWr(get_fpu_register(fd_reg())); | |
| 3369 break; | 3592 break; |
| 3370 case CMP_ULE: | 3593 case CMP_ULE: |
| 3371 if ((fs <= ft) || (std::isnan(fs) || std::isnan(ft))) { | 3594 if ((fs <= ft) || (std::isnan(fs) || std::isnan(ft))) { |
| 3372 set_fpu_register(fd_reg(), -1); | 3595 set_fpu_register(fd_reg(), -1); |
| 3373 } else { | 3596 } else { |
| 3374 set_fpu_register(fd_reg(), 0); | 3597 set_fpu_register(fd_reg(), 0); |
| 3375 } | 3598 } |
| 3599 TraceRegWr(get_fpu_register(fd_reg())); | |
| 3376 break; | 3600 break; |
| 3377 case CMP_OR: | 3601 case CMP_OR: |
| 3378 if (!std::isnan(fs) && !std::isnan(ft)) { | 3602 if (!std::isnan(fs) && !std::isnan(ft)) { |
| 3379 set_fpu_register(fd_reg(), -1); | 3603 set_fpu_register(fd_reg(), -1); |
| 3380 } else { | 3604 } else { |
| 3381 set_fpu_register(fd_reg(), 0); | 3605 set_fpu_register(fd_reg(), 0); |
| 3382 } | 3606 } |
| 3607 TraceRegWr(get_fpu_register(fd_reg())); | |
| 3383 break; | 3608 break; |
| 3384 case CMP_UNE: | 3609 case CMP_UNE: |
| 3385 if ((fs != ft) || (std::isnan(fs) || std::isnan(ft))) { | 3610 if ((fs != ft) || (std::isnan(fs) || std::isnan(ft))) { |
| 3386 set_fpu_register(fd_reg(), -1); | 3611 set_fpu_register(fd_reg(), -1); |
| 3387 } else { | 3612 } else { |
| 3388 set_fpu_register(fd_reg(), 0); | 3613 set_fpu_register(fd_reg(), 0); |
| 3389 } | 3614 } |
| 3615 TraceRegWr(get_fpu_register(fd_reg())); | |
| 3390 break; | 3616 break; |
| 3391 case CMP_NE: | 3617 case CMP_NE: |
| 3392 if (fs != ft && (!std::isnan(fs) && !std::isnan(ft))) { | 3618 if (fs != ft && (!std::isnan(fs) && !std::isnan(ft))) { |
| 3393 set_fpu_register(fd_reg(), -1); | 3619 set_fpu_register(fd_reg(), -1); |
| 3394 } else { | 3620 } else { |
| 3395 set_fpu_register(fd_reg(), 0); | 3621 set_fpu_register(fd_reg(), 0); |
| 3396 } | 3622 } |
| 3623 TraceRegWr(get_fpu_register(fd_reg())); | |
| 3397 break; | 3624 break; |
| 3398 default: | 3625 default: |
| 3399 UNREACHABLE(); | 3626 UNREACHABLE(); |
| 3400 } | 3627 } |
| 3401 } | 3628 } |
| 3402 | 3629 |
| 3403 | 3630 |
| 3404 void Simulator::DecodeTypeRegisterCOP1() { | 3631 void Simulator::DecodeTypeRegisterCOP1() { |
| 3405 switch (instr_.RsFieldRaw()) { | 3632 switch (instr_.RsFieldRaw()) { |
| 3406 case CFC1: | 3633 case CFC1: |
| 3407 // At the moment only FCSR is supported. | 3634 // At the moment only FCSR is supported. |
| 3408 DCHECK(fs_reg() == kFCSRRegister); | 3635 DCHECK(fs_reg() == kFCSRRegister); |
| 3409 set_register(rt_reg(), FCSR_); | 3636 set_register(rt_reg(), FCSR_); |
| 3637 TraceRegWr(get_register(rt_reg())); | |
| 3410 break; | 3638 break; |
| 3411 case MFC1: | 3639 case MFC1: |
| 3412 set_register(rt_reg(), get_fpu_register_word(fs_reg())); | 3640 set_register(rt_reg(), get_fpu_register_word(fs_reg())); |
| 3641 TraceRegWr(get_register(rt_reg())); | |
| 3413 break; | 3642 break; |
| 3414 case MFHC1: | 3643 case MFHC1: |
| 3415 if (IsFp64Mode()) { | 3644 if (IsFp64Mode()) { |
| 3416 set_register(rt_reg(), get_fpu_register_hi_word(fs_reg())); | 3645 set_register(rt_reg(), get_fpu_register_hi_word(fs_reg())); |
| 3417 } else { | 3646 } else { |
| 3418 set_register(rt_reg(), get_fpu_register_word(fs_reg() + 1)); | 3647 set_register(rt_reg(), get_fpu_register_word(fs_reg() + 1)); |
| 3419 } | 3648 } |
| 3649 TraceRegWr(get_register(rt_reg())); | |
| 3420 break; | 3650 break; |
| 3421 case CTC1: { | 3651 case CTC1: { |
| 3422 // At the moment only FCSR is supported. | 3652 // At the moment only FCSR is supported. |
| 3423 DCHECK(fs_reg() == kFCSRRegister); | 3653 DCHECK(fs_reg() == kFCSRRegister); |
| 3424 int32_t reg = registers_[rt_reg()]; | 3654 int32_t reg = registers_[rt_reg()]; |
| 3425 if (IsMipsArchVariant(kMips32r6)) { | 3655 if (IsMipsArchVariant(kMips32r6)) { |
| 3426 FCSR_ = reg | kFCSRNaN2008FlagMask; | 3656 FCSR_ = reg | kFCSRNaN2008FlagMask; |
| 3427 } else { | 3657 } else { |
| 3428 DCHECK(IsMipsArchVariant(kMips32r1) || IsMipsArchVariant(kMips32r2)); | 3658 DCHECK(IsMipsArchVariant(kMips32r1) || IsMipsArchVariant(kMips32r2)); |
| 3429 FCSR_ = reg & ~kFCSRNaN2008FlagMask; | 3659 FCSR_ = reg & ~kFCSRNaN2008FlagMask; |
| 3430 } | 3660 } |
| 3661 TraceRegWr(static_cast<int32_t>(FCSR_), FLOAT); | |
| 3431 break; | 3662 break; |
| 3432 } | 3663 } |
| 3433 case MTC1: | 3664 case MTC1: |
| 3434 // Hardware writes upper 32-bits to zero on mtc1. | 3665 // Hardware writes upper 32-bits to zero on mtc1. |
| 3435 set_fpu_register_hi_word(fs_reg(), 0); | 3666 set_fpu_register_hi_word(fs_reg(), 0); |
| 3436 set_fpu_register_word(fs_reg(), registers_[rt_reg()]); | 3667 set_fpu_register_word(fs_reg(), registers_[rt_reg()]); |
| 3668 TraceRegWr(get_fpu_register_word(fs_reg()), FLOAT); | |
| 3437 break; | 3669 break; |
| 3438 case MTHC1: | 3670 case MTHC1: |
| 3439 if (IsFp64Mode()) { | 3671 if (IsFp64Mode()) { |
| 3440 set_fpu_register_hi_word(fs_reg(), registers_[rt_reg()]); | 3672 set_fpu_register_hi_word(fs_reg(), registers_[rt_reg()]); |
| 3673 TraceRegWr(get_fpu_register(fs_reg()), DOUBLE); | |
| 3441 } else { | 3674 } else { |
| 3442 set_fpu_register_word(fs_reg() + 1, registers_[rt_reg()]); | 3675 set_fpu_register_word(fs_reg() + 1, registers_[rt_reg()]); |
| 3676 if (fs_reg() % 2) { | |
| 3677 TraceRegWr(get_fpu_register_word(fs_reg() + 1), FLOAT); | |
| 3678 } else { | |
| 3679 TraceRegWr(get_fpu_register(fs_reg()), DOUBLE); | |
| 3680 } | |
| 3443 } | 3681 } |
| 3444 break; | 3682 break; |
| 3445 case S: { | 3683 case S: { |
| 3446 DecodeTypeRegisterSRsType(); | 3684 DecodeTypeRegisterSRsType(); |
| 3447 break; | 3685 break; |
| 3448 } | 3686 } |
| 3449 case D: | 3687 case D: |
| 3450 DecodeTypeRegisterDRsType(); | 3688 DecodeTypeRegisterDRsType(); |
| 3451 break; | 3689 break; |
| 3452 case W: | 3690 case W: |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 3466 | 3704 |
| 3467 void Simulator::DecodeTypeRegisterCOP1X() { | 3705 void Simulator::DecodeTypeRegisterCOP1X() { |
| 3468 switch (instr_.FunctionFieldRaw()) { | 3706 switch (instr_.FunctionFieldRaw()) { |
| 3469 case MADD_S: { | 3707 case MADD_S: { |
| 3470 DCHECK(IsMipsArchVariant(kMips32r2)); | 3708 DCHECK(IsMipsArchVariant(kMips32r2)); |
| 3471 float fr, ft, fs; | 3709 float fr, ft, fs; |
| 3472 fr = get_fpu_register_float(fr_reg()); | 3710 fr = get_fpu_register_float(fr_reg()); |
| 3473 fs = get_fpu_register_float(fs_reg()); | 3711 fs = get_fpu_register_float(fs_reg()); |
| 3474 ft = get_fpu_register_float(ft_reg()); | 3712 ft = get_fpu_register_float(ft_reg()); |
| 3475 set_fpu_register_float(fd_reg(), fs * ft + fr); | 3713 set_fpu_register_float(fd_reg(), fs * ft + fr); |
| 3714 TraceRegWr(get_fpu_register_word(fd_reg()), FLOAT); | |
| 3476 break; | 3715 break; |
| 3477 } | 3716 } |
| 3478 case MSUB_S: { | 3717 case MSUB_S: { |
| 3479 DCHECK(IsMipsArchVariant(kMips32r2)); | 3718 DCHECK(IsMipsArchVariant(kMips32r2)); |
| 3480 float fr, ft, fs; | 3719 float fr, ft, fs; |
| 3481 fr = get_fpu_register_float(fr_reg()); | 3720 fr = get_fpu_register_float(fr_reg()); |
| 3482 fs = get_fpu_register_float(fs_reg()); | 3721 fs = get_fpu_register_float(fs_reg()); |
| 3483 ft = get_fpu_register_float(ft_reg()); | 3722 ft = get_fpu_register_float(ft_reg()); |
| 3484 set_fpu_register_float(fd_reg(), fs * ft - fr); | 3723 set_fpu_register_float(fd_reg(), fs * ft - fr); |
| 3724 TraceRegWr(get_fpu_register_word(fd_reg()), FLOAT); | |
| 3485 break; | 3725 break; |
| 3486 } | 3726 } |
| 3487 case MADD_D: { | 3727 case MADD_D: { |
| 3488 DCHECK(IsMipsArchVariant(kMips32r2)); | 3728 DCHECK(IsMipsArchVariant(kMips32r2)); |
| 3489 double fr, ft, fs; | 3729 double fr, ft, fs; |
| 3490 fr = get_fpu_register_double(fr_reg()); | 3730 fr = get_fpu_register_double(fr_reg()); |
| 3491 fs = get_fpu_register_double(fs_reg()); | 3731 fs = get_fpu_register_double(fs_reg()); |
| 3492 ft = get_fpu_register_double(ft_reg()); | 3732 ft = get_fpu_register_double(ft_reg()); |
| 3493 set_fpu_register_double(fd_reg(), fs * ft + fr); | 3733 set_fpu_register_double(fd_reg(), fs * ft + fr); |
| 3734 TraceRegWr(get_fpu_register(fd_reg()), DOUBLE); | |
| 3494 break; | 3735 break; |
| 3495 } | 3736 } |
| 3496 case MSUB_D: { | 3737 case MSUB_D: { |
| 3497 DCHECK(IsMipsArchVariant(kMips32r2)); | 3738 DCHECK(IsMipsArchVariant(kMips32r2)); |
| 3498 double fr, ft, fs; | 3739 double fr, ft, fs; |
| 3499 fr = get_fpu_register_double(fr_reg()); | 3740 fr = get_fpu_register_double(fr_reg()); |
| 3500 fs = get_fpu_register_double(fs_reg()); | 3741 fs = get_fpu_register_double(fs_reg()); |
| 3501 ft = get_fpu_register_double(ft_reg()); | 3742 ft = get_fpu_register_double(ft_reg()); |
| 3502 set_fpu_register_double(fd_reg(), fs * ft - fr); | 3743 set_fpu_register_double(fd_reg(), fs * ft - fr); |
| 3744 TraceRegWr(get_fpu_register(fd_reg()), DOUBLE); | |
| 3503 break; | 3745 break; |
| 3504 } | 3746 } |
| 3505 default: | 3747 default: |
| 3506 UNREACHABLE(); | 3748 UNREACHABLE(); |
| 3507 } | 3749 } |
| 3508 } | 3750 } |
| 3509 | 3751 |
| 3510 | 3752 |
| 3511 void Simulator::DecodeTypeRegisterSPECIAL() { | 3753 void Simulator::DecodeTypeRegisterSPECIAL() { |
| 3512 int64_t alu_out = 0x12345678; | 3754 int64_t alu_out = 0x12345678; |
| (...skipping 852 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4365 uint8_t al_offset = (rs + se_imm16) & kPointerAlignmentMask; | 4607 uint8_t al_offset = (rs + se_imm16) & kPointerAlignmentMask; |
| 4366 uint32_t mask = (1 << al_offset * 8) - 1; | 4608 uint32_t mask = (1 << al_offset * 8) - 1; |
| 4367 addr = rs + se_imm16 - al_offset; | 4609 addr = rs + se_imm16 - al_offset; |
| 4368 uint32_t mem_value = ReadW(addr, instr_.instr()); | 4610 uint32_t mem_value = ReadW(addr, instr_.instr()); |
| 4369 mem_value = (rt << al_offset * 8) | (mem_value & mask); | 4611 mem_value = (rt << al_offset * 8) | (mem_value & mask); |
| 4370 WriteW(addr, mem_value, instr_.instr()); | 4612 WriteW(addr, mem_value, instr_.instr()); |
| 4371 break; | 4613 break; |
| 4372 } | 4614 } |
| 4373 case LWC1: | 4615 case LWC1: |
| 4374 set_fpu_register_hi_word(ft_reg, 0); | 4616 set_fpu_register_hi_word(ft_reg, 0); |
| 4375 set_fpu_register_word(ft_reg, ReadW(rs + se_imm16, instr_.instr())); | 4617 set_fpu_register_word(ft_reg, |
| 4618 ReadW(rs + se_imm16, instr_.instr(), FLOAT)); | |
| 4619 if (ft_reg % 2) { | |
| 4620 TraceMemRd(rs + se_imm16, get_fpu_register(ft_reg - 1), FLOAT_DOUBLE); | |
| 4621 } else { | |
| 4622 TraceMemRd(rs + se_imm16, get_fpu_register_word(ft_reg), FLOAT); | |
| 4623 } | |
| 4376 break; | 4624 break; |
| 4377 case LDC1: | 4625 case LDC1: |
| 4378 set_fpu_register_double(ft_reg, ReadD(rs + se_imm16, instr_.instr())); | 4626 set_fpu_register_double(ft_reg, ReadD(rs + se_imm16, instr_.instr())); |
| 4627 TraceMemRd(rs + se_imm16, get_fpu_register(ft_reg), DOUBLE); | |
| 4379 break; | 4628 break; |
| 4380 case SWC1: | 4629 case SWC1: |
| 4381 WriteW(rs + se_imm16, get_fpu_register_word(ft_reg), instr_.instr()); | 4630 WriteW(rs + se_imm16, get_fpu_register_word(ft_reg), instr_.instr()); |
| 4631 TraceMemWr(rs + se_imm16, get_fpu_register_word(ft_reg)); | |
| 4382 break; | 4632 break; |
| 4383 case SDC1: | 4633 case SDC1: |
| 4384 WriteD(rs + se_imm16, get_fpu_register_double(ft_reg), instr_.instr()); | 4634 WriteD(rs + se_imm16, get_fpu_register_double(ft_reg), instr_.instr()); |
| 4635 TraceMemWr(rs + se_imm16, get_fpu_register(ft_reg)); | |
| 4385 break; | 4636 break; |
| 4386 // ------------- PC-Relative instructions. | 4637 // ------------- PC-Relative instructions. |
| 4387 case PCREL: { | 4638 case PCREL: { |
| 4388 // rt field: checking 5-bits. | 4639 // rt field: checking 5-bits. |
| 4389 int32_t imm21 = instr_.Imm21Value(); | 4640 int32_t imm21 = instr_.Imm21Value(); |
| 4390 int32_t current_pc = get_pc(); | 4641 int32_t current_pc = get_pc(); |
| 4391 uint8_t rt = (imm21 >> kImm16Bits); | 4642 uint8_t rt = (imm21 >> kImm16Bits); |
| 4392 switch (rt) { | 4643 switch (rt) { |
| 4393 case ALUIPC: | 4644 case ALUIPC: |
| 4394 addr = current_pc + (se_imm16 << 16); | 4645 addr = current_pc + (se_imm16 << 16); |
| (...skipping 299 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4694 | 4945 |
| 4695 | 4946 |
| 4696 #undef UNSUPPORTED | 4947 #undef UNSUPPORTED |
| 4697 | 4948 |
| 4698 } // namespace internal | 4949 } // namespace internal |
| 4699 } // namespace v8 | 4950 } // namespace v8 |
| 4700 | 4951 |
| 4701 #endif // USE_SIMULATOR | 4952 #endif // USE_SIMULATOR |
| 4702 | 4953 |
| 4703 #endif // V8_TARGET_ARCH_MIPS | 4954 #endif // V8_TARGET_ARCH_MIPS |
| OLD | NEW |