ppc float entianness
PATCH 1/1 ppc float entianness
The PPC FPU emulation is broken on hosts with with weird floating point word ordering (ie. arm).
The attached patch fixes this by using CPU_DoubleU as appropriate.
Paul
Index: target-ppc/op_helper.c
===================================================================
RCS file: /cvsroot/qemu/qemu/target-ppc/op_helper.c,v retrieving revision 1.12
op_helper.c +58 -82
@@ -180,25 +180,13 @@ void do_load_fpscr (void)/* The 32 MSB of the target fpr are undefined. * They'll be zero... */ -union { -double d; -struct { -uint32_t u[2 ]; - } s; - } u; +CPU_DoubleU u;int i; -#ifdef WORDS_BIGENDIAN -#define WORD0 0 -#define WORD1 1 -#else -#define WORD0 1 -#define WORD1 0 -#endif - u.s.u[WORD0 ] =0 ; - u.s.u[WORD1 ] =0 ; + u.l.upper =0 ; + u.l.lower =0 ;for (i =0 ; i <8 ; i++) - u.s.u[WORD1 ] |= env->fpscr[i] << (4 * i); + u.l.lower |= env->fpscr[i] << (4 * i);FT0 = u.d; }
@@ -207,20 +195,15 @@ void do_store_fpscr (uint32_t mask)/* * We use only the 32 LSB of the incoming fpr */ -union { -double d; -struct { -uint32_t u[2 ]; - } s; - } u; +CPU_DoubleU u;int i, rnd_type; u.d =FT0 ;if (mask &0x80 ) - env->fpscr[0 ] = (env->fpscr[0 ] &0x9 ) | ((u.s.u[WORD1 ] >>28 ) & ~0x9 ); + env->fpscr[0 ] = (env->fpscr[0 ] &0x9 ) | ((u.l.lower >>28 ) & ~0x9 );for (i =1 ; i <7 ; i++) {if (mask & (1 << (7 - i))) - env->fpscr[i] = (u.s.u[WORD1 ] >> (4 * (7 - i))) &0xF ; + env->fpscr[i] = (u.l.lower >> (4 * (7 - i))) &0xF ; }/* TODO: update FEX & VX */ /* Set rounding mode */
@@ -248,32 +231,30 @@ void do_store_fpscr (uint32_t mask)void do_fctiw (void ) { -union { -double d; -uint64_t i; - } p; +CPU_DoubleU u; +uint64_t i;/* XXX: higher bits are not supposed to be significant. * to make tests easier, return the same as a real PPC 750 (aka G3) */ - p.i =float64_to_int32 (FT0 , &env->fp_status); - p.i |=0xFFF80000ULL <<32 ; -FT0 = p.d; + i =float64_to_int32 (FT0 , &env->fp_status); + u.l.upper = i >>32 ; + u.l.lower = i; +FT0 = u.d; }void do_fctiwz (void ) { -union { -double d; -uint64_t i; - } p; +CPU_DoubleU u; +uint64_t i;/* XXX: higher bits are not supposed to be significant. * to make tests easier, return the same as a real PPC 750 (aka G3) */ - p.i =float64_to_int32_round_to_zero (FT0 , &env->fp_status); - p.i |=0xFFF80000ULL <<32 ; -FT0 = p.d; + i =float64_to_int32_round_to_zero (FT0 , &env->fp_status); + u.l.upper = (i >>32 ) |0xFFF80000 ; + u.l.lower = i; +FT0 = u.d; }void do_fnmadd (void )
@@ -305,54 +286,55 @@ void do_fsqrt (void)void do_fres (void ) { -union { -double d; -uint64_t i; - } p; +CPU_DoubleU u;if (isnormal (FT0 )) {FT0 = (float )(1.0 /FT0 ); }else { - p.d =FT0 ; -if (p.i ==0x8000000000000000ULL ) { - p.i =0xFFF0000000000000ULL ; - }else if (p.i ==0x0000000000000000ULL ) { - p.i =0x7FF0000000000000ULL ; + u.d =FT0 ; +if (u.l.upper ==0x80000000u && u.l.lower ==0 ) { + u.l.upper =0xFFF00000u ; + }else if (u.l.upper ==0 && u.l.lower ==0 ) { + u.l.upper =0x7FF00000u ; }else if (isnan (FT0 )) { - p.i =0x7FF8000000000000ULL ; + u.l.upper =0x7FF80000u ; + u.l.lower =0 ; }else if (FT0 <0.0 ) { - p.i =0x8000000000000000ULL ; + u.l.upper =0x80000000u ; + u.l.lower =0 ; }else { - p.i =0x0000000000000000ULL ; + u.l.upper =0 ; + u.l.lower =0 ; } -FT0 = p.d; +FT0 = u.d; } }void do_frsqrte (void ) { -union { -double d; -uint64_t i; - } p; +CPU_DoubleU u;if (isnormal (FT0 ) &&FT0 >0.0 ) {FT0 = (float )(1.0 /sqrt (FT0 )); }else { - p.d =FT0 ; -if (p.i ==0x8000000000000000ULL ) { - p.i =0xFFF0000000000000ULL ; - }else if (p.i ==0x0000000000000000ULL ) { - p.i =0x7FF0000000000000ULL ; + u.d =FT0 ; +if (u.l.upper ==0x80000000u && u.l.lower ==0 ) { + u.l.upper =0xFFF00000u ; + }else if (u.l.upper ==0 && u.l.lower ==0 ) { + u.l.upper =0x7FF00000u ; }else if (isnan (FT0 )) { -if (!(p.i &0x0008000000000000ULL )) - p.i |=0x000FFFFFFFFFFFFFULL ; - }else if (FT0 <0 ) { - p.i =0x7FF8000000000000ULL ; +if (!(u.l.upper &0x00080000u )){ + u.l.upper |=0x000fffffu ; + u.l.lower |=0xffffffffu ; + } + }else if (FT0 <0.0 ) { + u.l.upper =0x7ff80000u ; + u.l.lower =0 ; }else { - p.i =0x0000000000000000ULL ; + u.l.upper =0 ; + u.l.lower =0 ; } -FT0 = p.d; +FT0 = u.d; } }
@@ -406,26 +388,20 @@ void do_fcmpo (void)void do_fabs (void ) { -union { -double d; -uint64_t i; - } p; - - p.d =FT0 ; - p.i &= ~0x8000000000000000ULL ; -FT0 = p.d; +CPU_DoubleU u; + + u.d =FT0 ; + u.l.upper &= ~0x80000000u ; +FT0 = u.d; }void do_fnabs (void ) { -union { -double d; -uint64_t i; - } p; - - p.d =FT0 ; - p.i |=0x8000000000000000ULL ; -FT0 = p.d; +CPU_DoubleU u; + + u.d =FT0 ; + u.l.upper &= ~0x80000000u ; +FT0 = u.d; }/* Instruction cache invalidation helper */