W
wrschlanger
Does anyone care to comment on the below program I wrote?
The question I was wondering is: why do compilers still use IMUL or MUL forsigned or unsigned multiplication respectively when there is no differencein the numeric value of the result provided the product size is the same as the size of the two factors that are being multiplied together?
This program prints PASS on my screen when I run it. Am I missing something?
Here is what I think is going on. The Intel manual lists IMUL for signed imultiplication and MUL for unsigned. It does this because originally those instructions always doubled capacity, i.e. the product had twice the size ofthe factors.
But then a variant of IMUL was introduced that discards the upper half of the result, i.e. it works like the C * operator. This is still listed as being for "signed" multiplication but it works equally well for unsigned multiplication and might be more efficient because it can take more operands.
Do any compiler writers know about this?? Or do they blindly trust the Intel manuals?
(By the way--interestingly I can't get (unsigned char)(0xff) to equal (signed char)(0xff) in GCC).
---
#include <cstdio>
int main()
{
for(int a = 0; a < 256; ++a)
{
for(int b = 0; b < 256; ++b)
{
signed char sa = a;
signed char sb = b;
unsigned char ua = a;
unsigned char ub = b;
signed char sc = sa * sb;
unsigned char uc = ua * ub;
unsigned char usc = sc;
if(uc != usc)
{
std:rintf("FAIL %02x * %02x = %02x vs. %02x\n", ua, ub, (unsigned int)(unsigned char)(sc), uc);
break;
}
}
}
std:rintf("PASS\n");
return 0;
}
The question I was wondering is: why do compilers still use IMUL or MUL forsigned or unsigned multiplication respectively when there is no differencein the numeric value of the result provided the product size is the same as the size of the two factors that are being multiplied together?
This program prints PASS on my screen when I run it. Am I missing something?
Here is what I think is going on. The Intel manual lists IMUL for signed imultiplication and MUL for unsigned. It does this because originally those instructions always doubled capacity, i.e. the product had twice the size ofthe factors.
But then a variant of IMUL was introduced that discards the upper half of the result, i.e. it works like the C * operator. This is still listed as being for "signed" multiplication but it works equally well for unsigned multiplication and might be more efficient because it can take more operands.
Do any compiler writers know about this?? Or do they blindly trust the Intel manuals?
(By the way--interestingly I can't get (unsigned char)(0xff) to equal (signed char)(0xff) in GCC).
---
#include <cstdio>
int main()
{
for(int a = 0; a < 256; ++a)
{
for(int b = 0; b < 256; ++b)
{
signed char sa = a;
signed char sb = b;
unsigned char ua = a;
unsigned char ub = b;
signed char sc = sa * sb;
unsigned char uc = ua * ub;
unsigned char usc = sc;
if(uc != usc)
{
std:rintf("FAIL %02x * %02x = %02x vs. %02x\n", ua, ub, (unsigned int)(unsigned char)(sc), uc);
break;
}
}
}
std:rintf("PASS\n");
return 0;
}