sysdep.h 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534
  1. /* Assembly macros for C-SKY.
  2. Copyright (C) 2018-2019 Free Software Foundation, Inc.
  3. This file is part of the GNU C Library.
  4. The GNU C Library is free software; you can redistribute it and/or
  5. modify it under the terms of the GNU Lesser General Public
  6. License as published by the Free Software Foundation; either
  7. version 2.1 of the License, or (at your option) any later version.
  8. The GNU C Library is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  11. Lesser General Public License for more details.
  12. You should have received a copy of the GNU Lesser General Public
  13. License along with the GNU C Library. If not, see
  14. <http://www.gnu.org/licenses/>. */
  15. #ifndef _LINUX_CSKY_SYSDEP_H
  16. #define _LINUX_CSKY_SYSDEP_H 1
  17. /* There is some commonality. */
  18. #include <sysdeps/unix/sysv/linux/generic/sysdep.h>
  19. #include <sysdeps/unix/sysv/linux/sysdep.h>
  20. #include <sysdeps/csky/sysdep.h>
  21. /* Defines RTLD_PRIVATE_ERRNO and USE_DL_SYSINFO. */
  22. #include <dl-sysdep.h>
  23. #include <tls.h>
  24. /* In order to get __set_errno() definition in INLINE_SYSCALL. */
  25. #ifndef __ASSEMBLER__
  26. # include <errno.h>
  27. #endif
  28. #undef SYS_ify
  29. #define SYS_ify(syscall_name) (__NR_##syscall_name)
  30. #ifdef __ASSEMBLER__
  31. /* Linux uses a negative return value to indicate syscall errors,
  32. unlike most Unices, which use the condition codes' carry flag.
  33. Since version 2.1 the return value of a system call might be
  34. negative even if the call succeeded. E.g., the `lseek' system call
  35. might return a large offset. Therefore we must not anymore test
  36. for < 0, but test for a real error by making sure the value in R0
  37. is a real error number. Linus said he will make sure the no syscall
  38. returns a value in -1 .. -4095 as a valid result so we can safely
  39. test with -4095. */
  40. # undef PSEUDO
  41. # define PSEUDO(name, syscall_name, args) \
  42. .text; \
  43. ENTRY (name); \
  44. DO_CALL (syscall_name, args);
  45. # define GETGB \
  46. grs t0, .Lgetpc; \
  47. .Lgetpc: \
  48. lrw gb, .Lgetpc@GOTPC; \
  49. addu gb, t0;
  50. # if IS_IN (libc)
  51. # ifdef __PIC__
  52. # define PSEUDO_RET \
  53. btsti a0, 31; \
  54. bf 1f; \
  55. subi sp, 8; \
  56. st.w lr, (sp); \
  57. st.w gb, (sp, 4); \
  58. GETGB; \
  59. lrw a2, SYSCALL_ERROR@PLT; \
  60. add a2, gb; \
  61. ld.w a2, (a2); \
  62. jsr a2; \
  63. ld.w lr, (sp); \
  64. ld.w gb, (sp, 4); \
  65. addi sp, 8; \
  66. 1: \
  67. rts
  68. # else
  69. # define PSEUDO_RET \
  70. btsti a0, 31; \
  71. bf 1f; \
  72. jmpi SYSCALL_ERROR; \
  73. 1: \
  74. rts
  75. # endif
  76. # else
  77. # ifdef __PIC__
  78. # define PSEUDO_RET \
  79. btsti a0, 31; \
  80. bf 1f; \
  81. subi sp, 8; \
  82. st.w lr, (sp); \
  83. st.w gb, (sp, 4); \
  84. GETGB; \
  85. bsr SYSCALL_ERROR; \
  86. ld.w lr, (sp); \
  87. ld.w gb, (sp, 4); \
  88. addi sp, 8; \
  89. 1: \
  90. rts
  91. # else
  92. # define PSEUDO_RET \
  93. btsti a0, 31; \
  94. bt SYSCALL_ERROR; \
  95. rts
  96. # endif
  97. # endif
  98. # undef ret
  99. # define ret PSEUDO_RET
  100. # undef PSEUDO_END
  101. # define PSEUDO_END(name) \
  102. .align 4; \
  103. SYSCALL_ERROR_HANDLER; \
  104. END (name)
  105. # undef PSEUDO_NOERRNO
  106. # define PSEUDO_NOERRNO(name, syscall_name, args) \
  107. .text; \
  108. ENTRY (name); \
  109. DO_CALL (syscall_name, args)
  110. # define PSEUDO_RET_NOERRNO rts
  111. # undef ret_NOERRNO
  112. # define ret_NOERRNO PSEUDO_RET_NOERRNO
  113. # undef PSEUDO_END_NOERRNO
  114. # define PSEUDO_END_NOERRNO(name) END (name)
  115. /* The function has to return the error code. */
  116. # undef PSEUDO_ERRVAL
  117. # define PSEUDO_ERRVAL(name, syscall_name, args) \
  118. .text; \
  119. ENTRY (name) \
  120. DO_CALL (syscall_name, args); \
  121. not a0; \
  122. addi a0, 1
  123. # undef PSEUDO_END_ERRVAL
  124. # define PSEUDO_END_ERRVAL(name) END (name)
  125. # define ret_ERRVAL rts
  126. # if !IS_IN (libc)
  127. # define SYSCALL_ERROR __local_syscall_error
  128. # if RTLD_PRIVATE_ERRNO
  129. # ifdef __PIC__
  130. # define SYSCALL_ERROR_HANDLER \
  131. __local_syscall_error: \
  132. lrw a1, rtld_errno@PLT; \
  133. addu a1, gb; \
  134. ldw a1, (a1); \
  135. rsubi a0, 0; \
  136. stw a0, (a1); \
  137. bmaski a0, 0; \
  138. rts
  139. # else /* __PIC__ */
  140. # define SYSCALL_ERROR_HANDLER \
  141. __local_syscall_error: \
  142. lrw a1, rtld_errno; \
  143. rsubi a0, 0; \
  144. stw a0, (a1); \
  145. bmaski a0, 0; \
  146. rts
  147. # endif /* __PIC__ */
  148. # else /* !RTLD_PRIVATE_ERRNO */
  149. # ifdef __PIC__
  150. # define SYSCALL_ERROR_HANDLER \
  151. __local_syscall_error: \
  152. subi sp, 8; \
  153. stw a0, (sp, 0); \
  154. stw r15, (sp, 4); \
  155. lrw a1, __errno_location@PLT; \
  156. add a1, gb; \
  157. ldw a1, (a1); \
  158. jsr a1; \
  159. ldw a1, (sp, 0); /* load errno*/ \
  160. ldw r15, (sp, 4); \
  161. addi sp, 8; \
  162. movi a2, 0; \
  163. rsub a1, a1, a2; \
  164. stw a1, (a0); \
  165. bmaski a0, 0; \
  166. rts
  167. # else
  168. # define SYSCALL_ERROR_HANDLER \
  169. __local_syscall_error: \
  170. subi sp, 8; \
  171. stw a0, (sp, 0); \
  172. stw r15, (sp, 4); \
  173. lrw a1, __errno_location; \
  174. jsr a1; \
  175. ldw a1, (sp, 0); /* load errno */ \
  176. ldw r15, (sp, 4); \
  177. addi sp, 8; \
  178. movi a2, 0; \
  179. rsub a1, a1, a2; \
  180. stw a1, (a0); \
  181. bmaski a0, 0; \
  182. rts
  183. # endif /* __PIC__ */
  184. # endif/* RTLD_PRIVATE_ERROR */
  185. # else
  186. # define SYSCALL_ERROR_HANDLER /* Nothing here; code in sysdep.S is used. */
  187. # define SYSCALL_ERROR __syscall_error
  188. # endif/* IS_IN (libc) */
  189. /* define DO_CALL */
  190. # undef DO_CALL
  191. # define DO_CALL(syscall_name, args) \
  192. DOARGS_##args; \
  193. lrw r7, SYS_ify(syscall_name); \
  194. trap 0; \
  195. UNDOARGS_##args
  196. # undef DOARGS_0
  197. # define DOARGS_0 \
  198. subi sp, 8; \
  199. cfi_adjust_cfa_offset (8); \
  200. stw r7, (sp, 0); \
  201. cfi_rel_offset (r7, 0);
  202. # undef DOARGS_1
  203. # define DOARGS_1 DOARGS_0
  204. # undef DOARGS_2
  205. # define DOARGS_2 DOARGS_0
  206. # undef DOARGS_3
  207. # define DOARGS_3 DOARGS_0
  208. # undef DOARGS_4
  209. # define DOARGS_4 DOARGS_0
  210. # undef DOARGS_5
  211. # define DOARGS_5 \
  212. subi sp, 8; \
  213. cfi_adjust_cfa_offset (8); \
  214. stw r7, (sp, 0); \
  215. cfi_rel_offset (7, 0); \
  216. stw r4, (sp, 4); \
  217. cfi_rel_offset (4, 4); \
  218. ldw r4, (sp, 8)
  219. # undef DOARGS_6
  220. # define DOARGS_6 \
  221. subi sp, 16; \
  222. cfi_adjust_cfa_offset (16); \
  223. stw r7, (sp, 0); \
  224. cfi_rel_offset (7, 0); \
  225. stw r4, (sp, 4); \
  226. cfi_rel_offset (4, 4); \
  227. stw r5, (sp, 8); \
  228. cfi_rel_offset (5, 8); \
  229. ldw r4, (sp, 16); \
  230. ldw r5, (sp, 20)
  231. # undef UNDOARGS_0
  232. # define UNDOARGS_0 \
  233. ldw r7, (sp, 0); \
  234. cfi_restore (r7); \
  235. addi sp, 8; \
  236. cfi_adjust_cfa_offset (-8);
  237. # undef UNDOARGS_1
  238. # define UNDOARGS_1 UNDOARGS_0
  239. # undef UNDOARGS_2
  240. # define UNDOARGS_2 UNDOARGS_0
  241. # undef UNDOARGS_3
  242. # define UNDOARGS_3 UNDOARGS_0
  243. # undef UNDOARGS_4
  244. # define UNDOARGS_4 UNDOARGS_0
  245. # undef UNDOARGS_5
  246. # define UNDOARGS_5 \
  247. ldw r7, (sp, 0); \
  248. cfi_restore (r4); \
  249. ldw r4, (sp, 4); \
  250. cfi_restore (r4); \
  251. addi sp, 8; \
  252. cfi_adjust_cfa_offset (-8);
  253. # undef UNDOARGS_6
  254. # define UNDOARGS_6 \
  255. ldw r7, (sp, 0); \
  256. cfi_restore (r7); \
  257. ldw r4, (sp, 4); \
  258. cfi_restore (r4); \
  259. ldw r5, (sp, 8); \
  260. cfi_restore (r5); \
  261. addi sp, 16; \
  262. cfi_adjust_cfa_offset (-16);
  263. #else /* not __ASSEMBLER__ */
  264. /* Define a macro which expands into the inline wrapper code for a system
  265. call. */
  266. # undef INLINE_SYSCALL
  267. # define INLINE_SYSCALL(name, nr, args...) \
  268. ({ unsigned int _sys_result = INTERNAL_SYSCALL (name, , nr, args); \
  269. if (__builtin_expect (INTERNAL_SYSCALL_ERROR_P (_sys_result,), 0)) \
  270. { \
  271. __set_errno (INTERNAL_SYSCALL_ERRNO (_sys_result, )); \
  272. _sys_result = (unsigned int) -1; \
  273. } \
  274. (int) _sys_result; })
  275. # undef INTERNAL_SYSCALL_DECL
  276. # define INTERNAL_SYSCALL_DECL(err) do { } while (0)
  277. # undef INTERNAL_SYSCALL_ERROR_P
  278. # define INTERNAL_SYSCALL_ERROR_P(val, err) \
  279. ((unsigned int) (val) >= 0xffffff01u)
  280. # undef INTERNAL_SYSCALL_ERRNO
  281. # define INTERNAL_SYSCALL_ERRNO(val, err) (-(val))
  282. # undef INTERNAL_SYSCALL_RAW
  283. # define INTERNAL_SYSCALL_RAW0(name, err, dummy...) \
  284. ({unsigned int __sys_result; \
  285. { \
  286. register int _a1 __asm__ ("a0"), _nr __asm__ ("r7"); \
  287. _nr = name; \
  288. __asm__ __volatile__ ("trap 0 \n\t" \
  289. : "=r" (_a1) \
  290. : "r" (_nr) \
  291. : "memory"); \
  292. __sys_result = _a1; \
  293. } \
  294. (int) __sys_result; })
  295. # define INTERNAL_SYSCALL_RAW1(name, err, arg1) \
  296. ({unsigned int __sys_result; \
  297. register int _tmp_arg1 = (int)(arg1); \
  298. { \
  299. register int _a1 __asm__ ("a0"), _nr __asm__ ("r7"); \
  300. _a1 = _tmp_arg1; \
  301. _nr = name; \
  302. __asm__ __volatile__ ("trap 0 \n\t" \
  303. : "=r" (_a1) \
  304. : "r" (_nr), "r" (_a1) \
  305. : "memory"); \
  306. __sys_result = _a1; \
  307. } \
  308. (int) __sys_result; })
  309. # define INTERNAL_SYSCALL_RAW2(name, err, arg1, arg2) \
  310. ({unsigned int __sys_result; \
  311. register int _tmp_arg1 = (int)(arg1), _tmp_arg2 = (int)(arg2); \
  312. { \
  313. register int _nr __asm__ ("r7"); \
  314. register int _a1 __asm__ ("a0"), _a2 __asm__ ("a1"); \
  315. _a1 = _tmp_arg1, _a2 = _tmp_arg2; \
  316. _nr = name; \
  317. __asm__ __volatile__ ("trap 0 \n\t" \
  318. : "=r" (_a1) \
  319. : "r" (_nr), "r" (_a1), "r" (_a2) \
  320. : "memory"); \
  321. __sys_result = _a1; \
  322. } \
  323. (int) __sys_result; })
  324. # define INTERNAL_SYSCALL_RAW3(name, err, arg1, arg2, arg3) \
  325. ({unsigned int __sys_result; \
  326. register int _tmp_arg1 = (int)(arg1), _tmp_arg2 = (int)(arg2); \
  327. register int _tmp_arg3 = (int)(arg3); \
  328. { \
  329. register int _nr __asm__ ("r7"); \
  330. register int _a1 __asm__ ("a0"), _a2 __asm__ ("a1"); \
  331. register int _a3 __asm__ ("a2"); \
  332. _a1 = _tmp_arg1; \
  333. _a2 = _tmp_arg2; \
  334. _a3 = _tmp_arg3; \
  335. _nr = name; \
  336. __asm__ __volatile__ ("trap 0 \n\t" \
  337. : "=r" (_a1) \
  338. : "r" (_nr), "r" (_a1), "r" (_a2), \
  339. "r" (_a3) \
  340. : "memory"); \
  341. __sys_result = _a1; \
  342. } \
  343. (int) __sys_result; })
  344. # define INTERNAL_SYSCALL_RAW4(name, err, arg1, arg2, arg3, arg4) \
  345. ({unsigned int __sys_result; \
  346. register int _tmp_arg1 = (int)(arg1), _tmp_arg2 = (int)(arg2); \
  347. register int _tmp_arg3 = (int)(arg3), _tmp_arg4 = (int)(arg4); \
  348. { \
  349. register int _nr __asm__ ("r7"); \
  350. register int _a1 __asm__ ("a0"), _a2 __asm__ ("a1"); \
  351. register int _a3 __asm__ ("a2"), _a4 __asm__ ("a3"); \
  352. _a1 = _tmp_arg1, _a2 = _tmp_arg2, _a3 = _tmp_arg3; \
  353. _a4 = _tmp_arg4; \
  354. _nr = name; \
  355. __asm__ __volatile__ ("trap 0 \n\t" \
  356. : "=r" (_a1) \
  357. : "r" (_nr), "r" (_a1), "r" (_a2), \
  358. "r" (_a3), "r" (_a4) \
  359. : "memory"); \
  360. __sys_result = _a1; \
  361. } \
  362. (int) __sys_result; })
  363. # define INTERNAL_SYSCALL_RAW5(name, err, arg1, arg2, arg3, arg4, \
  364. arg5) \
  365. ({unsigned int __sys_result; \
  366. register int _tmp_arg1 = (int)(arg1), _tmp_arg2 = (int)(arg2); \
  367. register int _tmp_arg3 = (int)(arg3), _tmp_arg4 = (int)(arg4); \
  368. register int _tmp_arg5 = (int)(arg5); \
  369. { \
  370. register int _nr __asm__ ("r7"); \
  371. register int _a1 __asm__ ("a0"), _a2 __asm__ ("a1"); \
  372. register int _a3 __asm__ ("a2"), _a4 __asm__ ("a3"); \
  373. register int _a5 __asm__ ("r4"); \
  374. _a1 = _tmp_arg1, _a2 = _tmp_arg2, _a3 = _tmp_arg3; \
  375. _a4 = _tmp_arg4, _a5 = _tmp_arg5; \
  376. _nr = name; \
  377. __asm__ __volatile__ ("trap 0 \n\t" \
  378. : "=r" (_a1) \
  379. : "r" (_nr), "r" (_a1), "r" (_a2), \
  380. "r" (_a3), "r" (_a4), "r" (_a5) \
  381. : "memory"); \
  382. __sys_result = _a1; \
  383. } \
  384. (int) __sys_result; })
  385. # define INTERNAL_SYSCALL_RAW6(name, err, arg1, arg2, arg3, arg4, \
  386. arg5, arg6) \
  387. ({unsigned int __sys_result; \
  388. register int _tmp_arg1 = (int)(arg1), _tmp_arg2 = (int)(arg2); \
  389. register int _tmp_arg3 = (int)(arg3), _tmp_arg4 = (int)(arg4); \
  390. register int _tmp_arg5 = (int)(arg5), _tmp_arg6 = (int)(arg6); \
  391. { \
  392. register int _nr __asm__ ("r7"); \
  393. register int _a1 __asm__ ("a0"), _a2 __asm__ ("a1"); \
  394. register int _a3 __asm__ ("a2"), _a4 __asm__ ("a3"); \
  395. register int _a5 __asm__ ("r4"), _a6 __asm__ ("r5"); \
  396. _a1 = _tmp_arg1, _a2 = _tmp_arg2, _a3 = _tmp_arg3; \
  397. _a4 = _tmp_arg4, _a5 = _tmp_arg5, _a6 = _tmp_arg6; \
  398. _nr = name; \
  399. __asm__ __volatile__ ("trap 0 \n\t" \
  400. : "=r" (_a1) \
  401. : "r" (_nr), "r" (_a1), "r" (_a2), \
  402. "r" (_a3), "r" (_a4), "r" (_a5), \
  403. "r" (_a6) \
  404. : "memory"); \
  405. __sys_result = _a1; \
  406. } \
  407. (int) __sys_result; })
  408. # define INTERNAL_SYSCALL_RAW7(name, err, arg1, arg2, arg3, arg4, \
  409. arg5, arg6, arg7) \
  410. ({unsigned int __sys_result; \
  411. register int _tmp_arg1 = (int)(arg1), _tmp_arg2 = (int)(arg2); \
  412. register int _tmp_arg3 = (int)(arg3), _tmp_arg4 = (int)(arg4); \
  413. register int _tmp_arg5 = (int)(arg5), _tmp_arg6 = (int)(arg6); \
  414. register int _tmp_arg7 = (int)(arg7); \
  415. { \
  416. register int _nr __asm__ ("r7"); \
  417. register int _a1 __asm__ ("a0"), _a2 __asm__ ("a1"); \
  418. register int _a3 __asm__ ("a2"), _a4 __asm__ ("a3"); \
  419. register int _a5 __asm__ ("r4"), _a6 __asm__ ("r5"); \
  420. register int _a7 __asm__ ("r6"); \
  421. _a1 = _tmp_arg1, _a2 = _tmp_arg2, _a3 = _tmp_arg3; \
  422. _a4 = _tmp_arg4, _a5 = _tmp_arg5, _a6 = _tmp_arg6; \
  423. _a7 = _tmp_arg7; \
  424. _nr = name; \
  425. __asm__ __volatile__ ("trap 0 \n\t" \
  426. : "=r" (_a1) \
  427. : "r" (_nr), "r" (_a1), "r" (_a2), \
  428. "r" (_a3), "r" (_a4), "r" (_a5), \
  429. "r" (_a6), "r" (_a7) \
  430. : "memory"); \
  431. __sys_result = _a1; \
  432. } \
  433. (int) __sys_result; })
  434. # undef INTERNAL_SYSCALL
  435. # define INTERNAL_SYSCALL(name, err, nr, args...) \
  436. INTERNAL_SYSCALL_RAW##nr(SYS_ify(name), err, args)
  437. # undef INTERNAL_SYSCALL_NCS
  438. # define INTERNAL_SYSCALL_NCS(number, err, nr, args...) \
  439. INTERNAL_SYSCALL_RAW##nr (number, err, args)
  440. #endif /* __ASSEMBLER__ */
  441. /* Pointer mangling support. */
  442. #if (IS_IN (rtld) || \
  443. (!defined SHARED && (IS_IN (libc) || IS_IN (libpthread))))
  444. # ifdef __ASSEMBLER__
  445. # define PTR_MANGLE(dst, src, guard) \
  446. grs t0, 1f; \
  447. 1: \
  448. lrw guard, 1b@GOTPC; \
  449. addu t0, guard; \
  450. lrw guard, __pointer_chk_guard_local@GOT; \
  451. ldr.w guard, (t0, guard << 0); \
  452. ldw guard, (guard, 0); \
  453. xor dst, src, guard;
  454. # define PTR_DEMANGLE(dst, src, guard) PTR_MANGLE (dst, src, guard)
  455. # define PTR_MANGLE2(dst, src, guard) \
  456. xor dst, src, guard
  457. # define PTR_DEMANGLE2(dst, src, guard) PTR_MANGLE2 (dst, src, guard)
  458. # else
  459. extern uintptr_t __pointer_chk_guard_local;
  460. # define PTR_MANGLE(var) \
  461. (var) = (__typeof (var)) ((uintptr_t) (var) ^ __pointer_chk_guard_local)
  462. # define PTR_DEMANGLE(var) PTR_MANGLE (var)
  463. # endif
  464. #else
  465. # ifdef __ASSEMBLER__
  466. # define PTR_MANGLE(dst, src, guard) \
  467. grs t0, 1f; \
  468. 1: \
  469. lrw guard, 1b@GOTPC; \
  470. addu t0, guard; \
  471. lrw guard, __pointer_chk_guard@GOT; \
  472. ldr.w guard, (t0, guard << 0); \
  473. ldw guard, (guard, 0); \
  474. xor dst, src, guard;
  475. # define PTR_DEMANGLE(dst, src, guard) PTR_MANGLE (dst, src, guard)
  476. # define PTR_MANGLE2(dst, src, guard) \
  477. xor dst, src, guard
  478. # define PTR_DEMANGLE2(dst, src, guard) PTR_MANGLE2 (dst, src, guard)
  479. # else
  480. extern uintptr_t __pointer_chk_guard;
  481. # define PTR_MANGLE(var) \
  482. (var) = (__typeof (var)) ((uintptr_t) (var) ^ __pointer_chk_guard)
  483. # define PTR_DEMANGLE(var) PTR_MANGLE (var)
  484. # endif
  485. #endif
  486. #endif /* linux/csky/sysdep.h */