Merge pull request #147 from chrisps/canary_experimental
setup initial value of MSR on ppc context
This commit is contained in:
commit
e9d1e51c32
|
@ -14,20 +14,32 @@
|
|||
// Includes Windows headers, so it goes after platform_win.h.
|
||||
#include "third_party/xbyak/xbyak/xbyak_util.h"
|
||||
|
||||
class StartupAvxCheck {
|
||||
class StartupCpuFeatureCheck {
|
||||
public:
|
||||
StartupAvxCheck() {
|
||||
StartupCpuFeatureCheck() {
|
||||
Xbyak::util::Cpu cpu;
|
||||
if (cpu.has(Xbyak::util::Cpu::tAVX)) {
|
||||
return;
|
||||
const char* error_message = nullptr;
|
||||
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
|
||||
#pragma warning(suppress : 4073)
|
||||
#pragma init_seg(lib)
|
||||
static StartupAvxCheck gStartupAvxCheck;
|
||||
static StartupCpuFeatureCheck gStartupAvxCheck;
|
|
@ -71,6 +71,13 @@ void InitFeatureFlags() {
|
|||
unsigned int data[4];
|
||||
Xbyak::util::Cpu::getCpuid(0x80000001, data);
|
||||
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 ((cvars::x64_extension_mask & kX64EmitLZCNT) == kX64EmitLZCNT) {
|
||||
feature_flags_ |= kX64EmitLZCNT;
|
||||
|
|
|
@ -30,11 +30,6 @@ DEFINE_bool(trace_function_references, false,
|
|||
DEFINE_bool(trace_function_data, false,
|
||||
"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,
|
||||
"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_data);
|
||||
|
||||
DECLARE_bool(disable_global_lock);
|
||||
|
||||
DECLARE_bool(validate_hir);
|
||||
|
||||
DECLARE_uint64(pvr);
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
|
||||
#include "xenia/base/atomic.h"
|
||||
#include "xenia/base/logging.h"
|
||||
#include "xenia/base/mutex.h"
|
||||
#include "xenia/cpu/ppc/ppc_context.h"
|
||||
#include "xenia/cpu/ppc/ppc_emit.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
|
||||
// value.
|
||||
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);
|
||||
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;
|
||||
}
|
||||
|
||||
// Enters the global lock. Safe to recursion.
|
||||
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);
|
||||
global_mutex->lock();
|
||||
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.
|
||||
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 new_lock_count = xe::atomic_dec(global_lock_count);
|
||||
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[13] = pcr_address;
|
||||
// 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() {
|
||||
|
|
Loading…
Reference in New Issue