A byproduct of many value producing operations is that you get certain properties of the result value for free.
In traditional architectures those status flags are kept in a global status register, and each operation that produces status flags replaces the previous value.
This approach has two major drawbacks:
For one those bits are only rarely needed, yet they are part of the thread and process space and always need to be preserved, just in case.
And then of course you are limited to the most recently produced status flags.
Both means, as global changeable data usually does, a big obstacle to parallelism and speculative execution.
The Mill takes a different approach. There is no global status flag register. A lot of operations still produce these flags as condition codes, but usually they get immediately discarded. Only when the program actually needs one or more of these condition codes, as determined by the compiler, they get explicitly extracted into the belt with a dedicated operation, which is ganged with the actual value and condition code producing operation. And from the belt other operations can make use of it as normal arguments.
The condition codes, and their respective extracting operation names are:
- carry - for unsigned integer this is also the overflow
- fault - when a NaR is produced
The condition codes are generated and are available for extraction no matter what the overflow behavior of the operation itself is. Even modulo wraparound operations produce overflow and carry codes.