| ... | ... | @@ -118,9 +118,6 @@ pub fn syscall5(number: SYS, arg1: usize, arg2: usize, arg3: usize, arg4: usize, |
| 118 | 118 | ); |
| 119 | 119 | } |
| 120 | 120 | |
| 121 | | // NOTE: The o32 calling convention requires the callee to reserve 16 bytes for |
| 122 | | // the first four arguments even though they're passed in $a0-$a3. |
| 123 | | |
| 124 | 121 | pub fn syscall6( |
| 125 | 122 | number: SYS, |
| 126 | 123 | arg1: usize, |
| ... | ... | @@ -175,10 +172,44 @@ pub fn syscall7( |
| 175 | 172 | ); |
| 176 | 173 | } |
| 177 | 174 | |
| 178 | | const CloneFn = *const fn (arg: usize) callconv(.C) u8; |
| 179 | | |
| 180 | | /// This matches the libc clone function. |
| 181 | | pub extern fn clone(func: CloneFn, stack: usize, flags: u32, arg: usize, ptid: *i32, tls: usize, ctid: *i32) usize; |
| 175 | pub fn clone() callconv(.Naked) usize { |
| 176 | // __clone(func, stack, flags, arg, ptid, tls, ctid) |
| 177 | // 3, 4, 5, 6, 7, 8, 9 |
| 178 | // |
| 179 | // syscall(SYS_clone, flags, stack, ptid, tls, ctid) |
| 180 | // 2 4, 5, 6, 7, 8 |
| 181 | asm volatile ( |
| 182 | \\ # Save function pointer and argument pointer on new thread stack |
| 183 | \\ and $5, $5, -16 |
| 184 | \\ dsubu $5, $5, 16 |
| 185 | \\ sd $4, 0($5) |
| 186 | \\ sd $7, 8($5) |
| 187 | \\ # Shuffle (fn,sp,fl,arg,ptid,tls,ctid) to (fl,sp,ptid,tls,ctid) |
| 188 | \\ move $4, $6 |
| 189 | \\ move $6, $8 |
| 190 | \\ move $7, $9 |
| 191 | \\ move $8, $10 |
| 192 | \\ li $2, 5055 # SYS_clone |
| 193 | \\ syscall |
| 194 | \\ beq $7, $0, 1f |
| 195 | \\ nop |
| 196 | \\ jr $ra |
| 197 | \\ dsubu $2, $0, $2 |
| 198 | \\1: |
| 199 | \\ beq $2, $0, 1f |
| 200 | \\ nop |
| 201 | \\ jr $ra |
| 202 | \\ nop |
| 203 | \\1: |
| 204 | \\ ld $25, 0($sp) |
| 205 | \\ ld $4, 8($sp) |
| 206 | \\ jalr $25 |
| 207 | \\ nop |
| 208 | \\ move $4, $2 |
| 209 | \\ li $2, 5058 # SYS_exit |
| 210 | \\ syscall |
| 211 | ); |
| 212 | } |
| 182 | 213 | |
| 183 | 214 | pub fn restore() callconv(.Naked) noreturn { |
| 184 | 215 | asm volatile ( |