aboutsummaryrefslogtreecommitdiff
path: root/lib/include/syscall.h
diff options
context:
space:
mode:
authorjohannst <johannes.stoelp@gmail.com>2021-03-20 02:34:01 +0100
committerjohannst <johannes.stoelp@gmail.com>2021-03-20 02:34:01 +0100
commitef6a411ce8ff615d65e2be105834c2fdbe557de1 (patch)
tree3336df00ca14b6783486188fed5b4dde5df6cec3 /lib/include/syscall.h
parent3cbf2298b2b3dc24355449131d2e496f8e02b8f5 (diff)
downloaddynld-ef6a411ce8ff615d65e2be105834c2fdbe557de1.tar.gz
dynld-ef6a411ce8ff615d65e2be105834c2fdbe557de1.zip
Split common headers in header/src files.
Diffstat (limited to 'lib/include/syscall.h')
-rw-r--r--lib/include/syscall.h63
1 files changed, 63 insertions, 0 deletions
diff --git a/lib/include/syscall.h b/lib/include/syscall.h
new file mode 100644
index 0000000..4947155
--- /dev/null
+++ b/lib/include/syscall.h
@@ -0,0 +1,63 @@
+// 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"(r12));
+// ```
+//
+// 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 syscall1(n, a1) _syscall1(n, argcast(a1))
+#define syscall3(n, a1, a2, a3) _syscall3(n, argcast(a1), argcast(a2), argcast(a3))
+
+static inline long _syscall1(long n, long a1) {
+ long ret;
+ asm volatile("syscall" : "=a"(ret) : "a"(n), "D"(a1) : "memory");
+ return ret;
+}
+
+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;
+}