syscalls.h 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257
  1. /* Copyright (C) 1992, 1995, 1996, 2000, 2003, 2004, 2006
  2. Free Software Foundation, Inc.
  3. This file is part of the GNU C Library.
  4. Contributed by Brendan Kehoe (brendan@zen.org).
  5. The GNU C Library is free software; you can redistribute it and/or
  6. modify it under the terms of the GNU Lesser General Public
  7. License as published by the Free Software Foundation; either
  8. version 2.1 of the License, or (at your option) any later version.
  9. The GNU C Library is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  12. Lesser General Public License for more details.
  13. You should have received a copy of the GNU Lesser General Public
  14. License along with the GNU C Library; if not, write to the Free
  15. Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
  16. 02111-1307 USA. */
  17. #ifndef _BITS_SYSCALLS_H
  18. #define _BITS_SYSCALLS_H
  19. #ifndef _SYSCALL_H
  20. # error "Never use <bits/syscalls.h> directly; include <sys/syscall.h> instead."
  21. #endif
  22. #ifndef __ASSEMBLER__
  23. #define INLINE_SYSCALL_NCS(name, nr, args...) \
  24. ({ \
  25. long _sc_ret, _sc_err; \
  26. inline_syscall##nr(name, args); \
  27. if (__builtin_expect (_sc_err, 0)) \
  28. { \
  29. __set_errno (_sc_ret); \
  30. _sc_ret = -1L; \
  31. } \
  32. _sc_ret; \
  33. })
  34. #define INTERNAL_SYSCALL_NCS(name, err_out, nr, args...) \
  35. ({ \
  36. long _sc_ret, _sc_err; \
  37. inline_syscall##nr(name, args); \
  38. err_out = _sc_err; \
  39. _sc_ret; \
  40. })
  41. #define INTERNAL_SYSCALL_DECL(err) long int err
  42. #define INTERNAL_SYSCALL_ERROR_P(val, err) err
  43. #define INTERNAL_SYSCALL_ERRNO(val, err) val
  44. #define inline_syscall_clobbers \
  45. "$1", "$2", "$3", "$4", "$5", "$6", "$7", "$8", \
  46. "$22", "$23", "$24", "$25", "$27", "$28", "memory"
  47. /* If TLS is in use, we have a conflict between the PAL_rduniq primitive,
  48. as modeled within GCC, and explicit use of the R0 register. If we use
  49. the register via the asm, the scheduler may place the PAL_rduniq insn
  50. before we've copied the data from R0 into _sc_ret. If this happens
  51. we'll get a reload abort, since R0 is live at the same time it is
  52. needed for the PAL_rduniq.
  53. Solve this by using the "v" constraint instead of an asm for the syscall
  54. output. We don't do this unconditionally to allow compilation with
  55. older compilers. */
  56. #ifdef HAVE___THREAD
  57. #define inline_syscall_r0_asm
  58. #define inline_syscall_r0_out_constraint "=v"
  59. #else
  60. #define inline_syscall_r0_asm __asm__("$0")
  61. #define inline_syscall_r0_out_constraint "=r"
  62. #endif
  63. /* It is moderately important optimization-wise to limit the lifetime
  64. of the hard-register variables as much as possible. Thus we copy
  65. in/out as close to the asm as possible. */
  66. #define inline_syscall0(name, args...) \
  67. { \
  68. register long _sc_0 inline_syscall_r0_asm; \
  69. register long _sc_19 __asm__("$19"); \
  70. \
  71. _sc_0 = name; \
  72. __asm__ __volatile__ \
  73. ("callsys # %0 %1 <= %2" \
  74. : inline_syscall_r0_out_constraint (_sc_0), \
  75. "=r"(_sc_19) \
  76. : "0"(_sc_0) \
  77. : inline_syscall_clobbers, \
  78. "$16", "$17", "$18", "$20", "$21"); \
  79. _sc_ret = _sc_0, _sc_err = _sc_19; \
  80. }
  81. #define inline_syscall1(name,arg1) \
  82. { \
  83. register long _sc_0 inline_syscall_r0_asm; \
  84. register long _sc_16 __asm__("$16"); \
  85. register long _sc_19 __asm__("$19"); \
  86. register long _tmp_16 = (long) (arg1); \
  87. \
  88. _sc_0 = name; \
  89. _sc_16 = _tmp_16; \
  90. __asm__ __volatile__ \
  91. ("callsys # %0 %1 <= %2 %3" \
  92. : inline_syscall_r0_out_constraint (_sc_0), \
  93. "=r"(_sc_19), "=r"(_sc_16) \
  94. : "0"(_sc_0), "2"(_sc_16) \
  95. : inline_syscall_clobbers, \
  96. "$17", "$18", "$20", "$21"); \
  97. _sc_ret = _sc_0, _sc_err = _sc_19; \
  98. }
  99. #define inline_syscall2(name,arg1,arg2) \
  100. { \
  101. register long _sc_0 inline_syscall_r0_asm; \
  102. register long _sc_16 __asm__("$16"); \
  103. register long _sc_17 __asm__("$17"); \
  104. register long _sc_19 __asm__("$19"); \
  105. register long _tmp_16 = (long) (arg1); \
  106. register long _tmp_17 = (long) (arg2); \
  107. \
  108. _sc_0 = name; \
  109. _sc_16 = _tmp_16; \
  110. _sc_17 = _tmp_17; \
  111. __asm__ __volatile__ \
  112. ("callsys # %0 %1 <= %2 %3 %4" \
  113. : inline_syscall_r0_out_constraint (_sc_0), \
  114. "=r"(_sc_19), "=r"(_sc_16), "=r"(_sc_17) \
  115. : "0"(_sc_0), "2"(_sc_16), "3"(_sc_17) \
  116. : inline_syscall_clobbers, \
  117. "$18", "$20", "$21"); \
  118. _sc_ret = _sc_0, _sc_err = _sc_19; \
  119. }
  120. #define inline_syscall3(name,arg1,arg2,arg3) \
  121. { \
  122. register long _sc_0 inline_syscall_r0_asm; \
  123. register long _sc_16 __asm__("$16"); \
  124. register long _sc_17 __asm__("$17"); \
  125. register long _sc_18 __asm__("$18"); \
  126. register long _sc_19 __asm__("$19"); \
  127. register long _tmp_16 = (long) (arg1); \
  128. register long _tmp_17 = (long) (arg2); \
  129. register long _tmp_18 = (long) (arg3); \
  130. \
  131. _sc_0 = name; \
  132. _sc_16 = _tmp_16; \
  133. _sc_17 = _tmp_17; \
  134. _sc_18 = _tmp_18; \
  135. __asm__ __volatile__ \
  136. ("callsys # %0 %1 <= %2 %3 %4 %5" \
  137. : inline_syscall_r0_out_constraint (_sc_0), \
  138. "=r"(_sc_19), "=r"(_sc_16), "=r"(_sc_17), \
  139. "=r"(_sc_18) \
  140. : "0"(_sc_0), "2"(_sc_16), "3"(_sc_17), \
  141. "4"(_sc_18) \
  142. : inline_syscall_clobbers, "$20", "$21"); \
  143. _sc_ret = _sc_0, _sc_err = _sc_19; \
  144. }
  145. #define inline_syscall4(name,arg1,arg2,arg3,arg4) \
  146. { \
  147. register long _sc_0 inline_syscall_r0_asm; \
  148. register long _sc_16 __asm__("$16"); \
  149. register long _sc_17 __asm__("$17"); \
  150. register long _sc_18 __asm__("$18"); \
  151. register long _sc_19 __asm__("$19"); \
  152. register long _tmp_16 = (long) (arg1); \
  153. register long _tmp_17 = (long) (arg2); \
  154. register long _tmp_18 = (long) (arg3); \
  155. register long _tmp_19 = (long) (arg4); \
  156. \
  157. _sc_0 = name; \
  158. _sc_16 = _tmp_16; \
  159. _sc_17 = _tmp_17; \
  160. _sc_18 = _tmp_18; \
  161. _sc_19 = _tmp_19; \
  162. __asm__ __volatile__ \
  163. ("callsys # %0 %1 <= %2 %3 %4 %5 %6" \
  164. : inline_syscall_r0_out_constraint (_sc_0), \
  165. "=r"(_sc_19), "=r"(_sc_16), "=r"(_sc_17), \
  166. "=r"(_sc_18) \
  167. : "0"(_sc_0), "2"(_sc_16), "3"(_sc_17), \
  168. "4"(_sc_18), "1"(_sc_19) \
  169. : inline_syscall_clobbers, "$20", "$21"); \
  170. _sc_ret = _sc_0, _sc_err = _sc_19; \
  171. }
  172. #define inline_syscall5(name,arg1,arg2,arg3,arg4,arg5) \
  173. { \
  174. register long _sc_0 inline_syscall_r0_asm; \
  175. register long _sc_16 __asm__("$16"); \
  176. register long _sc_17 __asm__("$17"); \
  177. register long _sc_18 __asm__("$18"); \
  178. register long _sc_19 __asm__("$19"); \
  179. register long _sc_20 __asm__("$20"); \
  180. register long _tmp_16 = (long) (arg1); \
  181. register long _tmp_17 = (long) (arg2); \
  182. register long _tmp_18 = (long) (arg3); \
  183. register long _tmp_19 = (long) (arg4); \
  184. register long _tmp_20 = (long) (arg5); \
  185. \
  186. _sc_0 = name; \
  187. _sc_16 = _tmp_16; \
  188. _sc_17 = _tmp_17; \
  189. _sc_18 = _tmp_18; \
  190. _sc_19 = _tmp_19; \
  191. _sc_20 = _tmp_20; \
  192. __asm__ __volatile__ \
  193. ("callsys # %0 %1 <= %2 %3 %4 %5 %6 %7" \
  194. : inline_syscall_r0_out_constraint (_sc_0), \
  195. "=r"(_sc_19), "=r"(_sc_16), "=r"(_sc_17), \
  196. "=r"(_sc_18), "=r"(_sc_20) \
  197. : "0"(_sc_0), "2"(_sc_16), "3"(_sc_17), \
  198. "4"(_sc_18), "1"(_sc_19), "5"(_sc_20) \
  199. : inline_syscall_clobbers, "$21"); \
  200. _sc_ret = _sc_0, _sc_err = _sc_19; \
  201. }
  202. #define inline_syscall6(name,arg1,arg2,arg3,arg4,arg5,arg6) \
  203. { \
  204. register long _sc_0 inline_syscall_r0_asm; \
  205. register long _sc_16 __asm__("$16"); \
  206. register long _sc_17 __asm__("$17"); \
  207. register long _sc_18 __asm__("$18"); \
  208. register long _sc_19 __asm__("$19"); \
  209. register long _sc_20 __asm__("$20"); \
  210. register long _sc_21 __asm__("$21"); \
  211. register long _tmp_16 = (long) (arg1); \
  212. register long _tmp_17 = (long) (arg2); \
  213. register long _tmp_18 = (long) (arg3); \
  214. register long _tmp_19 = (long) (arg4); \
  215. register long _tmp_20 = (long) (arg5); \
  216. register long _tmp_21 = (long) (arg6); \
  217. \
  218. _sc_0 = name; \
  219. _sc_16 = _tmp_16; \
  220. _sc_17 = _tmp_17; \
  221. _sc_18 = _tmp_18; \
  222. _sc_19 = _tmp_19; \
  223. _sc_20 = _tmp_20; \
  224. _sc_21 = _tmp_21; \
  225. __asm__ __volatile__ \
  226. ("callsys # %0 %1 <= %2 %3 %4 %5 %6 %7 %8" \
  227. : inline_syscall_r0_out_constraint (_sc_0), \
  228. "=r"(_sc_19), "=r"(_sc_16), "=r"(_sc_17), \
  229. "=r"(_sc_18), "=r"(_sc_20), "=r"(_sc_21) \
  230. : "0"(_sc_0), "2"(_sc_16), "3"(_sc_17), "4"(_sc_18), \
  231. "1"(_sc_19), "5"(_sc_20), "6"(_sc_21) \
  232. : inline_syscall_clobbers); \
  233. _sc_ret = _sc_0, _sc_err = _sc_19; \
  234. }
  235. #endif /* __ASSEMBLER__ */
  236. #endif /* _BITS_SYSCALLS_H */