For unsigned addition and subtraction, MSVC has _addcarry_u16/32/64
and _subborrow_u16/32/64
, all defined in <intrin.h>. They seem to produce optimal code, including generating add
and sub
instead of adc
and sbb
if you pass constant 0 for the carry in.
Unfortunately, there are no analogous intrinsics that return the overflow flag.
For 64×64 multiplication, __mulh
and __umulh
return the high 64 bits of the result, which you can compare with 0 in the unsigned case or low >> 63
in the signed case. There are also _[u]mul128
functions that return the whole result, but I think they would be more cumbersome to use and would generate the same code with optimization on (I haven't tested that).
For division, there are _[u]div64
and _[u]div128
, defined in <immintrin.h>
. It seems to be undocumented what they do in the case of overflow, but they most likely raise #DE, which could be caught with SEH.
In other cases, there's probably nothing better than to calculate the result at a higher precision and then bounds-check it.