#pragma once #include "Memory.h" class CPUThread; namespace vm { enum memory_location : uint { main, stack, //remove me sprx, user_space, memory_location_count }; static void set_stack_size(u32 size) {} static void initialize_stack() {} #ifdef _WIN32 extern HANDLE g_memory_handle; #endif extern void* g_priv_addr; extern void* const g_base_addr; // break the reservation, return true if it was successfully broken bool reservation_break(u32 addr); // read memory and reserve it for further atomic update, return true if the previous reservation was broken bool reservation_acquire(void* data, u32 addr, u32 size, const std::function& callback = nullptr); // attempt to atomically update reserved memory bool reservation_update(u32 addr, const void* data, u32 size); bool reservation_query(u32 addr); void reservation_free(); // perform complete operation void reservation_op(u32 addr, u32 size, std::function proc); bool map(u32 addr, u32 size, u32 flags); bool unmap(u32 addr, u32 size = 0, u32 flags = 0); u32 alloc(u32 size, memory_location location = user_space); u32 alloc(u32 addr, u32 size, memory_location location = user_space); void dealloc(u32 addr, memory_location location = user_space); template T* const get_ptr(u32 addr) { return reinterpret_cast(static_cast(g_base_addr) + addr); } template T& get_ref(u32 addr) { return *get_ptr(addr); } template T* const get_priv_ptr(u32 addr) { return reinterpret_cast(static_cast(g_priv_addr) + addr); } template T& get_priv_ref(u32 addr) { return *get_priv_ptr(addr); } u32 get_addr(const void* real_pointer); __noinline void error(const u64 addr, const char* func); template struct cast_ptr { static_assert(std::is_same::value, "Unsupported vm::cast() type"); __forceinline static u32 cast(const T& addr, const char* func) { return 0; } }; template<> struct cast_ptr { __forceinline static u32 cast(const u32 addr, const char* func) { return addr; } }; template<> struct cast_ptr { __forceinline static u32 cast(const u64 addr, const char* func) { const u32 res = static_cast(addr); if (res != addr) { vm::error(addr, func); } return res; } }; template struct cast_ptr> { __forceinline static u32 cast(const be_t& addr, const char* func) { return cast_ptr::cast(addr.value(), func); } }; template __forceinline static u32 cast(const T& addr, const char* func = "vm::cast") { return cast_ptr::cast(addr, func); } namespace ps3 { void init(); static u8 read8(u32 addr) { return get_ref(addr); } static void write8(u32 addr, u8 value) { get_ref(addr) = value; } static u16 read16(u32 addr) { return get_ref>(addr); } static void write16(u32 addr, be_t value) { get_ref>(addr) = value; } static u32 read32(u32 addr) { return get_ref>(addr); } static void write32(u32 addr, be_t value) { get_ref>(addr) = value; } static u64 read64(u32 addr) { return get_ref>(addr); } static void write64(u32 addr, be_t value) { get_ref>(addr) = value; } static void write16(u32 addr, u16 value) { write16(addr, be_t::make(value)); } static void write32(u32 addr, u32 value) { write32(addr, be_t::make(value)); } static void write64(u32 addr, u64 value) { write64(addr, be_t::make(value)); } static u128 read128(u32 addr) { return get_ref>(addr); } static void write128(u32 addr, u128 value) { get_ref>(addr) = value; } } namespace psv { void init(); static u8 read8(u32 addr) { return get_ref(addr); } static void write8(u32 addr, u8 value) { get_ref(addr) = value; } static u16 read16(u32 addr) { return get_ref(addr); } static void write16(u32 addr, u16 value) { get_ref(addr) = value; } static u32 read32(u32 addr) { return get_ref(addr); } static void write32(u32 addr, u32 value) { get_ref(addr) = value; } static u64 read64(u32 addr) { return get_ref(addr); } static void write64(u32 addr, u64 value) { get_ref(addr) = value; } static u128 read128(u32 addr) { return get_ref(addr); } static void write128(u32 addr, u128 value) { get_ref(addr) = value; } } namespace psp { using namespace psv; void init(); } void close(); u32 stack_push(CPUThread& CPU, u32 size, u32 align, u32& old_pos); void stack_pop(CPUThread& CPU, u32 addr, u32 old_pos); } #include "vm_ref.h" #include "vm_ptr.h" #include "vm_var.h" namespace vm { struct location_info { u32 addr_offset; u32 size; u32(*allocator)(u32 size); u32(*fixed_allocator)(u32 addr, u32 size); void(*deallocator)(u32 addr); u32 alloc_offset; template ptr alloc(u32 count) const { return ptr::make(allocator(count * sizeof(T))); } }; extern location_info g_locations[memory_location_count]; template location_info& get() { assert(location < memory_location_count); return g_locations[location]; } class stack { u32 m_begin; u32 m_size; int m_page_size; int m_position; u8 m_align; public: void init(u32 begin, u32 size, u32 page_size = 180, u8 align = 0x10) { m_begin = begin; m_size = size; m_page_size = page_size; m_position = 0; m_align = align; } u32 alloc_new_page() { assert(m_position + m_page_size < (int)m_size); m_position += (int)m_page_size; return m_begin + m_position; } u32 dealloc_new_page() { assert(m_position - m_page_size > 0); m_position -= (int)m_page_size; return m_begin + m_position; } }; }