blob: 0460ede4fd00bb8665e41c1249930ebd0ce7f29f (
plain) (
tree)
|
|
// 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;
}
|