Alan Lehotsky <apl@alum.mit.edu> Joern Rennecke <joern.rennecke@embecosm.com> * configure.in: Add Epiphany support. * configure: Regenerate. * epiphany: New directory. * libgloss/README: Add Epiphany entry.
		
			
				
	
	
		
			166 lines
		
	
	
		
			5.3 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			166 lines
		
	
	
		
			5.3 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /* EPIPHANY implementation of _sbrk ()
 | |
| 
 | |
|    Copyright (c) 2011, Adapteva, Inc.
 | |
|    All rights reserved.
 | |
| 
 | |
|    Contributor Jeremy Bennett <jeremy.bennett@embecosm.com> for Adapteva Inc
 | |
| 
 | |
|    Redistribution and use in source and binary forms, with or without
 | |
|    modification, are permitted provided that the following conditions are met:
 | |
|     * Redistributions of source code must retain the above copyright notice,
 | |
|       this list of conditions and the following disclaimer.
 | |
|     * Redistributions in binary form must reproduce the above copyright
 | |
|       notice, this list of conditions and the following disclaimer in the
 | |
|       documentation and/or other materials provided with the distribution.
 | |
|     * Neither the name of Adapteva nor the names of its contributors may be
 | |
|       used to endorse or promote products derived from this software without
 | |
|       specific prior written permission.
 | |
| 
 | |
|    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | |
|    AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | |
|    IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 | |
|    ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 | |
|    LIABLE FOR ANY 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)
 | |
|    ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 | |
|    POSSIBILITY OF SUCH DAMAGE.                                               */
 | |
| /* ------------------------------------------------------------------------- */
 | |
| /* This implementation is suitable for use with the Verilator simulation of
 | |
|    the EPIPHANY.
 | |
| 
 | |
|    Commenting suitable for processing by Doxygen is provided throughout.     */
 | |
| /* ------------------------------------------------------------------------- */
 | |
| #include <sys/types.h>
 | |
| #include <errno.h>
 | |
| #include <stddef.h>
 | |
| 
 | |
| /* ------------------------------------------------------------------------- */
 | |
| /*!Increase program data space
 | |
| 
 | |
|    This is a minimal implementation.  Assuming the heap is growing upwards
 | |
|    from __heap_start towards __heap_end.
 | |
|    See linker file for definition.
 | |
| 
 | |
|    @param[in] incr  The number of bytes to increment the stack by.
 | |
| 
 | |
|    @return  A pointer to the start of the new block of memory                */
 | |
| /* ------------------------------------------------------------------------- */
 | |
| void *
 | |
| _sbrk (int  incr)
 | |
| {
 | |
| 	extern char __heap_start;//set by linker
 | |
| 	extern char __heap_end;//set by linker
 | |
| 
 | |
| 	static char *heap_end;		/* Previous end of heap or 0 if none */
 | |
| 	char        *prev_heap_end;
 | |
| 
 | |
| 	if (0 == heap_end) {
 | |
| 		heap_end = &__heap_start;			/* Initialize first time round */
 | |
| 	}
 | |
| 
 | |
| 	prev_heap_end  = heap_end;
 | |
| 	heap_end      += incr;
 | |
| 	//check
 | |
| 	if( heap_end < (&__heap_end)) {
 | |
| 
 | |
| 	} else {
 | |
| 		errno = ENOMEM;
 | |
| 		return (char*)-1;
 | |
| 	}
 | |
| 	return (void *) prev_heap_end;
 | |
| 
 | |
| }	/* _sbrk () */
 | |
| 
 | |
| 
 | |
| 
 | |
| ///* sbrk support */
 | |
| //
 | |
| ///* The current plan is to have one sbrk handler for all cpus.
 | |
| //   Hence use `asm' for each global variable here to avoid the cpu prefix.
 | |
| //   We can't intrude on the user's namespace (another reason to use asm).  */
 | |
| //
 | |
| //#include <sys/types.h>
 | |
| ///*#include <sys/syscall.h>*/
 | |
| //#include <errno.h>
 | |
| //#include <stddef.h>
 | |
| //
 | |
| ///* These variables are publicly accessible for debugging purposes.
 | |
| //   The user is also free to set sbrk_size to something different.
 | |
| //   See mem-layout.c.  */
 | |
| //
 | |
| //extern int sbrk_size asm ("sbrk_size");
 | |
| //
 | |
| //caddr_t sbrk_start asm ("sbrk_start");
 | |
| //caddr_t sbrk_loc asm ("sbrk_loc");
 | |
| //extern char  end;                    /* Defined by linker.  */
 | |
| //
 | |
| ///*caddr_t _sbrk_r (struct _reent *, size_t) asm ("__sbrk_r");*/
 | |
| //
 | |
| //
 | |
| ///* This symbol can be defined with the --defsym linker option.  */
 | |
| //extern char __heap_end __attribute__((weak));
 | |
| //
 | |
| //
 | |
| ///* FIXME: We need a semaphore here.  */
 | |
| //
 | |
| //caddr_t
 | |
| //_sbrk_r (struct _reent *r, size_t nbytes)
 | |
| //{
 | |
| //   extern char  end;			/* Defined by linker.  */
 | |
| //   static char *heap_end;		/* Previous end of heap or 0 if none */
 | |
| //   char        *prev_heap_end;
 | |
| //   register char* stack asm("sp");
 | |
| //
 | |
| //   if (0 == heap_end)
 | |
| //     {
 | |
| //       heap_end = &end;			/* Initialize first time round */
 | |
| //     }
 | |
| //
 | |
| //   prev_heap_end  = heap_end;
 | |
| //
 | |
| //   if (stack < (prev_heap_end+nbytes)) {
 | |
| //     /* heap would overlap the current stack depth.
 | |
| //      * Future:  use sbrk() system call to make simulator grow memory beyond
 | |
| //      * the stack and allocate that
 | |
| //      */
 | |
| //     errno = ENOMEM;
 | |
| //     return (char*)-1;
 | |
| //   }
 | |
| //
 | |
| //   heap_end      += nbytes;
 | |
| //
 | |
| //   return (caddr_t) prev_heap_end;
 | |
| //
 | |
| //}	/* _sbrk () */
 | |
| 
 | |
| 
 | |
| //caddr_t
 | |
| //_sbrk_r (struct _reent *r, size_t nbytes)
 | |
| //{
 | |
| //  caddr_t result;
 | |
| //
 | |
| //  void *heap_end;
 | |
| //
 | |
| //  heap_end = &__heap_end;
 | |
| //  if (!heap_end)
 | |
| //    heap_end = sbrk_start + sbrk_size;
 | |
| //  if (
 | |
| //      /* Ensure we don't underflow.  */
 | |
| //      sbrk_loc + nbytes < sbrk_start
 | |
| //      /* Ensure we don't overflow.  */
 | |
| //      || sbrk_loc + nbytes > (caddr_t)heap_end)
 | |
| //    {
 | |
| //      errno = ENOMEM;
 | |
| //      return ((caddr_t) -1);
 | |
| //    }
 | |
| //
 | |
| //  if (0 == sbrk_loc)
 | |
| //    sbrk_loc = &end;                 /* Initialize first time round */
 | |
| //  result = sbrk_loc;
 | |
| //  sbrk_loc += nbytes;
 | |
| //  return result;
 | |
| //}
 |