Shrinking alloy memory interface so that alloy-sandbox doesn't need xe.
This commit is contained in:
parent
76d524b655
commit
48a0e5c601
|
@ -1499,7 +1499,9 @@ int Translate_LOAD(TranslationContext& ctx, Instr* i) {
|
||||||
|
|
||||||
void MarkPageDirty(IntCodeState& ics, uint32_t address) {
|
void MarkPageDirty(IntCodeState& ics, uint32_t address) {
|
||||||
// 16KB pages.
|
// 16KB pages.
|
||||||
ics.page_table[(address >> 14) & 0x7FFF] = 1;
|
if (ics.page_table) {
|
||||||
|
ics.page_table[(address >> 14) & 0x7FFF] = 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
uint32_t IntCode_STORE_I8(IntCodeState& ics, const IntCode* i) {
|
uint32_t IntCode_STORE_I8(IntCodeState& ics, const IntCode* i) {
|
||||||
uint32_t address = ics.rf[i->src1_reg].u32;
|
uint32_t address = ics.rf[i->src1_reg].u32;
|
||||||
|
|
|
@ -1557,9 +1557,12 @@ EMITTER_OPCODE_TABLE(
|
||||||
// Note: most *should* be aligned, but needs to be checked!
|
// Note: most *should* be aligned, but needs to be checked!
|
||||||
void EmitMarkPageDirty(X64Emitter& e, RegExp& addr) {
|
void EmitMarkPageDirty(X64Emitter& e, RegExp& addr) {
|
||||||
// 16KB pages.
|
// 16KB pages.
|
||||||
e.shr(e.eax, 14);
|
auto page_table_address = e.page_table_address();
|
||||||
e.and(e.eax, 0x7FFF);
|
if (page_table_address) {
|
||||||
e.mov(e.byte[e.rdx + e.rax + e.page_table_address()], 1);
|
e.shr(e.eax, 14);
|
||||||
|
e.and(e.eax, 0x7FFF);
|
||||||
|
e.mov(e.byte[e.rdx + e.rax + page_table_address], 1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
EMITTER(STORE_I8, MATCH(I<OPCODE_STORE, VoidOp, I64<>, I8<>>)) {
|
EMITTER(STORE_I8, MATCH(I<OPCODE_STORE, VoidOp, I64<>, I8<>>)) {
|
||||||
static void Emit(X64Emitter& e, const EmitArgType& i) {
|
static void Emit(X64Emitter& e, const EmitArgType& i) {
|
||||||
|
|
|
@ -172,7 +172,7 @@ typedef struct alignas(64) PPCContext_s {
|
||||||
uint32_t thread_id;
|
uint32_t thread_id;
|
||||||
|
|
||||||
// Reserve address for load acquire/store release. Shared.
|
// Reserve address for load acquire/store release. Shared.
|
||||||
uint32_t* reserve_address;
|
uint64_t* reserve_address;
|
||||||
|
|
||||||
// Runtime-specific data pointer. Used on callbacks to get access to the
|
// Runtime-specific data pointer. Used on callbacks to get access to the
|
||||||
// current runtime and its data.
|
// current runtime and its data.
|
||||||
|
|
|
@ -61,4 +61,43 @@ uint64_t Memory::SearchAligned(uint64_t start, uint64_t end,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SimpleMemory::SimpleMemory(size_t capacity) : memory_(capacity) {
|
||||||
|
membase_ = reinterpret_cast<uint8_t*>(memory_.data());
|
||||||
|
reserve_address_ = capacity - 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
SimpleMemory::~SimpleMemory() = default;
|
||||||
|
|
||||||
|
uint8_t SimpleMemory::LoadI8(uint64_t address) {
|
||||||
|
return poly::load<uint8_t>(membase_ + address);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t SimpleMemory::LoadI16(uint64_t address) {
|
||||||
|
return poly::load<uint16_t>(membase_ + address);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t SimpleMemory::LoadI32(uint64_t address) {
|
||||||
|
return poly::load<uint32_t>(membase_ + address);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t SimpleMemory::LoadI64(uint64_t address) {
|
||||||
|
return poly::load<uint64_t>(membase_ + address);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SimpleMemory::StoreI8(uint64_t address, uint8_t value) {
|
||||||
|
poly::store<uint8_t>(membase_ + address, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SimpleMemory::StoreI16(uint64_t address, uint16_t value) {
|
||||||
|
poly::store<uint16_t>(membase_ + address, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SimpleMemory::StoreI32(uint64_t address, uint32_t value) {
|
||||||
|
poly::store<uint32_t>(membase_ + address, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SimpleMemory::StoreI64(uint64_t address, uint64_t value) {
|
||||||
|
poly::store<uint64_t>(membase_ + address, value);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace alloy
|
} // namespace alloy
|
||||||
|
|
|
@ -14,23 +14,6 @@
|
||||||
|
|
||||||
namespace alloy {
|
namespace alloy {
|
||||||
|
|
||||||
enum {
|
|
||||||
MEMORY_FLAG_64KB_PAGES = (1 << 1),
|
|
||||||
MEMORY_FLAG_ZERO = (1 << 2),
|
|
||||||
MEMORY_FLAG_PHYSICAL = (1 << 3),
|
|
||||||
};
|
|
||||||
|
|
||||||
// Equivalent to the Win32 MEMORY_BASIC_INFORMATION struct.
|
|
||||||
struct AllocationInfo {
|
|
||||||
uint64_t base_address;
|
|
||||||
uint64_t allocation_base;
|
|
||||||
uint32_t allocation_protect; // TBD
|
|
||||||
size_t region_size;
|
|
||||||
uint32_t state; // TBD
|
|
||||||
uint32_t protect; // TBD
|
|
||||||
uint32_t type; // TBD
|
|
||||||
};
|
|
||||||
|
|
||||||
class Memory {
|
class Memory {
|
||||||
public:
|
public:
|
||||||
Memory();
|
Memory();
|
||||||
|
@ -40,8 +23,9 @@ class Memory {
|
||||||
inline uint8_t* Translate(uint64_t guest_address) const {
|
inline uint8_t* Translate(uint64_t guest_address) const {
|
||||||
return membase_ + guest_address;
|
return membase_ + guest_address;
|
||||||
};
|
};
|
||||||
inline uint32_t* reserve_address() { return &reserve_address_; }
|
inline uint64_t* reserve_address() { return &reserve_address_; }
|
||||||
|
|
||||||
|
// TODO(benvanik): remove with GPU refactor.
|
||||||
virtual uint64_t page_table() const = 0;
|
virtual uint64_t page_table() const = 0;
|
||||||
|
|
||||||
uint64_t trace_base() const { return trace_base_; }
|
uint64_t trace_base() const { return trace_base_; }
|
||||||
|
@ -49,6 +33,7 @@ class Memory {
|
||||||
|
|
||||||
virtual int Initialize();
|
virtual int Initialize();
|
||||||
|
|
||||||
|
// TODO(benvanik): make poly memory utils for these.
|
||||||
void Zero(uint64_t address, size_t size);
|
void Zero(uint64_t address, size_t size);
|
||||||
void Fill(uint64_t address, size_t size, uint8_t value);
|
void Fill(uint64_t address, size_t size, uint8_t value);
|
||||||
void Copy(uint64_t dest, uint64_t src, size_t size);
|
void Copy(uint64_t dest, uint64_t src, size_t size);
|
||||||
|
@ -56,6 +41,7 @@ class Memory {
|
||||||
uint64_t SearchAligned(uint64_t start, uint64_t end, const uint32_t* values,
|
uint64_t SearchAligned(uint64_t start, uint64_t end, const uint32_t* values,
|
||||||
size_t value_count);
|
size_t value_count);
|
||||||
|
|
||||||
|
// TODO(benvanik): remove with IVM.
|
||||||
virtual uint8_t LoadI8(uint64_t address) = 0;
|
virtual uint8_t LoadI8(uint64_t address) = 0;
|
||||||
virtual uint16_t LoadI16(uint64_t address) = 0;
|
virtual uint16_t LoadI16(uint64_t address) = 0;
|
||||||
virtual uint32_t LoadI32(uint64_t address) = 0;
|
virtual uint32_t LoadI32(uint64_t address) = 0;
|
||||||
|
@ -65,24 +51,34 @@ class Memory {
|
||||||
virtual void StoreI32(uint64_t address, uint32_t value) = 0;
|
virtual void StoreI32(uint64_t address, uint32_t value) = 0;
|
||||||
virtual void StoreI64(uint64_t address, uint64_t value) = 0;
|
virtual void StoreI64(uint64_t address, uint64_t value) = 0;
|
||||||
|
|
||||||
virtual uint64_t HeapAlloc(uint64_t base_address, size_t size, uint32_t flags,
|
|
||||||
uint32_t alignment = 0x20) = 0;
|
|
||||||
virtual int HeapFree(uint64_t address, size_t size) = 0;
|
|
||||||
|
|
||||||
virtual bool QueryInformation(uint64_t base_address,
|
|
||||||
AllocationInfo* mem_info) = 0;
|
|
||||||
virtual size_t QuerySize(uint64_t base_address) = 0;
|
|
||||||
|
|
||||||
virtual int Protect(uint64_t address, size_t size, uint32_t access) = 0;
|
|
||||||
virtual uint32_t QueryProtect(uint64_t address) = 0;
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
size_t system_page_size_;
|
size_t system_page_size_;
|
||||||
uint8_t* membase_;
|
uint8_t* membase_;
|
||||||
uint32_t reserve_address_;
|
uint64_t reserve_address_;
|
||||||
uint64_t trace_base_;
|
uint64_t trace_base_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class SimpleMemory : public Memory {
|
||||||
|
public:
|
||||||
|
SimpleMemory(size_t capacity);
|
||||||
|
~SimpleMemory() override;
|
||||||
|
|
||||||
|
uint64_t page_table() const override { return 0; }
|
||||||
|
|
||||||
|
// TODO(benvanik): remove with IVM.
|
||||||
|
uint8_t LoadI8(uint64_t address) override;
|
||||||
|
uint16_t LoadI16(uint64_t address) override;
|
||||||
|
uint32_t LoadI32(uint64_t address) override;
|
||||||
|
uint64_t LoadI64(uint64_t address) override;
|
||||||
|
void StoreI8(uint64_t address, uint8_t value) override;
|
||||||
|
void StoreI16(uint64_t address, uint16_t value) override;
|
||||||
|
void StoreI32(uint64_t address, uint32_t value) override;
|
||||||
|
void StoreI64(uint64_t address, uint64_t value) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::vector<uint8_t> memory_;
|
||||||
|
};
|
||||||
|
|
||||||
} // namespace alloy
|
} // namespace alloy
|
||||||
|
|
||||||
#endif // ALLOY_MEMORY_H_
|
#endif // ALLOY_MEMORY_H_
|
||||||
|
|
|
@ -15,11 +15,7 @@ namespace runtime {
|
||||||
RawModule::RawModule(Runtime* runtime)
|
RawModule::RawModule(Runtime* runtime)
|
||||||
: Module(runtime), base_address_(0), low_address_(0), high_address_(0) {}
|
: Module(runtime), base_address_(0), low_address_(0), high_address_(0) {}
|
||||||
|
|
||||||
RawModule::~RawModule() {
|
RawModule::~RawModule() {}
|
||||||
if (base_address_) {
|
|
||||||
memory_->HeapFree(base_address_, high_address_ - low_address_);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int RawModule::LoadFile(uint64_t base_address, const std::string& path) {
|
int RawModule::LoadFile(uint64_t base_address, const std::string& path) {
|
||||||
FILE* file = fopen(path.c_str(), "rb");
|
FILE* file = fopen(path.c_str(), "rb");
|
||||||
|
@ -28,15 +24,12 @@ int RawModule::LoadFile(uint64_t base_address, const std::string& path) {
|
||||||
fseek(file, 0, SEEK_SET);
|
fseek(file, 0, SEEK_SET);
|
||||||
|
|
||||||
// Allocate memory.
|
// Allocate memory.
|
||||||
base_address_ =
|
// Since we have no real heap just load it wherever.
|
||||||
memory_->HeapAlloc(base_address, file_length, MEMORY_FLAG_ZERO);
|
base_address_ = base_address;
|
||||||
if (!base_address_) {
|
uint8_t* p = memory_->Translate(base_address_);
|
||||||
fclose(file);
|
memset(p, 0, file_length);
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Read into memory.
|
// Read into memory.
|
||||||
uint8_t* p = memory_->Translate(base_address_);
|
|
||||||
fread(p, file_length, 1, file);
|
fread(p, file_length, 1, file);
|
||||||
|
|
||||||
fclose(file);
|
fclose(file);
|
||||||
|
|
|
@ -48,7 +48,7 @@ X_STATUS AudioSystem::Setup() {
|
||||||
new XenonThreadState(emulator_->processor()->runtime(), 0, 16 * 1024, 0);
|
new XenonThreadState(emulator_->processor()->runtime(), 0, 16 * 1024, 0);
|
||||||
thread_state_->set_name("Audio Worker");
|
thread_state_->set_name("Audio Worker");
|
||||||
thread_block_ =
|
thread_block_ =
|
||||||
(uint32_t)memory_->HeapAlloc(0, 2048, alloy::MEMORY_FLAG_ZERO);
|
(uint32_t)memory_->HeapAlloc(0, 2048, MEMORY_FLAG_ZERO);
|
||||||
thread_state_->context()->r[13] = thread_block_;
|
thread_state_->context()->r[13] = thread_block_;
|
||||||
|
|
||||||
// Create worker thread.
|
// Create worker thread.
|
||||||
|
|
|
@ -12,13 +12,9 @@
|
||||||
|
|
||||||
#include <xenia/common.h>
|
#include <xenia/common.h>
|
||||||
|
|
||||||
#include <alloy/memory.h>
|
|
||||||
namespace xe {
|
|
||||||
using Memory = alloy::Memory;
|
|
||||||
} // namespace xe
|
|
||||||
|
|
||||||
#include <xenia/core/ref.h>
|
#include <xenia/core/ref.h>
|
||||||
#include <xenia/core/run_loop.h>
|
#include <xenia/core/run_loop.h>
|
||||||
#include <xenia/core/socket.h>
|
#include <xenia/core/socket.h>
|
||||||
|
#include <xenia/memory.h>
|
||||||
|
|
||||||
#endif // XENIA_CORE_H_
|
#endif // XENIA_CORE_H_
|
||||||
|
|
|
@ -12,7 +12,6 @@
|
||||||
#include <xenia/emulator.h>
|
#include <xenia/emulator.h>
|
||||||
#include <xenia/export_resolver.h>
|
#include <xenia/export_resolver.h>
|
||||||
#include <xenia/cpu/cpu-private.h>
|
#include <xenia/cpu/cpu-private.h>
|
||||||
#include <xenia/cpu/xenon_memory.h>
|
|
||||||
#include <xenia/cpu/xenon_runtime.h>
|
#include <xenia/cpu/xenon_runtime.h>
|
||||||
#include <xenia/cpu/xex_module.h>
|
#include <xenia/cpu/xex_module.h>
|
||||||
|
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
XEDECLARECLASS2(alloy, runtime, Breakpoint);
|
XEDECLARECLASS2(alloy, runtime, Breakpoint);
|
||||||
XEDECLARECLASS1(xe, Emulator);
|
XEDECLARECLASS1(xe, Emulator);
|
||||||
XEDECLARECLASS1(xe, ExportResolver);
|
XEDECLARECLASS1(xe, ExportResolver);
|
||||||
|
XEDECLARECLASS1(xe, Memory);
|
||||||
XEDECLARECLASS2(xe, cpu, XenonMemory);
|
XEDECLARECLASS2(xe, cpu, XenonMemory);
|
||||||
XEDECLARECLASS2(xe, cpu, XenonRuntime);
|
XEDECLARECLASS2(xe, cpu, XenonRuntime);
|
||||||
XEDECLARECLASS2(xe, cpu, XenonThreadState);
|
XEDECLARECLASS2(xe, cpu, XenonThreadState);
|
||||||
|
|
|
@ -8,8 +8,6 @@
|
||||||
'mmio_handler.h',
|
'mmio_handler.h',
|
||||||
'processor.cc',
|
'processor.cc',
|
||||||
'processor.h',
|
'processor.h',
|
||||||
'xenon_memory.cc',
|
|
||||||
'xenon_memory.h',
|
|
||||||
'xenon_runtime.cc',
|
'xenon_runtime.cc',
|
||||||
'xenon_runtime.h',
|
'xenon_runtime.h',
|
||||||
'xenon_thread_state.cc',
|
'xenon_thread_state.cc',
|
||||||
|
|
|
@ -10,25 +10,20 @@
|
||||||
#include <xenia/cpu/xenon_runtime.h>
|
#include <xenia/cpu/xenon_runtime.h>
|
||||||
|
|
||||||
#include <alloy/frontend/ppc/ppc_frontend.h>
|
#include <alloy/frontend/ppc/ppc_frontend.h>
|
||||||
|
|
||||||
#include <xenia/cpu/xenon_thread_state.h>
|
#include <xenia/cpu/xenon_thread_state.h>
|
||||||
|
|
||||||
using namespace alloy;
|
|
||||||
using namespace alloy::frontend::ppc;
|
|
||||||
using namespace alloy::runtime;
|
|
||||||
using namespace xe;
|
using namespace xe;
|
||||||
using namespace xe::cpu;
|
using namespace xe::cpu;
|
||||||
|
|
||||||
XenonRuntime::XenonRuntime(alloy::Memory* memory,
|
XenonRuntime::XenonRuntime(Memory* memory, ExportResolver* export_resolver,
|
||||||
ExportResolver* export_resolver,
|
|
||||||
uint32_t debug_info_flags, uint32_t trace_flags)
|
uint32_t debug_info_flags, uint32_t trace_flags)
|
||||||
: Runtime(memory, debug_info_flags, trace_flags),
|
: Runtime(memory, debug_info_flags, trace_flags),
|
||||||
export_resolver_(export_resolver) {}
|
export_resolver_(export_resolver) {}
|
||||||
|
|
||||||
XenonRuntime::~XenonRuntime() = default;
|
XenonRuntime::~XenonRuntime() = default;
|
||||||
|
|
||||||
int XenonRuntime::Initialize(std::unique_ptr<backend::Backend> backend) {
|
int XenonRuntime::Initialize(std::unique_ptr<alloy::backend::Backend> backend) {
|
||||||
std::unique_ptr<PPCFrontend> frontend(new PPCFrontend(this));
|
auto frontend = std::make_unique<alloy::frontend::ppc::PPCFrontend>(this);
|
||||||
// TODO(benvanik): set options/etc.
|
// TODO(benvanik): set options/etc.
|
||||||
|
|
||||||
int result = Runtime::Initialize(std::move(frontend), std::move(backend));
|
int result = Runtime::Initialize(std::move(frontend), std::move(backend));
|
||||||
|
|
|
@ -24,7 +24,7 @@ XenonThreadState::XenonThreadState(XenonRuntime* runtime, uint32_t thread_id,
|
||||||
: ThreadState(runtime, thread_id),
|
: ThreadState(runtime, thread_id),
|
||||||
stack_size_(stack_size),
|
stack_size_(stack_size),
|
||||||
thread_state_address_(thread_state_address) {
|
thread_state_address_(thread_state_address) {
|
||||||
stack_address_ = memory_->HeapAlloc(0, stack_size, MEMORY_FLAG_ZERO);
|
stack_address_ = xenon_memory()->HeapAlloc(0, stack_size, MEMORY_FLAG_ZERO);
|
||||||
assert_not_zero(stack_address_);
|
assert_not_zero(stack_address_);
|
||||||
|
|
||||||
// Allocate with 64b alignment.
|
// Allocate with 64b alignment.
|
||||||
|
@ -56,7 +56,7 @@ XenonThreadState::~XenonThreadState() {
|
||||||
runtime_->debugger()->OnThreadDestroyed(this);
|
runtime_->debugger()->OnThreadDestroyed(this);
|
||||||
|
|
||||||
xe_free_aligned(context_);
|
xe_free_aligned(context_);
|
||||||
memory_->HeapFree(stack_address_, stack_size_);
|
xenon_memory()->HeapFree(stack_address_, stack_size_);
|
||||||
}
|
}
|
||||||
|
|
||||||
void XenonThreadState::WriteRegisters(xdb::protocol::Registers* registers) {
|
void XenonThreadState::WriteRegisters(xdb::protocol::Registers* registers) {
|
||||||
|
|
|
@ -27,13 +27,13 @@ class XenonRuntime;
|
||||||
|
|
||||||
using PPCContext = alloy::frontend::ppc::PPCContext;
|
using PPCContext = alloy::frontend::ppc::PPCContext;
|
||||||
|
|
||||||
|
|
||||||
class XenonThreadState : public alloy::runtime::ThreadState {
|
class XenonThreadState : public alloy::runtime::ThreadState {
|
||||||
public:
|
public:
|
||||||
XenonThreadState(XenonRuntime* runtime, uint32_t thread_id,
|
XenonThreadState(XenonRuntime* runtime, uint32_t thread_id, size_t stack_size,
|
||||||
size_t stack_size, uint64_t thread_state_address);
|
uint64_t thread_state_address);
|
||||||
virtual ~XenonThreadState();
|
virtual ~XenonThreadState();
|
||||||
|
|
||||||
|
Memory* xenon_memory() { return static_cast<Memory*>(memory_); }
|
||||||
uint64_t stack_address() const { return stack_address_; }
|
uint64_t stack_address() const { return stack_address_; }
|
||||||
size_t stack_size() const { return stack_size_; }
|
size_t stack_size() const { return stack_size_; }
|
||||||
uint64_t thread_state_address() const { return thread_state_address_; }
|
uint64_t thread_state_address() const { return thread_state_address_; }
|
||||||
|
@ -41,18 +41,16 @@ public:
|
||||||
|
|
||||||
void WriteRegisters(xdb::protocol::Registers* registers);
|
void WriteRegisters(xdb::protocol::Registers* registers);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
uint64_t stack_address_;
|
uint64_t stack_address_;
|
||||||
size_t stack_size_;
|
size_t stack_size_;
|
||||||
uint64_t thread_state_address_;
|
uint64_t thread_state_address_;
|
||||||
|
|
||||||
// NOTE: must be 64b aligned for SSE ops.
|
// NOTE: must be 64b aligned for SSE ops.
|
||||||
PPCContext* context_;
|
PPCContext* context_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
} // namespace cpu
|
} // namespace cpu
|
||||||
} // namespace xe
|
} // namespace xe
|
||||||
|
|
||||||
|
|
||||||
#endif // XENIA_CPU_XENON_THREAD_STATE_H_
|
#endif // XENIA_CPU_XENON_THREAD_STATE_H_
|
||||||
|
|
|
@ -13,13 +13,13 @@
|
||||||
#include <xdb/protocol.h>
|
#include <xdb/protocol.h>
|
||||||
#include <xenia/apu/apu.h>
|
#include <xenia/apu/apu.h>
|
||||||
#include <xenia/cpu/cpu.h>
|
#include <xenia/cpu/cpu.h>
|
||||||
#include <xenia/cpu/xenon_memory.h>
|
|
||||||
#include <xenia/gpu/gpu.h>
|
#include <xenia/gpu/gpu.h>
|
||||||
#include <xenia/hid/hid.h>
|
#include <xenia/hid/hid.h>
|
||||||
#include <xenia/kernel/kernel.h>
|
#include <xenia/kernel/kernel.h>
|
||||||
#include <xenia/kernel/kernel_state.h>
|
#include <xenia/kernel/kernel_state.h>
|
||||||
#include <xenia/kernel/modules.h>
|
#include <xenia/kernel/modules.h>
|
||||||
#include <xenia/kernel/fs/filesystem.h>
|
#include <xenia/kernel/fs/filesystem.h>
|
||||||
|
#include <xenia/memory.h>
|
||||||
#include <xenia/ui/window.h>
|
#include <xenia/ui/window.h>
|
||||||
|
|
||||||
namespace xe {
|
namespace xe {
|
||||||
|
@ -87,7 +87,7 @@ X_STATUS Emulator::Setup() {
|
||||||
XEEXPECTZERO(result);
|
XEEXPECTZERO(result);
|
||||||
|
|
||||||
// Create memory system first, as it is required for other systems.
|
// Create memory system first, as it is required for other systems.
|
||||||
memory_ = new XenonMemory();
|
memory_ = new Memory();
|
||||||
XEEXPECTNOTNULL(memory_);
|
XEEXPECTNOTNULL(memory_);
|
||||||
result = memory_->Initialize();
|
result = memory_->Initialize();
|
||||||
XEEXPECTZERO(result);
|
XEEXPECTZERO(result);
|
||||||
|
|
|
@ -14,7 +14,6 @@
|
||||||
|
|
||||||
#include <xenia/common.h>
|
#include <xenia/common.h>
|
||||||
#include <xenia/core.h>
|
#include <xenia/core.h>
|
||||||
#include <xenia/cpu/xenon_memory.h>
|
|
||||||
#include <xenia/debug_agent.h>
|
#include <xenia/debug_agent.h>
|
||||||
#include <xenia/kernel/kernel_state.h>
|
#include <xenia/kernel/kernel_state.h>
|
||||||
#include <xenia/xbox.h>
|
#include <xenia/xbox.h>
|
||||||
|
@ -55,7 +54,7 @@ class Emulator {
|
||||||
ui::Window* main_window() const { return main_window_; }
|
ui::Window* main_window() const { return main_window_; }
|
||||||
void set_main_window(ui::Window* window);
|
void set_main_window(ui::Window* window);
|
||||||
|
|
||||||
cpu::XenonMemory* memory() const { return memory_; }
|
Memory* memory() const { return memory_; }
|
||||||
|
|
||||||
DebugAgent* debug_agent() const { return debug_agent_.get(); }
|
DebugAgent* debug_agent() const { return debug_agent_.get(); }
|
||||||
|
|
||||||
|
@ -79,31 +78,29 @@ class Emulator {
|
||||||
|
|
||||||
private:
|
private:
|
||||||
X_STATUS CompleteLaunch(const std::wstring& path,
|
X_STATUS CompleteLaunch(const std::wstring& path,
|
||||||
const std::string& module_path);
|
const std::string& module_path);
|
||||||
|
|
||||||
std::wstring command_line_;
|
std::wstring command_line_;
|
||||||
|
|
||||||
ui::Window* main_window_;
|
ui::Window* main_window_;
|
||||||
|
|
||||||
cpu::XenonMemory* memory_;
|
Memory* memory_;
|
||||||
|
|
||||||
std::unique_ptr<DebugAgent> debug_agent_;
|
std::unique_ptr<DebugAgent> debug_agent_;
|
||||||
|
|
||||||
cpu::Processor* processor_;
|
cpu::Processor* processor_;
|
||||||
apu::AudioSystem* audio_system_;
|
apu::AudioSystem* audio_system_;
|
||||||
gpu::GraphicsSystem* graphics_system_;
|
gpu::GraphicsSystem* graphics_system_;
|
||||||
hid::InputSystem* input_system_;
|
hid::InputSystem* input_system_;
|
||||||
|
|
||||||
ExportResolver* export_resolver_;
|
ExportResolver* export_resolver_;
|
||||||
kernel::fs::FileSystem* file_system_;
|
kernel::fs::FileSystem* file_system_;
|
||||||
|
|
||||||
kernel::KernelState* kernel_state_;
|
kernel::KernelState* kernel_state_;
|
||||||
kernel::XamModule* xam_;
|
kernel::XamModule* xam_;
|
||||||
kernel::XboxkrnlModule* xboxkrnl_;
|
kernel::XboxkrnlModule* xboxkrnl_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
} // namespace xe
|
} // namespace xe
|
||||||
|
|
||||||
|
|
||||||
#endif // XENIA_EMULATOR_H_
|
#endif // XENIA_EMULATOR_H_
|
||||||
|
|
|
@ -152,7 +152,7 @@ X_STATUS XThread::Create() {
|
||||||
// So, at offset 0x100 we have a 4b pointer to offset 200, then have the
|
// So, at offset 0x100 we have a 4b pointer to offset 200, then have the
|
||||||
// structure.
|
// structure.
|
||||||
thread_state_address_ =
|
thread_state_address_ =
|
||||||
(uint32_t)memory()->HeapAlloc(0, 2048, alloy::MEMORY_FLAG_ZERO);
|
(uint32_t)memory()->HeapAlloc(0, 2048, MEMORY_FLAG_ZERO);
|
||||||
if (!thread_state_address_) {
|
if (!thread_state_address_) {
|
||||||
XELOGW("Unable to allocate thread state block");
|
XELOGW("Unable to allocate thread state block");
|
||||||
return X_STATUS_NO_MEMORY;
|
return X_STATUS_NO_MEMORY;
|
||||||
|
@ -167,13 +167,12 @@ X_STATUS XThread::Create() {
|
||||||
// This is used by interrupts/APCs/etc so we can round-trip pointers through.
|
// This is used by interrupts/APCs/etc so we can round-trip pointers through.
|
||||||
scratch_size_ = 4 * 16;
|
scratch_size_ = 4 * 16;
|
||||||
scratch_address_ =
|
scratch_address_ =
|
||||||
(uint32_t)memory()->HeapAlloc(0, scratch_size_, alloy::MEMORY_FLAG_ZERO);
|
(uint32_t)memory()->HeapAlloc(0, scratch_size_, MEMORY_FLAG_ZERO);
|
||||||
|
|
||||||
// Allocate TLS block.
|
// Allocate TLS block.
|
||||||
const xe_xex2_header_t* header = module->xex_header();
|
const xe_xex2_header_t* header = module->xex_header();
|
||||||
uint32_t tls_size = header->tls_info.slot_count * header->tls_info.data_size;
|
uint32_t tls_size = header->tls_info.slot_count * header->tls_info.data_size;
|
||||||
tls_address_ =
|
tls_address_ = (uint32_t)memory()->HeapAlloc(0, tls_size, MEMORY_FLAG_ZERO);
|
||||||
(uint32_t)memory()->HeapAlloc(0, tls_size, alloy::MEMORY_FLAG_ZERO);
|
|
||||||
if (!tls_address_) {
|
if (!tls_address_) {
|
||||||
XELOGW("Unable to allocate thread local storage block");
|
XELOGW("Unable to allocate thread local storage block");
|
||||||
module->Release();
|
module->Release();
|
||||||
|
|
|
@ -21,14 +21,14 @@
|
||||||
#include <third_party/mspack/mspack.h>
|
#include <third_party/mspack/mspack.h>
|
||||||
#include <third_party/pe/pe_image.h>
|
#include <third_party/pe/pe_image.h>
|
||||||
|
|
||||||
using namespace alloy;
|
// using namespace alloy;
|
||||||
|
|
||||||
DEFINE_bool(xex_dev_key, false, "Use the devkit key.");
|
DEFINE_bool(xex_dev_key, false, "Use the devkit key.");
|
||||||
|
|
||||||
typedef struct xe_xex2 {
|
typedef struct xe_xex2 {
|
||||||
xe_ref_t ref;
|
xe_ref_t ref;
|
||||||
|
|
||||||
Memory *memory;
|
xe::Memory *memory;
|
||||||
|
|
||||||
xe_xex2_header_t header;
|
xe_xex2_header_t header;
|
||||||
|
|
||||||
|
@ -44,13 +44,13 @@ int xe_xex2_read_header(const uint8_t *addr, const size_t length,
|
||||||
xe_xex2_header_t *header);
|
xe_xex2_header_t *header);
|
||||||
int xe_xex2_decrypt_key(xe_xex2_header_t *header);
|
int xe_xex2_decrypt_key(xe_xex2_header_t *header);
|
||||||
int xe_xex2_read_image(xe_xex2_ref xex, const uint8_t *xex_addr,
|
int xe_xex2_read_image(xe_xex2_ref xex, const uint8_t *xex_addr,
|
||||||
const size_t xex_length, Memory *memory);
|
const size_t xex_length, xe::Memory *memory);
|
||||||
int xe_xex2_load_pe(xe_xex2_ref xex);
|
int xe_xex2_load_pe(xe_xex2_ref xex);
|
||||||
int xe_xex2_find_import_infos(xe_xex2_ref xex,
|
int xe_xex2_find_import_infos(xe_xex2_ref xex,
|
||||||
const xe_xex2_import_library_t *library);
|
const xe_xex2_import_library_t *library);
|
||||||
|
|
||||||
xe_xex2_ref xe_xex2_load(Memory *memory, const void *addr, const size_t length,
|
xe_xex2_ref xe_xex2_load(xe::Memory *memory, const void *addr,
|
||||||
xe_xex2_options_t options) {
|
const size_t length, xe_xex2_options_t options) {
|
||||||
xe_xex2_ref xex = (xe_xex2_ref)xe_calloc(sizeof(xe_xex2));
|
xe_xex2_ref xex = (xe_xex2_ref)xe_calloc(sizeof(xe_xex2));
|
||||||
xe_ref_init((xe_ref)xex);
|
xe_ref_init((xe_ref)xex);
|
||||||
|
|
||||||
|
@ -542,12 +542,13 @@ void xe_xex2_decrypt_buffer(const uint8_t *session_key,
|
||||||
|
|
||||||
int xe_xex2_read_image_uncompressed(const xe_xex2_header_t *header,
|
int xe_xex2_read_image_uncompressed(const xe_xex2_header_t *header,
|
||||||
const uint8_t *xex_addr,
|
const uint8_t *xex_addr,
|
||||||
const size_t xex_length, Memory *memory) {
|
const size_t xex_length,
|
||||||
|
xe::Memory *memory) {
|
||||||
// Allocate in-place the XEX memory.
|
// Allocate in-place the XEX memory.
|
||||||
const size_t exe_length = xex_length - header->exe_offset;
|
const size_t exe_length = xex_length - header->exe_offset;
|
||||||
size_t uncompressed_size = exe_length;
|
size_t uncompressed_size = exe_length;
|
||||||
uint32_t alloc_result = (uint32_t)memory->HeapAlloc(
|
uint32_t alloc_result = (uint32_t)memory->HeapAlloc(
|
||||||
header->exe_address, uncompressed_size, MEMORY_FLAG_ZERO);
|
header->exe_address, uncompressed_size, xe::MEMORY_FLAG_ZERO);
|
||||||
if (!alloc_result) {
|
if (!alloc_result) {
|
||||||
XELOGE("Unable to allocate XEX memory at %.8X-%.8X.", header->exe_address,
|
XELOGE("Unable to allocate XEX memory at %.8X-%.8X.", header->exe_address,
|
||||||
uncompressed_size);
|
uncompressed_size);
|
||||||
|
@ -575,7 +576,7 @@ int xe_xex2_read_image_uncompressed(const xe_xex2_header_t *header,
|
||||||
int xe_xex2_read_image_basic_compressed(const xe_xex2_header_t *header,
|
int xe_xex2_read_image_basic_compressed(const xe_xex2_header_t *header,
|
||||||
const uint8_t *xex_addr,
|
const uint8_t *xex_addr,
|
||||||
const size_t xex_length,
|
const size_t xex_length,
|
||||||
Memory *memory) {
|
xe::Memory *memory) {
|
||||||
const size_t exe_length = xex_length - header->exe_offset;
|
const size_t exe_length = xex_length - header->exe_offset;
|
||||||
const uint8_t *source_buffer = (const uint8_t *)xex_addr + header->exe_offset;
|
const uint8_t *source_buffer = (const uint8_t *)xex_addr + header->exe_offset;
|
||||||
const uint8_t *p = source_buffer;
|
const uint8_t *p = source_buffer;
|
||||||
|
@ -592,7 +593,7 @@ int xe_xex2_read_image_basic_compressed(const xe_xex2_header_t *header,
|
||||||
|
|
||||||
// Allocate in-place the XEX memory.
|
// Allocate in-place the XEX memory.
|
||||||
uint32_t alloc_result = (uint32_t)memory->HeapAlloc(
|
uint32_t alloc_result = (uint32_t)memory->HeapAlloc(
|
||||||
header->exe_address, uncompressed_size, MEMORY_FLAG_ZERO);
|
header->exe_address, uncompressed_size, xe::MEMORY_FLAG_ZERO);
|
||||||
if (!alloc_result) {
|
if (!alloc_result) {
|
||||||
XELOGE("Unable to allocate XEX memory at %.8X-%.8X.", header->exe_address,
|
XELOGE("Unable to allocate XEX memory at %.8X-%.8X.", header->exe_address,
|
||||||
uncompressed_size);
|
uncompressed_size);
|
||||||
|
@ -645,7 +646,7 @@ XECLEANUP:
|
||||||
|
|
||||||
int xe_xex2_read_image_compressed(const xe_xex2_header_t *header,
|
int xe_xex2_read_image_compressed(const xe_xex2_header_t *header,
|
||||||
const uint8_t *xex_addr,
|
const uint8_t *xex_addr,
|
||||||
const size_t xex_length, Memory *memory) {
|
const size_t xex_length, xe::Memory *memory) {
|
||||||
const size_t exe_length = xex_length - header->exe_offset;
|
const size_t exe_length = xex_length - header->exe_offset;
|
||||||
const uint8_t *exe_buffer = (const uint8_t *)xex_addr + header->exe_offset;
|
const uint8_t *exe_buffer = (const uint8_t *)xex_addr + header->exe_offset;
|
||||||
|
|
||||||
|
@ -726,7 +727,7 @@ int xe_xex2_read_image_compressed(const xe_xex2_header_t *header,
|
||||||
|
|
||||||
// Allocate in-place the XEX memory.
|
// Allocate in-place the XEX memory.
|
||||||
uint32_t alloc_result = (uint32_t)memory->HeapAlloc(
|
uint32_t alloc_result = (uint32_t)memory->HeapAlloc(
|
||||||
header->exe_address, uncompressed_size, MEMORY_FLAG_ZERO);
|
header->exe_address, uncompressed_size, xe::MEMORY_FLAG_ZERO);
|
||||||
if (!alloc_result) {
|
if (!alloc_result) {
|
||||||
XELOGE("Unable to allocate XEX memory at %.8X-%.8X.", header->exe_address,
|
XELOGE("Unable to allocate XEX memory at %.8X-%.8X.", header->exe_address,
|
||||||
uncompressed_size);
|
uncompressed_size);
|
||||||
|
@ -778,7 +779,7 @@ XECLEANUP:
|
||||||
}
|
}
|
||||||
|
|
||||||
int xe_xex2_read_image(xe_xex2_ref xex, const uint8_t *xex_addr,
|
int xe_xex2_read_image(xe_xex2_ref xex, const uint8_t *xex_addr,
|
||||||
const size_t xex_length, Memory *memory) {
|
const size_t xex_length, xe::Memory *memory) {
|
||||||
const xe_xex2_header_t *header = &xex->header;
|
const xe_xex2_header_t *header = &xex->header;
|
||||||
switch (header->file_format_info.compression_type) {
|
switch (header->file_format_info.compression_type) {
|
||||||
case XEX_COMPRESSION_NONE:
|
case XEX_COMPRESSION_NONE:
|
||||||
|
|
|
@ -158,7 +158,7 @@ SHIM_CALL NtQueryVirtualMemory_shim(PPCContext* ppc_state, KernelState* state) {
|
||||||
XELOGD("NtQueryVirtualMemory(%.8X, %.8X)", base_address,
|
XELOGD("NtQueryVirtualMemory(%.8X, %.8X)", base_address,
|
||||||
memory_basic_information_ptr);
|
memory_basic_information_ptr);
|
||||||
|
|
||||||
alloy::AllocationInfo mem_info;
|
AllocationInfo mem_info;
|
||||||
size_t result = state->memory()->QueryInformation(base_address, &mem_info);
|
size_t result = state->memory()->QueryInformation(base_address, &mem_info);
|
||||||
if (!result) {
|
if (!result) {
|
||||||
SHIM_SET_RETURN_32(X_STATUS_INVALID_PARAMETER);
|
SHIM_SET_RETURN_32(X_STATUS_INVALID_PARAMETER);
|
||||||
|
@ -250,7 +250,7 @@ SHIM_CALL MmAllocatePhysicalMemoryEx_shim(PPCContext* ppc_state,
|
||||||
assert_true(max_addr_range == 0xFFFFFFFF);
|
assert_true(max_addr_range == 0xFFFFFFFF);
|
||||||
|
|
||||||
// Allocate.
|
// Allocate.
|
||||||
uint32_t flags = alloy::MEMORY_FLAG_PHYSICAL;
|
uint32_t flags = MEMORY_FLAG_PHYSICAL;
|
||||||
uint32_t base_address = (uint32_t)state->memory()->HeapAlloc(
|
uint32_t base_address = (uint32_t)state->memory()->HeapAlloc(
|
||||||
0, adjusted_size, flags, adjusted_alignment);
|
0, adjusted_size, flags, adjusted_alignment);
|
||||||
if (!base_address) {
|
if (!base_address) {
|
||||||
|
@ -410,7 +410,7 @@ SHIM_CALL ExAllocatePoolTypeWithTag_shim(PPCContext* ppc_state,
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t addr = (uint32_t)state->memory()->HeapAlloc(
|
uint32_t addr = (uint32_t)state->memory()->HeapAlloc(
|
||||||
0, adjusted_size, alloy::MEMORY_FLAG_ZERO, alignment);
|
0, adjusted_size, MEMORY_FLAG_ZERO, alignment);
|
||||||
|
|
||||||
SHIM_SET_RETURN_32(addr);
|
SHIM_SET_RETURN_32(addr);
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,16 +7,16 @@
|
||||||
******************************************************************************
|
******************************************************************************
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <xenia/cpu/xenon_memory.h>
|
#include <xenia/memory.h>
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
|
|
||||||
#include <gflags/gflags.h>
|
#include <gflags/gflags.h>
|
||||||
#include <poly/math.h>
|
#include <poly/math.h>
|
||||||
|
#include <xenia/cpu/mmio_handler.h>
|
||||||
|
|
||||||
using namespace alloy;
|
using namespace xe;
|
||||||
using namespace xe::cpu;
|
|
||||||
|
|
||||||
// TODO(benvanik): move xbox.h out
|
// TODO(benvanik): move xbox.h out
|
||||||
#include <xenia/xbox.h>
|
#include <xenia/xbox.h>
|
||||||
|
@ -84,10 +84,10 @@ DEFINE_bool(scribble_heap, false,
|
||||||
#define XENON_MEMORY_VIRTUAL_HEAP_LOW 0x20000000
|
#define XENON_MEMORY_VIRTUAL_HEAP_LOW 0x20000000
|
||||||
#define XENON_MEMORY_VIRTUAL_HEAP_HIGH 0x40000000
|
#define XENON_MEMORY_VIRTUAL_HEAP_HIGH 0x40000000
|
||||||
|
|
||||||
class xe::cpu::XenonMemoryHeap {
|
class xe::MemoryHeap {
|
||||||
public:
|
public:
|
||||||
XenonMemoryHeap(XenonMemory* memory, bool is_physical);
|
MemoryHeap(Memory* memory, bool is_physical);
|
||||||
~XenonMemoryHeap();
|
~MemoryHeap();
|
||||||
|
|
||||||
int Initialize(uint64_t low, uint64_t high);
|
int Initialize(uint64_t low, uint64_t high);
|
||||||
|
|
||||||
|
@ -104,7 +104,7 @@ class xe::cpu::XenonMemoryHeap {
|
||||||
void* context);
|
void* context);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
XenonMemory* memory_;
|
Memory* memory_;
|
||||||
uint32_t heap_id_;
|
uint32_t heap_id_;
|
||||||
bool is_physical_;
|
bool is_physical_;
|
||||||
std::mutex lock_;
|
std::mutex lock_;
|
||||||
|
@ -112,15 +112,15 @@ class xe::cpu::XenonMemoryHeap {
|
||||||
uint8_t* ptr_;
|
uint8_t* ptr_;
|
||||||
mspace space_;
|
mspace space_;
|
||||||
};
|
};
|
||||||
uint32_t XenonMemoryHeap::next_heap_id_ = 1;
|
uint32_t MemoryHeap::next_heap_id_ = 1;
|
||||||
|
|
||||||
XenonMemory::XenonMemory()
|
Memory::Memory()
|
||||||
: Memory(), mapping_(0), mapping_base_(0), page_table_(0) {
|
: alloy::Memory(), mapping_(0), mapping_base_(0), page_table_(0) {
|
||||||
virtual_heap_ = new XenonMemoryHeap(this, false);
|
virtual_heap_ = new MemoryHeap(this, false);
|
||||||
physical_heap_ = new XenonMemoryHeap(this, true);
|
physical_heap_ = new MemoryHeap(this, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
XenonMemory::~XenonMemory() {
|
Memory::~Memory() {
|
||||||
// Uninstall the MMIO handler, as we won't be able to service more
|
// Uninstall the MMIO handler, as we won't be able to service more
|
||||||
// requests.
|
// requests.
|
||||||
mmio_handler_.reset();
|
mmio_handler_.reset();
|
||||||
|
@ -142,8 +142,8 @@ XenonMemory::~XenonMemory() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int XenonMemory::Initialize() {
|
int Memory::Initialize() {
|
||||||
int result = Memory::Initialize();
|
int result = alloy::Memory::Initialize();
|
||||||
if (result) {
|
if (result) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -196,7 +196,7 @@ int XenonMemory::Initialize() {
|
||||||
VirtualAlloc(Translate(0xC0000000), 0x00100000, MEM_COMMIT, PAGE_READWRITE);
|
VirtualAlloc(Translate(0xC0000000), 0x00100000, MEM_COMMIT, PAGE_READWRITE);
|
||||||
|
|
||||||
// Add handlers for MMIO.
|
// Add handlers for MMIO.
|
||||||
mmio_handler_ = MMIOHandler::Install(mapping_base_);
|
mmio_handler_ = cpu::MMIOHandler::Install(mapping_base_);
|
||||||
if (!mmio_handler_) {
|
if (!mmio_handler_) {
|
||||||
XELOGE("Unable to install MMIO handlers");
|
XELOGE("Unable to install MMIO handlers");
|
||||||
assert_always();
|
assert_always();
|
||||||
|
@ -227,7 +227,7 @@ const static struct {
|
||||||
0xC0000000, 0xDFFFFFFF, 0x00000000, // - physical 16mb pages
|
0xC0000000, 0xDFFFFFFF, 0x00000000, // - physical 16mb pages
|
||||||
0xE0000000, 0xFFFFFFFF, 0x00000000, // - physical 4k pages
|
0xE0000000, 0xFFFFFFFF, 0x00000000, // - physical 4k pages
|
||||||
};
|
};
|
||||||
int XenonMemory::MapViews(uint8_t* mapping_base) {
|
int Memory::MapViews(uint8_t* mapping_base) {
|
||||||
assert_true(poly::countof(map_info) == poly::countof(views_.all_views));
|
assert_true(poly::countof(map_info) == poly::countof(views_.all_views));
|
||||||
for (size_t n = 0; n < poly::countof(map_info); n++) {
|
for (size_t n = 0; n < poly::countof(map_info); n++) {
|
||||||
#if XE_PLATFORM_WIN32
|
#if XE_PLATFORM_WIN32
|
||||||
|
@ -252,7 +252,7 @@ XECLEANUP:
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void XenonMemory::UnmapViews() {
|
void Memory::UnmapViews() {
|
||||||
for (size_t n = 0; n < poly::countof(views_.all_views); n++) {
|
for (size_t n = 0; n < poly::countof(views_.all_views); n++) {
|
||||||
if (views_.all_views[n]) {
|
if (views_.all_views[n]) {
|
||||||
#if XE_PLATFORM_WIN32
|
#if XE_PLATFORM_WIN32
|
||||||
|
@ -266,9 +266,9 @@ void XenonMemory::UnmapViews() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool XenonMemory::AddMappedRange(uint64_t address, uint64_t mask, uint64_t size,
|
bool Memory::AddMappedRange(uint64_t address, uint64_t mask, uint64_t size,
|
||||||
void* context, MMIOReadCallback read_callback,
|
void* context, cpu::MMIOReadCallback read_callback,
|
||||||
MMIOWriteCallback write_callback) {
|
cpu::MMIOWriteCallback write_callback) {
|
||||||
DWORD protect = PAGE_NOACCESS;
|
DWORD protect = PAGE_NOACCESS;
|
||||||
if (!VirtualAlloc(Translate(address), size, MEM_COMMIT, protect)) {
|
if (!VirtualAlloc(Translate(address), size, MEM_COMMIT, protect)) {
|
||||||
XELOGE("Unable to map range; commit/protect failed");
|
XELOGE("Unable to map range; commit/protect failed");
|
||||||
|
@ -278,7 +278,7 @@ bool XenonMemory::AddMappedRange(uint64_t address, uint64_t mask, uint64_t size,
|
||||||
read_callback, write_callback);
|
read_callback, write_callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t XenonMemory::LoadI8(uint64_t address) {
|
uint8_t Memory::LoadI8(uint64_t address) {
|
||||||
uint64_t value;
|
uint64_t value;
|
||||||
if (!mmio_handler_->CheckLoad(address, &value)) {
|
if (!mmio_handler_->CheckLoad(address, &value)) {
|
||||||
value = *reinterpret_cast<uint8_t*>(Translate(address));
|
value = *reinterpret_cast<uint8_t*>(Translate(address));
|
||||||
|
@ -286,7 +286,7 @@ uint8_t XenonMemory::LoadI8(uint64_t address) {
|
||||||
return static_cast<uint8_t>(value);
|
return static_cast<uint8_t>(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t XenonMemory::LoadI16(uint64_t address) {
|
uint16_t Memory::LoadI16(uint64_t address) {
|
||||||
uint64_t value;
|
uint64_t value;
|
||||||
if (!mmio_handler_->CheckLoad(address, &value)) {
|
if (!mmio_handler_->CheckLoad(address, &value)) {
|
||||||
value = *reinterpret_cast<uint16_t*>(Translate(address));
|
value = *reinterpret_cast<uint16_t*>(Translate(address));
|
||||||
|
@ -294,7 +294,7 @@ uint16_t XenonMemory::LoadI16(uint64_t address) {
|
||||||
return static_cast<uint16_t>(value);
|
return static_cast<uint16_t>(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t XenonMemory::LoadI32(uint64_t address) {
|
uint32_t Memory::LoadI32(uint64_t address) {
|
||||||
uint64_t value;
|
uint64_t value;
|
||||||
if (!mmio_handler_->CheckLoad(address, &value)) {
|
if (!mmio_handler_->CheckLoad(address, &value)) {
|
||||||
value = *reinterpret_cast<uint32_t*>(Translate(address));
|
value = *reinterpret_cast<uint32_t*>(Translate(address));
|
||||||
|
@ -302,7 +302,7 @@ uint32_t XenonMemory::LoadI32(uint64_t address) {
|
||||||
return static_cast<uint32_t>(value);
|
return static_cast<uint32_t>(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t XenonMemory::LoadI64(uint64_t address) {
|
uint64_t Memory::LoadI64(uint64_t address) {
|
||||||
uint64_t value;
|
uint64_t value;
|
||||||
if (!mmio_handler_->CheckLoad(address, &value)) {
|
if (!mmio_handler_->CheckLoad(address, &value)) {
|
||||||
value = *reinterpret_cast<uint64_t*>(Translate(address));
|
value = *reinterpret_cast<uint64_t*>(Translate(address));
|
||||||
|
@ -310,32 +310,32 @@ uint64_t XenonMemory::LoadI64(uint64_t address) {
|
||||||
return static_cast<uint64_t>(value);
|
return static_cast<uint64_t>(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
void XenonMemory::StoreI8(uint64_t address, uint8_t value) {
|
void Memory::StoreI8(uint64_t address, uint8_t value) {
|
||||||
if (!mmio_handler_->CheckStore(address, value)) {
|
if (!mmio_handler_->CheckStore(address, value)) {
|
||||||
*reinterpret_cast<uint8_t*>(Translate(address)) = value;
|
*reinterpret_cast<uint8_t*>(Translate(address)) = value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void XenonMemory::StoreI16(uint64_t address, uint16_t value) {
|
void Memory::StoreI16(uint64_t address, uint16_t value) {
|
||||||
if (!mmio_handler_->CheckStore(address, value)) {
|
if (!mmio_handler_->CheckStore(address, value)) {
|
||||||
*reinterpret_cast<uint16_t*>(Translate(address)) = value;
|
*reinterpret_cast<uint16_t*>(Translate(address)) = value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void XenonMemory::StoreI32(uint64_t address, uint32_t value) {
|
void Memory::StoreI32(uint64_t address, uint32_t value) {
|
||||||
if (!mmio_handler_->CheckStore(address, value)) {
|
if (!mmio_handler_->CheckStore(address, value)) {
|
||||||
*reinterpret_cast<uint32_t*>(Translate(address)) = value;
|
*reinterpret_cast<uint32_t*>(Translate(address)) = value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void XenonMemory::StoreI64(uint64_t address, uint64_t value) {
|
void Memory::StoreI64(uint64_t address, uint64_t value) {
|
||||||
if (!mmio_handler_->CheckStore(address, value)) {
|
if (!mmio_handler_->CheckStore(address, value)) {
|
||||||
*reinterpret_cast<uint64_t*>(Translate(address)) = value;
|
*reinterpret_cast<uint64_t*>(Translate(address)) = value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t XenonMemory::HeapAlloc(uint64_t base_address, size_t size,
|
uint64_t Memory::HeapAlloc(uint64_t base_address, size_t size, uint32_t flags,
|
||||||
uint32_t flags, uint32_t alignment) {
|
uint32_t alignment) {
|
||||||
// If we were given a base address we are outside of the normal heap and
|
// If we were given a base address we are outside of the normal heap and
|
||||||
// will place wherever asked (so long as it doesn't overlap the heap).
|
// will place wherever asked (so long as it doesn't overlap the heap).
|
||||||
if (!base_address) {
|
if (!base_address) {
|
||||||
|
@ -384,7 +384,7 @@ uint64_t XenonMemory::HeapAlloc(uint64_t base_address, size_t size,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int XenonMemory::HeapFree(uint64_t address, size_t size) {
|
int Memory::HeapFree(uint64_t address, size_t size) {
|
||||||
if (address >= XENON_MEMORY_VIRTUAL_HEAP_LOW &&
|
if (address >= XENON_MEMORY_VIRTUAL_HEAP_LOW &&
|
||||||
address < XENON_MEMORY_VIRTUAL_HEAP_HIGH) {
|
address < XENON_MEMORY_VIRTUAL_HEAP_HIGH) {
|
||||||
return virtual_heap_->Free(address, size) ? 0 : 1;
|
return virtual_heap_->Free(address, size) ? 0 : 1;
|
||||||
|
@ -398,8 +398,7 @@ int XenonMemory::HeapFree(uint64_t address, size_t size) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool XenonMemory::QueryInformation(uint64_t base_address,
|
bool Memory::QueryInformation(uint64_t base_address, AllocationInfo* mem_info) {
|
||||||
AllocationInfo* mem_info) {
|
|
||||||
uint8_t* p = Translate(base_address);
|
uint8_t* p = Translate(base_address);
|
||||||
MEMORY_BASIC_INFORMATION mbi;
|
MEMORY_BASIC_INFORMATION mbi;
|
||||||
if (!VirtualQuery(p, &mbi, sizeof(mbi))) {
|
if (!VirtualQuery(p, &mbi, sizeof(mbi))) {
|
||||||
|
@ -416,7 +415,7 @@ bool XenonMemory::QueryInformation(uint64_t base_address,
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t XenonMemory::QuerySize(uint64_t base_address) {
|
size_t Memory::QuerySize(uint64_t base_address) {
|
||||||
if (base_address >= XENON_MEMORY_VIRTUAL_HEAP_LOW &&
|
if (base_address >= XENON_MEMORY_VIRTUAL_HEAP_LOW &&
|
||||||
base_address < XENON_MEMORY_VIRTUAL_HEAP_HIGH) {
|
base_address < XENON_MEMORY_VIRTUAL_HEAP_HIGH) {
|
||||||
return virtual_heap_->QuerySize(base_address);
|
return virtual_heap_->QuerySize(base_address);
|
||||||
|
@ -436,7 +435,7 @@ size_t XenonMemory::QuerySize(uint64_t base_address) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int XenonMemory::Protect(uint64_t address, size_t size, uint32_t access) {
|
int Memory::Protect(uint64_t address, size_t size, uint32_t access) {
|
||||||
uint8_t* p = Translate(address);
|
uint8_t* p = Translate(address);
|
||||||
|
|
||||||
size_t heap_guard_size = FLAGS_heap_guard_pages * 4096;
|
size_t heap_guard_size = FLAGS_heap_guard_pages * 4096;
|
||||||
|
@ -452,7 +451,7 @@ int XenonMemory::Protect(uint64_t address, size_t size, uint32_t access) {
|
||||||
return VirtualProtect(p, size, new_protect, &old_protect) == TRUE ? 0 : 1;
|
return VirtualProtect(p, size, new_protect, &old_protect) == TRUE ? 0 : 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t XenonMemory::QueryProtect(uint64_t address) {
|
uint32_t Memory::QueryProtect(uint64_t address) {
|
||||||
uint8_t* p = Translate(address);
|
uint8_t* p = Translate(address);
|
||||||
MEMORY_BASIC_INFORMATION info;
|
MEMORY_BASIC_INFORMATION info;
|
||||||
size_t info_size = VirtualQuery((void*)p, &info, sizeof(info));
|
size_t info_size = VirtualQuery((void*)p, &info, sizeof(info));
|
||||||
|
@ -462,12 +461,12 @@ uint32_t XenonMemory::QueryProtect(uint64_t address) {
|
||||||
return info.Protect;
|
return info.Protect;
|
||||||
}
|
}
|
||||||
|
|
||||||
XenonMemoryHeap::XenonMemoryHeap(XenonMemory* memory, bool is_physical)
|
MemoryHeap::MemoryHeap(Memory* memory, bool is_physical)
|
||||||
: memory_(memory), is_physical_(is_physical) {
|
: memory_(memory), is_physical_(is_physical) {
|
||||||
heap_id_ = next_heap_id_++;
|
heap_id_ = next_heap_id_++;
|
||||||
}
|
}
|
||||||
|
|
||||||
XenonMemoryHeap::~XenonMemoryHeap() {
|
MemoryHeap::~MemoryHeap() {
|
||||||
if (space_) {
|
if (space_) {
|
||||||
std::lock_guard<std::mutex> guard(lock_);
|
std::lock_guard<std::mutex> guard(lock_);
|
||||||
destroy_mspace(space_);
|
destroy_mspace(space_);
|
||||||
|
@ -479,7 +478,7 @@ XenonMemoryHeap::~XenonMemoryHeap() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int XenonMemoryHeap::Initialize(uint64_t low, uint64_t high) {
|
int MemoryHeap::Initialize(uint64_t low, uint64_t high) {
|
||||||
// Commit the memory where our heap will live and allocate it.
|
// Commit the memory where our heap will live and allocate it.
|
||||||
// TODO(benvanik): replace dlmalloc with an implementation that can commit
|
// TODO(benvanik): replace dlmalloc with an implementation that can commit
|
||||||
// as it goes.
|
// as it goes.
|
||||||
|
@ -494,8 +493,8 @@ int XenonMemoryHeap::Initialize(uint64_t low, uint64_t high) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t XenonMemoryHeap::Alloc(uint64_t base_address, size_t size,
|
uint64_t MemoryHeap::Alloc(uint64_t base_address, size_t size, uint32_t flags,
|
||||||
uint32_t flags, uint32_t alignment) {
|
uint32_t alignment) {
|
||||||
lock_.lock();
|
lock_.lock();
|
||||||
size_t alloc_size = size;
|
size_t alloc_size = size;
|
||||||
size_t heap_guard_size = FLAGS_heap_guard_pages * 4096;
|
size_t heap_guard_size = FLAGS_heap_guard_pages * 4096;
|
||||||
|
@ -547,7 +546,7 @@ uint64_t XenonMemoryHeap::Alloc(uint64_t base_address, size_t size,
|
||||||
return address;
|
return address;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t XenonMemoryHeap::Free(uint64_t address, size_t size) {
|
uint64_t MemoryHeap::Free(uint64_t address, size_t size) {
|
||||||
uint8_t* p = memory_->Translate(address);
|
uint8_t* p = memory_->Translate(address);
|
||||||
|
|
||||||
// Heap allocated address.
|
// Heap allocated address.
|
||||||
|
@ -590,7 +589,7 @@ uint64_t XenonMemoryHeap::Free(uint64_t address, size_t size) {
|
||||||
return (uint64_t)real_size;
|
return (uint64_t)real_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t XenonMemoryHeap::QuerySize(uint64_t base_address) {
|
size_t MemoryHeap::QuerySize(uint64_t base_address) {
|
||||||
uint8_t* p = memory_->Translate(base_address);
|
uint8_t* p = memory_->Translate(base_address);
|
||||||
|
|
||||||
// Heap allocated address.
|
// Heap allocated address.
|
||||||
|
@ -605,8 +604,8 @@ size_t XenonMemoryHeap::QuerySize(uint64_t base_address) {
|
||||||
return real_size;
|
return real_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
void XenonMemoryHeap::Dump() {
|
void MemoryHeap::Dump() {
|
||||||
XELOGI("XenonMemoryHeap::Dump - %s", is_physical_ ? "physical" : "virtual");
|
XELOGI("MemoryHeap::Dump - %s", is_physical_ ? "physical" : "virtual");
|
||||||
if (FLAGS_heap_guard_pages) {
|
if (FLAGS_heap_guard_pages) {
|
||||||
XELOGI(" (heap guard pages enabled, stats will be wrong)");
|
XELOGI(" (heap guard pages enabled, stats will be wrong)");
|
||||||
}
|
}
|
||||||
|
@ -622,10 +621,10 @@ void XenonMemoryHeap::Dump() {
|
||||||
mspace_inspect_all(space_, DumpHandler, this);
|
mspace_inspect_all(space_, DumpHandler, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void XenonMemoryHeap::DumpHandler(void* start, void* end, size_t used_bytes,
|
void MemoryHeap::DumpHandler(void* start, void* end, size_t used_bytes,
|
||||||
void* context) {
|
void* context) {
|
||||||
XenonMemoryHeap* heap = (XenonMemoryHeap*)context;
|
MemoryHeap* heap = (MemoryHeap*)context;
|
||||||
XenonMemory* memory = heap->memory_;
|
Memory* memory = heap->memory_;
|
||||||
size_t heap_guard_size = FLAGS_heap_guard_pages * 4096;
|
size_t heap_guard_size = FLAGS_heap_guard_pages * 4096;
|
||||||
uint64_t start_addr = (uint64_t)start + heap_guard_size;
|
uint64_t start_addr = (uint64_t)start + heap_guard_size;
|
||||||
uint64_t end_addr = (uint64_t)end - heap_guard_size;
|
uint64_t end_addr = (uint64_t)end - heap_guard_size;
|
|
@ -7,8 +7,8 @@
|
||||||
******************************************************************************
|
******************************************************************************
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef XENIA_CPU_XENON_MEMORY_H_
|
#ifndef XENIA_MEMORY_H_
|
||||||
#define XENIA_CPU_XENON_MEMORY_H_
|
#define XENIA_MEMORY_H_
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
|
@ -20,22 +20,41 @@
|
||||||
typedef struct xe_ppc_state xe_ppc_state_t;
|
typedef struct xe_ppc_state xe_ppc_state_t;
|
||||||
|
|
||||||
namespace xe {
|
namespace xe {
|
||||||
namespace cpu {
|
|
||||||
|
|
||||||
class XenonMemoryHeap;
|
class MemoryHeap;
|
||||||
|
|
||||||
class XenonMemory : public alloy::Memory {
|
// TODO(benvanik): move to heap.
|
||||||
|
enum {
|
||||||
|
MEMORY_FLAG_64KB_PAGES = (1 << 1),
|
||||||
|
MEMORY_FLAG_ZERO = (1 << 2),
|
||||||
|
MEMORY_FLAG_PHYSICAL = (1 << 3),
|
||||||
|
};
|
||||||
|
|
||||||
|
// TODO(benvanik): move to heap.
|
||||||
|
// Equivalent to the Win32 MEMORY_BASIC_INFORMATION struct.
|
||||||
|
struct AllocationInfo {
|
||||||
|
uint64_t base_address;
|
||||||
|
uint64_t allocation_base;
|
||||||
|
uint32_t allocation_protect; // TBD
|
||||||
|
size_t region_size;
|
||||||
|
uint32_t state; // TBD
|
||||||
|
uint32_t protect; // TBD
|
||||||
|
uint32_t type; // TBD
|
||||||
|
};
|
||||||
|
|
||||||
|
class Memory : public alloy::Memory {
|
||||||
public:
|
public:
|
||||||
XenonMemory();
|
Memory();
|
||||||
virtual ~XenonMemory();
|
~Memory() override;
|
||||||
|
|
||||||
int Initialize() override;
|
int Initialize() override;
|
||||||
|
|
||||||
|
// TODO(benvanik): remove with GPU refactor.
|
||||||
uint64_t page_table() const override { return page_table_; }
|
uint64_t page_table() const override { return page_table_; }
|
||||||
|
|
||||||
bool AddMappedRange(uint64_t address, uint64_t mask, uint64_t size,
|
bool AddMappedRange(uint64_t address, uint64_t mask, uint64_t size,
|
||||||
void* context, MMIOReadCallback read_callback,
|
void* context, cpu::MMIOReadCallback read_callback,
|
||||||
MMIOWriteCallback write_callback);
|
cpu::MMIOWriteCallback write_callback);
|
||||||
|
|
||||||
uint8_t LoadI8(uint64_t address) override;
|
uint8_t LoadI8(uint64_t address) override;
|
||||||
uint16_t LoadI16(uint64_t address) override;
|
uint16_t LoadI16(uint64_t address) override;
|
||||||
|
@ -47,15 +66,14 @@ class XenonMemory : public alloy::Memory {
|
||||||
void StoreI64(uint64_t address, uint64_t value) override;
|
void StoreI64(uint64_t address, uint64_t value) override;
|
||||||
|
|
||||||
uint64_t HeapAlloc(uint64_t base_address, size_t size, uint32_t flags,
|
uint64_t HeapAlloc(uint64_t base_address, size_t size, uint32_t flags,
|
||||||
uint32_t alignment = 0x20) override;
|
uint32_t alignment = 0x20);
|
||||||
int HeapFree(uint64_t address, size_t size) override;
|
int HeapFree(uint64_t address, size_t size);
|
||||||
|
|
||||||
bool QueryInformation(uint64_t base_address,
|
bool QueryInformation(uint64_t base_address, AllocationInfo* mem_info);
|
||||||
alloy::AllocationInfo* mem_info) override;
|
size_t QuerySize(uint64_t base_address);
|
||||||
size_t QuerySize(uint64_t base_address) override;
|
|
||||||
|
|
||||||
int Protect(uint64_t address, size_t size, uint32_t access) override;
|
int Protect(uint64_t address, size_t size, uint32_t access);
|
||||||
uint32_t QueryProtect(uint64_t address) override;
|
uint32_t QueryProtect(uint64_t address);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int MapViews(uint8_t* mapping_base);
|
int MapViews(uint8_t* mapping_base);
|
||||||
|
@ -76,17 +94,16 @@ class XenonMemory : public alloy::Memory {
|
||||||
uint8_t* all_views[6];
|
uint8_t* all_views[6];
|
||||||
} views_;
|
} views_;
|
||||||
|
|
||||||
std::unique_ptr<MMIOHandler> mmio_handler_;
|
std::unique_ptr<cpu::MMIOHandler> mmio_handler_;
|
||||||
|
|
||||||
XenonMemoryHeap* virtual_heap_;
|
MemoryHeap* virtual_heap_;
|
||||||
XenonMemoryHeap* physical_heap_;
|
MemoryHeap* physical_heap_;
|
||||||
|
|
||||||
uint64_t page_table_;
|
uint64_t page_table_;
|
||||||
|
|
||||||
friend class XenonMemoryHeap;
|
friend class MemoryHeap;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace cpu
|
|
||||||
} // namespace xe
|
} // namespace xe
|
||||||
|
|
||||||
#endif // XENIA_CPU_XENON_MEMORY_H_
|
#endif // XENIA_MEMORY_H_
|
|
@ -13,6 +13,8 @@
|
||||||
'logging.h',
|
'logging.h',
|
||||||
'malloc.cc',
|
'malloc.cc',
|
||||||
'malloc.h',
|
'malloc.h',
|
||||||
|
'memory.cc',
|
||||||
|
'memory.h',
|
||||||
'profiling.cc',
|
'profiling.cc',
|
||||||
'profiling.h',
|
'profiling.h',
|
||||||
'types.h',
|
'types.h',
|
||||||
|
|
|
@ -15,7 +15,6 @@
|
||||||
#include <alloy/runtime/raw_module.h>
|
#include <alloy/runtime/raw_module.h>
|
||||||
#include <poly/main.h>
|
#include <poly/main.h>
|
||||||
#include <poly/poly.h>
|
#include <poly/poly.h>
|
||||||
#include <xenia/cpu/xenon_memory.h>
|
|
||||||
|
|
||||||
#include <gflags/gflags.h>
|
#include <gflags/gflags.h>
|
||||||
|
|
||||||
|
@ -28,11 +27,12 @@ using alloy::runtime::Runtime;
|
||||||
class ThreadState : public alloy::runtime::ThreadState {
|
class ThreadState : public alloy::runtime::ThreadState {
|
||||||
public:
|
public:
|
||||||
ThreadState(Runtime* runtime, uint32_t thread_id, size_t stack_size,
|
ThreadState(Runtime* runtime, uint32_t thread_id, size_t stack_size,
|
||||||
uint64_t thread_state_address)
|
uint64_t thread_state_address, uint64_t thread_stack_address)
|
||||||
: alloy::runtime::ThreadState(runtime, thread_id),
|
: alloy::runtime::ThreadState(runtime, thread_id),
|
||||||
|
stack_address_(thread_stack_address),
|
||||||
stack_size_(stack_size),
|
stack_size_(stack_size),
|
||||||
thread_state_address_(thread_state_address) {
|
thread_state_address_(thread_state_address) {
|
||||||
stack_address_ = memory_->HeapAlloc(0, stack_size, MEMORY_FLAG_ZERO);
|
memset(memory_->Translate(stack_address_), 0, stack_size_);
|
||||||
|
|
||||||
// Allocate with 64b alignment.
|
// Allocate with 64b alignment.
|
||||||
context_ = (PPCContext*)xe_malloc_aligned(sizeof(PPCContext));
|
context_ = (PPCContext*)xe_malloc_aligned(sizeof(PPCContext));
|
||||||
|
@ -60,7 +60,6 @@ class ThreadState : public alloy::runtime::ThreadState {
|
||||||
~ThreadState() override {
|
~ThreadState() override {
|
||||||
runtime_->debugger()->OnThreadDestroyed(this);
|
runtime_->debugger()->OnThreadDestroyed(this);
|
||||||
xe_free_aligned(context_);
|
xe_free_aligned(context_);
|
||||||
memory_->HeapFree(stack_address_, stack_size_);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
PPCContext* context() const { return context_; }
|
PPCContext* context() const { return context_; }
|
||||||
|
@ -80,7 +79,8 @@ int main(std::vector<std::wstring>& args) {
|
||||||
xe::Profiler::Initialize();
|
xe::Profiler::Initialize();
|
||||||
xe::Profiler::ThreadEnter("main");
|
xe::Profiler::ThreadEnter("main");
|
||||||
|
|
||||||
auto memory = std::make_unique<xe::cpu::XenonMemory>();
|
size_t memory_size = 16 * 1024 * 1024;
|
||||||
|
auto memory = std::make_unique<SimpleMemory>(memory_size);
|
||||||
auto runtime = std::make_unique<Runtime>(memory.get());
|
auto runtime = std::make_unique<Runtime>(memory.get());
|
||||||
|
|
||||||
auto frontend =
|
auto frontend =
|
||||||
|
@ -97,11 +97,14 @@ int main(std::vector<std::wstring>& args) {
|
||||||
runtime->AddModule(std::move(module));
|
runtime->AddModule(std::move(module));
|
||||||
|
|
||||||
{
|
{
|
||||||
auto thread_state =
|
uint64_t thread_state_address = 0;
|
||||||
std::make_unique<ThreadState>(runtime.get(), 100, 64 * 1024, 0);
|
uint64_t stack_address = memory_size - 1024;
|
||||||
|
uint64_t stack_size = 64 * 1024;
|
||||||
|
auto thread_state = std::make_unique<ThreadState>(
|
||||||
|
runtime.get(), 100, stack_address, stack_size, thread_state_address);
|
||||||
|
|
||||||
alloy::runtime::Function* fn;
|
alloy::runtime::Function* fn;
|
||||||
runtime->ResolveFunction(0x82000000, &fn);
|
runtime->ResolveFunction(0x1000, &fn);
|
||||||
auto ctx = thread_state->context();
|
auto ctx = thread_state->context();
|
||||||
ctx->lr = 0xBEBEBEBE;
|
ctx->lr = 0xBEBEBEBE;
|
||||||
ctx->r[5] = 10;
|
ctx->r[5] = 10;
|
||||||
|
|
Loading…
Reference in New Issue