Reputation: 2876
Assume we have:
a = 0b11111001;
b = 0b11110011;
If we do Addition
and Multiplication
on paper with hand we get this result, we don't care if its signed or not:
a + b = 111101100
a * b = 1110110001011011
I know that Multiplication doubles the width and addition could overflow:
Why is imul used for multiplying unsigned numbers?
Why do some CPUs have different instructions to do signed and unsigned operations?
My question is, why instructions like Add
don't usually have a signed/unsigned version, but Multiply
and Divide
do?
Why can't we have a generic unsigned multiply
, do the math like I did above and truncate the result if its singed, same way Add
does.
Or the other, why can't Add
have a signed/unsigned version. I have checked a few architectures and this seems to be the case.
Upvotes: 1
Views: 298
Reputation: 363980
I think your choice of example misled you into thinking the signed product could be obtained by truncating the 8x8 => 16-bit unsigned product down to 8 bits. That is not the case.
(249-256) * (243-256)
= 0x005b
, a small positive result that happens to fit in the low half of the full result. But the full signed result is not always the operand-size truncation of the unsigned product.
For example, -128 * 127
is -16256
, or as 16-bit 2's complement, 0xc080
.
But 0x80 * 0x7f
is + 16256, i.e. 0x3f80
. Same low half, different upper half.
Or for another example, see Why are signed and unsigned multiplication different instructions on x86(-64)?
Widening signed-multiply doesn't involve any truncation. The low half of signed and unsigned multiply is the same, that's why x86 for example only has immediate and 2-operand forms of imul
, not also mul
. Only widening multiply needs a separate form. (Or if you want FLAGS set according to unsigned overflow of the low half, instead of signed overflow. - so you can't easily use non-widening imul
if you want to detect when the full unsigned result didn't fit.)
Upvotes: 1