[PATCH v4 07/15] ARC: hardware floating point support
Vineet Gupta
Vineet.Gupta1@synopsys.com
Fri Mar 27 01:50:47 GMT 2020
On 3/26/20 4:22 PM, Joseph Myers wrote:
> On Thu, 12 Mar 2020, Vineet Gupta via Libc-alpha wrote:
>
>> +int
>> +fegetmode (femode_t *modep)
>> +{
>> + unsigned int fpcr;
>> +
>> + _FPU_GETCW (fpcr);
>> + *modep = fpcr >> __FPU_RND_SHIFT;
>
> The bits to enable exception traps look like dynamic control mode bits to
> me. In general fegetmode should only need to mask off bits on
> architectures where the same register has both control and status bits,
> not on architectures where those are separate registers and fegetmode /
> fesetmode can work with the whole control register.
Yeah, looking back into my old dev branch, that is how I did it initially, but
then switched to current implementation to "make get/set mode functions
inter-operate with get/set round" - although there was no inter-calling between
the two. We can go back to that implementation as it seems slightly better in
generated code, but I'm curious if it is wrong too....
>> +int
>> +__fesetround (int round)
>> +{
>> + unsigned int fpcr;
>> +
>> + _FPU_GETCW (fpcr);
>> +
>> + if (__glibc_unlikely (((fpcr >> __FPU_RND_SHIFT) & FE_DOWNWARD) != round))
>> + {
>> + fpcr = (fpcr & ~(FE_DOWNWARD << __FPU_RND_SHIFT)) | (round << __FPU_RND_SHIFT);
>> + _FPU_SETCW (fpcr);
>> + }
>
> I don't think the use of __glibc_unlikely is appropriate here. It's not
> at all clear to me that the normal fesetround case is setting the rounding
> mode to the value it already has, as the use of __glibc_unlikely would
> suggest.
Ok removed.
>> +int
>> +__feupdateenv (const fenv_t *envp)
>> +{
>> + unsigned int fpcr;
>> + unsigned int fpsr;
>> +
>> + _FPU_GETCW (fpcr);
>> + _FPU_GETS (fpsr);
>> +
>> + /* rounding mode set to what is in env. */
>> + fpcr = envp->__fpcr;
>> +
>> + /* currently raised exceptions are OR'ed with env. */
>> + fpsr |= envp->__fpsr;
>
> This looks like it wouldn't work for FE_DFL_ENV, which is a valid argument
> to feupdateenv.
Is following pseudo-code correct for semantics ?
fesetenv(env)
if FE_DFL_ENV
fpcr = _FPU_DEFAULT;
fpsr = _FPU_FPSR_DEFAULT;
else
fpcr = envp->__fpcr;
fpsr = envp->__fpsr;
feupdateenv(env)
if FE_DFL_ENV
fpcr = _FPU_DEFAULT;
fpsr = _FPU_FPSR_DEFAULT;
else
fpcr = envp->__fpcr;
fpsr |= envp->__fpsr; <-- this is different
> It looks like we're missing test coverage for feupdateenv
> (FE_DFL_ENV) (we have coverage for feupdateenv (FE_NOMASK_ENV) and
> fesetenv (FE_DFL_ENV)).
>
>> +static inline int
>> +get_rounding_mode (void)
>> +{
>> +#if defined(__ARC_FPU_SP__) || defined(__ARC_FPU_DP__)
>> + unsigned int fpcr;
>> + _FPU_GETCW (fpcr);
>> +
>> + return fpcr >> __FPU_RND_SHIFT;
>
> Both here and in fegetround you're not doing anything to mask off high
> bits of the control register. That seems unsafe to me, should future
> processors add new control bits in the high bits that might sometimes be
> nonzero.
Yeah we can certainly add masking for future proofing.
In some places I have following:
if (((fpcr >> __FPU_RND_SHIFT) & FE_DOWNWARD) != round)
So FE_DOWNWARD (0x3) is used as mask, is that OK or would you rather see
#define __FPU_RND_MASK 0x3
More information about the Libc-alpha
mailing list