packages feed

Box2D-0.1.0.0: upstream/src/simd.c

// SPDX-FileCopyrightText: 2026 Erin Catto
// SPDX-License-Identifier: MIT

#include "simd.h"

#include "platform.h"

#include <stdbool.h>
#include <stdint.h>

static b2AtomicInt b2_simdWidth;

#if defined( B2_SIMD_HAS_WIDTH_8 )

#if defined( _MSC_VER )
#include <intrin.h>
#endif

// This code enables runtime dispatch to AVX2.
// Inspired by https://github.com/simdjson/simdjson/blob/master/src/internal/isadetection.h

static void b2CpuId( unsigned int leaf, unsigned int subLeaf, unsigned int registers[4] )
{
#if defined( _MSC_VER )
	int info[4];
	__cpuidex( info, (int)leaf, (int)subLeaf );
	registers[0] = (unsigned int)info[0];
	registers[1] = (unsigned int)info[1];
	registers[2] = (unsigned int)info[2];
	registers[3] = (unsigned int)info[3];
#else
	// clang cpuid.h can give the rbx swap register the same register as the leaf input, clobbering rbx
	__asm__ volatile( "cpuid"
					  : "=a"( registers[0] ), "=b"( registers[1] ), "=c"( registers[2] ), "=d"( registers[3] )
					  : "a"( leaf ), "c"( subLeaf ) );
#endif
}

static uint64_t b2GetExtendedControlRegister( void )
{
#if defined( _MSC_VER ) && !defined( __clang__ )
	return _xgetbv( 0 );
#else
	uint32_t low, high;
	__asm__ volatile( "xgetbv" : "=a"( low ), "=d"( high ) : "c"( 0 ) );
	return ( (uint64_t)high << 32 ) | low;
#endif
}

static bool b2HasAVX2( void )
{
	unsigned int registers[4];
	b2CpuId( 0, 0, registers );
	if ( registers[0] < 7 )
	{
		return false;
	}

	b2CpuId( 1, 0, registers );
	unsigned int osxsaveAndAvx = ( 1u << 27 ) | ( 1u << 28 );
	if ( ( registers[2] & osxsaveAndAvx ) != osxsaveAndAvx )
	{
		return false;
	}

	if ( ( b2GetExtendedControlRegister() & 6 ) != 6 )
	{
		return false;
	}

	b2CpuId( 7, 0, registers );
	return ( registers[1] & ( 1u << 5 ) ) != 0;
}

#endif

static int b2DetectSIMDWidth( void )
{
#if defined( B2_SIMD_HAS_WIDTH_8 )
	return b2HasAVX2() ? 8 : 4;
#else
	return 4;
#endif
}

int b2GetSIMDWidth( void )
{
	int width = b2AtomicLoadInt( &b2_simdWidth );
	if ( width == 0 )
	{
		width = b2DetectSIMDWidth();
		b2AtomicStoreInt( &b2_simdWidth, width );
	}

	return width;
}

bool b2IsAVX2Available( void )
{
	return b2DetectSIMDWidth() == 8;
}

void b2SetSIMDWidth( int width )
{
	B2_ASSERT( width == 0 || width == 4 || width == 8 );
	if ( width == 8 && b2DetectSIMDWidth() != 8 )
	{
		width = 4;
	}

	b2AtomicStoreInt( &b2_simdWidth, width );
}