sysdep.h 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391
  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: 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: j __syscall_error; \
  93. nop; \
  94. ENTRY(name) \
  95. .set noreorder; \
  96. li v0, SYS_ify(syscall_name); \
  97. syscall; \
  98. .set reorder; \
  99. bne a3, zero, 99b; \
  100. L(syse1):
  101. #endif
  102. /* We don't want the label for the error handler to be visible in the symbol
  103. table when we define it here. */
  104. #ifdef __PIC__
  105. # define SYSCALL_ERROR_LABEL 99b
  106. #endif
  107. #else /* ! __ASSEMBLER__ */
  108. /* Define a macro which expands into the inline wrapper code for a system
  109. call. */
  110. #undef INLINE_SYSCALL
  111. #define INLINE_SYSCALL(name, nr, args...) \
  112. ({ INTERNAL_SYSCALL_DECL(err); \
  113. long result_var = INTERNAL_SYSCALL (name, err, nr, args); \
  114. if ( INTERNAL_SYSCALL_ERROR_P (result_var, err) ) \
  115. { \
  116. __set_errno (INTERNAL_SYSCALL_ERRNO (result_var, err)); \
  117. result_var = -1L; \
  118. } \
  119. result_var; })
  120. #undef INTERNAL_SYSCALL_DECL
  121. #define INTERNAL_SYSCALL_DECL(err) long err
  122. #undef INTERNAL_SYSCALL_ERROR_P
  123. #define INTERNAL_SYSCALL_ERROR_P(val, err) ((long) (err))
  124. #undef INTERNAL_SYSCALL_ERRNO
  125. #define INTERNAL_SYSCALL_ERRNO(val, err) (val)
  126. #undef INTERNAL_SYSCALL
  127. #define INTERNAL_SYSCALL(name, err, nr, args...) \
  128. internal_syscall##nr (, "li\t$2, %2\t\t\t# " #name "\n\t", \
  129. "i" (SYS_ify (name)), err, args)
  130. #undef INTERNAL_SYSCALL_NCS
  131. #define INTERNAL_SYSCALL_NCS(number, err, nr, args...) \
  132. internal_syscall##nr (= number, , "r" (__v0), err, args)
  133. #undef internal_syscall0
  134. #define internal_syscall0(ncs_init, cs_init, input, err, dummy...) \
  135. ({ \
  136. long _sys_result; \
  137. \
  138. { \
  139. register long __v0 __asm__("$2") ncs_init; \
  140. register long __a3 __asm__("$7"); \
  141. __asm__ volatile ( \
  142. ".set\tnoreorder\n\t" \
  143. cs_init \
  144. "syscall\n\t" \
  145. ".set reorder" \
  146. : "=r" (__v0), "=r" (__a3) \
  147. : input \
  148. : __SYSCALL_CLOBBERS); \
  149. err = __a3; \
  150. _sys_result = __v0; \
  151. } \
  152. _sys_result; \
  153. })
  154. #undef internal_syscall1
  155. #define internal_syscall1(ncs_init, cs_init, input, err, arg1) \
  156. ({ \
  157. long _sys_result; \
  158. \
  159. { \
  160. register long __v0 __asm__("$2") ncs_init; \
  161. register long __a0 __asm__("$4") = (long) arg1; \
  162. register long __a3 __asm__("$7"); \
  163. __asm__ volatile ( \
  164. ".set\tnoreorder\n\t" \
  165. cs_init \
  166. "syscall\n\t" \
  167. ".set reorder" \
  168. : "=r" (__v0), "=r" (__a3) \
  169. : input, "r" (__a0) \
  170. : __SYSCALL_CLOBBERS); \
  171. err = __a3; \
  172. _sys_result = __v0; \
  173. } \
  174. _sys_result; \
  175. })
  176. #undef internal_syscall2
  177. #define internal_syscall2(ncs_init, cs_init, input, err, arg1, arg2) \
  178. ({ \
  179. long _sys_result; \
  180. \
  181. { \
  182. register long __v0 __asm__("$2") ncs_init; \
  183. register long __a0 __asm__("$4") = (long) arg1; \
  184. register long __a1 __asm__("$5") = (long) arg2; \
  185. register long __a3 __asm__("$7"); \
  186. __asm__ volatile ( \
  187. ".set\tnoreorder\n\t" \
  188. cs_init \
  189. "syscall\n\t" \
  190. ".set\treorder" \
  191. : "=r" (__v0), "=r" (__a3) \
  192. : input, "r" (__a0), "r" (__a1) \
  193. : __SYSCALL_CLOBBERS); \
  194. err = __a3; \
  195. _sys_result = __v0; \
  196. } \
  197. _sys_result; \
  198. })
  199. #undef internal_syscall3
  200. #define internal_syscall3(ncs_init, cs_init, input, err, arg1, arg2, arg3)\
  201. ({ \
  202. long _sys_result; \
  203. \
  204. { \
  205. register long __v0 __asm__("$2") ncs_init; \
  206. register long __a0 __asm__("$4") = (long) arg1; \
  207. register long __a1 __asm__("$5") = (long) arg2; \
  208. register long __a2 __asm__("$6") = (long) arg3; \
  209. register long __a3 __asm__("$7"); \
  210. __asm__ volatile ( \
  211. ".set\tnoreorder\n\t" \
  212. cs_init \
  213. "syscall\n\t" \
  214. ".set\treorder" \
  215. : "=r" (__v0), "=r" (__a3) \
  216. : input, "r" (__a0), "r" (__a1), "r" (__a2) \
  217. : __SYSCALL_CLOBBERS); \
  218. err = __a3; \
  219. _sys_result = __v0; \
  220. } \
  221. _sys_result; \
  222. })
  223. #undef internal_syscall4
  224. #define internal_syscall4(ncs_init, cs_init, input, err, arg1, arg2, arg3, arg4)\
  225. ({ \
  226. long _sys_result; \
  227. \
  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. cs_init \
  237. "syscall\n\t" \
  238. ".set\treorder" \
  239. : "=r" (__v0), "+r" (__a3) \
  240. : input, "r" (__a0), "r" (__a1), "r" (__a2) \
  241. : __SYSCALL_CLOBBERS); \
  242. err = __a3; \
  243. _sys_result = __v0; \
  244. } \
  245. _sys_result; \
  246. })
  247. /* We need to use a frame pointer for the functions in which we
  248. adjust $sp around the syscall, or debug information and unwind
  249. information will be $sp relative and thus wrong during the syscall. As
  250. of GCC 3.4.3, this is sufficient. */
  251. #define FORCE_FRAME_POINTER alloca (4)
  252. #undef internal_syscall5
  253. #define internal_syscall5(ncs_init, cs_init, input, err, arg1, arg2, arg3, arg4, arg5)\
  254. ({ \
  255. long _sys_result; \
  256. \
  257. FORCE_FRAME_POINTER; \
  258. { \
  259. register long __v0 __asm__("$2") ncs_init; \
  260. register long __a0 __asm__("$4") = (long) arg1; \
  261. register long __a1 __asm__("$5") = (long) arg2; \
  262. register long __a2 __asm__("$6") = (long) arg3; \
  263. register long __a3 __asm__("$7") = (long) arg4; \
  264. __asm__ volatile ( \
  265. ".set\tnoreorder\n\t" \
  266. "subu\t$29, 32\n\t" \
  267. "sw\t%6, 16($29)\n\t" \
  268. cs_init \
  269. "syscall\n\t" \
  270. "addiu\t$29, 32\n\t" \
  271. ".set\treorder" \
  272. : "=r" (__v0), "+r" (__a3) \
  273. : input, "r" (__a0), "r" (__a1), "r" (__a2), \
  274. "r" ((long)arg5) \
  275. : __SYSCALL_CLOBBERS); \
  276. err = __a3; \
  277. _sys_result = __v0; \
  278. } \
  279. _sys_result; \
  280. })
  281. #undef internal_syscall6
  282. #define internal_syscall6(ncs_init, cs_init, input, err, arg1, arg2, arg3, arg4, arg5, arg6)\
  283. ({ \
  284. long _sys_result; \
  285. \
  286. FORCE_FRAME_POINTER; \
  287. { \
  288. register long __v0 __asm__("$2") ncs_init; \
  289. register long __a0 __asm__("$4") = (long) arg1; \
  290. register long __a1 __asm__("$5") = (long) arg2; \
  291. register long __a2 __asm__("$6") = (long) arg3; \
  292. register long __a3 __asm__("$7") = (long) arg4; \
  293. __asm__ volatile ( \
  294. ".set\tnoreorder\n\t" \
  295. "subu\t$29, 32\n\t" \
  296. "sw\t%6, 16($29)\n\t" \
  297. "sw\t%7, 20($29)\n\t" \
  298. cs_init \
  299. "syscall\n\t" \
  300. "addiu\t$29, 32\n\t" \
  301. ".set\treorder" \
  302. : "=r" (__v0), "+r" (__a3) \
  303. : input, "r" (__a0), "r" (__a1), "r" (__a2), \
  304. "r" ((long)arg5), "r" ((long)arg6) \
  305. : __SYSCALL_CLOBBERS); \
  306. err = __a3; \
  307. _sys_result = __v0; \
  308. } \
  309. _sys_result; \
  310. })
  311. #undef internal_syscall7
  312. #define internal_syscall7(ncs_init, cs_init, input, err, arg1, arg2, arg3, arg4, arg5, arg6, arg7)\
  313. ({ \
  314. long _sys_result; \
  315. \
  316. FORCE_FRAME_POINTER; \
  317. { \
  318. register long __v0 __asm__("$2") ncs_init; \
  319. register long __a0 __asm__("$4") = (long) arg1; \
  320. register long __a1 __asm__("$5") = (long) arg2; \
  321. register long __a2 __asm__("$6") = (long) arg3; \
  322. register long __a3 __asm__("$7") = (long) arg4; \
  323. __asm__ volatile ( \
  324. ".set\tnoreorder\n\t" \
  325. "subu\t$29, 32\n\t" \
  326. "sw\t%6, 16($29)\n\t" \
  327. "sw\t%7, 20($29)\n\t" \
  328. "sw\t%8, 24($29)\n\t" \
  329. cs_init \
  330. "syscall\n\t" \
  331. "addiu\t$29, 32\n\t" \
  332. ".set\treorder" \
  333. : "=r" (__v0), "+r" (__a3) \
  334. : input, "r" (__a0), "r" (__a1), "r" (__a2), \
  335. "r" ((long)arg5), "r" ((long)arg6), "r" ((long)arg7) \
  336. : __SYSCALL_CLOBBERS); \
  337. err = __a3; \
  338. _sys_result = __v0; \
  339. } \
  340. _sys_result; \
  341. })
  342. #undef __SYSCALL_CLOBBERS
  343. #define __SYSCALL_CLOBBERS "$1", "$3", "$8", "$9", "$10", "$11", "$12", "$13", \
  344. "$14", "$15", "$24", "$25", "memory"
  345. /* Pointer mangling is not yet supported for MIPS. */
  346. #define PTR_MANGLE(var) (void) (var)
  347. #define PTR_DEMANGLE(var) (void) (var)
  348. #endif /* __ASSEMBLER__ */
  349. #endif /* _LINUX_MIPS_SYSDEP_H */