mirror of
				https://git.tardis.systems/mirrors/yuzu
				synced 2025-10-31 10:44:49 +01:00 
			
		
		
		
	common/x64: Use TSC clock rate from CPUID when available
The current method used to estimate the TSC is fairly accurate - within a few kHz - but the exact value can be extracted from CPUID if available.
This commit is contained in:
		
							parent
							
								
									770611fdf3
								
							
						
					
					
						commit
						b2ad4dd189
					
				| @ -67,7 +67,7 @@ std::unique_ptr<WallClock> CreateBestMatchingClock(u64 emulated_cpu_frequency, | ||||
|     const auto& caps = GetCPUCaps(); | ||||
|     u64 rtsc_frequency = 0; | ||||
|     if (caps.invariant_tsc) { | ||||
|         rtsc_frequency = EstimateRDTSCFrequency(); | ||||
|         rtsc_frequency = caps.tsc_frequency ? caps.tsc_frequency : EstimateRDTSCFrequency(); | ||||
|     } | ||||
| 
 | ||||
|     // Fallback to StandardWallClock if the hardware TSC does not have the precision greater than:
 | ||||
|  | ||||
| @ -161,6 +161,19 @@ static CPUCaps Detect() { | ||||
|         caps.invariant_tsc = Common::Bit<8>(cpu_id[3]); | ||||
|     } | ||||
| 
 | ||||
|     if (max_std_fn >= 0x15) { | ||||
|         __cpuid(cpu_id, 0x15); | ||||
|         caps.tsc_crystal_ratio_denominator = cpu_id[0]; | ||||
|         caps.tsc_crystal_ratio_numerator = cpu_id[1]; | ||||
|         caps.crystal_frequency = cpu_id[2]; | ||||
|         // Some CPU models might not return a crystal frequency.
 | ||||
|         // The CPU model can be detected to use the values from turbostat
 | ||||
|         // https://github.com/torvalds/linux/blob/master/tools/power/x86/turbostat/turbostat.c#L5569
 | ||||
|         // but it's easier to just estimate the TSC tick rate for these cases.
 | ||||
|         caps.tsc_frequency = static_cast<u64>(caps.crystal_frequency) * | ||||
|                              caps.tsc_crystal_ratio_numerator / caps.tsc_crystal_ratio_denominator; | ||||
|     } | ||||
| 
 | ||||
|     if (max_std_fn >= 0x16) { | ||||
|         __cpuid(cpu_id, 0x16); | ||||
|         caps.base_frequency = cpu_id[0]; | ||||
|  | ||||
| @ -30,6 +30,11 @@ struct CPUCaps { | ||||
|     u32 max_frequency; | ||||
|     u32 bus_frequency; | ||||
| 
 | ||||
|     u32 tsc_crystal_ratio_denominator; | ||||
|     u32 tsc_crystal_ratio_numerator; | ||||
|     u32 crystal_frequency; | ||||
|     u64 tsc_frequency; // Derived from the above three values
 | ||||
| 
 | ||||
|     bool sse : 1; | ||||
|     bool sse2 : 1; | ||||
|     bool sse3 : 1; | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user