diff options
author | j_mayer <j_mayer@c046a42c-6fe2-441c-8c8c-71466251a162> | 2007-09-30 01:11:48 +0000 |
---|---|---|
committer | j_mayer <j_mayer@c046a42c-6fe2-441c-8c8c-71466251a162> | 2007-09-30 01:11:48 +0000 |
commit | d7e4b87e53923542c1a7220e08bcae2252f5a22e (patch) | |
tree | 0d29076ef6fd68674772fcefa0382a6921f0889c | |
parent | 477023a6038e8f457c604b138198f76d093b9a87 (diff) |
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
-rw-r--r-- | target-ppc/op.c | 31 | ||||
-rw-r--r-- | target-ppc/op_helper.c | 56 | ||||
-rw-r--r-- | target-ppc/op_helper.h | 5 | ||||
-rw-r--r-- | target-ppc/translate.c | 14 |
4 files changed, 106 insertions, 0 deletions
diff --git a/target-ppc/op.c b/target-ppc/op.c index 4622534c27..46843d790f 100644 --- a/target-ppc/op.c +++ b/target-ppc/op.c @@ -1701,6 +1701,13 @@ void OPPROTO op_fsqrt (void) RETURN(); } +/* fre - fre. */ +void OPPROTO op_fre (void) +{ + do_fre(); + RETURN(); +} + /* fres - fres. */ void OPPROTO op_fres (void) { @@ -1806,6 +1813,30 @@ void OPPROTO op_fctidz (void) } #endif +void OPPROTO op_frin (void) +{ + do_frin(); + RETURN(); +} + +void OPPROTO op_friz (void) +{ + do_friz(); + RETURN(); +} + +void OPPROTO op_frip (void) +{ + do_frip(); + RETURN(); +} + +void OPPROTO op_frim (void) +{ + do_frim(); + RETURN(); +} + /*** Floating-Point compare ***/ /* fcmpu */ void OPPROTO op_fcmpu (void) diff --git a/target-ppc/op_helper.c b/target-ppc/op_helper.c index 9a79953f7d..08441caaec 100644 --- a/target-ppc/op_helper.c +++ b/target-ppc/op_helper.c @@ -700,6 +700,36 @@ void do_fctidz (void) #endif +static inline void do_fri (int rounding_mode) +{ + int curmode; + + curmode = env->fp_status.float_rounding_mode; + set_float_rounding_mode(rounding_mode, &env->fp_status); + FT0 = float64_round_to_int(FT0, &env->fp_status); + set_float_rounding_mode(curmode, &env->fp_status); +} + +void do_frin (void) +{ + do_fri(float_round_nearest_even); +} + +void do_friz (void) +{ + do_fri(float_round_to_zero); +} + +void do_frip (void) +{ + do_fri(float_round_up); +} + +void do_frim (void) +{ + do_fri(float_round_down); +} + #if USE_PRECISE_EMULATION void do_fmadd (void) { @@ -789,6 +819,32 @@ void do_fsqrt (void) FT0 = float64_sqrt(FT0, &env->fp_status); } +void do_fre (void) +{ + union { + double d; + uint64_t i; + } p; + + if (likely(isnormal(FT0))) { + FT0 = float64_div(1.0, FT0, &env->fp_status); + } else { + p.d = FT0; + if (p.i == 0x8000000000000000ULL) { + p.i = 0xFFF0000000000000ULL; + } else if (p.i == 0x0000000000000000ULL) { + p.i = 0x7FF0000000000000ULL; + } else if (isnan(FT0)) { + p.i = 0x7FF8000000000000ULL; + } else if (FT0 < 0.0) { + p.i = 0x8000000000000000ULL; + } else { + p.i = 0x0000000000000000ULL; + } + FT0 = p.d; + } +} + void do_fres (void) { union { diff --git a/target-ppc/op_helper.h b/target-ppc/op_helper.h index 4db8ac5308..6c0d2fbf92 100644 --- a/target-ppc/op_helper.h +++ b/target-ppc/op_helper.h @@ -94,6 +94,7 @@ void do_popcntb_64 (void); /* Floating-point arithmetic helpers */ void do_fsqrt (void); +void do_fre (void); void do_fres (void); void do_frsqrte (void); void do_fsel (void); @@ -110,6 +111,10 @@ void do_fcfid (void); void do_fctid (void); void do_fctidz (void); #endif +void do_frin (void); +void do_friz (void); +void do_frip (void); +void do_frim (void); void do_fcmpu (void); void do_fcmpo (void); diff --git a/target-ppc/translate.c b/target-ppc/translate.c index 7f84ed7d69..f4ff22e385 100644 --- a/target-ppc/translate.c +++ b/target-ppc/translate.c @@ -476,6 +476,8 @@ enum { PPC_RFMCI = 0x0000020000000000ULL, /* user-mode DCR access, implemented in PowerPC 460 */ PPC_DCRUX = 0x0000040000000000ULL, + /* New floating-point extensions (PowerPC 2.0x) */ + PPC_FLOAT_EXT = 0x0000080000000000ULL, }; /*****************************************************************************/ @@ -1660,6 +1662,9 @@ GEN_FLOAT_AB(div, 0x12, 0x000007C0); /* fmul - fmuls */ GEN_FLOAT_AC(mul, 0x19, 0x0000F800); +/* fre */ +GEN_FLOAT_BS(re, 0x3F, 0x18, PPC_FLOAT_EXT); + /* fres */ GEN_FLOAT_BS(res, 0x3B, 0x18, PPC_FLOAT_FRES); @@ -1727,6 +1732,15 @@ GEN_FLOAT_B(ctid, 0x0E, 0x19, PPC_64B); GEN_FLOAT_B(ctidz, 0x0F, 0x19, PPC_64B); #endif +/* frin */ +GEN_FLOAT_B(rin, 0x08, 0x0C, PPC_FLOAT_EXT); +/* friz */ +GEN_FLOAT_B(riz, 0x08, 0x0D, PPC_FLOAT_EXT); +/* frip */ +GEN_FLOAT_B(rip, 0x08, 0x0E, PPC_FLOAT_EXT); +/* frim */ +GEN_FLOAT_B(rim, 0x08, 0x0F, PPC_FLOAT_EXT); + /*** Floating-Point compare ***/ /* fcmpo */ GEN_HANDLER(fcmpo, 0x3F, 0x00, 0x01, 0x00600001, PPC_FLOAT) |