From 03a68d4c4935dd88dbb47042da85a2e743f555ff Mon Sep 17 00:00:00 2001 From: Ben Vanik Date: Wed, 25 Sep 2013 18:36:34 -0700 Subject: [PATCH] PerformanceCounter. --- src/xenia/cpu/x64/x64_emit_control.cc | 13 +++++++++-- .../modules/xboxkrnl/xboxkrnl_threading.cc | 22 +++++++++++++++++++ .../modules/xboxkrnl/xboxkrnl_threading.h | 2 ++ 3 files changed, 35 insertions(+), 2 deletions(-) diff --git a/src/xenia/cpu/x64/x64_emit_control.cc b/src/xenia/cpu/x64/x64_emit_control.cc index 8f1c1f22e..a997271d1 100644 --- a/src/xenia/cpu/x64/x64_emit_control.cc +++ b/src/xenia/cpu/x64/x64_emit_control.cc @@ -635,6 +635,7 @@ XEEMITTER(mfspr, 0x7C0002A6, XFX)(X64Emitter& e, X86Compiler& c, InstrDat // CTR v = e.ctr_value(); break; + // 268 + 269 = TB + TBU default: XEINSTRNOTIMPLEMENTED(); return 1; @@ -648,8 +649,16 @@ XEEMITTER(mfspr, 0x7C0002A6, XFX)(X64Emitter& e, X86Compiler& c, InstrDat } XEEMITTER(mftb, 0x7C0002E6, XFX)(X64Emitter& e, X86Compiler& c, InstrData& i) { - XEINSTRNOTIMPLEMENTED(); - return 1; + LARGE_INTEGER counter; + if (QueryPerformanceCounter(&counter)) { + e.update_gpr_value(i.XFX.RT, e.get_uint64(counter.QuadPart)); + } else { + e.update_gpr_value(i.XFX.RT, e.get_uint64(0)); + } + + e.clear_constant_gpr_value(i.XFX.RT); + + return 0; } XEEMITTER(mtcrf, 0x7C000120, XFX)(X64Emitter& e, X86Compiler& c, InstrData& i) { diff --git a/src/xenia/kernel/modules/xboxkrnl/xboxkrnl_threading.cc b/src/xenia/kernel/modules/xboxkrnl/xboxkrnl_threading.cc index 2bd2fdbf9..d700623e9 100644 --- a/src/xenia/kernel/modules/xboxkrnl/xboxkrnl_threading.cc +++ b/src/xenia/kernel/modules/xboxkrnl/xboxkrnl_threading.cc @@ -155,6 +155,26 @@ SHIM_CALL KeGetCurrentProcessType_shim( } +uint64_t xeKeQueryPerformanceFrequency() { + LARGE_INTEGER frequency; + if (QueryPerformanceFrequency(&frequency)) { + return frequency.QuadPart; + } else { + return 0; + } +} + + +SHIM_CALL KeQueryPerformanceFrequency_shim( + xe_ppc_state_t* ppc_state, KernelState* state) { + XELOGD( + "KeQueryPerformanceFrequency()"); + + uint64_t result = xeKeQueryPerformanceFrequency(); + SHIM_SET_RETURN(result); +} + + // The TLS system used here is a bit hacky, but seems to work. // Both Win32 and pthreads use unsigned longs as TLS indices, so we can map // right into the system for these calls. We're just round tripping the IDs and @@ -414,6 +434,8 @@ void xe::kernel::xboxkrnl::RegisterThreadingExports( SHIM_SET_MAPPING("xboxkrnl.exe", KeGetCurrentProcessType, state); + SHIM_SET_MAPPING("xboxkrnl.exe", KeQueryPerformanceFrequency, state); + SHIM_SET_MAPPING("xboxkrnl.exe", KeTlsAlloc, state); SHIM_SET_MAPPING("xboxkrnl.exe", KeTlsFree, state); SHIM_SET_MAPPING("xboxkrnl.exe", KeTlsGetValue, state); diff --git a/src/xenia/kernel/modules/xboxkrnl/xboxkrnl_threading.h b/src/xenia/kernel/modules/xboxkrnl/xboxkrnl_threading.h index 9b18d19c3..10326d6f4 100644 --- a/src/xenia/kernel/modules/xboxkrnl/xboxkrnl_threading.h +++ b/src/xenia/kernel/modules/xboxkrnl/xboxkrnl_threading.h @@ -28,6 +28,8 @@ X_STATUS xeExCreateThread( uint32_t xeKeGetCurrentProcessType(); +uint64_t xeKeQueryPerformanceFrequency(); + uint32_t xeKeTlsAlloc(); int KeTlsFree(uint32_t tls_index); uint32_t xeKeTlsGetValue(uint32_t tls_index);