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 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 677 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 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 set_fpu_register_double(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 } |
| 2591 TraceRegWr(get_fpu_register(fd_reg()), DOUBLE); | |
| 2467 break; | 2592 break; |
| 2468 } | 2593 } |
| 2469 case SEL: | 2594 case SEL: |
| 2470 DCHECK(IsMipsArchVariant(kMips32r6)); | 2595 DCHECK(IsMipsArchVariant(kMips32r6)); |
| 2471 set_fpu_register_double(fd_reg(), (fd_int & 0x1) == 0 ? fs : ft); | 2596 set_fpu_register_double(fd_reg(), (fd_int & 0x1) == 0 ? fs : ft); |
| 2597 TraceRegWr(get_fpu_register(fd_reg()), DOUBLE); | |
| 2472 break; | 2598 break; |
| 2473 case SELEQZ_C: | 2599 case SELEQZ_C: |
| 2474 DCHECK(IsMipsArchVariant(kMips32r6)); | 2600 DCHECK(IsMipsArchVariant(kMips32r6)); |
| 2475 set_fpu_register_double(fd_reg(), (ft_int & 0x1) == 0 ? fs : 0.0); | 2601 set_fpu_register_double(fd_reg(), (ft_int & 0x1) == 0 ? fs : 0.0); |
| 2602 TraceRegWr(get_fpu_register(fd_reg()), DOUBLE); | |
| 2476 break; | 2603 break; |
| 2477 case SELNEZ_C: | 2604 case SELNEZ_C: |
| 2478 DCHECK(IsMipsArchVariant(kMips32r6)); | 2605 DCHECK(IsMipsArchVariant(kMips32r6)); |
| 2479 set_fpu_register_double(fd_reg(), (ft_int & 0x1) != 0 ? fs : 0.0); | 2606 set_fpu_register_double(fd_reg(), (ft_int & 0x1) != 0 ? fs : 0.0); |
| 2607 TraceRegWr(get_fpu_register(fd_reg()), DOUBLE); | |
| 2480 break; | 2608 break; |
| 2481 case MOVZ_C: { | 2609 case MOVZ_C: { |
| 2482 DCHECK(IsMipsArchVariant(kMips32r2)); | 2610 DCHECK(IsMipsArchVariant(kMips32r2)); |
| 2483 if (rt() == 0) { | 2611 if (rt() == 0) { |
| 2484 set_fpu_register_double(fd_reg(), fs); | 2612 set_fpu_register_double(fd_reg(), fs); |
| 2485 } | 2613 } |
| 2614 TraceRegWr(get_fpu_register(fd_reg()), DOUBLE); | |
|
ivica.bogosavljevic
2017/01/27 09:55:11
If rt() != 0, the trace will point that the value
Ilija.Pavlovic1
2017/01/31 08:59:35
Done.
| |
| 2486 break; | 2615 break; |
| 2487 } | 2616 } |
| 2488 case MOVN_C: { | 2617 case MOVN_C: { |
| 2489 DCHECK(IsMipsArchVariant(kMips32r2)); | 2618 DCHECK(IsMipsArchVariant(kMips32r2)); |
| 2490 int32_t rt_reg = instr_.RtValue(); | 2619 int32_t rt_reg = instr_.RtValue(); |
| 2491 int32_t rt = get_register(rt_reg); | 2620 int32_t rt = get_register(rt_reg); |
| 2492 if (rt != 0) { | 2621 if (rt != 0) { |
| 2493 set_fpu_register_double(fd_reg(), fs); | 2622 set_fpu_register_double(fd_reg(), fs); |
| 2494 } | 2623 } |
| 2624 TraceRegWr(get_fpu_register(fd_reg()), DOUBLE); | |
| 2495 break; | 2625 break; |
| 2496 } | 2626 } |
| 2497 case MOVF: { | 2627 case MOVF: { |
| 2498 // Same function field for MOVT.D and MOVF.D | 2628 // Same function field for MOVT.D and MOVF.D |
| 2499 uint32_t ft_cc = (ft_reg() >> 2) & 0x7; | 2629 uint32_t ft_cc = (ft_reg() >> 2) & 0x7; |
| 2500 ft_cc = get_fcsr_condition_bit(ft_cc); | 2630 ft_cc = get_fcsr_condition_bit(ft_cc); |
| 2501 if (instr_.Bit(16)) { // Read Tf bit. | 2631 if (instr_.Bit(16)) { // Read Tf bit. |
| 2502 // MOVT.D | 2632 // MOVT.D |
| 2503 if (test_fcsr_bit(ft_cc)) set_fpu_register_double(fd_reg(), fs); | 2633 if (test_fcsr_bit(ft_cc)) set_fpu_register_double(fd_reg(), fs); |
| 2504 } else { | 2634 } else { |
| 2505 // MOVF.D | 2635 // MOVF.D |
| 2506 if (!test_fcsr_bit(ft_cc)) set_fpu_register_double(fd_reg(), fs); | 2636 if (!test_fcsr_bit(ft_cc)) set_fpu_register_double(fd_reg(), fs); |
| 2507 } | 2637 } |
| 2638 TraceRegWr(get_fpu_register(fd_reg()), DOUBLE); | |
| 2508 break; | 2639 break; |
| 2509 } | 2640 } |
| 2510 case MIN: | 2641 case MIN: |
| 2511 DCHECK(IsMipsArchVariant(kMips32r6)); | 2642 DCHECK(IsMipsArchVariant(kMips32r6)); |
| 2512 set_fpu_register_double(fd_reg(), FPUMin(ft, fs)); | 2643 set_fpu_register_double(fd_reg(), FPUMin(ft, fs)); |
| 2644 TraceRegWr(get_fpu_register(fd_reg()), DOUBLE); | |
|
ivica.bogosavljevic
2017/01/27 09:55:11
I think it would be a very good idea to implement
Ilija.Pavlovic1
2017/01/31 08:59:35
Done.
| |
| 2513 break; | 2645 break; |
| 2514 case MAX: | 2646 case MAX: |
| 2515 DCHECK(IsMipsArchVariant(kMips32r6)); | 2647 DCHECK(IsMipsArchVariant(kMips32r6)); |
| 2516 set_fpu_register_double(fd_reg(), FPUMax(ft, fs)); | 2648 set_fpu_register_double(fd_reg(), FPUMax(ft, fs)); |
| 2649 TraceRegWr(get_fpu_register(fd_reg()), DOUBLE); | |
| 2517 break; | 2650 break; |
| 2518 case MINA: | 2651 case MINA: |
| 2519 DCHECK(IsMipsArchVariant(kMips32r6)); | 2652 DCHECK(IsMipsArchVariant(kMips32r6)); |
| 2520 set_fpu_register_double(fd_reg(), FPUMinA(ft, fs)); | 2653 set_fpu_register_double(fd_reg(), FPUMinA(ft, fs)); |
| 2654 TraceRegWr(get_fpu_register(fd_reg()), DOUBLE); | |
| 2521 break; | 2655 break; |
| 2522 case MAXA: | 2656 case MAXA: |
| 2523 DCHECK(IsMipsArchVariant(kMips32r6)); | 2657 DCHECK(IsMipsArchVariant(kMips32r6)); |
| 2524 set_fpu_register_double(fd_reg(), FPUMaxA(ft, fs)); | 2658 set_fpu_register_double(fd_reg(), FPUMaxA(ft, fs)); |
| 2659 TraceRegWr(get_fpu_register(fd_reg()), DOUBLE); | |
| 2525 break; | 2660 break; |
| 2526 case ADD_D: | 2661 case ADD_D: |
| 2527 set_fpu_register_double( | 2662 set_fpu_register_double( |
| 2528 fd_reg(), | 2663 fd_reg(), |
| 2529 FPUCanonalizeOperation( | 2664 FPUCanonalizeOperation( |
| 2530 [](double lhs, double rhs) { return lhs + rhs; }, fs, ft)); | 2665 [](double lhs, double rhs) { return lhs + rhs; }, fs, ft)); |
| 2666 TraceRegWr(get_fpu_register(fd_reg()), DOUBLE); | |
| 2531 break; | 2667 break; |
| 2532 case SUB_D: | 2668 case SUB_D: |
| 2533 set_fpu_register_double( | 2669 set_fpu_register_double( |
| 2534 fd_reg(), | 2670 fd_reg(), |
| 2535 FPUCanonalizeOperation( | 2671 FPUCanonalizeOperation( |
| 2536 [](double lhs, double rhs) { return lhs - rhs; }, fs, ft)); | 2672 [](double lhs, double rhs) { return lhs - rhs; }, fs, ft)); |
| 2673 TraceRegWr(get_fpu_register(fd_reg()), DOUBLE); | |
| 2537 break; | 2674 break; |
| 2538 case MADDF_D: | 2675 case MADDF_D: |
| 2539 DCHECK(IsMipsArchVariant(kMips32r6)); | 2676 DCHECK(IsMipsArchVariant(kMips32r6)); |
| 2540 set_fpu_register_double(fd_reg(), std::fma(fs, ft, fd)); | 2677 set_fpu_register_double(fd_reg(), std::fma(fs, ft, fd)); |
| 2678 TraceRegWr(get_fpu_register(fd_reg()), DOUBLE); | |
| 2541 break; | 2679 break; |
| 2542 case MSUBF_D: | 2680 case MSUBF_D: |
| 2543 DCHECK(IsMipsArchVariant(kMips32r6)); | 2681 DCHECK(IsMipsArchVariant(kMips32r6)); |
| 2544 set_fpu_register_double(fd_reg(), std::fma(-fs, ft, fd)); | 2682 set_fpu_register_double(fd_reg(), std::fma(-fs, ft, fd)); |
| 2683 TraceRegWr(get_fpu_register(fd_reg()), DOUBLE); | |
| 2545 break; | 2684 break; |
| 2546 case MUL_D: | 2685 case MUL_D: |
| 2547 set_fpu_register_double( | 2686 set_fpu_register_double( |
| 2548 fd_reg(), | 2687 fd_reg(), |
| 2549 FPUCanonalizeOperation( | 2688 FPUCanonalizeOperation( |
| 2550 [](double lhs, double rhs) { return lhs * rhs; }, fs, ft)); | 2689 [](double lhs, double rhs) { return lhs * rhs; }, fs, ft)); |
| 2690 TraceRegWr(get_fpu_register(fd_reg()), DOUBLE); | |
| 2551 break; | 2691 break; |
| 2552 case DIV_D: | 2692 case DIV_D: |
| 2553 set_fpu_register_double( | 2693 set_fpu_register_double( |
| 2554 fd_reg(), | 2694 fd_reg(), |
| 2555 FPUCanonalizeOperation( | 2695 FPUCanonalizeOperation( |
| 2556 [](double lhs, double rhs) { return lhs / rhs; }, fs, ft)); | 2696 [](double lhs, double rhs) { return lhs / rhs; }, fs, ft)); |
| 2697 TraceRegWr(get_fpu_register(fd_reg()), DOUBLE); | |
| 2557 break; | 2698 break; |
| 2558 case ABS_D: | 2699 case ABS_D: |
| 2559 set_fpu_register_double( | 2700 set_fpu_register_double( |
| 2560 fd_reg(), | 2701 fd_reg(), |
| 2561 FPUCanonalizeOperation([](double fs) { return FPAbs(fs); }, fs)); | 2702 FPUCanonalizeOperation([](double fs) { return FPAbs(fs); }, fs)); |
| 2703 TraceRegWr(get_fpu_register(fd_reg()), DOUBLE); | |
| 2562 break; | 2704 break; |
| 2563 case MOV_D: | 2705 case MOV_D: |
| 2564 set_fpu_register_double(fd_reg(), fs); | 2706 set_fpu_register_double(fd_reg(), fs); |
| 2707 TraceRegWr(get_fpu_register(fd_reg()), DOUBLE); | |
| 2565 break; | 2708 break; |
| 2566 case NEG_D: | 2709 case NEG_D: |
| 2567 set_fpu_register_double( | 2710 set_fpu_register_double( |
| 2568 fd_reg(), FPUCanonalizeOperation([](double src) { return -src; }, | 2711 fd_reg(), FPUCanonalizeOperation([](double src) { return -src; }, |
| 2569 KeepSign::yes, fs)); | 2712 KeepSign::yes, fs)); |
| 2713 TraceRegWr(get_fpu_register(fd_reg()), DOUBLE); | |
| 2570 break; | 2714 break; |
| 2571 case SQRT_D: | 2715 case SQRT_D: |
| 2572 set_fpu_register_double( | 2716 set_fpu_register_double( |
| 2573 fd_reg(), | 2717 fd_reg(), |
| 2574 FPUCanonalizeOperation([](double fs) { return std::sqrt(fs); }, fs)); | 2718 FPUCanonalizeOperation([](double fs) { return std::sqrt(fs); }, fs)); |
| 2719 TraceRegWr(get_fpu_register(fd_reg()), DOUBLE); | |
| 2575 break; | 2720 break; |
| 2576 case RSQRT_D: | 2721 case RSQRT_D: |
| 2577 set_fpu_register_double( | 2722 set_fpu_register_double( |
| 2578 fd_reg(), FPUCanonalizeOperation( | 2723 fd_reg(), FPUCanonalizeOperation( |
| 2579 [](double fs) { return 1.0 / std::sqrt(fs); }, fs)); | 2724 [](double fs) { return 1.0 / std::sqrt(fs); }, fs)); |
| 2725 TraceRegWr(get_fpu_register(fd_reg()), DOUBLE); | |
| 2580 break; | 2726 break; |
| 2581 case RECIP_D: | 2727 case RECIP_D: |
| 2582 set_fpu_register_double( | 2728 set_fpu_register_double( |
| 2583 fd_reg(), | 2729 fd_reg(), |
| 2584 FPUCanonalizeOperation([](double fs) { return 1.0 / fs; }, fs)); | 2730 FPUCanonalizeOperation([](double fs) { return 1.0 / fs; }, fs)); |
| 2731 TraceRegWr(get_fpu_register(fd_reg()), DOUBLE); | |
| 2585 break; | 2732 break; |
| 2586 case C_UN_D: | 2733 case C_UN_D: |
| 2587 set_fcsr_bit(fcsr_cc, std::isnan(fs) || std::isnan(ft)); | 2734 set_fcsr_bit(fcsr_cc, std::isnan(fs) || std::isnan(ft)); |
| 2735 TraceRegWr(test_fcsr_bit(fcsr_cc)); | |
| 2588 break; | 2736 break; |
| 2589 case C_EQ_D: | 2737 case C_EQ_D: |
| 2590 set_fcsr_bit(fcsr_cc, (fs == ft)); | 2738 set_fcsr_bit(fcsr_cc, (fs == ft)); |
| 2739 TraceRegWr(test_fcsr_bit(fcsr_cc)); | |
| 2591 break; | 2740 break; |
| 2592 case C_UEQ_D: | 2741 case C_UEQ_D: |
| 2593 set_fcsr_bit(fcsr_cc, (fs == ft) || (std::isnan(fs) || std::isnan(ft))); | 2742 set_fcsr_bit(fcsr_cc, (fs == ft) || (std::isnan(fs) || std::isnan(ft))); |
| 2743 TraceRegWr(test_fcsr_bit(fcsr_cc)); | |
| 2594 break; | 2744 break; |
| 2595 case C_OLT_D: | 2745 case C_OLT_D: |
| 2596 set_fcsr_bit(fcsr_cc, (fs < ft)); | 2746 set_fcsr_bit(fcsr_cc, (fs < ft)); |
| 2747 TraceRegWr(test_fcsr_bit(fcsr_cc)); | |
| 2597 break; | 2748 break; |
| 2598 case C_ULT_D: | 2749 case C_ULT_D: |
| 2599 set_fcsr_bit(fcsr_cc, (fs < ft) || (std::isnan(fs) || std::isnan(ft))); | 2750 set_fcsr_bit(fcsr_cc, (fs < ft) || (std::isnan(fs) || std::isnan(ft))); |
| 2751 TraceRegWr(test_fcsr_bit(fcsr_cc)); | |
| 2600 break; | 2752 break; |
| 2601 case C_OLE_D: | 2753 case C_OLE_D: |
| 2602 set_fcsr_bit(fcsr_cc, (fs <= ft)); | 2754 set_fcsr_bit(fcsr_cc, (fs <= ft)); |
| 2755 TraceRegWr(test_fcsr_bit(fcsr_cc)); | |
| 2603 break; | 2756 break; |
| 2604 case C_ULE_D: | 2757 case C_ULE_D: |
| 2605 set_fcsr_bit(fcsr_cc, (fs <= ft) || (std::isnan(fs) || std::isnan(ft))); | 2758 set_fcsr_bit(fcsr_cc, (fs <= ft) || (std::isnan(fs) || std::isnan(ft))); |
| 2759 TraceRegWr(test_fcsr_bit(fcsr_cc)); | |
| 2606 break; | 2760 break; |
| 2607 case CVT_W_D: { // Convert double to word. | 2761 case CVT_W_D: { // Convert double to word. |
| 2608 double rounded; | 2762 double rounded; |
| 2609 int32_t result; | 2763 int32_t result; |
| 2610 round_according_to_fcsr(fs, rounded, result, fs); | 2764 round_according_to_fcsr(fs, rounded, result, fs); |
| 2611 set_fpu_register_word(fd_reg(), result); | 2765 set_fpu_register_word(fd_reg(), result); |
| 2612 if (set_fcsr_round_error(fs, rounded)) { | 2766 if (set_fcsr_round_error(fs, rounded)) { |
| 2613 set_fpu_register_word_invalid_result(fs, rounded); | 2767 set_fpu_register_word_invalid_result(fs, rounded); |
| 2614 } | 2768 } |
| 2769 TraceRegWr(get_fpu_register_word(fd_reg())); | |
| 2615 } break; | 2770 } break; |
| 2616 case ROUND_W_D: // Round double to word (round half to even). | 2771 case ROUND_W_D: // Round double to word (round half to even). |
| 2617 { | 2772 { |
| 2618 double rounded = std::floor(fs + 0.5); | 2773 double rounded = std::floor(fs + 0.5); |
| 2619 int32_t result = static_cast<int32_t>(rounded); | 2774 int32_t result = static_cast<int32_t>(rounded); |
| 2620 if ((result & 1) != 0 && result - fs == 0.5) { | 2775 if ((result & 1) != 0 && result - fs == 0.5) { |
| 2621 // If the number is halfway between two integers, | 2776 // If the number is halfway between two integers, |
| 2622 // round to the even one. | 2777 // round to the even one. |
| 2623 result--; | 2778 result--; |
| 2624 } | 2779 } |
| 2625 set_fpu_register_word(fd_reg(), result); | 2780 set_fpu_register_word(fd_reg(), result); |
| 2626 if (set_fcsr_round_error(fs, rounded)) { | 2781 if (set_fcsr_round_error(fs, rounded)) { |
| 2627 set_fpu_register_word_invalid_result(fs, rounded); | 2782 set_fpu_register_word_invalid_result(fs, rounded); |
| 2628 } | 2783 } |
| 2784 TraceRegWr(get_fpu_register_word(fd_reg())); | |
| 2629 } break; | 2785 } break; |
| 2630 case TRUNC_W_D: // Truncate double to word (round towards 0). | 2786 case TRUNC_W_D: // Truncate double to word (round towards 0). |
| 2631 { | 2787 { |
| 2632 double rounded = trunc(fs); | 2788 double rounded = trunc(fs); |
| 2633 int32_t result = static_cast<int32_t>(rounded); | 2789 int32_t result = static_cast<int32_t>(rounded); |
| 2634 set_fpu_register_word(fd_reg(), result); | 2790 set_fpu_register_word(fd_reg(), result); |
| 2635 if (set_fcsr_round_error(fs, rounded)) { | 2791 if (set_fcsr_round_error(fs, rounded)) { |
| 2636 set_fpu_register_word_invalid_result(fs, rounded); | 2792 set_fpu_register_word_invalid_result(fs, rounded); |
| 2637 } | 2793 } |
| 2794 TraceRegWr(get_fpu_register_word(fd_reg())); | |
| 2638 } break; | 2795 } break; |
| 2639 case FLOOR_W_D: // Round double to word towards negative infinity. | 2796 case FLOOR_W_D: // Round double to word towards negative infinity. |
| 2640 { | 2797 { |
| 2641 double rounded = std::floor(fs); | 2798 double rounded = std::floor(fs); |
| 2642 int32_t result = static_cast<int32_t>(rounded); | 2799 int32_t result = static_cast<int32_t>(rounded); |
| 2643 set_fpu_register_word(fd_reg(), result); | 2800 set_fpu_register_word(fd_reg(), result); |
| 2644 if (set_fcsr_round_error(fs, rounded)) { | 2801 if (set_fcsr_round_error(fs, rounded)) { |
| 2645 set_fpu_register_word_invalid_result(fs, rounded); | 2802 set_fpu_register_word_invalid_result(fs, rounded); |
| 2646 } | 2803 } |
| 2804 TraceRegWr(get_fpu_register_word(fd_reg())); | |
| 2647 } break; | 2805 } break; |
| 2648 case CEIL_W_D: // Round double to word towards positive infinity. | 2806 case CEIL_W_D: // Round double to word towards positive infinity. |
| 2649 { | 2807 { |
| 2650 double rounded = std::ceil(fs); | 2808 double rounded = std::ceil(fs); |
| 2651 int32_t result = static_cast<int32_t>(rounded); | 2809 int32_t result = static_cast<int32_t>(rounded); |
| 2652 set_fpu_register_word(fd_reg(), result); | 2810 set_fpu_register_word(fd_reg(), result); |
| 2653 if (set_fcsr_round_error(fs, rounded)) { | 2811 if (set_fcsr_round_error(fs, rounded)) { |
| 2654 set_fpu_register_word_invalid_result(fs, rounded); | 2812 set_fpu_register_word_invalid_result(fs, rounded); |
| 2655 } | 2813 } |
| 2814 TraceRegWr(get_fpu_register_word(fd_reg())); | |
| 2656 } break; | 2815 } break; |
| 2657 case CVT_S_D: // Convert double to float (single). | 2816 case CVT_S_D: // Convert double to float (single). |
| 2658 set_fpu_register_float(fd_reg(), static_cast<float>(fs)); | 2817 set_fpu_register_float(fd_reg(), static_cast<float>(fs)); |
| 2818 TraceRegWr(get_fpu_register_word(fd_reg()), FLOAT); | |
| 2659 break; | 2819 break; |
| 2660 case CVT_L_D: { // Mips32r2: Truncate double to 64-bit long-word. | 2820 case CVT_L_D: { // Mips32r2: Truncate double to 64-bit long-word. |
| 2661 if (IsFp64Mode()) { | 2821 if (IsFp64Mode()) { |
| 2662 int64_t result; | 2822 int64_t result; |
| 2663 double rounded; | 2823 double rounded; |
| 2664 round64_according_to_fcsr(fs, rounded, result, fs); | 2824 round64_according_to_fcsr(fs, rounded, result, fs); |
| 2665 set_fpu_register(fd_reg(), result); | 2825 set_fpu_register(fd_reg(), result); |
| 2666 if (set_fcsr_round64_error(fs, rounded)) { | 2826 if (set_fcsr_round64_error(fs, rounded)) { |
| 2667 set_fpu_register_invalid_result64(fs, rounded); | 2827 set_fpu_register_invalid_result64(fs, rounded); |
| 2668 } | 2828 } |
| 2829 TraceRegWr(get_fpu_register(fd_reg())); | |
| 2669 } else { | 2830 } else { |
| 2670 UNSUPPORTED(); | 2831 UNSUPPORTED(); |
| 2671 } | 2832 } |
| 2672 break; | 2833 break; |
| 2673 break; | 2834 break; |
| 2674 } | 2835 } |
| 2675 case TRUNC_L_D: { // Mips32r2 instruction. | 2836 case TRUNC_L_D: { // Mips32r2 instruction. |
| 2676 DCHECK(IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)); | 2837 DCHECK(IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)); |
| 2677 double rounded = trunc(fs); | 2838 double rounded = trunc(fs); |
| 2678 i64 = static_cast<int64_t>(rounded); | 2839 i64 = static_cast<int64_t>(rounded); |
| 2679 if (IsFp64Mode()) { | 2840 if (IsFp64Mode()) { |
| 2680 set_fpu_register(fd_reg(), i64); | 2841 set_fpu_register(fd_reg(), i64); |
| 2681 if (set_fcsr_round64_error(fs, rounded)) { | 2842 if (set_fcsr_round64_error(fs, rounded)) { |
| 2682 set_fpu_register_invalid_result64(fs, rounded); | 2843 set_fpu_register_invalid_result64(fs, rounded); |
| 2683 } | 2844 } |
| 2845 TraceRegWr(get_fpu_register(fd_reg())); | |
| 2684 } else { | 2846 } else { |
| 2685 UNSUPPORTED(); | 2847 UNSUPPORTED(); |
| 2686 } | 2848 } |
| 2687 break; | 2849 break; |
| 2688 } | 2850 } |
| 2689 case ROUND_L_D: { // Mips32r2 instruction. | 2851 case ROUND_L_D: { // Mips32r2 instruction. |
| 2690 DCHECK(IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)); | 2852 DCHECK(IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)); |
| 2691 double rounded = std::floor(fs + 0.5); | 2853 double rounded = std::floor(fs + 0.5); |
| 2692 int64_t result = static_cast<int64_t>(rounded); | 2854 int64_t result = static_cast<int64_t>(rounded); |
| 2693 if ((result & 1) != 0 && result - fs == 0.5) { | 2855 if ((result & 1) != 0 && result - fs == 0.5) { |
| 2694 // If the number is halfway between two integers, | 2856 // If the number is halfway between two integers, |
| 2695 // round to the even one. | 2857 // round to the even one. |
| 2696 result--; | 2858 result--; |
| 2697 } | 2859 } |
| 2698 int64_t i64 = static_cast<int64_t>(result); | 2860 int64_t i64 = static_cast<int64_t>(result); |
| 2699 if (IsFp64Mode()) { | 2861 if (IsFp64Mode()) { |
| 2700 set_fpu_register(fd_reg(), i64); | 2862 set_fpu_register(fd_reg(), i64); |
| 2701 if (set_fcsr_round64_error(fs, rounded)) { | 2863 if (set_fcsr_round64_error(fs, rounded)) { |
| 2702 set_fpu_register_invalid_result64(fs, rounded); | 2864 set_fpu_register_invalid_result64(fs, rounded); |
| 2703 } | 2865 } |
| 2866 TraceRegWr(get_fpu_register(fd_reg())); | |
| 2704 } else { | 2867 } else { |
| 2705 UNSUPPORTED(); | 2868 UNSUPPORTED(); |
| 2706 } | 2869 } |
| 2707 break; | 2870 break; |
| 2708 } | 2871 } |
| 2709 case FLOOR_L_D: { // Mips32r2 instruction. | 2872 case FLOOR_L_D: { // Mips32r2 instruction. |
| 2710 DCHECK(IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)); | 2873 DCHECK(IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)); |
| 2711 double rounded = std::floor(fs); | 2874 double rounded = std::floor(fs); |
| 2712 int64_t i64 = static_cast<int64_t>(rounded); | 2875 int64_t i64 = static_cast<int64_t>(rounded); |
| 2713 if (IsFp64Mode()) { | 2876 if (IsFp64Mode()) { |
| 2714 set_fpu_register(fd_reg(), i64); | 2877 set_fpu_register(fd_reg(), i64); |
| 2715 if (set_fcsr_round64_error(fs, rounded)) { | 2878 if (set_fcsr_round64_error(fs, rounded)) { |
| 2716 set_fpu_register_invalid_result64(fs, rounded); | 2879 set_fpu_register_invalid_result64(fs, rounded); |
| 2717 } | 2880 } |
| 2881 TraceRegWr(get_fpu_register(fd_reg())); | |
| 2718 } else { | 2882 } else { |
| 2719 UNSUPPORTED(); | 2883 UNSUPPORTED(); |
| 2720 } | 2884 } |
| 2721 break; | 2885 break; |
| 2722 } | 2886 } |
| 2723 case CEIL_L_D: { // Mips32r2 instruction. | 2887 case CEIL_L_D: { // Mips32r2 instruction. |
| 2724 DCHECK(IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)); | 2888 DCHECK(IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)); |
| 2725 double rounded = std::ceil(fs); | 2889 double rounded = std::ceil(fs); |
| 2726 int64_t i64 = static_cast<int64_t>(rounded); | 2890 int64_t i64 = static_cast<int64_t>(rounded); |
| 2727 if (IsFp64Mode()) { | 2891 if (IsFp64Mode()) { |
| 2728 set_fpu_register(fd_reg(), i64); | 2892 set_fpu_register(fd_reg(), i64); |
| 2729 if (set_fcsr_round64_error(fs, rounded)) { | 2893 if (set_fcsr_round64_error(fs, rounded)) { |
| 2730 set_fpu_register_invalid_result64(fs, rounded); | 2894 set_fpu_register_invalid_result64(fs, rounded); |
| 2731 } | 2895 } |
| 2896 TraceRegWr(get_fpu_register(fd_reg())); | |
| 2732 } else { | 2897 } else { |
| 2733 UNSUPPORTED(); | 2898 UNSUPPORTED(); |
| 2734 } | 2899 } |
| 2735 break; | 2900 break; |
| 2736 } | 2901 } |
| 2737 case CLASS_D: { // Mips32r6 instruction | 2902 case CLASS_D: { // Mips32r6 instruction |
| 2738 // Convert double input to uint64_t for easier bit manipulation | 2903 // Convert double input to uint64_t for easier bit manipulation |
| 2739 uint64_t classed = bit_cast<uint64_t>(fs); | 2904 uint64_t classed = bit_cast<uint64_t>(fs); |
| 2740 | 2905 |
| 2741 // Extracting sign, exponent and mantissa from the input double | 2906 // Extracting sign, exponent and mantissa from the input double |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2789 | 2954 |
| 2790 // Calculating result according to description of CLASS.D instruction | 2955 // Calculating result according to description of CLASS.D instruction |
| 2791 result = (posZero << 9) | (posSubnorm << 8) | (posNorm << 7) | | 2956 result = (posZero << 9) | (posSubnorm << 8) | (posNorm << 7) | |
| 2792 (posInf << 6) | (negZero << 5) | (negSubnorm << 4) | | 2957 (posInf << 6) | (negZero << 5) | (negSubnorm << 4) | |
| 2793 (negNorm << 3) | (negInf << 2) | (quietNan << 1) | signalingNan; | 2958 (negNorm << 3) | (negInf << 2) | (quietNan << 1) | signalingNan; |
| 2794 | 2959 |
| 2795 DCHECK(result != 0); | 2960 DCHECK(result != 0); |
| 2796 | 2961 |
| 2797 dResult = bit_cast<double>(result); | 2962 dResult = bit_cast<double>(result); |
| 2798 set_fpu_register_double(fd_reg(), dResult); | 2963 set_fpu_register_double(fd_reg(), dResult); |
| 2964 TraceRegWr(get_fpu_register(fd_reg()), DOUBLE); | |
| 2799 | 2965 |
| 2800 break; | 2966 break; |
| 2801 } | 2967 } |
| 2802 case C_F_D: { | 2968 case C_F_D: { |
| 2803 set_fcsr_bit(fcsr_cc, false); | 2969 set_fcsr_bit(fcsr_cc, false); |
| 2970 TraceRegWr(test_fcsr_bit(fcsr_cc)); | |
| 2804 break; | 2971 break; |
| 2805 } | 2972 } |
| 2806 default: | 2973 default: |
| 2807 UNREACHABLE(); | 2974 UNREACHABLE(); |
| 2808 } | 2975 } |
| 2809 } | 2976 } |
| 2810 | 2977 |
| 2811 | 2978 |
| 2812 void Simulator::DecodeTypeRegisterWRsType() { | 2979 void Simulator::DecodeTypeRegisterWRsType() { |
| 2813 float fs = get_fpu_register_float(fs_reg()); | 2980 float fs = get_fpu_register_float(fs_reg()); |
| 2814 float ft = get_fpu_register_float(ft_reg()); | 2981 float ft = get_fpu_register_float(ft_reg()); |
| 2815 int32_t alu_out = 0x12345678; | 2982 int32_t alu_out = 0x12345678; |
| 2816 switch (instr_.FunctionFieldRaw()) { | 2983 switch (instr_.FunctionFieldRaw()) { |
| 2817 case CVT_S_W: // Convert word to float (single). | 2984 case CVT_S_W: // Convert word to float (single). |
| 2818 alu_out = get_fpu_register_signed_word(fs_reg()); | 2985 alu_out = get_fpu_register_signed_word(fs_reg()); |
| 2819 set_fpu_register_float(fd_reg(), static_cast<float>(alu_out)); | 2986 set_fpu_register_float(fd_reg(), static_cast<float>(alu_out)); |
| 2987 TraceRegWr(get_fpu_register_word(fd_reg()), FLOAT); | |
| 2820 break; | 2988 break; |
| 2821 case CVT_D_W: // Convert word to double. | 2989 case CVT_D_W: // Convert word to double. |
| 2822 alu_out = get_fpu_register_signed_word(fs_reg()); | 2990 alu_out = get_fpu_register_signed_word(fs_reg()); |
| 2823 set_fpu_register_double(fd_reg(), static_cast<double>(alu_out)); | 2991 set_fpu_register_double(fd_reg(), static_cast<double>(alu_out)); |
| 2992 TraceRegWr(get_fpu_register(fd_reg()), DOUBLE); | |
| 2824 break; | 2993 break; |
| 2825 case CMP_AF: | 2994 case CMP_AF: |
| 2826 set_fpu_register_word(fd_reg(), 0); | 2995 set_fpu_register_word(fd_reg(), 0); |
| 2996 TraceRegWr(get_fpu_register_word(fd_reg())); | |
| 2827 break; | 2997 break; |
| 2828 case CMP_UN: | 2998 case CMP_UN: |
| 2829 if (std::isnan(fs) || std::isnan(ft)) { | 2999 if (std::isnan(fs) || std::isnan(ft)) { |
| 2830 set_fpu_register_word(fd_reg(), -1); | 3000 set_fpu_register_word(fd_reg(), -1); |
| 2831 } else { | 3001 } else { |
| 2832 set_fpu_register_word(fd_reg(), 0); | 3002 set_fpu_register_word(fd_reg(), 0); |
| 2833 } | 3003 } |
| 3004 TraceRegWr(get_fpu_register_word(fd_reg())); | |
| 2834 break; | 3005 break; |
| 2835 case CMP_EQ: | 3006 case CMP_EQ: |
| 2836 if (fs == ft) { | 3007 if (fs == ft) { |
| 2837 set_fpu_register_word(fd_reg(), -1); | 3008 set_fpu_register_word(fd_reg(), -1); |
| 2838 } else { | 3009 } else { |
| 2839 set_fpu_register_word(fd_reg(), 0); | 3010 set_fpu_register_word(fd_reg(), 0); |
| 2840 } | 3011 } |
| 3012 TraceRegWr(get_fpu_register_word(fd_reg())); | |
| 2841 break; | 3013 break; |
| 2842 case CMP_UEQ: | 3014 case CMP_UEQ: |
| 2843 if ((fs == ft) || (std::isnan(fs) || std::isnan(ft))) { | 3015 if ((fs == ft) || (std::isnan(fs) || std::isnan(ft))) { |
| 2844 set_fpu_register_word(fd_reg(), -1); | 3016 set_fpu_register_word(fd_reg(), -1); |
| 2845 } else { | 3017 } else { |
| 2846 set_fpu_register_word(fd_reg(), 0); | 3018 set_fpu_register_word(fd_reg(), 0); |
| 2847 } | 3019 } |
| 3020 TraceRegWr(get_fpu_register_word(fd_reg())); | |
| 2848 break; | 3021 break; |
| 2849 case CMP_LT: | 3022 case CMP_LT: |
| 2850 if (fs < ft) { | 3023 if (fs < ft) { |
| 2851 set_fpu_register_word(fd_reg(), -1); | 3024 set_fpu_register_word(fd_reg(), -1); |
| 2852 } else { | 3025 } else { |
| 2853 set_fpu_register_word(fd_reg(), 0); | 3026 set_fpu_register_word(fd_reg(), 0); |
| 2854 } | 3027 } |
| 3028 TraceRegWr(get_fpu_register_word(fd_reg())); | |
| 2855 break; | 3029 break; |
| 2856 case CMP_ULT: | 3030 case CMP_ULT: |
| 2857 if ((fs < ft) || (std::isnan(fs) || std::isnan(ft))) { | 3031 if ((fs < ft) || (std::isnan(fs) || std::isnan(ft))) { |
| 2858 set_fpu_register_word(fd_reg(), -1); | 3032 set_fpu_register_word(fd_reg(), -1); |
| 2859 } else { | 3033 } else { |
| 2860 set_fpu_register_word(fd_reg(), 0); | 3034 set_fpu_register_word(fd_reg(), 0); |
| 2861 } | 3035 } |
| 3036 TraceRegWr(get_fpu_register_word(fd_reg())); | |
| 2862 break; | 3037 break; |
| 2863 case CMP_LE: | 3038 case CMP_LE: |
| 2864 if (fs <= ft) { | 3039 if (fs <= ft) { |
| 2865 set_fpu_register_word(fd_reg(), -1); | 3040 set_fpu_register_word(fd_reg(), -1); |
| 2866 } else { | 3041 } else { |
| 2867 set_fpu_register_word(fd_reg(), 0); | 3042 set_fpu_register_word(fd_reg(), 0); |
| 2868 } | 3043 } |
| 3044 TraceRegWr(get_fpu_register_word(fd_reg())); | |
| 2869 break; | 3045 break; |
| 2870 case CMP_ULE: | 3046 case CMP_ULE: |
| 2871 if ((fs <= ft) || (std::isnan(fs) || std::isnan(ft))) { | 3047 if ((fs <= ft) || (std::isnan(fs) || std::isnan(ft))) { |
| 2872 set_fpu_register_word(fd_reg(), -1); | 3048 set_fpu_register_word(fd_reg(), -1); |
| 2873 } else { | 3049 } else { |
| 2874 set_fpu_register_word(fd_reg(), 0); | 3050 set_fpu_register_word(fd_reg(), 0); |
| 2875 } | 3051 } |
| 3052 TraceRegWr(get_fpu_register_word(fd_reg())); | |
| 2876 break; | 3053 break; |
| 2877 case CMP_OR: | 3054 case CMP_OR: |
| 2878 if (!std::isnan(fs) && !std::isnan(ft)) { | 3055 if (!std::isnan(fs) && !std::isnan(ft)) { |
| 2879 set_fpu_register_word(fd_reg(), -1); | 3056 set_fpu_register_word(fd_reg(), -1); |
| 2880 } else { | 3057 } else { |
| 2881 set_fpu_register_word(fd_reg(), 0); | 3058 set_fpu_register_word(fd_reg(), 0); |
| 2882 } | 3059 } |
| 3060 TraceRegWr(get_fpu_register_word(fd_reg())); | |
| 2883 break; | 3061 break; |
| 2884 case CMP_UNE: | 3062 case CMP_UNE: |
| 2885 if ((fs != ft) || (std::isnan(fs) || std::isnan(ft))) { | 3063 if ((fs != ft) || (std::isnan(fs) || std::isnan(ft))) { |
| 2886 set_fpu_register_word(fd_reg(), -1); | 3064 set_fpu_register_word(fd_reg(), -1); |
| 2887 } else { | 3065 } else { |
| 2888 set_fpu_register_word(fd_reg(), 0); | 3066 set_fpu_register_word(fd_reg(), 0); |
| 2889 } | 3067 } |
| 3068 TraceRegWr(get_fpu_register_word(fd_reg())); | |
| 2890 break; | 3069 break; |
| 2891 case CMP_NE: | 3070 case CMP_NE: |
| 2892 if (fs != ft) { | 3071 if (fs != ft) { |
| 2893 set_fpu_register_word(fd_reg(), -1); | 3072 set_fpu_register_word(fd_reg(), -1); |
| 2894 } else { | 3073 } else { |
| 2895 set_fpu_register_word(fd_reg(), 0); | 3074 set_fpu_register_word(fd_reg(), 0); |
| 2896 } | 3075 } |
| 3076 TraceRegWr(get_fpu_register_word(fd_reg())); | |
| 2897 break; | 3077 break; |
| 2898 default: | 3078 default: |
| 2899 UNREACHABLE(); | 3079 UNREACHABLE(); |
| 2900 } | 3080 } |
| 2901 } | 3081 } |
| 2902 | 3082 |
| 2903 | 3083 |
| 2904 void Simulator::DecodeTypeRegisterSRsType() { | 3084 void Simulator::DecodeTypeRegisterSRsType() { |
| 2905 float fs, ft, fd; | 3085 float fs, ft, fd; |
| 2906 fs = get_fpu_register_float(fs_reg()); | 3086 fs = get_fpu_register_float(fs_reg()); |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2941 result = upper; | 3121 result = upper; |
| 2942 break; | 3122 break; |
| 2943 case kRoundToMinusInf: | 3123 case kRoundToMinusInf: |
| 2944 result = lower; | 3124 result = lower; |
| 2945 break; | 3125 break; |
| 2946 } | 3126 } |
| 2947 set_fpu_register_float(fd_reg(), result); | 3127 set_fpu_register_float(fd_reg(), result); |
| 2948 if (result != fs) { | 3128 if (result != fs) { |
| 2949 set_fcsr_bit(kFCSRInexactFlagBit, true); | 3129 set_fcsr_bit(kFCSRInexactFlagBit, true); |
| 2950 } | 3130 } |
| 3131 TraceRegWr(get_fpu_register_word(fd_reg()), FLOAT); | |
| 2951 break; | 3132 break; |
| 2952 } | 3133 } |
| 2953 case ADD_S: | 3134 case ADD_S: |
| 2954 set_fpu_register_float( | 3135 set_fpu_register_float( |
| 2955 fd_reg(), | 3136 fd_reg(), |
| 2956 FPUCanonalizeOperation([](float lhs, float rhs) { return lhs + rhs; }, | 3137 FPUCanonalizeOperation([](float lhs, float rhs) { return lhs + rhs; }, |
| 2957 fs, ft)); | 3138 fs, ft)); |
| 3139 TraceRegWr(get_fpu_register_word(fd_reg()), FLOAT); | |
| 2958 break; | 3140 break; |
| 2959 case SUB_S: | 3141 case SUB_S: |
| 2960 set_fpu_register_float( | 3142 set_fpu_register_float( |
| 2961 fd_reg(), | 3143 fd_reg(), |
| 2962 FPUCanonalizeOperation([](float lhs, float rhs) { return lhs - rhs; }, | 3144 FPUCanonalizeOperation([](float lhs, float rhs) { return lhs - rhs; }, |
| 2963 fs, ft)); | 3145 fs, ft)); |
| 3146 TraceRegWr(get_fpu_register_word(fd_reg()), FLOAT); | |
| 2964 break; | 3147 break; |
| 2965 case MADDF_S: | 3148 case MADDF_S: |
| 2966 DCHECK(IsMipsArchVariant(kMips32r6)); | 3149 DCHECK(IsMipsArchVariant(kMips32r6)); |
| 2967 set_fpu_register_float(fd_reg(), std::fma(fs, ft, fd)); | 3150 set_fpu_register_float(fd_reg(), std::fma(fs, ft, fd)); |
| 3151 TraceRegWr(get_fpu_register_word(fd_reg()), FLOAT); | |
| 2968 break; | 3152 break; |
| 2969 case MSUBF_S: | 3153 case MSUBF_S: |
| 2970 DCHECK(IsMipsArchVariant(kMips32r6)); | 3154 DCHECK(IsMipsArchVariant(kMips32r6)); |
| 2971 set_fpu_register_float(fd_reg(), std::fma(-fs, ft, fd)); | 3155 set_fpu_register_float(fd_reg(), std::fma(-fs, ft, fd)); |
| 3156 TraceRegWr(get_fpu_register_word(fd_reg()), FLOAT); | |
| 2972 break; | 3157 break; |
| 2973 case MUL_S: | 3158 case MUL_S: |
| 2974 set_fpu_register_float( | 3159 set_fpu_register_float( |
| 2975 fd_reg(), | 3160 fd_reg(), |
| 2976 FPUCanonalizeOperation([](float lhs, float rhs) { return lhs * rhs; }, | 3161 FPUCanonalizeOperation([](float lhs, float rhs) { return lhs * rhs; }, |
| 2977 fs, ft)); | 3162 fs, ft)); |
| 3163 TraceRegWr(get_fpu_register_word(fd_reg()), FLOAT); | |
| 2978 break; | 3164 break; |
| 2979 case DIV_S: | 3165 case DIV_S: |
| 2980 set_fpu_register_float( | 3166 set_fpu_register_float( |
| 2981 fd_reg(), | 3167 fd_reg(), |
| 2982 FPUCanonalizeOperation([](float lhs, float rhs) { return lhs / rhs; }, | 3168 FPUCanonalizeOperation([](float lhs, float rhs) { return lhs / rhs; }, |
| 2983 fs, ft)); | 3169 fs, ft)); |
| 3170 TraceRegWr(get_fpu_register_word(fd_reg()), FLOAT); | |
| 2984 break; | 3171 break; |
| 2985 case ABS_S: | 3172 case ABS_S: |
| 2986 set_fpu_register_float( | 3173 set_fpu_register_float( |
| 2987 fd_reg(), | 3174 fd_reg(), |
| 2988 FPUCanonalizeOperation([](float fs) { return FPAbs(fs); }, fs)); | 3175 FPUCanonalizeOperation([](float fs) { return FPAbs(fs); }, fs)); |
| 3176 TraceRegWr(get_fpu_register_word(fd_reg()), FLOAT); | |
| 2989 break; | 3177 break; |
| 2990 case MOV_S: | 3178 case MOV_S: |
| 2991 set_fpu_register_float(fd_reg(), fs); | 3179 set_fpu_register_float(fd_reg(), fs); |
| 3180 TraceRegWr(get_fpu_register_word(fd_reg()), FLOAT); | |
| 2992 break; | 3181 break; |
| 2993 case NEG_S: | 3182 case NEG_S: |
| 2994 set_fpu_register_float( | 3183 set_fpu_register_float( |
| 2995 fd_reg(), FPUCanonalizeOperation([](float src) { return -src; }, | 3184 fd_reg(), FPUCanonalizeOperation([](float src) { return -src; }, |
| 2996 KeepSign::yes, fs)); | 3185 KeepSign::yes, fs)); |
| 3186 TraceRegWr(get_fpu_register_word(fd_reg()), FLOAT); | |
| 2997 break; | 3187 break; |
| 2998 case SQRT_S: | 3188 case SQRT_S: |
| 2999 set_fpu_register_float( | 3189 set_fpu_register_float( |
| 3000 fd_reg(), | 3190 fd_reg(), |
| 3001 FPUCanonalizeOperation([](float src) { return std::sqrt(src); }, fs)); | 3191 FPUCanonalizeOperation([](float src) { return std::sqrt(src); }, fs)); |
| 3192 TraceRegWr(get_fpu_register_word(fd_reg()), FLOAT); | |
| 3002 break; | 3193 break; |
| 3003 case RSQRT_S: | 3194 case RSQRT_S: |
| 3004 set_fpu_register_float( | 3195 set_fpu_register_float( |
| 3005 fd_reg(), FPUCanonalizeOperation( | 3196 fd_reg(), FPUCanonalizeOperation( |
| 3006 [](float src) { return 1.0 / std::sqrt(src); }, fs)); | 3197 [](float src) { return 1.0 / std::sqrt(src); }, fs)); |
| 3198 TraceRegWr(get_fpu_register_word(fd_reg()), FLOAT); | |
| 3007 break; | 3199 break; |
| 3008 case RECIP_S: | 3200 case RECIP_S: |
| 3009 set_fpu_register_float( | 3201 set_fpu_register_float( |
| 3010 fd_reg(), | 3202 fd_reg(), |
| 3011 FPUCanonalizeOperation([](float src) { return 1.0 / src; }, fs)); | 3203 FPUCanonalizeOperation([](float src) { return 1.0 / src; }, fs)); |
| 3204 TraceRegWr(get_fpu_register_word(fd_reg()), FLOAT); | |
| 3012 break; | 3205 break; |
| 3013 case C_F_D: | 3206 case C_F_D: |
| 3014 set_fcsr_bit(fcsr_cc, false); | 3207 set_fcsr_bit(fcsr_cc, false); |
| 3208 TraceRegWr(test_fcsr_bit(fcsr_cc)); | |
| 3015 break; | 3209 break; |
| 3016 case C_UN_D: | 3210 case C_UN_D: |
| 3017 set_fcsr_bit(fcsr_cc, std::isnan(fs) || std::isnan(ft)); | 3211 set_fcsr_bit(fcsr_cc, std::isnan(fs) || std::isnan(ft)); |
| 3212 TraceRegWr(test_fcsr_bit(fcsr_cc)); | |
| 3018 break; | 3213 break; |
| 3019 case C_EQ_D: | 3214 case C_EQ_D: |
| 3020 set_fcsr_bit(fcsr_cc, (fs == ft)); | 3215 set_fcsr_bit(fcsr_cc, (fs == ft)); |
| 3216 TraceRegWr(test_fcsr_bit(fcsr_cc)); | |
| 3021 break; | 3217 break; |
| 3022 case C_UEQ_D: | 3218 case C_UEQ_D: |
| 3023 set_fcsr_bit(fcsr_cc, (fs == ft) || (std::isnan(fs) || std::isnan(ft))); | 3219 set_fcsr_bit(fcsr_cc, (fs == ft) || (std::isnan(fs) || std::isnan(ft))); |
| 3220 TraceRegWr(test_fcsr_bit(fcsr_cc)); | |
| 3024 break; | 3221 break; |
| 3025 case C_OLT_D: | 3222 case C_OLT_D: |
| 3026 set_fcsr_bit(fcsr_cc, (fs < ft)); | 3223 set_fcsr_bit(fcsr_cc, (fs < ft)); |
| 3224 TraceRegWr(test_fcsr_bit(fcsr_cc)); | |
| 3027 break; | 3225 break; |
| 3028 case C_ULT_D: | 3226 case C_ULT_D: |
| 3029 set_fcsr_bit(fcsr_cc, (fs < ft) || (std::isnan(fs) || std::isnan(ft))); | 3227 set_fcsr_bit(fcsr_cc, (fs < ft) || (std::isnan(fs) || std::isnan(ft))); |
| 3228 TraceRegWr(test_fcsr_bit(fcsr_cc)); | |
| 3030 break; | 3229 break; |
| 3031 case C_OLE_D: | 3230 case C_OLE_D: |
| 3032 set_fcsr_bit(fcsr_cc, (fs <= ft)); | 3231 set_fcsr_bit(fcsr_cc, (fs <= ft)); |
| 3232 TraceRegWr(test_fcsr_bit(fcsr_cc)); | |
| 3033 break; | 3233 break; |
| 3034 case C_ULE_D: | 3234 case C_ULE_D: |
| 3035 set_fcsr_bit(fcsr_cc, (fs <= ft) || (std::isnan(fs) || std::isnan(ft))); | 3235 set_fcsr_bit(fcsr_cc, (fs <= ft) || (std::isnan(fs) || std::isnan(ft))); |
| 3236 TraceRegWr(test_fcsr_bit(fcsr_cc)); | |
| 3036 break; | 3237 break; |
| 3037 case CVT_D_S: | 3238 case CVT_D_S: |
| 3038 set_fpu_register_double(fd_reg(), static_cast<double>(fs)); | 3239 set_fpu_register_double(fd_reg(), static_cast<double>(fs)); |
| 3240 TraceRegWr(get_fpu_register(fd_reg()), DOUBLE); | |
| 3039 break; | 3241 break; |
| 3040 case SEL: | 3242 case SEL: |
| 3041 DCHECK(IsMipsArchVariant(kMips32r6)); | 3243 DCHECK(IsMipsArchVariant(kMips32r6)); |
| 3042 set_fpu_register_float(fd_reg(), (fd_int & 0x1) == 0 ? fs : ft); | 3244 set_fpu_register_float(fd_reg(), (fd_int & 0x1) == 0 ? fs : ft); |
| 3245 TraceRegWr(get_fpu_register_word(fd_reg()), FLOAT); | |
| 3043 break; | 3246 break; |
| 3044 case CLASS_S: { // Mips32r6 instruction | 3247 case CLASS_S: { // Mips32r6 instruction |
| 3045 // Convert float input to uint32_t for easier bit manipulation | 3248 // Convert float input to uint32_t for easier bit manipulation |
| 3046 float fs = get_fpu_register_float(fs_reg()); | 3249 float fs = get_fpu_register_float(fs_reg()); |
| 3047 uint32_t classed = bit_cast<uint32_t>(fs); | 3250 uint32_t classed = bit_cast<uint32_t>(fs); |
| 3048 | 3251 |
| 3049 // Extracting sign, exponent and mantissa from the input float | 3252 // Extracting sign, exponent and mantissa from the input float |
| 3050 uint32_t sign = (classed >> 31) & 1; | 3253 uint32_t sign = (classed >> 31) & 1; |
| 3051 uint32_t exponent = (classed >> 23) & 0x000000ff; | 3254 uint32_t exponent = (classed >> 23) & 0x000000ff; |
| 3052 uint32_t mantissa = classed & 0x007fffff; | 3255 uint32_t mantissa = classed & 0x007fffff; |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3097 | 3300 |
| 3098 // Calculating result according to description of CLASS.S instruction | 3301 // Calculating result according to description of CLASS.S instruction |
| 3099 result = (posZero << 9) | (posSubnorm << 8) | (posNorm << 7) | | 3302 result = (posZero << 9) | (posSubnorm << 8) | (posNorm << 7) | |
| 3100 (posInf << 6) | (negZero << 5) | (negSubnorm << 4) | | 3303 (posInf << 6) | (negZero << 5) | (negSubnorm << 4) | |
| 3101 (negNorm << 3) | (negInf << 2) | (quietNan << 1) | signalingNan; | 3304 (negNorm << 3) | (negInf << 2) | (quietNan << 1) | signalingNan; |
| 3102 | 3305 |
| 3103 DCHECK(result != 0); | 3306 DCHECK(result != 0); |
| 3104 | 3307 |
| 3105 fResult = bit_cast<float>(result); | 3308 fResult = bit_cast<float>(result); |
| 3106 set_fpu_register_float(fd_reg(), fResult); | 3309 set_fpu_register_float(fd_reg(), fResult); |
| 3310 TraceRegWr(get_fpu_register_word(fd_reg()), FLOAT); | |
| 3107 | 3311 |
| 3108 break; | 3312 break; |
| 3109 } | 3313 } |
| 3110 case SELEQZ_C: | 3314 case SELEQZ_C: |
| 3111 DCHECK(IsMipsArchVariant(kMips32r6)); | 3315 DCHECK(IsMipsArchVariant(kMips32r6)); |
| 3112 set_fpu_register_float(fd_reg(), (ft_int & 0x1) == 0 | 3316 set_fpu_register_float(fd_reg(), (ft_int & 0x1) == 0 |
| 3113 ? get_fpu_register_float(fs_reg()) | 3317 ? get_fpu_register_float(fs_reg()) |
| 3114 : 0.0); | 3318 : 0.0); |
| 3319 TraceRegWr(get_fpu_register_word(fd_reg()), FLOAT); | |
| 3115 break; | 3320 break; |
| 3116 case SELNEZ_C: | 3321 case SELNEZ_C: |
| 3117 DCHECK(IsMipsArchVariant(kMips32r6)); | 3322 DCHECK(IsMipsArchVariant(kMips32r6)); |
| 3118 set_fpu_register_float(fd_reg(), (ft_int & 0x1) != 0 | 3323 set_fpu_register_float(fd_reg(), (ft_int & 0x1) != 0 |
| 3119 ? get_fpu_register_float(fs_reg()) | 3324 ? get_fpu_register_float(fs_reg()) |
| 3120 : 0.0); | 3325 : 0.0); |
| 3326 TraceRegWr(get_fpu_register_word(fd_reg()), FLOAT); | |
| 3121 break; | 3327 break; |
| 3122 case MOVZ_C: { | 3328 case MOVZ_C: { |
| 3123 DCHECK(IsMipsArchVariant(kMips32r2)); | 3329 DCHECK(IsMipsArchVariant(kMips32r2)); |
| 3124 if (rt() == 0) { | 3330 if (rt() == 0) { |
| 3125 set_fpu_register_float(fd_reg(), fs); | 3331 set_fpu_register_float(fd_reg(), fs); |
| 3126 } | 3332 } |
| 3333 TraceRegWr(get_fpu_register_word(fd_reg()), FLOAT); | |
| 3127 break; | 3334 break; |
| 3128 } | 3335 } |
| 3129 case MOVN_C: { | 3336 case MOVN_C: { |
| 3130 DCHECK(IsMipsArchVariant(kMips32r2)); | 3337 DCHECK(IsMipsArchVariant(kMips32r2)); |
| 3131 if (rt() != 0) { | 3338 if (rt() != 0) { |
| 3132 set_fpu_register_float(fd_reg(), fs); | 3339 set_fpu_register_float(fd_reg(), fs); |
| 3133 } | 3340 } |
| 3341 TraceRegWr(get_fpu_register_word(fd_reg()), FLOAT); | |
| 3134 break; | 3342 break; |
| 3135 } | 3343 } |
| 3136 case MOVF: { | 3344 case MOVF: { |
| 3137 // Same function field for MOVT.D and MOVF.D | 3345 // Same function field for MOVT.D and MOVF.D |
| 3138 uint32_t ft_cc = (ft_reg() >> 2) & 0x7; | 3346 uint32_t ft_cc = (ft_reg() >> 2) & 0x7; |
| 3139 ft_cc = get_fcsr_condition_bit(ft_cc); | 3347 ft_cc = get_fcsr_condition_bit(ft_cc); |
| 3140 | 3348 |
| 3141 if (instr_.Bit(16)) { // Read Tf bit. | 3349 if (instr_.Bit(16)) { // Read Tf bit. |
| 3142 // MOVT.D | 3350 // MOVT.D |
| 3143 if (test_fcsr_bit(ft_cc)) set_fpu_register_float(fd_reg(), fs); | 3351 if (test_fcsr_bit(ft_cc)) set_fpu_register_float(fd_reg(), fs); |
| 3144 } else { | 3352 } else { |
| 3145 // MOVF.D | 3353 // MOVF.D |
| 3146 if (!test_fcsr_bit(ft_cc)) set_fpu_register_float(fd_reg(), fs); | 3354 if (!test_fcsr_bit(ft_cc)) set_fpu_register_float(fd_reg(), fs); |
| 3147 } | 3355 } |
| 3356 TraceRegWr(get_fpu_register_word(fd_reg()), FLOAT); | |
| 3148 break; | 3357 break; |
| 3149 } | 3358 } |
| 3150 case TRUNC_W_S: { // Truncate single to word (round towards 0). | 3359 case TRUNC_W_S: { // Truncate single to word (round towards 0). |
| 3151 float rounded = trunc(fs); | 3360 float rounded = trunc(fs); |
| 3152 int32_t result = static_cast<int32_t>(rounded); | 3361 int32_t result = static_cast<int32_t>(rounded); |
| 3153 set_fpu_register_word(fd_reg(), result); | 3362 set_fpu_register_word(fd_reg(), result); |
| 3154 if (set_fcsr_round_error(fs, rounded)) { | 3363 if (set_fcsr_round_error(fs, rounded)) { |
| 3155 set_fpu_register_word_invalid_result(fs, rounded); | 3364 set_fpu_register_word_invalid_result(fs, rounded); |
| 3156 } | 3365 } |
| 3366 TraceRegWr(get_fpu_register_word(fd_reg())); | |
| 3157 } break; | 3367 } break; |
| 3158 case TRUNC_L_S: { // Mips32r2 instruction. | 3368 case TRUNC_L_S: { // Mips32r2 instruction. |
| 3159 DCHECK(IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)); | 3369 DCHECK(IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)); |
| 3160 float rounded = trunc(fs); | 3370 float rounded = trunc(fs); |
| 3161 int64_t i64 = static_cast<int64_t>(rounded); | 3371 int64_t i64 = static_cast<int64_t>(rounded); |
| 3162 if (IsFp64Mode()) { | 3372 if (IsFp64Mode()) { |
| 3163 set_fpu_register(fd_reg(), i64); | 3373 set_fpu_register(fd_reg(), i64); |
| 3164 if (set_fcsr_round64_error(fs, rounded)) { | 3374 if (set_fcsr_round64_error(fs, rounded)) { |
| 3165 set_fpu_register_invalid_result64(fs, rounded); | 3375 set_fpu_register_invalid_result64(fs, rounded); |
| 3166 } | 3376 } |
| 3377 TraceRegWr(get_fpu_register(fd_reg())); | |
| 3167 } else { | 3378 } else { |
| 3168 UNSUPPORTED(); | 3379 UNSUPPORTED(); |
| 3169 } | 3380 } |
| 3170 break; | 3381 break; |
| 3171 } | 3382 } |
| 3172 case FLOOR_W_S: // Round double to word towards negative infinity. | 3383 case FLOOR_W_S: // Round double to word towards negative infinity. |
| 3173 { | 3384 { |
| 3174 float rounded = std::floor(fs); | 3385 float rounded = std::floor(fs); |
| 3175 int32_t result = static_cast<int32_t>(rounded); | 3386 int32_t result = static_cast<int32_t>(rounded); |
| 3176 set_fpu_register_word(fd_reg(), result); | 3387 set_fpu_register_word(fd_reg(), result); |
| 3177 if (set_fcsr_round_error(fs, rounded)) { | 3388 if (set_fcsr_round_error(fs, rounded)) { |
| 3178 set_fpu_register_word_invalid_result(fs, rounded); | 3389 set_fpu_register_word_invalid_result(fs, rounded); |
| 3179 } | 3390 } |
| 3391 TraceRegWr(get_fpu_register_word(fd_reg())); | |
| 3180 } break; | 3392 } break; |
| 3181 case FLOOR_L_S: { // Mips32r2 instruction. | 3393 case FLOOR_L_S: { // Mips32r2 instruction. |
| 3182 DCHECK(IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)); | 3394 DCHECK(IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)); |
| 3183 float rounded = std::floor(fs); | 3395 float rounded = std::floor(fs); |
| 3184 int64_t i64 = static_cast<int64_t>(rounded); | 3396 int64_t i64 = static_cast<int64_t>(rounded); |
| 3185 if (IsFp64Mode()) { | 3397 if (IsFp64Mode()) { |
| 3186 set_fpu_register(fd_reg(), i64); | 3398 set_fpu_register(fd_reg(), i64); |
| 3187 if (set_fcsr_round64_error(fs, rounded)) { | 3399 if (set_fcsr_round64_error(fs, rounded)) { |
| 3188 set_fpu_register_invalid_result64(fs, rounded); | 3400 set_fpu_register_invalid_result64(fs, rounded); |
| 3189 } | 3401 } |
| 3402 TraceRegWr(get_fpu_register(fd_reg())); | |
| 3190 } else { | 3403 } else { |
| 3191 UNSUPPORTED(); | 3404 UNSUPPORTED(); |
| 3192 } | 3405 } |
| 3193 break; | 3406 break; |
| 3194 } | 3407 } |
| 3195 case ROUND_W_S: { | 3408 case ROUND_W_S: { |
| 3196 float rounded = std::floor(fs + 0.5); | 3409 float rounded = std::floor(fs + 0.5); |
| 3197 int32_t result = static_cast<int32_t>(rounded); | 3410 int32_t result = static_cast<int32_t>(rounded); |
| 3198 if ((result & 1) != 0 && result - fs == 0.5) { | 3411 if ((result & 1) != 0 && result - fs == 0.5) { |
| 3199 // If the number is halfway between two integers, | 3412 // If the number is halfway between two integers, |
| 3200 // round to the even one. | 3413 // round to the even one. |
| 3201 result--; | 3414 result--; |
| 3202 } | 3415 } |
| 3203 set_fpu_register_word(fd_reg(), result); | 3416 set_fpu_register_word(fd_reg(), result); |
| 3204 if (set_fcsr_round_error(fs, rounded)) { | 3417 if (set_fcsr_round_error(fs, rounded)) { |
| 3205 set_fpu_register_word_invalid_result(fs, rounded); | 3418 set_fpu_register_word_invalid_result(fs, rounded); |
| 3206 } | 3419 } |
| 3420 TraceRegWr(get_fpu_register_word(fd_reg())); | |
| 3207 break; | 3421 break; |
| 3208 } | 3422 } |
| 3209 case ROUND_L_S: { // Mips32r2 instruction. | 3423 case ROUND_L_S: { // Mips32r2 instruction. |
| 3210 DCHECK(IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)); | 3424 DCHECK(IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)); |
| 3211 float rounded = std::floor(fs + 0.5); | 3425 float rounded = std::floor(fs + 0.5); |
| 3212 int64_t result = static_cast<int64_t>(rounded); | 3426 int64_t result = static_cast<int64_t>(rounded); |
| 3213 if ((result & 1) != 0 && result - fs == 0.5) { | 3427 if ((result & 1) != 0 && result - fs == 0.5) { |
| 3214 // If the number is halfway between two integers, | 3428 // If the number is halfway between two integers, |
| 3215 // round to the even one. | 3429 // round to the even one. |
| 3216 result--; | 3430 result--; |
| 3217 } | 3431 } |
| 3218 int64_t i64 = static_cast<int64_t>(result); | 3432 int64_t i64 = static_cast<int64_t>(result); |
| 3219 if (IsFp64Mode()) { | 3433 if (IsFp64Mode()) { |
| 3220 set_fpu_register(fd_reg(), i64); | 3434 set_fpu_register(fd_reg(), i64); |
| 3221 if (set_fcsr_round64_error(fs, rounded)) { | 3435 if (set_fcsr_round64_error(fs, rounded)) { |
| 3222 set_fpu_register_invalid_result64(fs, rounded); | 3436 set_fpu_register_invalid_result64(fs, rounded); |
| 3223 } | 3437 } |
| 3438 TraceRegWr(get_fpu_register(fd_reg())); | |
| 3224 } else { | 3439 } else { |
| 3225 UNSUPPORTED(); | 3440 UNSUPPORTED(); |
| 3226 } | 3441 } |
| 3227 break; | 3442 break; |
| 3228 } | 3443 } |
| 3229 case CEIL_W_S: // Round double to word towards positive infinity. | 3444 case CEIL_W_S: // Round double to word towards positive infinity. |
| 3230 { | 3445 { |
| 3231 float rounded = std::ceil(fs); | 3446 float rounded = std::ceil(fs); |
| 3232 int32_t result = static_cast<int32_t>(rounded); | 3447 int32_t result = static_cast<int32_t>(rounded); |
| 3233 set_fpu_register_word(fd_reg(), result); | 3448 set_fpu_register_word(fd_reg(), result); |
| 3234 if (set_fcsr_round_error(fs, rounded)) { | 3449 if (set_fcsr_round_error(fs, rounded)) { |
| 3235 set_fpu_register_word_invalid_result(fs, rounded); | 3450 set_fpu_register_word_invalid_result(fs, rounded); |
| 3236 } | 3451 } |
| 3452 TraceRegWr(get_fpu_register_word(fd_reg())); | |
| 3237 } break; | 3453 } break; |
| 3238 case CEIL_L_S: { // Mips32r2 instruction. | 3454 case CEIL_L_S: { // Mips32r2 instruction. |
| 3239 DCHECK(IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)); | 3455 DCHECK(IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)); |
| 3240 float rounded = std::ceil(fs); | 3456 float rounded = std::ceil(fs); |
| 3241 int64_t i64 = static_cast<int64_t>(rounded); | 3457 int64_t i64 = static_cast<int64_t>(rounded); |
| 3242 if (IsFp64Mode()) { | 3458 if (IsFp64Mode()) { |
| 3243 set_fpu_register(fd_reg(), i64); | 3459 set_fpu_register(fd_reg(), i64); |
| 3244 if (set_fcsr_round64_error(fs, rounded)) { | 3460 if (set_fcsr_round64_error(fs, rounded)) { |
| 3245 set_fpu_register_invalid_result64(fs, rounded); | 3461 set_fpu_register_invalid_result64(fs, rounded); |
| 3246 } | 3462 } |
| 3463 TraceRegWr(get_fpu_register(fd_reg())); | |
| 3247 } else { | 3464 } else { |
| 3248 UNSUPPORTED(); | 3465 UNSUPPORTED(); |
| 3249 } | 3466 } |
| 3250 break; | 3467 break; |
| 3251 } | 3468 } |
| 3252 case MIN: | 3469 case MIN: |
| 3253 DCHECK(IsMipsArchVariant(kMips32r6)); | 3470 DCHECK(IsMipsArchVariant(kMips32r6)); |
| 3254 set_fpu_register_float(fd_reg(), FPUMin(ft, fs)); | 3471 set_fpu_register_float(fd_reg(), FPUMin(ft, fs)); |
| 3472 TraceRegWr(get_fpu_register_word(fd_reg()), FLOAT); | |
| 3255 break; | 3473 break; |
| 3256 case MAX: | 3474 case MAX: |
| 3257 DCHECK(IsMipsArchVariant(kMips32r6)); | 3475 DCHECK(IsMipsArchVariant(kMips32r6)); |
| 3258 set_fpu_register_float(fd_reg(), FPUMax(ft, fs)); | 3476 set_fpu_register_float(fd_reg(), FPUMax(ft, fs)); |
| 3477 TraceRegWr(get_fpu_register_word(fd_reg()), FLOAT); | |
| 3259 break; | 3478 break; |
| 3260 case MINA: | 3479 case MINA: |
| 3261 DCHECK(IsMipsArchVariant(kMips32r6)); | 3480 DCHECK(IsMipsArchVariant(kMips32r6)); |
| 3262 set_fpu_register_float(fd_reg(), FPUMinA(ft, fs)); | 3481 set_fpu_register_float(fd_reg(), FPUMinA(ft, fs)); |
| 3482 TraceRegWr(get_fpu_register_word(fd_reg()), FLOAT); | |
| 3263 break; | 3483 break; |
| 3264 case MAXA: | 3484 case MAXA: |
| 3265 DCHECK(IsMipsArchVariant(kMips32r6)); | 3485 DCHECK(IsMipsArchVariant(kMips32r6)); |
| 3266 set_fpu_register_float(fd_reg(), FPUMaxA(ft, fs)); | 3486 set_fpu_register_float(fd_reg(), FPUMaxA(ft, fs)); |
| 3487 TraceRegWr(get_fpu_register_word(fd_reg()), FLOAT); | |
| 3267 break; | 3488 break; |
| 3268 case CVT_L_S: { | 3489 case CVT_L_S: { |
| 3269 if (IsFp64Mode()) { | 3490 if (IsFp64Mode()) { |
| 3270 int64_t result; | 3491 int64_t result; |
| 3271 float rounded; | 3492 float rounded; |
| 3272 round64_according_to_fcsr(fs, rounded, result, fs); | 3493 round64_according_to_fcsr(fs, rounded, result, fs); |
| 3273 set_fpu_register(fd_reg(), result); | 3494 set_fpu_register(fd_reg(), result); |
| 3274 if (set_fcsr_round64_error(fs, rounded)) { | 3495 if (set_fcsr_round64_error(fs, rounded)) { |
| 3275 set_fpu_register_invalid_result64(fs, rounded); | 3496 set_fpu_register_invalid_result64(fs, rounded); |
| 3276 } | 3497 } |
| 3498 TraceRegWr(get_fpu_register(fd_reg())); | |
| 3277 } else { | 3499 } else { |
| 3278 UNSUPPORTED(); | 3500 UNSUPPORTED(); |
| 3279 } | 3501 } |
| 3280 break; | 3502 break; |
| 3281 } | 3503 } |
| 3282 case CVT_W_S: { | 3504 case CVT_W_S: { |
| 3283 float rounded; | 3505 float rounded; |
| 3284 int32_t result; | 3506 int32_t result; |
| 3285 round_according_to_fcsr(fs, rounded, result, fs); | 3507 round_according_to_fcsr(fs, rounded, result, fs); |
| 3286 set_fpu_register_word(fd_reg(), result); | 3508 set_fpu_register_word(fd_reg(), result); |
| 3287 if (set_fcsr_round_error(fs, rounded)) { | 3509 if (set_fcsr_round_error(fs, rounded)) { |
| 3288 set_fpu_register_word_invalid_result(fs, rounded); | 3510 set_fpu_register_word_invalid_result(fs, rounded); |
| 3289 } | 3511 } |
| 3512 TraceRegWr(get_fpu_register_word(fd_reg())); | |
| 3290 break; | 3513 break; |
| 3291 } | 3514 } |
| 3292 default: | 3515 default: |
| 3293 // CVT_W_S CVT_L_S ROUND_W_S ROUND_L_S FLOOR_W_S FLOOR_L_S | 3516 // 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. | 3517 // CEIL_W_S CEIL_L_S CVT_PS_S are unimplemented. |
| 3295 UNREACHABLE(); | 3518 UNREACHABLE(); |
| 3296 } | 3519 } |
| 3297 } | 3520 } |
| 3298 | 3521 |
| 3299 | 3522 |
| 3300 void Simulator::DecodeTypeRegisterLRsType() { | 3523 void Simulator::DecodeTypeRegisterLRsType() { |
| 3301 double fs = get_fpu_register_double(fs_reg()); | 3524 double fs = get_fpu_register_double(fs_reg()); |
| 3302 double ft = get_fpu_register_double(ft_reg()); | 3525 double ft = get_fpu_register_double(ft_reg()); |
| 3303 switch (instr_.FunctionFieldRaw()) { | 3526 switch (instr_.FunctionFieldRaw()) { |
| 3304 case CVT_D_L: // Mips32r2 instruction. | 3527 case CVT_D_L: // Mips32r2 instruction. |
| 3305 // Watch the signs here, we want 2 32-bit vals | 3528 // Watch the signs here, we want 2 32-bit vals |
| 3306 // to make a sign-64. | 3529 // to make a sign-64. |
| 3307 int64_t i64; | 3530 int64_t i64; |
| 3308 if (IsFp64Mode()) { | 3531 if (IsFp64Mode()) { |
| 3309 i64 = get_fpu_register(fs_reg()); | 3532 i64 = get_fpu_register(fs_reg()); |
| 3310 } else { | 3533 } else { |
| 3311 i64 = static_cast<uint32_t>(get_fpu_register_word(fs_reg())); | 3534 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; | 3535 i64 |= static_cast<int64_t>(get_fpu_register_word(fs_reg() + 1)) << 32; |
| 3313 } | 3536 } |
| 3314 set_fpu_register_double(fd_reg(), static_cast<double>(i64)); | 3537 set_fpu_register_double(fd_reg(), static_cast<double>(i64)); |
| 3538 TraceRegWr(get_fpu_register(fd_reg()), DOUBLE); | |
| 3315 break; | 3539 break; |
| 3316 case CVT_S_L: | 3540 case CVT_S_L: |
| 3317 if (IsFp64Mode()) { | 3541 if (IsFp64Mode()) { |
| 3318 i64 = get_fpu_register(fs_reg()); | 3542 i64 = get_fpu_register(fs_reg()); |
| 3319 } else { | 3543 } else { |
| 3320 i64 = static_cast<uint32_t>(get_fpu_register_word(fs_reg())); | 3544 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; | 3545 i64 |= static_cast<int64_t>(get_fpu_register_word(fs_reg() + 1)) << 32; |
| 3322 } | 3546 } |
| 3323 set_fpu_register_float(fd_reg(), static_cast<float>(i64)); | 3547 set_fpu_register_float(fd_reg(), static_cast<float>(i64)); |
| 3548 TraceRegWr(get_fpu_register_word(fd_reg()), FLOAT); | |
| 3324 break; | 3549 break; |
| 3325 case CMP_AF: // Mips64r6 CMP.D instructions. | 3550 case CMP_AF: // Mips64r6 CMP.D instructions. |
| 3326 set_fpu_register(fd_reg(), 0); | 3551 set_fpu_register(fd_reg(), 0); |
| 3552 TraceRegWr(get_fpu_register(fd_reg())); | |
| 3327 break; | 3553 break; |
| 3328 case CMP_UN: | 3554 case CMP_UN: |
| 3329 if (std::isnan(fs) || std::isnan(ft)) { | 3555 if (std::isnan(fs) || std::isnan(ft)) { |
| 3330 set_fpu_register(fd_reg(), -1); | 3556 set_fpu_register(fd_reg(), -1); |
| 3331 } else { | 3557 } else { |
| 3332 set_fpu_register(fd_reg(), 0); | 3558 set_fpu_register(fd_reg(), 0); |
| 3333 } | 3559 } |
| 3560 TraceRegWr(get_fpu_register(fd_reg())); | |
| 3334 break; | 3561 break; |
| 3335 case CMP_EQ: | 3562 case CMP_EQ: |
| 3336 if (fs == ft) { | 3563 if (fs == ft) { |
| 3337 set_fpu_register(fd_reg(), -1); | 3564 set_fpu_register(fd_reg(), -1); |
| 3338 } else { | 3565 } else { |
| 3339 set_fpu_register(fd_reg(), 0); | 3566 set_fpu_register(fd_reg(), 0); |
| 3340 } | 3567 } |
| 3568 TraceRegWr(get_fpu_register(fd_reg())); | |
| 3341 break; | 3569 break; |
| 3342 case CMP_UEQ: | 3570 case CMP_UEQ: |
| 3343 if ((fs == ft) || (std::isnan(fs) || std::isnan(ft))) { | 3571 if ((fs == ft) || (std::isnan(fs) || std::isnan(ft))) { |
| 3344 set_fpu_register(fd_reg(), -1); | 3572 set_fpu_register(fd_reg(), -1); |
| 3345 } else { | 3573 } else { |
| 3346 set_fpu_register(fd_reg(), 0); | 3574 set_fpu_register(fd_reg(), 0); |
| 3347 } | 3575 } |
| 3576 TraceRegWr(get_fpu_register(fd_reg())); | |
| 3348 break; | 3577 break; |
| 3349 case CMP_LT: | 3578 case CMP_LT: |
| 3350 if (fs < ft) { | 3579 if (fs < ft) { |
| 3351 set_fpu_register(fd_reg(), -1); | 3580 set_fpu_register(fd_reg(), -1); |
| 3352 } else { | 3581 } else { |
| 3353 set_fpu_register(fd_reg(), 0); | 3582 set_fpu_register(fd_reg(), 0); |
| 3354 } | 3583 } |
| 3584 TraceRegWr(get_fpu_register(fd_reg())); | |
| 3355 break; | 3585 break; |
| 3356 case CMP_ULT: | 3586 case CMP_ULT: |
| 3357 if ((fs < ft) || (std::isnan(fs) || std::isnan(ft))) { | 3587 if ((fs < ft) || (std::isnan(fs) || std::isnan(ft))) { |
| 3358 set_fpu_register(fd_reg(), -1); | 3588 set_fpu_register(fd_reg(), -1); |
| 3359 } else { | 3589 } else { |
| 3360 set_fpu_register(fd_reg(), 0); | 3590 set_fpu_register(fd_reg(), 0); |
| 3361 } | 3591 } |
| 3592 TraceRegWr(get_fpu_register(fd_reg())); | |
| 3362 break; | 3593 break; |
| 3363 case CMP_LE: | 3594 case CMP_LE: |
| 3364 if (fs <= ft) { | 3595 if (fs <= ft) { |
| 3365 set_fpu_register(fd_reg(), -1); | 3596 set_fpu_register(fd_reg(), -1); |
| 3366 } else { | 3597 } else { |
| 3367 set_fpu_register(fd_reg(), 0); | 3598 set_fpu_register(fd_reg(), 0); |
| 3368 } | 3599 } |
| 3600 TraceRegWr(get_fpu_register(fd_reg())); | |
| 3369 break; | 3601 break; |
| 3370 case CMP_ULE: | 3602 case CMP_ULE: |
| 3371 if ((fs <= ft) || (std::isnan(fs) || std::isnan(ft))) { | 3603 if ((fs <= ft) || (std::isnan(fs) || std::isnan(ft))) { |
| 3372 set_fpu_register(fd_reg(), -1); | 3604 set_fpu_register(fd_reg(), -1); |
| 3373 } else { | 3605 } else { |
| 3374 set_fpu_register(fd_reg(), 0); | 3606 set_fpu_register(fd_reg(), 0); |
| 3375 } | 3607 } |
| 3608 TraceRegWr(get_fpu_register(fd_reg())); | |
| 3376 break; | 3609 break; |
| 3377 case CMP_OR: | 3610 case CMP_OR: |
| 3378 if (!std::isnan(fs) && !std::isnan(ft)) { | 3611 if (!std::isnan(fs) && !std::isnan(ft)) { |
| 3379 set_fpu_register(fd_reg(), -1); | 3612 set_fpu_register(fd_reg(), -1); |
| 3380 } else { | 3613 } else { |
| 3381 set_fpu_register(fd_reg(), 0); | 3614 set_fpu_register(fd_reg(), 0); |
| 3382 } | 3615 } |
| 3616 TraceRegWr(get_fpu_register(fd_reg())); | |
| 3383 break; | 3617 break; |
| 3384 case CMP_UNE: | 3618 case CMP_UNE: |
| 3385 if ((fs != ft) || (std::isnan(fs) || std::isnan(ft))) { | 3619 if ((fs != ft) || (std::isnan(fs) || std::isnan(ft))) { |
| 3386 set_fpu_register(fd_reg(), -1); | 3620 set_fpu_register(fd_reg(), -1); |
| 3387 } else { | 3621 } else { |
| 3388 set_fpu_register(fd_reg(), 0); | 3622 set_fpu_register(fd_reg(), 0); |
| 3389 } | 3623 } |
| 3624 TraceRegWr(get_fpu_register(fd_reg())); | |
| 3390 break; | 3625 break; |
| 3391 case CMP_NE: | 3626 case CMP_NE: |
| 3392 if (fs != ft && (!std::isnan(fs) && !std::isnan(ft))) { | 3627 if (fs != ft && (!std::isnan(fs) && !std::isnan(ft))) { |
| 3393 set_fpu_register(fd_reg(), -1); | 3628 set_fpu_register(fd_reg(), -1); |
| 3394 } else { | 3629 } else { |
| 3395 set_fpu_register(fd_reg(), 0); | 3630 set_fpu_register(fd_reg(), 0); |
| 3396 } | 3631 } |
| 3632 TraceRegWr(get_fpu_register(fd_reg())); | |
| 3397 break; | 3633 break; |
| 3398 default: | 3634 default: |
| 3399 UNREACHABLE(); | 3635 UNREACHABLE(); |
| 3400 } | 3636 } |
| 3401 } | 3637 } |
| 3402 | 3638 |
| 3403 | 3639 |
| 3404 void Simulator::DecodeTypeRegisterCOP1() { | 3640 void Simulator::DecodeTypeRegisterCOP1() { |
| 3405 switch (instr_.RsFieldRaw()) { | 3641 switch (instr_.RsFieldRaw()) { |
| 3406 case CFC1: | 3642 case CFC1: |
| 3407 // At the moment only FCSR is supported. | 3643 // At the moment only FCSR is supported. |
| 3408 DCHECK(fs_reg() == kFCSRRegister); | 3644 DCHECK(fs_reg() == kFCSRRegister); |
| 3409 set_register(rt_reg(), FCSR_); | 3645 set_register(rt_reg(), FCSR_); |
| 3646 TraceRegWr(get_register(rt_reg())); | |
| 3410 break; | 3647 break; |
| 3411 case MFC1: | 3648 case MFC1: |
| 3412 set_register(rt_reg(), get_fpu_register_word(fs_reg())); | 3649 set_register(rt_reg(), get_fpu_register_word(fs_reg())); |
| 3650 TraceRegWr(get_register(rt_reg())); | |
| 3413 break; | 3651 break; |
| 3414 case MFHC1: | 3652 case MFHC1: |
| 3415 if (IsFp64Mode()) { | 3653 if (IsFp64Mode()) { |
| 3416 set_register(rt_reg(), get_fpu_register_hi_word(fs_reg())); | 3654 set_register(rt_reg(), get_fpu_register_hi_word(fs_reg())); |
| 3417 } else { | 3655 } else { |
| 3418 set_register(rt_reg(), get_fpu_register_word(fs_reg() + 1)); | 3656 set_register(rt_reg(), get_fpu_register_word(fs_reg() + 1)); |
| 3419 } | 3657 } |
| 3658 TraceRegWr(get_register(rt_reg())); | |
| 3420 break; | 3659 break; |
| 3421 case CTC1: { | 3660 case CTC1: { |
| 3422 // At the moment only FCSR is supported. | 3661 // At the moment only FCSR is supported. |
| 3423 DCHECK(fs_reg() == kFCSRRegister); | 3662 DCHECK(fs_reg() == kFCSRRegister); |
| 3424 int32_t reg = registers_[rt_reg()]; | 3663 int32_t reg = registers_[rt_reg()]; |
| 3425 if (IsMipsArchVariant(kMips32r6)) { | 3664 if (IsMipsArchVariant(kMips32r6)) { |
| 3426 FCSR_ = reg | kFCSRNaN2008FlagMask; | 3665 FCSR_ = reg | kFCSRNaN2008FlagMask; |
| 3427 } else { | 3666 } else { |
| 3428 DCHECK(IsMipsArchVariant(kMips32r1) || IsMipsArchVariant(kMips32r2)); | 3667 DCHECK(IsMipsArchVariant(kMips32r1) || IsMipsArchVariant(kMips32r2)); |
| 3429 FCSR_ = reg & ~kFCSRNaN2008FlagMask; | 3668 FCSR_ = reg & ~kFCSRNaN2008FlagMask; |
| 3430 } | 3669 } |
| 3670 TraceRegWr(static_cast<int32_t>(FCSR_), FLOAT); | |
| 3431 break; | 3671 break; |
| 3432 } | 3672 } |
| 3433 case MTC1: | 3673 case MTC1: |
| 3434 // Hardware writes upper 32-bits to zero on mtc1. | 3674 // Hardware writes upper 32-bits to zero on mtc1. |
| 3435 set_fpu_register_hi_word(fs_reg(), 0); | 3675 set_fpu_register_hi_word(fs_reg(), 0); |
| 3436 set_fpu_register_word(fs_reg(), registers_[rt_reg()]); | 3676 set_fpu_register_word(fs_reg(), registers_[rt_reg()]); |
| 3677 TraceRegWr(get_fpu_register_word(fs_reg()), FLOAT); | |
| 3437 break; | 3678 break; |
| 3438 case MTHC1: | 3679 case MTHC1: |
| 3439 if (IsFp64Mode()) { | 3680 if (IsFp64Mode()) { |
| 3440 set_fpu_register_hi_word(fs_reg(), registers_[rt_reg()]); | 3681 set_fpu_register_hi_word(fs_reg(), registers_[rt_reg()]); |
| 3682 TraceRegWr(get_fpu_register(fs_reg()), DOUBLE); | |
| 3441 } else { | 3683 } else { |
| 3442 set_fpu_register_word(fs_reg() + 1, registers_[rt_reg()]); | 3684 set_fpu_register_word(fs_reg() + 1, registers_[rt_reg()]); |
| 3685 if (fs_reg() % 2) { | |
| 3686 TraceRegWr(get_fpu_register_word(fs_reg() + 1), FLOAT); | |
| 3687 } else { | |
| 3688 TraceRegWr(get_fpu_register(fs_reg()), DOUBLE); | |
| 3689 } | |
| 3443 } | 3690 } |
| 3444 break; | 3691 break; |
| 3445 case S: { | 3692 case S: { |
| 3446 DecodeTypeRegisterSRsType(); | 3693 DecodeTypeRegisterSRsType(); |
| 3447 break; | 3694 break; |
| 3448 } | 3695 } |
| 3449 case D: | 3696 case D: |
| 3450 DecodeTypeRegisterDRsType(); | 3697 DecodeTypeRegisterDRsType(); |
| 3451 break; | 3698 break; |
| 3452 case W: | 3699 case W: |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 3466 | 3713 |
| 3467 void Simulator::DecodeTypeRegisterCOP1X() { | 3714 void Simulator::DecodeTypeRegisterCOP1X() { |
| 3468 switch (instr_.FunctionFieldRaw()) { | 3715 switch (instr_.FunctionFieldRaw()) { |
| 3469 case MADD_S: { | 3716 case MADD_S: { |
| 3470 DCHECK(IsMipsArchVariant(kMips32r2)); | 3717 DCHECK(IsMipsArchVariant(kMips32r2)); |
| 3471 float fr, ft, fs; | 3718 float fr, ft, fs; |
| 3472 fr = get_fpu_register_float(fr_reg()); | 3719 fr = get_fpu_register_float(fr_reg()); |
| 3473 fs = get_fpu_register_float(fs_reg()); | 3720 fs = get_fpu_register_float(fs_reg()); |
| 3474 ft = get_fpu_register_float(ft_reg()); | 3721 ft = get_fpu_register_float(ft_reg()); |
| 3475 set_fpu_register_float(fd_reg(), fs * ft + fr); | 3722 set_fpu_register_float(fd_reg(), fs * ft + fr); |
| 3723 TraceRegWr(get_fpu_register_word(fd_reg()), FLOAT); | |
| 3476 break; | 3724 break; |
| 3477 } | 3725 } |
| 3478 case MSUB_S: { | 3726 case MSUB_S: { |
| 3479 DCHECK(IsMipsArchVariant(kMips32r2)); | 3727 DCHECK(IsMipsArchVariant(kMips32r2)); |
| 3480 float fr, ft, fs; | 3728 float fr, ft, fs; |
| 3481 fr = get_fpu_register_float(fr_reg()); | 3729 fr = get_fpu_register_float(fr_reg()); |
| 3482 fs = get_fpu_register_float(fs_reg()); | 3730 fs = get_fpu_register_float(fs_reg()); |
| 3483 ft = get_fpu_register_float(ft_reg()); | 3731 ft = get_fpu_register_float(ft_reg()); |
| 3484 set_fpu_register_float(fd_reg(), fs * ft - fr); | 3732 set_fpu_register_float(fd_reg(), fs * ft - fr); |
| 3733 TraceRegWr(get_fpu_register_word(fd_reg()), FLOAT); | |
| 3485 break; | 3734 break; |
| 3486 } | 3735 } |
| 3487 case MADD_D: { | 3736 case MADD_D: { |
| 3488 DCHECK(IsMipsArchVariant(kMips32r2)); | 3737 DCHECK(IsMipsArchVariant(kMips32r2)); |
| 3489 double fr, ft, fs; | 3738 double fr, ft, fs; |
| 3490 fr = get_fpu_register_double(fr_reg()); | 3739 fr = get_fpu_register_double(fr_reg()); |
| 3491 fs = get_fpu_register_double(fs_reg()); | 3740 fs = get_fpu_register_double(fs_reg()); |
| 3492 ft = get_fpu_register_double(ft_reg()); | 3741 ft = get_fpu_register_double(ft_reg()); |
| 3493 set_fpu_register_double(fd_reg(), fs * ft + fr); | 3742 set_fpu_register_double(fd_reg(), fs * ft + fr); |
| 3743 TraceRegWr(get_fpu_register(fd_reg()), DOUBLE); | |
| 3494 break; | 3744 break; |
| 3495 } | 3745 } |
| 3496 case MSUB_D: { | 3746 case MSUB_D: { |
| 3497 DCHECK(IsMipsArchVariant(kMips32r2)); | 3747 DCHECK(IsMipsArchVariant(kMips32r2)); |
| 3498 double fr, ft, fs; | 3748 double fr, ft, fs; |
| 3499 fr = get_fpu_register_double(fr_reg()); | 3749 fr = get_fpu_register_double(fr_reg()); |
| 3500 fs = get_fpu_register_double(fs_reg()); | 3750 fs = get_fpu_register_double(fs_reg()); |
| 3501 ft = get_fpu_register_double(ft_reg()); | 3751 ft = get_fpu_register_double(ft_reg()); |
| 3502 set_fpu_register_double(fd_reg(), fs * ft - fr); | 3752 set_fpu_register_double(fd_reg(), fs * ft - fr); |
| 3753 TraceRegWr(get_fpu_register(fd_reg()), DOUBLE); | |
| 3503 break; | 3754 break; |
| 3504 } | 3755 } |
| 3505 default: | 3756 default: |
| 3506 UNREACHABLE(); | 3757 UNREACHABLE(); |
| 3507 } | 3758 } |
| 3508 } | 3759 } |
| 3509 | 3760 |
| 3510 | 3761 |
| 3511 void Simulator::DecodeTypeRegisterSPECIAL() { | 3762 void Simulator::DecodeTypeRegisterSPECIAL() { |
| 3512 int64_t alu_out = 0x12345678; | 3763 int64_t alu_out = 0x12345678; |
| 3513 int64_t i64hilo = 0; | 3764 int64_t i64hilo = 0; |
| 3514 uint64_t u64hilo = 0; | 3765 uint64_t u64hilo = 0; |
| 3515 bool do_interrupt = false; | 3766 bool do_interrupt = false; |
| 3516 | 3767 |
| 3517 switch (instr_.FunctionFieldRaw()) { | 3768 switch (instr_.FunctionFieldRaw()) { |
| 3518 case SELEQZ_S: | 3769 case SELEQZ_S: |
| 3519 DCHECK(IsMipsArchVariant(kMips32r6)); | 3770 DCHECK(IsMipsArchVariant(kMips32r6)); |
| 3520 set_register(rd_reg(), rt() == 0 ? rs() : 0); | 3771 SetResult(rd_reg(), rt() == 0 ? rs() : 0); |
| 3521 break; | 3772 break; |
| 3522 case SELNEZ_S: | 3773 case SELNEZ_S: |
| 3523 DCHECK(IsMipsArchVariant(kMips32r6)); | 3774 DCHECK(IsMipsArchVariant(kMips32r6)); |
| 3524 set_register(rd_reg(), rt() != 0 ? rs() : 0); | 3775 SetResult(rd_reg(), rt() != 0 ? rs() : 0); |
| 3525 break; | 3776 break; |
| 3526 case JR: { | 3777 case JR: { |
| 3527 int32_t next_pc = rs(); | 3778 int32_t next_pc = rs(); |
| 3528 int32_t current_pc = get_pc(); | 3779 int32_t current_pc = get_pc(); |
| 3529 Instruction* branch_delay_instr = | 3780 Instruction* branch_delay_instr = |
| 3530 reinterpret_cast<Instruction*>(current_pc + Instruction::kInstrSize); | 3781 reinterpret_cast<Instruction*>(current_pc + Instruction::kInstrSize); |
| 3531 BranchDelayInstructionDecode(branch_delay_instr); | 3782 BranchDelayInstructionDecode(branch_delay_instr); |
| 3532 set_pc(next_pc); | 3783 set_pc(next_pc); |
| 3533 pc_modified_ = true; | 3784 pc_modified_ = true; |
| 3534 break; | 3785 break; |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3615 break; | 3866 break; |
| 3616 // Instructions using HI and LO registers. | 3867 // Instructions using HI and LO registers. |
| 3617 case MULT: | 3868 case MULT: |
| 3618 i64hilo = static_cast<int64_t>(rs()) * static_cast<int64_t>(rt()); | 3869 i64hilo = static_cast<int64_t>(rs()) * static_cast<int64_t>(rt()); |
| 3619 if (!IsMipsArchVariant(kMips32r6)) { | 3870 if (!IsMipsArchVariant(kMips32r6)) { |
| 3620 set_register(LO, static_cast<int32_t>(i64hilo & 0xffffffff)); | 3871 set_register(LO, static_cast<int32_t>(i64hilo & 0xffffffff)); |
| 3621 set_register(HI, static_cast<int32_t>(i64hilo >> 32)); | 3872 set_register(HI, static_cast<int32_t>(i64hilo >> 32)); |
| 3622 } else { | 3873 } else { |
| 3623 switch (sa()) { | 3874 switch (sa()) { |
| 3624 case MUL_OP: | 3875 case MUL_OP: |
| 3625 set_register(rd_reg(), static_cast<int32_t>(i64hilo & 0xffffffff)); | 3876 SetResult(rd_reg(), static_cast<int32_t>(i64hilo & 0xffffffff)); |
| 3626 break; | 3877 break; |
| 3627 case MUH_OP: | 3878 case MUH_OP: |
| 3628 set_register(rd_reg(), static_cast<int32_t>(i64hilo >> 32)); | 3879 SetResult(rd_reg(), static_cast<int32_t>(i64hilo >> 32)); |
| 3629 break; | 3880 break; |
| 3630 default: | 3881 default: |
| 3631 UNIMPLEMENTED_MIPS(); | 3882 UNIMPLEMENTED_MIPS(); |
| 3632 break; | 3883 break; |
| 3633 } | 3884 } |
| 3634 } | 3885 } |
| 3635 break; | 3886 break; |
| 3636 case MULTU: | 3887 case MULTU: |
| 3637 u64hilo = static_cast<uint64_t>(rs_u()) * static_cast<uint64_t>(rt_u()); | 3888 u64hilo = static_cast<uint64_t>(rs_u()) * static_cast<uint64_t>(rt_u()); |
| 3638 if (!IsMipsArchVariant(kMips32r6)) { | 3889 if (!IsMipsArchVariant(kMips32r6)) { |
| 3639 set_register(LO, static_cast<int32_t>(u64hilo & 0xffffffff)); | 3890 set_register(LO, static_cast<int32_t>(u64hilo & 0xffffffff)); |
| 3640 set_register(HI, static_cast<int32_t>(u64hilo >> 32)); | 3891 set_register(HI, static_cast<int32_t>(u64hilo >> 32)); |
| 3641 } else { | 3892 } else { |
| 3642 switch (sa()) { | 3893 switch (sa()) { |
| 3643 case MUL_OP: | 3894 case MUL_OP: |
| 3644 set_register(rd_reg(), static_cast<int32_t>(u64hilo & 0xffffffff)); | 3895 SetResult(rd_reg(), static_cast<int32_t>(u64hilo & 0xffffffff)); |
| 3645 break; | 3896 break; |
| 3646 case MUH_OP: | 3897 case MUH_OP: |
| 3647 set_register(rd_reg(), static_cast<int32_t>(u64hilo >> 32)); | 3898 SetResult(rd_reg(), static_cast<int32_t>(u64hilo >> 32)); |
| 3648 break; | 3899 break; |
| 3649 default: | 3900 default: |
| 3650 UNIMPLEMENTED_MIPS(); | 3901 UNIMPLEMENTED_MIPS(); |
| 3651 break; | 3902 break; |
| 3652 } | 3903 } |
| 3653 } | 3904 } |
| 3654 break; | 3905 break; |
| 3655 case DIV: | 3906 case DIV: |
| 3656 if (IsMipsArchVariant(kMips32r6)) { | 3907 if (IsMipsArchVariant(kMips32r6)) { |
| 3657 switch (sa()) { | 3908 switch (sa()) { |
| 3658 case DIV_OP: | 3909 case DIV_OP: |
| 3659 if (rs() == INT_MIN && rt() == -1) { | 3910 if (rs() == INT_MIN && rt() == -1) { |
| 3660 set_register(rd_reg(), INT_MIN); | 3911 SetResult(rd_reg(), INT_MIN); |
| 3661 } else if (rt() != 0) { | 3912 } else if (rt() != 0) { |
| 3662 set_register(rd_reg(), rs() / rt()); | 3913 SetResult(rd_reg(), rs() / rt()); |
| 3663 } | 3914 } |
| 3664 break; | 3915 break; |
| 3665 case MOD_OP: | 3916 case MOD_OP: |
| 3666 if (rs() == INT_MIN && rt() == -1) { | 3917 if (rs() == INT_MIN && rt() == -1) { |
| 3667 set_register(rd_reg(), 0); | 3918 SetResult(rd_reg(), 0); |
| 3668 } else if (rt() != 0) { | 3919 } else if (rt() != 0) { |
| 3669 set_register(rd_reg(), rs() % rt()); | 3920 SetResult(rd_reg(), rs() % rt()); |
| 3670 } | 3921 } |
| 3671 break; | 3922 break; |
| 3672 default: | 3923 default: |
| 3673 UNIMPLEMENTED_MIPS(); | 3924 UNIMPLEMENTED_MIPS(); |
| 3674 break; | 3925 break; |
| 3675 } | 3926 } |
| 3676 } else { | 3927 } else { |
| 3677 // Divide by zero and overflow was not checked in the | 3928 // Divide by zero and overflow was not checked in the |
| 3678 // configuration step - div and divu do not raise exceptions. On | 3929 // configuration step - div and divu do not raise exceptions. On |
| 3679 // division by 0 the result will be UNPREDICTABLE. On overflow | 3930 // division by 0 the result will be UNPREDICTABLE. On overflow |
| 3680 // (INT_MIN/-1), return INT_MIN which is what the hardware does. | 3931 // (INT_MIN/-1), return INT_MIN which is what the hardware does. |
| 3681 if (rs() == INT_MIN && rt() == -1) { | 3932 if (rs() == INT_MIN && rt() == -1) { |
| 3682 set_register(LO, INT_MIN); | 3933 set_register(LO, INT_MIN); |
| 3683 set_register(HI, 0); | 3934 set_register(HI, 0); |
| 3684 } else if (rt() != 0) { | 3935 } else if (rt() != 0) { |
| 3685 set_register(LO, rs() / rt()); | 3936 set_register(LO, rs() / rt()); |
| 3686 set_register(HI, rs() % rt()); | 3937 set_register(HI, rs() % rt()); |
| 3687 } | 3938 } |
| 3688 } | 3939 } |
| 3689 break; | 3940 break; |
| 3690 case DIVU: | 3941 case DIVU: |
| 3691 if (IsMipsArchVariant(kMips32r6)) { | 3942 if (IsMipsArchVariant(kMips32r6)) { |
| 3692 switch (sa()) { | 3943 switch (sa()) { |
| 3693 case DIV_OP: | 3944 case DIV_OP: |
| 3694 if (rt_u() != 0) { | 3945 if (rt_u() != 0) { |
| 3695 set_register(rd_reg(), rs_u() / rt_u()); | 3946 SetResult(rd_reg(), rs_u() / rt_u()); |
| 3696 } | 3947 } |
| 3697 break; | 3948 break; |
| 3698 case MOD_OP: | 3949 case MOD_OP: |
| 3699 if (rt_u() != 0) { | 3950 if (rt_u() != 0) { |
| 3700 set_register(rd_reg(), rs_u() % rt_u()); | 3951 SetResult(rd_reg(), rs_u() % rt_u()); |
| 3701 } | 3952 } |
| 3702 break; | 3953 break; |
| 3703 default: | 3954 default: |
| 3704 UNIMPLEMENTED_MIPS(); | 3955 UNIMPLEMENTED_MIPS(); |
| 3705 break; | 3956 break; |
| 3706 } | 3957 } |
| 3707 } else { | 3958 } else { |
| 3708 if (rt_u() != 0) { | 3959 if (rt_u() != 0) { |
| 3709 set_register(LO, rs_u() / rt_u()); | 3960 set_register(LO, rs_u() / rt_u()); |
| 3710 set_register(HI, rs_u() % rt_u()); | 3961 set_register(HI, rs_u() % rt_u()); |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3784 break; | 4035 break; |
| 3785 case TNE: | 4036 case TNE: |
| 3786 do_interrupt = rs() != rt(); | 4037 do_interrupt = rs() != rt(); |
| 3787 break; | 4038 break; |
| 3788 case SYNC: | 4039 case SYNC: |
| 3789 // TODO(palfia): Ignore sync instruction for now. | 4040 // TODO(palfia): Ignore sync instruction for now. |
| 3790 break; | 4041 break; |
| 3791 // Conditional moves. | 4042 // Conditional moves. |
| 3792 case MOVN: | 4043 case MOVN: |
| 3793 if (rt()) { | 4044 if (rt()) { |
| 3794 set_register(rd_reg(), rs()); | 4045 SetResult(rd_reg(), rs()); |
| 3795 TraceRegWr(rs()); | |
| 3796 } | 4046 } |
| 3797 break; | 4047 break; |
| 3798 case MOVCI: { | 4048 case MOVCI: { |
| 3799 uint32_t cc = instr_.FBccValue(); | 4049 uint32_t cc = instr_.FBccValue(); |
| 3800 uint32_t fcsr_cc = get_fcsr_condition_bit(cc); | 4050 uint32_t fcsr_cc = get_fcsr_condition_bit(cc); |
| 3801 if (instr_.Bit(16)) { // Read Tf bit. | 4051 if (instr_.Bit(16)) { // Read Tf bit. |
| 3802 if (test_fcsr_bit(fcsr_cc)) set_register(rd_reg(), rs()); | 4052 if (test_fcsr_bit(fcsr_cc)) set_register(rd_reg(), rs()); |
| 3803 } else { | 4053 } else { |
| 3804 if (!test_fcsr_bit(fcsr_cc)) set_register(rd_reg(), rs()); | 4054 if (!test_fcsr_bit(fcsr_cc)) set_register(rd_reg(), rs()); |
| 3805 } | 4055 } |
| 3806 break; | 4056 break; |
| 3807 } | 4057 } |
| 3808 case MOVZ: | 4058 case MOVZ: |
| 3809 if (!rt()) { | 4059 if (!rt()) { |
| 3810 set_register(rd_reg(), rs()); | 4060 SetResult(rd_reg(), rs()); |
| 3811 TraceRegWr(rs()); | |
| 3812 } | 4061 } |
| 3813 break; | 4062 break; |
| 3814 default: | 4063 default: |
| 3815 UNREACHABLE(); | 4064 UNREACHABLE(); |
| 3816 } | 4065 } |
| 3817 if (do_interrupt) { | 4066 if (do_interrupt) { |
| 3818 SoftwareInterrupt(); | 4067 SoftwareInterrupt(); |
| 3819 } | 4068 } |
| 3820 } | 4069 } |
| 3821 | 4070 |
| (...skipping 543 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4365 uint8_t al_offset = (rs + se_imm16) & kPointerAlignmentMask; | 4614 uint8_t al_offset = (rs + se_imm16) & kPointerAlignmentMask; |
| 4366 uint32_t mask = (1 << al_offset * 8) - 1; | 4615 uint32_t mask = (1 << al_offset * 8) - 1; |
| 4367 addr = rs + se_imm16 - al_offset; | 4616 addr = rs + se_imm16 - al_offset; |
| 4368 uint32_t mem_value = ReadW(addr, instr_.instr()); | 4617 uint32_t mem_value = ReadW(addr, instr_.instr()); |
| 4369 mem_value = (rt << al_offset * 8) | (mem_value & mask); | 4618 mem_value = (rt << al_offset * 8) | (mem_value & mask); |
| 4370 WriteW(addr, mem_value, instr_.instr()); | 4619 WriteW(addr, mem_value, instr_.instr()); |
| 4371 break; | 4620 break; |
| 4372 } | 4621 } |
| 4373 case LWC1: | 4622 case LWC1: |
| 4374 set_fpu_register_hi_word(ft_reg, 0); | 4623 set_fpu_register_hi_word(ft_reg, 0); |
| 4375 set_fpu_register_word(ft_reg, ReadW(rs + se_imm16, instr_.instr())); | 4624 set_fpu_register_word(ft_reg, |
| 4625 ReadW(rs + se_imm16, instr_.instr(), FLOAT)); | |
| 4626 if (ft_reg % 2) { | |
| 4627 TraceMemRd(rs + se_imm16, get_fpu_register(ft_reg - 1), FLOAT_DOUBLE); | |
| 4628 } else { | |
| 4629 TraceMemRd(rs + se_imm16, get_fpu_register_word(ft_reg), FLOAT); | |
| 4630 } | |
| 4376 break; | 4631 break; |
| 4377 case LDC1: | 4632 case LDC1: |
| 4378 set_fpu_register_double(ft_reg, ReadD(rs + se_imm16, instr_.instr())); | 4633 set_fpu_register_double(ft_reg, ReadD(rs + se_imm16, instr_.instr())); |
| 4634 TraceMemRd(rs + se_imm16, get_fpu_register(ft_reg), DOUBLE); | |
| 4379 break; | 4635 break; |
| 4380 case SWC1: | 4636 case SWC1: |
| 4381 WriteW(rs + se_imm16, get_fpu_register_word(ft_reg), instr_.instr()); | 4637 WriteW(rs + se_imm16, get_fpu_register_word(ft_reg), instr_.instr()); |
| 4638 TraceMemWr(rs + se_imm16, get_fpu_register_word(ft_reg)); | |
| 4382 break; | 4639 break; |
| 4383 case SDC1: | 4640 case SDC1: |
| 4384 WriteD(rs + se_imm16, get_fpu_register_double(ft_reg), instr_.instr()); | 4641 WriteD(rs + se_imm16, get_fpu_register_double(ft_reg), instr_.instr()); |
| 4642 TraceMemWr(rs + se_imm16, get_fpu_register(ft_reg)); | |
| 4385 break; | 4643 break; |
| 4386 // ------------- PC-Relative instructions. | 4644 // ------------- PC-Relative instructions. |
| 4387 case PCREL: { | 4645 case PCREL: { |
| 4388 // rt field: checking 5-bits. | 4646 // rt field: checking 5-bits. |
| 4389 int32_t imm21 = instr_.Imm21Value(); | 4647 int32_t imm21 = instr_.Imm21Value(); |
| 4390 int32_t current_pc = get_pc(); | 4648 int32_t current_pc = get_pc(); |
| 4391 uint8_t rt = (imm21 >> kImm16Bits); | 4649 uint8_t rt = (imm21 >> kImm16Bits); |
| 4392 switch (rt) { | 4650 switch (rt) { |
| 4393 case ALUIPC: | 4651 case ALUIPC: |
| 4394 addr = current_pc + (se_imm16 << 16); | 4652 addr = current_pc + (se_imm16 << 16); |
| (...skipping 20 matching lines...) Expand all Loading... | |
| 4415 int32_t se_imm19 = imm19 | ((imm19 & 0x40000) ? 0xfff80000 : 0); | 4673 int32_t se_imm19 = imm19 | ((imm19 & 0x40000) ? 0xfff80000 : 0); |
| 4416 alu_out = current_pc + (se_imm19 << 2); | 4674 alu_out = current_pc + (se_imm19 << 2); |
| 4417 break; | 4675 break; |
| 4418 } | 4676 } |
| 4419 default: | 4677 default: |
| 4420 UNREACHABLE(); | 4678 UNREACHABLE(); |
| 4421 break; | 4679 break; |
| 4422 } | 4680 } |
| 4423 } | 4681 } |
| 4424 } | 4682 } |
| 4425 set_register(rs_reg, alu_out); | 4683 SetResult(rs_reg, alu_out); |
| 4426 break; | 4684 break; |
| 4427 } | 4685 } |
| 4428 default: | 4686 default: |
| 4429 UNREACHABLE(); | 4687 UNREACHABLE(); |
| 4430 } | 4688 } |
| 4431 | 4689 |
| 4432 if (execute_branch_delay_instruction) { | 4690 if (execute_branch_delay_instruction) { |
| 4433 // Execute branch delay slot | 4691 // Execute branch delay slot |
| 4434 // We don't check for end_sim_pc. First it should not be met as the current | 4692 // 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. | 4693 // 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 | 4952 |
| 4695 | 4953 |
| 4696 #undef UNSUPPORTED | 4954 #undef UNSUPPORTED |
| 4697 | 4955 |
| 4698 } // namespace internal | 4956 } // namespace internal |
| 4699 } // namespace v8 | 4957 } // namespace v8 |
| 4700 | 4958 |
| 4701 #endif // USE_SIMULATOR | 4959 #endif // USE_SIMULATOR |
| 4702 | 4960 |
| 4703 #endif // V8_TARGET_ARCH_MIPS | 4961 #endif // V8_TARGET_ARCH_MIPS |
| OLD | NEW |