Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(106)

Side by Side Diff: src/mips/simulator-mips.cc

Issue 2603083002: MIPS[64]: Add support for FPR content in simulator trace. (Closed)
Patch Set: Updates and corrections. Created 3 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/mips/simulator-mips.h ('k') | src/mips64/simulator-mips64.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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, &registers_[reg], 2 * sizeof(registers_[0])); 1125 memcpy(buffer, &registers_[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
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
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
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
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
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « src/mips/simulator-mips.h ('k') | src/mips64/simulator-mips64.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698