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 /target-ppc/op_helper.c | |
parent | 477023a6038e8f457c604b138198f76d093b9a87 (diff) | |
download | qemu-d7e4b87e53923542c1a7220e08bcae2252f5a22e.zip qemu-d7e4b87e53923542c1a7220e08bcae2252f5a22e.tar.gz qemu-d7e4b87e53923542c1a7220e08bcae2252f5a22e.tar.bz2 |
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
Diffstat (limited to 'target-ppc/op_helper.c')
-rw-r--r-- | target-ppc/op_helper.c | 56 |
1 files changed, 56 insertions, 0 deletions
diff --git a/target-ppc/op_helper.c b/target-ppc/op_helper.c index 9a79953..08441ca 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 { |