Cleanup before kernel export refactor.
This commit is contained in:
parent
fccab79a7a
commit
9c3d2b54fb
|
@ -417,18 +417,27 @@ uint64_t UndefinedCallExtern(void* raw_context, uint64_t symbol_info_ptr) {
|
|||
}
|
||||
void X64Emitter::CallExtern(const hir::Instr* instr,
|
||||
const FunctionInfo* symbol_info) {
|
||||
assert_true(symbol_info->behavior() == FunctionInfo::BEHAVIOR_EXTERN);
|
||||
|
||||
if (!symbol_info->extern_handler()) {
|
||||
CallNative(UndefinedCallExtern, reinterpret_cast<uint64_t>(symbol_info));
|
||||
} else {
|
||||
} else if (symbol_info->behavior() == FunctionBehavior::kBuiltin) {
|
||||
// rcx = context
|
||||
// rdx = target host function
|
||||
// r8 = arg0
|
||||
// r9 = arg1
|
||||
mov(rdx, reinterpret_cast<uint64_t>(symbol_info->builtin_handler()));
|
||||
mov(r8, reinterpret_cast<uint64_t>(symbol_info->builtin_arg0()));
|
||||
mov(r9, reinterpret_cast<uint64_t>(symbol_info->builtin_arg1()));
|
||||
auto thunk = backend()->guest_to_host_thunk();
|
||||
mov(rax, reinterpret_cast<uint64_t>(thunk));
|
||||
call(rax);
|
||||
ReloadECX();
|
||||
ReloadEDX();
|
||||
// rax = host return
|
||||
} else if (symbol_info->behavior() == FunctionBehavior::kExtern) {
|
||||
// rcx = context
|
||||
// rdx = target host function
|
||||
mov(rdx, reinterpret_cast<uint64_t>(symbol_info->extern_handler()));
|
||||
mov(r8, reinterpret_cast<uint64_t>(symbol_info->extern_arg0()));
|
||||
mov(r9, reinterpret_cast<uint64_t>(symbol_info->extern_arg1()));
|
||||
mov(r8, qword[rcx + offsetof(cpu::frontend::PPCContext, kernel_state)]);
|
||||
auto thunk = backend()->guest_to_host_thunk();
|
||||
mov(rax, reinterpret_cast<uint64_t>(thunk));
|
||||
call(rax);
|
||||
|
|
|
@ -20,19 +20,17 @@ ExportResolver::ExportResolver() {}
|
|||
ExportResolver::~ExportResolver() {}
|
||||
|
||||
void ExportResolver::RegisterTable(const std::string& library_name,
|
||||
KernelExport* exports, const size_t count) {
|
||||
Export* exports, const size_t count) {
|
||||
tables_.emplace_back(library_name, exports, count);
|
||||
|
||||
for (size_t n = 0; n < count; n++) {
|
||||
exports[n].is_implemented = false;
|
||||
exports[n].variable_ptr = 0;
|
||||
exports[n].function_data.shim_data = nullptr;
|
||||
exports[n].function_data.shim = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
KernelExport* ExportResolver::GetExportByOrdinal(
|
||||
const std::string& library_name, const uint32_t ordinal) {
|
||||
Export* ExportResolver::GetExportByOrdinal(const std::string& library_name,
|
||||
const uint32_t ordinal) {
|
||||
for (const auto& table : tables_) {
|
||||
if (table.name == library_name || table.simple_name == library_name) {
|
||||
// TODO(benvanik): binary search?
|
||||
|
@ -50,20 +48,19 @@ KernelExport* ExportResolver::GetExportByOrdinal(
|
|||
void ExportResolver::SetVariableMapping(const std::string& library_name,
|
||||
const uint32_t ordinal,
|
||||
uint32_t value) {
|
||||
auto kernel_export = GetExportByOrdinal(library_name, ordinal);
|
||||
assert_not_null(kernel_export);
|
||||
kernel_export->is_implemented = true;
|
||||
kernel_export->variable_ptr = value;
|
||||
auto export = GetExportByOrdinal(library_name, ordinal);
|
||||
assert_not_null(export);
|
||||
export->tags |= ExportTag::kImplemented;
|
||||
export->variable_ptr = value;
|
||||
}
|
||||
|
||||
void ExportResolver::SetFunctionMapping(const std::string& library_name,
|
||||
const uint32_t ordinal, void* shim_data,
|
||||
const uint32_t ordinal,
|
||||
xe_kernel_export_shim_fn shim) {
|
||||
auto kernel_export = GetExportByOrdinal(library_name, ordinal);
|
||||
assert_not_null(kernel_export);
|
||||
kernel_export->is_implemented = true;
|
||||
kernel_export->function_data.shim_data = shim_data;
|
||||
kernel_export->function_data.shim = shim;
|
||||
auto export = GetExportByOrdinal(library_name, ordinal);
|
||||
assert_not_null(export);
|
||||
export->tags |= ExportTag::kImplemented;
|
||||
export->function_data.shim = shim;
|
||||
}
|
||||
|
||||
} // namespace cpu
|
||||
|
|
|
@ -13,24 +13,51 @@
|
|||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "xenia/cpu/frontend/ppc_context.h"
|
||||
|
||||
namespace xe {
|
||||
namespace cpu {
|
||||
|
||||
struct ExportTag {
|
||||
typedef uint32_t type;
|
||||
|
||||
static const type kImplemented = 1 << 0;
|
||||
static const type kSketchy = 1 << 1;
|
||||
static const type kHighFrequency = 1 << 2;
|
||||
static const type kImportant = 1 << 3;
|
||||
|
||||
static const type kThreading = 1 << 10;
|
||||
static const type kInput = 1 << 11;
|
||||
static const type kAudio = 1 << 12;
|
||||
static const type kVideo = 1 << 13;
|
||||
static const type kFileSystem = 1 << 14;
|
||||
static const type kModules = 1 << 15;
|
||||
static const type kUserProfiles = 1 << 16;
|
||||
|
||||
static const type kLog = 1 << 31;
|
||||
};
|
||||
|
||||
// DEPRECATED
|
||||
typedef void (*xe_kernel_export_shim_fn)(void*, void*);
|
||||
|
||||
class KernelExport {
|
||||
class Export {
|
||||
public:
|
||||
enum ExportType {
|
||||
Function = 0,
|
||||
Variable = 1,
|
||||
enum class Type {
|
||||
kFunction = 0,
|
||||
kVariable = 1,
|
||||
};
|
||||
|
||||
uint32_t ordinal;
|
||||
ExportType type;
|
||||
uint32_t flags;
|
||||
char name[96];
|
||||
Type type;
|
||||
std::string name;
|
||||
ExportTag::type tags;
|
||||
|
||||
bool is_implemented;
|
||||
void (*trampoline)(xe::cpu::frontend::PPCContext* ppc_context);
|
||||
uint64_t call_count;
|
||||
|
||||
bool is_implemented() const {
|
||||
return (tags & ExportTag::kImplemented) == ExportTag::kImplemented;
|
||||
}
|
||||
|
||||
union {
|
||||
// Variable data. Only valid when kXEKernelExportFlagVariable is set.
|
||||
|
@ -39,9 +66,6 @@ class KernelExport {
|
|||
uint32_t variable_ptr;
|
||||
|
||||
struct {
|
||||
// Second argument passed to the shim function.
|
||||
void* shim_data;
|
||||
|
||||
// Shimmed implementation.
|
||||
// This is called directly from generated code.
|
||||
// It should parse args, do fixups, and call the impl.
|
||||
|
@ -55,25 +79,25 @@ class ExportResolver {
|
|||
ExportResolver();
|
||||
~ExportResolver();
|
||||
|
||||
void RegisterTable(const std::string& library_name, KernelExport* exports,
|
||||
void RegisterTable(const std::string& library_name, Export* exports,
|
||||
const size_t count);
|
||||
|
||||
KernelExport* GetExportByOrdinal(const std::string& library_name,
|
||||
const uint32_t ordinal);
|
||||
Export* GetExportByOrdinal(const std::string& library_name,
|
||||
const uint32_t ordinal);
|
||||
|
||||
void SetVariableMapping(const std::string& library_name,
|
||||
const uint32_t ordinal, uint32_t value);
|
||||
void SetFunctionMapping(const std::string& library_name,
|
||||
const uint32_t ordinal, void* shim_data,
|
||||
const uint32_t ordinal,
|
||||
xe_kernel_export_shim_fn shim);
|
||||
|
||||
private:
|
||||
struct ExportTable {
|
||||
std::string name;
|
||||
std::string simple_name; // without extension
|
||||
KernelExport* exports;
|
||||
Export* exports;
|
||||
size_t count;
|
||||
ExportTable(const std::string& name, KernelExport* exports, size_t count)
|
||||
ExportTable(const std::string& name, Export* exports, size_t count)
|
||||
: name(name), exports(exports), count(count) {
|
||||
auto dot_pos = name.find_last_of('.');
|
||||
if (dot_pos != std::string::npos) {
|
||||
|
|
|
@ -78,12 +78,10 @@ void HandleGlobalLock(PPCContext* ppc_state, void* arg0, void* arg1) {
|
|||
bool PPCFrontend::Initialize() {
|
||||
void* arg0 = reinterpret_cast<void*>(&builtins_.global_lock);
|
||||
void* arg1 = reinterpret_cast<void*>(&builtins_.global_lock_taken);
|
||||
builtins_.check_global_lock = processor_->DefineBuiltin(
|
||||
"CheckGlobalLock", (FunctionInfo::ExternHandler)CheckGlobalLock, arg0,
|
||||
arg1);
|
||||
builtins_.check_global_lock =
|
||||
processor_->DefineBuiltin("CheckGlobalLock", CheckGlobalLock, arg0, arg1);
|
||||
builtins_.handle_global_lock = processor_->DefineBuiltin(
|
||||
"HandleGlobalLock", (FunctionInfo::ExternHandler)HandleGlobalLock, arg0,
|
||||
arg1);
|
||||
"HandleGlobalLock", HandleGlobalLock, arg0, arg1);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -38,7 +38,7 @@ bool PPCScanner::IsRestGprLr(uint32_t address) {
|
|||
if (!frontend_->processor()->LookupFunctionInfo(address, &symbol_info)) {
|
||||
return false;
|
||||
}
|
||||
return symbol_info->behavior() == FunctionInfo::BEHAVIOR_EPILOG_RETURN;
|
||||
return symbol_info->behavior() == FunctionBehavior::kEpilogReturn;
|
||||
}
|
||||
|
||||
bool PPCScanner::Scan(FunctionInfo* symbol_info, DebugInfo* debug_info) {
|
||||
|
|
|
@ -75,14 +75,17 @@ bool Function::Call(ThreadState* thread_state, uint32_t return_address) {
|
|||
|
||||
bool result = true;
|
||||
|
||||
if (symbol_info_->behavior() == FunctionInfo::BEHAVIOR_EXTERN) {
|
||||
if (symbol_info_->behavior() == FunctionBehavior::kBuiltin) {
|
||||
auto handler = symbol_info_->builtin_handler();
|
||||
assert_not_null(handler);
|
||||
handler(thread_state->context(), symbol_info_->builtin_arg0(),
|
||||
symbol_info_->builtin_arg1());
|
||||
} else if (symbol_info_->behavior() == FunctionBehavior::kExtern) {
|
||||
auto handler = symbol_info_->extern_handler();
|
||||
|
||||
if (handler) {
|
||||
handler(thread_state->context(), symbol_info_->extern_arg0(),
|
||||
symbol_info_->extern_arg1());
|
||||
handler(thread_state->context(), thread_state->context()->kernel_state);
|
||||
} else {
|
||||
XELOGW("undefined extern call to %.8llX %s", symbol_info_->address(),
|
||||
XELOGW("undefined extern call to %.8X %s", symbol_info_->address(),
|
||||
symbol_info_->name().c_str());
|
||||
result = false;
|
||||
}
|
||||
|
|
|
@ -31,7 +31,7 @@ SymbolInfo* Module::LookupSymbol(uint32_t address, bool wait) {
|
|||
const auto it = map_.find(address);
|
||||
SymbolInfo* symbol_info = it != map_.end() ? it->second : nullptr;
|
||||
if (symbol_info) {
|
||||
if (symbol_info->status() == SymbolInfo::STATUS_DECLARING) {
|
||||
if (symbol_info->status() == SymbolStatus::kDeclaring) {
|
||||
// Some other thread is declaring the symbol - wait.
|
||||
if (wait) {
|
||||
do {
|
||||
|
@ -39,7 +39,7 @@ SymbolInfo* Module::LookupSymbol(uint32_t address, bool wait) {
|
|||
// TODO(benvanik): sleep for less time?
|
||||
xe::threading::Sleep(std::chrono::microseconds(100));
|
||||
lock_.lock();
|
||||
} while (symbol_info->status() == SymbolInfo::STATUS_DECLARING);
|
||||
} while (symbol_info->status() == SymbolStatus::kDeclaring);
|
||||
} else {
|
||||
// Immediate request, just return.
|
||||
symbol_info = nullptr;
|
||||
|
@ -50,89 +50,88 @@ SymbolInfo* Module::LookupSymbol(uint32_t address, bool wait) {
|
|||
return symbol_info;
|
||||
}
|
||||
|
||||
SymbolInfo::Status Module::DeclareSymbol(SymbolInfo::Type type,
|
||||
uint32_t address,
|
||||
SymbolInfo** out_symbol_info) {
|
||||
SymbolStatus Module::DeclareSymbol(SymbolType type, uint32_t address,
|
||||
SymbolInfo** out_symbol_info) {
|
||||
*out_symbol_info = nullptr;
|
||||
lock_.lock();
|
||||
auto it = map_.find(address);
|
||||
SymbolInfo* symbol_info = it != map_.end() ? it->second : nullptr;
|
||||
SymbolInfo::Status status;
|
||||
SymbolStatus status;
|
||||
if (symbol_info) {
|
||||
// If we exist but are the wrong type, die.
|
||||
if (symbol_info->type() != type) {
|
||||
lock_.unlock();
|
||||
return SymbolInfo::STATUS_FAILED;
|
||||
return SymbolStatus::kFailed;
|
||||
}
|
||||
// If we aren't ready yet spin and wait.
|
||||
if (symbol_info->status() == SymbolInfo::STATUS_DECLARING) {
|
||||
if (symbol_info->status() == SymbolStatus::kDeclaring) {
|
||||
// Still declaring, so spin.
|
||||
do {
|
||||
lock_.unlock();
|
||||
// TODO(benvanik): sleep for less time?
|
||||
xe::threading::Sleep(std::chrono::microseconds(100));
|
||||
lock_.lock();
|
||||
} while (symbol_info->status() == SymbolInfo::STATUS_DECLARING);
|
||||
} while (symbol_info->status() == SymbolStatus::kDeclaring);
|
||||
}
|
||||
status = symbol_info->status();
|
||||
} else {
|
||||
// Create and return for initialization.
|
||||
switch (type) {
|
||||
case SymbolInfo::TYPE_FUNCTION:
|
||||
case SymbolType::kFunction:
|
||||
symbol_info = new FunctionInfo(this, address);
|
||||
break;
|
||||
case SymbolInfo::TYPE_VARIABLE:
|
||||
case SymbolType::kVariable:
|
||||
symbol_info = new VariableInfo(this, address);
|
||||
break;
|
||||
}
|
||||
map_[address] = symbol_info;
|
||||
list_.emplace_back(symbol_info);
|
||||
status = SymbolInfo::STATUS_NEW;
|
||||
status = SymbolStatus::kNew;
|
||||
}
|
||||
lock_.unlock();
|
||||
*out_symbol_info = symbol_info;
|
||||
|
||||
// Get debug info from providers, if this is new.
|
||||
if (status == SymbolInfo::STATUS_NEW) {
|
||||
if (status == SymbolStatus::kNew) {
|
||||
// TODO(benvanik): lookup in map data/dwarf/etc?
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
SymbolInfo::Status Module::DeclareFunction(uint32_t address,
|
||||
FunctionInfo** out_symbol_info) {
|
||||
SymbolStatus Module::DeclareFunction(uint32_t address,
|
||||
FunctionInfo** out_symbol_info) {
|
||||
SymbolInfo* symbol_info;
|
||||
SymbolInfo::Status status =
|
||||
DeclareSymbol(SymbolInfo::TYPE_FUNCTION, address, &symbol_info);
|
||||
SymbolStatus status =
|
||||
DeclareSymbol(SymbolType::kFunction, address, &symbol_info);
|
||||
*out_symbol_info = (FunctionInfo*)symbol_info;
|
||||
return status;
|
||||
}
|
||||
|
||||
SymbolInfo::Status Module::DeclareVariable(uint32_t address,
|
||||
VariableInfo** out_symbol_info) {
|
||||
SymbolStatus Module::DeclareVariable(uint32_t address,
|
||||
VariableInfo** out_symbol_info) {
|
||||
SymbolInfo* symbol_info;
|
||||
SymbolInfo::Status status =
|
||||
DeclareSymbol(SymbolInfo::TYPE_VARIABLE, address, &symbol_info);
|
||||
SymbolStatus status =
|
||||
DeclareSymbol(SymbolType::kVariable, address, &symbol_info);
|
||||
*out_symbol_info = (VariableInfo*)symbol_info;
|
||||
return status;
|
||||
}
|
||||
|
||||
SymbolInfo::Status Module::DefineSymbol(SymbolInfo* symbol_info) {
|
||||
SymbolStatus Module::DefineSymbol(SymbolInfo* symbol_info) {
|
||||
lock_.lock();
|
||||
SymbolInfo::Status status;
|
||||
if (symbol_info->status() == SymbolInfo::STATUS_DECLARED) {
|
||||
SymbolStatus status;
|
||||
if (symbol_info->status() == SymbolStatus::kDeclared) {
|
||||
// Declared but undefined, so request caller define it.
|
||||
symbol_info->set_status(SymbolInfo::STATUS_DEFINING);
|
||||
status = SymbolInfo::STATUS_NEW;
|
||||
} else if (symbol_info->status() == SymbolInfo::STATUS_DEFINING) {
|
||||
symbol_info->set_status(SymbolStatus::kDefining);
|
||||
status = SymbolStatus::kNew;
|
||||
} else if (symbol_info->status() == SymbolStatus::kDefining) {
|
||||
// Still defining, so spin.
|
||||
do {
|
||||
lock_.unlock();
|
||||
// TODO(benvanik): sleep for less time?
|
||||
xe::threading::Sleep(std::chrono::microseconds(100));
|
||||
lock_.lock();
|
||||
} while (symbol_info->status() == SymbolInfo::STATUS_DEFINING);
|
||||
} while (symbol_info->status() == SymbolStatus::kDefining);
|
||||
status = symbol_info->status();
|
||||
} else {
|
||||
status = symbol_info->status();
|
||||
|
@ -141,11 +140,11 @@ SymbolInfo::Status Module::DefineSymbol(SymbolInfo* symbol_info) {
|
|||
return status;
|
||||
}
|
||||
|
||||
SymbolInfo::Status Module::DefineFunction(FunctionInfo* symbol_info) {
|
||||
SymbolStatus Module::DefineFunction(FunctionInfo* symbol_info) {
|
||||
return DefineSymbol((SymbolInfo*)symbol_info);
|
||||
}
|
||||
|
||||
SymbolInfo::Status Module::DefineVariable(VariableInfo* symbol_info) {
|
||||
SymbolStatus Module::DefineVariable(VariableInfo* symbol_info) {
|
||||
return DefineSymbol((SymbolInfo*)symbol_info);
|
||||
}
|
||||
|
||||
|
@ -153,7 +152,7 @@ void Module::ForEachFunction(std::function<void(FunctionInfo*)> callback) {
|
|||
SCOPE_profile_cpu_f("cpu");
|
||||
std::lock_guard<xe::mutex> guard(lock_);
|
||||
for (auto& symbol_info : list_) {
|
||||
if (symbol_info->type() == SymbolInfo::TYPE_FUNCTION) {
|
||||
if (symbol_info->type() == SymbolType::kFunction) {
|
||||
FunctionInfo* info = static_cast<FunctionInfo*>(symbol_info.get());
|
||||
callback(info);
|
||||
}
|
||||
|
@ -168,7 +167,7 @@ void Module::ForEachFunction(size_t since, size_t& version,
|
|||
version = count;
|
||||
for (size_t n = since; n < count; n++) {
|
||||
auto& symbol_info = list_[n];
|
||||
if (symbol_info->type() == SymbolInfo::TYPE_FUNCTION) {
|
||||
if (symbol_info->type() == SymbolType::kFunction) {
|
||||
FunctionInfo* info = static_cast<FunctionInfo*>(symbol_info.get());
|
||||
callback(info);
|
||||
}
|
||||
|
|
|
@ -38,13 +38,13 @@ class Module {
|
|||
virtual bool ContainsAddress(uint32_t address);
|
||||
|
||||
SymbolInfo* LookupSymbol(uint32_t address, bool wait = true);
|
||||
virtual SymbolInfo::Status DeclareFunction(uint32_t address,
|
||||
FunctionInfo** out_symbol_info);
|
||||
virtual SymbolInfo::Status DeclareVariable(uint32_t address,
|
||||
VariableInfo** out_symbol_info);
|
||||
virtual SymbolStatus DeclareFunction(uint32_t address,
|
||||
FunctionInfo** out_symbol_info);
|
||||
virtual SymbolStatus DeclareVariable(uint32_t address,
|
||||
VariableInfo** out_symbol_info);
|
||||
|
||||
SymbolInfo::Status DefineFunction(FunctionInfo* symbol_info);
|
||||
SymbolInfo::Status DefineVariable(VariableInfo* symbol_info);
|
||||
SymbolStatus DefineFunction(FunctionInfo* symbol_info);
|
||||
SymbolStatus DefineVariable(VariableInfo* symbol_info);
|
||||
|
||||
void ForEachFunction(std::function<void(FunctionInfo*)> callback);
|
||||
void ForEachFunction(size_t since, size_t& version,
|
||||
|
@ -53,9 +53,9 @@ class Module {
|
|||
bool ReadMap(const char* file_name);
|
||||
|
||||
private:
|
||||
SymbolInfo::Status DeclareSymbol(SymbolInfo::Type type, uint32_t address,
|
||||
SymbolInfo** out_symbol_info);
|
||||
SymbolInfo::Status DefineSymbol(SymbolInfo* symbol_info);
|
||||
SymbolStatus DeclareSymbol(SymbolType type, uint32_t address,
|
||||
SymbolInfo** out_symbol_info);
|
||||
SymbolStatus DefineSymbol(SymbolInfo* symbol_info);
|
||||
|
||||
protected:
|
||||
Processor* processor_;
|
||||
|
|
|
@ -76,18 +76,11 @@ Processor::Processor(xe::Memory* memory, ExportResolver* export_resolver,
|
|||
debug_info_flags_(0),
|
||||
builtin_module_(nullptr),
|
||||
next_builtin_address_(0xFFFF0000ul),
|
||||
export_resolver_(export_resolver),
|
||||
interrupt_thread_state_(nullptr),
|
||||
interrupt_thread_block_(0) {
|
||||
export_resolver_(export_resolver) {
|
||||
InitializeIfNeeded();
|
||||
}
|
||||
|
||||
Processor::~Processor() {
|
||||
if (interrupt_thread_block_) {
|
||||
memory_->SystemHeapFree(interrupt_thread_block_);
|
||||
delete interrupt_thread_state_;
|
||||
}
|
||||
|
||||
{
|
||||
std::lock_guard<xe::mutex> guard(modules_lock_);
|
||||
modules_.clear();
|
||||
|
@ -144,18 +137,6 @@ bool Processor::Setup() {
|
|||
backend_ = std::move(backend);
|
||||
frontend_ = std::move(frontend);
|
||||
|
||||
// DEPRECATED: will be removed.
|
||||
interrupt_thread_state_ =
|
||||
new ThreadState(this, 0, ThreadStackType::kKernelStack, 0, 128 * 1024, 0);
|
||||
interrupt_thread_state_->set_name("Interrupt");
|
||||
interrupt_thread_block_ = memory_->SystemHeapAlloc(2048);
|
||||
interrupt_thread_state_->context()->r[13] = interrupt_thread_block_;
|
||||
XELOGI("Interrupt Thread %X Stack: %.8X-%.8X",
|
||||
interrupt_thread_state_->thread_id(),
|
||||
interrupt_thread_state_->stack_address(),
|
||||
interrupt_thread_state_->stack_address() +
|
||||
interrupt_thread_state_->stack_size());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -185,7 +166,7 @@ std::vector<Module*> Processor::GetModules() {
|
|||
}
|
||||
|
||||
FunctionInfo* Processor::DefineBuiltin(const std::string& name,
|
||||
FunctionInfo::ExternHandler handler,
|
||||
FunctionInfo::BuiltinHandler handler,
|
||||
void* arg0, void* arg1) {
|
||||
uint32_t address = next_builtin_address_;
|
||||
next_builtin_address_ += 4;
|
||||
|
@ -194,8 +175,8 @@ FunctionInfo* Processor::DefineBuiltin(const std::string& name,
|
|||
builtin_module_->DeclareFunction(address, &fn_info);
|
||||
fn_info->set_end_address(address + 4);
|
||||
fn_info->set_name(name);
|
||||
fn_info->SetupExtern(handler, arg0, arg1);
|
||||
fn_info->set_status(SymbolInfo::STATUS_DECLARED);
|
||||
fn_info->SetupBuiltin(handler, arg0, arg1);
|
||||
fn_info->set_status(SymbolStatus::kDeclared);
|
||||
|
||||
return fn_info;
|
||||
}
|
||||
|
@ -266,15 +247,14 @@ bool Processor::LookupFunctionInfo(Module* module, uint32_t address,
|
|||
// Atomic create/lookup symbol in module.
|
||||
// If we get back the NEW flag we must declare it now.
|
||||
FunctionInfo* symbol_info = nullptr;
|
||||
SymbolInfo::Status symbol_status =
|
||||
module->DeclareFunction(address, &symbol_info);
|
||||
if (symbol_status == SymbolInfo::STATUS_NEW) {
|
||||
SymbolStatus symbol_status = module->DeclareFunction(address, &symbol_info);
|
||||
if (symbol_status == SymbolStatus::kNew) {
|
||||
// Symbol is undeclared, so declare now.
|
||||
if (!frontend_->DeclareFunction(symbol_info)) {
|
||||
symbol_info->set_status(SymbolInfo::STATUS_FAILED);
|
||||
symbol_info->set_status(SymbolStatus::kFailed);
|
||||
return false;
|
||||
}
|
||||
symbol_info->set_status(SymbolInfo::STATUS_DECLARED);
|
||||
symbol_info->set_status(SymbolStatus::kDeclared);
|
||||
}
|
||||
|
||||
*out_symbol_info = symbol_info;
|
||||
|
@ -288,12 +268,12 @@ bool Processor::DemandFunction(FunctionInfo* symbol_info,
|
|||
// Lock function for generation. If it's already being generated
|
||||
// by another thread this will block and return DECLARED.
|
||||
Module* module = symbol_info->module();
|
||||
SymbolInfo::Status symbol_status = module->DefineFunction(symbol_info);
|
||||
if (symbol_status == SymbolInfo::STATUS_NEW) {
|
||||
SymbolStatus symbol_status = module->DefineFunction(symbol_info);
|
||||
if (symbol_status == SymbolStatus::kNew) {
|
||||
// Symbol is undefined, so define now.
|
||||
Function* function = nullptr;
|
||||
if (!frontend_->DefineFunction(symbol_info, debug_info_flags_, &function)) {
|
||||
symbol_info->set_status(SymbolInfo::STATUS_FAILED);
|
||||
symbol_info->set_status(SymbolStatus::kFailed);
|
||||
return false;
|
||||
}
|
||||
symbol_info->set_function(function);
|
||||
|
@ -303,11 +283,11 @@ bool Processor::DemandFunction(FunctionInfo* symbol_info,
|
|||
debugger_->OnFunctionDefined(symbol_info, function);
|
||||
}
|
||||
|
||||
symbol_info->set_status(SymbolInfo::STATUS_DEFINED);
|
||||
symbol_info->set_status(SymbolStatus::kDefined);
|
||||
symbol_status = symbol_info->status();
|
||||
}
|
||||
|
||||
if (symbol_status == SymbolInfo::STATUS_FAILED) {
|
||||
if (symbol_status == SymbolStatus::kFailed) {
|
||||
// Symbol likely failed.
|
||||
return false;
|
||||
}
|
||||
|
@ -374,18 +354,5 @@ void Processor::LowerIrql(Irql old_value) {
|
|||
reinterpret_cast<volatile uint32_t*>(&irql_));
|
||||
}
|
||||
|
||||
uint64_t Processor::ExecuteInterrupt(uint32_t address, uint64_t args[],
|
||||
size_t arg_count) {
|
||||
SCOPE_profile_cpu_f("cpu");
|
||||
|
||||
// Acquire lock on interrupt thread (we can only dispatch one at a time).
|
||||
std::lock_guard<xe::mutex> lock(interrupt_thread_lock_);
|
||||
|
||||
// Execute interrupt.
|
||||
uint64_t result = Execute(interrupt_thread_state_, address, args, arg_count);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
} // namespace cpu
|
||||
} // namespace xe
|
||||
|
|
|
@ -58,7 +58,7 @@ class Processor {
|
|||
|
||||
Module* builtin_module() const { return builtin_module_; }
|
||||
FunctionInfo* DefineBuiltin(const std::string& name,
|
||||
FunctionInfo::ExternHandler handler, void* arg0,
|
||||
FunctionInfo::BuiltinHandler handler, void* arg0,
|
||||
void* arg1);
|
||||
|
||||
std::vector<Function*> FindFunctionsWithAddress(uint32_t address);
|
||||
|
@ -75,10 +75,6 @@ class Processor {
|
|||
Irql RaiseIrql(Irql new_value);
|
||||
void LowerIrql(Irql old_value);
|
||||
|
||||
// DEPRECATED: will be removed.
|
||||
uint64_t ExecuteInterrupt(uint32_t address, uint64_t args[],
|
||||
size_t arg_count);
|
||||
|
||||
private:
|
||||
bool DemandFunction(FunctionInfo* symbol_info, Function** out_function);
|
||||
|
||||
|
@ -98,9 +94,6 @@ class Processor {
|
|||
uint32_t next_builtin_address_;
|
||||
|
||||
Irql irql_;
|
||||
xe::mutex interrupt_thread_lock_;
|
||||
ThreadState* interrupt_thread_state_;
|
||||
uint32_t interrupt_thread_block_;
|
||||
};
|
||||
|
||||
} // namespace cpu
|
||||
|
|
|
@ -12,34 +12,40 @@
|
|||
namespace xe {
|
||||
namespace cpu {
|
||||
|
||||
SymbolInfo::SymbolInfo(Type type, Module* module, uint32_t address)
|
||||
SymbolInfo::SymbolInfo(SymbolType type, Module* module, uint32_t address)
|
||||
: type_(type),
|
||||
module_(module),
|
||||
status_(STATUS_DEFINING),
|
||||
status_(SymbolStatus::kDefining),
|
||||
address_(address),
|
||||
name_("") {}
|
||||
|
||||
SymbolInfo::~SymbolInfo() = default;
|
||||
|
||||
FunctionInfo::FunctionInfo(Module* module, uint32_t address)
|
||||
: SymbolInfo(SymbolInfo::TYPE_FUNCTION, module, address),
|
||||
: SymbolInfo(SymbolType::kFunction, module, address),
|
||||
end_address_(0),
|
||||
behavior_(BEHAVIOR_DEFAULT),
|
||||
function_(0) {
|
||||
behavior_(FunctionBehavior::kDefault),
|
||||
function_(nullptr) {
|
||||
std::memset(&extern_info_, 0, sizeof(extern_info_));
|
||||
}
|
||||
|
||||
FunctionInfo::~FunctionInfo() = default;
|
||||
|
||||
void FunctionInfo::SetupExtern(ExternHandler handler, void* arg0, void* arg1) {
|
||||
behavior_ = BEHAVIOR_EXTERN;
|
||||
void FunctionInfo::SetupBuiltin(BuiltinHandler handler, void* arg0,
|
||||
void* arg1) {
|
||||
behavior_ = FunctionBehavior::kBuiltin;
|
||||
builtin_info_.handler = handler;
|
||||
builtin_info_.arg0 = arg0;
|
||||
builtin_info_.arg1 = arg1;
|
||||
}
|
||||
|
||||
void FunctionInfo::SetupExtern(ExternHandler handler) {
|
||||
behavior_ = FunctionBehavior::kExtern;
|
||||
extern_info_.handler = handler;
|
||||
extern_info_.arg0 = arg0;
|
||||
extern_info_.arg1 = arg1;
|
||||
}
|
||||
|
||||
VariableInfo::VariableInfo(Module* module, uint32_t address)
|
||||
: SymbolInfo(SymbolInfo::TYPE_VARIABLE, module, address) {}
|
||||
: SymbolInfo(SymbolType::kVariable, module, address) {}
|
||||
|
||||
VariableInfo::~VariableInfo() = default;
|
||||
|
||||
|
|
|
@ -13,59 +13,61 @@
|
|||
#include <cstdint>
|
||||
#include <string>
|
||||
|
||||
#include "xenia/cpu/frontend/ppc_context.h"
|
||||
|
||||
namespace xe {
|
||||
namespace cpu {
|
||||
|
||||
class Function;
|
||||
class Module;
|
||||
|
||||
enum class SymbolType {
|
||||
kFunction,
|
||||
kVariable,
|
||||
};
|
||||
|
||||
enum class SymbolStatus {
|
||||
kNew,
|
||||
kDeclaring,
|
||||
kDeclared,
|
||||
kDefining,
|
||||
kDefined,
|
||||
kFailed,
|
||||
};
|
||||
|
||||
class SymbolInfo {
|
||||
public:
|
||||
enum Type {
|
||||
TYPE_FUNCTION,
|
||||
TYPE_VARIABLE,
|
||||
};
|
||||
enum Status {
|
||||
STATUS_NEW,
|
||||
STATUS_DECLARING,
|
||||
STATUS_DECLARED,
|
||||
STATUS_DEFINING,
|
||||
STATUS_DEFINED,
|
||||
STATUS_FAILED,
|
||||
};
|
||||
|
||||
public:
|
||||
SymbolInfo(Type type, Module* module, uint32_t address);
|
||||
SymbolInfo(SymbolType type, Module* module, uint32_t address);
|
||||
virtual ~SymbolInfo();
|
||||
|
||||
Type type() const { return type_; }
|
||||
SymbolType type() const { return type_; }
|
||||
Module* module() const { return module_; }
|
||||
Status status() const { return status_; }
|
||||
void set_status(Status value) { status_ = value; }
|
||||
SymbolStatus status() const { return status_; }
|
||||
void set_status(SymbolStatus value) { status_ = value; }
|
||||
uint32_t address() const { return address_; }
|
||||
|
||||
const std::string& name() const { return name_; }
|
||||
void set_name(const std::string& value) { name_ = value; }
|
||||
|
||||
protected:
|
||||
Type type_;
|
||||
SymbolType type_;
|
||||
Module* module_;
|
||||
Status status_;
|
||||
SymbolStatus status_;
|
||||
uint32_t address_;
|
||||
|
||||
std::string name_;
|
||||
};
|
||||
|
||||
class FunctionInfo : public SymbolInfo {
|
||||
public:
|
||||
enum Behavior {
|
||||
BEHAVIOR_DEFAULT = 0,
|
||||
BEHAVIOR_PROLOG,
|
||||
BEHAVIOR_EPILOG,
|
||||
BEHAVIOR_EPILOG_RETURN,
|
||||
BEHAVIOR_EXTERN,
|
||||
};
|
||||
enum class FunctionBehavior {
|
||||
kDefault = 0,
|
||||
kProlog,
|
||||
kEpilog,
|
||||
kEpilogReturn,
|
||||
kBuiltin,
|
||||
kExtern,
|
||||
};
|
||||
|
||||
class FunctionInfo : public SymbolInfo {
|
||||
public:
|
||||
FunctionInfo(Module* module, uint32_t address);
|
||||
~FunctionInfo() override;
|
||||
|
@ -74,27 +76,38 @@ class FunctionInfo : public SymbolInfo {
|
|||
uint32_t end_address() const { return end_address_; }
|
||||
void set_end_address(uint32_t value) { end_address_ = value; }
|
||||
|
||||
Behavior behavior() const { return behavior_; }
|
||||
void set_behavior(Behavior value) { behavior_ = value; }
|
||||
FunctionBehavior behavior() const { return behavior_; }
|
||||
void set_behavior(FunctionBehavior value) { behavior_ = value; }
|
||||
|
||||
Function* function() const { return function_; }
|
||||
void set_function(Function* value) { function_ = value; }
|
||||
|
||||
typedef void (*ExternHandler)(void* context, void* arg0, void* arg1);
|
||||
void SetupExtern(ExternHandler handler, void* arg0, void* arg1);
|
||||
typedef void (*BuiltinHandler)(frontend::PPCContext* ppc_context, void* arg0,
|
||||
void* arg1);
|
||||
void SetupBuiltin(BuiltinHandler handler, void* arg0, void* arg1);
|
||||
BuiltinHandler builtin_handler() const { return builtin_info_.handler; }
|
||||
void* builtin_arg0() const { return builtin_info_.arg0; }
|
||||
void* builtin_arg1() const { return builtin_info_.arg1; }
|
||||
|
||||
typedef void (*ExternHandler)(frontend::PPCContext* ppc_context,
|
||||
kernel::KernelState* kernel_state);
|
||||
void SetupExtern(ExternHandler handler);
|
||||
ExternHandler extern_handler() const { return extern_info_.handler; }
|
||||
void* extern_arg0() const { return extern_info_.arg0; }
|
||||
void* extern_arg1() const { return extern_info_.arg1; }
|
||||
|
||||
private:
|
||||
uint32_t end_address_;
|
||||
Behavior behavior_;
|
||||
FunctionBehavior behavior_;
|
||||
Function* function_;
|
||||
struct {
|
||||
ExternHandler handler;
|
||||
void* arg0;
|
||||
void* arg1;
|
||||
} extern_info_;
|
||||
union {
|
||||
struct {
|
||||
ExternHandler handler;
|
||||
} extern_info_;
|
||||
struct {
|
||||
BuiltinHandler handler;
|
||||
void* arg0;
|
||||
void* arg1;
|
||||
} builtin_info_;
|
||||
};
|
||||
};
|
||||
|
||||
class VariableInfo : public SymbolInfo {
|
||||
|
|
|
@ -71,10 +71,10 @@ bool TestModule::ContainsAddress(uint32_t address) {
|
|||
return contains_address_(address);
|
||||
}
|
||||
|
||||
SymbolInfo::Status TestModule::DeclareFunction(uint32_t address,
|
||||
FunctionInfo** out_symbol_info) {
|
||||
SymbolInfo::Status status = Module::DeclareFunction(address, out_symbol_info);
|
||||
if (status == SymbolInfo::STATUS_NEW) {
|
||||
SymbolStatus TestModule::DeclareFunction(uint32_t address,
|
||||
FunctionInfo** out_symbol_info) {
|
||||
SymbolStatus status = Module::DeclareFunction(address, out_symbol_info);
|
||||
if (status == SymbolStatus::kNew) {
|
||||
auto symbol_info = *out_symbol_info;
|
||||
|
||||
// Reset() all caching when we leave.
|
||||
|
@ -82,8 +82,8 @@ SymbolInfo::Status TestModule::DeclareFunction(uint32_t address,
|
|||
xe::make_reset_scope(assembler_);
|
||||
|
||||
if (!generate_(*builder_.get())) {
|
||||
symbol_info->set_status(SymbolInfo::STATUS_FAILED);
|
||||
return SymbolInfo::STATUS_FAILED;
|
||||
symbol_info->set_status(SymbolStatus::kFailed);
|
||||
return SymbolStatus::kFailed;
|
||||
}
|
||||
|
||||
compiler_->Compile(builder_.get());
|
||||
|
@ -92,7 +92,7 @@ SymbolInfo::Status TestModule::DeclareFunction(uint32_t address,
|
|||
assembler_->Assemble(symbol_info, builder_.get(), 0, nullptr, &fn);
|
||||
|
||||
symbol_info->set_function(fn);
|
||||
status = SymbolInfo::STATUS_DEFINED;
|
||||
status = SymbolStatus::kDefined;
|
||||
symbol_info->set_status(status);
|
||||
}
|
||||
return status;
|
||||
|
|
|
@ -33,8 +33,8 @@ class TestModule : public Module {
|
|||
|
||||
bool ContainsAddress(uint32_t address) override;
|
||||
|
||||
SymbolInfo::Status DeclareFunction(uint32_t address,
|
||||
FunctionInfo** out_symbol_info) override;
|
||||
SymbolStatus DeclareFunction(uint32_t address,
|
||||
FunctionInfo** out_symbol_info) override;
|
||||
|
||||
private:
|
||||
std::string name_;
|
||||
|
|
|
@ -29,7 +29,8 @@ using namespace xe::kernel;
|
|||
|
||||
using PPCContext = xe::cpu::frontend::PPCContext;
|
||||
|
||||
void UndefinedImport(PPCContext* ppc_state, void* arg0, void* arg1) {
|
||||
void UndefinedImport(PPCContext* ppc_context,
|
||||
kernel::KernelState* kernel_state) {
|
||||
XELOGE("call to undefined import");
|
||||
}
|
||||
|
||||
|
@ -118,8 +119,8 @@ bool XexModule::SetupLibraryImports(const xe_xex2_import_library_t* library) {
|
|||
libname = libname.substr(0, dot);
|
||||
}
|
||||
|
||||
KernelExport* kernel_export = NULL; // kernel export info
|
||||
uint32_t user_export_addr = 0; // user export address
|
||||
Export* kernel_export = nullptr; // kernel export info
|
||||
uint32_t user_export_addr = 0; // user export address
|
||||
|
||||
if (kernel_state_->IsKernelModule(library->name)) {
|
||||
kernel_export =
|
||||
|
@ -145,15 +146,15 @@ bool XexModule::SetupLibraryImports(const xe_xex2_import_library_t* library) {
|
|||
VariableInfo* var_info;
|
||||
DeclareVariable(info->value_address, &var_info);
|
||||
// var->set_name(name);
|
||||
var_info->set_status(SymbolInfo::STATUS_DECLARED);
|
||||
var_info->set_status(SymbolStatus::kDeclared);
|
||||
DefineVariable(var_info);
|
||||
// var->kernel_export = kernel_export;
|
||||
var_info->set_status(SymbolInfo::STATUS_DEFINED);
|
||||
var_info->set_status(SymbolStatus::kDefined);
|
||||
|
||||
// Grab, if available.
|
||||
auto slot = memory_->TranslateVirtual<uint32_t*>(info->value_address);
|
||||
if (kernel_export) {
|
||||
if (kernel_export->type == KernelExport::Function) {
|
||||
if (kernel_export->type == Export::Type::kFunction) {
|
||||
// Not exactly sure what this should be...
|
||||
if (info->thunk_address) {
|
||||
*slot = xe::byte_swap(info->thunk_address);
|
||||
|
@ -164,7 +165,7 @@ bool XexModule::SetupLibraryImports(const xe_xex2_import_library_t* library) {
|
|||
*slot = xe::byte_swap(0xF00DF00D);
|
||||
}
|
||||
} else {
|
||||
if (kernel_export->is_implemented) {
|
||||
if (kernel_export->is_implemented()) {
|
||||
// Implemented - replace with pointer.
|
||||
xe::store_and_swap<uint32_t>(slot, kernel_export->variable_ptr);
|
||||
} else {
|
||||
|
@ -232,22 +233,19 @@ bool XexModule::SetupLibraryImports(const xe_xex2_import_library_t* library) {
|
|||
xe::store_and_swap<uint32_t>(p + 0xC, 0x60000000);
|
||||
|
||||
FunctionInfo::ExternHandler handler = 0;
|
||||
void* handler_data = 0;
|
||||
if (kernel_export) {
|
||||
handler =
|
||||
(FunctionInfo::ExternHandler)kernel_export->function_data.shim;
|
||||
handler_data = kernel_export->function_data.shim_data;
|
||||
} else {
|
||||
handler = (FunctionInfo::ExternHandler)UndefinedImport;
|
||||
handler_data = this;
|
||||
handler = UndefinedImport;
|
||||
}
|
||||
|
||||
FunctionInfo* fn_info;
|
||||
DeclareFunction(info->thunk_address, &fn_info);
|
||||
fn_info->set_end_address(info->thunk_address + 16 - 4);
|
||||
fn_info->set_name(name);
|
||||
fn_info->SetupExtern(handler, handler_data, NULL);
|
||||
fn_info->set_status(SymbolInfo::STATUS_DECLARED);
|
||||
fn_info->SetupExtern(handler);
|
||||
fn_info->set_status(SymbolStatus::kDeclared);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -470,8 +468,8 @@ bool XexModule::FindSaveRest() {
|
|||
symbol_info->set_name(name);
|
||||
// TODO(benvanik): set type fn->type = FunctionSymbol::User;
|
||||
// TODO(benvanik): set flags fn->flags |= FunctionSymbol::kFlagSaveGprLr;
|
||||
symbol_info->set_behavior(FunctionInfo::BEHAVIOR_PROLOG);
|
||||
symbol_info->set_status(SymbolInfo::STATUS_DECLARED);
|
||||
symbol_info->set_behavior(FunctionBehavior::kProlog);
|
||||
symbol_info->set_status(SymbolStatus::kDeclared);
|
||||
address += 4;
|
||||
}
|
||||
address = gplr_start + 20 * 4;
|
||||
|
@ -483,8 +481,8 @@ bool XexModule::FindSaveRest() {
|
|||
symbol_info->set_name(name);
|
||||
// TODO(benvanik): set type fn->type = FunctionSymbol::User;
|
||||
// TODO(benvanik): set flags fn->flags |= FunctionSymbol::kFlagRestGprLr;
|
||||
symbol_info->set_behavior(FunctionInfo::BEHAVIOR_EPILOG_RETURN);
|
||||
symbol_info->set_status(SymbolInfo::STATUS_DECLARED);
|
||||
symbol_info->set_behavior(FunctionBehavior::kEpilogReturn);
|
||||
symbol_info->set_status(SymbolStatus::kDeclared);
|
||||
address += 4;
|
||||
}
|
||||
}
|
||||
|
@ -498,8 +496,8 @@ bool XexModule::FindSaveRest() {
|
|||
symbol_info->set_name(name);
|
||||
// TODO(benvanik): set type fn->type = FunctionSymbol::User;
|
||||
// TODO(benvanik): set flags fn->flags |= FunctionSymbol::kFlagSaveFpr;
|
||||
symbol_info->set_behavior(FunctionInfo::BEHAVIOR_PROLOG);
|
||||
symbol_info->set_status(SymbolInfo::STATUS_DECLARED);
|
||||
symbol_info->set_behavior(FunctionBehavior::kProlog);
|
||||
symbol_info->set_status(SymbolStatus::kDeclared);
|
||||
address += 4;
|
||||
}
|
||||
address = fpr_start + (18 * 4) + (1 * 4);
|
||||
|
@ -511,8 +509,8 @@ bool XexModule::FindSaveRest() {
|
|||
symbol_info->set_name(name);
|
||||
// TODO(benvanik): set type fn->type = FunctionSymbol::User;
|
||||
// TODO(benvanik): set flags fn->flags |= FunctionSymbol::kFlagRestFpr;
|
||||
symbol_info->set_behavior(FunctionInfo::BEHAVIOR_EPILOG);
|
||||
symbol_info->set_status(SymbolInfo::STATUS_DECLARED);
|
||||
symbol_info->set_behavior(FunctionBehavior::kEpilog);
|
||||
symbol_info->set_status(SymbolStatus::kDeclared);
|
||||
address += 4;
|
||||
}
|
||||
}
|
||||
|
@ -530,8 +528,8 @@ bool XexModule::FindSaveRest() {
|
|||
symbol_info->set_name(name);
|
||||
// TODO(benvanik): set type fn->type = FunctionSymbol::User;
|
||||
// TODO(benvanik): set flags fn->flags |= FunctionSymbol::kFlagSaveVmx;
|
||||
symbol_info->set_behavior(FunctionInfo::BEHAVIOR_PROLOG);
|
||||
symbol_info->set_status(SymbolInfo::STATUS_DECLARED);
|
||||
symbol_info->set_behavior(FunctionBehavior::kProlog);
|
||||
symbol_info->set_status(SymbolStatus::kDeclared);
|
||||
address += 2 * 4;
|
||||
}
|
||||
address += 4;
|
||||
|
@ -542,8 +540,8 @@ bool XexModule::FindSaveRest() {
|
|||
symbol_info->set_name(name);
|
||||
// TODO(benvanik): set type fn->type = FunctionSymbol::User;
|
||||
// TODO(benvanik): set flags fn->flags |= FunctionSymbol::kFlagSaveVmx;
|
||||
symbol_info->set_behavior(FunctionInfo::BEHAVIOR_PROLOG);
|
||||
symbol_info->set_status(SymbolInfo::STATUS_DECLARED);
|
||||
symbol_info->set_behavior(FunctionBehavior::kProlog);
|
||||
symbol_info->set_status(SymbolStatus::kDeclared);
|
||||
address += 2 * 4;
|
||||
}
|
||||
address = vmx_start + (18 * 2 * 4) + (1 * 4) + (64 * 2 * 4) + (1 * 4);
|
||||
|
@ -554,8 +552,8 @@ bool XexModule::FindSaveRest() {
|
|||
symbol_info->set_name(name);
|
||||
// TODO(benvanik): set type fn->type = FunctionSymbol::User;
|
||||
// TODO(benvanik): set flags fn->flags |= FunctionSymbol::kFlagRestVmx;
|
||||
symbol_info->set_behavior(FunctionInfo::BEHAVIOR_EPILOG);
|
||||
symbol_info->set_status(SymbolInfo::STATUS_DECLARED);
|
||||
symbol_info->set_behavior(FunctionBehavior::kEpilog);
|
||||
symbol_info->set_status(SymbolStatus::kDeclared);
|
||||
address += 2 * 4;
|
||||
}
|
||||
address += 4;
|
||||
|
@ -566,8 +564,8 @@ bool XexModule::FindSaveRest() {
|
|||
symbol_info->set_name(name);
|
||||
// TODO(benvanik): set type fn->type = FunctionSymbol::User;
|
||||
// TODO(benvanik): set flags fn->flags |= FunctionSymbol::kFlagRestVmx;
|
||||
symbol_info->set_behavior(FunctionInfo::BEHAVIOR_EPILOG);
|
||||
symbol_info->set_status(SymbolInfo::STATUS_DECLARED);
|
||||
symbol_info->set_behavior(FunctionBehavior::kEpilog);
|
||||
symbol_info->set_status(SymbolStatus::kDeclared);
|
||||
address += 2 * 4;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -34,7 +34,7 @@ uint32_t XKernelModule::GetProcAddressByOrdinal(uint16_t ordinal) {
|
|||
// Export (or its parent library) not found.
|
||||
return 0;
|
||||
}
|
||||
if (export->type == cpu::KernelExport::ExportType::Variable) {
|
||||
if (export->type == cpu::Export::Type::kVariable) {
|
||||
if (export->variable_ptr) {
|
||||
return export->variable_ptr;
|
||||
} else {
|
||||
|
|
|
@ -338,11 +338,11 @@ void XUserModule::Dump() {
|
|||
const xe_xex2_import_info_t* info = &import_infos[m];
|
||||
|
||||
if (kernel_state_->IsKernelModule(library->name)) {
|
||||
KernelExport* kernel_export =
|
||||
auto kernel_export =
|
||||
export_resolver->GetExportByOrdinal(library->name, info->ordinal);
|
||||
if (kernel_export) {
|
||||
known_count++;
|
||||
if (kernel_export->is_implemented) {
|
||||
if (kernel_export->is_implemented()) {
|
||||
impl_count++;
|
||||
} else {
|
||||
unimpl_count++;
|
||||
|
@ -384,13 +384,13 @@ void XUserModule::Dump() {
|
|||
const char* name = "UNKNOWN";
|
||||
bool implemented = false;
|
||||
|
||||
KernelExport* kernel_export = nullptr;
|
||||
Export* kernel_export = nullptr;
|
||||
if (kernel_state_->IsKernelModule(library->name)) {
|
||||
kernel_export =
|
||||
export_resolver->GetExportByOrdinal(library->name, info->ordinal);
|
||||
if (kernel_export) {
|
||||
name = kernel_export->name;
|
||||
implemented = kernel_export->is_implemented;
|
||||
name = kernel_export->name.c_str();
|
||||
implemented = kernel_export->is_implemented();
|
||||
}
|
||||
} else {
|
||||
auto module = kernel_state_->GetModule(library->name);
|
||||
|
@ -399,7 +399,7 @@ void XUserModule::Dump() {
|
|||
implemented = true;
|
||||
}
|
||||
}
|
||||
if (kernel_export && kernel_export->type == KernelExport::Variable) {
|
||||
if (kernel_export && kernel_export->type == Export::Type::kVariable) {
|
||||
printf(" V %.8X %.3X (%3d) %s %s\n", info->value_address,
|
||||
info->ordinal, info->ordinal, implemented ? " " : "!!", name);
|
||||
} else if (info->thunk_address) {
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
*
|
||||
* // Build the export table used for resolution.
|
||||
* #include "xenia/kernel/util/export_table_pre.inc"
|
||||
* static KernelExport my_module_export_table[] = {
|
||||
* static Export my_module_export_table[] = {
|
||||
* #include "xenia/kernel/my_module/my_module_table.inc"
|
||||
* };
|
||||
* #include "xenia/kernel/util/export_table_post.inc"
|
||||
|
@ -23,11 +23,10 @@
|
|||
*/
|
||||
|
||||
|
||||
#define XE_EXPORT(module, ordinal, name, type, flags) \
|
||||
#define XE_EXPORT(module, ordinal, name, type) \
|
||||
{ \
|
||||
ordinal, \
|
||||
xe::cpu::KernelExport::type, \
|
||||
flags, \
|
||||
xe::cpu::Export::Type::type, \
|
||||
#name, \
|
||||
}
|
||||
|
||||
|
|
|
@ -22,6 +22,6 @@
|
|||
*/
|
||||
|
||||
|
||||
#define XE_EXPORT(module, ordinal, name, type, flags) \
|
||||
#define XE_EXPORT(module, ordinal, name, type) \
|
||||
name = ordinal
|
||||
|
||||
|
|
|
@ -21,7 +21,7 @@ using PPCContext = xe::cpu::frontend::PPCContext;
|
|||
#define SHIM_CALL void _cdecl
|
||||
#define SHIM_SET_MAPPING(library_name, export_name, shim_data) \
|
||||
export_resolver->SetFunctionMapping( \
|
||||
library_name, ordinals::##export_name, shim_data, \
|
||||
library_name, ordinals::##export_name, \
|
||||
(xe::cpu::xe_kernel_export_shim_fn)export_name##_shim);
|
||||
|
||||
#define SHIM_MEM_BASE ppc_state->virtual_membase
|
||||
|
|
|
@ -42,7 +42,7 @@ void XamModule::RegisterExportTable(xe::cpu::ExportResolver* export_resolver) {
|
|||
|
||||
// Build the export table used for resolution.
|
||||
#include "xenia/kernel/util/export_table_pre.inc"
|
||||
static xe::cpu::KernelExport xam_export_table[] = {
|
||||
static xe::cpu::Export xam_export_table[] = {
|
||||
#include "xenia/kernel/xam_table.inc"
|
||||
};
|
||||
#include "xenia/kernel/util/export_table_post.inc"
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -159,7 +159,7 @@ void XboxkrnlModule::RegisterExportTable(
|
|||
|
||||
// Build the export table used for resolution.
|
||||
#include "xenia/kernel/util/export_table_pre.inc"
|
||||
static xe::cpu::KernelExport xboxkrnl_export_table[] = {
|
||||
static xe::cpu::Export xboxkrnl_export_table[] = {
|
||||
#include "xenia/kernel/xboxkrnl_table.inc"
|
||||
};
|
||||
#include "xenia/kernel/util/export_table_post.inc"
|
||||
|
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue