37constexpr u32 stack_align(u32 size) {
38 return (size + 15u) & ~15u;
43struct HoldsHostPointer
44 : std::bool_constant<std::is_pointer_v<T> || std::is_member_pointer_v<T> ||
45 std::is_null_pointer_v<T> || memory::is_mapped_ptr_v<T>> {};
48template <
typename T,
size_t N>
49struct HoldsHostPointer<T[N]> : HoldsHostPointer<T> {};
52template <
typename T,
size_t N>
53struct HoldsHostPointer<std::array<T, N>> : HoldsHostPointer<T> {};
57inline constexpr bool kHoldsHostPointer = HoldsHostPointer<std::remove_cv_t<T>>::value;
69inline BoundThread GetBoundThreadChecked() {
71 REX_ASSERT(bound.ctx !=
nullptr,
"StackFrame needs a thread state bound to the calling thread");
93 : ctx_(ctx), base_(base), saved_r1_(ctx.r1.u32), previous_(detail::GetInnermostStackFrame()) {
94 detail::GetInnermostStackFrame() =
this;
99 REX_ASSERT(detail::GetInnermostStackFrame() ==
this,
100 "StackFrame closed out of order, an inner frame is still open");
101 ctx_.r1.u32 = saved_r1_;
102 detail::GetInnermostStackFrame() = previous_;
110 template <
typename T>
112 static_assert(std::is_trivially_copyable_v<T>,
113 "StackFrame pushes only trivially copyable types");
114 static_assert(!detail::kHoldsHostPointer<T>,
115 "StackFrame cannot push a pointer or a MappedPtr, it would copy a host address");
116 const u32 address = Allocate(
sizeof(T));
118 std::memset(
static_cast<void*
>(host), 0,
sizeof(T));
128 template <
typename T>
130 static_assert(std::is_trivially_copyable_v<T>,
131 "StackFrame pushes only trivially copyable types");
132 static_assert(!detail::kHoldsHostPointer<T>,
133 "StackFrame cannot push a pointer or a MappedPtr, it would copy a host address");
134 const u32 address = Allocate(
sizeof(T));
136 if constexpr (std::is_arithmetic_v<T> || std::is_enum_v<T>) {
138 std::memcpy(
static_cast<void*
>(host), &swapped,
sizeof(T));
140 std::memcpy(
static_cast<void*
>(host), &value,
sizeof(T));
151 const u32 address = Allocate(
static_cast<u32
>(text.size()) + 1);
153 std::memcpy(host, text.data(), text.size());
154 host[text.size()] =
'\0';
164 const u32 address = Allocate((
static_cast<u32
>(text.size()) + 1) *
sizeof(u16));
166 std::ranges::transform(text, host,
167 [](
char16_t unit) {
return be_u16(
static_cast<u16
>(unit)); });
168 host[text.size()] = u16{0};
178 REX_ASSERT(!bytes.empty(),
"PushBytes needs at least 1 byte");
179 const u32 address = Allocate(
static_cast<u32
>(bytes.size()));
181 std::memcpy(host, bytes.data(), bytes.size());
185 PPCContext& GetContext()
const {
return ctx_; }
195 u32 Allocate(u32 size) {
196 const u32 new_r1 = ctx_.
r1.u32 - detail::stack_align(size);
198 ctx_.
r1.u32 = new_r1;
#define REX_ASSERT(cond,...)
Definition assert.h:84
Definition mapped_ptr.h:29
memory::MappedPtr< char > PushString(std::string_view text)
Definition stack.h:150
memory::MappedPtr< T > Push(const T &value)
Definition stack.h:129
StackFrame(PPCContext &ctx, u8 *base)
Definition stack.h:92
StackFrame()
Definition stack.h:84
memory::MappedPtr< be_u16 > PushWideString(std::u16string_view text)
Definition stack.h:163
~StackFrame()
Definition stack.h:98
u8 * GetBase() const
Definition stack.h:190
memory::MappedPtr< u8 > PushBytes(std::span< const u8 > bytes)
Definition stack.h:177
memory::MappedPtr< T > Push()
Definition stack.h:111
T GuestPtr(u8 *base, u32 guest_address) noexcept
Definition mapped_ptr.h:393
Definition title_runtime.h:33
REX_PPC_API BoundThread GetBoundThread()
void stack_bounds_check(PPCContext &ctx, u8 *base, u32 new_r1)
Definition call.h:748
constexpr T byte_swap(T value) noexcept
Definition types.h:52
PPCRegister r1
Definition context.h:396
Integer types, byte order wrappers and size literals.
Move only function, const propagating pointer and scope guard.