The bundled SoftFloat64.lib defines bool as an int, following the definition in platform.h.in. This can lead to unexpected behavior in Hercules, as the upper bits of the int may remain uncleared as MSVC/clang-cl compiles bool as a one-byte type.
I first encountered this while compiling Hercules with clang-cl (versions 20.1.8 and 22.1.3) and running the test suite. For example:
Begin: "runtest -d $(DEV)\hyperion\tests\ -v quiet -64" ...
On: Fri 04/17/2026 at 21:38:08 PM
Variable $platform set to "Windows"
>>>>> line 2018: Received unexpected wait state: 0002000000000000 0000000000000BAD
Test "bfp-004-cvttolog": 0 OK compares. One failure.
>>>>> line 2123: Received unexpected wait state: 0002000000000000 0000000000000BAD
Test "bfp-005-cvttolog64": 0 OK compares. One failure.
>>>>> line 2291: Received unexpected wait state: 0002000000000000 0000000000000BAD
Test "bfp-006-cvttofix": 0 OK compares. One failure.
>>>>> line 2456: Received unexpected wait state: 0002000000000000 0000000000000BAD
Test "bfp-007-cvttofix64": 0 OK compares. One failure.
Did 305 tests. 4 failed; 301 OK
Investigating Test "bfp-004-cvttolog", I found that some failures were caused by f64_to_ui32 (in CLFDBR) setting the inexact bit in softfloat_exceptionFlags, even though it should have been suppressed. For reference, here is the (dis)assembly for f64_to_ui32 in SoftFloat64.lib:
.text:0000000000000034 mov edi, r8d
...
.text:000000000000005D mov r9d, edi ;// 'bool' exact
.text:0000000000000060 movzx r8d, sil ;// uint_fast8_t roundingMode
.text:0000000000000064 mov rdx, rax ;// uint_fast64_t sig
.text:0000000000000067 mov ecx, ebx ;// 'bool' sign
.text:0000000000000069 call softfloat_roundToUI32
Jumping to softfloat_roundToUI32:
.text:0000000000000020 mov ebx, r9d
// ...
.text:0000000000000109 test ebx, ebx
.text:000000000000010B jz short loc_113
If bool were defined as a single byte, it is expected those two parameters would be setup with movzx ecx * and movzx r9d * for the softfloat_roundToUI32 call and the test would be 8-bit (or something isomorphic/functionally-equivalent).
In investigating why this bug has been dormant for so long I have provided the relevant snippets from:
Hercules (clang-cl 20.1.8):
.text:00000000000041A1 test r14d, 400h ;// Multiple bytes packed in one register
.text:00000000000041A8 setz r8b ;// x86-64 does not automatically clear the upper bits of the register
.text:00000000000041AC mov rcx, rdi
.text:00000000000041AF call f64_to_ui32
Hercules (MSVC 19.51.36231):
.text:0000000000002F52 movzx r8d, r12b ;// All higher bits of R8 are cleared!
.text:0000000000002F5B shr r8b, 2
// ...
.text:0000000000002F62 not r8b
.text:0000000000002F65 and r8b, 1
// ...
.text:0000000000002F6D call f64_to_ui32
This isn’t urgent; just a reminder to update the bool definition when dependencies are next bumped or recompiled.
The bundled SoftFloat64.lib defines
boolas anint, following the definition in platform.h.in. This can lead to unexpected behavior in Hercules, as the upper bits of theintmay remain uncleared as MSVC/clang-cl compiles bool as a one-byte type.I first encountered this while compiling Hercules with
clang-cl(versions 20.1.8 and 22.1.3) and running the test suite. For example:Investigating
Test "bfp-004-cvttolog", I found that some failures were caused byf64_to_ui32(inCLFDBR) setting theinexactbit insoftfloat_exceptionFlags, even though it should have been suppressed. For reference, here is the (dis)assembly forf64_to_ui32inSoftFloat64.lib:Jumping to softfloat_roundToUI32:
If
boolwere defined as a single byte, it is expected those two parameters would be setup withmovzx ecx *andmovzx r9d *for thesoftfloat_roundToUI32call and thetestwould be 8-bit (or something isomorphic/functionally-equivalent).In investigating why this bug has been dormant for so long I have provided the relevant snippets from:
Hercules (clang-cl 20.1.8):
Hercules (MSVC 19.51.36231):
This isn’t urgent; just a reminder to update the
booldefinition when dependencies are next bumped or recompiled.