NO

Author Topic: 128-bit intrinsic math buggy?  (Read 6021 times)

Offline Akko

  • Member
  • *
  • Posts: 31
128-bit intrinsic math buggy?
« 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.

Offline frankie

  • Global Moderator
  • Member
  • *****
  • Posts: 2114
Re: 128-bit intrinsic math buggy?
« Reply #1 on: May 26, 2023, 11:49:40 PM »
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.
"It is better to be hated for what you are than to be loved for what you are not." - Andre Gide

Offline Pelle

  • Administrator
  • Member
  • *****
  • Posts: 2266
    • http://www.smorgasbordet.com
Re: 128-bit intrinsic math buggy?
« Reply #2 on: May 27, 2023, 01:12:52 PM »
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.
/Pelle

Offline frankie

  • Global Moderator
  • Member
  • *****
  • Posts: 2114
Re: 128-bit intrinsic math buggy?
« Reply #3 on: May 27, 2023, 04:00:40 PM »
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.   ;)
« Last Edit: May 27, 2023, 04:05:54 PM by frankie »
"It is better to be hated for what you are than to be loved for what you are not." - Andre Gide

Offline Akko

  • Member
  • *
  • Posts: 31
Re: 128-bit intrinsic math buggy?
« Reply #4 on: May 27, 2023, 11:54:41 PM »
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.   

Offline Pelle

  • Administrator
  • Member
  • *****
  • Posts: 2266
    • http://www.smorgasbordet.com
Re: 128-bit intrinsic math buggy?
« Reply #5 on: May 28, 2023, 10:59:59 AM »
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.
/Pelle

Offline Akko

  • Member
  • *
  • Posts: 31
Re: 128-bit intrinsic math buggy?
« Reply #6 on: June 05, 2023, 08:42:52 AM »
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;
}
« Last Edit: June 06, 2023, 09:17:43 AM by Akko »