gcc built_in functions

Headers, Bindings, Libraries for use with FreeBASIC, Please include example of use to help ensure they are tested and usable.
Post Reply
srvaldez
Posts: 3380
Joined: Sep 25, 2005 21:54

gcc built_in functions

Post by srvaldez »

calling the gcc __builtin functions from FB don't necessarily work with all toolchains, one solution is to make a wrapper lib of your favorite __builtin functions
checking for cpu features can be handy so that one doesn't have to resort to inline asm

to compile with gcc do
gcc -c -O2 built_in.c

then to build the lib do
ar rcs libbuilt_in.a built_in.o

or you can get the binaries here https://u.pcloud.link/publink/show?code ... HBWyjsC1tV

built_in.c

Code: Select all

#include <cpuid.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>

extern int __builtin_cpu_supports (const char *feature);
extern int __builtin_ia32_rdrand16_step (uint16_t *);
extern int __builtin_ia32_rdrand32_step (uint32_t *);

#if __SIZEOF_POINTER__ == 8
    extern int __builtin_ia32_rdrand64_step (uint64_t *);
#endif

int cpu_supports_cmov (void)
{
    return __builtin_cpu_supports ("cmov");
}

int cpu_supports_mmx (void)
{
    return __builtin_cpu_supports ("mmx");
}

int cpu_supports_popcnt (void)
{
    return __builtin_cpu_supports ("popcnt");
}

int cpu_supports_sse (void)
{
    return __builtin_cpu_supports ("sse");
}

int cpu_supports_sse2 (void)
{
    return __builtin_cpu_supports ("sse2");
}

int cpu_supports_sse3 (void)
{
    return __builtin_cpu_supports ("sse3");
}

int cpu_supports_sse41 (void)
{
    return __builtin_cpu_supports ("sse4.1");
}

int cpu_supports_sse42 (void)
{
    return __builtin_cpu_supports ("sse4.2");
}

int cpu_supports_sse4a (void)
{
    return __builtin_cpu_supports ("sse4a");
}

int cpu_supports_avx (void)
{
    return __builtin_cpu_supports ("avx");
}

int cpu_supports_avx2 (void)
{
    return __builtin_cpu_supports ("avx2");
}

int cpu_supports_fma4 (void)
{
    return __builtin_cpu_supports ("fma4");
}

int cpu_supports_xop (void)
{
    return __builtin_cpu_supports ("xop");
}

int cpu_supports_fma (void)
{
    return __builtin_cpu_supports ("fma");
}

int cpu_supports_avx512f (void)
{
    return __builtin_cpu_supports ("avx512f");
}

int cpu_supports_bmi (void)
{
    return __builtin_cpu_supports ("bmi");
}

int cpu_supports_bmi2 (void)
{
    return __builtin_cpu_supports ("bmi2");
}

int cpu_supports_aes (void)
{
    return __builtin_cpu_supports ("aes");
}

int cpu_supports_pclmul (void)
{
    return __builtin_cpu_supports ("pclmul");
}

int cpu_supports_avx512vl (void)
{
    return __builtin_cpu_supports ("avx512vl");
}

int cpu_supports_avx512bw (void)
{
    return __builtin_cpu_supports ("avx512bw");
}

int cpu_supports_avx512dq (void)
{
    return __builtin_cpu_supports ("avx512dq");
}

int cpu_supports_avx512cd (void)
{
    return __builtin_cpu_supports ("avx512cd");
}

int cpu_supports_avx512er (void)
{
    return __builtin_cpu_supports ("avx512er");
}

int cpu_supports_avx512pf (void)
{
    return __builtin_cpu_supports ("avx512pf");
}

int cpu_supports_avx512vbmi (void)
{
    return __builtin_cpu_supports ("avx512vbmi");
}

int cpu_supports_avx512ifma (void)
{
    return __builtin_cpu_supports ("avx512ifma");
}

int cpu_supports_avx5124vnniw (void)
{
    return __builtin_cpu_supports ("avx5124vnniw");
}

int cpu_supports_avx5124fmaps (void)
{
    return __builtin_cpu_supports ("avx5124fmaps");
}

int cpu_supports_avx512vpopcntdq (void)
{
    return __builtin_cpu_supports ("avx512vpopcntdq");
}

int cpu_supports_avx512vbmi2 (void)
{
    return __builtin_cpu_supports ("avx512vbmi2");
}

int cpu_supports_gfni (void)
{
    return __builtin_cpu_supports ("gfni");
}

int cpu_supports_vpclmulqdq (void)
{
    return __builtin_cpu_supports ("vpclmulqdq");
}

int cpu_supports_avx512vnni (void)
{
    return __builtin_cpu_supports ("avx512vnni");
}

int cpu_supports_avx512bitalg (void)
{
    return __builtin_cpu_supports ("avx512bitalg");
}

int cpu_supports_x86_64 (void)
{
    return __builtin_cpu_supports ("x86-64");
}

int cpu_supports_x86_64_v2 (void)
{
    return __builtin_cpu_supports ("x86-64-v2");
}

int cpu_supports_x86_64_v3 (void)
{
    return __builtin_cpu_supports ("x86-64-v3");
}

int cpu_supports_x86_64_v4 (void)
{
    return __builtin_cpu_supports ("x86-64-v4");
}

void call_cpuid(unsigned int EAX_input, unsigned int *eax, unsigned int *ebx, unsigned int *ecx, unsigned int *edx) {
        unsigned int ret;

        ret = __get_cpuid(EAX_input, eax, ebx, ecx, edx);
        if (ret != 1) {
                printf( "Failed to call CPUID with EAX=%d", EAX_input);
        }
}

int ia32_rdrand16_step (uint16_t *r)
{
    return __builtin_ia32_rdrand16_step (r);
}

int ia32_rdrand32_step (uint32_t *r)
{
    return __builtin_ia32_rdrand32_step (r);
}

#if __SIZEOF_POINTER__ == 8
    int ia32_rdrand64_step (uint64_t *r)
    {
        return __builtin_ia32_rdrand64_step (r);
    }
#endif

/*
int main(void)
{
    #if __SIZEOF_POINTER__ == 8
        uint64_t r;
        unsigned int f;
        f=ia32_rdrand64_step (&r);
        printf("%lld\n",r);
    #else
        uint32_t r;
        unsigned int f;
        f=ia32_rdrand32_step (&r);
        printf("%ld\n",r);
    #endif
    return 0;
}
*/
built_in.bi

Code: Select all

#inclib "built_in"

extern "C"

declare function cpu_supports_cmov() as long
declare function cpu_supports_mmx() as long
declare function cpu_supports_popcnt() as long
declare function cpu_supports_sse() as long
declare function cpu_supports_sse2() as long
declare function cpu_supports_sse3() as long
declare function cpu_supports_sse41() as long
declare function cpu_supports_sse42() as long
declare function cpu_supports_sse4a() as long
declare function cpu_supports_avx() as long
declare function cpu_supports_avx2() as long
declare function cpu_supports_fma4() as long
declare function cpu_supports_xop() as long
declare function cpu_supports_fma() as long
declare function cpu_supports_avx512f() as long
declare function cpu_supports_bmi() as long
declare function cpu_supports_bmi2() as long
declare function cpu_supports_aes() as long
declare function cpu_supports_pclmul() as long
declare function cpu_supports_avx512vl() as long
declare function cpu_supports_avx512bw() as long
declare function cpu_supports_avx512dq() as long
declare function cpu_supports_avx512cd() as long
declare function cpu_supports_avx512er() as long
declare function cpu_supports_avx512pf() as long
declare function cpu_supports_avx512vbmi() as long
declare function cpu_supports_avx512ifma() as long
declare function cpu_supports_avx5124vnniw() as long
declare function cpu_supports_avx5124fmaps() as long
declare function cpu_supports_avx512vpopcntdq() as long
declare function cpu_supports_avx512vbmi2() as long
declare function cpu_supports_gfni() as long
declare function cpu_supports_vpclmulqdq() as long
declare function cpu_supports_avx512vnni() as long
declare function cpu_supports_avx512bitalg() as long
declare function cpu_supports_x86_64() as long
declare function cpu_supports_x86_64_v2() as long
declare function cpu_supports_x86_64_v3() as long
declare function cpu_supports_x86_64_v4() as long
declare sub call_cpuid(byval EAX_input as ulong, byref eax as ulong, byref ebx as ulong, byref ecx as ulong, byref edx as ulong)
declare function ia32_rdrand16_step (byref as ushort) as ulong
declare function ia32_rdrand32_step (byref as ulong) as ulong
declare function ia32_rdrand64_step (byref as ulongint) as ulong
end extern
simple test

Code: Select all

'#cmdline "-asm att -w all -arch native -gen clang -Wc -O2"

#include "built_in.bi"

union cpuid
    as ulong r(2)
    as string*12 id
end union

function cpu_id() as string
    dim as cpuid id
    dim as ulong Reax
    call_cpuid(0, Reax, id.r(0), id.r(2), id.r(1))
    return id.id
end function

Print "cpu_supports_aes   = ";cpu_supports_aes
Print "cpu_supports_avx   = ";cpu_supports_avx
Print "cpu_supports_avx2  = ";cpu_supports_avx2
Print "cpu_supports_sse42 = ";cpu_supports_sse42

Print "cpu id = ";cpu_id

dim as ulong r
dim as ulongint rr

if ia32_rdrand32_step (r)<>0 then
	Print "r = ";r
end if
#ifdef __FB_64BIT__
	if ia32_rdrand64_step(rr)<>0 then
		Print "rr = ";rr
	end if
#endif
Sleep
a non-zero result means that the function is supported
a zero result means that the function is not supported
see https://gcc.gnu.org/onlinedocs/gcc/x86- ... tions.html
https://gcc.gnu.org/onlinedocs/gcc/Other-Builtins.html
https://gcc.gnu.org/onlinedocs/gcc/Inte ... ltins.html

<edit> added binaries and added the __builtin_ia32_rdrandxx functions
Last edited by srvaldez on Apr 12, 2024 12:24, edited 1 time in total.
deltarho[1859]
Posts: 4313
Joined: Jan 02, 2017 0:34
Location: UK
Contact:

Re: gcc built_in functions

Post by deltarho[1859] »

@srvaldez

If you want some feedback on this thread, you'll have to 'dumb it down' a bit.

> 'gcc -c -O2 built_in.c'

You have obviously learnt a few undocumented shortcuts to command lines, but that will not work as a command line, and it will not produce an 'o' file expected in the next statement.

> 'ar rcs libbuilt_in.a built_in.o'

What is that?

Now I know that every toolchain has, in '\bin\winXX', ar.exe, but they are different with each toolchain. Most members will not have seen ar.exe.

At an admin Command Prompt I tried 'ar /?' but it was not recognised.

I searched my C Drive for ar.exe, but I haven't got one.

So, back to gcc — which ar.exe are you using?
marcov
Posts: 3462
Joined: Jun 16, 2005 9:45
Location: Netherlands
Contact:

Re: gcc built_in functions

Post by marcov »

(afaik ar doesn't respect windows switch char, and must be queried with ar -? )
deltarho[1859]
Posts: 4313
Joined: Jan 02, 2017 0:34
Location: UK
Contact:

Re: gcc built_in functions

Post by deltarho[1859] »

ar is a GNU Binary Utility, apparently.

srvaldez knocked out some great instructions recently regarding toolchains and made no assumptions about the reader's expertise.

'ar rcs libbuilt_in.a built_in.o' without further ado is not helpful.
marcov
Posts: 3462
Joined: Jun 16, 2005 9:45
Location: Netherlands
Contact:

Re: gcc built_in functions

Post by marcov »

deltarho[1859] wrote: Apr 12, 2024 8:16 'ar rcs libbuilt_in.a built_in.o' without further ado is not helpful.
If you had done ar -? you would have read:

r=Add/or replace .o into .a archive
c= do not warn if library has to be created
s=create an archive index (ranlib)

If I can do it, why can't you?
deltarho[1859]
Posts: 4313
Joined: Jan 02, 2017 0:34
Location: UK
Contact:

Re: gcc built_in functions

Post by deltarho[1859] »

marcov wrote:If I can do it, why can't you?
Bit too early in the morning for you to employ a civil tongue?
srvaldez
Posts: 3380
Joined: Sep 25, 2005 21:54

Re: gcc built_in functions

Post by srvaldez »

hello deltarho[1859] :)
I edited my opening post and included a link for the binaries, I also included the random functions
the following works with clang but not with gcc unless you use gcc-9.3.0 from winlibs

Code: Select all

extern "C"
    declare function __builtin_ia32_rdrand16_step (byref as ushort) as ulong
    declare function __builtin_ia32_rdrand32_step (byref as ulong) as ulong
    #ifdef __FB_64BIT__
        declare function __builtin_ia32_rdrand64_step (byref as ulongint) as ulong
    #endif
end extern
so I included them in the wrapper library but dropped the __builtin_ from their names, so the following works

Code: Select all

dim as ulong r

ia32_rdrand32_step (r)
Print "r = ";r
having the cpuid function available should come in handy
Post Reply