Valhalla Legends Archive

Programming => General Programming => Assembly Language (any cpu) => Topic started by: Eibro on November 17, 2004, 10:19 PM

Title: mul/imul
Post by: Eibro on November 17, 2004, 10:19 PM
mul -- unsigned multiply.
I want to convert the following into C++
mov     eax, bufdata
mul     factor
add     eax, tableval
adc     edx, 0x0
mov     bufdata, eax
mov     tableval, edx


Yet everytime I try the compiler generates an imul (signed multiply) instruction even though both the operands are unsigned. eg. This will generate an imul (using cl)

unsigned bufdata = pbuf[buflen - i - 1];
unsigned __int64 result = bufdata * factor + tableval;

tableval = ( result >> 32 );
pbuf[buflen - i - 1] = result & 0xffffffff;
I don't understand why it is doing this.
Title: Re: mul/imul
Post by: Kp on November 17, 2004, 11:02 PM
Maybe 'unsigned __int64' is confusing cl (since int64 is an MSVC extension).  Try using unsigned long long (under gcc).  The following code produces a 64bit mull for me:

extern unsigned pbuf[];
unsigned tableval, factor;
typedef unsigned long long uint64_t;
int m(int a, char **b) {
(void)(a&&b);
unsigned bufdata = pbuf[0];
unsigned long long result = ((uint64_t)bufdata) * ((uint64_t)factor) + ((uint64_t)tableval);
tableval = ( result >> 32 );
pbuf[1] = result & 0xffffffff;
return 0;
}

Produces:_m:
movl _factor, %ecx
movl _pbuf, %eax
pushl %ebx
mull %ecx
movl %eax, %ecx
movl %edx, %ebx
movl _tableval, %eax
xorl %edx, %edx
addl %eax, %ecx
adcl %edx, %ebx
movl %ecx, _pbuf+4
xorl %eax, %eax
movl %ebx, _tableval
popl %ebx
ret
Title: Re: mul/imul
Post by: Skywing on November 17, 2004, 11:55 PM
Quote from: Eibro[yL] on November 17, 2004, 10:19 PM
mul -- unsigned multiply.
I want to convert the following into C++
mov     eax, bufdata
mul     factor
add     eax, tableval
adc     edx, 0x0
mov     bufdata, eax
mov     tableval, edx


Yet everytime I try the compiler generates an imul (signed multiply) instruction even though both the operands are unsigned. eg. This will generate an imul (using cl)

unsigned bufdata = pbuf[buflen - i - 1];
unsigned __int64 result = bufdata * factor + tableval;

tableval = ( result >> 32 );
pbuf[buflen - i - 1] = result & 0xffffffff;
I don't understand why it is doing this.
Try casting the * operands to 64-bit numbers.
Title: Re: mul/imul
Post by: Eibro on November 18, 2004, 06:13 AM
Quote from: Skywing on November 17, 2004, 11:55 PM
Quote from: Eibro[yL] on November 17, 2004, 10:19 PM
mul -- unsigned multiply.
I want to convert the following into C++
mov     eax, bufdata
mul     factor
add     eax, tableval
adc     edx, 0x0
mov     bufdata, eax
mov     tableval, edx


Yet everytime I try the compiler generates an imul (signed multiply) instruction even though both the operands are unsigned. eg. This will generate an imul (using cl)

unsigned bufdata = pbuf[buflen - i - 1];
unsigned __int64 result = bufdata * factor + tableval;

tableval = ( result >> 32 );
pbuf[buflen - i - 1] = result & 0xffffffff;
I don't understand why it is doing this.
Try casting the * operands to 64-bit numbers.
Yep. That did it.
Thanks Skywing & Kp.
Title: Re: mul/imul
Post by: Eibro on November 18, 2004, 06:37 AM
Quote from: Kp on November 17, 2004, 11:02 PM
Maybe 'unsigned __int64' is confusing cl (since int64 is an MSVC extension).  Try using unsigned long long (under gcc).  The following code produces a 64bit mull for me:

extern unsigned pbuf[];
unsigned tableval, factor;
typedef unsigned long long uint64_t;
int m(int a, char **b) {
(void)(a&&b);
unsigned bufdata = pbuf[0];
unsigned long long result = ((uint64_t)bufdata) * ((uint64_t)factor) + ((uint64_t)tableval);
tableval = ( result >> 32 );
pbuf[1] = result & 0xffffffff;
return 0;
}

Produces:_m:
movl _factor, %ecx
movl _pbuf, %eax
pushl %ebx
mull %ecx
movl %eax, %ecx
movl %edx, %ebx
movl _tableval, %eax
xorl %edx, %edx
addl %eax, %ecx
adcl %edx, %ebx
movl %ecx, _pbuf+4
xorl %eax, %eax
movl %ebx, _tableval
popl %ebx
ret

Hmm it doesn't seem as if cl was confused (unless gcc is too). gcc emitted the same imul if the operands were 32 bits wide.
Title: Re: mul/imul
Post by: Skywing on November 18, 2004, 01:00 PM
For future reference, you might want to compare the code generated by the compiler there and the UInt32x32To64 macro.
Title: Re: mul/imul
Post by: Kp on November 19, 2004, 06:26 PM
Quote from: Eibro[yL] on November 18, 2004, 06:37 AMHmm it doesn't seem as if cl was confused (unless gcc is too). gcc emitted the same imul if the operands were 32 bits wide.

What C code did you feed to gcc?  Your MSVC code won't work verbatim due to the difference over what to name a 64bit number.
Title: Re: mul/imul
Post by: Eibro on November 19, 2004, 10:27 PM
Quote from: Kp on November 19, 2004, 06:26 PM
Quote from: Eibro[yL] on November 18, 2004, 06:37 AMHmm it doesn't seem as if cl was confused (unless gcc is too). gcc emitted the same imul if the operands were 32 bits wide.

What C code did you feed to gcc?  Your MSVC code won't work verbatim due to the difference over what to name a 64bit number.
The code you posted, less the casting.