syscalls.h 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350
  1. #ifndef _BITS_SYSCALLS_H
  2. #define _BITS_SYSCALLS_H
  3. #ifndef _SYSCALL_H
  4. # error "Never use <bits/syscalls.h> directly; include <sys/syscall.h> instead."
  5. #endif
  6. #include <sgidefs.h>
  7. #ifndef __ASSEMBLER__
  8. #include <errno.h>
  9. /*
  10. * Import from:
  11. * glibc-ports/sysdeps/unix/sysv/linux/mips/mips32/sysdep.h
  12. * glibc-ports/sysdeps/unix/sysv/linux/mips/mips64/n32/sysdep.h
  13. * glibc-ports/sysdeps/unix/sysv/linux/mips/mips64/n64/sysdep.h
  14. */
  15. /* Define a macro which expands into the inline wrapper code for a system
  16. call. */
  17. #define INLINE_SYSCALL(name, nr, args...) \
  18. ({ INTERNAL_SYSCALL_DECL(err); \
  19. long result_var = INTERNAL_SYSCALL(name, err, nr, args); \
  20. if ( INTERNAL_SYSCALL_ERROR_P (result_var, err) ) \
  21. { \
  22. __set_errno (INTERNAL_SYSCALL_ERRNO (result_var, err)); \
  23. result_var = -1L; \
  24. } \
  25. result_var; })
  26. #define INLINE_SYSCALL_NOERR_NCS(name, nr, args...) \
  27. ({ \
  28. INTERNAL_SYSCALL_DECL(err); \
  29. long res = INTERNAL_SYSCALL_NCS(name, err, nr, args); \
  30. if (unlikely(INTERNAL_SYSCALL_ERROR_P(res, err))) { \
  31. res = -res; \
  32. } \
  33. res; \
  34. })
  35. #define INTERNAL_SYSCALL_DECL(err) long err attribute_unused
  36. #define INTERNAL_SYSCALL_ERROR_P(val, err) ((long) (err))
  37. #define INTERNAL_SYSCALL_ERRNO(val, err) (val)
  38. #define INTERNAL_SYSCALL(name, err, nr, args...) \
  39. internal_syscall##nr (, "li\t$2, %2\t\t\t# " #name "\n\t", \
  40. "i" (SYS_ify (name)), err, args)
  41. #define INTERNAL_SYSCALL_NCS(number, err, nr, args...) \
  42. internal_syscall##nr (= number, , "r" (__v0), err, args)
  43. #if _MIPS_SIM == _ABIO32 || _MIPS_SIM == _ABI64
  44. # define ARG_TYPE long
  45. #else
  46. # define ARG_TYPE long long
  47. #endif
  48. #define internal_syscall0(ncs_init, cs_init, input, err, dummy...) \
  49. ({ \
  50. long _sys_result; \
  51. \
  52. { \
  53. register ARG_TYPE __v0 __asm__("$2") ncs_init; \
  54. register ARG_TYPE __a3 __asm__("$7"); \
  55. __asm__ __volatile__ ( \
  56. ".set\tnoreorder\n\t" \
  57. cs_init \
  58. "syscall\n\t" \
  59. ".set reorder" \
  60. : "=r" (__v0), "=r" (__a3) \
  61. : input \
  62. : __SYSCALL_CLOBBERS); \
  63. err = __a3; \
  64. _sys_result = __v0; \
  65. } \
  66. _sys_result; \
  67. })
  68. #define internal_syscall1(ncs_init, cs_init, input, err, arg1) \
  69. ({ \
  70. long _sys_result; \
  71. \
  72. { \
  73. register ARG_TYPE __v0 __asm__("$2") ncs_init; \
  74. register ARG_TYPE __a0 __asm__("$4") = (ARG_TYPE) arg1; \
  75. register ARG_TYPE __a3 __asm__("$7"); \
  76. __asm__ __volatile__ ( \
  77. ".set\tnoreorder\n\t" \
  78. cs_init \
  79. "syscall\n\t" \
  80. ".set reorder" \
  81. : "=r" (__v0), "=r" (__a3) \
  82. : input, "r" (__a0) \
  83. : __SYSCALL_CLOBBERS); \
  84. err = __a3; \
  85. _sys_result = __v0; \
  86. } \
  87. _sys_result; \
  88. })
  89. #define internal_syscall2(ncs_init, cs_init, input, err, arg1, arg2) \
  90. ({ \
  91. long _sys_result; \
  92. \
  93. { \
  94. register ARG_TYPE __v0 __asm__("$2") ncs_init; \
  95. register ARG_TYPE __a0 __asm__("$4") = (ARG_TYPE) arg1; \
  96. register ARG_TYPE __a1 __asm__("$5") = (ARG_TYPE) arg2; \
  97. register ARG_TYPE __a3 __asm__("$7"); \
  98. __asm__ __volatile__ ( \
  99. ".set\tnoreorder\n\t" \
  100. cs_init \
  101. "syscall\n\t" \
  102. ".set\treorder" \
  103. : "=r" (__v0), "=r" (__a3) \
  104. : input, "r" (__a0), "r" (__a1) \
  105. : __SYSCALL_CLOBBERS); \
  106. err = __a3; \
  107. _sys_result = __v0; \
  108. } \
  109. _sys_result; \
  110. })
  111. #define internal_syscall3(ncs_init, cs_init, input, err, arg1, arg2, arg3)\
  112. ({ \
  113. long _sys_result; \
  114. \
  115. { \
  116. register ARG_TYPE __v0 __asm__("$2") ncs_init; \
  117. register ARG_TYPE __a0 __asm__("$4") = (ARG_TYPE) arg1; \
  118. register ARG_TYPE __a1 __asm__("$5") = (ARG_TYPE) arg2; \
  119. register ARG_TYPE __a2 __asm__("$6") = (ARG_TYPE) arg3; \
  120. register ARG_TYPE __a3 __asm__("$7"); \
  121. __asm__ __volatile__ ( \
  122. ".set\tnoreorder\n\t" \
  123. cs_init \
  124. "syscall\n\t" \
  125. ".set\treorder" \
  126. : "=r" (__v0), "=r" (__a3) \
  127. : input, "r" (__a0), "r" (__a1), "r" (__a2) \
  128. : __SYSCALL_CLOBBERS); \
  129. err = __a3; \
  130. _sys_result = __v0; \
  131. } \
  132. _sys_result; \
  133. })
  134. #define internal_syscall4(ncs_init, cs_init, input, err, arg1, arg2, arg3, arg4)\
  135. ({ \
  136. long _sys_result; \
  137. \
  138. { \
  139. register ARG_TYPE __v0 __asm__("$2") ncs_init; \
  140. register ARG_TYPE __a0 __asm__("$4") = (ARG_TYPE) arg1; \
  141. register ARG_TYPE __a1 __asm__("$5") = (ARG_TYPE) arg2; \
  142. register ARG_TYPE __a2 __asm__("$6") = (ARG_TYPE) arg3; \
  143. register ARG_TYPE __a3 __asm__("$7") = (ARG_TYPE) arg4; \
  144. __asm__ __volatile__ ( \
  145. ".set\tnoreorder\n\t" \
  146. cs_init \
  147. "syscall\n\t" \
  148. ".set\treorder" \
  149. : "=r" (__v0), "+r" (__a3) \
  150. : input, "r" (__a0), "r" (__a1), "r" (__a2) \
  151. : __SYSCALL_CLOBBERS); \
  152. err = __a3; \
  153. _sys_result = __v0; \
  154. } \
  155. _sys_result; \
  156. })
  157. #if _MIPS_SIM == _ABIO32
  158. #include <alloca.h>
  159. /* We need to use a frame pointer for the functions in which we
  160. adjust $sp around the syscall, or debug information and unwind
  161. information will be $sp relative and thus wrong during the syscall. As
  162. of GCC 3.4.3, this is sufficient. */
  163. #define FORCE_FRAME_POINTER alloca (4)
  164. #define internal_syscall5(ncs_init, cs_init, input, err, arg1, arg2, arg3, arg4, arg5)\
  165. ({ \
  166. long _sys_result; \
  167. \
  168. int* array = FORCE_FRAME_POINTER; \
  169. { \
  170. register long __v0 __asm__("$2") ncs_init; \
  171. register long __a0 __asm__("$4") = (long) arg1; \
  172. register long __a1 __asm__("$5") = (long) arg2; \
  173. register long __a2 __asm__("$6") = (long) arg3; \
  174. register long __a3 __asm__("$7") = (long) arg4; \
  175. __asm__ __volatile__ ( \
  176. ".set\tnoreorder\n\t" \
  177. "subu\t$29, 32\n\t" \
  178. "sw\t%6, 16($29)\n\t" \
  179. cs_init \
  180. "syscall\n\t" \
  181. "addiu\t$29, 32\n\t" \
  182. "addiu\t%7, %7, 0\n\t" \
  183. ".set\treorder" \
  184. : "=r" (__v0), "+r" (__a3) \
  185. : input, "r" (__a0), "r" (__a1), "r" (__a2), \
  186. "r" ((long)arg5), "r" (array) \
  187. : __SYSCALL_CLOBBERS); \
  188. err = __a3; \
  189. _sys_result = __v0; \
  190. } \
  191. _sys_result; \
  192. })
  193. #define internal_syscall6(ncs_init, cs_init, input, err, arg1, arg2, arg3, arg4, arg5, arg6)\
  194. ({ \
  195. long _sys_result; \
  196. \
  197. int* array = FORCE_FRAME_POINTER; \
  198. { \
  199. register long __v0 __asm__("$2") ncs_init; \
  200. register long __a0 __asm__("$4") = (long) arg1; \
  201. register long __a1 __asm__("$5") = (long) arg2; \
  202. register long __a2 __asm__("$6") = (long) arg3; \
  203. register long __a3 __asm__("$7") = (long) arg4; \
  204. __asm__ __volatile__ ( \
  205. ".set\tnoreorder\n\t" \
  206. "subu\t$29, 32\n\t" \
  207. "sw\t%6, 16($29)\n\t" \
  208. "sw\t%7, 20($29)\n\t" \
  209. cs_init \
  210. "syscall\n\t" \
  211. "addiu\t$29, 32\n\t" \
  212. "addiu\t%8, %8, 0\n\t" \
  213. ".set\treorder" \
  214. : "=r" (__v0), "+r" (__a3) \
  215. : input, "r" (__a0), "r" (__a1), "r" (__a2), \
  216. "r" ((long)arg5), "r" ((long)arg6), "r" (array) \
  217. : __SYSCALL_CLOBBERS); \
  218. err = __a3; \
  219. _sys_result = __v0; \
  220. } \
  221. _sys_result; \
  222. })
  223. #define internal_syscall7(ncs_init, cs_init, input, err, arg1, arg2, arg3, arg4, arg5, arg6, arg7)\
  224. ({ \
  225. long _sys_result; \
  226. \
  227. int* array = FORCE_FRAME_POINTER; \
  228. { \
  229. register long __v0 __asm__("$2") ncs_init; \
  230. register long __a0 __asm__("$4") = (long) arg1; \
  231. register long __a1 __asm__("$5") = (long) arg2; \
  232. register long __a2 __asm__("$6") = (long) arg3; \
  233. register long __a3 __asm__("$7") = (long) arg4; \
  234. __asm__ __volatile__ ( \
  235. ".set\tnoreorder\n\t" \
  236. "subu\t$29, 32\n\t" \
  237. "sw\t%6, 16($29)\n\t" \
  238. "sw\t%7, 20($29)\n\t" \
  239. "sw\t%8, 24($29)\n\t" \
  240. cs_init \
  241. "syscall\n\t" \
  242. "addiu\t$29, 32\n\t" \
  243. "addiu\t%9, %9, 0\n\t" \
  244. ".set\treorder" \
  245. : "=r" (__v0), "+r" (__a3) \
  246. : input, "r" (__a0), "r" (__a1), "r" (__a2), \
  247. "r" ((long)arg5), "r" ((long)arg6), "r" ((long)arg7), \
  248. "r" (array) \
  249. : __SYSCALL_CLOBBERS); \
  250. err = __a3; \
  251. _sys_result = __v0; \
  252. } \
  253. _sys_result; \
  254. })
  255. #if __mips_isa_rev >= 6
  256. # define __SYSCALL_CLOBBERS "$1", "$3", "$8", "$9", "$10", "$11", "$12", "$13", \
  257. "$14", "$15", "$24", "$25", "memory"
  258. #else
  259. # define __SYSCALL_CLOBBERS "$1", "$3", "$8", "$9", "$10", "$11", "$12", "$13", \
  260. "$14", "$15", "$24", "$25", "hi", "lo", "memory"
  261. #endif
  262. #else /* N32 || N64 */
  263. #define internal_syscall5(ncs_init, cs_init, input, err, arg1, arg2, arg3, arg4, arg5) \
  264. ({ \
  265. long _sys_result; \
  266. \
  267. { \
  268. register ARG_TYPE __v0 __asm__("$2") ncs_init; \
  269. register ARG_TYPE __a0 __asm__("$4") = (ARG_TYPE) arg1; \
  270. register ARG_TYPE __a1 __asm__("$5") = (ARG_TYPE) arg2; \
  271. register ARG_TYPE __a2 __asm__("$6") = (ARG_TYPE) arg3; \
  272. register ARG_TYPE __a3 __asm__("$7") = (ARG_TYPE) arg4; \
  273. register ARG_TYPE __a4 __asm__("$8") = (ARG_TYPE) arg5; \
  274. __asm__ __volatile__ ( \
  275. ".set\tnoreorder\n\t" \
  276. cs_init \
  277. "syscall\n\t" \
  278. ".set\treorder" \
  279. : "=r" (__v0), "+r" (__a3) \
  280. : input, "r" (__a0), "r" (__a1), "r" (__a2), "r" (__a4) \
  281. : __SYSCALL_CLOBBERS); \
  282. err = __a3; \
  283. _sys_result = __v0; \
  284. } \
  285. _sys_result; \
  286. })
  287. #define internal_syscall6(ncs_init, cs_init, input, err, arg1, arg2, arg3, arg4, arg5, arg6) \
  288. ({ \
  289. long _sys_result; \
  290. \
  291. { \
  292. register ARG_TYPE __v0 __asm__("$2") ncs_init; \
  293. register ARG_TYPE __a0 __asm__("$4") = (ARG_TYPE) arg1; \
  294. register ARG_TYPE __a1 __asm__("$5") = (ARG_TYPE) arg2; \
  295. register ARG_TYPE __a2 __asm__("$6") = (ARG_TYPE) arg3; \
  296. register ARG_TYPE __a3 __asm__("$7") = (ARG_TYPE) arg4; \
  297. register ARG_TYPE __a4 __asm__("$8") = (ARG_TYPE) arg5; \
  298. register ARG_TYPE __a5 __asm__("$9") = (ARG_TYPE) arg6; \
  299. __asm__ __volatile__ ( \
  300. ".set\tnoreorder\n\t" \
  301. cs_init \
  302. "syscall\n\t" \
  303. ".set\treorder" \
  304. : "=r" (__v0), "+r" (__a3) \
  305. : input, "r" (__a0), "r" (__a1), "r" (__a2), "r" (__a4), \
  306. "r" (__a5) \
  307. : __SYSCALL_CLOBBERS); \
  308. err = __a3; \
  309. _sys_result = __v0; \
  310. } \
  311. _sys_result; \
  312. })
  313. #if __mips_isa_rev >= 6
  314. # define __SYSCALL_CLOBBERS "$1", "$3", "$10", "$11", "$12", "$13", \
  315. "$14", "$15", "$24", "$25", "memory"
  316. #else
  317. # define __SYSCALL_CLOBBERS "$1", "$3", "$10", "$11", "$12", "$13", \
  318. "$14", "$15", "$24", "$25", "hi", "lo", "memory"
  319. #endif
  320. #endif
  321. #endif /* __ASSEMBLER__ */
  322. #endif /* _BITS_SYSCALLS_H */