Print this page
5224 snprintf rounding under [default] FE_TONEAREST

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