Xenomai  3.1
syscall.h
1 /*
2  * Copyright (C) 2001,2002,2003,2004 Philippe Gerum <rpm@xenomai.org>.
3  *
4  * ARM port
5  * Copyright (C) 2005 Stelian Pop
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
20  */
21 #ifndef _LIB_COBALT_ARM_SYSCALL_H
22 #define _LIB_COBALT_ARM_SYSCALL_H
23 
24 #include <xeno_config.h>
25 #include <errno.h>
26 #include <cobalt/uapi/syscall.h>
27 
28 /*
29  * Some of the following macros have been adapted from Linux's
30  * implementation of the syscall mechanism in <asm-arm/unistd.h>:
31  */
32 #if defined(HAVE_TLS) && __GNUC__ == 4 && __GNUC_MINOR__ >= 3
33 #error TLS support (__thread) is broken with GCC >= 4.3, use --disable-tls when configuring
34 #endif
35 
36 #define LOADARGS_0(syscode, dummy...) \
37  __a0 = (unsigned long) (syscode)
38 #define LOADARGS_1(syscode, arg1) \
39  LOADARGS_0(syscode); \
40  __a1 = (unsigned long) (arg1)
41 #define LOADARGS_2(syscode, arg1, arg2) \
42  LOADARGS_1(syscode, arg1); \
43  __a2 = (unsigned long) (arg2)
44 #define LOADARGS_3(syscode, arg1, arg2, arg3) \
45  LOADARGS_2(syscode, arg1, arg2); \
46  __a3 = (unsigned long) (arg3)
47 #define LOADARGS_4(syscode, arg1, arg2, arg3, arg4) \
48  LOADARGS_3(syscode, arg1, arg2, arg3); \
49  __a4 = (unsigned long) (arg4)
50 #define LOADARGS_5(syscode, arg1, arg2, arg3, arg4, arg5) \
51  LOADARGS_4(syscode, arg1, arg2, arg3, arg4); \
52  __a5 = (unsigned long) (arg5)
53 
54 #define CLOBBER_REGS_0 "r0"
55 #define CLOBBER_REGS_1 CLOBBER_REGS_0, "r1"
56 #define CLOBBER_REGS_2 CLOBBER_REGS_1, "r2"
57 #define CLOBBER_REGS_3 CLOBBER_REGS_2, "r3"
58 #define CLOBBER_REGS_4 CLOBBER_REGS_3, "r4"
59 #define CLOBBER_REGS_5 CLOBBER_REGS_4, "r5"
60 
61 #define LOADREGS_0 __r0 = __a0
62 #define LOADREGS_1 LOADREGS_0; __r1 = __a1
63 #define LOADREGS_2 LOADREGS_1; __r2 = __a2
64 #define LOADREGS_3 LOADREGS_2; __r3 = __a3
65 #define LOADREGS_4 LOADREGS_3; __r4 = __a4
66 #define LOADREGS_5 LOADREGS_4; __r5 = __a5
67 
68 #define ASM_INDECL_0 \
69  unsigned long __a0; register unsigned long __r0 __asm__ ("r0");
70 #define ASM_INDECL_1 ASM_INDECL_0; \
71  unsigned long __a1; register unsigned long __r1 __asm__ ("r1")
72 #define ASM_INDECL_2 ASM_INDECL_1; \
73  unsigned long __a2; register unsigned long __r2 __asm__ ("r2")
74 #define ASM_INDECL_3 ASM_INDECL_2; \
75  unsigned long __a3; register unsigned long __r3 __asm__ ("r3")
76 #define ASM_INDECL_4 ASM_INDECL_3; \
77  unsigned long __a4; register unsigned long __r4 __asm__ ("r4")
78 #define ASM_INDECL_5 ASM_INDECL_4; \
79  unsigned long __a5; register unsigned long __r5 __asm__ ("r5")
80 
81 #define ASM_INPUT_0 "0" (__r0)
82 #define ASM_INPUT_1 ASM_INPUT_0, "r" (__r1)
83 #define ASM_INPUT_2 ASM_INPUT_1, "r" (__r2)
84 #define ASM_INPUT_3 ASM_INPUT_2, "r" (__r3)
85 #define ASM_INPUT_4 ASM_INPUT_3, "r" (__r4)
86 #define ASM_INPUT_5 ASM_INPUT_4, "r" (__r5)
87 
88 #define __sys2(x) #x
89 #define __sys1(x) __sys2(x)
90 
91 #ifdef __ARM_EABI__
92 #define __SYS_REG , "r7"
93 #define __SYS_REG_DECL register unsigned long __r7 __asm__ ("r7")
94 #define __SYS_REG_SET __r7 = XENO_ARM_SYSCALL
95 #define __SYS_REG_INPUT ,"r" (__r7)
96 #define __SYS_CALLOP "swi\t0"
97 #else
98 #define __SYS_REG
99 #define __SYS_REG_DECL
100 #define __SYS_REG_SET
101 #define __SYS_REG_INPUT
102 #define __NR_OABI_SYSCALL_BASE 0x900000
103 #define __SYS_CALLOP "swi\t" __sys1(__NR_OABI_SYSCALL_BASE + XENO_ARM_SYSCALL) ""
104 #endif
105 
106 #define XENOMAI_DO_SYSCALL(nr, op, args...) \
107  ({ \
108  ASM_INDECL_##nr; \
109  __SYS_REG_DECL; \
110  LOADARGS_##nr(__xn_syscode(op), args); \
111  __asm__ __volatile__ ("" : /* */ : /* */ : \
112  CLOBBER_REGS_##nr __SYS_REG); \
113  LOADREGS_##nr; \
114  __SYS_REG_SET; \
115  __asm__ __volatile__ ( \
116  __SYS_CALLOP \
117  : "=r" (__r0) \
118  : ASM_INPUT_##nr __SYS_REG_INPUT \
119  : "memory"); \
120  (int) __r0; \
121  })
122 
123 #define XENOMAI_SYSCALL0(op) \
124  XENOMAI_DO_SYSCALL(0,op)
125 #define XENOMAI_SYSCALL1(op,a1) \
126  XENOMAI_DO_SYSCALL(1,op,a1)
127 #define XENOMAI_SYSCALL2(op,a1,a2) \
128  XENOMAI_DO_SYSCALL(2,op,a1,a2)
129 #define XENOMAI_SYSCALL3(op,a1,a2,a3) \
130  XENOMAI_DO_SYSCALL(3,op,a1,a2,a3)
131 #define XENOMAI_SYSCALL4(op,a1,a2,a3,a4) \
132  XENOMAI_DO_SYSCALL(4,op,a1,a2,a3,a4)
133 #define XENOMAI_SYSCALL5(op,a1,a2,a3,a4,a5) \
134  XENOMAI_DO_SYSCALL(5,op,a1,a2,a3,a4,a5)
135 #define XENOMAI_SYSBIND(breq) \
136  XENOMAI_DO_SYSCALL(1,sc_cobalt_bind,breq)
137 
138 #endif /* !_LIB_COBALT_ARM_SYSCALL_H */