2000-02-10 Andreas Jaeger <aj@suse.de>

* sysdeps/unix/sysv/linux/mips/clone.S: Rewritten.
	Based on a patch by Hiroyuki Machida <machida@sm.sony.co.jp>.
This commit is contained in:
Andreas Jaeger 2000-02-10 11:09:31 +00:00
parent b7393d1c58
commit a233bb29c8

View File

@ -1,4 +1,4 @@
/* Copyright (C) 1996, 1997 Free Software Foundation, Inc. /* Copyright (C) 1996, 1997, 2000 Free Software Foundation, Inc.
This file is part of the GNU C Library. This file is part of the GNU C Library.
Contributed by Ralf Baechle <ralf@gnu.ai.mit.edu>, 1996. Contributed by Ralf Baechle <ralf@gnu.ai.mit.edu>, 1996.
@ -26,9 +26,9 @@
#define _ERRNO_H 1 #define _ERRNO_H 1
#include <bits/errno.h> #include <bits/errno.h>
/* int clone(int (*fn)(), void *child_stack, int flags, int nargs, ...) */ /* int clone(int (*fn)(), void *child_stack, int flags, void *arg) */
#define FRAMESZ 4*SZREG #define FRAMESZ 8*SZREG
#if _MIPS_SIM == _MIPS_SIM_ABI32 #if _MIPS_SIM == _MIPS_SIM_ABI32
#define MAX_REG_ARGS 4 #define MAX_REG_ARGS 4
#else #else
@ -36,14 +36,16 @@
#endif #endif
.text .text
NESTED(__clone,4*SZREG,sp) NESTED(__clone,FRAMESZ,sp)
#ifdef PIC #ifdef __PIC__
.set noreorder .set noreorder
.cpload $25 .cpload $25
.set reorder .set reorder
.cprestore 16
#endif
PTR_SUBIU sp,FRAMESZ PTR_SUBIU sp,FRAMESZ
.cprestore SZREG*4
#else
PTR_SUBIU sp,FRAMESZ
#endif
#ifdef PROF #ifdef PROF
.set noat .set noat
move $1,ra move $1,ra
@ -51,25 +53,20 @@ NESTED(__clone,4*SZREG,sp)
.set at .set at
#endif #endif
REG_S s0,FRAMESZ-SZREG*2(sp)
REG_S s1,FRAMESZ-SZREG*3(sp)
/* Sanity check arguments. */ /* Sanity check arguments. */
li v0,EINVAL li v0,EINVAL
beqz a0,error /* no NULL function pointers */ beqz a0,error /* no NULL function pointers */
beqz a1,error /* no NULL stack pointers */ beqz a1,error /* no NULL stack pointers */
bltz a3,error /* no negative argument counts */
/* Allocate space on the new stack and copy args over */ /* Allocate space on the new stack and copy args over */
move t0,a3 # save nargs for __thread_start /* Save the arg for user's function */
PTR_SLL t1,a3,PTR_SCALESHIFT move s0,a3 /* Save arg __thread_start. */
PTR_ADDU t1,a3,sp move s1,a0 /* Save func. pointer. */
1: REG_L t2,-SZREG(t1)
PTR_SUBIU t1,SZREG
REG_S t2,-SZREG(a1)
PTR_SUBIU a3,1
PTR_SUBIU a1,SZREG
bnez a3,1b
/* Do the system call */ /* Do the system call */
move t9,a0 # get fn ptr out of the way
move a0,a2 move a0,a2
li v0,__NR_clone li v0,__NR_clone
syscall syscall
@ -78,11 +75,15 @@ NESTED(__clone,4*SZREG,sp)
beqz v0,__thread_start beqz v0,__thread_start
/* Successful return from the parent */ /* Successful return from the parent */
REG_L s0,FRAMESZ-SZREG*2(sp)
REG_L s1,FRAMESZ-SZREG*3(sp)
PTR_ADDIU sp,FRAMESZ PTR_ADDIU sp,FRAMESZ
ret ret
/* Something bad happened -- no child created */ /* Something bad happened -- no child created */
error: error:
REG_L s0,FRAMESZ-SZREG*2(sp)
REG_L s1,FRAMESZ-SZREG*3(sp)
PTR_ADDIU sp,FRAMESZ PTR_ADDIU sp,FRAMESZ
#ifdef PIC #ifdef PIC
la t9,__syscall_error la t9,__syscall_error
@ -96,30 +97,25 @@ error:
its own function so that we can terminate the stack trace with our its own function so that we can terminate the stack trace with our
debug info. debug info.
At this point we have t0=nargs, t9=fn, sp=&arg[0]. */ At this point we have s0=arg, s1=fn. */
NESTED(__thread_start,32,sp) NESTED(__thread_start,FRAMESZ,sp)
/* Stackframe has been created on entry of clone() */ /* The stackframe has been created on entry of clone(). */
/* Calculate address of jump into argument loading code */ /* Resort the arg for user's function. */
li t1,MAX_REG_ARGS move a0,s0
slt t0,t1,t2 /* max MAX_REG_ARGS args in registers */ move t9,s1
MOVN (t2,t1,t0)
la v0,arg0
PTR_SLL t1,t0,PTR_SCALESHIFT
PTR_SUBU v0,t1
jr v0
/* Load the integer register arguments */ /* Call the user's function. */
REG_L a0,SZREG(sp)
arg0:
/* Call the user's function */
jalr t9 jalr t9
/* Call _exit rather than doing it inline for breakpoint purposes */ /* Call _exit rather than doing it inline for breakpoint purposes. */
move a0,v0 move a0,v0
#ifdef __PIC__
la t9,_exit
jalr t9
#else
jal _exit jal _exit
#endif
END(__thread_start) END(__thread_start)
weak_alias(__clone, clone) weak_alias(__clone, clone)