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]

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


Patch applied.

-- Jeff J.

cgd@broadcom.com wrote:
> 
> 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]