x32 port (diff against vanilla x86_64)
[musl] / arch / x32 / syscall_arch.h
1 #define __SYSCALL_LL_E(x) (x)
2 #define __SYSCALL_LL_O(x) (x)
3
4 #define __scc(X) sizeof(1?(X):0ULL) < 8 ? (unsigned long) (X) : (long long) (X)
5 #define syscall_arg_t long long
6 struct __timespec { long long tv_sec; long tv_nsec; };
7 struct __timespec_kernel { long long tv_sec; long long tv_nsec; };
8 #define __tsc(X) ((struct __timespec*)(unsigned long)(X))
9
10 static __inline long __syscall0(long long n)
11 {
12         unsigned long ret;
13         __asm__ __volatile__ ("syscall" : "=a"(ret) : "a"(n) : "rcx", "r11", "memory");
14         return ret;
15 }
16
17 static __inline long __syscall1(long long n, long long a1)
18 {
19         unsigned long ret;
20         __asm__ __volatile__ ("syscall" : "=a"(ret) : "a"(n), "D"(a1) : "rcx", "r11", "memory");
21         return ret;
22 }
23
24 static __inline long __syscall2(long long n, long long a1, long long a2)
25 {
26         unsigned long ret;
27         struct __timespec *ts2 = 0;
28         switch (n) {
29         case SYS_nanosleep:
30                 if(a1) a1 = (unsigned long) (&(struct __timespec_kernel) {
31                 .tv_sec = __tsc(a1)->tv_sec, .tv_nsec = __tsc(a1)->tv_nsec});
32                 break;
33         case SYS_clock_settime:
34                 if(a2) a2 = (unsigned long) (&(struct __timespec_kernel) {
35                 .tv_sec = __tsc(a2)->tv_sec, .tv_nsec = __tsc(a2)->tv_nsec});
36         }
37         __asm__ __volatile__ ("syscall" : "=a"(ret) : "a"(n), "D"(a1), "S"(a2)
38                                         : "rcx", "r11", "memory");
39         return ret;
40 }
41
42 static __inline long __syscall3(long long n, long long a1, long long a2, long long a3)
43 {
44         unsigned long ret;
45         __asm__ __volatile__ ("syscall" : "=a"(ret) : "a"(n), "D"(a1), "S"(a2),
46                                                   "d"(a3) : "rcx", "r11", "memory");
47         return ret;
48 }
49
50 static __inline long __syscall4(long long n, long long a1, long long a2, long long a3,
51                                      long long a4)
52 {
53         unsigned long ret;
54         register long long r10 __asm__("r10") = a4;
55         switch (n) {
56         case SYS_futex:
57                 if((a2 & (~128 /* FUTEX_PRIVATE_FLAG */)) == 0 /* FUTEX_WAIT */) {
58                         if(r10) r10 = (unsigned long) (&(struct __timespec_kernel) {
59                         .tv_sec = __tsc(r10)->tv_sec, .tv_nsec = __tsc(r10)->tv_nsec});
60                 }
61                 break;
62         case SYS_utimensat:
63                 if(a3) a3 = (unsigned long) ((struct __timespec_kernel[2]) {
64                 [0] = {.tv_sec = __tsc(a3)[0].tv_sec, .tv_nsec = __tsc(a3)[0].tv_nsec},
65                 [1] = {.tv_sec = __tsc(a3)[1].tv_sec, .tv_nsec = __tsc(a3)[1].tv_nsec},
66                 });
67                 break;
68         case SYS_clock_nanosleep:
69         case SYS_rt_sigtimedwait: case SYS_ppoll:
70                 if(a3) a3 = (unsigned long) (&(struct __timespec_kernel) {
71                 .tv_sec = __tsc(a3)->tv_sec, .tv_nsec = __tsc(a3)->tv_nsec});
72         }
73         __asm__ __volatile__ ("syscall" : "=a"(ret) : "a"(n), "D"(a1), "S"(a2),
74                                           "d"(a3), "r"(r10): "rcx", "r11", "memory");
75         return ret;
76 }
77
78 static __inline long __syscall5(long long n, long long a1, long long a2, long long a3,
79                                      long long a4, long long a5)
80 {
81         unsigned long ret;
82         register long long r10 __asm__("r10") = a4;
83         register long long r8 __asm__("r8") = a5;
84         switch (n) {
85         case SYS_futex:
86                 if((a2 & (~128 /* FUTEX_PRIVATE_FLAG */)) == 0 /* FUTEX_WAIT */) {
87                         if(r10) r10 = (unsigned long) (&(struct __timespec_kernel) {
88                         .tv_sec = __tsc(r10)->tv_sec, .tv_nsec = __tsc(r10)->tv_nsec});
89                 }
90                 break;
91         case SYS_mq_timedsend: case SYS_mq_timedreceive:
92                 if(r8) r8 = (unsigned long) (&(struct __timespec_kernel) {
93                 .tv_sec = __tsc(r8)->tv_sec, .tv_nsec = __tsc(r8)->tv_nsec});
94         }
95         __asm__ __volatile__ ("syscall" : "=a"(ret) : "a"(n), "D"(a1), "S"(a2),
96                                           "d"(a3), "r"(r10), "r"(r8) : "rcx", "r11", "memory");
97         return ret;
98 }
99
100 static __inline long __syscall6(long long n, long long a1, long long a2, long long a3,
101                                      long long a4, long long a5, long long a6)
102 {
103         unsigned long ret;
104         register long long r10 __asm__("r10") = a4;
105         register long long r8 __asm__("r8") = a5;
106         register long long r9 __asm__("r9") = a6;
107         switch (n) {
108         case SYS_futex:
109                 if((a2 & (~128 /* FUTEX_PRIVATE_FLAG */)) == 0 /* FUTEX_WAIT */) {
110                         if(r10) r10 = (unsigned long) (&(struct __timespec_kernel) {
111                         .tv_sec = __tsc(r10)->tv_sec, .tv_nsec = __tsc(r10)->tv_nsec});
112                 }
113                 break;
114         case SYS_pselect6:
115                 if(r8) r8 = (unsigned long) (&(struct __timespec_kernel) {
116                 .tv_sec = __tsc(r8)->tv_sec, .tv_nsec = __tsc(r8)->tv_nsec});
117         }
118         __asm__ __volatile__ ("syscall" : "=a"(ret) : "a"(n), "D"(a1), "S"(a2),
119                                           "d"(a3), "r"(r10), "r"(r8), "r"(r9) : "rcx", "r11", "memory");
120         return ret;
121 }