Renaming xe::cpu::frontend to xe::cpu::ppc.
This commit is contained in:
112
src/xenia/cpu/ppc/ppc_frontend.cc
Normal file
112
src/xenia/cpu/ppc/ppc_frontend.cc
Normal file
@@ -0,0 +1,112 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* Xenia : Xbox 360 Emulator Research Project *
|
||||
******************************************************************************
|
||||
* Copyright 2013 Ben Vanik. All rights reserved. *
|
||||
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#include "xenia/cpu/ppc/ppc_frontend.h"
|
||||
|
||||
#include "xenia/base/atomic.h"
|
||||
#include "xenia/cpu/ppc/ppc_context.h"
|
||||
#include "xenia/cpu/ppc/ppc_disasm.h"
|
||||
#include "xenia/cpu/ppc/ppc_emit.h"
|
||||
#include "xenia/cpu/ppc/ppc_translator.h"
|
||||
#include "xenia/cpu/processor.h"
|
||||
|
||||
namespace xe {
|
||||
namespace cpu {
|
||||
namespace ppc {
|
||||
|
||||
void InitializeIfNeeded();
|
||||
void CleanupOnShutdown();
|
||||
|
||||
void InitializeIfNeeded() {
|
||||
static bool has_initialized = false;
|
||||
if (has_initialized) {
|
||||
return;
|
||||
}
|
||||
has_initialized = true;
|
||||
|
||||
RegisterEmitCategoryAltivec();
|
||||
RegisterEmitCategoryALU();
|
||||
RegisterEmitCategoryControl();
|
||||
RegisterEmitCategoryFPU();
|
||||
RegisterEmitCategoryMemory();
|
||||
|
||||
atexit(CleanupOnShutdown);
|
||||
}
|
||||
|
||||
void CleanupOnShutdown() {}
|
||||
|
||||
PPCFrontend::PPCFrontend(Processor* processor) : processor_(processor) {
|
||||
InitializeIfNeeded();
|
||||
}
|
||||
|
||||
PPCFrontend::~PPCFrontend() {
|
||||
// Force cleanup now before we deinit.
|
||||
translator_pool_.Reset();
|
||||
}
|
||||
|
||||
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_lock_count = reinterpret_cast<int32_t*>(arg1);
|
||||
std::lock_guard<std::recursive_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_lock_count = reinterpret_cast<int32_t*>(arg1);
|
||||
global_mutex->lock();
|
||||
xe::atomic_inc(global_lock_count);
|
||||
}
|
||||
|
||||
// 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_lock_count = reinterpret_cast<int32_t*>(arg1);
|
||||
auto new_lock_count = xe::atomic_dec(global_lock_count);
|
||||
assert_true(new_lock_count >= 0);
|
||||
global_mutex->unlock();
|
||||
}
|
||||
|
||||
bool PPCFrontend::Initialize() {
|
||||
void* arg0 = reinterpret_cast<void*>(&xe::global_critical_region::mutex());
|
||||
void* arg1 = reinterpret_cast<void*>(&builtins_.global_lock_count);
|
||||
builtins_.check_global_lock =
|
||||
processor_->DefineBuiltin("CheckGlobalLock", CheckGlobalLock, arg0, arg1);
|
||||
builtins_.enter_global_lock =
|
||||
processor_->DefineBuiltin("EnterGlobalLock", EnterGlobalLock, arg0, arg1);
|
||||
builtins_.leave_global_lock =
|
||||
processor_->DefineBuiltin("LeaveGlobalLock", LeaveGlobalLock, arg0, arg1);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PPCFrontend::DeclareFunction(GuestFunction* function) {
|
||||
// Could scan or something here.
|
||||
// Could also check to see if it's a well-known function type and classify
|
||||
// for later.
|
||||
// Could also kick off a precompiler, since we know it's likely the function
|
||||
// will be demanded soon.
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PPCFrontend::DefineFunction(GuestFunction* function,
|
||||
uint32_t debug_info_flags) {
|
||||
auto translator = translator_pool_.Allocate(this);
|
||||
bool result = translator->Translate(function, debug_info_flags);
|
||||
translator_pool_.Release(translator);
|
||||
return result;
|
||||
}
|
||||
|
||||
} // namespace ppc
|
||||
} // namespace cpu
|
||||
} // namespace xe
|
||||
Reference in New Issue
Block a user