#pragma once
|
|
|
|
#include "gp/containers/buffer.hpp"
|
|
|
|
#include <cstdint>
|
|
|
|
#define no_inline_decl(a) __attribute__((noinline)) a
|
|
|
|
namespace gp{
|
|
namespace system {
|
|
namespace specifics {
|
|
struct platform_data {
|
|
platform_data() = default;
|
|
|
|
platform_data(gp::buffer<char> stack_str)
|
|
: stack_ptr((stack_str.end()-16).data)
|
|
, base_ptr(stack_ptr)
|
|
{}
|
|
|
|
uint64_t rbx, r12, r13, r14, r15;
|
|
|
|
void* stack_ptr;
|
|
void* base_ptr;
|
|
|
|
void pull() __attribute__((always_inline))
|
|
{
|
|
__asm__ __volatile__(
|
|
"movq %%rsp, %0\n"
|
|
"movq %%rbp, %1\n"
|
|
"movq %%rbx, %2\n"
|
|
"movq %%r12, %3\n"
|
|
"movq %%r13, %4\n"
|
|
"movq %%r14, %5\n"
|
|
"movq %%r15, %6\n"
|
|
: "=m"(stack_ptr)
|
|
, "=m"(base_ptr)
|
|
, "=m"(rbx)
|
|
, "=m"(r12)
|
|
, "=m"(r13)
|
|
, "=m"(r14)
|
|
, "=m"(r15)
|
|
);
|
|
}
|
|
|
|
void* push(void* location) __attribute__((always_inline))
|
|
{
|
|
volatile void* volatile tmp = static_cast<char*>(stack_ptr) - sizeof(void*);
|
|
*static_cast<volatile void* volatile * volatile>(tmp) = location;
|
|
__asm__ __volatile__(
|
|
"movq %1, %%rsp\n"
|
|
"movq %2, %%rbp\n"
|
|
"movq %3, %%rbx\n"
|
|
"movq %4, %%r12\n"
|
|
"movq %5, %%r13\n"
|
|
"movq %6, %%r14\n"
|
|
"movq %7, %%r15\n"
|
|
"popq %0\n"
|
|
: "+r"(location)
|
|
: "m"(tmp)
|
|
, "m"(base_ptr)
|
|
, "m"(rbx)
|
|
, "m"(r12)
|
|
, "m"(r13)
|
|
, "m"(r14)
|
|
, "m"(r15)
|
|
: "memory"
|
|
);
|
|
return location;
|
|
}
|
|
};
|
|
}
|
|
}
|
|
}
|