Print this page
5224 snprintf rounding under [default] FE_TONEAREST

Split Close
Expand all
Collapse all
          --- old/usr/src/lib/libc/i386/fp/_base_il.c
          +++ new/usr/src/lib/libc/i386/fp/_base_il.c
↓ open down ↓ 30 lines elided ↑ open up ↑
  31   31  
  32   32  /* The following should be coded as inline expansion templates.  */
  33   33  
  34   34  /*
  35   35   * Multiplies two normal or subnormal doubles, returns result and exceptions.
  36   36   */
  37   37  double
  38   38  __mul_set(double x, double y, int *pe) {
  39   39          extern void _putsw(), _getsw();
  40   40          int sw;
  41      -        double z;
       41 +        volatile double z;
  42   42  
  43   43          _putsw(0);
       44 +        /*
       45 +         * NOTE:  By declaring 'z' volatile above, we intend for the
       46 +         * compiler to not move this after the _getmxcsr() call, whose results
       47 +         * are only useful if they immediately follow the multiply.
       48 +         *
       49 +         * From the C11 spec:
       50 +         *
       51 +         * 134 - A volatile declaration may be used to describe an
       52 +         * object corresponding to a memory-mapped input/output port
       53 +         * or an object accessed by an asynchronously interrupting
       54 +         * function. Actions on objects so declared shall by an
       55 +         * implementation or reordered except as permitted by the
       56 +         * rules for evaluating expressions."
       57 +         */
  44   58          z = x * y;
  45   59          _getsw(&sw);
  46   60          if ((sw & 0x3f) == 0) {
  47   61                  *pe = 0;
  48   62          } else {
  49   63                  /* Result may not be exact. */
  50   64                  *pe = 1;
  51   65          }
  52   66          return (z);
  53   67  }
  54   68  
  55   69  /*
  56   70   * Divides two normal or subnormal doubles x/y, returns result and exceptions.
  57   71   */
  58   72  double
  59   73  __div_set(double x, double y, int *pe) {
  60   74          extern void _putsw(), _getsw();
  61   75          int sw;
  62      -        double z;
       76 +        volatile double z;
  63   77  
  64   78          _putsw(0);
       79 +        /* NOTE:  See __mul_set() above, same principle applies here. */
  65   80          z = x / y;
  66   81          _getsw(&sw);
  67   82          if ((sw & 0x3f) == 0) {
  68   83                  *pe = 0;
  69   84          } else {
  70   85                  *pe = 1;
  71   86          }
  72   87          return (z);
  73   88  }
  74   89  
↓ open down ↓ 39 lines elided ↑ open up ↑
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX