| ... | @@ -386,6 +386,11 @@ fn clone() callconv(.Naked) void { | ... | @@ -386,6 +386,11 @@ fn clone() callconv(.Naked) void { |
| 386 | ); | 386 | ); |
| 387 | }, | 387 | }, |
| 388 | .arm => { | 388 | .arm => { |
| | 389 | // __clone(func, stack, flags, arg, ptid, tls, ctid) |
| | 390 | // r0, r1, r2, r3, +0, +4, +8 |
| | 391 | |
| | 392 | // syscall(SYS_clone, flags, stack, ptid, tls, ctid) |
| | 393 | // r7 r0, r1, r2, r3, r4 |
| 389 | asm volatile ( | 394 | asm volatile ( |
| 390 | \\ stmfd sp!,{r4,r5,r6,r7} | 395 | \\ stmfd sp!,{r4,r5,r6,r7} |
| 391 | \\ mov r7,#120 | 396 | \\ mov r7,#120 |
| ... | @@ -445,6 +450,11 @@ fn clone() callconv(.Naked) void { | ... | @@ -445,6 +450,11 @@ fn clone() callconv(.Naked) void { |
| 445 | ); | 450 | ); |
| 446 | }, | 451 | }, |
| 447 | .mips, .mipsel => { | 452 | .mips, .mipsel => { |
| | 453 | // __clone(func, stack, flags, arg, ptid, tls, ctid) |
| | 454 | // 3, 4, 5, 6, 7, 8, 9 |
| | 455 | |
| | 456 | // syscall(SYS_clone, flags, stack, ptid, tls, ctid) |
| | 457 | // 2 4, 5, 6, 7, 8 |
| 448 | asm volatile ( | 458 | asm volatile ( |
| 449 | \\ # Save function pointer and argument pointer on new thread stack | 459 | \\ # Save function pointer and argument pointer on new thread stack |
| 450 | \\ and $5, $5, -8 | 460 | \\ and $5, $5, -8 |
| ... | @@ -465,12 +475,14 @@ fn clone() callconv(.Naked) void { | ... | @@ -465,12 +475,14 @@ fn clone() callconv(.Naked) void { |
| 465 | \\ addu $sp, $sp, 16 | 475 | \\ addu $sp, $sp, 16 |
| 466 | \\ jr $ra | 476 | \\ jr $ra |
| 467 | \\ subu $2, $0, $2 | 477 | \\ subu $2, $0, $2 |
| 468 | \\1: beq $2, $0, 1f | 478 | \\1: |
| | 479 | \\ beq $2, $0, 1f |
| 469 | \\ nop | 480 | \\ nop |
| 470 | \\ addu $sp, $sp, 16 | 481 | \\ addu $sp, $sp, 16 |
| 471 | \\ jr $ra | 482 | \\ jr $ra |
| 472 | \\ nop | 483 | \\ nop |
| 473 | \\1: lw $25, 0($sp) | 484 | \\1: |
| | 485 | \\ lw $25, 0($sp) |
| 474 | \\ lw $4, 4($sp) | 486 | \\ lw $4, 4($sp) |
| 475 | \\ jalr $25 | 487 | \\ jalr $25 |
| 476 | \\ nop | 488 | \\ nop |
| ... | @@ -480,51 +492,48 @@ fn clone() callconv(.Naked) void { | ... | @@ -480,51 +492,48 @@ fn clone() callconv(.Naked) void { |
| 480 | ); | 492 | ); |
| 481 | }, | 493 | }, |
| 482 | .powerpc64, .powerpc64le => { | 494 | .powerpc64, .powerpc64le => { |
| | 495 | // __clone(func, stack, flags, arg, ptid, tls, ctid) |
| | 496 | // 3, 4, 5, 6, 7, 8, 9 |
| | 497 | |
| | 498 | // syscall(SYS_clone, flags, stack, ptid, tls, ctid) |
| | 499 | // 0 3, 4, 5, 6, 7 |
| 483 | asm volatile ( | 500 | asm volatile ( |
| 484 | \\ # store non-volatile regs r30, r31 on stack in order to put our | | |
| 485 | \\ # start func and its arg there | | |
| 486 | \\ stwu 30, -16(1) | | |
| 487 | \\ stw 31, 4(1) | | |
| 488 | \\ # save r3 (func) into r30, and r6(arg) into r31 | | |
| 489 | \\ mr 30, 3 | | |
| 490 | \\ mr 31, 6 | | |
| 491 | \\ # create initial stack frame for new thread | 501 | \\ # create initial stack frame for new thread |
| 492 | \\ clrrwi 4, 4, 4 | 502 | \\ clrrdi 4, 4, 4 |
| 493 | \\ li 0, 0 | 503 | \\ li 0, 0 |
| 494 | \\ stwu 0, -16(4) | 504 | \\ stdu 0,-32(4) |
| 495 | \\ #move c into first arg | 505 | \\ |
| 496 | \\ mr 3, 5 | 506 | \\ # save fn and arg to child stack |
| 497 | \\ mr 5, 7 | 507 | \\ std 3, 8(4) |
| 498 | \\ mr 6, 8 | 508 | \\ std 6, 16(4) |
| 499 | \\ mr 7, 9 | 509 | \\ |
| 500 | \\ # move syscall number into r0 | 510 | \\ # shuffle args into correct registers and call SYS_clone |
| 501 | \\ li 0, 120 | 511 | \\ mr 3, 5 |
| | 512 | \\ #mr 4, 4 |
| | 513 | \\ mr 5, 7 |
| | 514 | \\ mr 6, 8 |
| | 515 | \\ mr 7, 9 |
| | 516 | \\ li 0, 120 # SYS_clone = 120 |
| 502 | \\ sc | 517 | \\ sc |
| 503 | \\ # check for syscall error | 518 | \\ |
| 504 | \\ bns+ 1f # jump to label 1 if no summary overflow. | 519 | \\ # if error, negate return (errno) |
| 505 | \\ #else | 520 | \\ bns+ 1f |
| 506 | \\ neg 3, 3 #negate the result (errno) | 521 | \\ neg 3, 3 |
| | 522 | \\ |
| 507 | \\1: | 523 | \\1: |
| 508 | \\ # compare sc result with 0 | 524 | \\ # if we're the parent, return |
| 509 | \\ cmpwi cr7, 3, 0 | 525 | \\ cmpwi cr7, 3, 0 |
| 510 | \\ # if not 0, jump to end | 526 | \\ bnelr cr7 |
| 511 | \\ bne cr7, 2f | 527 | \\ |
| 512 | \\ #else: we're the child | 528 | \\ # we're the child. call fn(arg) |
| 513 | \\ #call funcptr: move arg (d) into r3 | 529 | \\ ld 3, 16(1) |
| 514 | \\ mr 3, 31 | 530 | \\ ld 12, 8(1) |
| 515 | \\ #move r30 (funcptr) into CTR reg | 531 | \\ mtctr 12 |
| 516 | \\ mtctr 30 | | |
| 517 | \\ # call CTR reg | | |
| 518 | \\ bctrl | 532 | \\ bctrl |
| 519 | \\ # mov SYS_exit into r0 (the exit param is already in r3) | 533 | \\ |
| 520 | \\ li 0, 1 | 534 | \\ # call SYS_exit. exit code is already in r3 from fn return value |
| | 535 | \\ li 0, 1 # SYS_exit = 1 |
| 521 | \\ sc | 536 | \\ sc |
| 522 | \\2: | | |
| 523 | \\ # restore stack | | |
| 524 | \\ lwz 30, 0(1) | | |
| 525 | \\ lwz 31, 4(1) | | |
| 526 | \\ addi 1, 1, 16 | | |
| 527 | \\ blr | | |
| 528 | ); | 537 | ); |
| 529 | }, | 538 | }, |
| 530 | .sparcv9 => { | 539 | .sparcv9 => { |