syscalls.h 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259
  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, see
  15. <http://www.gnu.org/licenses/>. */
  16. #ifndef _BITS_SYSCALLS_H
  17. #define _BITS_SYSCALLS_H
  18. #ifndef _SYSCALL_H
  19. # error "Never use <bits/syscalls.h> directly; include <sys/syscall.h> instead."
  20. #endif
  21. #ifndef __ASSEMBLER__
  22. #define INLINE_SYSCALL_NCS(name, nr, args...) \
  23. (__extension__ \
  24. ({ \
  25. long _sc_ret, _sc_err; \
  26. inline_syscall##nr(name, args); \
  27. if (unlikely (_sc_err)) \
  28. { \
  29. __set_errno (_sc_ret); \
  30. _sc_ret = -1L; \
  31. } \
  32. _sc_ret; \
  33. }) \
  34. )
  35. #define INTERNAL_SYSCALL_NCS(name, err_out, nr, args...) \
  36. (__extension__ \
  37. ({ \
  38. long _sc_ret, _sc_err; \
  39. inline_syscall##nr(name, args); \
  40. err_out = _sc_err; \
  41. _sc_ret; \
  42. }) \
  43. )
  44. #define INTERNAL_SYSCALL_DECL(err) long int err
  45. #define INTERNAL_SYSCALL_ERROR_P(val, err) err
  46. #define INTERNAL_SYSCALL_ERRNO(val, err) val
  47. #define inline_syscall_clobbers \
  48. "$1", "$2", "$3", "$4", "$5", "$6", "$7", "$8", \
  49. "$22", "$23", "$24", "$25", "$27", "$28", "memory"
  50. /* If TLS is in use, we have a conflict between the PAL_rduniq primitive,
  51. as modeled within GCC, and explicit use of the R0 register. If we use
  52. the register via the asm, the scheduler may place the PAL_rduniq insn
  53. before we've copied the data from R0 into _sc_ret. If this happens
  54. we'll get a reload abort, since R0 is live at the same time it is
  55. needed for the PAL_rduniq.
  56. Solve this by using the "v" constraint instead of an asm for the syscall
  57. output. We don't do this unconditionally to allow compilation with
  58. older compilers. */
  59. #ifdef HAVE___THREAD
  60. #define inline_syscall_r0_asm
  61. #define inline_syscall_r0_out_constraint "=v"
  62. #else
  63. #define inline_syscall_r0_asm __asm__("$0")
  64. #define inline_syscall_r0_out_constraint "=r"
  65. #endif
  66. /* It is moderately important optimization-wise to limit the lifetime
  67. of the hard-register variables as much as possible. Thus we copy
  68. in/out as close to the asm as possible. */
  69. #define inline_syscall0(name, args...) \
  70. { \
  71. register long _sc_0 inline_syscall_r0_asm; \
  72. register long _sc_19 __asm__("$19"); \
  73. \
  74. _sc_0 = name; \
  75. __asm__ __volatile__ \
  76. ("callsys # %0 %1 <= %2" \
  77. : inline_syscall_r0_out_constraint (_sc_0), \
  78. "=r"(_sc_19) \
  79. : "0"(_sc_0) \
  80. : inline_syscall_clobbers, \
  81. "$16", "$17", "$18", "$20", "$21"); \
  82. _sc_ret = _sc_0, _sc_err = _sc_19; \
  83. }
  84. #define inline_syscall1(name,arg1) \
  85. { \
  86. register long _sc_0 inline_syscall_r0_asm; \
  87. register long _sc_16 __asm__("$16"); \
  88. register long _sc_19 __asm__("$19"); \
  89. register long _tmp_16 = (long) (arg1); \
  90. \
  91. _sc_0 = name; \
  92. _sc_16 = _tmp_16; \
  93. __asm__ __volatile__ \
  94. ("callsys # %0 %1 <= %2 %3" \
  95. : inline_syscall_r0_out_constraint (_sc_0), \
  96. "=r"(_sc_19), "=r"(_sc_16) \
  97. : "0"(_sc_0), "2"(_sc_16) \
  98. : inline_syscall_clobbers, \
  99. "$17", "$18", "$20", "$21"); \
  100. _sc_ret = _sc_0, _sc_err = _sc_19; \
  101. }
  102. #define inline_syscall2(name,arg1,arg2) \
  103. { \
  104. register long _sc_0 inline_syscall_r0_asm; \
  105. register long _sc_16 __asm__("$16"); \
  106. register long _sc_17 __asm__("$17"); \
  107. register long _sc_19 __asm__("$19"); \
  108. register long _tmp_16 = (long) (arg1); \
  109. register long _tmp_17 = (long) (arg2); \
  110. \
  111. _sc_0 = name; \
  112. _sc_16 = _tmp_16; \
  113. _sc_17 = _tmp_17; \
  114. __asm__ __volatile__ \
  115. ("callsys # %0 %1 <= %2 %3 %4" \
  116. : inline_syscall_r0_out_constraint (_sc_0), \
  117. "=r"(_sc_19), "=r"(_sc_16), "=r"(_sc_17) \
  118. : "0"(_sc_0), "2"(_sc_16), "3"(_sc_17) \
  119. : inline_syscall_clobbers, \
  120. "$18", "$20", "$21"); \
  121. _sc_ret = _sc_0, _sc_err = _sc_19; \
  122. }
  123. #define inline_syscall3(name,arg1,arg2,arg3) \
  124. { \
  125. register long _sc_0 inline_syscall_r0_asm; \
  126. register long _sc_16 __asm__("$16"); \
  127. register long _sc_17 __asm__("$17"); \
  128. register long _sc_18 __asm__("$18"); \
  129. register long _sc_19 __asm__("$19"); \
  130. register long _tmp_16 = (long) (arg1); \
  131. register long _tmp_17 = (long) (arg2); \
  132. register long _tmp_18 = (long) (arg3); \
  133. \
  134. _sc_0 = name; \
  135. _sc_16 = _tmp_16; \
  136. _sc_17 = _tmp_17; \
  137. _sc_18 = _tmp_18; \
  138. __asm__ __volatile__ \
  139. ("callsys # %0 %1 <= %2 %3 %4 %5" \
  140. : inline_syscall_r0_out_constraint (_sc_0), \
  141. "=r"(_sc_19), "=r"(_sc_16), "=r"(_sc_17), \
  142. "=r"(_sc_18) \
  143. : "0"(_sc_0), "2"(_sc_16), "3"(_sc_17), \
  144. "4"(_sc_18) \
  145. : inline_syscall_clobbers, "$20", "$21"); \
  146. _sc_ret = _sc_0, _sc_err = _sc_19; \
  147. }
  148. #define inline_syscall4(name,arg1,arg2,arg3,arg4) \
  149. { \
  150. register long _sc_0 inline_syscall_r0_asm; \
  151. register long _sc_16 __asm__("$16"); \
  152. register long _sc_17 __asm__("$17"); \
  153. register long _sc_18 __asm__("$18"); \
  154. register long _sc_19 __asm__("$19"); \
  155. register long _tmp_16 = (long) (arg1); \
  156. register long _tmp_17 = (long) (arg2); \
  157. register long _tmp_18 = (long) (arg3); \
  158. register long _tmp_19 = (long) (arg4); \
  159. \
  160. _sc_0 = name; \
  161. _sc_16 = _tmp_16; \
  162. _sc_17 = _tmp_17; \
  163. _sc_18 = _tmp_18; \
  164. _sc_19 = _tmp_19; \
  165. __asm__ __volatile__ \
  166. ("callsys # %0 %1 <= %2 %3 %4 %5 %6" \
  167. : inline_syscall_r0_out_constraint (_sc_0), \
  168. "=r"(_sc_19), "=r"(_sc_16), "=r"(_sc_17), \
  169. "=r"(_sc_18) \
  170. : "0"(_sc_0), "2"(_sc_16), "3"(_sc_17), \
  171. "4"(_sc_18), "1"(_sc_19) \
  172. : inline_syscall_clobbers, "$20", "$21"); \
  173. _sc_ret = _sc_0, _sc_err = _sc_19; \
  174. }
  175. #define inline_syscall5(name,arg1,arg2,arg3,arg4,arg5) \
  176. { \
  177. register long _sc_0 inline_syscall_r0_asm; \
  178. register long _sc_16 __asm__("$16"); \
  179. register long _sc_17 __asm__("$17"); \
  180. register long _sc_18 __asm__("$18"); \
  181. register long _sc_19 __asm__("$19"); \
  182. register long _sc_20 __asm__("$20"); \
  183. register long _tmp_16 = (long) (arg1); \
  184. register long _tmp_17 = (long) (arg2); \
  185. register long _tmp_18 = (long) (arg3); \
  186. register long _tmp_19 = (long) (arg4); \
  187. register long _tmp_20 = (long) (arg5); \
  188. \
  189. _sc_0 = name; \
  190. _sc_16 = _tmp_16; \
  191. _sc_17 = _tmp_17; \
  192. _sc_18 = _tmp_18; \
  193. _sc_19 = _tmp_19; \
  194. _sc_20 = _tmp_20; \
  195. __asm__ __volatile__ \
  196. ("callsys # %0 %1 <= %2 %3 %4 %5 %6 %7" \
  197. : inline_syscall_r0_out_constraint (_sc_0), \
  198. "=r"(_sc_19), "=r"(_sc_16), "=r"(_sc_17), \
  199. "=r"(_sc_18), "=r"(_sc_20) \
  200. : "0"(_sc_0), "2"(_sc_16), "3"(_sc_17), \
  201. "4"(_sc_18), "1"(_sc_19), "5"(_sc_20) \
  202. : inline_syscall_clobbers, "$21"); \
  203. _sc_ret = _sc_0, _sc_err = _sc_19; \
  204. }
  205. #define inline_syscall6(name,arg1,arg2,arg3,arg4,arg5,arg6) \
  206. { \
  207. register long _sc_0 inline_syscall_r0_asm; \
  208. register long _sc_16 __asm__("$16"); \
  209. register long _sc_17 __asm__("$17"); \
  210. register long _sc_18 __asm__("$18"); \
  211. register long _sc_19 __asm__("$19"); \
  212. register long _sc_20 __asm__("$20"); \
  213. register long _sc_21 __asm__("$21"); \
  214. register long _tmp_16 = (long) (arg1); \
  215. register long _tmp_17 = (long) (arg2); \
  216. register long _tmp_18 = (long) (arg3); \
  217. register long _tmp_19 = (long) (arg4); \
  218. register long _tmp_20 = (long) (arg5); \
  219. register long _tmp_21 = (long) (arg6); \
  220. \
  221. _sc_0 = name; \
  222. _sc_16 = _tmp_16; \
  223. _sc_17 = _tmp_17; \
  224. _sc_18 = _tmp_18; \
  225. _sc_19 = _tmp_19; \
  226. _sc_20 = _tmp_20; \
  227. _sc_21 = _tmp_21; \
  228. __asm__ __volatile__ \
  229. ("callsys # %0 %1 <= %2 %3 %4 %5 %6 %7 %8" \
  230. : inline_syscall_r0_out_constraint (_sc_0), \
  231. "=r"(_sc_19), "=r"(_sc_16), "=r"(_sc_17), \
  232. "=r"(_sc_18), "=r"(_sc_20), "=r"(_sc_21) \
  233. : "0"(_sc_0), "2"(_sc_16), "3"(_sc_17), "4"(_sc_18), \
  234. "1"(_sc_19), "5"(_sc_20), "6"(_sc_21) \
  235. : inline_syscall_clobbers); \
  236. _sc_ret = _sc_0, _sc_err = _sc_19; \
  237. }
  238. #endif /* __ASSEMBLER__ */
  239. #endif /* _BITS_SYSCALLS_H */