
	.align	4
	.arm
	

;*************************************************
;*
;* mem_init
;*
;* 	r0 	= base
;* 	r2 	= len
;*
;*************************************************;******

	.global		mem_init
	.type		mem_init,function	
	

mem_init

	stmfd	sp!,{r0,r1,r2,r3}

	mov	r1,#0	
	mov	r3,#8+(4*3)	;content size used,free&size + overhead
	
	str	r1,[r0]		;next (first element)
	str	r3,[r0,#4]	;size
	str	r1,[r0,#8]	;use counter
	str	r2,[r0,#12]	;free_size
	str	r2,[r0,#16]	;size
	
	ldmfd	sp!,{r0,r1,r2,r3}
	
	bx	lr

;*************************************************
;*
;* mem_malloc
;*
;* 	r0 	= base
;* 	r6 	= size
;* ret: r2 	= adr to free mem or 0
;*	
;*
;*************************************************

	.global		mem_malloc
	.type		mem_malloc,function

mem_malloc		

	stmfd	sp!,{r1,r3-r9}

	ldr	r8,[r0,#16]	;base->size
	add	r8,r8,r0	;overflowadr=base+base->size

	ands	r5,r6,#$3	;kein durch 4 teilbar?
	bicne	r6,r6,#$3	;dann rest weg
	addne	r6,r6,#4	;und 4 plus
	
	add	r6,r6,#8	;noch 8 für overhead (next/size)
	
	mov	r7,r0		;svae base
	mov	r5,r0		;last = base
	
find_free
		
	ldmia	r0,{r3,r4}	;next element;
				;size of this element
	
	;**** overflow test
	
	add	r9,r0,r6	;akt_element + gewünschter Size > Overlow 
	cmp	r9,r8		;dann return(0);
	movhi	r2,#0
	ldmhifd	sp!,{r1,r3-r9}
	movhi	pc,lr	
	
	;**** last element
	
	cmp	r3,#0		;next 0, dann nehmen wir es
	beq	set_element_tail
	
	;**** leakcheck
	
	add	r1,r0,r4	;this + size of this element = this.lenght
	sub	r2,r3,r1	;next - this = leaksize
	cmp	r2,r6		;if leaksize >= will size
	bge	set_element_insert
		
	
		
	;**** gehe zum nächsten element	
		
	mov	r5,r0		;last = this
	mov	r0,r3		;this = next
	b	find_free


;*************************************************
;*
;* set_element_insert
;*
;* 	r1 = this+size = me
;* 	r3 = next
;* ret: r2 	= adr to free mem or 0
;*	
;*
;*************************************************

	.global		set_element_insert
	.type		set_element_insert,function

set_element_insert	
		
	str	r1,[r0]		;this->next = me;
	stmia	r1,{r3,r6}	;me->next   = this->next;	
				;me->length = length
	
	add	r2,r1,#8	;return me+8
	ldmfd	sp!,{r1,r3-r9}
	mov	pc,lr

;*************************************************
;*
;* set_element_tail
;*
;* 	r0 = dest
;* 	r5 = next
;* ret: r2 	= adr to free mem or 0
;*	
;*
;*************************************************

	
	.global		set_element_tail
	.type		set_element_tail,function

set_element_tail

	
	mov	r1,#0
	
	add	r2,r0,r4	;next = this + this->size 	
	str	r2,[r0]		;this->next = me
	
	stmia	r2,{r1,r6}	;me->next   = 0
				;me->lenght = length
		
	add	r2,r2,#8	;return me+8
	ldmfd	sp!,{r1,r3-r9}
	mov	pc,lr
	
;*************************************************
;*
;* mem_free
;*
;* 	r0 = base
;* 	r6 = memadr
;*
;*************************************************	

	.global		mem_free
	.type		mem_free,function

mem_free

	stmfd	sp!,{r0-r9}

	mov	r5,r0		;last = base
	sub	r6,r6,#8	;skip overhead
	
	mov	r7,r0

scan_memlist

	ldmia	r0,{r3,r4}	;next element,size
	
	cmp	r3,r6		;remove this mem
	beq	mem_rem
	
	cmp	r3,#0		;?? out of list
	beq	free_not_found
	
	mov	r0,r3
	mov	r5,r3
	b	scan_memlist

free_not_found

	;**** mache fehler meldung

	ldmfd	sp!,{r0-r9}
	mov	pc,lr

mem_rem

	ldr	r0,[r6]		;r0 = this->next
	
	mov	r1,#0
	str	r1,[r6]		;this->next 	= 0 (nicht unbedingt nötig, nur für besseres debugging)
	str	r1,[r6,#4]	;this->length 	= 0
	
	str	r0,[r5]		;last->next = r0

	ldmfd	sp!,{r0-r9}
	mov	pc,lr	
	
;*************************************************
;*
;* mem_trace
;*
;* 	  r0 = base
;-
;* return r1 = alloc cnt
;*	  r2 = free_size
;*	  r3 = leek cnt  
;*	  r4 = leek size
;*	  r5 = absolute used
;*	
;*
;*************************************************

	.global		mem_trace
	.type		mem_trace,function

mem_trace

	mov	r1,#0		;alloc_cnt = 0
	mov	r3,#0		;leek_cnt = 0
	mov	r4,#0		;leek_size = 0
	mov	r5,#0		;absolute_used = 0
	
	mov	r8,r0		;last=base
	mov	r9,r0		;savebase=base

scan_ml
	
	ldmia	r0,{r6,r7}	;next element;
				;size of this element
						
	add	r10,r0,r7	;this + size of this element = this.lenght
	sub	r11,r10,r6	;next - this = leaksize			
			
			
	add	r1,r1,#1	;alloc_cnt ++;	
	cmp	r11,#0
	addne	r3,r3,#1	;leekcnt++ (wenn leak>0)		
	addne	r4,r4,r10	;leeksize+=leak
	
	sub	r10,r10,r9	;
	add	r5,r5,r10	;abolute_used+=this.length-base
			
	cmp	r6,#0
	beq	scan_ml_halt				
			
	mov	r8,r6		;last = this
	mov	r0,r6		;this = next			
	b	scan_ml				

scan_ml_halt

	ldr	r2,[r9,#16]	;base->size
	sub	r2,r2,r5	;size-=absolute used

	sub	r4,r4,r9
	sub	r4,r4,#$14
	sub	r3,r3,#1
	
		

	mov	pc,lr


;*************************************************
;********* 	stack 		   ***************
;*************************************************



;*************************************************
;*
;* stack_alloc
;*
;* 	  r0 = size
;*
;* return r1 = space addr
;*
;*************************************************

	.global		stack_alloc
	.type		stack_alloc,function

stack_alloc
	
	tst	r0,#3		;aufrunden auf 4
	bicne	r0,r0,#3
	addne	r0,r0,#4
				
	mov	r1,sp		;jetzige pos
	sub	sp,sp,r0	;sp-size
	stmfd	sp!,{r1}	;-sp=backadr
	add	r1,sp,#4	;sp+4 = userspace -> back to user
	
	bx	lr
	
;*************************************************
;*
;* stack_free
;*
;*************************************************

	.global		stack_free
	.type		stack_free,function

stack_free
	
	ldr	sp,[sp]	
	bx	lr
	
	
;*************************************************
;********* 	stack THMUB        ***************
;*************************************************

	.thumb
	.align	4

;*************************************************
;*
;* stack_alloc_th
;*
;* 	  r0 = size
;*
;* return r1 = space addr
;*
;*************************************************

stack_alloc_th
	
	mov	r1,#3
	tst	r0,r1		;aufrunden auf 4
	beq	stack_no_ra
	bic	r0,r1
	add	r0,r0,#4	;aufrunden
	
stack_no_ra	

	mov	r2,sp		;jetzige pos
	sub	r1,r2,r0	;r1=sp-size	(r1=spaceadr)
	mov	sp,r1		;sp=r1
	push	{r2}		;-sp=backadr
	
	bx	lr
	
;*************************************************
;*
;* stack_free_th
;*
;*************************************************

stack_free_th
	
	ldr	r0,[sp]
	mov	sp,r0
	bx	lr
	
	.end
	