setup initial value of MSR on ppc context
Fixed PrefetchW feature check Added prefetchw check to startup AVX check, there should be no CPUs that support AVX but not PrefetchW. Init VRSAVE to all ones. Removed unused disable_global_lock flag.
This commit is contained in:
parent
8678becda6
commit
6ccdc4d0df
|
@ -14,20 +14,32 @@
|
||||||
// Includes Windows headers, so it goes after platform_win.h.
|
// Includes Windows headers, so it goes after platform_win.h.
|
||||||
#include "third_party/xbyak/xbyak/xbyak_util.h"
|
#include "third_party/xbyak/xbyak/xbyak_util.h"
|
||||||
|
|
||||||
class StartupAvxCheck {
|
class StartupCpuFeatureCheck {
|
||||||
public:
|
public:
|
||||||
StartupAvxCheck() {
|
StartupCpuFeatureCheck() {
|
||||||
Xbyak::util::Cpu cpu;
|
Xbyak::util::Cpu cpu;
|
||||||
if (cpu.has(Xbyak::util::Cpu::tAVX)) {
|
const char* error_message = nullptr;
|
||||||
return;
|
if (!cpu.has(Xbyak::util::Cpu::tAVX)) {
|
||||||
|
error_message =
|
||||||
|
"Your CPU does not support AVX, which is required by Xenia. See "
|
||||||
|
"the "
|
||||||
|
"FAQ for system requirements at https://xenia.jp";
|
||||||
|
}
|
||||||
|
unsigned int data[4];
|
||||||
|
Xbyak::util::Cpu::getCpuid(0x80000001, data);
|
||||||
|
if (!(data[2] & (1U << 8))) {
|
||||||
|
error_message =
|
||||||
|
"Your cpu does not support PrefetchW, which Xenia Canary "
|
||||||
|
"requires.";
|
||||||
|
}
|
||||||
|
if (error_message == nullptr) {
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
// TODO(gibbed): detect app type and printf instead, if needed?
|
||||||
|
MessageBoxA(nullptr, error_message, "Xenia Error",
|
||||||
|
MB_OK | MB_ICONERROR | MB_SETFOREGROUND);
|
||||||
|
ExitProcess(static_cast<uint32_t>(-1));
|
||||||
}
|
}
|
||||||
// TODO(gibbed): detect app type and printf instead, if needed?
|
|
||||||
MessageBoxA(
|
|
||||||
nullptr,
|
|
||||||
"Your CPU does not support AVX, which is required by Xenia. See the "
|
|
||||||
"FAQ for system requirements at https://xenia.jp",
|
|
||||||
"Xenia Error", MB_OK | MB_ICONERROR | MB_SETFOREGROUND);
|
|
||||||
ExitProcess(static_cast<uint32_t>(-1));
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -38,4 +50,4 @@ class StartupAvxCheck {
|
||||||
// https://docs.microsoft.com/en-us/cpp/preprocessor/init-seg
|
// https://docs.microsoft.com/en-us/cpp/preprocessor/init-seg
|
||||||
#pragma warning(suppress : 4073)
|
#pragma warning(suppress : 4073)
|
||||||
#pragma init_seg(lib)
|
#pragma init_seg(lib)
|
||||||
static StartupAvxCheck gStartupAvxCheck;
|
static StartupCpuFeatureCheck gStartupAvxCheck;
|
|
@ -71,6 +71,13 @@ void InitFeatureFlags() {
|
||||||
unsigned int data[4];
|
unsigned int data[4];
|
||||||
Xbyak::util::Cpu::getCpuid(0x80000001, data);
|
Xbyak::util::Cpu::getCpuid(0x80000001, data);
|
||||||
unsigned amd_flags = data[2];
|
unsigned amd_flags = data[2];
|
||||||
|
// chrispy: do prefetchw manually, prefetchw is one of the features xbyak
|
||||||
|
// ignores if you have an amd cpu.
|
||||||
|
|
||||||
|
if (amd_flags & (1U << 8)) {
|
||||||
|
// no mask for prefetchw
|
||||||
|
feature_flags_ |= kX64EmitPrefetchW;
|
||||||
|
}
|
||||||
if (amd_flags & (1U << 5)) {
|
if (amd_flags & (1U << 5)) {
|
||||||
if ((cvars::x64_extension_mask & kX64EmitLZCNT) == kX64EmitLZCNT) {
|
if ((cvars::x64_extension_mask & kX64EmitLZCNT) == kX64EmitLZCNT) {
|
||||||
feature_flags_ |= kX64EmitLZCNT;
|
feature_flags_ |= kX64EmitLZCNT;
|
||||||
|
|
|
@ -30,11 +30,6 @@ DEFINE_bool(trace_function_references, false,
|
||||||
DEFINE_bool(trace_function_data, false,
|
DEFINE_bool(trace_function_data, false,
|
||||||
"Generate tracing for function result data.", "CPU");
|
"Generate tracing for function result data.", "CPU");
|
||||||
|
|
||||||
DEFINE_bool(
|
|
||||||
disable_global_lock, false,
|
|
||||||
"Disables global lock usage in guest code. Does not affect host code.",
|
|
||||||
"CPU");
|
|
||||||
|
|
||||||
DEFINE_bool(validate_hir, false,
|
DEFINE_bool(validate_hir, false,
|
||||||
"Perform validation checks on the HIR during compilation.", "CPU");
|
"Perform validation checks on the HIR during compilation.", "CPU");
|
||||||
|
|
||||||
|
|
|
@ -22,8 +22,6 @@ DECLARE_bool(trace_function_coverage);
|
||||||
DECLARE_bool(trace_function_references);
|
DECLARE_bool(trace_function_references);
|
||||||
DECLARE_bool(trace_function_data);
|
DECLARE_bool(trace_function_data);
|
||||||
|
|
||||||
DECLARE_bool(disable_global_lock);
|
|
||||||
|
|
||||||
DECLARE_bool(validate_hir);
|
DECLARE_bool(validate_hir);
|
||||||
|
|
||||||
DECLARE_uint64(pvr);
|
DECLARE_uint64(pvr);
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
|
|
||||||
#include "xenia/base/atomic.h"
|
#include "xenia/base/atomic.h"
|
||||||
#include "xenia/base/logging.h"
|
#include "xenia/base/logging.h"
|
||||||
|
#include "xenia/base/mutex.h"
|
||||||
#include "xenia/cpu/ppc/ppc_context.h"
|
#include "xenia/cpu/ppc/ppc_context.h"
|
||||||
#include "xenia/cpu/ppc/ppc_emit.h"
|
#include "xenia/cpu/ppc/ppc_emit.h"
|
||||||
#include "xenia/cpu/ppc/ppc_opcode_info.h"
|
#include "xenia/cpu/ppc/ppc_opcode_info.h"
|
||||||
|
@ -56,15 +57,15 @@ Memory* PPCFrontend::memory() const { return processor_->memory(); }
|
||||||
// Checks the state of the global lock and sets scratch to the current MSR
|
// Checks the state of the global lock and sets scratch to the current MSR
|
||||||
// value.
|
// value.
|
||||||
void CheckGlobalLock(PPCContext* ppc_context, void* arg0, void* arg1) {
|
void CheckGlobalLock(PPCContext* ppc_context, void* arg0, void* arg1) {
|
||||||
auto global_mutex = reinterpret_cast<std::recursive_mutex*>(arg0);
|
auto global_mutex = reinterpret_cast<xe_global_mutex*>(arg0);
|
||||||
auto global_lock_count = reinterpret_cast<int32_t*>(arg1);
|
auto global_lock_count = reinterpret_cast<int32_t*>(arg1);
|
||||||
std::lock_guard<std::recursive_mutex> lock(*global_mutex);
|
std::lock_guard<xe_global_mutex> lock(*global_mutex);
|
||||||
ppc_context->scratch = *global_lock_count ? 0 : 0x8000;
|
ppc_context->scratch = *global_lock_count ? 0 : 0x8000;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Enters the global lock. Safe to recursion.
|
// Enters the global lock. Safe to recursion.
|
||||||
void EnterGlobalLock(PPCContext* ppc_context, void* arg0, void* arg1) {
|
void EnterGlobalLock(PPCContext* ppc_context, void* arg0, void* arg1) {
|
||||||
auto global_mutex = reinterpret_cast<std::recursive_mutex*>(arg0);
|
auto global_mutex = reinterpret_cast<xe_global_mutex*>(arg0);
|
||||||
auto global_lock_count = reinterpret_cast<int32_t*>(arg1);
|
auto global_lock_count = reinterpret_cast<int32_t*>(arg1);
|
||||||
global_mutex->lock();
|
global_mutex->lock();
|
||||||
xe::atomic_inc(global_lock_count);
|
xe::atomic_inc(global_lock_count);
|
||||||
|
@ -72,7 +73,7 @@ void EnterGlobalLock(PPCContext* ppc_context, void* arg0, void* arg1) {
|
||||||
|
|
||||||
// Leaves the global lock. Safe to recursion.
|
// Leaves the global lock. Safe to recursion.
|
||||||
void LeaveGlobalLock(PPCContext* ppc_context, void* arg0, void* arg1) {
|
void LeaveGlobalLock(PPCContext* ppc_context, void* arg0, void* arg1) {
|
||||||
auto global_mutex = reinterpret_cast<std::recursive_mutex*>(arg0);
|
auto global_mutex = reinterpret_cast<xe_global_mutex*>(arg0);
|
||||||
auto global_lock_count = reinterpret_cast<int32_t*>(arg1);
|
auto global_lock_count = reinterpret_cast<int32_t*>(arg1);
|
||||||
auto new_lock_count = xe::atomic_dec(global_lock_count);
|
auto new_lock_count = xe::atomic_dec(global_lock_count);
|
||||||
assert_true(new_lock_count >= 0);
|
assert_true(new_lock_count >= 0);
|
||||||
|
|
|
@ -95,6 +95,12 @@ ThreadState::ThreadState(Processor* processor, uint32_t thread_id,
|
||||||
context_->r[1] = stack_base;
|
context_->r[1] = stack_base;
|
||||||
context_->r[13] = pcr_address;
|
context_->r[13] = pcr_address;
|
||||||
// fixme: VSCR must be set here!
|
// fixme: VSCR must be set here!
|
||||||
|
context_->msr = 0x9030; // dumped from a real 360, 0x8000
|
||||||
|
|
||||||
|
//this register can be used for arbitrary data according to the PPC docs
|
||||||
|
//but the suggested use is to mark which vector registers are in use, for faster save/restore
|
||||||
|
//it seems unlikely anything uses this, especially since we have way more than 32 vrs, but setting it to all ones seems closer to correct than 0
|
||||||
|
context_->vrsave = ~0u;
|
||||||
}
|
}
|
||||||
|
|
||||||
ThreadState::~ThreadState() {
|
ThreadState::~ThreadState() {
|
||||||
|
|
Loading…
Reference in New Issue