Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 9 Jul 2022 21:24:47 -0700
From:      Patrick Mahan <plmahan@gmail.com>
To:        Dimitry Andric <dim@freebsd.org>
Cc:        Marc Veldman <marc@bumblingdork.com>, freebsd-hackers@freebsd.org
Subject:   Re: Canonical way / best practice for 128-bit integers
Message-ID:  <CAFDHx1KtHcvy0Ma8oDASsfRWSz%2B0N3McKDM60uteyPoX_Y6_Eg@mail.gmail.com>
In-Reply-To: <903B6B84-4AFE-4BB5-94F5-5DFD65BAC1B6@FreeBSD.org>
References:  <86CB4C22-9CAB-4578-8F11-962B4B08F756@bumblingdork.com> <903B6B84-4AFE-4BB5-94F5-5DFD65BAC1B6@FreeBSD.org>

next in thread | previous in thread | raw e-mail | index | archive | help
--0000000000006c3c9305e36bd197
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable

On Sat, Jul 9, 2022 at 10:06 AM Dimitry Andric <dim@freebsd.org> wrote:

> On 9 Jul 2022, at 18:26, Marc Veldman <marc@bumblingdork.com> wrote:
> >
> > I=E2=80=99m working on some bluetooth code, and that involves handling =
128-bit
> uuids.
> > There are various ways to handle in the FreeBSD codebase, like in sdp.h=
:
> >
> > /*
> > * SDP int128/uint128 parameter
> > */
> >
> > struct int128 {
> >        int8_t  b[16];
> > };
> > typedef struct int128   int128_t;
> > typedef struct int128   uint128_t;
> >
> > and in sys/dev/random/uint128.h
> >
> > #ifdef USE_REAL_UINT128_T
> > typedef __uint128_t uint128_t;
> > #define UINT128_ZERO 0ULL
> > #else
> > typedef struct {
> >        /* Ignore endianness */
> >        uint64_t u128t_word0;
> >        uint64_t u128t_word1;
> > } uint128_t;
> > static const uint128_t very_long_zero =3D {0UL,0UL};
> > #define UINT128_ZERO very_long_zero
> > #endif
> >
> > Is there any recommended / standard way to handle 128 bit integers in a
> portable way?
>
> Of course recent compilers have built-in support for __int128_t and
> __uint128_t, but it comes with a *lot* of caveats: not supported on all
> architectures, definitely never on 32-bit ones, differences between
> compilers, and even compiler versions, etc etc.
>
> If you want it portable, the only way is to handle them as two 64 bit
> integers, and leave any arithmetic or conversion to library routines.
>
>
I second this, especially if you want to use any of the underlying assembly
code.  For example, the Intel architecture supports the data type but does
not support 128-bit instructions but instead requires you to shift the
upper 64 bits to operate with a 64-bit instruction.

I found this out when we needed to speed up the ability to walk a 128-bit
bitmask (we were doing it the hard way).   I wound up converting everything
back to 64-bit and saw a tremendous speed up in our code.

I mostly use it for defining the storage of an IP address (either IPv4 or
IPv6) where storage does not need to be exceedingly tight.

Also, I have only used it on Intel/AMD architectures.  Back when I was
working in MIPS architectures (mostly Cavium multi-core) we did not have
this data type available.  And I have only briefly looked at AArch64 so it
may or may not be supported there.

Patrick

--0000000000006c3c9305e36bd197
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr"><div dir=3D"ltr">On Sat, Jul 9, 2022 at 10:06 AM Dimitry A=
ndric &lt;<a href=3D"mailto:dim@freebsd.org">dim@freebsd.org</a>&gt; wrote:=
<br></div><div class=3D"gmail_quote"><blockquote class=3D"gmail_quote" styl=
e=3D"margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);paddin=
g-left:1ex">On 9 Jul 2022, at 18:26, Marc Veldman &lt;<a href=3D"mailto:mar=
c@bumblingdork.com" target=3D"_blank">marc@bumblingdork.com</a>&gt; wrote:<=
br>
&gt; <br>
&gt; I=E2=80=99m working on some bluetooth code, and that involves handling=
 128-bit uuids.<br>
&gt; There are various ways to handle in the FreeBSD codebase, like in sdp.=
h:<br>
&gt; <br>
&gt; /*<br>
&gt; * SDP int128/uint128 parameter<br>
&gt; */<br>
&gt; <br>
&gt; struct int128 {<br>
&gt;=C2=A0 =C2=A0 =C2=A0 =C2=A0 int8_t=C2=A0 b[16];<br>
&gt; };<br>
&gt; typedef struct int128=C2=A0 =C2=A0int128_t;<br>
&gt; typedef struct int128=C2=A0 =C2=A0uint128_t;<br>
&gt; <br>
&gt; and in sys/dev/random/uint128.h<br>
&gt; <br>
&gt; #ifdef USE_REAL_UINT128_T<br>
&gt; typedef __uint128_t uint128_t;<br>
&gt; #define UINT128_ZERO 0ULL<br>
&gt; #else<br>
&gt; typedef struct {<br>
&gt;=C2=A0 =C2=A0 =C2=A0 =C2=A0 /* Ignore endianness */<br>
&gt;=C2=A0 =C2=A0 =C2=A0 =C2=A0 uint64_t u128t_word0;<br>
&gt;=C2=A0 =C2=A0 =C2=A0 =C2=A0 uint64_t u128t_word1;<br>
&gt; } uint128_t;<br>
&gt; static const uint128_t very_long_zero =3D {0UL,0UL};<br>
&gt; #define UINT128_ZERO very_long_zero<br>
&gt; #endif<br>
&gt; <br>
&gt; Is there any recommended / standard way to handle 128 bit integers in =
a portable way?<br>
<br>
Of course recent compilers have built-in support for __int128_t and<br>
__uint128_t, but it comes with a *lot* of caveats: not supported on all<br>
architectures, definitely never on 32-bit ones, differences between<br>
compilers, and even compiler versions, etc etc.<br>
<br>
If you want it portable, the only way is to handle them as two 64 bit<br>
integers, and leave any arithmetic or conversion to library routines.<br>
<br></blockquote><div><br></div><div>I second this, especially if you want =
to use any of the underlying assembly code.=C2=A0 For example, the Intel ar=
chitecture supports the data type but does not support 128-bit instructions=
 but instead requires you to shift the upper=C2=A064 bits to operate with a=
 64-bit instruction.</div><div><br></div><div>I found this out when we need=
ed to speed up the ability to walk a 128-bit bitmask (we were doing it the =
hard way).=C2=A0 =C2=A0I wound up converting everything back to 64-bit and =
saw a tremendous speed up in our code.</div><div><br></div><div>I mostly us=
e it for defining the storage of an IP address (either IPv4 or IPv6) where =
storage does not need to be exceedingly tight.</div><div><br></div><div>Als=
o, I have only used it on Intel/AMD architectures.=C2=A0 Back when I was wo=
rking in MIPS architectures (mostly Cavium multi-core) we did not have this=
 data type available.=C2=A0 And I have only briefly looked at AArch64 so it=
 may or may not be supported there.</div><div><br></div><div>Patrick</div><=
/div></div>

--0000000000006c3c9305e36bd197--



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?CAFDHx1KtHcvy0Ma8oDASsfRWSz%2B0N3McKDM60uteyPoX_Y6_Eg>