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