sysdep.h 11 KB

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