|
|
- #pragma once
- #include <cstdint>
- #include <cstddef>
- #include <gp/containers/buffer.hpp>
-
- #if defined(__x86_64__)
- #if defined(__linux__)
-
- constexpr bool is_x86_64_linux = true;
- #else
- constexpr bool is_x86_64_linux = false;
- #endif
- #else
- constexpr bool is_x86_64_linux = false;
- #endif
-
- template<int64_t syscall_id, int arg_count>
- struct syscall;
-
- template<int64_t syscall_id>
- requires is_x86_64_linux
- struct syscall<syscall_id, 1> {
- int64_t operator()(int64_t p1) const {
- int64_t ret;
- asm volatile
- (
- "syscall"
- : "=a" (ret)
- : "0"(syscall_id), "D"(p1)
- : "rcx", "r11", "memory"
- );
- return ret;
- }
- };
-
- template<int64_t syscall_id>
- requires is_x86_64_linux
- struct syscall<syscall_id, 2> {
- int64_t operator()(int64_t p1,int64_t p2) const {
- int64_t ret;
- asm volatile
- (
- "syscall"
- : "=a" (ret)
- : "0"(syscall_id), "D"(p1), "S"(p2)
- : "rcx", "r11", "memory"
- );
- return ret;
- }
- };
-
- template<int64_t syscall_id>
- requires is_x86_64_linux
- struct syscall<syscall_id, 3> {
- int64_t operator()(int64_t p1,int64_t p2,int64_t p3) const {
- int64_t ret;
- asm volatile
- (
- "syscall"
- : "=a" (ret)
- : "0"(syscall_id), "D"(p1), "S"(p2), "d"(p3)
- : "rcx", "r11", "memory"
- );
- return ret;
- }
- };
-
- template<int64_t syscall_id>
- requires is_x86_64_linux
- struct syscall<syscall_id, 4> {
- int64_t operator()(int64_t p1,int64_t p2,int64_t p3,int64_t p4) const {
- int64_t ret;
- register long r10 asm("r10") = p4;
- asm volatile
- (
- "syscall"
- : "=a" (ret)
- : "0"(syscall_id), "D"(p1), "S"(p2), "d"(p3), "r"(r10)
- : "rcx", "r11", "memory"
- );
- return ret;
- }
- };
-
- template<int64_t syscall_id>
- requires is_x86_64_linux
- struct syscall<syscall_id, 5> {
- int64_t operator()(int64_t p1,int64_t p2,int64_t p3,int64_t p4,int64_t p5) const {
- int64_t ret;
- register long r10 asm("r10") = p4;
- register long r8 asm("r8") = p5;
- asm volatile
- (
- "syscall"
- : "=a" (ret)
- : "0"(syscall_id), "D"(p1), "S"(p2), "d"(p3), "r"(r10), "r"(r8)
- : "rcx", "r11", "memory"
- );
- return ret;
- }
- };
-
- template<int64_t syscall_id>
- requires is_x86_64_linux
- struct syscall<syscall_id, 6> {
- int64_t operator()(int64_t p1,int64_t p2,int64_t p3,int64_t p4,int64_t p5,int64_t p6) const {
- int64_t ret;
- register long r10 asm("r10") = p4;
- register long r8 asm("r8") = p5;
- register long r9 asm("r9") = p6;
- asm volatile
- (
- "syscall"
- : "=a" (ret)
- : "0"(syscall_id), "D"(p1), "S"(p2), "d"(p3), "r"(r10), "r"(r8), "r"(r9)
- : "rcx", "r11", "memory"
- );
- return ret;
- }
- };
-
- constexpr auto _read = syscall<0, 3>{};
- constexpr auto _write = syscall<1, 3>{};
- constexpr auto _mmap = syscall<9, 6>{};
- constexpr auto _munmap = syscall<11, 2>{};
- constexpr auto _exit = syscall<60, 1>{};
-
- inline int read(int fd, char* buffer, size_t sz) {
- return _read((int64_t)fd, (int64_t)buffer, (int64_t)sz);
- }
-
- inline int write(int fd, char* buffer, size_t sz) {
- return _write((int64_t)fd, (int64_t)buffer, (int64_t)sz);
- }
-
- inline void* mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset) {
- return (void*)_mmap((int64_t)addr, (int64_t)length, (int64_t)prot, (int64_t)flags, (int64_t)fd, (int64_t)offset);
- }
-
- inline int munmap(void *addr, size_t length) {
- return _munmap((int64_t)addr, (int64_t)length);
- }
-
- extern "C" {
- /// Yes, __attribute__((__noreturn__)), not [[noreturn]], because some God forsaken potato decided that those attributes are not the attributes I am looking for
- inline __attribute__ ((__noreturn__)) void exit(int status) {
- _exit((int64_t)status);
- while(true);
- }
-
- }
-
- inline int read(int fd, gp::buffer<char> buffer) {
- return _read((int64_t)fd, (int64_t)buffer.begin().data, (int64_t)buffer.size());
- }
-
- inline int write(int fd, gp::buffer<char> buffer) {
- return _write((int64_t)fd, (int64_t)buffer.begin().data, (int64_t)buffer.size());
- }
|