Pelles C forum
C language => Expert questions => Topic started by: Akko on May 24, 2023, 12:21:06 AM
-
The following code works in MSVC (64-bit) but I cannot make it run in PC12 (64-bit console):
// Intrinsic 128-bit multiplication/division test
#include <stdlib.h>
#include <stdint.h>
#include <stdio.h>
#include <intrin.h>
int main(void) {
uint64_t upl,uph,uq,ur=7;
upl=_umul128(-1,2,&uph);
printf("\nuph=1?%d upl=-2?%d",(int)uph,(int)upl);
uq=_udiv128(uph,upl,2,&ur);
printf("\nuq=-1?%d ur=0?%d",(int)uq,(int)ur);
return 0;
}
I tried /Ze compiler flags et cetera, but PC12 always struggles with the division :-(
Multiplication is no issue.
-
It seems that for the functions _umul128() and _udiv128() the compiler don't emits the intrinsic code, but emits a call to the specific function that, obviously, is missing (doesn't exist in any library).
For me is a compiler bug.
-
Confirmed.
The compiler internal intrinsic signature for __udiv128 (and _udiv128 if you insist on using the /Ze option) contains (signed) __int64 while the externally visible signature contains (the correct) unsigned __int64. The signatures will never match, so you get the default behavior of calling an external function.
AFAICT this has been broken since __udiv128 and _udiv128 were introduced in version 10 (you guys did a poor job of testing... :P). With version 12 being done, this will be fixed in some possible future version.
-
Confirmed.
....
AFAICT this has been broken since __udiv128 and _udiv128 were introduced in version 10 (you guys did a poor job of testing... :P).
LOL ;D :D ;D :D ;D :D ;D :D ;D
Of course you're absolutely right Pelle. ;)
-
AFAICT also clang has/had similar difficulties with compiling (u)int128_t intrinsics.
Here clang lags behind gcc that has working builtins since long.
I can understand why Pelles C does not support a 64-bit assembler, but for such cases
it would be nice to have one. Long division (eg shift-subtract) in C is painfully slow.
-
As explained in the help file ("Appendix" : "The inline assembler for X64"), mixing inline assembly and C code in the same function is a bad idea. When creating a whole function using inline assembly, it shouldn't be too hard moving this code to a separate file and use POASM. If problems, ask and someone in this forum will surely help you.
-
The signed _mul128 intrinsic is buggy too. Perhaps the similar problem as with _udiv128 ...
Test code (ph should be 0):
// Intrinsic 128-bit multiplication test
#include <stdlib.h>
#include <stdint.h>
#include <stdio.h>
#include <intrin.h>
int main(void) {
int64_t ph=-7, pl=7;
pl=_mul128((int64_t)-3,(int64_t)-3,&ph);
printf("\npl=9?%d ph=0?%d",(int)pl,(int)ph);
return 0;
}