diff --git a/libc/config/windows/entrypoints.txt b/libc/config/windows/entrypoints.txt --- a/libc/config/windows/entrypoints.txt +++ b/libc/config/windows/entrypoints.txt @@ -17,9 +17,6 @@ libc.src.ctype.tolower libc.src.ctype.toupper - # errno.h entrypoints - libc.src.errno.__errno_location - # string.h entrypoints libc.src.string.bcmp libc.src.string.bzero diff --git a/libc/src/__support/FPUtil/x86_64/FEnvImpl.h b/libc/src/__support/FPUtil/x86_64/FEnvImpl.h --- a/libc/src/__support/FPUtil/x86_64/FEnvImpl.h +++ b/libc/src/__support/FPUtil/x86_64/FEnvImpl.h @@ -345,8 +345,8 @@ // MSVC fenv.h defines a very simple representation of the floating point state // which just consists of control and status words of the x87 unit. struct FPState { - uint32_t ControlWord; - uint32_t StatusWord; + uint32_t control_word; + uint32_t status_word; }; #else struct FPState { @@ -364,20 +364,51 @@ #ifdef _WIN32 static inline int get_env(fenv_t *envp) { internal::FPState *state = reinterpret_cast(envp); - internal::X87StateDescriptor X87Status; - internal::getX87StateDescriptor(X87Status); - state->ControlWord = X87Status.ControlWord; - state->StatusWord = X87Status.StatusWord; + internal::X87StateDescriptor x87_status; + internal::get_x87_state_descriptor(x87_status); + state->control_word = x87_status.control_word; + state->status_word = x87_status.status_word; return 0; } static inline int set_env(const fenv_t *envp) { const internal::FPState *state = reinterpret_cast(envp); - internal::X87StateDescriptor X87Status; - X87Status.ControlWord = state->ControlWord; - X87Status.StatusWord = state->StatusWord; - internal::writeX87StateDescriptor(X87Status); + internal::X87StateDescriptor x87_status; + + if (envp == FE_DFL_ENV) { + // Reset the exception flags in the status word. + x87_status.status_word &= ~uint16_t(0x3F); + // Reset other non-sensitive parts of the status word. + for (int i = 0; i < 5; i++) + x87_status._[i] = 0; + // In the control word, we do the following: + // 1. Mask all exceptions + // 2. Set rounding mode to round-to-nearest + // 3. Set the internal precision to double extended precision. + x87_status.control_word |= uint16_t(0x3F); // Mask all exceptions. + x87_status.control_word &= ~(uint16_t(0x3) << 10); // Round to nearest. + x87_status.control_word |= (uint16_t(0x3) << 8); // Extended precision. + internal::write_x87_state_descriptor(x87_status); + + // We take the exact same approach MXCSR register as well. + // MXCSR has two additional fields, "flush-to-zero" and + // "denormals-are-zero". We reset those bits. Also, MXCSR does not + // have a field which controls the precision of internal operations. + uint32_t mxcsr = internal::get_mxcsr(); + mxcsr &= ~uint16_t(0x3F); // Clear exception flags. + mxcsr &= ~(uint16_t(0x1) << 6); // Reset denormals-are-zero + mxcsr |= (uint16_t(0x3F) << 7); // Mask exceptions + mxcsr &= ~(uint16_t(0x3) << 13); // Round to nearest. + mxcsr &= ~(uint16_t(0x1) << 15); // Reset flush-to-zero + internal::write_mxcsr(mxcsr); + + return 0; + } + + x87_status.control_word = state->control_word; + x87_status.status_word = state->status_word; + internal::write_x87_state_descriptor(x87_status); return 0; } #else