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) | ... | ... |