sysdep.h 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392
  1. /* Copyright (C) 1992, 1995, 1997, 1999, 2000, 2002, 2003, 2004
  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 _LINUX_MIPS_SYSDEP_H
  17. #define _LINUX_MIPS_SYSDEP_H 1
  18. #include <sgidefs.h>
  19. #include <common/sysdep.h>
  20. /* For Linux we can use the system call table in the header file
  21. /usr/include/asm/unistd.h
  22. of the kernel. But these symbols do not follow the SYS_* syntax
  23. so we have to redefine the `SYS_ify' macro here. */
  24. #undef SYS_ify
  25. #ifdef __STDC__
  26. # define SYS_ify(syscall_name) __NR_##syscall_name
  27. #else
  28. # define SYS_ify(syscall_name) __NR_/**/syscall_name
  29. #endif
  30. #ifdef __ASSEMBLER__
  31. #include <sys/regdef.h>
  32. #define ENTRY(name) \
  33. .globl name; \
  34. .align 2; \
  35. .ent name,0; \
  36. name##:
  37. #undef END
  38. #define END(function) \
  39. .end function; \
  40. .size function,.-function
  41. #define ret j ra ; nop
  42. #undef PSEUDO_END
  43. #define PSEUDO_END(sym) .end sym; .size sym,.-sym
  44. #define PSEUDO_NOERRNO(name, syscall_name, args) \
  45. .align 2; \
  46. ENTRY(name) \
  47. .set noreorder; \
  48. li v0, SYS_ify(syscall_name); \
  49. syscall
  50. #undef PSEUDO_END_NOERRNO
  51. #define PSEUDO_END_NOERRNO(sym) .end sym; .size sym,.-sym
  52. #define ret_NOERRNO ret
  53. #define PSEUDO_ERRVAL(name, syscall_name, args) \
  54. .align 2; \
  55. ENTRY(name) \
  56. .set noreorder; \
  57. li v0, SYS_ify(syscall_name); \
  58. syscall
  59. #undef PSEUDO_END_ERRVAL
  60. #define PSEUDO_END_ERRVAL(sym) .end sym; .size sym,.-sym
  61. #define ret_ERRVAL ret
  62. #define r0 v0
  63. #define r1 v1
  64. /* The mips move insn is d,s. */
  65. #define MOVE(x,y) move y , x
  66. #if _MIPS_SIM == _ABIO32
  67. # define L(label) $L ## label
  68. #else
  69. # define L(label) .L ## label
  70. #endif
  71. /* Note that while it's better structurally, going back to call __syscall_error
  72. can make things confusing if you're debugging---it looks like it's jumping
  73. backwards into the previous fn. */
  74. #ifdef __PIC__
  75. #define PSEUDO(name, syscall_name, args) \
  76. .align 2; \
  77. 99: move a0, v0; \
  78. la t9,__syscall_error; \
  79. jr t9; \
  80. ENTRY(name) \
  81. .set noreorder; \
  82. .cpload t9; \
  83. li v0, SYS_ify(syscall_name); \
  84. syscall; \
  85. .set reorder; \
  86. bne a3, zero, 99b; \
  87. L(syse1):
  88. #else
  89. #define PSEUDO(name, syscall_name, args) \
  90. .set noreorder; \
  91. .align 2; \
  92. 99: move a0, v0; \
  93. j __syscall_error; \
  94. nop; \
  95. ENTRY(name) \
  96. .set noreorder; \
  97. li v0, SYS_ify(syscall_name); \
  98. syscall; \
  99. .set reorder; \
  100. bne a3, zero, 99b; \
  101. L(syse1):
  102. #endif
  103. /* We don't want the label for the error handler to be visible in the symbol
  104. table when we define it here. */
  105. #ifdef __PIC__
  106. # define SYSCALL_ERROR_LABEL 99b
  107. #endif
  108. #else /* ! __ASSEMBLER__ */
  109. /* Define a macro which expands into the inline wrapper code for a system
  110. call. */
  111. #undef INLINE_SYSCALL
  112. #define INLINE_SYSCALL(name, nr, args...) \
  113. ({ INTERNAL_SYSCALL_DECL(err); \
  114. long result_var = INTERNAL_SYSCALL (name, err, nr, args); \
  115. if ( INTERNAL_SYSCALL_ERROR_P (result_var, err) ) \
  116. { \
  117. __set_errno (INTERNAL_SYSCALL_ERRNO (result_var, err)); \
  118. result_var = -1L; \
  119. } \
  120. result_var; })
  121. #undef INTERNAL_SYSCALL_DECL
  122. #define INTERNAL_SYSCALL_DECL(err) long err
  123. #undef INTERNAL_SYSCALL_ERROR_P
  124. #define INTERNAL_SYSCALL_ERROR_P(val, err) ((long) (err))
  125. #undef INTERNAL_SYSCALL_ERRNO
  126. #define INTERNAL_SYSCALL_ERRNO(val, err) (val)
  127. #undef INTERNAL_SYSCALL
  128. #define INTERNAL_SYSCALL(name, err, nr, args...) \
  129. internal_syscall##nr (, "li\t$2, %2\t\t\t# " #name "\n\t", \
  130. "i" (SYS_ify (name)), err, args)
  131. #undef INTERNAL_SYSCALL_NCS
  132. #define INTERNAL_SYSCALL_NCS(number, err, nr, args...) \
  133. internal_syscall##nr (= number, , "r" (__v0), err, args)
  134. #undef internal_syscall0
  135. #define internal_syscall0(ncs_init, cs_init, input, err, dummy...) \
  136. ({ \
  137. long _sys_result; \
  138. \
  139. { \
  140. register long __v0 __asm__("$2") ncs_init; \
  141. register long __a3 __asm__("$7"); \
  142. __asm__ __volatile__ ( \
  143. ".set\tnoreorder\n\t" \
  144. cs_init \
  145. "syscall\n\t" \
  146. ".set reorder" \
  147. : "=r" (__v0), "=r" (__a3) \
  148. : input \
  149. : __SYSCALL_CLOBBERS); \
  150. err = __a3; \
  151. _sys_result = __v0; \
  152. } \
  153. _sys_result; \
  154. })
  155. #undef internal_syscall1
  156. #define internal_syscall1(ncs_init, cs_init, input, err, arg1) \
  157. ({ \
  158. long _sys_result; \
  159. \
  160. { \
  161. register long __v0 __asm__("$2") ncs_init; \
  162. register long __a0 __asm__("$4") = (long) arg1; \
  163. register long __a3 __asm__("$7"); \
  164. __asm__ __volatile__ ( \
  165. ".set\tnoreorder\n\t" \
  166. cs_init \
  167. "syscall\n\t" \
  168. ".set reorder" \
  169. : "=r" (__v0), "=r" (__a3) \
  170. : input, "r" (__a0) \
  171. : __SYSCALL_CLOBBERS); \
  172. err = __a3; \
  173. _sys_result = __v0; \
  174. } \
  175. _sys_result; \
  176. })
  177. #undef internal_syscall2
  178. #define internal_syscall2(ncs_init, cs_init, input, err, arg1, arg2) \
  179. ({ \
  180. long _sys_result; \
  181. \
  182. { \
  183. register long __v0 __asm__("$2") ncs_init; \
  184. register long __a0 __asm__("$4") = (long) arg1; \
  185. register long __a1 __asm__("$5") = (long) arg2; \
  186. register long __a3 __asm__("$7"); \
  187. __asm__ __volatile__ ( \
  188. ".set\tnoreorder\n\t" \
  189. cs_init \
  190. "syscall\n\t" \
  191. ".set\treorder" \
  192. : "=r" (__v0), "=r" (__a3) \
  193. : input, "r" (__a0), "r" (__a1) \
  194. : __SYSCALL_CLOBBERS); \
  195. err = __a3; \
  196. _sys_result = __v0; \
  197. } \
  198. _sys_result; \
  199. })
  200. #undef internal_syscall3
  201. #define internal_syscall3(ncs_init, cs_init, input, err, arg1, arg2, arg3)\
  202. ({ \
  203. long _sys_result; \
  204. \
  205. { \
  206. register long __v0 __asm__("$2") ncs_init; \
  207. register long __a0 __asm__("$4") = (long) arg1; \
  208. register long __a1 __asm__("$5") = (long) arg2; \
  209. register long __a2 __asm__("$6") = (long) arg3; \
  210. register long __a3 __asm__("$7"); \
  211. __asm__ __volatile__ ( \
  212. ".set\tnoreorder\n\t" \
  213. cs_init \
  214. "syscall\n\t" \
  215. ".set\treorder" \
  216. : "=r" (__v0), "=r" (__a3) \
  217. : input, "r" (__a0), "r" (__a1), "r" (__a2) \
  218. : __SYSCALL_CLOBBERS); \
  219. err = __a3; \
  220. _sys_result = __v0; \
  221. } \
  222. _sys_result; \
  223. })
  224. #undef internal_syscall4
  225. #define internal_syscall4(ncs_init, cs_init, input, err, arg1, arg2, arg3, arg4)\
  226. ({ \
  227. long _sys_result; \
  228. \
  229. { \
  230. register long __v0 __asm__("$2") ncs_init; \
  231. register long __a0 __asm__("$4") = (long) arg1; \
  232. register long __a1 __asm__("$5") = (long) arg2; \
  233. register long __a2 __asm__("$6") = (long) arg3; \
  234. register long __a3 __asm__("$7") = (long) arg4; \
  235. __asm__ __volatile__ ( \
  236. ".set\tnoreorder\n\t" \
  237. cs_init \
  238. "syscall\n\t" \
  239. ".set\treorder" \
  240. : "=r" (__v0), "+r" (__a3) \
  241. : input, "r" (__a0), "r" (__a1), "r" (__a2) \
  242. : __SYSCALL_CLOBBERS); \
  243. err = __a3; \
  244. _sys_result = __v0; \
  245. } \
  246. _sys_result; \
  247. })
  248. /* We need to use a frame pointer for the functions in which we
  249. adjust $sp around the syscall, or debug information and unwind
  250. information will be $sp relative and thus wrong during the syscall. As
  251. of GCC 3.4.3, this is sufficient. */
  252. #define FORCE_FRAME_POINTER alloca (4)
  253. #undef internal_syscall5
  254. #define internal_syscall5(ncs_init, cs_init, input, err, arg1, arg2, arg3, arg4, arg5)\
  255. ({ \
  256. long _sys_result; \
  257. \
  258. FORCE_FRAME_POINTER; \
  259. { \
  260. register long __v0 __asm__("$2") ncs_init; \
  261. register long __a0 __asm__("$4") = (long) arg1; \
  262. register long __a1 __asm__("$5") = (long) arg2; \
  263. register long __a2 __asm__("$6") = (long) arg3; \
  264. register long __a3 __asm__("$7") = (long) arg4; \
  265. __asm__ __volatile__ ( \
  266. ".set\tnoreorder\n\t" \
  267. "subu\t$29, 32\n\t" \
  268. "sw\t%6, 16($29)\n\t" \
  269. cs_init \
  270. "syscall\n\t" \
  271. "addiu\t$29, 32\n\t" \
  272. ".set\treorder" \
  273. : "=r" (__v0), "+r" (__a3) \
  274. : input, "r" (__a0), "r" (__a1), "r" (__a2), \
  275. "r" ((long)arg5) \
  276. : __SYSCALL_CLOBBERS); \
  277. err = __a3; \
  278. _sys_result = __v0; \
  279. } \
  280. _sys_result; \
  281. })
  282. #undef internal_syscall6
  283. #define internal_syscall6(ncs_init, cs_init, input, err, arg1, arg2, arg3, arg4, arg5, arg6)\
  284. ({ \
  285. long _sys_result; \
  286. \
  287. FORCE_FRAME_POINTER; \
  288. { \
  289. register long __v0 __asm__("$2") ncs_init; \
  290. register long __a0 __asm__("$4") = (long) arg1; \
  291. register long __a1 __asm__("$5") = (long) arg2; \
  292. register long __a2 __asm__("$6") = (long) arg3; \
  293. register long __a3 __asm__("$7") = (long) arg4; \
  294. __asm__ __volatile__ ( \
  295. ".set\tnoreorder\n\t" \
  296. "subu\t$29, 32\n\t" \
  297. "sw\t%6, 16($29)\n\t" \
  298. "sw\t%7, 20($29)\n\t" \
  299. cs_init \
  300. "syscall\n\t" \
  301. "addiu\t$29, 32\n\t" \
  302. ".set\treorder" \
  303. : "=r" (__v0), "+r" (__a3) \
  304. : input, "r" (__a0), "r" (__a1), "r" (__a2), \
  305. "r" ((long)arg5), "r" ((long)arg6) \
  306. : __SYSCALL_CLOBBERS); \
  307. err = __a3; \
  308. _sys_result = __v0; \
  309. } \
  310. _sys_result; \
  311. })
  312. #undef internal_syscall7
  313. #define internal_syscall7(ncs_init, cs_init, input, err, arg1, arg2, arg3, arg4, arg5, arg6, arg7)\
  314. ({ \
  315. long _sys_result; \
  316. \
  317. FORCE_FRAME_POINTER; \
  318. { \
  319. register long __v0 __asm__("$2") ncs_init; \
  320. register long __a0 __asm__("$4") = (long) arg1; \
  321. register long __a1 __asm__("$5") = (long) arg2; \
  322. register long __a2 __asm__("$6") = (long) arg3; \
  323. register long __a3 __asm__("$7") = (long) arg4; \
  324. __asm__ __volatile__ ( \
  325. ".set\tnoreorder\n\t" \
  326. "subu\t$29, 32\n\t" \
  327. "sw\t%6, 16($29)\n\t" \
  328. "sw\t%7, 20($29)\n\t" \
  329. "sw\t%8, 24($29)\n\t" \
  330. cs_init \
  331. "syscall\n\t" \
  332. "addiu\t$29, 32\n\t" \
  333. ".set\treorder" \
  334. : "=r" (__v0), "+r" (__a3) \
  335. : input, "r" (__a0), "r" (__a1), "r" (__a2), \
  336. "r" ((long)arg5), "r" ((long)arg6), "r" ((long)arg7) \
  337. : __SYSCALL_CLOBBERS); \
  338. err = __a3; \
  339. _sys_result = __v0; \
  340. } \
  341. _sys_result; \
  342. })
  343. #undef __SYSCALL_CLOBBERS
  344. #define __SYSCALL_CLOBBERS "$1", "$3", "$8", "$9", "$10", "$11", "$12", "$13", \
  345. "$14", "$15", "$24", "$25", "memory"
  346. /* Pointer mangling is not yet supported for MIPS. */
  347. #define PTR_MANGLE(var) (void) (var)
  348. #define PTR_DEMANGLE(var) (void) (var)
  349. #endif /* __ASSEMBLER__ */
  350. #endif /* _LINUX_MIPS_SYSDEP_H */