mirror of
https://github.com/xenia-project/xenia.git
synced 2024-11-30 15:00:25 +00:00
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) {
|
||||
// 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 address = ics.rf[i->src1_reg].u32;
|
||||
|
@ -1557,9 +1557,12 @@ EMITTER_OPCODE_TABLE(
|
||||
// Note: most *should* be aligned, but needs to be checked!
|
||||
void EmitMarkPageDirty(X64Emitter& e, RegExp& addr) {
|
||||
// 16KB pages.
|
||||
e.shr(e.eax, 14);
|
||||
e.and(e.eax, 0x7FFF);
|
||||
e.mov(e.byte[e.rdx + e.rax + e.page_table_address()], 1);
|
||||
auto page_table_address = e.page_table_address();
|
||||
if (page_table_address) {
|
||||
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<>>)) {
|
||||
static void Emit(X64Emitter& e, const EmitArgType& i) {
|
||||
|
@ -172,7 +172,7 @@ typedef struct alignas(64) PPCContext_s {
|
||||
uint32_t thread_id;
|
||||
|
||||
// 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
|
||||
// current runtime and its data.
|
||||
|
@ -61,4 +61,43 @@ uint64_t Memory::SearchAligned(uint64_t start, uint64_t end,
|
||||
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
|
||||
|
@ -14,23 +14,6 @@
|
||||
|
||||
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 {
|
||||
public:
|
||||
Memory();
|
||||
@ -40,8 +23,9 @@ class Memory {
|
||||
inline uint8_t* Translate(uint64_t guest_address) const {
|
||||
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;
|
||||
|
||||
uint64_t trace_base() const { return trace_base_; }
|
||||
@ -49,6 +33,7 @@ class Memory {
|
||||
|
||||
virtual int Initialize();
|
||||
|
||||
// TODO(benvanik): make poly memory utils for these.
|
||||
void Zero(uint64_t address, size_t size);
|
||||
void Fill(uint64_t address, size_t size, uint8_t value);
|
||||
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,
|
||||
size_t value_count);
|
||||
|
||||
// TODO(benvanik): remove with IVM.
|
||||
virtual uint8_t LoadI8(uint64_t address) = 0;
|
||||
virtual uint16_t LoadI16(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 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:
|
||||
size_t system_page_size_;
|
||||
uint8_t* membase_;
|
||||
uint32_t reserve_address_;
|
||||
uint64_t reserve_address_;
|
||||
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
|
||||
|
||||
#endif // ALLOY_MEMORY_H_
|
||||
|
@ -15,11 +15,7 @@ namespace runtime {
|
||||
RawModule::RawModule(Runtime* runtime)
|
||||
: Module(runtime), base_address_(0), low_address_(0), high_address_(0) {}
|
||||
|
||||
RawModule::~RawModule() {
|
||||
if (base_address_) {
|
||||
memory_->HeapFree(base_address_, high_address_ - low_address_);
|
||||
}
|
||||
}
|
||||
RawModule::~RawModule() {}
|
||||
|
||||
int RawModule::LoadFile(uint64_t base_address, const std::string& path) {
|
||||
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);
|
||||
|
||||
// Allocate memory.
|
||||
base_address_ =
|
||||
memory_->HeapAlloc(base_address, file_length, MEMORY_FLAG_ZERO);
|
||||
if (!base_address_) {
|
||||
fclose(file);
|
||||
return 1;
|
||||
}
|
||||
// Since we have no real heap just load it wherever.
|
||||
base_address_ = base_address;
|
||||
uint8_t* p = memory_->Translate(base_address_);
|
||||
memset(p, 0, file_length);
|
||||
|
||||
// Read into memory.
|
||||
uint8_t* p = memory_->Translate(base_address_);
|
||||
fread(p, file_length, 1, file);
|
||||
|
||||
fclose(file);
|
||||
|
@ -48,7 +48,7 @@ X_STATUS AudioSystem::Setup() {
|
||||
new XenonThreadState(emulator_->processor()->runtime(), 0, 16 * 1024, 0);
|
||||
thread_state_->set_name("Audio Worker");
|
||||
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_;
|
||||
|
||||
// Create worker thread.
|
||||
|
@ -12,13 +12,9 @@
|
||||
|
||||
#include <xenia/common.h>
|
||||
|
||||
#include <alloy/memory.h>
|
||||
namespace xe {
|
||||
using Memory = alloy::Memory;
|
||||
} // namespace xe
|
||||
|
||||
#include <xenia/core/ref.h>
|
||||
#include <xenia/core/run_loop.h>
|
||||
#include <xenia/core/socket.h>
|
||||
#include <xenia/memory.h>
|
||||
|
||||
#endif // XENIA_CORE_H_
|
||||
|
@ -12,7 +12,6 @@
|
||||
#include <xenia/emulator.h>
|
||||
#include <xenia/export_resolver.h>
|
||||
#include <xenia/cpu/cpu-private.h>
|
||||
#include <xenia/cpu/xenon_memory.h>
|
||||
#include <xenia/cpu/xenon_runtime.h>
|
||||
#include <xenia/cpu/xex_module.h>
|
||||
|
||||
|
@ -19,6 +19,7 @@
|
||||
XEDECLARECLASS2(alloy, runtime, Breakpoint);
|
||||
XEDECLARECLASS1(xe, Emulator);
|
||||
XEDECLARECLASS1(xe, ExportResolver);
|
||||
XEDECLARECLASS1(xe, Memory);
|
||||
XEDECLARECLASS2(xe, cpu, XenonMemory);
|
||||
XEDECLARECLASS2(xe, cpu, XenonRuntime);
|
||||
XEDECLARECLASS2(xe, cpu, XenonThreadState);
|
||||
|
@ -8,8 +8,6 @@
|
||||
'mmio_handler.h',
|
||||
'processor.cc',
|
||||
'processor.h',
|
||||
'xenon_memory.cc',
|
||||
'xenon_memory.h',
|
||||
'xenon_runtime.cc',
|
||||
'xenon_runtime.h',
|
||||
'xenon_thread_state.cc',
|
||||
|
@ -10,25 +10,20 @@
|
||||
#include <xenia/cpu/xenon_runtime.h>
|
||||
|
||||
#include <alloy/frontend/ppc/ppc_frontend.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::cpu;
|
||||
|
||||
XenonRuntime::XenonRuntime(alloy::Memory* memory,
|
||||
ExportResolver* export_resolver,
|
||||
XenonRuntime::XenonRuntime(Memory* memory, ExportResolver* export_resolver,
|
||||
uint32_t debug_info_flags, uint32_t trace_flags)
|
||||
: Runtime(memory, debug_info_flags, trace_flags),
|
||||
export_resolver_(export_resolver) {}
|
||||
|
||||
XenonRuntime::~XenonRuntime() = default;
|
||||
|
||||
int XenonRuntime::Initialize(std::unique_ptr<backend::Backend> backend) {
|
||||
std::unique_ptr<PPCFrontend> frontend(new PPCFrontend(this));
|
||||
int XenonRuntime::Initialize(std::unique_ptr<alloy::backend::Backend> backend) {
|
||||
auto frontend = std::make_unique<alloy::frontend::ppc::PPCFrontend>(this);
|
||||
// TODO(benvanik): set options/etc.
|
||||
|
||||
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),
|
||||
stack_size_(stack_size),
|
||||
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_);
|
||||
|
||||
// Allocate with 64b alignment.
|
||||
@ -56,7 +56,7 @@ XenonThreadState::~XenonThreadState() {
|
||||
runtime_->debugger()->OnThreadDestroyed(this);
|
||||
|
||||
xe_free_aligned(context_);
|
||||
memory_->HeapFree(stack_address_, stack_size_);
|
||||
xenon_memory()->HeapFree(stack_address_, stack_size_);
|
||||
}
|
||||
|
||||
void XenonThreadState::WriteRegisters(xdb::protocol::Registers* registers) {
|
||||
|
@ -27,13 +27,13 @@ class XenonRuntime;
|
||||
|
||||
using PPCContext = alloy::frontend::ppc::PPCContext;
|
||||
|
||||
|
||||
class XenonThreadState : public alloy::runtime::ThreadState {
|
||||
public:
|
||||
XenonThreadState(XenonRuntime* runtime, uint32_t thread_id,
|
||||
size_t stack_size, uint64_t thread_state_address);
|
||||
public:
|
||||
XenonThreadState(XenonRuntime* runtime, uint32_t thread_id, size_t stack_size,
|
||||
uint64_t thread_state_address);
|
||||
virtual ~XenonThreadState();
|
||||
|
||||
Memory* xenon_memory() { return static_cast<Memory*>(memory_); }
|
||||
uint64_t stack_address() const { return stack_address_; }
|
||||
size_t stack_size() const { return stack_size_; }
|
||||
uint64_t thread_state_address() const { return thread_state_address_; }
|
||||
@ -41,18 +41,16 @@ public:
|
||||
|
||||
void WriteRegisters(xdb::protocol::Registers* registers);
|
||||
|
||||
private:
|
||||
uint64_t stack_address_;
|
||||
size_t stack_size_;
|
||||
uint64_t thread_state_address_;
|
||||
private:
|
||||
uint64_t stack_address_;
|
||||
size_t stack_size_;
|
||||
uint64_t thread_state_address_;
|
||||
|
||||
// NOTE: must be 64b aligned for SSE ops.
|
||||
PPCContext* context_;
|
||||
};
|
||||
|
||||
|
||||
} // namespace cpu
|
||||
} // namespace xe
|
||||
|
||||
|
||||
#endif // XENIA_CPU_XENON_THREAD_STATE_H_
|
||||
|
@ -13,13 +13,13 @@
|
||||
#include <xdb/protocol.h>
|
||||
#include <xenia/apu/apu.h>
|
||||
#include <xenia/cpu/cpu.h>
|
||||
#include <xenia/cpu/xenon_memory.h>
|
||||
#include <xenia/gpu/gpu.h>
|
||||
#include <xenia/hid/hid.h>
|
||||
#include <xenia/kernel/kernel.h>
|
||||
#include <xenia/kernel/kernel_state.h>
|
||||
#include <xenia/kernel/modules.h>
|
||||
#include <xenia/kernel/fs/filesystem.h>
|
||||
#include <xenia/memory.h>
|
||||
#include <xenia/ui/window.h>
|
||||
|
||||
namespace xe {
|
||||
@ -87,7 +87,7 @@ X_STATUS Emulator::Setup() {
|
||||
XEEXPECTZERO(result);
|
||||
|
||||
// Create memory system first, as it is required for other systems.
|
||||
memory_ = new XenonMemory();
|
||||
memory_ = new Memory();
|
||||
XEEXPECTNOTNULL(memory_);
|
||||
result = memory_->Initialize();
|
||||
XEEXPECTZERO(result);
|
||||
|
@ -14,7 +14,6 @@
|
||||
|
||||
#include <xenia/common.h>
|
||||
#include <xenia/core.h>
|
||||
#include <xenia/cpu/xenon_memory.h>
|
||||
#include <xenia/debug_agent.h>
|
||||
#include <xenia/kernel/kernel_state.h>
|
||||
#include <xenia/xbox.h>
|
||||
@ -55,7 +54,7 @@ class Emulator {
|
||||
ui::Window* main_window() const { return main_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(); }
|
||||
|
||||
@ -79,31 +78,29 @@ class Emulator {
|
||||
|
||||
private:
|
||||
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_;
|
||||
|
||||
cpu::Processor* processor_;
|
||||
apu::AudioSystem* audio_system_;
|
||||
gpu::GraphicsSystem* graphics_system_;
|
||||
hid::InputSystem* input_system_;
|
||||
cpu::Processor* processor_;
|
||||
apu::AudioSystem* audio_system_;
|
||||
gpu::GraphicsSystem* graphics_system_;
|
||||
hid::InputSystem* input_system_;
|
||||
|
||||
ExportResolver* export_resolver_;
|
||||
ExportResolver* export_resolver_;
|
||||
kernel::fs::FileSystem* file_system_;
|
||||
|
||||
kernel::KernelState* kernel_state_;
|
||||
kernel::XamModule* xam_;
|
||||
kernel::KernelState* kernel_state_;
|
||||
kernel::XamModule* xam_;
|
||||
kernel::XboxkrnlModule* xboxkrnl_;
|
||||
};
|
||||
|
||||
|
||||
} // namespace xe
|
||||
|
||||
|
||||
#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
|
||||
// structure.
|
||||
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_) {
|
||||
XELOGW("Unable to allocate thread state block");
|
||||
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.
|
||||
scratch_size_ = 4 * 16;
|
||||
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.
|
||||
const xe_xex2_header_t* header = module->xex_header();
|
||||
uint32_t tls_size = header->tls_info.slot_count * header->tls_info.data_size;
|
||||
tls_address_ =
|
||||
(uint32_t)memory()->HeapAlloc(0, tls_size, alloy::MEMORY_FLAG_ZERO);
|
||||
tls_address_ = (uint32_t)memory()->HeapAlloc(0, tls_size, MEMORY_FLAG_ZERO);
|
||||
if (!tls_address_) {
|
||||
XELOGW("Unable to allocate thread local storage block");
|
||||
module->Release();
|
||||
|
@ -21,14 +21,14 @@
|
||||
#include <third_party/mspack/mspack.h>
|
||||
#include <third_party/pe/pe_image.h>
|
||||
|
||||
using namespace alloy;
|
||||
// using namespace alloy;
|
||||
|
||||
DEFINE_bool(xex_dev_key, false, "Use the devkit key.");
|
||||
|
||||
typedef struct xe_xex2 {
|
||||
xe_ref_t ref;
|
||||
|
||||
Memory *memory;
|
||||
xe::Memory *memory;
|
||||
|
||||
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);
|
||||
int xe_xex2_decrypt_key(xe_xex2_header_t *header);
|
||||
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_find_import_infos(xe_xex2_ref xex,
|
||||
const xe_xex2_import_library_t *library);
|
||||
|
||||
xe_xex2_ref xe_xex2_load(Memory *memory, const void *addr, const size_t length,
|
||||
xe_xex2_options_t options) {
|
||||
xe_xex2_ref xe_xex2_load(xe::Memory *memory, const void *addr,
|
||||
const size_t length, xe_xex2_options_t options) {
|
||||
xe_xex2_ref xex = (xe_xex2_ref)xe_calloc(sizeof(xe_xex2));
|
||||
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,
|
||||
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.
|
||||
const size_t exe_length = xex_length - header->exe_offset;
|
||||
size_t uncompressed_size = exe_length;
|
||||
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) {
|
||||
XELOGE("Unable to allocate XEX memory at %.8X-%.8X.", header->exe_address,
|
||||
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,
|
||||
const uint8_t *xex_addr,
|
||||
const size_t xex_length,
|
||||
Memory *memory) {
|
||||
xe::Memory *memory) {
|
||||
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 *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.
|
||||
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) {
|
||||
XELOGE("Unable to allocate XEX memory at %.8X-%.8X.", header->exe_address,
|
||||
uncompressed_size);
|
||||
@ -645,7 +646,7 @@ XECLEANUP:
|
||||
|
||||
int xe_xex2_read_image_compressed(const xe_xex2_header_t *header,
|
||||
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 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.
|
||||
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) {
|
||||
XELOGE("Unable to allocate XEX memory at %.8X-%.8X.", header->exe_address,
|
||||
uncompressed_size);
|
||||
@ -778,7 +779,7 @@ XECLEANUP:
|
||||
}
|
||||
|
||||
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;
|
||||
switch (header->file_format_info.compression_type) {
|
||||
case XEX_COMPRESSION_NONE:
|
||||
|
@ -158,7 +158,7 @@ SHIM_CALL NtQueryVirtualMemory_shim(PPCContext* ppc_state, KernelState* state) {
|
||||
XELOGD("NtQueryVirtualMemory(%.8X, %.8X)", base_address,
|
||||
memory_basic_information_ptr);
|
||||
|
||||
alloy::AllocationInfo mem_info;
|
||||
AllocationInfo mem_info;
|
||||
size_t result = state->memory()->QueryInformation(base_address, &mem_info);
|
||||
if (!result) {
|
||||
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);
|
||||
|
||||
// Allocate.
|
||||
uint32_t flags = alloy::MEMORY_FLAG_PHYSICAL;
|
||||
uint32_t flags = MEMORY_FLAG_PHYSICAL;
|
||||
uint32_t base_address = (uint32_t)state->memory()->HeapAlloc(
|
||||
0, adjusted_size, flags, adjusted_alignment);
|
||||
if (!base_address) {
|
||||
@ -410,7 +410,7 @@ SHIM_CALL ExAllocatePoolTypeWithTag_shim(PPCContext* ppc_state,
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
@ -7,16 +7,16 @@
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#include <xenia/cpu/xenon_memory.h>
|
||||
#include <xenia/memory.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <mutex>
|
||||
|
||||
#include <gflags/gflags.h>
|
||||
#include <poly/math.h>
|
||||
#include <xenia/cpu/mmio_handler.h>
|
||||
|
||||
using namespace alloy;
|
||||
using namespace xe::cpu;
|
||||
using namespace xe;
|
||||
|
||||
// TODO(benvanik): move xbox.h out
|
||||
#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_HIGH 0x40000000
|
||||
|
||||
class xe::cpu::XenonMemoryHeap {
|
||||
class xe::MemoryHeap {
|
||||
public:
|
||||
XenonMemoryHeap(XenonMemory* memory, bool is_physical);
|
||||
~XenonMemoryHeap();
|
||||
MemoryHeap(Memory* memory, bool is_physical);
|
||||
~MemoryHeap();
|
||||
|
||||
int Initialize(uint64_t low, uint64_t high);
|
||||
|
||||
@ -104,7 +104,7 @@ class xe::cpu::XenonMemoryHeap {
|
||||
void* context);
|
||||
|
||||
private:
|
||||
XenonMemory* memory_;
|
||||
Memory* memory_;
|
||||
uint32_t heap_id_;
|
||||
bool is_physical_;
|
||||
std::mutex lock_;
|
||||
@ -112,15 +112,15 @@ class xe::cpu::XenonMemoryHeap {
|
||||
uint8_t* ptr_;
|
||||
mspace space_;
|
||||
};
|
||||
uint32_t XenonMemoryHeap::next_heap_id_ = 1;
|
||||
uint32_t MemoryHeap::next_heap_id_ = 1;
|
||||
|
||||
XenonMemory::XenonMemory()
|
||||
: Memory(), mapping_(0), mapping_base_(0), page_table_(0) {
|
||||
virtual_heap_ = new XenonMemoryHeap(this, false);
|
||||
physical_heap_ = new XenonMemoryHeap(this, true);
|
||||
Memory::Memory()
|
||||
: alloy::Memory(), mapping_(0), mapping_base_(0), page_table_(0) {
|
||||
virtual_heap_ = new MemoryHeap(this, false);
|
||||
physical_heap_ = new MemoryHeap(this, true);
|
||||
}
|
||||
|
||||
XenonMemory::~XenonMemory() {
|
||||
Memory::~Memory() {
|
||||
// Uninstall the MMIO handler, as we won't be able to service more
|
||||
// requests.
|
||||
mmio_handler_.reset();
|
||||
@ -142,8 +142,8 @@ XenonMemory::~XenonMemory() {
|
||||
}
|
||||
}
|
||||
|
||||
int XenonMemory::Initialize() {
|
||||
int result = Memory::Initialize();
|
||||
int Memory::Initialize() {
|
||||
int result = alloy::Memory::Initialize();
|
||||
if (result) {
|
||||
return result;
|
||||
}
|
||||
@ -196,7 +196,7 @@ int XenonMemory::Initialize() {
|
||||
VirtualAlloc(Translate(0xC0000000), 0x00100000, MEM_COMMIT, PAGE_READWRITE);
|
||||
|
||||
// Add handlers for MMIO.
|
||||
mmio_handler_ = MMIOHandler::Install(mapping_base_);
|
||||
mmio_handler_ = cpu::MMIOHandler::Install(mapping_base_);
|
||||
if (!mmio_handler_) {
|
||||
XELOGE("Unable to install MMIO handlers");
|
||||
assert_always();
|
||||
@ -227,7 +227,7 @@ const static struct {
|
||||
0xC0000000, 0xDFFFFFFF, 0x00000000, // - physical 16mb 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));
|
||||
for (size_t n = 0; n < poly::countof(map_info); n++) {
|
||||
#if XE_PLATFORM_WIN32
|
||||
@ -252,7 +252,7 @@ XECLEANUP:
|
||||
return 1;
|
||||
}
|
||||
|
||||
void XenonMemory::UnmapViews() {
|
||||
void Memory::UnmapViews() {
|
||||
for (size_t n = 0; n < poly::countof(views_.all_views); n++) {
|
||||
if (views_.all_views[n]) {
|
||||
#if XE_PLATFORM_WIN32
|
||||
@ -266,9 +266,9 @@ void XenonMemory::UnmapViews() {
|
||||
}
|
||||
}
|
||||
|
||||
bool XenonMemory::AddMappedRange(uint64_t address, uint64_t mask, uint64_t size,
|
||||
void* context, MMIOReadCallback read_callback,
|
||||
MMIOWriteCallback write_callback) {
|
||||
bool Memory::AddMappedRange(uint64_t address, uint64_t mask, uint64_t size,
|
||||
void* context, cpu::MMIOReadCallback read_callback,
|
||||
cpu::MMIOWriteCallback write_callback) {
|
||||
DWORD protect = PAGE_NOACCESS;
|
||||
if (!VirtualAlloc(Translate(address), size, MEM_COMMIT, protect)) {
|
||||
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);
|
||||
}
|
||||
|
||||
uint8_t XenonMemory::LoadI8(uint64_t address) {
|
||||
uint8_t Memory::LoadI8(uint64_t address) {
|
||||
uint64_t value;
|
||||
if (!mmio_handler_->CheckLoad(address, &value)) {
|
||||
value = *reinterpret_cast<uint8_t*>(Translate(address));
|
||||
@ -286,7 +286,7 @@ uint8_t XenonMemory::LoadI8(uint64_t address) {
|
||||
return static_cast<uint8_t>(value);
|
||||
}
|
||||
|
||||
uint16_t XenonMemory::LoadI16(uint64_t address) {
|
||||
uint16_t Memory::LoadI16(uint64_t address) {
|
||||
uint64_t value;
|
||||
if (!mmio_handler_->CheckLoad(address, &value)) {
|
||||
value = *reinterpret_cast<uint16_t*>(Translate(address));
|
||||
@ -294,7 +294,7 @@ uint16_t XenonMemory::LoadI16(uint64_t address) {
|
||||
return static_cast<uint16_t>(value);
|
||||
}
|
||||
|
||||
uint32_t XenonMemory::LoadI32(uint64_t address) {
|
||||
uint32_t Memory::LoadI32(uint64_t address) {
|
||||
uint64_t value;
|
||||
if (!mmio_handler_->CheckLoad(address, &value)) {
|
||||
value = *reinterpret_cast<uint32_t*>(Translate(address));
|
||||
@ -302,7 +302,7 @@ uint32_t XenonMemory::LoadI32(uint64_t address) {
|
||||
return static_cast<uint32_t>(value);
|
||||
}
|
||||
|
||||
uint64_t XenonMemory::LoadI64(uint64_t address) {
|
||||
uint64_t Memory::LoadI64(uint64_t address) {
|
||||
uint64_t value;
|
||||
if (!mmio_handler_->CheckLoad(address, &value)) {
|
||||
value = *reinterpret_cast<uint64_t*>(Translate(address));
|
||||
@ -310,32 +310,32 @@ uint64_t XenonMemory::LoadI64(uint64_t address) {
|
||||
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)) {
|
||||
*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)) {
|
||||
*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)) {
|
||||
*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)) {
|
||||
*reinterpret_cast<uint64_t*>(Translate(address)) = value;
|
||||
}
|
||||
}
|
||||
|
||||
uint64_t XenonMemory::HeapAlloc(uint64_t base_address, size_t size,
|
||||
uint32_t flags, uint32_t alignment) {
|
||||
uint64_t Memory::HeapAlloc(uint64_t base_address, size_t size, uint32_t flags,
|
||||
uint32_t alignment) {
|
||||
// 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).
|
||||
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 &&
|
||||
address < XENON_MEMORY_VIRTUAL_HEAP_HIGH) {
|
||||
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,
|
||||
AllocationInfo* mem_info) {
|
||||
bool Memory::QueryInformation(uint64_t base_address, AllocationInfo* mem_info) {
|
||||
uint8_t* p = Translate(base_address);
|
||||
MEMORY_BASIC_INFORMATION mbi;
|
||||
if (!VirtualQuery(p, &mbi, sizeof(mbi))) {
|
||||
@ -416,7 +415,7 @@ bool XenonMemory::QueryInformation(uint64_t base_address,
|
||||
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 &&
|
||||
base_address < XENON_MEMORY_VIRTUAL_HEAP_HIGH) {
|
||||
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);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
uint32_t XenonMemory::QueryProtect(uint64_t address) {
|
||||
uint32_t Memory::QueryProtect(uint64_t address) {
|
||||
uint8_t* p = Translate(address);
|
||||
MEMORY_BASIC_INFORMATION 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;
|
||||
}
|
||||
|
||||
XenonMemoryHeap::XenonMemoryHeap(XenonMemory* memory, bool is_physical)
|
||||
MemoryHeap::MemoryHeap(Memory* memory, bool is_physical)
|
||||
: memory_(memory), is_physical_(is_physical) {
|
||||
heap_id_ = next_heap_id_++;
|
||||
}
|
||||
|
||||
XenonMemoryHeap::~XenonMemoryHeap() {
|
||||
MemoryHeap::~MemoryHeap() {
|
||||
if (space_) {
|
||||
std::lock_guard<std::mutex> guard(lock_);
|
||||
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.
|
||||
// TODO(benvanik): replace dlmalloc with an implementation that can commit
|
||||
// as it goes.
|
||||
@ -494,8 +493,8 @@ int XenonMemoryHeap::Initialize(uint64_t low, uint64_t high) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint64_t XenonMemoryHeap::Alloc(uint64_t base_address, size_t size,
|
||||
uint32_t flags, uint32_t alignment) {
|
||||
uint64_t MemoryHeap::Alloc(uint64_t base_address, size_t size, uint32_t flags,
|
||||
uint32_t alignment) {
|
||||
lock_.lock();
|
||||
size_t alloc_size = size;
|
||||
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;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
// Heap allocated address.
|
||||
@ -590,7 +589,7 @@ uint64_t XenonMemoryHeap::Free(uint64_t address, size_t 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);
|
||||
|
||||
// Heap allocated address.
|
||||
@ -605,8 +604,8 @@ size_t XenonMemoryHeap::QuerySize(uint64_t base_address) {
|
||||
return real_size;
|
||||
}
|
||||
|
||||
void XenonMemoryHeap::Dump() {
|
||||
XELOGI("XenonMemoryHeap::Dump - %s", is_physical_ ? "physical" : "virtual");
|
||||
void MemoryHeap::Dump() {
|
||||
XELOGI("MemoryHeap::Dump - %s", is_physical_ ? "physical" : "virtual");
|
||||
if (FLAGS_heap_guard_pages) {
|
||||
XELOGI(" (heap guard pages enabled, stats will be wrong)");
|
||||
}
|
||||
@ -622,10 +621,10 @@ void XenonMemoryHeap::Dump() {
|
||||
mspace_inspect_all(space_, DumpHandler, this);
|
||||
}
|
||||
|
||||
void XenonMemoryHeap::DumpHandler(void* start, void* end, size_t used_bytes,
|
||||
void* context) {
|
||||
XenonMemoryHeap* heap = (XenonMemoryHeap*)context;
|
||||
XenonMemory* memory = heap->memory_;
|
||||
void MemoryHeap::DumpHandler(void* start, void* end, size_t used_bytes,
|
||||
void* context) {
|
||||
MemoryHeap* heap = (MemoryHeap*)context;
|
||||
Memory* memory = heap->memory_;
|
||||
size_t heap_guard_size = FLAGS_heap_guard_pages * 4096;
|
||||
uint64_t start_addr = (uint64_t)start + heap_guard_size;
|
||||
uint64_t end_addr = (uint64_t)end - heap_guard_size;
|
@ -7,8 +7,8 @@
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef XENIA_CPU_XENON_MEMORY_H_
|
||||
#define XENIA_CPU_XENON_MEMORY_H_
|
||||
#ifndef XENIA_MEMORY_H_
|
||||
#define XENIA_MEMORY_H_
|
||||
|
||||
#include <memory>
|
||||
|
||||
@ -20,22 +20,41 @@
|
||||
typedef struct xe_ppc_state xe_ppc_state_t;
|
||||
|
||||
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:
|
||||
XenonMemory();
|
||||
virtual ~XenonMemory();
|
||||
Memory();
|
||||
~Memory() override;
|
||||
|
||||
int Initialize() override;
|
||||
|
||||
// TODO(benvanik): remove with GPU refactor.
|
||||
uint64_t page_table() const override { return page_table_; }
|
||||
|
||||
bool AddMappedRange(uint64_t address, uint64_t mask, uint64_t size,
|
||||
void* context, MMIOReadCallback read_callback,
|
||||
MMIOWriteCallback write_callback);
|
||||
void* context, cpu::MMIOReadCallback read_callback,
|
||||
cpu::MMIOWriteCallback write_callback);
|
||||
|
||||
uint8_t LoadI8(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;
|
||||
|
||||
uint64_t HeapAlloc(uint64_t base_address, size_t size, uint32_t flags,
|
||||
uint32_t alignment = 0x20) override;
|
||||
int HeapFree(uint64_t address, size_t size) override;
|
||||
uint32_t alignment = 0x20);
|
||||
int HeapFree(uint64_t address, size_t size);
|
||||
|
||||
bool QueryInformation(uint64_t base_address,
|
||||
alloy::AllocationInfo* mem_info) override;
|
||||
size_t QuerySize(uint64_t base_address) override;
|
||||
bool QueryInformation(uint64_t base_address, AllocationInfo* mem_info);
|
||||
size_t QuerySize(uint64_t base_address);
|
||||
|
||||
int Protect(uint64_t address, size_t size, uint32_t access) override;
|
||||
uint32_t QueryProtect(uint64_t address) override;
|
||||
int Protect(uint64_t address, size_t size, uint32_t access);
|
||||
uint32_t QueryProtect(uint64_t address);
|
||||
|
||||
private:
|
||||
int MapViews(uint8_t* mapping_base);
|
||||
@ -76,17 +94,16 @@ class XenonMemory : public alloy::Memory {
|
||||
uint8_t* all_views[6];
|
||||
} views_;
|
||||
|
||||
std::unique_ptr<MMIOHandler> mmio_handler_;
|
||||
std::unique_ptr<cpu::MMIOHandler> mmio_handler_;
|
||||
|
||||
XenonMemoryHeap* virtual_heap_;
|
||||
XenonMemoryHeap* physical_heap_;
|
||||
MemoryHeap* virtual_heap_;
|
||||
MemoryHeap* physical_heap_;
|
||||
|
||||
uint64_t page_table_;
|
||||
|
||||
friend class XenonMemoryHeap;
|
||||
friend class MemoryHeap;
|
||||
};
|
||||
|
||||
} // namespace cpu
|
||||
} // namespace xe
|
||||
|
||||
#endif // XENIA_CPU_XENON_MEMORY_H_
|
||||
#endif // XENIA_MEMORY_H_
|
@ -13,6 +13,8 @@
|
||||
'logging.h',
|
||||
'malloc.cc',
|
||||
'malloc.h',
|
||||
'memory.cc',
|
||||
'memory.h',
|
||||
'profiling.cc',
|
||||
'profiling.h',
|
||||
'types.h',
|
||||
|
@ -15,7 +15,6 @@
|
||||
#include <alloy/runtime/raw_module.h>
|
||||
#include <poly/main.h>
|
||||
#include <poly/poly.h>
|
||||
#include <xenia/cpu/xenon_memory.h>
|
||||
|
||||
#include <gflags/gflags.h>
|
||||
|
||||
@ -28,11 +27,12 @@ using alloy::runtime::Runtime;
|
||||
class ThreadState : public alloy::runtime::ThreadState {
|
||||
public:
|
||||
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),
|
||||
stack_address_(thread_stack_address),
|
||||
stack_size_(stack_size),
|
||||
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.
|
||||
context_ = (PPCContext*)xe_malloc_aligned(sizeof(PPCContext));
|
||||
@ -60,7 +60,6 @@ class ThreadState : public alloy::runtime::ThreadState {
|
||||
~ThreadState() override {
|
||||
runtime_->debugger()->OnThreadDestroyed(this);
|
||||
xe_free_aligned(context_);
|
||||
memory_->HeapFree(stack_address_, stack_size_);
|
||||
}
|
||||
|
||||
PPCContext* context() const { return context_; }
|
||||
@ -80,7 +79,8 @@ int main(std::vector<std::wstring>& args) {
|
||||
xe::Profiler::Initialize();
|
||||
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 frontend =
|
||||
@ -97,11 +97,14 @@ int main(std::vector<std::wstring>& args) {
|
||||
runtime->AddModule(std::move(module));
|
||||
|
||||
{
|
||||
auto thread_state =
|
||||
std::make_unique<ThreadState>(runtime.get(), 100, 64 * 1024, 0);
|
||||
uint64_t thread_state_address = 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;
|
||||
runtime->ResolveFunction(0x82000000, &fn);
|
||||
runtime->ResolveFunction(0x1000, &fn);
|
||||
auto ctx = thread_state->context();
|
||||
ctx->lr = 0xBEBEBEBE;
|
||||
ctx->r[5] = 10;
|
||||
|
Loading…
Reference in New Issue
Block a user