forked from eden-emu/eden
		
	Merge pull request #2129 from FernandoS27/cntpct
Correct CNTPCT from using CPU Cycles to using Clock Cycles
This commit is contained in:
		
						commit
						059465d496
					
				
					 6 changed files with 69 additions and 2 deletions
				
			
		|  | @ -114,6 +114,8 @@ add_library(common STATIC | |||
|     threadsafe_queue.h | ||||
|     timer.cpp | ||||
|     timer.h | ||||
|     uint128.cpp | ||||
|     uint128.h | ||||
|     vector_math.h | ||||
|     web_result.h | ||||
| ) | ||||
|  |  | |||
							
								
								
									
										41
									
								
								src/common/uint128.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								src/common/uint128.cpp
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,41 @@ | |||
| #ifdef _MSC_VER | ||||
| #include <intrin.h> | ||||
| 
 | ||||
| #pragma intrinsic(_umul128) | ||||
| #endif | ||||
| #include <cstring> | ||||
| #include "common/uint128.h" | ||||
| 
 | ||||
| namespace Common { | ||||
| 
 | ||||
| u128 Multiply64Into128(u64 a, u64 b) { | ||||
|     u128 result; | ||||
| #ifdef _MSC_VER | ||||
|     result[0] = _umul128(a, b, &result[1]); | ||||
| #else | ||||
|     unsigned __int128 tmp = a; | ||||
|     tmp *= b; | ||||
|     std::memcpy(&result, &tmp, sizeof(u128)); | ||||
| #endif | ||||
|     return result; | ||||
| } | ||||
| 
 | ||||
| std::pair<u64, u64> Divide128On32(u128 dividend, u32 divisor) { | ||||
|     u64 remainder = dividend[0] % divisor; | ||||
|     u64 accum = dividend[0] / divisor; | ||||
|     if (dividend[1] == 0) | ||||
|         return {accum, remainder}; | ||||
|     // We ignore dividend[1] / divisor as that overflows
 | ||||
|     const u64 first_segment = (dividend[1] % divisor) << 32; | ||||
|     accum += (first_segment / divisor) << 32; | ||||
|     const u64 second_segment = (first_segment % divisor) << 32; | ||||
|     accum += (second_segment / divisor); | ||||
|     remainder += second_segment % divisor; | ||||
|     if (remainder >= divisor) { | ||||
|         accum++; | ||||
|         remainder -= divisor; | ||||
|     } | ||||
|     return {accum, remainder}; | ||||
| } | ||||
| 
 | ||||
| } // namespace Common
 | ||||
							
								
								
									
										14
									
								
								src/common/uint128.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								src/common/uint128.h
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,14 @@ | |||
| 
 | ||||
| #include <utility> | ||||
| #include "common/common_types.h" | ||||
| 
 | ||||
| namespace Common { | ||||
| 
 | ||||
| // This function multiplies 2 u64 values and produces a u128 value;
 | ||||
| u128 Multiply64Into128(u64 a, u64 b); | ||||
| 
 | ||||
| // This function divides a u128 by a u32 value and produces two u64 values:
 | ||||
| // the result of division and the remainder
 | ||||
| std::pair<u64, u64> Divide128On32(u128 dividend, u32 divisor); | ||||
| 
 | ||||
| } // namespace Common
 | ||||
|  | @ -12,6 +12,7 @@ | |||
| #include "core/core.h" | ||||
| #include "core/core_cpu.h" | ||||
| #include "core/core_timing.h" | ||||
| #include "core/core_timing_util.h" | ||||
| #include "core/gdbstub/gdbstub.h" | ||||
| #include "core/hle/kernel/process.h" | ||||
| #include "core/hle/kernel/svc.h" | ||||
|  | @ -119,7 +120,7 @@ public: | |||
|         return std::max(parent.core_timing.GetDowncount(), 0); | ||||
|     } | ||||
|     u64 GetCNTPCT() override { | ||||
|         return parent.core_timing.GetTicks(); | ||||
|         return Timing::CpuCyclesToClockCycles(parent.core_timing.GetTicks()); | ||||
|     } | ||||
| 
 | ||||
|     ARM_Dynarmic& parent; | ||||
|  | @ -151,7 +152,7 @@ std::unique_ptr<Dynarmic::A64::Jit> ARM_Dynarmic::MakeJit() const { | |||
|     config.tpidr_el0 = &cb->tpidr_el0; | ||||
|     config.dczid_el0 = 4; | ||||
|     config.ctr_el0 = 0x8444c004; | ||||
|     config.cntfrq_el0 = 19200000; // Value from fusee.
 | ||||
|     config.cntfrq_el0 = Timing::CNTFREQ; | ||||
| 
 | ||||
|     // Unpredictable instructions
 | ||||
|     config.define_unpredictable_behaviour = true; | ||||
|  |  | |||
|  | @ -7,6 +7,7 @@ | |||
| #include <cinttypes> | ||||
| #include <limits> | ||||
| #include "common/logging/log.h" | ||||
| #include "common/uint128.h" | ||||
| 
 | ||||
| namespace Core::Timing { | ||||
| 
 | ||||
|  | @ -60,4 +61,9 @@ s64 nsToCycles(u64 ns) { | |||
|     return (BASE_CLOCK_RATE * static_cast<s64>(ns)) / 1000000000; | ||||
| } | ||||
| 
 | ||||
| u64 CpuCyclesToClockCycles(u64 ticks) { | ||||
|     const u128 temporal = Common::Multiply64Into128(ticks, CNTFREQ); | ||||
|     return Common::Divide128On32(temporal, static_cast<u32>(BASE_CLOCK_RATE)).first; | ||||
| } | ||||
| 
 | ||||
| } // namespace Core::Timing
 | ||||
|  |  | |||
|  | @ -11,6 +11,7 @@ namespace Core::Timing { | |||
| // The below clock rate is based on Switch's clockspeed being widely known as 1.020GHz
 | ||||
| // The exact value used is of course unverified.
 | ||||
| constexpr u64 BASE_CLOCK_RATE = 1019215872; // Switch clock speed is 1020MHz un/docked
 | ||||
| constexpr u64 CNTFREQ = 19200000;           // Value from fusee.
 | ||||
| 
 | ||||
| inline s64 msToCycles(int ms) { | ||||
|     // since ms is int there is no way to overflow
 | ||||
|  | @ -61,4 +62,6 @@ inline u64 cyclesToMs(s64 cycles) { | |||
|     return cycles * 1000 / BASE_CLOCK_RATE; | ||||
| } | ||||
| 
 | ||||
| u64 CpuCyclesToClockCycles(u64 ticks); | ||||
| 
 | ||||
| } // namespace Core::Timing
 | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 bunnei
						bunnei