• Welcome to Valhalla Legends Archive.
 

mul/imul

Started by Eibro, November 17, 2004, 10:19 PM

Previous topic - Next topic

Eibro

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.
Eibro of Yeti Lovers.

Kp

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
[19:20:23] (BotNet) <[vL]Kp> Any idiot can make a bot with CSB, and many do!

Skywing

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.

Eibro

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.
Eibro of Yeti Lovers.

Eibro

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.
Eibro of Yeti Lovers.

Skywing

For future reference, you might want to compare the code generated by the compiler there and the UInt32x32To64 macro.

Kp

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.
[19:20:23] (BotNet) <[vL]Kp> Any idiot can make a bot with CSB, and many do!

Eibro

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.
Eibro of Yeti Lovers.