On 12/17/2013 11:45 AM, Peter Maydell wrote: > On 11 December 2013 20:39, Tom Musta <tommu...@gmail.com> wrote: >> On 12/11/2013 1:53 PM, Peter Maydell wrote: >>> On 11 December 2013 19:16, Tom Musta <tommu...@gmail.com> wrote: >>>> uint32 float64_to_uint32( float64 a STATUS_PARAM ) >>>> { >>>> - int64_t v; >>>> + uint64_t v; >>>> uint32 res; >>>> >>>> - v = float64_to_int64(a STATUS_VAR); >>>> - if (v < 0) { >>>> - res = 0; >>>> - float_raise( float_flag_invalid STATUS_VAR); >>>> - } else if (v > 0xffffffff) { >>>> + v = float64_to_uint64(a STATUS_VAR); >>>> + if (v > 0xffffffff) { >>>> res = 0xffffffff; >>>> + STATUS(float_exception_flags) &= ~float_flag_inexact; >>> >>> The IEEE exception flags are cumulative (ie never get cleared >>> except by guest program explicit request); this change means >>> that if a previous operation raised the inexact flag you've just >>> lost that. >>> >>> thanks >>> -- PMM >>> >> Thank you, Peter. I will fix. > > I'm partway through fixing this bug in an implementation of > float*_to_uint16 which the ARM AArch64 needs. I think the > cleanest approach to this looks like this: > > uint32 float64_to_uint32( float64 a STATUS_PARAM ) > { > int64_t v; > uint32 res; > int old_exc_flags = get_float_exception_flags(status); > > v = float64_to_uint64(a STATUS_VAR); > if (v > 0xffffffff) { > res = 0xffffffff; > } else { > return v; > } > set_float_exception_flags(old_exc_flags); > float_raise(float_flag_invalid STATUS_VAR); > return res; > } > > thanks > -- PMM >
This seems to assume that the only case where flags could be set in float64_to_uint32 is the case where a large result is returned. Is this really the case? I was thinking something like this: uint32 float64_to_uint32( float64 a STATUS_PARAM ) { uint64_t v; uint32 res; int inexact = (STATUS(float_exception_flags) & float_flag_inexact) != 0; v = float64_to_uint64(a STATUS_VAR); if (v > 0xffffffff) { res = 0xffffffff; /* If the inexact flag was set during this operation, then clear it. */ if (!inexact) { STATUS(float_exception_flags) &= ~float_flag_inexact; } float_raise( float_flag_invalid STATUS_VAR); } else { res = v; } return res; }