Print this page
5224 snprintf rounding under [default] FE_TONEAREST

*** 39,51 **** */ double __mul_set(double x, double y, int *pe) { extern void _putmxcsr(), _getmxcsr(); int csr; ! double z; _putmxcsr(CSR_DEFAULT); z = x * y; _getmxcsr(&csr); if ((csr & 0x3f) == 0) { *pe = 0; } else { --- 39,65 ---- */ double __mul_set(double x, double y, int *pe) { extern void _putmxcsr(), _getmxcsr(); int csr; ! volatile double z; _putmxcsr(CSR_DEFAULT); + /* + * NOTE: By declaring 'z' volatile above, we intend for the + * compiler to not move this after the _getmxcsr() call, whose results + * are only useful if they immediately follow the multiply. + * + * From the C11 spec: + * + * 134 - A volatile declaration may be used to describe an + * object corresponding to a memory-mapped input/output port + * or an object accessed by an asynchronously interrupting + * function. Actions on objects so declared shall by an + * implementation or reordered except as permitted by the + * rules for evaluating expressions." + */ z = x * y; _getmxcsr(&csr); if ((csr & 0x3f) == 0) { *pe = 0; } else {
*** 60,72 **** */ double __div_set(double x, double y, int *pe) { extern void _putmxcsr(), _getmxcsr(); int csr; ! double z; _putmxcsr(CSR_DEFAULT); z = x / y; _getmxcsr(&csr); if ((csr & 0x3f) == 0) { *pe = 0; } else { --- 74,87 ---- */ double __div_set(double x, double y, int *pe) { extern void _putmxcsr(), _getmxcsr(); int csr; ! volatile double z; _putmxcsr(CSR_DEFAULT); + /* NOTE: See __mul_set() above, same principle applies here. */ z = x / y; _getmxcsr(&csr); if ((csr & 0x3f) == 0) { *pe = 0; } else {