mirror of
				https://github.com/Ed94/gencpp.git
				synced 2025-10-31 06:50:53 -07:00 
			
		
		
		
	
		
			
				
	
	
		
			168 lines
		
	
	
		
			4.1 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			168 lines
		
	
	
		
			4.1 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| #ifdef GEN_INTELLISENSE_DIRECTIVES
 | |
| #	pragma once
 | |
| #	include "filesystem.cpp"
 | |
| #endif
 | |
| 
 | |
| #pragma region Timing
 | |
| 
 | |
| #ifdef GEN_BENCHMARK
 | |
| 	#if defined( GEN_COMPILER_MSVC ) && ! defined( __clang__ )
 | |
| 	u64 read_cpu_time_stamp_counter( void )
 | |
| 	{
 | |
| 		return __rdtsc();
 | |
| 	}
 | |
| 	#elif defined( __i386__ )
 | |
| 	u64 read_cpu_time_stamp_counter( void )
 | |
| 	{
 | |
| 		u64 x;
 | |
| 		__asm__ volatile( ".byte 0x0f, 0x31" : "=A"( x ) );
 | |
| 		return x;
 | |
| 	}
 | |
| 	#elif defined( __x86_64__ )
 | |
| 	u64 read_cpu_time_stamp_counter( void )
 | |
| 	{
 | |
| 		u32 hi, lo;
 | |
| 		__asm__ __volatile__( "rdtsc" : "=a"( lo ), "=d"( hi ) );
 | |
| 		return scast( u64, lo ) | ( scast( u64, hi ) << 32 );
 | |
| 	}
 | |
| 	#elif defined( __powerpc__ )
 | |
| 	u64 read_cpu_time_stamp_counter( void )
 | |
| 	{
 | |
| 		u64 result = 0;
 | |
| 		u32 upper, lower, tmp;
 | |
| 		__asm__ volatile(
 | |
| 			"0:                   \n"
 | |
| 			"\tmftbu   %0         \n"
 | |
| 			"\tmftb    %1         \n"
 | |
| 			"\tmftbu   %2         \n"
 | |
| 			"\tcmpw    %2,%0      \n"
 | |
| 			"\tbne     0b         \n"
 | |
| 			: "=r"( upper ), "=r"( lower ), "=r"( tmp )
 | |
| 		);
 | |
| 		result = upper;
 | |
| 		result = result << 32;
 | |
| 		result = result | lower;
 | |
| 
 | |
| 		return result;
 | |
| 	}
 | |
| 	#elif defined( GEN_SYSTEM_EMSCRIPTEN )
 | |
| 	u64 read_cpu_time_stamp_counter( void )
 | |
| 	{
 | |
| 		return ( u64 )( emscripten_get_now() * 1e+6 );
 | |
| 	}
 | |
| 	#elif defined( GEN_CPU_ARM ) && ! defined( GEN_COMPILER_TINYC )
 | |
| 	u64 read_cpu_time_stamp_counter( void )
 | |
| 	{
 | |
| 	#	if defined( __aarch64__ )
 | |
| 		int64_t r = 0;
 | |
| 		asm volatile( "mrs %0, cntvct_el0" : "=r"( r ) );
 | |
| 	#	elif ( __ARM_ARCH >= 6 )
 | |
| 		uint32_t r = 0;
 | |
| 		uint32_t pmccntr;
 | |
| 		uint32_t pmuseren;
 | |
| 		uint32_t pmcntenset;
 | |
| 
 | |
| 		// Read the user mode perf monitor counter access permissions.
 | |
| 		asm volatile( "mrc p15, 0, %0, c9, c14, 0" : "=r"( pmuseren ) );
 | |
| 		if ( pmuseren & 1 )
 | |
| 		{    // Allows reading perfmon counters for user mode code.
 | |
| 			asm volatile( "mrc p15, 0, %0, c9, c12, 1" : "=r"( pmcntenset ) );
 | |
| 			if ( pmcntenset & 0x80000000ul )
 | |
| 			{    // Is it counting?
 | |
| 				asm volatile( "mrc p15, 0, %0, c9, c13, 0" : "=r"( pmccntr ) );
 | |
| 				// The counter is set up to count every 64th cycle
 | |
| 				return ( ( int64_t )pmccntr ) * 64;    // Should optimize to << 6
 | |
| 			}
 | |
| 		}
 | |
| 	#	else
 | |
| 	#		error "No suitable method for read_cpu_time_stamp_counter for this cpu type"
 | |
| 	#	endif
 | |
| 
 | |
| 		return r;
 | |
| 	}
 | |
| 	#else
 | |
| 	u64 read_cpu_time_stamp_counter( void )
 | |
| 	{
 | |
| 		GEN_PANIC( "read_cpu_time_stamp_counter is not supported on this particular setup" );
 | |
| 		return -0;
 | |
| 	}
 | |
| 	#endif
 | |
| 
 | |
| 	#if defined( GEN_SYSTEM_WINDOWS ) || defined( GEN_SYSTEM_CYGWIN )
 | |
| 
 | |
| 	u64 time_rel_ms( void )
 | |
| 	{
 | |
| 		local_persist LARGE_INTEGER win32_perf_count_freq = {};
 | |
| 		u64                         result;
 | |
| 		LARGE_INTEGER               counter;
 | |
| 		local_persist LARGE_INTEGER win32_perf_counter = {};
 | |
| 		if ( ! win32_perf_count_freq.QuadPart )
 | |
| 		{
 | |
| 			QueryPerformanceFrequency( &win32_perf_count_freq );
 | |
| 			GEN_ASSERT( win32_perf_count_freq.QuadPart != 0 );
 | |
| 			QueryPerformanceCounter( &win32_perf_counter );
 | |
| 		}
 | |
| 
 | |
| 		QueryPerformanceCounter( &counter );
 | |
| 
 | |
| 		result = ( counter.QuadPart - win32_perf_counter.QuadPart ) * 1000 / ( win32_perf_count_freq.QuadPart );
 | |
| 		return result;
 | |
| 	}
 | |
| 
 | |
| 	#else
 | |
| 
 | |
| 	#	if defined( GEN_SYSTEM_LINUX ) || defined( GEN_SYSTEM_FREEBSD ) || defined( GEN_SYSTEM_OPENBSD ) || defined( GEN_SYSTEM_EMSCRIPTEN )
 | |
| 	u64 _unix_gettime( void )
 | |
| 	{
 | |
| 		struct timespec t;
 | |
| 		u64             result;
 | |
| 
 | |
| 		clock_gettime( 1 /*CLOCK_MONOTONIC*/, &t );
 | |
| 		result = 1000 * t.tv_sec + 1.0e-6 * t.tv_nsec;
 | |
| 		return result;
 | |
| 	}
 | |
| 	#	endif
 | |
| 
 | |
| 	u64 time_rel_ms( void )
 | |
| 	{
 | |
| 	#	if defined( GEN_SYSTEM_OSX )
 | |
| 		u64 result;
 | |
| 
 | |
| 		local_persist u64 timebase  = 0;
 | |
| 		local_persist u64 timestart = 0;
 | |
| 
 | |
| 		if ( ! timestart )
 | |
| 		{
 | |
| 			mach_timebase_info_data_t tb = { 0 };
 | |
| 			mach_timebase_info( &tb );
 | |
| 			timebase   = tb.numer;
 | |
| 			timebase  /= tb.denom;
 | |
| 			timestart  = mach_absolute_time();
 | |
| 		}
 | |
| 
 | |
| 		// NOTE: mach_absolute_time() returns things in nanoseconds
 | |
| 		result = 1.0e-6 * ( mach_absolute_time() - timestart ) * timebase;
 | |
| 		return result;
 | |
| 	#	else
 | |
| 		local_persist u64 unix_timestart = 0.0;
 | |
| 
 | |
| 		if ( ! unix_timestart )
 | |
| 		{
 | |
| 			unix_timestart = _unix_gettime();
 | |
| 		}
 | |
| 
 | |
| 		u64 now = _unix_gettime();
 | |
| 
 | |
| 		return ( now - unix_timestart );
 | |
| 	#	endif
 | |
| 	}
 | |
| 	#endif
 | |
| 
 | |
| 	f64 time_rel( void )
 | |
| 	{
 | |
| 		return ( f64 )( time_rel_ms() * 1e-3 );
 | |
| 	}
 | |
| #endif
 | |
| 
 | |
| #pragma endregion Timing
 |