summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/csu/m88k/crt0.c89
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"