2014-07-31 18:08:02 +02:00
|
|
|
#pragma once
|
2014-11-19 15:16:30 +01:00
|
|
|
#include "Memory.h"
|
2014-07-31 18:08:02 +02:00
|
|
|
|
2015-01-07 17:44:47 +01:00
|
|
|
class CPUThread;
|
|
|
|
|
|
2014-07-31 18:08:02 +02:00
|
|
|
namespace vm
|
|
|
|
|
{
|
2015-02-13 16:26:42 +01:00
|
|
|
extern void* g_base_addr; // base address of ps3/psv virtual memory for common access
|
|
|
|
|
extern void* g_priv_addr; // base address of ps3/psv virtual memory for privileged access
|
|
|
|
|
|
2014-11-24 19:12:04 +01:00
|
|
|
enum memory_location : uint
|
2014-11-19 15:16:30 +01:00
|
|
|
{
|
|
|
|
|
main,
|
2015-02-13 15:04:03 +01:00
|
|
|
user_space,
|
2014-11-19 15:16:30 +01:00
|
|
|
stack,
|
2014-11-24 19:12:04 +01:00
|
|
|
|
2015-02-13 15:04:03 +01:00
|
|
|
memory_location_count
|
|
|
|
|
};
|
2014-11-24 19:12:04 +01:00
|
|
|
|
2015-02-13 15:04:03 +01:00
|
|
|
enum page_info_t : u8
|
|
|
|
|
{
|
|
|
|
|
page_readable = (1 << 0),
|
|
|
|
|
page_writable = (1 << 1),
|
|
|
|
|
page_executable = (1 << 2),
|
2014-11-19 15:16:30 +01:00
|
|
|
|
2015-02-13 15:04:03 +01:00
|
|
|
page_fault_notification = (1 << 3),
|
|
|
|
|
page_no_reservations = (1 << 4),
|
|
|
|
|
|
|
|
|
|
page_allocated = (1 << 7),
|
2014-11-19 15:16:30 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static void set_stack_size(u32 size) {}
|
|
|
|
|
static void initialize_stack() {}
|
|
|
|
|
|
2015-02-07 14:46:42 +01:00
|
|
|
// break the reservation, return true if it was successfully broken
|
2015-02-07 00:39:51 +01:00
|
|
|
bool reservation_break(u32 addr);
|
2015-02-07 14:46:42 +01:00
|
|
|
// read memory and reserve it for further atomic update, return true if the previous reservation was broken
|
2015-07-04 21:23:10 +02:00
|
|
|
bool reservation_acquire(void* data, u32 addr, u32 size, std::function<void()> callback = nullptr);
|
2015-02-16 18:19:17 +01:00
|
|
|
// same as reservation_acquire but does not have the callback argument
|
|
|
|
|
// used by the PPU LLVM JIT since creating a std::function object in LLVM IR is too complicated
|
|
|
|
|
bool reservation_acquire_no_cb(void* data, u32 addr, u32 size);
|
2015-02-07 14:46:42 +01:00
|
|
|
// attempt to atomically update reserved memory
|
2015-02-07 00:39:51 +01:00
|
|
|
bool reservation_update(u32 addr, const void* data, u32 size);
|
2015-02-13 15:04:03 +01:00
|
|
|
// for internal use
|
2015-02-17 01:08:23 +01:00
|
|
|
bool reservation_query(u32 addr, u32 size, bool is_writing, std::function<bool()> callback);
|
2015-02-13 15:04:03 +01:00
|
|
|
// for internal use
|
2015-02-07 00:39:51 +01:00
|
|
|
void reservation_free();
|
2015-02-07 14:46:42 +01:00
|
|
|
// perform complete operation
|
|
|
|
|
void reservation_op(u32 addr, u32 size, std::function<void()> proc);
|
2015-02-07 00:39:51 +01:00
|
|
|
|
2015-02-13 15:04:03 +01:00
|
|
|
// for internal use
|
|
|
|
|
void page_map(u32 addr, u32 size, u8 flags);
|
|
|
|
|
// for internal use
|
|
|
|
|
bool page_protect(u32 addr, u32 size, u8 flags_test = 0, u8 flags_set = 0, u8 flags_clear = 0);
|
|
|
|
|
// for internal use
|
|
|
|
|
void page_unmap(u32 addr, u32 size);
|
|
|
|
|
|
|
|
|
|
// unsafe address check
|
|
|
|
|
bool check_addr(u32 addr, u32 size = 1);
|
|
|
|
|
|
2014-08-01 18:27:48 +02:00
|
|
|
bool map(u32 addr, u32 size, u32 flags);
|
|
|
|
|
bool unmap(u32 addr, u32 size = 0, u32 flags = 0);
|
2014-11-19 15:16:30 +01:00
|
|
|
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);
|
2014-08-01 18:27:48 +02:00
|
|
|
|
2015-07-02 03:54:36 +02:00
|
|
|
template<typename T = void> T* get_ptr(u32 addr)
|
2014-07-31 18:08:02 +02:00
|
|
|
{
|
2015-01-19 20:41:31 +01:00
|
|
|
return reinterpret_cast<T*>(static_cast<u8*>(g_base_addr) + addr);
|
2014-07-31 18:08:02 +02:00
|
|
|
}
|
2014-11-19 15:16:30 +01:00
|
|
|
|
2015-07-02 03:54:36 +02:00
|
|
|
template<typename T> T& get_ref(u32 addr)
|
2014-08-31 11:54:12 +02:00
|
|
|
{
|
2014-09-15 00:17:24 +02:00
|
|
|
return *get_ptr<T>(addr);
|
2014-08-31 11:54:12 +02:00
|
|
|
}
|
|
|
|
|
|
2015-07-02 03:54:36 +02:00
|
|
|
template<typename T = void> T* priv_ptr(u32 addr)
|
2015-02-07 00:39:51 +01:00
|
|
|
{
|
|
|
|
|
return reinterpret_cast<T*>(static_cast<u8*>(g_priv_addr) + addr);
|
|
|
|
|
}
|
|
|
|
|
|
2015-07-02 03:54:36 +02:00
|
|
|
template<typename T> T& priv_ref(u32 addr)
|
2015-02-07 00:39:51 +01:00
|
|
|
{
|
2015-02-28 15:41:15 +01:00
|
|
|
return *priv_ptr<T>(addr);
|
2015-02-07 00:39:51 +01:00
|
|
|
}
|
|
|
|
|
|
2015-07-02 03:54:36 +02:00
|
|
|
inline u32 get_addr(const void* real_pointer)
|
|
|
|
|
{
|
2015-07-03 01:11:44 +02:00
|
|
|
const std::uintptr_t diff = reinterpret_cast<std::uintptr_t>(real_pointer) - reinterpret_cast<std::uintptr_t>(g_base_addr);
|
2015-07-02 03:54:36 +02:00
|
|
|
const u32 res = static_cast<u32>(diff);
|
|
|
|
|
|
|
|
|
|
if (res == diff)
|
|
|
|
|
{
|
|
|
|
|
return res;
|
|
|
|
|
}
|
2015-01-19 20:41:31 +01:00
|
|
|
|
2015-07-02 03:54:36 +02:00
|
|
|
if (real_pointer)
|
|
|
|
|
{
|
|
|
|
|
throw EXCEPTION("Not a virtual memory pointer (%p)", real_pointer);
|
|
|
|
|
}
|
2015-01-29 16:48:05 +01:00
|
|
|
|
2015-07-02 03:54:36 +02:00
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
template<typename T> struct cast_ptr
|
2015-01-14 14:57:19 +01:00
|
|
|
{
|
2015-07-03 01:11:44 +02:00
|
|
|
static_assert(std::is_same<T, u32>::value, "Unsupported VM_CAST() type");
|
2015-01-14 14:57:19 +01:00
|
|
|
|
2015-07-03 01:11:44 +02:00
|
|
|
force_inline static u32 cast(const T& addr, const char* file, int line, const char* func)
|
2015-01-14 14:57:19 +01:00
|
|
|
{
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
2015-07-02 03:54:36 +02:00
|
|
|
template<> struct cast_ptr<u32>
|
2015-01-14 14:57:19 +01:00
|
|
|
{
|
2015-07-03 01:11:44 +02:00
|
|
|
force_inline static u32 cast(const u32 addr, const char* file, int line, const char* func)
|
2015-01-14 14:57:19 +01:00
|
|
|
{
|
|
|
|
|
return addr;
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
2015-07-02 03:54:36 +02:00
|
|
|
template<> struct cast_ptr<u64>
|
2015-01-14 14:57:19 +01:00
|
|
|
{
|
2015-07-03 01:11:44 +02:00
|
|
|
force_inline static u32 cast(const u64 addr, const char* file, int line, const char* func)
|
2015-01-14 14:57:19 +01:00
|
|
|
{
|
2015-01-19 20:41:31 +01:00
|
|
|
const u32 res = static_cast<u32>(addr);
|
2015-07-02 03:54:36 +02:00
|
|
|
|
2015-01-14 14:57:19 +01:00
|
|
|
if (res != addr)
|
|
|
|
|
{
|
2015-07-03 01:11:44 +02:00
|
|
|
throw fmt::exception(file, line, func, "VM_CAST failed (addr=0x%llx)", addr);
|
2015-01-14 14:57:19 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return res;
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
2015-07-02 03:54:36 +02:00
|
|
|
template<typename T> struct cast_ptr<be_t<T>>
|
2015-01-14 14:57:19 +01:00
|
|
|
{
|
2015-07-03 01:11:44 +02:00
|
|
|
force_inline static u32 cast(const be_t<T>& addr, const char* file, int line, const char* func)
|
2015-01-14 14:57:19 +01:00
|
|
|
{
|
2015-07-03 01:11:44 +02:00
|
|
|
return cast_ptr<T>::cast(addr.value(), file, line, func);
|
2015-01-14 14:57:19 +01:00
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
2015-07-02 03:54:36 +02:00
|
|
|
template<typename T> struct cast_ptr<le_t<T>>
|
2015-06-21 01:04:01 +02:00
|
|
|
{
|
2015-07-03 01:11:44 +02:00
|
|
|
force_inline static u32 cast(const le_t<T>& addr, const char* file, int line, const char* func)
|
2015-06-21 01:04:01 +02:00
|
|
|
{
|
2015-07-03 01:11:44 +02:00
|
|
|
return cast_ptr<T>::cast(addr.value(), file, line, func);
|
2015-06-21 01:04:01 +02:00
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
2015-07-03 01:11:44 +02:00
|
|
|
// function for VM_CAST
|
|
|
|
|
template<typename T> force_inline static u32 impl_cast(const T& addr, const char* file, int line, const char* func)
|
2015-01-14 14:57:19 +01:00
|
|
|
{
|
2015-07-03 01:11:44 +02:00
|
|
|
return cast_ptr<T>::cast(addr, file, line, func);
|
2015-01-14 14:57:19 +01:00
|
|
|
}
|
|
|
|
|
|
2015-06-19 17:49:38 +02:00
|
|
|
static u8 read8(u32 addr)
|
2014-08-31 11:54:12 +02:00
|
|
|
{
|
2015-06-19 17:49:38 +02:00
|
|
|
return get_ref<u8>(addr);
|
|
|
|
|
}
|
2014-11-19 15:16:30 +01:00
|
|
|
|
2015-06-19 17:49:38 +02:00
|
|
|
static void write8(u32 addr, u8 value)
|
|
|
|
|
{
|
|
|
|
|
get_ref<u8>(addr) = value;
|
|
|
|
|
}
|
2014-09-15 00:17:24 +02:00
|
|
|
|
2015-06-19 17:49:38 +02:00
|
|
|
namespace ps3
|
|
|
|
|
{
|
|
|
|
|
void init();
|
2014-09-15 00:17:24 +02:00
|
|
|
|
2015-06-21 01:04:01 +02:00
|
|
|
inline const be_t<u16>& read16(u32 addr)
|
2014-08-31 11:54:12 +02:00
|
|
|
{
|
2015-06-21 01:04:01 +02:00
|
|
|
return get_ref<const be_t<u16>>(addr);
|
2014-09-15 00:17:24 +02:00
|
|
|
}
|
|
|
|
|
|
2015-06-21 01:04:01 +02:00
|
|
|
inline void write16(u32 addr, be_t<u16> value)
|
2014-08-31 11:54:12 +02:00
|
|
|
{
|
2015-01-19 20:41:31 +01:00
|
|
|
get_ref<be_t<u16>>(addr) = value;
|
2014-09-15 00:17:24 +02:00
|
|
|
}
|
|
|
|
|
|
2015-06-21 01:04:01 +02:00
|
|
|
inline void write16(u32 addr, u16 value)
|
2014-08-31 11:54:12 +02:00
|
|
|
{
|
2015-06-21 01:04:01 +02:00
|
|
|
get_ref<be_t<u16>>(addr) = value;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
inline const be_t<u32>& read32(u32 addr)
|
|
|
|
|
{
|
|
|
|
|
return get_ref<const be_t<u32>>(addr);
|
2014-08-31 11:54:12 +02:00
|
|
|
}
|
|
|
|
|
|
2015-06-21 01:04:01 +02:00
|
|
|
inline void write32(u32 addr, be_t<u32> value)
|
2014-08-31 11:54:12 +02:00
|
|
|
{
|
2015-01-19 20:41:31 +01:00
|
|
|
get_ref<be_t<u32>>(addr) = value;
|
2014-08-31 11:54:12 +02:00
|
|
|
}
|
|
|
|
|
|
2015-06-21 01:04:01 +02:00
|
|
|
inline void write32(u32 addr, u32 value)
|
2014-08-31 11:54:12 +02:00
|
|
|
{
|
2015-06-21 01:04:01 +02:00
|
|
|
get_ref<be_t<u32>>(addr) = value;
|
2014-09-15 00:17:24 +02:00
|
|
|
}
|
|
|
|
|
|
2015-06-21 01:04:01 +02:00
|
|
|
inline const be_t<u64>& read64(u32 addr)
|
2014-11-19 15:16:30 +01:00
|
|
|
{
|
2015-06-21 01:04:01 +02:00
|
|
|
return get_ref<const be_t<u64>>(addr);
|
2014-11-19 15:16:30 +01:00
|
|
|
}
|
|
|
|
|
|
2015-06-21 01:04:01 +02:00
|
|
|
inline void write64(u32 addr, be_t<u64> value)
|
2014-11-19 15:16:30 +01:00
|
|
|
{
|
2015-06-21 01:04:01 +02:00
|
|
|
get_ref<be_t<u64>>(addr) = value;
|
2014-11-19 15:16:30 +01:00
|
|
|
}
|
|
|
|
|
|
2015-06-21 01:04:01 +02:00
|
|
|
inline void write64(u32 addr, u64 value)
|
2014-11-19 15:16:30 +01:00
|
|
|
{
|
2015-06-21 01:04:01 +02:00
|
|
|
get_ref<be_t<u64>>(addr) = value;
|
2014-11-19 15:16:30 +01:00
|
|
|
}
|
|
|
|
|
|
2015-06-21 01:04:01 +02:00
|
|
|
inline const be_t<u128>& read128(u32 addr)
|
2014-08-31 11:54:12 +02:00
|
|
|
{
|
2015-06-21 01:04:01 +02:00
|
|
|
return get_ref<const be_t<u128>>(addr);
|
2014-09-15 00:17:24 +02:00
|
|
|
}
|
|
|
|
|
|
2015-06-21 01:04:01 +02:00
|
|
|
inline void write128(u32 addr, be_t<u128> value)
|
2014-08-31 11:54:12 +02:00
|
|
|
{
|
2015-06-21 01:04:01 +02:00
|
|
|
get_ref<be_t<u128>>(addr) = value;
|
2014-09-15 00:17:24 +02:00
|
|
|
}
|
|
|
|
|
|
2015-06-21 01:04:01 +02:00
|
|
|
inline void write128(u32 addr, u128 value)
|
2014-08-31 11:54:12 +02:00
|
|
|
{
|
2015-01-19 20:41:31 +01:00
|
|
|
get_ref<be_t<u128>>(addr) = value;
|
2014-09-15 00:17:24 +02:00
|
|
|
}
|
2014-08-31 11:54:12 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
namespace psv
|
|
|
|
|
{
|
2014-11-19 15:16:30 +01:00
|
|
|
void init();
|
|
|
|
|
|
2015-06-21 01:04:01 +02:00
|
|
|
inline const le_t<u16>& read16(u32 addr)
|
|
|
|
|
{
|
|
|
|
|
return get_ref<const le_t<u16>>(addr);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
inline void write16(u32 addr, le_t<u16> value)
|
|
|
|
|
{
|
|
|
|
|
get_ref<le_t<u16>>(addr) = value;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
inline void write16(u32 addr, u16 value)
|
|
|
|
|
{
|
|
|
|
|
get_ref<le_t<u16>>(addr) = value;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
inline const le_t<u32>& read32(u32 addr)
|
|
|
|
|
{
|
|
|
|
|
return get_ref<const le_t<u32>>(addr);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
inline void write32(u32 addr, le_t<u32> value)
|
2014-08-31 11:54:12 +02:00
|
|
|
{
|
2015-06-21 01:04:01 +02:00
|
|
|
get_ref<le_t<u32>>(addr) = value;
|
2014-08-31 11:54:12 +02:00
|
|
|
}
|
|
|
|
|
|
2015-06-21 01:04:01 +02:00
|
|
|
inline void write32(u32 addr, u32 value)
|
2014-08-31 11:54:12 +02:00
|
|
|
{
|
2015-06-21 01:04:01 +02:00
|
|
|
get_ref<le_t<u32>>(addr) = value;
|
2014-08-31 11:54:12 +02:00
|
|
|
}
|
|
|
|
|
|
2015-06-21 01:04:01 +02:00
|
|
|
inline const le_t<u64>& read64(u32 addr)
|
2014-08-31 11:54:12 +02:00
|
|
|
{
|
2015-06-21 01:04:01 +02:00
|
|
|
return get_ref<const le_t<u64>>(addr);
|
2014-08-31 11:54:12 +02:00
|
|
|
}
|
|
|
|
|
|
2015-06-21 01:04:01 +02:00
|
|
|
inline void write64(u32 addr, le_t<u64> value)
|
2014-08-31 11:54:12 +02:00
|
|
|
{
|
2015-06-21 01:04:01 +02:00
|
|
|
get_ref<le_t<u64>>(addr) = value;
|
2014-08-31 11:54:12 +02:00
|
|
|
}
|
|
|
|
|
|
2015-06-21 01:04:01 +02:00
|
|
|
inline void write64(u32 addr, u64 value)
|
2014-08-31 11:54:12 +02:00
|
|
|
{
|
2015-06-21 01:04:01 +02:00
|
|
|
get_ref<le_t<u64>>(addr) = value;
|
2014-08-31 11:54:12 +02:00
|
|
|
}
|
|
|
|
|
|
2015-06-21 01:04:01 +02:00
|
|
|
inline const le_t<u128>& read128(u32 addr)
|
2014-08-31 11:54:12 +02:00
|
|
|
{
|
2015-06-21 01:04:01 +02:00
|
|
|
return get_ref<const le_t<u128>>(addr);
|
2014-08-31 11:54:12 +02:00
|
|
|
}
|
|
|
|
|
|
2015-06-21 01:04:01 +02:00
|
|
|
inline void write128(u32 addr, le_t<u128> value)
|
2014-08-31 11:54:12 +02:00
|
|
|
{
|
2015-06-21 01:04:01 +02:00
|
|
|
get_ref<le_t<u128>>(addr) = value;
|
2014-08-31 11:54:12 +02:00
|
|
|
}
|
|
|
|
|
|
2015-06-21 01:04:01 +02:00
|
|
|
inline void write128(u32 addr, u128 value)
|
2014-08-31 11:54:12 +02:00
|
|
|
{
|
2015-06-21 01:04:01 +02:00
|
|
|
get_ref<le_t<u128>>(addr) = value;
|
2014-08-31 11:54:12 +02:00
|
|
|
}
|
|
|
|
|
}
|
2014-11-19 15:16:30 +01:00
|
|
|
|
|
|
|
|
namespace psp
|
|
|
|
|
{
|
|
|
|
|
using namespace psv;
|
|
|
|
|
|
|
|
|
|
void init();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void close();
|
2015-01-07 17:44:47 +01:00
|
|
|
|
|
|
|
|
u32 stack_push(CPUThread& CPU, u32 size, u32 align, u32& old_pos);
|
|
|
|
|
void stack_pop(CPUThread& CPU, u32 addr, u32 old_pos);
|
2014-07-31 18:08:02 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#include "vm_ref.h"
|
2014-08-31 01:38:55 +02:00
|
|
|
#include "vm_ptr.h"
|
2014-11-24 19:12:04 +01:00
|
|
|
#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<typename T = char>
|
2015-06-19 17:49:38 +02:00
|
|
|
_ptr_base<T> alloc(u32 count = 1) const
|
2014-11-24 19:12:04 +01:00
|
|
|
{
|
2015-06-19 17:49:38 +02:00
|
|
|
return{ allocator(count * sizeof32(T)) };
|
2014-11-24 19:12:04 +01:00
|
|
|
}
|
2015-04-01 01:49:39 +02:00
|
|
|
|
|
|
|
|
template<typename T = char>
|
2015-06-19 17:49:38 +02:00
|
|
|
_ptr_base<T> fixed_alloc(u32 addr, u32 count = 1) const
|
2015-04-01 01:49:39 +02:00
|
|
|
{
|
2015-06-19 17:49:38 +02:00
|
|
|
return{ fixed_allocator(addr, count * sizeof32(T)) };
|
2015-04-01 01:49:39 +02:00
|
|
|
}
|
2014-11-24 19:12:04 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
extern location_info g_locations[memory_location_count];
|
|
|
|
|
|
|
|
|
|
template<memory_location location = main>
|
|
|
|
|
location_info& get()
|
|
|
|
|
{
|
|
|
|
|
assert(location < memory_location_count);
|
|
|
|
|
return g_locations[location];
|
|
|
|
|
}
|
2014-11-29 14:16:53 +01:00
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
};
|
2014-11-24 19:12:04 +01:00
|
|
|
}
|