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 <<a href=3D"mailto:dim@freebsd.org">dim@freebsd.org</a>> 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 <<a href=3D"mailto:mar= c@bumblingdork.com" target=3D"_blank">marc@bumblingdork.com</a>> wrote:<= br> > <br> > I=E2=80=99m working on some bluetooth code, and that involves handling= 128-bit uuids.<br> > There are various ways to handle in the FreeBSD codebase, like in sdp.= h:<br> > <br> > /*<br> > * SDP int128/uint128 parameter<br> > */<br> > <br> > struct int128 {<br> >=C2=A0 =C2=A0 =C2=A0 =C2=A0 int8_t=C2=A0 b[16];<br> > };<br> > typedef struct int128=C2=A0 =C2=A0int128_t;<br> > typedef struct int128=C2=A0 =C2=A0uint128_t;<br> > <br> > and in sys/dev/random/uint128.h<br> > <br> > #ifdef USE_REAL_UINT128_T<br> > typedef __uint128_t uint128_t;<br> > #define UINT128_ZERO 0ULL<br> > #else<br> > typedef struct {<br> >=C2=A0 =C2=A0 =C2=A0 =C2=A0 /* Ignore endianness */<br> >=C2=A0 =C2=A0 =C2=A0 =C2=A0 uint64_t u128t_word0;<br> >=C2=A0 =C2=A0 =C2=A0 =C2=A0 uint64_t u128t_word1;<br> > } uint128_t;<br> > static const uint128_t very_long_zero =3D {0UL,0UL};<br> > #define UINT128_ZERO very_long_zero<br> > #endif<br> > <br> > 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>