diff options
-rw-r--r-- | lib/csu/m88k/crt0.c | 89 |
1 files changed, 65 insertions, 24 deletions
diff --git a/lib/csu/m88k/crt0.c b/lib/csu/m88k/crt0.c index f87274a2692..ac4e2a0f72e 100644 --- a/lib/csu/m88k/crt0.c +++ b/lib/csu/m88k/crt0.c @@ -1,4 +1,4 @@ -/* $OpenBSD: crt0.c,v 1.4 2003/12/25 23:26:09 miod Exp $ */ +/* $OpenBSD: crt0.c,v 1.5 2003/12/26 00:04:23 miod Exp $ */ /* * Mach Operating System @@ -28,40 +28,80 @@ */ #if defined(LIBC_SCCS) && !defined(lint) -static char rcsid[] = "$OpenBSD: crt0.c,v 1.4 2003/12/25 23:26:09 miod Exp $"; +static char rcsid[] = "$OpenBSD: crt0.c,v 1.5 2003/12/26 00:04:23 miod Exp $"; #endif /* LIBC_SCCS and not lint */ +/* + * Author : Jeffrey Friedl + * Created: July 1992 + * Standalone crt0. + */ + +/* + * GCCisms used: + * A "volatile void fcn()" is one that never returns. + * register var asm("r1"): variable VAR is raw access to named register. + */ + /* - * When a program starts, r31 points to a structure passed from the kernel. + * When a program begins, r31 points to info passed from the kernel. + * + * The following shows the memory to which r31 points (think "int *r31;"), + * and how we derive argc, argv, and envp from that: * - * This structure contains argc, the argv[] array, a NULL marker, then - * the envp[] array, and another NULL marker. + * +-------------------+ <-------------------------------------- r31 + * | ARGC | <- argc = r31[0]; + * +-------------------+ <- argv = &r31[1]; + * | &(argument #1) | + * +-------------------+ + * | &(argument #2) | + * - - - - - - - - - + * | &(argument #ARGC) | + * +-------------------+ + * | 0x00000000 | <- end-of-ARGV-list marker (redundant information). + * +-------------------+ <- environ = envp = &argv[argc+1]; + * | &(env. var. #1) | + * +-------------------+ + * | &(env. var. #2) | + * - - - - - - - - - + * | &(env. var. #N) | + * +-------------------+ + * | 0x00000000 | <- end-of-ENVP-list marker (not redundant!). + * +-------------------+ + * + * We use 'start:' to grab r31 and call real_start(argc, argv, envp). + * We must do this since the function prologue makes finding the initial + * r31 difficult in C. */ #include <stdlib.h> #include "common.h" -extern void start(void) __asm__("start"); - -void -start(void) -{ - struct kframe { - int argc; - char *argv[0]; - }; +asm(" text "); +asm(" align 4 "); +asm("start: global start "); +asm(" ld r2, r31, 0 "); /* First arg to real_start: argc */ +asm(" addu r3, r31, 4 "); /* Second arg to real_start: argv */ +asm(" lda r4, r3 [r2]"); /* Third arg to real_start: envp, but.... */ +asm(" addu r4, r4, 4 "); /* ... don't forget to skip past marker */ +asm(" br.n ___crt0_real_start"); +asm(" subu r31, r31, 32 "); - struct kframe *kfp; - char **argv, *ap, *s; +#ifdef DYNAMIC +extern struct _dynamic _DYNAMIC; +struct _dynamic *___pdynamic = &_DYNAMIC; +#endif - /* - * Pick the arguments frame as early as possible - */ - __asm__ __volatile__ ("or %0, r31, 0" : "=r" (kfp) :: "r31"); +/* static */ void volatile +__crt0_real_start(int argc, char *argv[], char *envp[]) +{ + register char *ap; + volatile int a = 0; + extern int end; + char *s; - argv = &kfp->argv[0]; - environ = argv + kfp->argc + 1; + environ = envp; /* environ is for the user that can't get at 'envp' */ if (ap = argv[0]) { if ((__progname = _strrchr(ap, '/')) == NULL) @@ -74,9 +114,10 @@ start(void) *s = '\0'; __progname = __progname_storage; } - asm ("__callmain:"); /* Defined for the benefit of debuggers */ - exit(main(kfp->argc, argv, environ)); + exit(main(argc, argv, environ)); + + /*NOTREACHED*/ } #include "common.c" |