aboutsummaryrefslogtreecommitdiff
path: root/include/syscall.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/syscall.h')
-rw-r--r--include/syscall.h56
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;
+}