clone.s 1.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273
  1. .text
  2. .global __clone
  3. .hidden __clone
  4. .type __clone, %function
  5. __clone:
  6. # int clone(fn, stack, flags, arg, ptid, tls, ctid)
  7. # a b c d e f g
  8. # 3 4 5 6 7 8 9
  9. # pseudo C code:
  10. # tid = syscall(SYS_clone,c,b,e,f,g);
  11. # if (!tid) syscall(SYS_exit, a(d));
  12. # return tid;
  13. # SYS_clone = 120
  14. # SYS_exit = 1
  15. # store non-volatile regs r30, r31 on stack in order to put our
  16. # start func and its arg there
  17. stwu 30, -16(1)
  18. stw 31, 4(1)
  19. # save r3 (func) into r30, and r6(arg) into r31
  20. mr 30, 3
  21. mr 31, 6
  22. # create initial stack frame for new thread
  23. clrrwi 4, 4, 4
  24. li 0, 0
  25. stwu 0, -16(4)
  26. #move c into first arg
  27. mr 3, 5
  28. #mr 4, 4
  29. mr 5, 7
  30. mr 6, 8
  31. mr 7, 9
  32. # move syscall number into r0
  33. li 0, 120
  34. sc
  35. # check for syscall error
  36. bns+ 1f # jump to label 1 if no summary overflow.
  37. #else
  38. neg 3, 3 #negate the result (errno)
  39. 1:
  40. # compare sc result with 0
  41. cmpwi cr7, 3, 0
  42. # if not 0, jump to end
  43. bne cr7, 2f
  44. #else: we're the child
  45. #call funcptr: move arg (d) into r3
  46. mr 3, 31
  47. #move r30 (funcptr) into CTR reg
  48. mtctr 30
  49. # call CTR reg
  50. bctrl
  51. # mov SYS_exit into r0 (the exit param is already in r3)
  52. li 0, 1
  53. sc
  54. 2:
  55. # restore stack
  56. lwz 30, 0(1)
  57. lwz 31, 4(1)
  58. addi 1, 1, 16
  59. blr