+
+ if(mem_start >= start && mem_start < end) {
+ size -= mem_start - start;
+ start = mem_start;
+ }
+
+ mr = (struct memrange*)start;
+ mr->magic = MAGIC;
+ mr->attr = type;
+ mr->size = size - sizeof *mr;
+ add_range(pidx, mr);
+ }
+
+ /* allocate stack space at the top of a memory range, order of preference:
+ * fast, slow, chip
+ */
+ smr = 0;
+ for(i=0; i<NUM_POOLS; i++) {
+ mr = pool[i];
+
+ /* ranges in the list are sorted, so keep updating the potential stack
+ * allocation until we reach the end of the list, and use the last one
+ * we found that fits. Note: at this point it's not expected that any
+ * one of the lists will have more than a single range, but this should
+ * work regardless.
+ */
+ while(mr) {
+ if(mr->size >= STACK_SIZE) {
+ stack_top = (uint32_t)mr->start + mr->size;
+ stack_base = stack_top - STACK_SIZE;
+ smr = mr;
+ }
+ mr = mr->next;
+ }
+
+ if(smr) {
+ smr->size -= STACK_SIZE;
+ break;
+ }
+ }
+
+ if(!stack_base) {
+ panic("Failed to allocate stack, no suitable memory ranges found!\n");
+ }
+
+ printf("Allocated %dk stack space: %06lx - %06lx\n", STACK_SIZE >> 10, stack_base, stack_top);
+ move_init_stack(stack_top);
+
+ return 0;
+}
+
+#define MIN_MEMRANGE 8
+
+void *mem_alloc(unsigned int sz, unsigned int attr)
+{
+ int i;
+ struct memrange *mr, *prev, dummy;
+ struct memrange *mem = 0;
+
+ if(!(attr & MEM_ANY)) {
+ attr |= MEM_ANY;
+ }
+
+ for(i=0; i<NUM_POOLS; i++) {
+ if(!(attr & (1 << i))) continue;
+
+ dummy.next = pool[i];
+ prev = &dummy;
+ mr = dummy.next;
+ while(mr) {
+ if(mr->size >= sz) {
+ if(mr->size >= sz + sizeof *mr + MIN_MEMRANGE) {
+ /* we have enough space for a leftover piece */
+ mem = mr;
+
+ mr = (struct memrange*)(mem->start + sz);
+ *mr = *mem;
+ mr->size -= sz + sizeof *mr;
+ prev->next = mr;
+
+ mem->size = sz;
+ mem->attr |= MEM_USED;
+ mem->next = 0;
+ } else {
+ /* not enough leftover space, just allocate the whole range */
+ mem = mr;
+ mr->attr |= MEM_USED;
+ prev->next = mr->next;
+ mr->next = 0;
+ }
+ break;
+ }
+ prev = mr;
+ mr = mr->next;
+ }
+ pool[i] = dummy.next;
+
+ if(mem) {
+ return mem->start;
+ }