* device/include/malloc.h: Added z80 and gbz80 support.
[fw/sdcc] / device / lib / malloc.c
index e9a67e11f97a15e67b1f65057ae145ee85a425cb..22f813c59a9b4b92effc54013f24e9d14356a992 100644 (file)
@@ -1,4 +1,121 @@
+#include <sdcc-lib.h>
 
+#if _SDCC_MALLOC_TYPE_MLH
+#include <malloc.h>
+
+typedef struct _MEMHEADER MEMHEADER;
+
+struct _MEMHEADER
+{
+  MEMHEADER *  next;
+  MEMHEADER *  prev;
+  unsigned int       len;
+  unsigned char      mem;
+};
+
+#define HEADER_SIZE (sizeof(MEMHEADER)-sizeof(char))
+#define NULL        0
+
+/* These veriables are defined through the crt0 functions. */
+/* Base of this variable is the first byte of the heap. */
+extern MEMHEADER _sdcc_heap_start;
+/* Address of this variable is the last byte of the heap. */
+extern char _sdcc_heap_end;
+
+void 
+_sdcc_heap_init(void)
+{
+  MEMHEADER *pbase = &_sdcc_heap_start;
+  unsigned int size = &_sdcc_heap_end - (char *)pbase;
+
+  pbase->next = (MEMHEADER *)((char *)pbase + size - HEADER_SIZE);
+  pbase->next->next = NULL; //And mark it as last
+  pbase->prev       = NULL; //and mark first as first
+  pbase->len        = 0;    //Empty and ready.
+}
+
+void *
+malloc (unsigned int size)
+{
+  MEMHEADER * current_header;
+  MEMHEADER * new_header;
+
+  if (size>(0xFFFF-HEADER_SIZE))
+    {
+      return NULL; //To prevent overflow in next line
+    }
+
+  size += HEADER_SIZE; //We need a memory for header too
+  current_header = &_sdcc_heap_start;
+
+  while (1)
+    {
+      //    current
+      //    |   len       next
+      //    v   v         v
+      //....*****.........******....
+      //         ^^^^^^^^^
+      //           spare
+
+      if ((((unsigned int)current_header->next) -
+           ((unsigned int)current_header) -
+           current_header->len) >= size) 
+        {
+          break; //if spare is more than need
+        }
+      current_header = current_header->next;    //else try next             
+      if (!current_header->next)  
+        {
+          return NULL;  //if end_of_list reached    
+        }
+    }
+
+  if (!current_header->len)
+    { //This code works only for first_header in the list and only
+      current_header->len = size; //for first allocation
+      return &current_header->mem;
+    } 
+  else
+    {
+      //else create new header at the begin of spare
+      new_header = (MEMHEADER * )((char *)current_header + current_header->len);
+      new_header->next = current_header->next; //and plug it into the chain
+      new_header->prev = current_header;
+      current_header->next  = new_header;
+      if (new_header->next)
+        {
+          new_header->next->prev = new_header;
+        }
+      new_header->len  = size; //mark as used
+      return &new_header->mem;
+    }
+}
+
+void 
+free (void *p)
+{
+  MEMHEADER *prev_header, *pthis;
+
+  if ( p ) //For allocated pointers only!
+    {
+      pthis = (MEMHEADER * )((char *)  p - HEADER_SIZE); //to start of header
+      if ( pthis->prev ) // For the regular header
+        {
+          prev_header = pthis->prev;
+          prev_header->next = pthis->next;
+          if (pthis->next)  
+            {
+              pthis->next->prev = prev_header;
+            }
+        }
+      else 
+        {
+          pthis->len = 0; //For the first header
+        }
+    }
+}
+
+#else
 
             //--------------------------------------------------------------------
             //Written by Dmitry S. Obukhov, 1997
 
             MEMHEADER
             {
-              MEMHEADER _xdata *  next;
-              MEMHEADER _xdata *  prev;
+              MEMHEADER xdata *  next;
+              MEMHEADER xdata *  prev;
               unsigned int       len;
-              unsigned char      mem[1];
+             unsigned char      mem;
             };
 
             #define HEADER_SIZE (sizeof(MEMHEADER)-1)
-            #define NULL        (void _xdata * ) 0
+            #define NULL        (void xdata * ) 0
 
 
             //Static here means: can be accessed from this module only
-            static MEMHEADER _xdata * FIRST_MEMORY_HEADER_PTR;
-            void init_dynamic_memory(MEMHEADER _xdata * array, unsigned int size) 
+            static MEMHEADER xdata * FIRST_MEMORY_HEADER_PTR;
+            void init_dynamic_memory(MEMHEADER xdata * array, unsigned int size) 
             {
 
             //This function MUST be called after the RESET.
 
               if ( !array ) /*Reserved memory starts on 0x0000 but it's NULL...*/
               {             //So, we lost one byte!
-                 array = (MEMHEADER _xdata * )((char _xdata * ) array + 1) ;
+                 array = (MEMHEADER xdata * )((char xdata * ) array + 1) ;
                  size --;
               }
               FIRST_MEMORY_HEADER_PTR = array;
               //Reserve a mem for last header
-              array->next = (MEMHEADER _xdata * )(((char _xdata * ) array) + size - HEADER_SIZE);
+              array->next = (MEMHEADER xdata * )(((char xdata * ) array) + size - HEADER_SIZE);
               array->next->next = NULL; //And mark it as last
               array->prev       = NULL; //and mark first as first
               array->len        = 0;    //Empty and ready.
             }
 
-            void  _xdata * malloc (unsigned int size)
+            void  xdata * malloc (unsigned int size)
             {
-              register MEMHEADER _xdata * current_header;
-              register MEMHEADER _xdata * new_header;
+              register MEMHEADER xdata * current_header;
+              register MEMHEADER xdata * new_header;
 
               if (size>(0xFFFF-HEADER_SIZE)) return NULL; //To prevent overflow in next line
               size += HEADER_SIZE; //We need a memory for header too
               if (!current_header->len)
               { //This code works only for first_header in the list and only
                  current_header->len = size; //for first allocation
-                 return (current_header->mem);
+                 return ((xdata *)&(current_header->mem));
               } //else create new header at the begin of spare
-              new_header = (MEMHEADER _xdata * )((char _xdata *)current_header + current_header->len);
+              new_header = (MEMHEADER xdata * )((char xdata *)current_header + current_header->len);
               new_header->next = current_header->next; //and plug it into the chain
               new_header->prev = current_header;
               current_header->next  = new_header;
               if (new_header->next)  new_header->next->prev = new_header;
               new_header->len  = size; //mark as used
-              return (new_header->mem);
+              return ((xdata *)&(new_header->mem));
             }
 
-            void free (MEMHEADER _xdata * p)
+            void free (MEMHEADER xdata * p)
             {
-              register MEMHEADER _xdata * prev_header;
+              register MEMHEADER xdata * prev_header;
               if ( p ) //For allocated pointers only!
               {
-                  p = (MEMHEADER _xdata * )((char _xdata *)  p - HEADER_SIZE); //to start of header
+                  p = (MEMHEADER xdata * )((char xdata *)  p - HEADER_SIZE); //to start of header
                   if ( p->prev ) // For the regular header
                   {
                     prev_header = p->prev;
             }
             //END OF MODULE
 
+#endif