rpcsx/rpcs3/Emu/Memory/vm_var.h

156 lines
3 KiB
C
Raw Normal View History

#pragma once
2016-02-01 22:52:49 +01:00
#include "vm_ptr.h"
namespace vm
{
template <memory_location_t Location = vm::main>
2016-02-01 22:52:49 +01:00
struct page_allocator
{
2016-05-13 16:01:48 +02:00
static inline vm::addr_t alloc(u32 size, u32 align)
{
return vm::cast(vm::alloc(size, Location, std::max<u32>(align, 0x10000)));
}
2016-02-01 22:52:49 +01:00
static inline void dealloc(u32 addr, u32 size = 0) noexcept
{
return vm::dealloc_verbose_nothrow(addr, Location);
}
};
2015-08-13 15:28:42 +02:00
template <typename T>
2016-02-01 22:52:49 +01:00
struct stack_allocator
{
2016-05-13 16:01:48 +02:00
static inline vm::addr_t alloc(u32 size, u32 align)
{
return vm::cast(T::stack_push(size, align));
}
2016-02-01 22:52:49 +01:00
static inline void dealloc(u32 addr, u32 size) noexcept
{
T::stack_pop_verbose(addr, size);
}
};
// General variable base class
template <typename T, typename A>
2016-02-01 22:52:49 +01:00
class _var_base final : public _ptr_base<T, const u32>
{
using pointer = _ptr_base<T, const u32>;
public:
// Unmoveable object
_var_base(const _var_base&) = delete;
2018-09-22 21:35:52 +02:00
_var_base& operator=(const _var_base&) = delete;
2016-02-01 22:52:49 +01:00
_var_base()
2018-09-03 17:46:14 +02:00
: pointer(A::alloc(sizeof(T), alignof(T)))
{
}
2016-02-01 22:52:49 +01:00
_var_base(const T& right)
: _var_base()
{
2016-02-01 22:52:49 +01:00
std::memcpy(pointer::get_ptr(), &right, sizeof(T));
}
2016-02-01 22:52:49 +01:00
~_var_base()
{
if (pointer::addr())
{
2018-09-03 17:46:14 +02:00
A::dealloc(pointer::addr(), sizeof(T));
}
2016-02-01 22:52:49 +01:00
}
};
// Dynamic length array variable specialization
template <typename T, typename A>
2016-02-01 22:52:49 +01:00
class _var_base<T[], A> final : public _ptr_base<T, const u32>
{
using pointer = _ptr_base<T, const u32>;
2016-02-01 22:52:49 +01:00
u32 m_size;
public:
_var_base(const _var_base&) = delete;
2018-09-22 21:35:52 +02:00
_var_base& operator=(const _var_base&) = delete;
_var_base(u32 count)
2018-09-03 17:46:14 +02:00
: pointer(A::alloc(u32{sizeof(T)} * count, alignof(T)))
, m_size(u32{sizeof(T)} * count)
{
}
// Initialize via the iterator
template <typename I>
_var_base(u32 count, I&& it)
: _var_base(count)
{
std::copy_n(std::forward<I>(it), count, pointer::get_ptr());
}
2016-02-01 22:52:49 +01:00
~_var_base()
{
if (pointer::addr())
{
A::dealloc(pointer::addr(), m_size);
}
}
// Remove operator ->
T* operator->() const = delete;
2016-02-01 22:52:49 +01:00
u32 get_count() const
{
2018-09-03 17:46:14 +02:00
return m_size / u32{sizeof(T)};
}
auto begin() const
{
return *this + 0;
}
auto end() const
{
return *this + get_count();
}
2015-08-13 15:28:42 +02:00
};
// LE variable
template <typename T, typename A>
using varl = _var_base<to_le_t<T>, A>;
// BE variable
template <typename T, typename A>
using varb = _var_base<to_be_t<T>, A>;
2015-03-13 16:06:27 +01:00
2018-02-09 15:49:37 +01:00
inline namespace ps3_
2015-08-13 15:28:42 +02:00
{
// BE variable
template <typename T, typename A = stack_allocator<ppu_thread>>
using var = varb<T, A>;
2016-02-01 22:52:49 +01:00
// Make BE variable initialized from value
template <typename T, typename A = stack_allocator<ppu_thread>>
[[nodiscard]] auto make_var(const T& value)
{
return (varb<T, A>(value));
}
// Make char[] variable initialized from std::string
template <typename A = stack_allocator<ppu_thread>>
[[nodiscard]] auto make_str(const std::string& str)
{
return (_var_base<char[], A>(size32(str) + 1, str.c_str()));
}
2016-02-01 22:52:49 +01:00
// Global HLE variable
template <typename T>
2016-02-01 22:52:49 +01:00
struct gvar : ptr<T>
{
};
} // namespace ps3_
} // namespace vm