clone.S 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  1. /*
  2. * Copyright (C) 2016 Andes Technology, Inc.
  3. * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
  4. */
  5. /* clone() is even more special than fork() as it mucks with stacks
  6. and invokes a function in the right context after its all over. */
  7. #include <sysdep.h>
  8. #include <sys/syscall.h>
  9. #define _ERRNO_H 1
  10. #include <bits/errno.h>
  11. /*
  12. int clone(int (*fn)(void *), void *child_stack, int flags, void *arg);
  13. _syscall2(int, clone, int, flags, void *, child_stack)
  14. */
  15. ENTRY(__clone)
  16. #ifdef PIC
  17. /* set GP register to parent only, cause child's $SP will be $r1. */
  18. pushm $fp, $gp
  19. #ifndef __NDS32_N1213_43U1H__
  20. mfusr $r15, $PC
  21. #endif
  22. sethi $gp, hi20(_GLOBAL_OFFSET_TABLE_+4)
  23. ori $gp, $gp, lo12(_GLOBAL_OFFSET_TABLE_+8)
  24. add $gp, $gp, $r15
  25. #endif
  26. /* sanity check arguments. */
  27. beqz $r0, 1f
  28. bnez $r1, 2f
  29. 1:
  30. movi $r0, -EINVAL
  31. 5:
  32. #ifdef PIC
  33. /* restore GP register, only in parent's stack */
  34. popm $fp, $gp
  35. la $r15, C_SYMBOL_NAME(__syscall_error@PLT)
  36. jr $r15
  37. #else
  38. b C_SYMBOL_NAME(__syscall_error)
  39. #endif
  40. 2:
  41. /* Child's $SP will be $r1, push to child's stack only. */
  42. addi $r1, $r1, -4
  43. swi.p $r3, [$r1], -4 ! arg
  44. swi $r0, [$r1] ! fn
  45. /* do the system call */
  46. or $r0, $r2, $r2 ! move r0, r2
  47. __do_syscall(clone)
  48. !syscall (__NR_clone)
  49. beqz $r0, 4f
  50. bltz $r0, 5b
  51. ! parent
  52. #ifdef PIC
  53. /* restore GP register, only in parent's stack */
  54. popm $fp, $gp
  55. #endif
  56. ret
  57. 4:
  58. /* Only in child's stack. */
  59. pop $r1 ! fn
  60. pop $r0 ! arg
  61. #if defined(NDS32_ABI_2) || defined(NDS32_ABI_2FP)
  62. #else
  63. addi $sp, $sp, -24
  64. #endif
  65. ! use r15 in case _exit is PIC
  66. #ifdef __NDS32_N1213_43U1H__
  67. or $r15, $r1, $r1 ! move r15, r2
  68. #endif
  69. bral $r1
  70. #if defined(NDS32_ABI_2) || defined(NDS32_ABI_2FP)
  71. #else
  72. addi $sp, $sp, 24
  73. #endif
  74. ! use r15 in case _exit is PIC
  75. #ifdef PIC
  76. la $r15, C_SYMBOL_NAME(_exit@PLT)
  77. jr $r15
  78. #else
  79. b C_SYMBOL_NAME(_exit)
  80. #endif
  81. PSEUDO_END (__clone)
  82. weak_alias (__clone, clone)