Commit d7e4b87e53923542c1a7220e08bcae2252f5a22e
1 parent
477023a6
Implement new floating-point instructions (fre, frin, friz, frip, frim)
as defined in the PowerPC 2.04 specification. git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@3281 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
4 changed files
with
106 additions
and
0 deletions
target-ppc/op.c
... | ... | @@ -1701,6 +1701,13 @@ void OPPROTO op_fsqrt (void) |
1701 | 1701 | RETURN(); |
1702 | 1702 | } |
1703 | 1703 | |
1704 | +/* fre - fre. */ | |
1705 | +void OPPROTO op_fre (void) | |
1706 | +{ | |
1707 | + do_fre(); | |
1708 | + RETURN(); | |
1709 | +} | |
1710 | + | |
1704 | 1711 | /* fres - fres. */ |
1705 | 1712 | void OPPROTO op_fres (void) |
1706 | 1713 | { |
... | ... | @@ -1806,6 +1813,30 @@ void OPPROTO op_fctidz (void) |
1806 | 1813 | } |
1807 | 1814 | #endif |
1808 | 1815 | |
1816 | +void OPPROTO op_frin (void) | |
1817 | +{ | |
1818 | + do_frin(); | |
1819 | + RETURN(); | |
1820 | +} | |
1821 | + | |
1822 | +void OPPROTO op_friz (void) | |
1823 | +{ | |
1824 | + do_friz(); | |
1825 | + RETURN(); | |
1826 | +} | |
1827 | + | |
1828 | +void OPPROTO op_frip (void) | |
1829 | +{ | |
1830 | + do_frip(); | |
1831 | + RETURN(); | |
1832 | +} | |
1833 | + | |
1834 | +void OPPROTO op_frim (void) | |
1835 | +{ | |
1836 | + do_frim(); | |
1837 | + RETURN(); | |
1838 | +} | |
1839 | + | |
1809 | 1840 | /*** Floating-Point compare ***/ |
1810 | 1841 | /* fcmpu */ |
1811 | 1842 | void OPPROTO op_fcmpu (void) | ... | ... |
target-ppc/op_helper.c
... | ... | @@ -700,6 +700,36 @@ void do_fctidz (void) |
700 | 700 | |
701 | 701 | #endif |
702 | 702 | |
703 | +static inline void do_fri (int rounding_mode) | |
704 | +{ | |
705 | + int curmode; | |
706 | + | |
707 | + curmode = env->fp_status.float_rounding_mode; | |
708 | + set_float_rounding_mode(rounding_mode, &env->fp_status); | |
709 | + FT0 = float64_round_to_int(FT0, &env->fp_status); | |
710 | + set_float_rounding_mode(curmode, &env->fp_status); | |
711 | +} | |
712 | + | |
713 | +void do_frin (void) | |
714 | +{ | |
715 | + do_fri(float_round_nearest_even); | |
716 | +} | |
717 | + | |
718 | +void do_friz (void) | |
719 | +{ | |
720 | + do_fri(float_round_to_zero); | |
721 | +} | |
722 | + | |
723 | +void do_frip (void) | |
724 | +{ | |
725 | + do_fri(float_round_up); | |
726 | +} | |
727 | + | |
728 | +void do_frim (void) | |
729 | +{ | |
730 | + do_fri(float_round_down); | |
731 | +} | |
732 | + | |
703 | 733 | #if USE_PRECISE_EMULATION |
704 | 734 | void do_fmadd (void) |
705 | 735 | { |
... | ... | @@ -789,6 +819,32 @@ void do_fsqrt (void) |
789 | 819 | FT0 = float64_sqrt(FT0, &env->fp_status); |
790 | 820 | } |
791 | 821 | |
822 | +void do_fre (void) | |
823 | +{ | |
824 | + union { | |
825 | + double d; | |
826 | + uint64_t i; | |
827 | + } p; | |
828 | + | |
829 | + if (likely(isnormal(FT0))) { | |
830 | + FT0 = float64_div(1.0, FT0, &env->fp_status); | |
831 | + } else { | |
832 | + p.d = FT0; | |
833 | + if (p.i == 0x8000000000000000ULL) { | |
834 | + p.i = 0xFFF0000000000000ULL; | |
835 | + } else if (p.i == 0x0000000000000000ULL) { | |
836 | + p.i = 0x7FF0000000000000ULL; | |
837 | + } else if (isnan(FT0)) { | |
838 | + p.i = 0x7FF8000000000000ULL; | |
839 | + } else if (FT0 < 0.0) { | |
840 | + p.i = 0x8000000000000000ULL; | |
841 | + } else { | |
842 | + p.i = 0x0000000000000000ULL; | |
843 | + } | |
844 | + FT0 = p.d; | |
845 | + } | |
846 | +} | |
847 | + | |
792 | 848 | void do_fres (void) |
793 | 849 | { |
794 | 850 | union { | ... | ... |
target-ppc/op_helper.h
... | ... | @@ -94,6 +94,7 @@ void do_popcntb_64 (void); |
94 | 94 | |
95 | 95 | /* Floating-point arithmetic helpers */ |
96 | 96 | void do_fsqrt (void); |
97 | +void do_fre (void); | |
97 | 98 | void do_fres (void); |
98 | 99 | void do_frsqrte (void); |
99 | 100 | void do_fsel (void); |
... | ... | @@ -110,6 +111,10 @@ void do_fcfid (void); |
110 | 111 | void do_fctid (void); |
111 | 112 | void do_fctidz (void); |
112 | 113 | #endif |
114 | +void do_frin (void); | |
115 | +void do_friz (void); | |
116 | +void do_frip (void); | |
117 | +void do_frim (void); | |
113 | 118 | void do_fcmpu (void); |
114 | 119 | void do_fcmpo (void); |
115 | 120 | ... | ... |
target-ppc/translate.c
... | ... | @@ -476,6 +476,8 @@ enum { |
476 | 476 | PPC_RFMCI = 0x0000020000000000ULL, |
477 | 477 | /* user-mode DCR access, implemented in PowerPC 460 */ |
478 | 478 | PPC_DCRUX = 0x0000040000000000ULL, |
479 | + /* New floating-point extensions (PowerPC 2.0x) */ | |
480 | + PPC_FLOAT_EXT = 0x0000080000000000ULL, | |
479 | 481 | }; |
480 | 482 | |
481 | 483 | /*****************************************************************************/ |
... | ... | @@ -1660,6 +1662,9 @@ GEN_FLOAT_AB(div, 0x12, 0x000007C0); |
1660 | 1662 | /* fmul - fmuls */ |
1661 | 1663 | GEN_FLOAT_AC(mul, 0x19, 0x0000F800); |
1662 | 1664 | |
1665 | +/* fre */ | |
1666 | +GEN_FLOAT_BS(re, 0x3F, 0x18, PPC_FLOAT_EXT); | |
1667 | + | |
1663 | 1668 | /* fres */ |
1664 | 1669 | GEN_FLOAT_BS(res, 0x3B, 0x18, PPC_FLOAT_FRES); |
1665 | 1670 | |
... | ... | @@ -1727,6 +1732,15 @@ GEN_FLOAT_B(ctid, 0x0E, 0x19, PPC_64B); |
1727 | 1732 | GEN_FLOAT_B(ctidz, 0x0F, 0x19, PPC_64B); |
1728 | 1733 | #endif |
1729 | 1734 | |
1735 | +/* frin */ | |
1736 | +GEN_FLOAT_B(rin, 0x08, 0x0C, PPC_FLOAT_EXT); | |
1737 | +/* friz */ | |
1738 | +GEN_FLOAT_B(riz, 0x08, 0x0D, PPC_FLOAT_EXT); | |
1739 | +/* frip */ | |
1740 | +GEN_FLOAT_B(rip, 0x08, 0x0E, PPC_FLOAT_EXT); | |
1741 | +/* frim */ | |
1742 | +GEN_FLOAT_B(rim, 0x08, 0x0F, PPC_FLOAT_EXT); | |
1743 | + | |
1730 | 1744 | /*** Floating-Point compare ***/ |
1731 | 1745 | /* fcmpo */ |
1732 | 1746 | GEN_HANDLER(fcmpo, 0x3F, 0x00, 0x01, 0x00600001, PPC_FLOAT) | ... | ... |