This is the mail archive of the newlib@sources.redhat.com mailing list for the newlib project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[patch RFA] update MIPS libgloss CFE support to be ... better.


This updates the MIPS libgloss CFE support to be ... better.

In particular:

        * doesn't do nasty things to CP0 registers at startup.

        * less hack-ish startup sequence (no special prestart function
          to squirrel incoming args away).

        * detects and makes available all memory in kseg0 for program
          operation.

        * provides a more pluggable low-level memory allocation
          interface, so that people who want to can implement
          something Better.  (we've had people use this to implement
          access via TLBs, and other stuff...  *shudder*)


when applying, be sure to 'patch -E' then cvs delete the
cfe_prestart.S file.  8-)

tested with mipsisa64-elf against a target board running CFE.  Results
as expected when compared to same target running sim.


BTW, if any of you are wondering what CFE *is*, i can't resist a plug:

        http://sibyte.broadcom.com/public/resources/#cfe

8-)


chris
--
2003-08-15  Chris Demetriou  <cgd@broadcom.com>

	* mips/crt0_cfe.S: New file.
	* mips/cfe_mem.c: New file.
	* mips/cfe_prestart.S: Remove.
	* mips/cfe.ld: Adjust to use crt0_cfe.o as the startup file, and
	and use _start as the entry point.  Align BSS to 32-byte boundary.
	* mips/cfe.c: Reimplement to fit on top of a crt0_cfe.o file.
	* mips/cfe_api.h (__libcfe_stack_size, __libcfe_mem_limit)
	(__libcfe_meminit, __libcfe_stack_top): New prototypes.
	* mips/Makefile.in (CFEOBJS): Replace cfe_prestart.o with cfe_mem.o.
	(cfe.o, cfe_api.o, cfe_mem.o, crt0_cfe.o): New targets.
	* mips/configure.in: Build and install crt0_cfe.o when CFE support
	is built.
	* mips/configure: Regenerate.

Index: mips/Makefile.in
===================================================================
RCS file: /cvs/src/src/libgloss/mips/Makefile.in,v
retrieving revision 1.4
diff -u -p -r1.4 Makefile.in
--- mips/Makefile.in	12 Nov 2002 23:14:24 -0000	1.4
+++ mips/Makefile.in	13 Aug 2003 20:49:44 -0000
@@ -73,8 +73,7 @@ PMONOBJS = pmon.o @part_specific_obj@ ${
 LSIOBJS = lsipmon.o @part_specific_obj@ ${GENOBJS}
 DVEOBJS = dvemon.o @part_specific_obj@ ${GENOBJS} ${GENOBJS2}
 JMR3904OBJS = jmr3904-io.o @part_specific_obj@ ${GENOBJS} ${GENOBJS2}
-CFEOBJS = cfe.o cfe_api.o cfe_prestart.o \
-	@part_specific_obj@ ${GENOBJS} ${GENOBJS2}
+CFEOBJS = cfe.o cfe_api.o cfe_mem.o @part_specific_obj@ ${GENOBJS} ${GENOBJS2}
 CYGMONOBJS = open.o close.o cygmon.o @part_specific_obj@ ${GENOBJS}
 
 # Nullmon cannot support read and write, but the test cases pull them in via libs
@@ -136,7 +135,6 @@ libcygmon.a: $(CYGMONOBJS)
 	${AR} ${ARFLAGS} $@ $(CYGMONOBJS)
 	${RANLIB} $@
 
-
 libcfe.a: $(CFEOBJS)
 	${AR} ${ARFLAGS} $@ $(CFEOBJS)
 	${RANLIB} $@
@@ -219,6 +217,7 @@ test.o:	${srcdir}/test.c
 crt0.o: ${srcdir}/crt0.S
 pcrt0.o: ${srcdir}/crt0.S
 	$(CC) -c $(CFLAGS_FOR_TARGET) $(CFLAGS) -DGCRT0 ${srcdir}/crt0.S -o ${PCRT0}
+crt0_cfe.o: ${srcdir}/crt0_cfe.S
 crt0_cygmon.o: ${srcdir}/crt0_cygmon.S
 idtmon.o: ${srcdir}/idtmon.S
 pmon.o: ${srcdir}/pmon.S
@@ -230,6 +229,12 @@ vr5xxx.o: ${srcdir}/vr5xxx.S
 lsipmon.o: $(srcdir)/lsipmon.S $(srcdir)/pmon.S
 jmr3904-io.o: ${srcdir}/jmr3904-io.c
 	$(CC) -c $(CFLAGS_FOR_TARGET) $(CFLAGS) ${srcdir}/jmr3904-io.c -o $@
+cfe.o: ${srcdir}/cfe.c ${srcdir}/cfe_api.h
+	$(CC) -c $(CFLAGS_FOR_TARGET) $(CFLAGS) ${srcdir}/cfe.c -o $@
+cfe_api.o: ${srcdir}/cfe_api.c ${srcdir}/cfe_api.h ${srcdir}/cfe_api_int.h
+	$(CC) -c $(CFLAGS_FOR_TARGET) $(CFLAGS) ${srcdir}/cfe_api.c -o $@
+cfe_mem.o: ${srcdir}/cfe_mem.c ${srcdir}/cfe_api.h
+	$(CC) -c $(CFLAGS_FOR_TARGET) $(CFLAGS) ${srcdir}/cfe_mem.c -o $@
 
 # cma101 can not be compiled mips16, if a mips16 version is needed then
 # it will have to be built, then this rule can be scrapped, allowing
Index: mips/cfe.c
===================================================================
RCS file: /cvs/src/src/libgloss/mips/cfe.c,v
retrieving revision 1.4
diff -u -p -r1.4 cfe.c
--- mips/cfe.c	10 Apr 2003 20:07:57 -0000	1.4
+++ mips/cfe.c	13 Aug 2003 20:49:44 -0000
@@ -1,7 +1,7 @@
 /* cfe.c -- I/O code for the MIPS boards running CFE.  */
 
 /*
- * Copyright 2001, 2002
+ * Copyright 2001, 2002, 2003
  * Broadcom Corporation. All rights reserved.
  * 
  * This software is furnished under license and may be used and copied only
@@ -32,37 +32,40 @@
 
 #include "cfe_api.h"
 
+void *__libcfe_init (long handle, long a1, long cfe_entrypoint, long a3);
+void __libcfe_exit (long status);
+
 char inbyte (void);
 int outbyte (char c);
 
-/* Make sure cfe_prestart is used.  It doesn't look like setting the
-   entry symbol in the linker script to a symbol from that fiel will do
-   this!  */
-extern int _prestart;
-static void *force_prestart = &_prestart;
-
-/* The following variables are initialized to non-zero so that they'll be
-   in data, rather than BSS.  Used to be that you could init variables to
-   any value to put them into initialized data sections rather than BSS,
-   but that decades-old idiom went out the window with gcc 3.2.  Now,
-   either you compile specially (with -fno-zero-initialized-in-bss), or
-   you init to non-zero.  In this case, initting to non-zero is OK (and
-   even beneficial; alignment fault via jump to odd if not properly
-   set up by _prestart()), so we do the latter.
-
-   These variables are 'int's so they can be reliably stored w/ "sw".
-   (longs fall victim to -mlong64.)  They are signed so that they remain
-   valid pointers when extended to cfe_xuint_t in the call to cfe_init().
-   This assumes that they are compatibility-space pointers.  */
-int __cfe_handle = 0xdeadbeef;
-int __cfe_entrypt = 0xdeadbeef;
-
 /* Echo input characters?  */
-int	__cfe_echo_input = 0;
+int	__libcfe_echo_input = 0;
 
 /* CFE handle used to access console device.  */
 static int cfe_conshandle;
 
+
+/* Initialize firmware callbacks.  Called from crt0_cfe.  Returns desired
+   stack pointer.  */
+void *
+__libcfe_init (long handle, long a1, long entrypoint, long a3)
+{
+  cfe_init (handle, entrypoint);
+  cfe_conshandle = cfe_getstdhandle (CFE_STDHANDLE_CONSOLE);
+
+  __libcfe_meminit ();
+  return __libcfe_stack_top ();
+}
+
+/* Exit back to monitor, with the given status code.  */
+void
+__libcfe_exit (long status)
+{
+  outbyte ('\r');
+  outbyte ('\n');
+  cfe_exit (CFE_FLG_WARMSTART, status);
+}
+
 char
 inbyte (void)
 {
@@ -73,7 +76,7 @@ inbyte (void)
     ;
   if (c == '\r')
     c = '\n';
-  if (__cfe_echo_input)
+  if (__libcfe_echo_input)
     outbyte (c);
   return c;
 }
@@ -91,41 +94,6 @@ outbyte (char c)
   if (c == '\n')
     outbyte ('\r');
   return 0;
-}
-
-/* Initialize hardware.  Called from crt0.  */
-void
-hardware_init_hook(void)
-{
-  cfe_init (__cfe_handle, __cfe_entrypt);
-  cfe_conshandle = cfe_getstdhandle(CFE_STDHANDLE_CONSOLE);
-}
-
-/* Exit back to monitor, with the given status code.  */
-void
-hardware_exit_hook (int status)
-{
-  	outbyte ('\r');
-  	outbyte ('\n');
-	cfe_exit (CFE_FLG_WARMSTART, status);
-}
-
-/* Structure filled in by get_mem_info.  Only the size field is
-   actually used (by sbrk), so the others aren't even filled in.  */
-struct s_mem
-{
-  unsigned int size;
-  unsigned int icsize;
-  unsigned int dcsize;
-};
-
-void
-get_mem_info (mem)
-     struct s_mem *mem;
-{
-  /* XXX FIXME: Fake this for now.  Should invoke cfe_enummem, but we
-     don't have enough stack to do that (yet).  */
-  mem->size = 0x4000000;	/* Assume 64 MB of RAM */
 }
 
 /* This is the MIPS cache flush function call.  No defines are provided
Index: mips/cfe.ld
===================================================================
RCS file: /cvs/src/src/libgloss/mips/cfe.ld,v
retrieving revision 1.2
diff -u -p -r1.2 cfe.ld
--- mips/cfe.ld	1 Aug 2002 20:21:23 -0000	1.2
+++ mips/cfe.ld	13 Aug 2003 20:49:44 -0000
@@ -1,8 +1,8 @@
 /* The following TEXT start address leaves space for the monitor
    workspace. */
 
-ENTRY(_prestart)
-STARTUP(crt0.o)
+ENTRY(_start)
+STARTUP(crt0_cfe.o)
 OUTPUT_FORMAT("elf32-bigmips", "elf32-bigmips", "elf32-littlemips")
 GROUP(-lc -lcfe -lgcc)
 SEARCH_DIR(.)
@@ -127,6 +127,7 @@ SECTIONS
     *(COMMON)
   }
 
+  . = ALIGN(32);
   PROVIDE (end = .);
   _end = .;
 
Index: mips/cfe_api.h
===================================================================
RCS file: /cvs/src/src/libgloss/mips/cfe_api.h,v
retrieving revision 1.1
diff -u -p -r1.1 cfe_api.h
--- mips/cfe_api.h	12 Jul 2002 17:55:04 -0000	1.1
+++ mips/cfe_api.h	13 Aug 2003 20:49:44 -0000
@@ -71,6 +71,40 @@ typedef unsigned _POINTER_INT uintptr_t;
 
 #define CFE_API_ALL
 #define CFE_API_IMPL_NAMESPACE
+
+/* Return the stack size to be used for the program.  Normally 32KB.  The
+   normal memory allocator uses the bottom of the stack as its heap limit,
+   so if your application uses a lot of stack space define this function
+   appropriately to keep the heap from growing into the stack.  */
+unsigned long __libcfe_stack_size(void) __attribute__((__weak__));
+
+/* Return the (max address + 1) to be used by this program.  (This address
+   minus '_end' is used as the heap size, so the address should be in the
+   same address space segments as _end.  The normal memory allocator
+   queries CFE to determine the available memory.  */
+void *__libcfe_mem_limit(void) __attribute__((__weak__));
+
+/* If the configuration ability provided by __libcfe_mem_limit() and
+   __libcfe_stack_size() do not provide enough flexibility for your
+   application's memory allocation needs, you can replace the normal
+   low-level allocator by providing the functions listed below and
+   also the function:
+
+	void *sbrk(ptrdiff_t incr);
+
+   If you provide any of these functions, you should provide all three,
+   and be sure to link them into your application as a .o file (rather
+   than a .a).
+
+   __libcfe_meminit() is responsible for initializing the low-level
+   memory allocator.
+
+   __libcfe_stack_top() returns a pointer to the top (highest address;
+   the stack grows down from that address) of the stack to be used by
+   the program.  */
+void __libcfe_meminit (void);
+void *__libcfe_stack_top (void);
+
 /* End customization. */
 
 
Index: mips/cfe_mem.c
===================================================================
RCS file: mips/cfe_mem.c
diff -N mips/cfe_mem.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ mips/cfe_mem.c	13 Aug 2003 20:49:44 -0000
@@ -0,0 +1,130 @@
+/* cfe_mem.c -- Replaceable memory management hooks for MIPS boards
+   running CFE.  */
+
+/*
+ * Copyright 2003
+ * Broadcom Corporation. All rights reserved.
+ * 
+ * This software is furnished under license and may be used and copied only
+ * in accordance with the following terms and conditions.  Subject to these
+ * conditions, you may download, copy, install, use, modify and distribute
+ * modified or unmodified copies of this software in source and/or binary
+ * form. No title or ownership is transferred hereby.
+ * 
+ * 1) Any source code used, modified or distributed must reproduce and
+ *    retain this copyright notice and list of conditions as they appear in
+ *    the source file.
+ * 
+ * 2) No right is granted to use any trade name, trademark, or logo of
+ *    Broadcom Corporation.  The "Broadcom Corporation" name may not be
+ *    used to endorse or promote products derived from this software
+ *    without the prior written permission of Broadcom Corporation.
+ * 
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR IMPLIED
+ *    WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED WARRANTIES OF
+ *    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR
+ *    NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL BROADCOM BE LIABLE
+ *    FOR ANY DAMAGES WHATSOEVER, AND IN PARTICULAR, BROADCOM SHALL NOT BE
+ *    LIABLE FOR DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ *    CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ *    SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ *    BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ */
+
+#include "cfe_api.h"
+
+/* Structure filled in by get_mem_info.  Only the size field is
+   actually used (by sbrk), so the others aren't even filled in.
+   Note that 'size' is the __size__ of the heap starting at _end!  */
+struct s_mem {
+  unsigned int size;
+  unsigned int icsize;
+  unsigned int dcsize;
+};
+
+void *get_mem_info (struct s_mem *);
+
+extern char _end[];
+
+/* Address immediately after available memory.  */
+static unsigned long memtop;
+
+/* Program stack size.  */
+static unsigned long stack_size;
+
+void
+__libcfe_meminit (void)
+{
+  /* If the user has provided a memory-limit function, use it to
+     determine the end of usable memory.  */
+  if (&__libcfe_mem_limit != NULL)
+    memtop = __libcfe_mem_limit ();
+  else
+    {
+      uint64_t start, length, type;
+      int i, rv;
+      long end_segbits, end_pa;
+
+      /* Note that this only works if _end and the program live in kseg0
+         or kseg1.  Not a problem with the default linker script, but
+         if you're writing your own, keep it in mind.  For more complex
+         memory allocation needs, you're encouraged to copy this file
+         and syscalls.c (for sbrk()), and reimplement as appropriate.  */
+      end_segbits = (long)_end & ~ 0x1fffffffL;
+      end_pa = (long)_end & 0x1fffffffL;
+
+      for (i = 0; ; i++)
+        {
+          rv = cfe_enummem(i, 0, &start, &length, &type);
+          if (rv < 0)
+            {
+              /* Did not find an available entry containing _end.
+                 Assume a minimal amount of memory (1MB).  */
+              memtop = _end + (1 * 1024 * 1024);
+              break;
+            }
+
+          /* If not available, try the next.  */
+          if (type != CFE_MI_AVAILABLE)
+            continue;
+
+          /* If end_pa is between start and (start + length) then we have
+	     a winner.  */
+          if (end_pa >= start && end_pa < (start + length))
+            {
+              memtop = (start + length) | end_segbits;
+              break;
+            }
+        }
+    }
+
+  /* If the user has provided a memory-limit function, use it to
+     determine the end of usable memory.  */
+  if (&__libcfe_stack_size != NULL)
+    stack_size = __libcfe_stack_size ();
+  else
+    stack_size = (32 * 1024);		/* Default = 32KB.  */
+
+  /* Chop the top of memory to a 32-byte aligned location, and
+     round the stack size up to a 32-byte multiple.  */
+  memtop = memtop & ~(unsigned long)31;
+  stack_size = (stack_size + 31) & ~(unsigned long)31;
+}
+
+void *
+__libcfe_stack_top (void)
+{
+  /* Grow down from the top of available memory.  Obviously, if
+     code writes above this limit, problems could result!  */
+  return (void *) memtop;
+}
+
+/* For compatibility, get_mem_info returns the top of memory
+   (i.e., the stack address).  Nothing actually uses that,
+   though.  */
+void *
+get_mem_info (struct s_mem *meminfo)
+{
+  meminfo->size = (char *)(memtop - stack_size) - _end;
+  return (void *) memtop;
+}
Index: mips/cfe_prestart.S
===================================================================
RCS file: mips/cfe_prestart.S
diff -N mips/cfe_prestart.S
--- mips/cfe_prestart.S	5 Feb 2003 17:01:33 -0000	1.2
+++ /dev/null	1 Jan 1970 00:00:00 -0000
@@ -1,86 +0,0 @@
-/*
- * cfe_prestart.S -- startup file for MIPS running CFE.
- * Derived from crt0.S.
- *
- * Copyright (c) 1995, 1996, 1997 Cygnus Support
- *
- * The authors hereby grant permission to use, copy, modify, distribute,
- * and license this software and its documentation for any purpose, provided
- * that existing copyright notices are retained in all copies and that this
- * notice is included verbatim in any distributions. No written agreement,
- * license, or royalty fee is required for any of the authorized uses.
- * Modifications to this software may be copyrighted by their authors
- * and need not follow the licensing terms described here, provided that
- * the new terms are clearly indicated on the first page of each file where
- * they apply.
- */
-
-#ifdef __mips16
-/* This file contains 32 bit assembly code.  */
-	.set nomips16
-#endif
-
-#include "regs.S"
-
-/* This is for referencing addresses that are not in the .sdata or
-   .sbss section under embedded-pic, or before we've set up gp.  */
-#ifdef __mips_embedded_pic
-# ifdef __mips64
-#  define LA(t,x) la t,x-PICBASE ; daddu t,s0,t
-# else
-#  define LA(t,x) la t,x-PICBASE ; addu t,s0,t
-# endif
-#else /* __mips_embedded_pic */ 
-# define LA(t,x) la t,x
-#endif /* __mips_embedded_pic */ 
-
-	.globl	__cfe_handle
-	.globl	__cfe_entrypt
-
-	.text
-	.align	2
-
-	.globl	_prestart
-	.ent	_prestart
-_prestart:
-	.set	noreorder
-#ifdef __mips_embedded_pic
-	PICBASE = .+8
-        bal	PICBASE
-	nop
-	move	s0,$31
-#endif
-
-	/* These are actually pointers, but they're guaranteed to be
-	   in compatibility space and it's just easier to store them
-	   as words ("unsigned int") than worry about the actual
-	   pointer size of the runtime we're building.  */
-	LA (v0, __cfe_handle)
-	sw	a0, 0(v0)
-	LA (v0, __cfe_entrypt)
-	sw	a2, 0(v0)
-
-	LA (v0, _start)
-	jr	v0
-	nop
-	.end _prestart
-
-
-/* Avoid worst-case execution hazards.  This is targetted at the SB-1
-   pipe, and is much worse than it needs to be (not even counting
-   the subroutine call and return).  */
-	.globl	hardware_hazard_hook
-	.ent	hardware_hazard_hook
-hardware_hazard_hook:
-	.set push
-	.set mips32
-	.set noreorder
-	ssnop
-	ssnop
-	ssnop
-	bnel	$0, $0, .+4
-	ssnop
-	j	ra
-	nop
-	.set pop
-	.end	hardware_hazard_hook
Index: mips/configure.in
===================================================================
RCS file: /cvs/src/src/libgloss/mips/configure.in,v
retrieving revision 1.8
diff -u -p -r1.8 configure.in
--- mips/configure.in	5 Feb 2003 17:10:43 -0000	1.8
+++ mips/configure.in	13 Aug 2003 20:49:44 -0000
@@ -94,7 +94,7 @@ case "${target}" in
         ;;
   mipsisa32-*-* | mipsisa32el-*-* | \
   mipsisa32r2-*-* | mipsisa32r2el-*-*)
-	crt0="crt0_cygmon.o crt0.o"
+	crt0="crt0_cfe.o crt0_cygmon.o crt0.o"
 	pcrt0="pcrt0.o"
 	part_specific_obj=
 	part_specific_defines=
@@ -119,6 +119,7 @@ case "${target}" in
 	bsp_list="libpmon.a libnullmon.a"
 	;;
   *)
+	crt0="crt0_cfe.o crt0.o"
         part_specific_obj="vr4300.o cma101.o"
 	part_specific_defines=
         script_list="idt pmon ddb ddb-kseg0 lsi cfe idtecoff nullmon"
Index: mips/crt0_cfe.S
===================================================================
RCS file: mips/crt0_cfe.S
diff -N mips/crt0_cfe.S
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ mips/crt0_cfe.S	13 Aug 2003 20:49:44 -0000
@@ -0,0 +1,263 @@
+/*
+ * crt0_cfe.S -- Runtime startup for MIPS targets running CFE.
+ *
+ * Copyright 2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and copied only
+ * in accordance with the following terms and conditions.  Subject to these
+ * conditions, you may download, copy, install, use, modify and distribute
+ * modified or unmodified copies of this software in source and/or binary
+ * form. No title or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce and
+ *    retain this copyright notice and list of conditions as they appear in
+ *    the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or logo of
+ *    Broadcom Corporation.  The "Broadcom Corporation" name may not be
+ *    used to endorse or promote products derived from this software
+ *    without the prior written permission of Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR IMPLIED
+ *    WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED WARRANTIES OF
+ *    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR
+ *    NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL BROADCOM BE LIABLE
+ *    FOR ANY DAMAGES WHATSOEVER, AND IN PARTICULAR, BROADCOM SHALL NOT BE
+ *    LIABLE FOR DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ *    CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ *    SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ *    BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ *    WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ *    OR OTHERWISE), EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Derived from crt0_cygmon.S:
+ *
+ * Copyright (c) 1995, 1996, 1997, 2000 Red Hat, Inc.
+ *
+ * The authors hereby grant permission to use, copy, modify, distribute,
+ * and license this software and its documentation for any purpose, provided
+ * that existing copyright notices are retained in all copies and that this
+ * notice is included verbatim in any distributions. No written agreement,
+ * license, or royalty fee is required for any of the authorized uses.
+ * Modifications to this software may be copyrighted by their authors
+ * and need not follow the licensing terms described here, provided that
+ * the new terms are clearly indicated on the first page of each file where
+ * they apply.
+ */
+
+/*
+ * This file does minimal runtime startup for code running under
+ * CFE firmware.
+ *
+ * It does minimal hardware initialization.  In particular
+ * it sets Status:FR to match the requested floating point
+ * mode.
+ *
+ * It is meant to be linked with the other files provided by libcfe.a,
+ * and calls routines in those files.
+ */
+
+#ifdef __mips16
+/* This file contains 32 bit assembly code.  */
+	.set nomips16
+#endif
+#ifdef __mips_embedded_pic
+# error -membedded-pic is not supported.
+#endif
+
+#include "regs.S"
+
+/*
+ * Set up some room for a stack. We just grab a chunk of memory.
+ */
+#define STARTUP_STACK_SIZE	(1 * 1024)		
+
+	.comm	_lstack, STARTUP_STACK_SIZE
+
+	.text
+	.align	4
+
+    /*
+     * Without the following nop, GDB thinks _start is a data variable.
+     * This is probably a bug in GDB in handling a symbol that is at the
+     * start of the .text section.
+     */
+	nop
+
+
+    /*
+     * On entry, the following values have been passed in registers
+     * by the firmware:
+     *
+     * a0: firmware handle
+     * a1: zero (unused)
+     * a2: firmware callback entrypoint
+     * a3: CFE entrypoint seal (unused)
+     *
+     * They must be preserved until the CFE entrypoint and handle
+     * are passed to __libcfe_init().
+     */
+
+	.globl	_start
+	.ent	_start
+_start:
+	.set	noreorder
+    /* Set the global data pointer, defined in the linker script.  */
+	la		gp, _gp
+
+#ifndef __mips_soft_float
+    /* If compiled for hard float, set the FPU mode based on the
+       compilation flags.  Note that this assumes that enough code
+       will run after the mtc0 to clear any hazards.  */
+	mfc0	t0, C0_SR
+	or	t0, t0, (SR_CU1 | SR_FR)
+#if (__mips_fpr == 32)
+	xor	t0, t0, SR_FR		/* If 32-bit FP mode, clear FR.  */
+#endif
+	mtc0	t0, C0_SR
+#endif
+	.end	_start
+
+    /*
+     * zero out the bss section.
+     */
+	.globl	_zerobss
+	.ent	_zerobss
+_zerobss:
+    /* These variables are defined in the linker script.  */
+	la		v0, _fbss
+	la		v1, _end
+
+3:
+	sw		zero, 0(v0)
+	bltu	v0, v1, 3b
+	addiu	v0, v0, 4		/* Delay slot.  */
+	.end	_zerobss
+
+    /*
+     * Setup a small stack so we can run some C code, and do
+     * the library initialization.  (32 bytes are saved for
+     * the argument registers' stack slots.)
+     */
+	.globl	_stackinit
+	.ent	_stackinit
+_stackinit:
+	la	t0, _lstack
+	addiu	sp, t0, (STARTUP_STACK_SIZE - 32)
+	jal	__libcfe_init
+	nop
+
+    /*
+     * Setup the stack pointer -- 
+     *    __libcfe_init() returns the value to be used as the top of
+     *    the program's stack.
+     *
+     *    We subtract 32 bytes for the 4 argument registers, in case
+     *    main() wants to write them back to the stack.  The caller
+     *    allocates stack space for parameters in the old MIPS ABIs.
+     *    We must do this even though we aren't passing arguments,
+     *    because main might be declared to have them.)
+     *
+     *    We subtract 32 more bytes for the argv/envp setup for the
+     *    call to main().
+     */
+	subu	v0, v0, 64
+	move	sp, v0
+
+	.end	_stackinit
+
+    /*
+     * initialize target specific stuff. Only execute these
+     * functions it they exist.
+     */
+	.globl	hardware_init_hook .text
+	.globl	software_init_hook .text
+	.type	_fini,@function
+	.type	_init,@function
+	.globl	atexit .text
+	.globl	exit .text
+	.globl	_crt0init
+	.ent	_crt0init
+_crt0init:
+	la		t9, hardware_init_hook	# init the hardware if needed
+	beq		t9, zero, 6f
+	nop
+	jal		t9
+	nop
+6:
+	la		t9, software_init_hook	# init the software if needed
+	beq		t9, zero, 7f
+	nop
+	jal		t9
+	nop
+7:
+	la		a0, _fini
+	jal		atexit
+	nop
+
+#ifdef GCRT0
+	.globl	_ftext
+	.globl	_extext
+	la		a0, _ftext
+	la		a1, _etext
+	jal		monstartup
+	nop
+#endif
+
+	jal	_init			# run global constructors
+	nop
+
+	addiu	a1,sp,32			# argv = sp + 32
+	addiu	a2,sp,40			# envp = sp + 40
+#if __mips64
+	sd	zero,(a1)			# argv[argc] = 0
+	sd	zero,(a2)			# envp[0] = 0
+#else
+	sw	zero,(a1)
+	sw	zero,(a2)
+#endif
+
+	jal	main			# call the program start function
+	move	a0,zero			# set argc to 0; delay slot.
+
+	# fall through to the "exit" routine
+	jal	exit			# call libc exit to run the G++
+					# destructors
+	move	a0, v0			# pass through the exit code
+	.end	_crt0init
+	
+/*
+ * _exit -- Exit from the application.  This is provided in this file because
+ *          program exit should shut down profiling (if GCRT0 is defined),
+ *          and only this file is compiled with GCRT0 defined.
+ */
+	.globl	_exit
+	.ent	_exit
+_exit:
+7:
+	move	s0, a0			/* Save in case we loop.  */
+
+#ifdef GCRT0
+	jal	_mcleanup
+	nop
+#endif
+
+	la	t0, hardware_exit_hook
+	beq	t0,zero,1f
+	nop
+	jal	t0
+	nop
+
+1:
+	/* Call into the library to do the heavy lifting.  */
+        jal	__libcfe_exit
+	move	a0, s0			/* Delay slot.  */
+
+	b	7b			/* Loop back just in case.  */
+	nop
+	.end	_exit
+
+/* EOF crt0_cfe.S */


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]