aboutsummaryrefslogtreecommitdiff
path: root/lib/darwin/manual-syscall.h
blob: 4d847acc5c92263a21ed1d18bee0403efc1e73c1 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
#pragma once

#define REG(var, reg) register long _##var __asm__(#reg) = var
#define OREG(var, reg) register long var __asm__(#reg)

__attribute__((always_inline))
#if defined(__x86_64__)
static int manual_syscall(long s, long a, long b, long c, long d, long e) {
    if (s < 0)
        s = -s | 1 << 24;
    else
        s |= 2 << 24;
    REG(s, rax); REG(a, rdi); REG(b, rsi); REG(c, rdx); REG(d, rcx);
    OREG(out, rax);
    __asm__ volatile("push %1; syscall; pop %1"
                     : "=r"(out)
                     : "r"(e), "r"(_s), "r"(_a), "r"(_b), "r"(_c), "r"(_d));
    return out;
}
#elif defined(__i386__)
static int manual_syscall(long s, long a, long b, long c, long d, long e) {
    REG(s, eax);
    OREG(out, eax);
    __asm__ volatile("push %6; push %5; push %4; push %3; push %2; push $0;"
                     "mov %%esp, %%ecx;"
                     "call 1f; 1: pop %%edx; add $(2f-1b), %%edx;"
                     "sysenter;"
                     "2: add $(6 * 4), %%esp"
                     : "=r"(out)
                     : "r"(_s), "g"(a), "g"(b), "g"(c), "g"(d), "g"(e)
                     : "edx", "ecx");
    return out;
}
#elif defined(__arm__)
static int manual_syscall(long s, long a, long b, long c, long d, long e) {
    REG(s, r12); REG(a, r0); REG(b, r1); REG(c, r2); REG(d, r3);
    OREG(out, r0);
    __asm__ volatile("push {%1}; svc #0x80; pop {%1}"
                     : "=r"(out)
                     : "r"(e), "r"(_s), "r"(_a), "r"(_b), "r"(_c), "r"(_d));
    return out;
}
#elif defined(__arm64__)
static int manual_syscall(long s, long a, long b, long c, long d, long e) {
    REG(s, x16); REG(a, x0); REG(b, x1); REG(c, x2); REG(d, x3);
    OREG(out, x0);
    __asm__ volatile("str %1, [sp, #-0x10]!\n svc #0x80\n ldr %1, [sp], #0x10"
                     : "=r"(out)
                     : "r"(e), "r"(_s), "r"(_a), "r"(_b), "r"(_c), "r"(_d));
    return out;
}
#else
#error ?
#endif