blob: d4e91b5756251f828dbb6802f4c1814e513aa084 [file] [log] [blame]
kthacker62e146c2006-04-17 15:11:35 +00001#include <sdcc-lib.h>
2#include <malloc.h>
3
4#if _SDCC_MALLOC_TYPE_MLH
5
6typedef struct _MEMHEADER MEMHEADER;
7
8struct _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
24extern char *get_ram_start();
25extern char *get_ram_end();
26extern void calc_free_ram();
27extern char progend;
28
29static MEMHEADER *firstheader;
30/* setup two headers. One at start of free ram, second at end of free ram.
31 We find free ram range by asking Amstrad's firmware. */
32
33void
34_sdcc_heap_init(void)
35{
36 MEMHEADER *lastheader;
37 unsigned int size;
38 char * ramstart;
39
40 /* ask firmware for free ram */
41 calc_free_ram();
42
43 /* start of ram is either start of range given by firmware,
44 or end of program; whichever is largest */
45 ramstart = get_ram_start();
46 if (ramstart<&progend)
47 ramstart = &progend;
48
49 /* this is our first mem header */
50 firstheader = (MEMHEADER *)ramstart;
51
52 /* this is the size of ram available */
53 size = get_ram_end() - ramstart;
54
55 /* calc address of last header */
56 lastheader = (MEMHEADER *)((char *)firstheader + size - HEADER_SIZE);
57
58 /* setup last header */
59 lastheader->next = NULL;
60 lastheader->prev = firstheader;
61 lastheader->len = 0;
62
63 /* setup first header */
64 firstheader->next = lastheader;
65 firstheader->prev = NULL; //and mark first as first
66 firstheader->len = 0; //Empty and ready.
67}
68
69void *
70malloc (unsigned int size)
71{
72 MEMHEADER * current_header;
73 MEMHEADER * new_header;
74
75 if (size>(0xFFFF-HEADER_SIZE))
76 {
77 return NULL; //To prevent overflow in next line
78 }
79
80 size += HEADER_SIZE; //We need a memory for header too
81 current_header = firstheader;
82
83 while (1)
84 {
85 // current
86 // | len next
87 // v v v
88 //....*****.........******....
89 // ^^^^^^^^^
90 // spare
91
92 if ((((unsigned int)current_header->next) -
93 ((unsigned int)current_header) -
94 current_header->len) >= size)
95 {
96 break; //if spare is more than need
97 }
98 current_header = current_header->next; //else try next
99 if (!current_header->next)
100 {
101 return NULL; //if end_of_list reached
102 }
103 }
104
105 if (!current_header->len)
106 { //This code works only for first_header in the list and only
107 current_header->len = size; //for first allocation
108 return &current_header->mem;
109 }
110 else
111 {
112 //else create new header at the begin of spare
113 new_header = (MEMHEADER * )((char *)current_header + current_header->len);
114 new_header->next = current_header->next; //and plug it into the chain
115 new_header->prev = current_header;
116 current_header->next = new_header;
117 if (new_header->next)
118 {
119 new_header->next->prev = new_header;
120 }
121 new_header->len = size; //mark as used
122 return &new_header->mem;
123 }
124}
125
126void
127free (void *p)
128{
129 MEMHEADER *prev_header, *pthis;
130
131 if ( p ) //For allocated pointers only!
132 {
133 pthis = (MEMHEADER * )((char *) p - HEADER_SIZE); //to start of header
134 if ( pthis->prev ) // For the regular header
135 {
136 prev_header = pthis->prev;
137 prev_header->next = pthis->next;
138 if (pthis->next)
139 {
140 pthis->next->prev = prev_header;
141 }
142 }
143 else
144 {
145 pthis->len = 0; //For the first header
146 }
147 }
148}
149
150#else
151
152 //--------------------------------------------------------------------
153 //Written by Dmitry S. Obukhov, 1997
154 //dso@usa.net
155 //--------------------------------------------------------------------
156 //Modified for SDCC by Sandeep Dutta, 1999
157 //sandeep.dutta@usa.net
158 //--------------------------------------------------------------------
159 //malloc and free functions implementation for embedded system
160 //Non-ANSI keywords are C51 specific.
161 // xdata - variable in external memory (just RAM)
162 //--------------------------------------------------------------------
163
164 #define MEMHEADER struct MAH// Memory Allocation Header
165
166 MEMHEADER
167 {
168 MEMHEADER xdata * next;
169 MEMHEADER xdata * prev;
170 unsigned int len;
171 unsigned char mem;
172 };
173
174 #define HEADER_SIZE (sizeof(MEMHEADER)-1)
175
176 //Static here means: can be accessed from this module only
177 static MEMHEADER xdata * FIRST_MEMORY_HEADER_PTR;
178 void init_dynamic_memory(MEMHEADER xdata * array, unsigned int size)
179 {
180
181 //This function MUST be called after the RESET.
182 //Parameters: array - pointer to memory allocated by the linker
183 // size - size of this memory pool
184 //Example:
185 // #define DYNAMIC_MEMORY_SIZE 0x2000
186 // .....
187 // unsigned char xdata dynamic_memory_pool[DYNAMIC_MEMORY_SIZE];
188 // unsigned char xdata * current_buffer;
189 // .....
190 // void main(void)
191 // {
192 // ...
193 // init_dynamic_memory(dynamic_memory_pool,DYNAMIC_MEMORY_SIZE);
194 // Now it is possible to use malloc.
195 // ...
196 // current_buffer = malloc(0x100);
197 //
198 //
199
200 if ( !array ) /*Reserved memory starts on 0x0000 but it's NULL...*/
201 { //So, we lost one byte!
202 array = (MEMHEADER xdata * )((char xdata * ) array + 1) ;
203 size --;
204 }
205 FIRST_MEMORY_HEADER_PTR = array;
206 //Reserve a mem for last header
207 array->next = (MEMHEADER xdata * )(((char xdata * ) array) + size - HEADER_SIZE);
208 array->next->next = (void xdata * ) NULL; //And mark it as last
209 array->prev = (void xdata * ) NULL; //and mark first as first
210 array->len = 0; //Empty and ready.
211 }
212
213 void xdata * malloc (unsigned int size)
214 {
215 register MEMHEADER xdata * current_header;
216 register MEMHEADER xdata * new_header;
217
218 if (size>(0xFFFF-HEADER_SIZE)) return (void xdata *) NULL; //To prevent overflow in next line
219 size += HEADER_SIZE; //We need a memory for header too
220 current_header = FIRST_MEMORY_HEADER_PTR;
221 while (1)
222 {
223
224 // current
225 // | len next
226 // v v v
227 //....*****.........******....
228 // ^^^^^^^^^
229 // spare
230
231 if ((((unsigned int)current_header->next) -
232 ((unsigned int)current_header) -
233 current_header->len) >= size) break; //if spare is more than need
234 current_header = current_header->next; //else try next
235 if (!current_header->next) return (void xdata *) NULL; //if end_of_list reached
236 }
237 if (!current_header->len)
238 { //This code works only for first_header in the list and only
239 current_header->len = size; //for first allocation
240 return ((xdata *)&(current_header->mem));
241 } //else create new header at the begin of spare
242 new_header = (MEMHEADER xdata * )((char xdata *)current_header + current_header->len);
243 new_header->next = current_header->next; //and plug it into the chain
244 new_header->prev = current_header;
245 current_header->next = new_header;
246 if (new_header->next) new_header->next->prev = new_header;
247 new_header->len = size; //mark as used
248 return ((xdata *)&(new_header->mem));
249 }
250
251 void free (void xdata * p)
252 {
253 register MEMHEADER xdata * prev_header;
254 if ( p ) //For allocated pointers only!
255 {
256 p = (MEMHEADER xdata * )((char xdata *) p - HEADER_SIZE); //to start of header
257 if ( ((MEMHEADER xdata * ) p)->prev ) // For the regular header
258 {
259 prev_header = ((MEMHEADER xdata * ) p)->prev;
260 prev_header->next = ((MEMHEADER xdata * ) p)->next;
261 if (((MEMHEADER xdata * ) p)->next)
262 ((MEMHEADER xdata * ) p)->next->prev = prev_header;
263 }
264 else ((MEMHEADER xdata * ) p)->len = 0; //For the first header
265 }
266 }
267 //END OF MODULE
268#endif