* src/hc08/gen.c (genPlusIncr, genUminus, genMinusDec, genCmp,
[fw/sdcc] / device / lib / malloc.c
1 #include <sdcc-lib.h>
2 #include <malloc.h>
3
4 #if _SDCC_MALLOC_TYPE_MLH
5
6 typedef struct _MEMHEADER MEMHEADER;
7
8 struct _MEMHEADER
9 {
10   MEMHEADER *  next;
11   MEMHEADER *  prev;
12   unsigned int       len;
13   unsigned char      mem;
14 };
15
16 #define HEADER_SIZE (sizeof(MEMHEADER)-sizeof(char))
17
18 /* These veriables are defined through the crt0 functions. */
19 /* Base of this variable is the first byte of the heap. */
20 extern MEMHEADER _sdcc_heap_start;
21 /* Address of this variable is the last byte of the heap. */
22 extern char _sdcc_heap_end;
23
24 void
25 _sdcc_heap_init(void)
26 {
27   MEMHEADER *pbase = &_sdcc_heap_start;
28   unsigned int size = &_sdcc_heap_end - (char *)pbase;
29
30   pbase->next = (MEMHEADER *)((char *)pbase + size - HEADER_SIZE);
31   pbase->next->next = NULL; //And mark it as last
32   pbase->prev       = NULL; //and mark first as first
33   pbase->len        = 0;    //Empty and ready.
34 }
35
36 void *
37 malloc (unsigned int size)
38 {
39   MEMHEADER * current_header;
40   MEMHEADER * new_header;
41
42   if (size>(0xFFFF-HEADER_SIZE))
43     {
44       return NULL; //To prevent overflow in next line
45     }
46
47   size += HEADER_SIZE; //We need a memory for header too
48   current_header = &_sdcc_heap_start;
49
50   while (1)
51     {
52       //    current
53       //    |   len       next
54       //    v   v         v
55       //....*****.........******....
56       //         ^^^^^^^^^
57       //           spare
58
59       if ((((unsigned int)current_header->next) -
60            ((unsigned int)current_header) -
61            current_header->len) >= size) 
62         {
63           break; //if spare is more than need
64         }
65       current_header = current_header->next;    //else try next             
66       if (!current_header->next)  
67         {
68           return NULL;  //if end_of_list reached    
69         }
70     }
71
72   if (!current_header->len)
73     { //This code works only for first_header in the list and only
74       current_header->len = size; //for first allocation
75       return &current_header->mem;
76     } 
77   else
78     {
79       //else create new header at the begin of spare
80       new_header = (MEMHEADER * )((char *)current_header + current_header->len);
81       new_header->next = current_header->next; //and plug it into the chain
82       new_header->prev = current_header;
83       current_header->next  = new_header;
84       if (new_header->next)
85         {
86           new_header->next->prev = new_header;
87         }
88       new_header->len  = size; //mark as used
89       return &new_header->mem;
90     }
91 }
92
93 void
94 free (void *p)
95 {
96   MEMHEADER *prev_header, *pthis;
97
98   if ( p ) //For allocated pointers only!
99     {
100       pthis = (MEMHEADER * )((char *)  p - HEADER_SIZE); //to start of header
101       if ( pthis->prev ) // For the regular header
102         {
103           prev_header = pthis->prev;
104           prev_header->next = pthis->next;
105           if (pthis->next)
106             {
107               pthis->next->prev = prev_header;
108             }
109         }
110       else
111         {
112           pthis->len = 0; //For the first header
113         }
114     }
115 }
116
117 #else
118
119             //--------------------------------------------------------------------
120             //Written by Dmitry S. Obukhov, 1997
121             //dso@usa.net
122             //--------------------------------------------------------------------
123             //Modified for SDCC by Sandeep Dutta, 1999
124             //sandeep.dutta@usa.net
125             //--------------------------------------------------------------------
126             //malloc and free functions implementation for embedded system
127             //Non-ANSI keywords are C51 specific.
128             // xdata - variable in external memory (just RAM)
129             //--------------------------------------------------------------------
130
131             #define MEMHEADER   struct MAH// Memory Allocation Header
132
133             MEMHEADER
134             {
135               MEMHEADER xdata *  next;
136               MEMHEADER xdata *  prev;
137               unsigned int       len;
138               unsigned char      mem;
139             };
140
141             #define HEADER_SIZE (sizeof(MEMHEADER)-1)
142
143             //Static here means: can be accessed from this module only
144             static MEMHEADER xdata * FIRST_MEMORY_HEADER_PTR;
145             void init_dynamic_memory(MEMHEADER xdata * array, unsigned int size) 
146             {
147
148             //This function MUST be called after the RESET.
149             //Parameters: array - pointer to memory allocated by the linker
150             //            size  - size of this memory pool
151             //Example:
152             //     #define DYNAMIC_MEMORY_SIZE 0x2000
153             //     .....
154             //     unsigned char xdata dynamic_memory_pool[DYNAMIC_MEMORY_SIZE];
155             //     unsigned char xdata * current_buffer;
156             //     .....
157             //     void main(void)
158             //     {
159             //         ...
160             //         init_dynamic_memory(dynamic_memory_pool,DYNAMIC_MEMORY_SIZE);
161             //         Now it is possible to use malloc.
162             //         ...
163             //         current_buffer = malloc(0x100);
164             //
165             //
166
167               if ( !array ) /*Reserved memory starts on 0x0000 but it's NULL...*/
168               {             //So, we lost one byte!
169                  array = (MEMHEADER xdata * )((char xdata * ) array + 1) ;
170                  size --;
171               }
172               FIRST_MEMORY_HEADER_PTR = array;
173               //Reserve a mem for last header
174               array->next = (MEMHEADER xdata * )(((char xdata * ) array) + size - HEADER_SIZE);
175               array->next->next = (void xdata * ) NULL; //And mark it as last
176               array->prev       = (void xdata * ) NULL; //and mark first as first
177               array->len        = 0;    //Empty and ready.
178             }
179
180             void  xdata * malloc (unsigned int size)
181             {
182               register MEMHEADER xdata * current_header;
183               register MEMHEADER xdata * new_header;
184
185               if (size>(0xFFFF-HEADER_SIZE)) return (void xdata *) NULL; //To prevent overflow in next line
186               size += HEADER_SIZE; //We need a memory for header too
187               current_header = FIRST_MEMORY_HEADER_PTR;
188               while (1)
189               {
190
191                 //    current
192                 //    |   len       next
193                 //    v   v         v
194                 //....*****.........******....
195                 //         ^^^^^^^^^
196                 //           spare
197
198                 if ((((unsigned int)current_header->next) -
199                      ((unsigned int)current_header) -
200                      current_header->len) >= size) break; //if spare is more than need
201                 current_header = current_header->next;    //else try next             
202                 if (!current_header->next)  return (void xdata *) NULL;  //if end_of_list reached
203               }
204               if (!current_header->len)
205               { //This code works only for first_header in the list and only
206                  current_header->len = size; //for first allocation
207                  return ((xdata *)&(current_header->mem));
208               } //else create new header at the begin of spare
209               new_header = (MEMHEADER xdata * )((char xdata *)current_header + current_header->len);
210               new_header->next = current_header->next; //and plug it into the chain
211               new_header->prev = current_header;
212               current_header->next  = new_header;
213               if (new_header->next)  new_header->next->prev = new_header;
214               new_header->len  = size; //mark as used
215               return ((xdata *)&(new_header->mem));
216             }
217
218             void free (void xdata * p)
219             {
220               register MEMHEADER xdata * prev_header;
221               if ( p ) //For allocated pointers only!
222               {
223                   p = (MEMHEADER xdata * )((char xdata *)  p - HEADER_SIZE); //to start of header
224                   if ( ((MEMHEADER xdata * ) p)->prev ) // For the regular header
225                   {
226                     prev_header = ((MEMHEADER xdata * ) p)->prev;
227                     prev_header->next = ((MEMHEADER xdata * ) p)->next;
228                     if (((MEMHEADER xdata * ) p)->next)
229                        ((MEMHEADER xdata * ) p)->next->prev = prev_header;
230                   }
231                   else ((MEMHEADER xdata * ) p)->len = 0; //For the first header
232               }
233             }
234             //END OF MODULE
235 #endif