#ifndef EXTRA_HEAP_C
#define EXTRA_HEAP_C

#include "globals.c"
#include "global_registers.c"
#include "gts_stack.c"


#ifdef zzzz
	.data
	.align	4
extraheapBottom:
	.long	0
extraP:
	.long	0
	
	.text
	.align 4
#endif

#ifdef zzz
// %ecx = amount of bytes
// can only be used within the first pass.
alloc_from_extra_heap:
#define temp %eax
	pushl 	temp
	
	movl	extraP,temp								// extra heap pointer
	subl	%ecx,temp								
	cmpl	stackBottom,temp						// enough extra heap available
	jae		alloc_from_extra_heap_enough_room
	
	// extraP < stackBottom;  not enough space
	pushl	temp
	
#define temp2 %ebx
	pushl	temp2
	
	movl	stackBottom,temp2
	subl	temp,temp2								// extra bytes needed = stackBottom (temp2) - extraP (temp)
	movl	temp2,%ecx
	shrl	$2,temp2
	
	subl	temp2,free
	js		alloc_from_extra_heap_gc 				// OLD: garbage_collection
	
	call	move_stack_downwards
	
	popl	temp2
	popl	temp
	
alloc_from_extra_heap_enough_room:
	movl	temp,extraP								// update extra heap pointer
	movl	temp,%ecx

	popl	temp
	ret

alloc_from_extra_heap_gc:
#undef temp2	
#undef temp

dynamic_gc:
	jmp		garbage_collection
	
#endif // zzz
	

/*

// ------------------------------------------------------------------------------------------	
// Linked block implementation
	
	// User definable
#define N_LB_ENTRIES		8			// n entries = 2 ^ N_LB_ENTRIES_EXP
#define N_LB_ENTRIES_EXP	3
#define LB_ENTRY_BSIZE		4			// in bytes

	// Implementation
#define LB_ENTRY_WSIZE	(LB_ENTRY_BSIZE / MACHINE_WORD_BSIZE)

#define LB_BLOCK_BSIZE	((N_LB_ENTRIES * LB_ENTRY_BSIZE) + 4)
#define LB_BLOCK_WSIZE	(LB_BLOCK_BSIZE / MACHINE_WORD_BSIZE)

	.data
	.align 	4
lb_root:
	.long	0							// address of root block
lb_current_block:						
	.long	0							// address of current block
lb_entry:
	.long	0							// number of next entry to be allocated
		
	.text
	.align 4
lb_init:
	movl	$0,lb_root
	ret
	
// IN:
// nothing
// OUT
// - %ecx = ptr to allocated entry
lb_alloc_entry:
	// a new block needed?
	cmpl	$0,lb_root
	je		lb_alloc_entry_new_block		
	cmpl	$ N_LB_ENTRIES,lb_entry	
	je		lb_alloc_entry_new_block
	
lb_alloc_entry_block_allocated:
#define temp %ecx
	movl	lb_entry,temp
	shll	$ LB_ENTRY_WSIZE+ 1,temp
	addl	lb_current_block,temp
	addl	$ 4,temp
#undef temp
	incl	lb_entry
	
	ret	

lb_alloc_entry_new_block:
	// allocate a new block
	call	lb_alloc_block
	jmp		lb_alloc_entry_block_allocated
	
// IN:
// - precondition; lb_entry == N_LB_ENTRIES or lb_root = 0; current block is full
// OUT:
// %ecx = ptr to newly allocated empty block
//
lb_alloc_block:
	subl 	$ LB_BLOCK_WSIZE,free
	js		garbage_collection
	
#define lb_block %ecx
	movl	$ LB_BLOCK_BSIZE,lb_block
	call	alloc_from_extra_heap
	
	movl	$0,(lb_block)				// ptr to next lb_block

	movl	$0,lb_entry					// zero entries in lb_block
	
	cmpl	$0,lb_root			
	je		lb_alloc_initial_block
	
#define temp %ebx
	movl	lb_current_block,temp		
	movl	lb_block,(temp)				// make previous block point to current block
#undef temp

	movl	lb_block,lb_current_block	// make newly allocated block the current one

	ret
	
lb_alloc_initial_block:
	movl	lb_block,lb_root			// make root point to initial block
	
	movl	lb_block,lb_current_block	// make newly allocated block the current one
	
	ret
#undef lb_block

// IN:
// - %ecx = valid zero-based index
lb_index_of_entry:
#define index %ecx
#define temp %eax
	pushl	temp
	pushl	index
	
	movl	lb_root,temp
	cmpl	$0,temp
	je 		lb_index_of_entry_internal_error
	
	shrl	$ N_LB_ENTRIES_EXP,index

lb_index_of_entry_loop:
	cmpl	$0,index
	je		lb_index_of_entry_found
	
	movl	(temp),temp
	
	decl	index
	jmp		lb_index_of_entry_loop
	
lb_index_of_entry_found:
	popl	index
	
	andl	$ N_LB_ENTRIES - 1,index
	
	shll	$ LB_ENTRY_WSIZE+ 1,index
	addl	temp,index
	addl	$4,index
		
	popl	temp
	
	ret
#undef temp
#undef index

lb_index_of_entry_internal_error:
	movl	$lb_index_of_entry_internal_error_string,%ecx
	jmp		abort

*/
// ------------------------------------------------------------------------------------------	
// %ecx = contains string

/*
	
	// User definable
#define N_LB_ENTRIES		8			// n entries = 2 ^ N_LB_ENTRIES_EXP
#define N_LB_ENTRIES_EXP	3


#define LB_ENTRY_BSIZE		4			// entry size = 2 ^ LB_ENTRY_BSIZE_EXP (in bytes)
#define LB_ENTRY_BSIZE_EXP	2			
#define MAKE_ID(x)			x##ID
#define MAKE_ID_ID(x)		x##ID

#include "LinkedBlock.c"
*/



	// User definable
#define N_LB_ENTRIES		8			// n entries = 2 ^ N_LB_ENTRIES_EXP
#define N_LB_ENTRIES_EXP	3


#define LB_ENTRY_BSIZE		8			// entry size = 2 ^ LB_ENTRY_BSIZE_EXP (in bytes)
#define LB_ENTRY_BSIZE_EXP	3			

#define MAKE_ID(x)			x##_SN					// data

// NEW ...
#define MAKE_ID_NSN(x)		x##_fixed_SN			// no stack
#define MAKE_ID_USN(x)		x##_unfixed_SN			// unfixed stack
#define MAKE_ID_FSN(x)		x##_fixed_SN			// fixed stack
#define SPECIAL										// To be removed
#define BOTH_FIXEDNESS								// used in both unfixed and fixed contexts
// ... NEW

#define MAKE_ID_SN(x)		x##_SN

#include "LinkedBlock.c"

// Shared nodes array
#define SN_DESCP			0
#define SN_COLOUR			4

#define TOPLEVEL_COLOUR		0

// Format: SN
// word 0:	descP
// word 1 (1234)
//			- highest significant bit of byte 3: 0 = means normal node (during colouring)
//												 1 = EN-node see its format in graph_to_string.c
//			- rest of 34: colour table index i.e. colour combination number
abort:
	movl	esp_backup,%esp
	movl	old_heap_pointer,%edi
	popl	%esi
	
	call	print__string__
	jmp		halt
	
	.data
	.align	4
lb_index_of_entry_internal_error_string:
	.long	__STRING__+2
	.long	57
	.ascii	"lb_index_of_entry_internal_error_string: (internal error)"
	//       012345678901234567890123456789012345678901234567890123456
	.byte 	0
	.byte 	0
	.byte 	0
	.byte	0

foutje:
	.long	__STRING__+2
	.long	6
	.ascii	"foutje"
	.byte 	0
	.byte 	0
	.byte 	0
	.byte	0
#endif

