diff options
Diffstat (limited to 'include/syscall.h')
-rw-r--r-- | include/syscall.h | 56 |
1 files changed, 56 insertions, 0 deletions
diff --git a/include/syscall.h b/include/syscall.h new file mode 100644 index 0000000..0460ede --- /dev/null +++ b/include/syscall.h @@ -0,0 +1,56 @@ +// Copyright (c) 2020 Johannes Stoelp + +#pragma once + +#if !defined(__linux__) || !defined(__x86_64__) +# error "Only supported on linux(x86_64)!" +#endif + +// Inline ASM +// Syntax: +// asm asm-qualifiers (AssemblerTemplate : OutputOperands : InputOperands : Clobbers) +// +// Output operand constraints: +// = | operand (variable) is written to by this instruction +// + | operand (variable) is written to / read from by this instruction +// +// Input/Output operand constraints: +// r | allocate general purpose register +// +// Machine specific constraints (x86_64): +// a | a register (eg rax) +// d | d register (eg rdx) +// D | di register (eg rdi) +// S | si register (eg rsi) +// +// Local register variables: +// In case a specific register is required which can not be specified via a +// machine specific constraint. +// ```c +// register long r12 asm ("r12") = 42; +// asm("nop" : : "r"(r10)); +// ``` +// +// Reference: +// https://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html +// https://gcc.gnu.org/onlinedocs/gcc/Machine-Constraints.html#Machine-Constraints +// https://gcc.gnu.org/onlinedocs/gcc/Local-Register-Variables.html + +// Linux syscall ABI +// x86-64 +// #syscall: rax +// ret : rax +// instr : syscall +// args : rdi rsi rdx r10 r8 r9 +// +// Reference: +// syscall(2) + +#define argcast(A) ((long)(A)) +#define syscall3(n,a1,a2,a3) _syscall3(n, argcast(a1), argcast(a2), argcast(a3)) + +static inline long _syscall3(long n, long a1, long a2, long a3) { + long ret; + asm volatile("syscall" : "=a"(ret) : "a"(n), "D"(a1), "S"(a2), "d"(a3) : "memory"); + return ret; +} |