
;	File:	astartup.asm
;	Author:	John van Groningen
;	Machine:	amd64

_TEXT	segment para 'CODE'
_TEXT	ends
_DATA	segment para 'DATA'
_DATA	ends

	d2 equ r10
	d3 equ r11
	d4 equ r12
	d5 equ r13

	d3d equ r11d
	d4d equ r12d

	d2b equ r10b

 ifdef LINUX
	.intel_syntax noprefix
 endif

 ifndef LINUX
	extrn	convert_real_to_string:near
 endif
 ifndef LINUX
	extrn	write_heap:near
 endif
	extrn	return_code:near
	extrn	execution_aborted:near
	extrn	e____system__kFinalizerGCTemp:near
	extrn	e____system__kFinalizer:near

 ifdef LINUX
	.globl	times
	.globl	exit
 else
	extrn	GetTickCount:near
	extrn	ExitProcess:near
 endif

 ifdef USE_LIBM
	extrn	cos:near
	extrn	sin:near
	extrn	tan:near
	extrn	atan:near
 endif

NEW_DESCRIPTORS = 1

	_DATA segment
	align	(1 shl 3)

semi_space_size	dq	0

heap_p1	dq	0
heap_p2	dq	0
heap_p3	dq	0
neg_heap_p3	dq	0
end_heap_p3	dq	0
vector_p	dq	0
vector_counter	dq	0
neg_heap_vector_plus_4	dq	0

heap_size_64_65	dq	0
heap_vector	dq	0
stack_top	dq	0
end_vector	dq	0

heap_size_257	dq	0
heap_copied_vector	dq	0

heap_end_after_gc	dq	0
extra_heap	dq	0
extra_heap_size	dq	0
stack_p	dq	0
halt_sp	dq	0
	
n_allocated_words	dq	0

last_time	dq	0
execute_time	dq	0
garbage_collect_time	dq	0
IO_time	dq	0

compact_garbage_collect_time	dq	0
mark_compact_garbage_collect_time	dq	0
total_gc_bytes	dq	0
total_compact_gc_bytes	dq	0

	public	saved_heap_p
saved_heap_p label ptr
	dq	0
	dq	0
	
	public	saved_a_stack_p
saved_a_stack_p	dq	0

	public	end_a_stack
end_a_stack	dq	0

	public	int_to_real_scratch
int_to_real_scratch	dq	0

heap_end_write_heap	dq	0
d3_flag_write_heap	dq	0
heap2_begin_and_end label ptr
		dq	0
		dq	0

	public	a_stack_guard_page
a_stack_guard_page	dq	0

	public	profile_stack_pointer
profile_stack_pointer	dq	0

dll_initisialised	dq	0
	public	end_b_stack
end_b_stack	dq	0
basic_only	dq	0
heap_size_65	dq	0
heap_copied_vector_size	dq	0
heap_end_after_copy_gc	dq	0
heap_mbp	dq	0
heap_p		dq	0
stack_mbp	dq	0

bit_counter	label ptr
	dq	0
bit_vector_p	label ptr
	dq	0
zero_bits_before_mark	label ptr
	dq	1
n_free_words_after_mark	label ptr
	dq	1000
n_last_heap_free_bytes	label ptr
	dq	0
lazy_array_list	label ptr
	dq	0
n_marked_words	label ptr
	dq	0
end_stack	label ptr
	dq	0

bit_vector_size	label ptr
	dq	0

caf_list	label ptr
	dq	0
	public	caf_listp
caf_listp	label ptr
	dq	0
	
zero_length_string	label ptr
	dq	__STRING__+2
	dq	0
true_string	label ptr
	dq	__STRING__+2
	dq	4
true_c_string	label ptr
	db	"True"
	db	0,0,0,0
false_string	label ptr
	dq	__STRING__+2
	dq	5
false_c_string	label ptr
	db	"False"
	db	0,0,0
file_c_string	label ptr
	db	"File"
	db	0,0,0,0
garbage_collect_flag	label ptr
	db	0
	db	0,0,0

	comm	sprintf_buffer:32

out_of_memory_string_1	label ptr
	db	"Not enough memory to allocate heap and stack"
	db	10,0
printf_int_string	label ptr
	db	"%d"
	db	0
printf_real_string	label ptr
	db	"%.15g"
	db	0
printf_string_string	label ptr
	db	"%s"
	db	0
printf_char_string	label ptr
	db	"%c"
	db	0
garbage_collect_string_1	label ptr
	db	"A stack: "
	db	0
garbage_collect_string_2	label ptr
	db	" bytes. BC stack: "
	db	0
garbage_collect_string_3	label ptr
	db	" bytes."
	db	10,0
heap_use_after_gc_string_1	label ptr
	db	"Heap use after garbage collection: "
	db	0
heap_use_after_compact_gc_string_1	label ptr
	db	"Heap use after compacting garbage collection: "
	db	0
heap_use_after_gc_string_2	label ptr
	db	" Bytes."
	db	10,0
stack_overflow_string	label ptr
	db	"Stack overflow."
	db	10,0
out_of_memory_string_4	label ptr
	db	"Heap full."
	db	10,0
time_string_1	label ptr
	db	"Execution: "
	db	0
time_string_2	label ptr
	db	"  Garbage collection: "
	db	0

time_string_3	label ptr
	db	" "
	db	0

time_string_4	label ptr
	db	"  Total: "
	db	0
high_index_string	label ptr
	db	"Index too high in UPDATE string."
	db	10,0
low_index_string	label ptr
	db	"Index negative in UPDATE string."
	db	10,0
IO_error_string	label ptr
	db	"IO error: "
	db	0
new_line_string	label ptr
	db	10,0
	
sprintf_time_string	label ptr
	db	"%d.%02d"
	db	0

marked_gc_string_1	label ptr
	db	"Marked: "
	db	0

 ifdef PROFILE
	align	8
m_system:
	dd	6
	db	"System"
	db	0
	db	0

	dd	m_system
garbage_collector_name:
	dq	0
	db	"garbage_collector"
	db	0
	align	8
 endif

	align	16
	public	sign_real_mask
sign_real_mask	label ptr
	dq	8000000000000000h,8000000000000000h
	public	abs_real_mask
abs_real_mask	label ptr
	dq	7fffffffffffffffh,7fffffffffffffffh

	align (1 shl 3) 
NAN_real	label ptr
	dd	0ffffffffh,7fffffffh
one_real	label ptr
	dd	00000000h,3ff00000h
zero_real	label ptr
	dd	00000000h,00000000h

	align (1 shl 2) 
bit_set_table	label ptr
	dd	00000001h,00000002h,00000004h,00000008h
	dd	00000010h,00000020h,00000040h,00000080h
	dd	00000100h,00000200h,00000400h,00000800h
	dd	00001000h,00002000h,00004000h,00008000h
	dd	00010000h,00020000h,00040000h,00080000h
	dd	00100000h,00200000h,00400000h,00800000h
	dd	01000000h,02000000h,04000000h,08000000h
	dd	10000000h,20000000h,40000000h,80000000h
	dd	0
bit_set_table2	label ptr
	dd	00000001h,0,00000002h,0,00000004h,0,00000008h,0
	dd	00000010h,0,00000020h,0,00000040h,0,00000080h,0
	dd	00000100h,0,00000200h,0,00000400h,0,00000800h,0
	dd	00001000h,0,00002000h,0,00004000h,0,00008000h,0
	dd	00010000h,0,00020000h,0,00040000h,0,00080000h,0
	dd	00100000h,0,00200000h,0,00400000h,0,00800000h,0
	dd	01000000h,0,02000000h,0,04000000h,0,08000000h,0
	dd	10000000h,0,20000000h,0,40000000h,0,80000000h,0
	dd	0,0
bit_clear_table	label ptr
	dd	0fffffffeh,0fffffffdh,0fffffffbh,0fffffff7h
	dd	0ffffffefh,0ffffffdfh,0ffffffbfh,0ffffff7fh
	dd	0fffffeffh,0fffffdffh,0fffffbffh,0fffff7ffh
	dd	0ffffefffh,0ffffdfffh,0ffffbfffh,0ffff7fffh
	dd	0fffeffffh,0fffdffffh,0fffbffffh,0fff7ffffh
	dd	0ffefffffh,0ffdfffffh,0ffbfffffh,0ff7fffffh
	dd	0feffffffh,0fdffffffh,0fbffffffh,0f7ffffffh
	dd	0efffffffh,0dfffffffh,0bfffffffh,7fffffffh
	dd	0ffffffffh
bit_clear_table2	label ptr
	dd	0fffffffeh,-1,0fffffffdh,-1,0fffffffbh,-1,0fffffff7h,-1
	dd	0ffffffefh,-1,0ffffffdfh,-1,0ffffffbfh,-1,0ffffff7fh,-1
	dd	0fffffeffh,-1,0fffffdffh,-1,0fffffbffh,-1,0fffff7ffh,-1
	dd	0ffffefffh,-1,0ffffdfffh,-1,0ffffbfffh,-1,0ffff7fffh,-1
	dd	0fffeffffh,-1,0fffdffffh,-1,0fffbffffh,-1,0fff7ffffh,-1
	dd	0ffefffffh,-1,0ffdfffffh,-1,0ffbfffffh,-1,0ff7fffffh,-1
	dd	0feffffffh,-1,0fdffffffh,-1,0fbffffffh,-1,0f7ffffffh,-1
	dd	0efffffffh,-1,0dfffffffh,-1,0bfffffffh,-1,7fffffffh,-1
	dd	0ffffffffh,-1
first_one_bit_table	label ptr
	db	-1,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0
	db	4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0
	db	5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0
	db	4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0
	db	6,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0
	db	4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0
	db	5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0
	db	4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0
	db	7,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0
	db	4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0
	db	5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0
	db	4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0
	db	6,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0
	db	4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0
	db	5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0
	db	4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0

	align(1 shl  2) 
	comm	sprintf_time_buffer:20

	align(1 shl  3)

;	public	small_integers
	comm	small_integers:33*16
;	public	static_characters
	comm	static_characters:256*16

;	extrn	clean_exception_handler:near
;	public	clean_unwind_info
;clean_unwind_info:
;	DD	000000009H
;	DD	imagerel(clean_exception_handler)

_DATA	ends
	_TEXT segment

	public	abc_main
	public	print
	public	print_char
	public	print_int
	public	print_real
	public	print__string__
	public	print__chars__sc
	public	print_sc
	public	print_symbol
	public	print_symbol_sc
	public	printD
	public	DtoAC
	public	push_t_r_args
	public	push_a_r_args
	public	halt
	public	dump

	public	catAC
	public	sliceAC
	public	updateAC
	public	eqAC
	public	cmpAC

	public	string_to_string_node

	public	_create_arrayB
	public	_create_arrayC
	public	_create_arrayI
	public	_create_arrayR
	public	_create_r_array
	public	create_array
	public	create_arrayB
	public	create_arrayC
	public	create_arrayI
	public	create_arrayR
	public	create_R_array

	public	BtoAC
	public	ItoAC
	public	RtoAC
	public	eqD

	public	collect_0
	public	collect_1
	public	collect_2
	public	collect_3

	public	yet_args_needed
	public	yet_args_needed_0
	public	yet_args_needed_1
	public	yet_args_needed_2
	public	yet_args_needed_3
	public	yet_args_needed_4

	public	_c3,_c4,_c5,_c6,_c7,_c8,_c9,_c10,_c11,_c12
	public	_c13,_c14,_c15,_c16,_c17,_c18,_c19,_c20,_c21,_c22
	public	_c23,_c24,_c25,_c26,_c27,_c28,_c29,_c30,_c31,_c32

	public	e__system__nind
	public	e__system__eaind
; old names of the previous two labels for compatibility, remove later
	public	__indirection,__eaind
	extrn	e__system__dind:near
	public	eval_fill

	public	eval_upd_0,eval_upd_1,eval_upd_2,eval_upd_3,eval_upd_4
	public	eval_upd_5,eval_upd_6,eval_upd_7,eval_upd_8,eval_upd_9
	public	eval_upd_10,eval_upd_11,eval_upd_12,eval_upd_13,eval_upd_14
	public	eval_upd_15,eval_upd_16,eval_upd_17,eval_upd_18,eval_upd_19
	public	eval_upd_20,eval_upd_21,eval_upd_22,eval_upd_23,eval_upd_24
	public	eval_upd_25,eval_upd_26,eval_upd_27,eval_upd_28,eval_upd_29
	public	eval_upd_30,eval_upd_31,eval_upd_32

	public	repl_args_b
	public	push_arg_b
	public	del_args

	public	add_IO_time
	public	add_execute_time
	public	IO_error
	public	stack_overflow

	public	out_of_memory_4
	public	print_error

 ifdef LINUX
	.globl	__start
 else
	extrn	_start:near
 endif

 ifdef PROFILE
;	extrn	init_profiler:near
;	extrn	profile_n:near
;	extrn	profile_s:near
;	extrn	profile_r:near
;	extrn	write_profile_information:near
;	extrn	write_profile_stack:near
 endif

  ifdef USE_LIBM
	public	cos_real
	public	sin_real
	public	tan_real
	public	asin_real
	public	acos_real
	public	atan_real
	public	ln_real
	public	log10_real
	public	exp_real
	public	pow_real
 endif
	public	entier_real
	public	r_to_i_real
  ifdef USE_LIBM
	public	_c_pow
	public	_c_log10
	public	_c_entier
 endif

	public	__driver

; from system.abc:	
	extrn	dINT:near
	extrn	CHAR:near
	extrn	BOOL:near
	extrn	REAL:near
	extrn	FILE:near
	extrn	__STRING__:near
	extrn	__ARRAY__:near
	extrn	__cycle__in__spine:near
	extrn	__print__graph:near
	extrn	__eval__to__nf:near

; from wcon.c:
	extrn	w_print_char:near
	extrn	w_print_string:near
	extrn	w_print_text:near
	extrn	w_print_int:near
	extrn	w_print_real:near

	extrn	ew_print_char:near
	extrn	ew_print_text:near
	extrn	ew_print_string:near
	extrn	ew_print_int:near

	extrn	ew_print_real:near

	extrn	ab_stack_size:near
	extrn	heap_size:near
	extrn	flags:near

; from standard c library:

 ifndef LINUX
	extrn	allocate_memory:near
	extrn	allocate_memory_with_guard_page_at_end:near
	extrn	free_memory:near
 endif
 
	extrn	heap_size_multiple:near
	extrn	initial_heap_size:near

	extrn	min_write_heap_size:near

	extrn	__Nil:near
;	public	finalizer_list
	comm	finalizer_list:qword
;	public	free_finalizer_list
	comm	free_finalizer_list:qword

abc_main:
	push	rbx
	push	rcx
	push	rdx 
	push	rbp 
	push	rsi 
	push	rdi 

	call	init_clean
	test	rax,rax
	jne	init_error

	call	init_timer

	mov	halt_sp,rsp

 ifdef PROFILE
	call	init_profiler
 endif

 ifdef LINUX
	call	__start

exit_:
 else
	call	_start

exit:
 endif

	call	exit_clean

init_error:
	pop	rdi
	pop	rsi
	pop	rbp
	pop	rdx
	pop	rcx
	pop	rbx

 ifdef LINUX
	mov	eax,dword ptr return_code
	jne	return_code_set_1
	mov	eax,-1
return_code_set_1:
 endif
	ret


	public	_DllMain
_DllMain:
	cmp	qword ptr 8[rsp ],1
	je	DLL_PROCESS_ATTACH
	jb	DLL_PROCESS_DETACH
	ret	12

DLL_PROCESS_ATTACH:
	push	rbx 
	push	rcx 
	push	rdx 
	push	rbp 
	push	rsi 
	push	rdi 

	mov	qword ptr dll_initisialised,1

	call	init_clean
	test	rax,rax
	jne	init_dll_error

	call	init_timer

	mov	halt_sp,rsp 

 ifdef PROFILE
	call	init_profiler
 endif

	mov	qword ptr saved_heap_p,rdi
	mov	qword ptr saved_heap_p+8,r15
	mov	saved_a_stack_p,rsi

	mov	rax,1
	jmp	exit_dll_init

init_dll_error:
	xor	rax,rax
	jmp	exit_dll_init
	
DLL_PROCESS_DETACH:
	push	rbx 
	push	rcx 
	push	rdx 
	push	rbp 
	push	rsi 
	push	rdi 
	
	mov	rdi,qword ptr saved_heap_p
	mov	r15,qword ptr saved_heap_p+8
	mov	rsi,saved_a_stack_p

	call	exit_clean

exit_dll_init:
	pop	rdi 
	pop	rsi 
	pop	rbp 
	pop	rdx 
	pop	rcx 
	pop	rbx 
	ret	12

init_clean:
	lea	rax,128[rsp]
	sub	rsp,32+8

	sub	rax,qword ptr ab_stack_size
	mov	end_b_stack,rax 

	mov	rax,qword ptr flags
	and	rax,1
	mov	basic_only,rax 

;	call	allow_prefetch_for_athlon

	mov	rax,qword ptr heap_size
	sub	rax,7
	xor	rdx,rdx 
	mov	rbx,65
	div	rbx
	mov	qword ptr heap_size_65,rax 

	mov	rax,qword ptr heap_size
	sub	rax,7
	xor	rdx,rdx 
	mov	rbx,257
	div	rbx
	mov	heap_size_257,rax
	add	rax,7
	and	rax,-8
	mov	qword ptr heap_copied_vector_size,rax
	mov	qword ptr heap_end_after_copy_gc,0

	mov	rax,qword ptr heap_size
	add	rax,7
	and	rax,-8
	mov	qword ptr heap_size,rax 
	add	rax,7

	mov	rbp,rsp
	and	rsp,-16
 ifdef LINUX
	mov	rdi,rax
	call	malloc
 else
	mov	rcx,rax
	call	allocate_memory
 endif
	mov	rsp,rbp

	test	rax,rax 
	je	no_memory_2

	mov	heap_mbp,rax
	lea	rdi,7[rax]
	and	rdi,-8
	mov	heap_p,rdi 

	mov	rbp,rsp
	and	rsp,-16
 ifdef LINUX
	mov	r14,rdi
	mov	rdi,qword ptr ab_stack_size
	add	rdi,7
	call	malloc
	mov	rdi,r14
 else
	mov	rcx,qword ptr ab_stack_size
	add	rcx,7
	call	allocate_memory_with_guard_page_at_end
 endif
	mov	rsp,rbp
	
	test	rax,rax 
	je	no_memory_3
	
	mov	stack_mbp,rax 

	add	rax,qword ptr ab_stack_size
	add	rax,7+4095
	and	rax,-4096
	mov	qword ptr a_stack_guard_page,rax 
	sub	rax,qword ptr ab_stack_size

	add	rax,7
	and	rax,-8

	mov	rsi,rax 
	mov	stack_p,rax 

	add	rax,qword ptr ab_stack_size
	sub	rax,64
	mov	qword ptr end_a_stack,rax 

	lea	rcx,small_integers
	xor	rax,rax 
	lea	rbx,(dINT+2)

make_small_integers_lp:
	mov	[rcx],rbx 
	mov	8[rcx],rax 
	inc	rax 
	add	rcx,16
	cmp	rax,33
	jne	make_small_integers_lp

	lea	rcx,static_characters
	xor	rax,rax 
	lea	rbx,(CHAR+2)

make_static_characters_lp:
	mov	[rcx],rbx 
	mov	8[rcx],rax 
	inc	rax 
	add	rcx,16
	cmp	rax,256
	jne	make_static_characters_lp

	lea	rcx,(caf_list+8)
	mov	qword ptr caf_listp,rcx 

	lea	rcx,__Nil-8
	mov	qword ptr finalizer_list,rcx
	mov	qword ptr free_finalizer_list,rcx

	mov	heap_p1,rdi

	mov	rbp,qword ptr heap_size_257
	shl	rbp,4
	lea	rax,[rdi+rbp*8]
	mov	heap_copied_vector,rax 
	add	rax,heap_copied_vector_size
	mov	heap_p2,rax

	mov	byte ptr garbage_collect_flag,0

	test	byte ptr flags,64
	je	no_mark1

	mov	rax,qword ptr heap_size_65
	mov	qword ptr heap_vector,rdi 
	add	rdi,rax

	add	rdi,7
	and	rdi,-8

	mov	qword ptr heap_p3,rdi
	lea	rbp,[rax*8]
	mov	byte ptr garbage_collect_flag,-1

no_mark1:
	mov	rax,qword ptr initial_heap_size

	mov	rbx,4000
	test	byte ptr flags,64
	jne	no_mark9
	add	rbx,rbx 
no_mark9:

	cmp	rax,rbx 
	jle	too_large_or_too_small
	shr	rax,3
	cmp	rax,rbp 
	jge	too_large_or_too_small
	mov	rbp,rax 
too_large_or_too_small:

	lea	rax,[rdi+rbp*8]
	mov	heap_end_after_gc,rax 

	test	byte ptr flags,64
	je	no_mark2
	mov	qword ptr bit_vector_size,rbp
no_mark2:

	mov	r15,rbp

	add	rsp,32+8
	xor	rax,rax
	ret

no_memory_2:
	mov	rbp,rsp
	and	rsp,-16
 ifdef LINUX
	lea	rdi,out_of_memory_string_1
 else
	lea	rcx,out_of_memory_string_1
 endif
	call	ew_print_string
	mov	rsp,rbp

	mov	qword ptr execution_aborted,1

	add	rsp,32
	mov	rax,1
	ret

no_memory_3:
	mov	rbp,rsp
	and	rsp,-16

 ifdef LINUX
	lea	rdi,out_of_memory_string_1
 else
	lea	ecx,out_of_memory_string_1
 endif
	call	ew_print_string

	mov	qword ptr execution_aborted,1
 
 ifdef LINUX
	mov	rdi,heap_mbp
	call	free
 else
	mov	rcx,heap_mbp
	call	free_memory
 endif

	mov	rsp,rbp

	add	rsp,32
	mov	rax,1
	ret

exit_clean:
	call	add_execute_time

	mov	rax,qword ptr flags
	test	al,8
	je	no_print_execution_time

	mov	rbp,rsp
	and	rsp,-16
 ifndef LINUX
	sub	rsp,32
 endif

 ifdef LINUX
	lea	rdi,time_string_1
 else
	lea	rcx,time_string_1
 endif
	call	ew_print_string
	
	mov	rax,execute_time
	call	print_time
	
 ifdef LINUX
	lea	rdi,time_string_2
 else
	lea	rcx,time_string_2
 endif
	call	ew_print_string

	mov	rax,garbage_collect_time
 ifdef MEASURE_GC
 else
	add	rax,mark_compact_garbage_collect_time
	add	rax,compact_garbage_collect_time
 endif
	call	print_time

 ifdef MEASURE_GC

  ifdef LINUX
	lea	rdi,time_string_3
  else
	lea	rcx,time_string_3
  endif
	call	ew_print_string

	mov	rax,mark_compact_garbage_collect_time
	call	print_time

  ifdef LINUX
	lea	rdi,time_string_3
  else
	lea	rcx,time_string_3
  endif
	call	ew_print_string

	mov	rax,compact_garbage_collect_time
	call	print_time
 
 endif

 ifdef LINUX
	lea	rdi,time_string_4
 else
	lea	rcx,time_string_4
 endif
	call	ew_print_string

	mov	rax,execute_time
	add	rax,garbage_collect_time
	add	rax,IO_time

	add	rax,mark_compact_garbage_collect_time
	add	rax,compact_garbage_collect_time

	call	print_time

 ifdef LINUX
	mov	rdi,10
 else
	mov	rcx,10
 endif
	call	ew_print_char

 ifdef MEASURE_GC

  ifdef LINUX
	mov	rdi,total_gc_bytes
  else
	mov	rcx,total_gc_bytes
  endif
	call	ew_print_int

  ifdef LINUX
	mov	rdi,32
  else
	mov	rcx,32
  endif
	call	ew_print_char

  ifdef LINUX
	mov rdi,total_compact_gc_bytes
  else
	mov rcx,total_compact_gc_bytes
  endif
	call	ew_print_int

  ifdef LINUX
	mov	rdi,32
  else
	mov	rcx,32
  endif
	call	ew_print_char

	mov	rax,1000
	cvtsi2sd	xmm1,rax
	cvtsi2sd	xmm0,qword ptr garbage_collect_time
	divsd	xmm0,xmm1
	call	ew_print_real

  ifdef LINUX
	mov	rdi,32
  else
	mov	rcx,32
  endif
	call	ew_print_char

	mov	rax,1000
	cvtsi2sd	xmm1,rax
	cvtsi2sd	xmm0,qword ptr mark_compact_garbage_collect_time
	divsd	xmm0,xmm1
	call	ew_print_real

  ifdef LINUX
	mov	rdi,32
  else
	mov	rcx,32
  endif
	call	ew_print_char

	mov	rax,1000
	cvtsi2sd	xmm1,rax
	cvtsi2sd	xmm0,qword ptr compact_garbage_collect_time
	divsd	xmm0,xmm1
	call	ew_print_real

  ifdef LINUX
	mov	rdi,10
  else
	mov	rcx,10
  endif
	call	ew_print_char

	mov	rax,1000
	cvtsi2sd	xmm1,rax
	cvtsi2sd	xmm2,qword ptr garbage_collect_time
	divsd	xmm2,xmm1
	mov	rax,qword ptr total_gc_bytes
	cvtsi2sd	xmm0,rax
	divsd	xmm0,xmm2
	call	ew_print_real

  ifdef LINUX
	mov	rdi,32
  else
	mov	rcx,32
  endif
	call	ew_print_char

	mov	rax,1000
	cvtsi2sd	xmm1,rax
	cvtsi2sd	xmm2,qword ptr mark_compact_garbage_collect_time
	divsd	xmm2,xmm1
	mov	rax,qword ptr total_compact_gc_bytes
	cvtsi2sd	xmm0,rax
	divsd	xmm0,xmm2
	call	ew_print_real

  ifdef LINUX
	mov	rdi,32
  else
	mov	rcx,32
  endif
	call	ew_print_char

	mov	rax,1000
	cvtsi2sd	xmm1,rax
	cvtsi2sd	xmm2,qword ptr compact_garbage_collect_time
	divsd	xmm2,xmm1
	mov	rax,qword ptr total_compact_gc_bytes
	cvtsi2sd	xmm0,rax
	divsd	xmm0,xmm2
	call	ew_print_real

  ifdef LINUX
	mov	rdi,32
  else
	mov	rcx,32
  endif
	call	ew_print_char

	mov	rax,1000
	cvtsi2sd	xmm1,rax
	cvtsi2sd	xmm2,qword ptr mark_compact_garbage_collect_time
	cvtsi2sd	xmm3,qword ptr compact_garbage_collect_time
	addsd	xmm2,xmm3
	divsd	xmm2,xmm1
	mov	rax,qword ptr total_compact_gc_bytes
	cvtsi2sd	xmm0,rax
	divsd	xmm0,xmm2
	call	ew_print_real

  ifdef LINUX
	mov	rdi,10
  else
	mov	rcx,10
  endif
	call	ew_print_char
 
 endif

	mov	rsp,rbp

no_print_execution_time:
	mov	rbp,rsp
	and	rsp,-16
 ifdef LINUX
	mov	rdi,stack_mbp
	call	free

	mov	rdi,heap_mbp
	call	free
 else
	mov	rcx,stack_mbp
	sub	rsp,32
	call	free_memory

	mov	rcx,heap_mbp
	call	free_memory
	add	rsp,32
 endif
	mov	rsp,rbp

 ifdef PROFILE
  ifndef TRACE
	call	write_profile_information
  endif
 endif

	ret

__driver:
	mov	rbp,qword ptr flags
	test	rbp,16
	je	__print__graph
	jmp	__eval__to__nf

print_time:
	push	rbp

	xor	rdx,rdx 
	mov	rbx,1000
	div	rbx 
	mov	rcx,rax 
	mov	rax,rdx 
	xor	rdx,rdx 
	mov	rbx,10
	div	rbx

	push	rax

	mov	rbp,rsp
	and	rsp,-16
 ifdef LINUX
	mov	rdi,rcx
 else
	sub	rsp,32
 endif
	call	ew_print_int
	mov	rsp,rbp

	lea	rcx,sprintf_time_buffer

	xor	rdx,rdx 
	mov	rbx,10

;	movb	$'.',(%rcx )
	mov	byte ptr [rcx],46

	pop	rax

	div	rbx 
	add	rax,48
	add	rdx,48
	mov	byte ptr 1[rcx],al 
	mov	byte ptr 2[rcx],dl 

	mov	rbp,rsp
	and	rsp,-16
 ifdef LINUX
	mov	rsi,3
	mov	rdi,rcx
 else
	mov	rdx,3
	sub	rsp,32
 endif
	call	ew_print_text
	mov	rsp,rbp

	pop	rbp
	ret

print_sc:
	mov	rbp,basic_only
	test	rbp,rbp 
	jne	end_print

print:
	mov	rbp,rsp
	and	rsp,-16
 ifdef LINUX
	mov	r13,rsi
	mov	r14,rdi
	mov	rdi,rax
 else
	mov	rcx,rax
	sub	rsp,32
 endif
	call	w_print_string
 ifdef LINUX
	mov	rsi,r13
	mov	rdi,r14
 endif
	mov	rsp,rbp

end_print:
	ret

dump:
	call	print
	jmp	halt

printD:	test	al,2
	jne	printD_

	mov	rbp,rsp
	and	rsp,-16
 ifdef LINUX
	mov	r13,rsi
	mov	r14,rdi

	lea	rdi,4[rax]
	mov	esi,0[rax]
 else
	lea	rcx,4[rax]
	mov	edx,dword ptr [rax]
	sub	rsp,32
 endif
	call	w_print_text
 ifdef LINUX
	mov	rsi,r13
	mov	rsi,r14
 endif
	mov	rsp,rbp
	ret

DtoAC_record:
 ifdef NEW_DESCRIPTORS
	movsxd	rbp,dword ptr (-6)[rax]
 else
	movsx	rbp,dword ptr (-4)[rbp]
 endif
	jmp	DtoAC_string_a2

DtoAC:	test	al,2
	jne	DtoAC_

	mov	rbp,rax 
	jmp	DtoAC_string_a2

DtoAC_:
 ifdef NEW_DESCRIPTORS
	cmp	word ptr (-2)[rax],256
	jae	DtoAC_record

	movzx	rbx,word ptr [rax]
	lea	rbp,10[rax+rbx]
 else
	lea	rbp,(-2)[rax]
	movsx	rbx,word ptr [rbp]
	cmp	rbx,256
	jae	DtoAC_record

	shl	rbx,3
	sub	rbp,rbx 

 	movzx	rbx,word ptr (-2)[rbp]
	lea	rbp,4[rbp+rbx*8]
 endif

DtoAC_string_a2:
	mov	eax,dword ptr [rbp]
	lea	rcx,4[rbp]
	jmp	build_string

print_symbol:
	xor	rbx,rbx 
	jmp	print_symbol_2

print_symbol_sc:
	mov	rbx,basic_only
print_symbol_2:
	mov	rax,[rcx]

	cmp	rax,offset dINT+2
	je	print_int_node

	cmp	rax,offset CHAR+2
	je	print_char_denotation

	cmp	rax,offset BOOL+2
	je	print_bool

	cmp	rax,offset REAL+2
	je	print_real_node
	
	test	rbx,rbx 
	jne	end_print_symbol

printD_:
 ifdef NEW_DESCRIPTORS
	cmp	word ptr (-2)[rax],256
	jae	print_record

	movzx	rbx,word ptr [rax]
	lea	rbp,10[rax+rbx]
	jmp	print_string_a2

print_record:
	movsxd	rbp,dword ptr (-6)[rax]
	jmp	print_string_a2
 else
	lea	rbp,(-2)[rax]
	movsx	rbx,word ptr [rbp]
	cmp	rbx,256
	jae	print_record

	shl	rbx,3
	sub	rbp,rbx

  	movzx	rbx,word ptr (-2)[rbp]
	lea	rbp,4[rbp+rbx*8]
	jmp	print_string_a2

print_record:
	mov	ebp,(-4)[rbp]
	jmp	print_string_a2
 endif

end_print_symbol:
	ret

print_int_node:
	mov	rbp,rsp
	and	rsp,-16
 ifdef LINUX
	mov	r13,rsi
	mov	r14,rdi
	mov	rdi,8[rcx]
 else
	sub	rsp,32
	mov	rcx,8[rcx]
 endif
	call	w_print_int
 ifdef LINUX
	mov	rsi,r13
	mov	rdi,r14
 endif
	mov	rsp,rbp
	ret

print_int:
	mov	rbp,rsp
	and	rsp,-16
 ifdef LINUX
	mov	r13,rsi
	mov	r14,rdi
	mov	rdi,rax
 else
	mov	rcx,rax
	sub	rsp,32
 endif
	call	w_print_int
 ifdef LINUX
	mov	rsi,r13
	mov	rdi,r14
 endif
	mov	rsp,rbp
	ret

print_char_denotation:
	test	rbx,rbx 
	jne	print_char_node

	mov	rbp,rsp
	and	rsp,-16
 ifdef LINUX
	mov	r13,rsi
	mov	r14,rdi
 else
	sub	rsp,32
 endif
	mov	rbx,8[rcx]

 ifdef LINUX
	mov	rdi,0x27
 else
	mov	rcx,27h
 endif
	call	w_print_char

 ifdef LINUX
	mov	rdi,rbx
 else
	mov	rcx,rbx
 endif
	call	w_print_char

 ifdef LINUX
	mov	rdi,0x27
 else
	mov	rcx,27h
 endif
	call	w_print_char

 ifdef LINUX
	mov	rsi,r13
	mov	rdi,r14
 endif
	mov	rsp,rbp
	ret

print_char_node:
	mov	rbp,rsp
	and	rsp,-16
 ifdef LINUX
	mov	r13,rsi
	mov	r14,rdi
 
	mov	rdi,8[rcx]
else
	mov	rcx,8[rcx]
	sub	rsp,32
 endif
	call	w_print_char
 ifdef LINUX
	mov	rsi,r13
	mov	rdi,r14
 endif
	mov	rsp,rbp
	ret
	
print_char:
	mov	rbp,rsp
	and	rsp,-16
 ifdef LINUX
	mov	r13,rsi
	mov	r14,rdi
	
	mov	rdi,rax
 else
	mov	rcx,rax 
	sub	rsp,32
 endif
	call	w_print_char
 ifdef LINUX
	mov	rsi,r13
	mov	rdi,r14
 endif
	mov	rsp,rbp
	ret

print_bool:
	movsx	rcx,byte ptr 8[rcx]
	test	rcx,rcx 
	je	print_false

print_true:
	mov	rbp,rsp
	and	rsp,-16
 ifdef LINUX
	mov	r13,rsi
	mov	r14,rdi
	lea	rdi,true_c_string
 else
	lea	rcx,true_c_string
	sub	rsp,32
 endif
	call	w_print_string
 ifdef LINUX
	mov	rsi,r13
	mov	rdi,r14
 endif
	mov	rsp,rbp
	ret

print_false:
	mov	rbp,rsp
	and	rsp,-16
 ifdef LINUX
	mov	r13,rsi
	mov	r14,rdi
	lea	rdi,false_c_string
 else
	lea	rcx,false_c_string
	sub	rsp,32
 endif
	call	w_print_string
 ifdef LINUX
	mov	rsi,r13
	mov	rdi,r14
 endif
	mov	rsp,rbp
	ret

print_real_node:
	movlpd	xmm0,qword ptr 8[rcx]
print_real:
	mov	rbp,rsp
	and	rsp,-16
 ifdef LINUX
	mov	r13,rsi
	mov	r14,rdi
 else
	sub	rsp,32
 endif
	call	w_print_real
 ifdef LINUX
	mov	rsi,r13
	mov	rdi,r14
 endif
	mov	rsp,rbp
	ret

print_string_a2:
 ifdef LINUX
	mov	r13,rsi
	mov	r14,rdi
	lea	rdi,4[rbp]
	mov	esi,0[rbp]
	mov	rbp,rsp
	and	rsp,-16
 else
	lea	rcx,4[rbp]
	mov	edx,0[rbp]
	mov	rbp,rsp
	and	rsp,-16
	sub	rsp,32
 endif
	call	w_print_text
 ifdef LINUX
	mov	rsi,r13
	mov	rdi,r14
 endif
	mov	rsp,rbp
	ret

print__chars__sc:
	mov	rbp,basic_only
	test	rbp,rbp 
	jne	no_print_chars

print__string__:
	mov	rbp,rsp
	and	rsp,-16
 ifdef LINUX
	mov	r13,rsi
	mov	r14,rdi
	mov	rsi,8[rcx]
	lea	rdi,16[rcx]
 else
	mov	rdx,8[rcx]
	lea	rcx,16[rcx]
	sub	rsp,32
 endif
	call	w_print_text
 ifdef LINUX
	mov	rsi,r13
	mov	rdi,r14
 endif
	mov	rsp,rbp
no_print_chars:
	ret

push_a_r_args:
	push	rdi

	mov	rdx,qword ptr 16[rcx]
	sub	rdx,2
	movzx	rdi,word ptr [rdx]
	sub	rdi,256
	movzx	rbx,word ptr 2[rdx]
	add	rdx,4
	push	rdx 
		
	mov	rdx,rdi 
	sub	rdx,rbx 

	shl	rax,3
	lea	rcx,24[rcx+rbx*8]
	dec	rdi 
mul_array_size_lp:
	add	rcx,rax 
	sub	rdi,1
	jnc	mul_array_size_lp

	lea	rdi,[rcx+rdx*8]
	jmp	push_a_elements
push_a_elements_lp:
	mov	rax,qword ptr (-8)[rcx]
	sub	rcx,8
	mov	qword ptr [rsi],rax 
	add	rsi,8
push_a_elements:
	sub	rbx,1
	jnc	push_a_elements_lp

	mov	rcx,rdi
	pop	rax
	pop	rdi

	pop	rbp 
	jmp	push_b_elements
push_b_elements_lp:
	push	(-8)[rcx]
	sub	rcx,8
push_b_elements:
	sub	rdx,1
	jnc	push_b_elements_lp

	jmp	rbp

push_t_r_args:
	pop	rbp

	mov	rdx,qword ptr [rcx]
	add	rcx,8
	sub	rdx,2
	movzx	rax,word ptr [rdx]
	sub	rax,256
	movzx	rbx,word ptr 2[rdx]
	add	rdx,4

	mov	qword ptr [rsi],rdx
	mov	qword ptr 8[rsi],rbx

	sub	rbx,rax
	neg	rbx 

	lea	rdx,[rcx+rax*8]
	cmp	rax,2
	jbe	small_record
	mov	rdx,qword ptr 8[rcx]
	lea	rdx,(-8)[rdx+rax*8]
small_record:
	jmp	push_r_b_elements

push_r_b_elements_lp:
	dec	rax 
	jne	not_first_arg_b
	
	push	[rcx]
	jmp	push_r_b_elements
not_first_arg_b:
	push	(-8)[rdx]
	sub	rdx,8
push_r_b_elements:
	sub	rbx,1
	jnc	push_r_b_elements_lp

	mov	rbx,qword ptr 8[rsi]
	push	rbp
	push	[rsi]
	jmp	push_r_a_elements

push_r_a_elements_lp:
	dec	rax 
	jne	not_first_arg_a
	
	mov	rbp,qword ptr [rcx]
	mov	qword ptr [rsi],rbp
	add	rsi,8
	jmp	push_r_a_elements
not_first_arg_a:
	mov	rbp,qword ptr (-8)[rdx]
	sub	rdx,8
	mov	qword ptr [rsi],rbp
	add	rsi,8
push_r_a_elements:
	sub	rbx,1
	jnc	push_r_a_elements_lp

	pop	rax 
	ret

BtoAC:
	test	al,al 
	je	BtoAC_false
BtoAC_true:
	mov	rcx,offset true_string
	ret
BtoAC_false:
	mov	rcx,offset false_string
	ret

RtoAC:
	mov	rbp,rsp
	and	rsp,-16
 ifdef LINUX
	mov	r13,rsi
	mov	r14,rdi
	lea	rsi,printf_real_string
	lea	rdi,sprintf_buffer
	mov	rax,1
	call	sprintf
	mov	rsi,r13
	mov	rdi,r14
 else
	lea	rdx,sprintf_buffer
	sub	rsp,32
	call	convert_real_to_string
 endif
	mov	rsp,rbp
	jmp	return_sprintf_buffer

ItoAC:
	mov	rcx,offset sprintf_buffer
	call	int_to_string
	
	mov	rax,rcx 
	sub	rax,offset sprintf_buffer

	jmp	sprintf_buffer_to_string

	public	convert_int_to_string
convert_int_to_string:
	push	rbp
	push	rbx
	mov	rax,rdx
	call	int_to_string
	mov	rax,rcx 
	pop	rbx
	pop	rbp
	ret

int_to_string:
	test	rax,rax
	jns	no_minus
	mov	byte ptr [rcx],45
	inc	rcx
	neg	rax 
no_minus:
	mov	rbp,rcx

	je	zero_digit
	
calculate_digits:
	cmp	rax,10
	jb	last_digit

	mov	rdx,0cccccccccccccccdh
	mov	rbx,rax 

	mul	rdx  

	mov	rax,rdx 
	and	rdx,-8
	add	rbx,48

	shr	rax,3
	sub	rbx,rdx
	shr	rdx,2

	sub	rbx,rdx
	mov	byte ptr [rcx],bl 

	inc	rcx
	jmp	calculate_digits

last_digit:
	test	rax,rax 
	je	no_zero
zero_digit:
	add	rax,48
	mov	byte ptr [rcx],al 
	inc	rcx
no_zero:
	mov	rdx,rcx

reverse_digits:
	dec	rdx
	cmp	rbp,rdx
	jae	end_reverse_digits
	mov	bl,byte ptr [rbp]
	mov	al,byte ptr [rdx] 
	mov	byte ptr [rdx],bl
	mov	byte ptr [rbp],al
	inc	rbp
	jmp	reverse_digits

end_reverse_digits:
	mov	byte ptr [rcx],0
	ret

return_sprintf_buffer:
	mov	rax,offset sprintf_buffer-1
skip_characters:
	inc	rax 
	cmp	byte ptr [rax],0
	jne	skip_characters

	sub	rax,offset sprintf_buffer

sprintf_buffer_to_string:
	mov	rcx,offset sprintf_buffer
build_string:

	lea	rbx,16+7[rax]
	shr	rbx,3

	sub	r15,rbx
	jge	D_to_S_no_gc

	push	rcx 
	call	collect_0
	pop	rcx 

D_to_S_no_gc:
	sub	rbx,2
	mov	rbp,rdi 
	lea	r9,__STRING__+2
	mov	qword ptr [rdi],r9
	mov	8[rdi],rax 
	add	rdi,16
	jmp	D_to_S_cp_str_2

D_to_S_cp_str_1:
	mov	rax,[rcx]
	add	rcx,8
	mov	[rdi],rax 
	add	rdi,8
D_to_S_cp_str_2:
	sub	rbx,1
	jnc	D_to_S_cp_str_1
	
	mov	rcx,rbp 
	ret

eqD:	mov	rax,[rcx]
	cmp	rax,[rdx]
	jne	eqD_false

	cmp	rax,offset dINT+2
	je	eqD_INT
	cmp	rax,offset CHAR+2
	je	eqD_CHAR
	cmp	rax ,offset BOOL+2
	je	eqD_BOOL
	cmp	rax ,offset REAL+2
	je	eqD_REAL

	mov	rax ,1
	ret

eqD_CHAR:
eqD_INT:
	mov	rbx,8[rcx]
	xor	rax,rax 
	cmp	rbx,8[rdx]
	sete	al
	ret

eqD_BOOL:
	mov	bl,byte ptr 8[rcx]
	xor	rax,rax 
	cmp	bl,byte ptr 8[rdx]
	sete	al 
	ret

eqD_REAL:
	movlpd	xmm0,qword ptr 8[rcx]
	comisd	xmm0,qword ptr 8[rdx]
	fnstsw	ax
	and	ah,68
	xor	ah,64
	sete	al
	and	rax,1
	ret

eqD_false:
	xor	rax ,rax 
	ret
;
;	the timer
;


init_timer:
	mov	rbp,rsp
	and	rsp,-16
	sub	rsp,32
 ifdef LINUX
	mov	r13,rsi
	mov	r14,rdi
	mov	rdi,rsp
	call    times
	mov	rsi,r13
	mov	rdi,r14
	mov	eax,[rsp]
	imul	eax,10
 else
	call	GetTickCount
 endif
	mov	rsp,rbp

	mov	last_time,rax 
	xor	rax ,rax 
	mov	execute_time,rax 
	mov	garbage_collect_time,rax 
	mov	IO_time,rax 

	mov	mark_compact_garbage_collect_time,rax 
	mov	compact_garbage_collect_time,rax 

	ret

get_time_diff:
	mov	rbp,rsp
	and	rsp,-16
	sub	rsp,32
 ifdef LINUX
	mov	r13,rsi
	mov	r14,rdi
	mov	rdi,rsp
	call    times
	mov	rsi,r13
	mov	rdi,r14
	mov	eax,[rsp]
	imul	eax,10
 else
	call	GetTickCount
 endif
	mov	rsp,rbp

	lea	rcx,last_time
	mov	rdx,[rcx]
	mov	[rcx],rax 
	sub	rax,rdx
	ret
	
add_execute_time:
	call	get_time_diff
	lea	rcx,execute_time

add_time:
	add	rax,[rcx]
	mov	[rcx],rax 
	ret

add_garbage_collect_time:
	call	get_time_diff
	mov	rcx,offset garbage_collect_time
	jmp	add_time

add_IO_time:
	call	get_time_diff
	mov	rcx,offset IO_time
	jmp	add_time

add_mark_compact_garbage_collect_time:
	call	get_time_diff
	mov	rcx,offset mark_compact_garbage_collect_time
	jmp	add_time

add_compact_garbage_collect_time:
	call	get_time_diff
	mov	rcx,offset compact_garbage_collect_time
	jmp	add_time
;
;	the garbage collector
;

collect_3:
 ifdef PROFILE
	lea	rbp,garbage_collector_name
	call	profile_s
 endif
	mov	[rsi],rcx 
	mov	8[rsi],rdx 
	mov	16[rsi],r8
	add	rsi,24
	call	collect_0_
	mov	r8,(-8)[rsi]
	mov	rdx,(-16)[rsi]
	mov	rcx,(-24)[rsi]
	sub	rsi,24
 ifdef PROFILE
	jmp	profile_r
 else
	ret
 endif

collect_2:
 ifdef PROFILE
	lea	rbp,garbage_collector_name
	call	profile_s
 endif
	mov	[rsi],rcx 
	mov	8[rsi],rdx 
	add	rsi,16
	call	collect_0_
	mov	rdx,(-8)[rsi]
	mov	rcx,(-16)[rsi]
	sub	rsi,16
 ifdef PROFILE
	jmp	profile_r
 else
	ret
 endif

collect_1:
 ifdef PROFILE
	lea	rbp,garbage_collector_name
	call	profile_s
 endif
	mov	[rsi],rcx 
	add	rsi,8
	call	collect_0_
	mov	rcx,(-8)[rsi]
	sub	rsi,8
 ifdef PROFILE
	jmp	profile_r
 else
	ret
 endif

collect_0:
 ifdef PROFILE
	lea	rbp,garbage_collector_name
	call	profile_s
 endif
	call	collect_0_
 ifdef PROFILE
	jmp	profile_r
 else
	ret
 endif

collect_0_:
	mov	rbp,rdi 

	push	rax
	push	rbx

	mov	rbx,qword ptr heap_end_after_gc
	sub	rbx,rdi

	shr	rbx,3
	sub	rbx,r15
	mov	qword ptr n_allocated_words,rbx

	test	byte ptr flags,64
	je	no_mark3

	mov	rbp,qword ptr bit_counter
	test	rbp,rbp 
	je	no_scan

	push	rsi
	mov	rsi,rbx

	xor	rbx,rbx 
	mov	rcx,qword ptr bit_vector_p

scan_bits:
	cmp	ebx,dword ptr[rcx]
	je	zero_bits
	mov	dword ptr [rcx],ebx 
	add	rcx,4
	sub	rbp,1
	jne	scan_bits

	jmp	end_scan

zero_bits:
	lea	rdx,4[rcx]
	add	rcx,4
	sub	rbp,1
	jne	skip_zero_bits_lp1
	jmp	end_bits

skip_zero_bits_lp:
	test	rax,rax 
	jne	end_zero_bits
skip_zero_bits_lp1:
	mov	eax,dword ptr [rcx]
	add	rcx,4
	sub	rbp,1
	jne	skip_zero_bits_lp

	test	rax,rax 
	je	end_bits
	mov	dword ptr (-4)[rcx],ebx 
	mov	rax,rcx 
	sub	rax,rdx 
	jmp	end_bits2

end_zero_bits:
	mov	rax,rcx 
	sub	rax,rdx 
	shl	rax,3
	add	qword ptr n_free_words_after_mark,rax 
	mov	dword ptr (-4)[rcx],ebx

	cmp	rax,rsi
	jb	scan_bits

found_free_memory:
	mov	qword ptr bit_counter,rbp 
	mov	qword ptr bit_vector_p,rcx 

	lea	rbp,(-4)[rdx]
	sub	rbp,qword ptr heap_vector
	shl	rbp,6
	mov	rdi,qword ptr heap_p3
	add	rdi,rbp 

	lea	rbp,[rdi+rax*8]
	mov	qword ptr heap_end_after_gc,rbp 

	mov	r15,rax
	sub	r15,rsi

	pop	rsi 
	pop	rbx 
	pop	rax 
	ret

end_bits:
	mov	rax,rcx 
	sub	rax,rdx 
	add	rax,4
end_bits2:
	shl	rax,3
	add	qword ptr n_free_words_after_mark,rax 
	cmp	rax,rsi 
	jae	found_free_memory

end_scan:
	pop	rsi 
	mov	qword ptr bit_counter,rbp 

no_scan:

no_mark3:
	movsx	rax,byte ptr garbage_collect_flag
	test	rax,rax 
	jle	collect

	sub	rax,2
	mov	byte ptr garbage_collect_flag,al 

	mov	rbp,qword ptr extra_heap_size
	cmp	rbx,rbp 
	ja	collect

	mov	rdi,qword ptr extra_heap

	mov	r15,rbp

	lea	rbp,[rdi+rbp*8]
	mov	qword ptr heap_end_after_gc,rbp 

	sub	r15,rbx

	pop	rbx 
	pop	rax 
	ret

collect:
 ifdef LINUX
	sub	rsp,104
 else
	sub	rsp,88
 endif
	mov	32[rsp],r10
	mov	24[rsp],r11
	mov	16[rsp],r12
	mov	8[rsp],r13
	mov	[rsp],r14
	movsd	40[rsp],xmm0
	movsd	48[rsp],xmm1
	movsd	56[rsp],xmm2
	movsd	64[rsp],xmm3
	movsd	72[rsp],xmm4
	movsd	80[rsp],xmm5
 ifdef LINUX
	movsd	88[rsp],xmm6
	movsd	96[rsp],xmm7
 endif

	call	add_execute_time

	test	qword ptr flags,4
	je	no_print_stack_sizes

	mov	rbp,rsp
	and	rsp,-16
 ifdef LINUX
 	mov	r13,rsi
	mov	r14,rdi
 else
	sub	rsp,32
 endif

 if 0
  ifdef LINUX
	mov	rdi,qword ptr 64[rsp]
  else
	mov	rcx,qword ptr 96[rsp]
  endif
	call	ew_print_int

  ifdef LINUX
	mov	rdi,32
  else
	mov	rcx,32
  endif
	call	ew_print_char
 endif

 ifdef LINUX
	lea	rdi,garbage_collect_string_1
 else
	lea	rcx,garbage_collect_string_1
 endif
	call	ew_print_string

 ifdef LINUX
	mov	rdi,r13
	sub	rdi,stack_p
 else
	mov	rcx,rsi 
	sub	rcx,stack_p
 endif
	call	ew_print_int

 ifdef LINUX
	lea	rdi,garbage_collect_string_2
 else
	lea	rcx,garbage_collect_string_2
 endif
	call	ew_print_string

 ifdef LINUX
	mov	rdi,halt_sp
	sub	rdi,rsp 
 else
	mov	rcx,halt_sp
	sub	rcx,rsp 
 endif
	call	ew_print_int

 ifdef LINUX
	lea	rdi,garbage_collect_string_3
 else
	lea	rcx,garbage_collect_string_3
 endif
	call	ew_print_string

 ifdef LINUX
	mov	rsi,r13
	mov	rdi,r14
 endif
	mov	rsp,rbp

no_print_stack_sizes:
	mov	rax,stack_p
	add	rax,qword ptr ab_stack_size
	cmp	rsi,rax 
	ja	stack_overflow

	test	byte ptr flags,64
	jne	compacting_collector

	cmp	byte ptr garbage_collect_flag,0
	jne	compacting_collector

	mov	rbp,heap_copied_vector

	cmp	qword ptr heap_end_after_copy_gc,0
	je	zero_all

	mov	rax,rdi
	sub	rax,qword ptr heap_p1
	add	rax,127*8
	shr	rax,9
	call	zero_bit_vector

	mov	rdx,qword ptr heap_end_after_copy_gc
	sub	rdx,qword ptr heap_p1
	shr	rdx,7
	and	rdx,-4

	mov	rbp,qword ptr heap_copied_vector
	mov	rax,qword ptr heap_copied_vector_size
	add	rbp,rdx 
	sub	rax,rdx 
	shr	rax,2

	mov	qword ptr heap_end_after_copy_gc,0

	call	zero_bit_vector
	jmp	end_zero_bit_vector

zero_all:
	mov	rax,heap_copied_vector_size
	shr	rax,2
	call	zero_bit_vector

end_zero_bit_vector:

	include	acopy.asm

	mov	qword ptr heap2_begin_and_end,rsi 

	mov	r15,rsi
	sub	r15,rdi

	mov	rax,heap_size_257
	shl	rax,7
	sub	rax,r15
	add	qword ptr total_gc_bytes,rax

	shr	r15,3

	pop	rsi 

	call	add_garbage_collect_time

	sub	r15,qword ptr n_allocated_words
	jc	switch_to_mark_scan

	lea	rax,[r15+r15*4]
	shl	rax,6
	mov	rbx,qword ptr heap_size
	mov	rcx,rbx 
	shl	rbx,2
	add	rbx,rcx 
	add	rbx,rbx 
	add	rbx,rcx
	cmp	rax,rbx
	jnc	no_mark_scan

switch_to_mark_scan:
	mov	rax,qword ptr heap_size_65
	shl	rax,6
	mov	rbx,qword ptr heap_p

	mov	rcx,qword ptr heap_p1
	cmp	rcx,qword ptr heap_p2
	jc	vector_at_begin
	
vector_at_end:
	mov	qword ptr heap_p3,rbx 
	add	rbx,rax 
	mov	qword ptr heap_vector,rbx 
	
	mov	rax,qword ptr heap_p1
	mov	qword ptr extra_heap,rax 
	sub	rbx,rax 
	shr	rbx,3
	mov	qword ptr extra_heap_size,rbx 
	jmp	switch_to_mark_scan_2

vector_at_begin:
	mov	qword ptr heap_vector,rbx 
	add	rbx,qword ptr heap_size
	sub	rbx,rax 
	mov	qword ptr heap_p3,rbx 
	
	mov	qword ptr extra_heap,rbx 
	mov	rcx,qword ptr heap_p2
	sub	rcx,rbx 
	shr	rcx,3
	mov	qword ptr extra_heap_size,rcx 

switch_to_mark_scan_2:
	mov	rax,heap_size_257
	shl	rax,7-3
	sub	rax,r15
	shl	rax,3

	mov	byte ptr garbage_collect_flag,1

	lea	rcx,heap_use_after_gc_string_1

	test	r15,r15
	jns	end_garbage_collect
	
	mov	byte ptr garbage_collect_flag,-1
	
	mov	rbx,qword ptr extra_heap_size
	mov	r15,rbx
	sub	r15,qword ptr n_allocated_words
	js	out_of_memory_4_3

	mov	rdi,qword ptr extra_heap
	shl	rbx,3
	add	rbx,rdi
	mov	qword ptr heap_end_after_gc,rbx 

	mov	qword ptr heap_end_write_heap,rdi 

	mov	qword ptr d3_flag_write_heap,1
	jmp	end_garbage_collect_

no_mark_scan:
; exchange the semi_spaces
	mov	rax,heap_p1
	mov	rbx,heap_p2
	mov	heap_p2,rax 
	mov	heap_p1,rbx 

	mov	rax,heap_size_257
	shl	rax,7-3
	mov	rbx,rax
	sub	rax,r15

	mov	rcx,rax
	imul	qword ptr heap_size_multiple
	shrd	rax,rdx,9
	shr	rdx,9
	jne	no_small_heap1

	cmp	rax,4000
	jge	not_too_small1
	mov	rax,4000
not_too_small1:
	sub	rbx,rax 
	jb	no_small_heap1

	sub	r15,rbx
	shl	rbx,3
	mov	rbp,qword ptr heap_end_after_gc
	mov	qword ptr heap_end_after_copy_gc,rbp 
	sub	rbp,rbx 
	mov	qword ptr heap_end_after_gc,rbp 

no_small_heap1:
	mov	rax,rcx
	shl	rax,3

	lea	rcx,heap_use_after_gc_string_1

end_garbage_collect:

	mov	qword ptr heap_end_write_heap,rdi 
	mov	qword ptr d3_flag_write_heap,0

end_garbage_collect_:
	test	qword ptr flags,2
	je	no_heap_use_message

	push	rax

	mov	rbp,rsp
	and	rsp,-16

 ifdef LINUX
	mov	r13,rsi
	mov	r14,rdi	

	mov	rdi,rcx
 else
	sub	rsp,32
 endif
	call	ew_print_string

 ifdef LINUX
	mov	rdi,[rbp]
 else
	mov	rcx,[rbp]
 endif
	call	ew_print_int

 ifdef LINUX
	lea	rdi,heap_use_after_gc_string_2
 else
	lea	rcx,heap_use_after_gc_string_2
 endif
	call	ew_print_string

 ifdef LINUX
	mov	rsi,r13
	mov	rdi,r14
 else
 	add	rsp,32
 endif
	mov	rsp,rbp

	pop	rax

no_heap_use_message:
	call	call_finalizers
	 
	test	byte ptr flags,32
	je	no_write_heap

	cmp	rax,qword ptr min_write_heap_size
	jb	no_write_heap

	push	rcx 
	push 	rdx 
	push	rbp 
	push	rsi 
	push	rdi 

	sub	rsp,128

	mov	rax,qword ptr d3_flag_write_heap
	test	rax,rax 
	jne	copy_to_compact_with_alloc_in_extra_heap

	movsx	rax,byte ptr garbage_collect_flag
	
	mov	rcx,qword ptr heap2_begin_and_end
	mov	rdx,qword ptr (heap2_begin_and_end+8)

	mov	rbx,offset heap_p1
	
	test	rax,rax 
	je	gc0
	
	mov	rbx,offset heap_p2
	jg	gc1

	mov	rbx,offset heap_p3
	xor	rcx,rcx 
	xor	rdx,rdx 

gc0:
gc1:
	mov	rbx,qword ptr [rbx ]
	
	mov	rax,rsp 
	
	mov	qword ptr [rax],rbx 
	mov	qword ptr 8[rax],rdi 
	
	mov	qword ptr 16[rax],rcx 
	mov	qword ptr 24[rax],rdx 
	
	mov	rbx ,qword ptr stack_p
	mov	qword ptr 32[rax],rbx 

	mov	qword ptr 40[rax],rsi 
	mov	qword ptr 48[rax],0
	mov	qword ptr 56[rax],0
	
	mov	qword ptr 64[rax],offset small_integers
	mov	qword ptr 72[rax],offset static_characters
	
	mov	qword ptr 80[rax],offset dINT+2
	mov	qword ptr 88[rax],offset CHAR+2
	mov	qword ptr 96[rax],offset REAL+2
	mov	qword ptr 104[rax],offset BOOL+2
	mov	qword ptr 112[rax],offset __STRING__+2
	mov	qword ptr 120[rax],offset __ARRAY__+2

	mov	rbp,rsp
	and	rsp,-16
 ifdef LINUX
	mov	rdi,rax
 else
	mov	rcx,rax
	sub	rsp,32
 endif
 ifndef LINUX
	call	write_heap
 endif
	mov	rsp,rbp

	add	rsp,128
	
	pop	rdi 
	pop	rsi 
	pop	rbp 
	pop	rdx 
	pop	rcx 
no_write_heap:

restore_registers_after_gc_and_return:
	mov	r10,32[rsp]
	mov	r11,24[rsp]
	mov	r12,16[rsp]
	mov	r13,8[rsp]
	mov	r14,[rsp]
	movlpd	xmm0,40[rsp]
	movlpd	xmm1,48[rsp]
	movlpd	xmm2,56[rsp]
	movlpd	xmm3,64[rsp]
	movlpd	xmm4,72[rsp]
	movlpd	xmm5,80[rsp]
 ifdef LINUX
	movlpd	xmm6,88[rsp]
	movlpd	xmm7,96[rsp]
	add	rsp,104
 else
	add	rsp,88
 endif
	pop	rbx 
	pop	rax 
	ret

call_finalizers:
	mov	rax,qword ptr free_finalizer_list

call_finalizers_lp:
	lea	r9,__Nil-8
	cmp	rax,r9
	je	end_call_finalizers
	push	8[rax]
	mov	rbx,qword ptr 16[rax]
	push	8[rbx]
	call	qword ptr [rbx]
	add	rsp,8
	pop	rax 
	jmp	call_finalizers_lp
end_call_finalizers:

	lea	r9,__Nil-8
	mov	qword ptr free_finalizer_list,r9
	ret

copy_to_compact_with_alloc_in_extra_heap:
	mov	rcx,qword ptr heap2_begin_and_end
	mov	rdx,qword ptr (heap2_begin_and_end+8)
	mov	rbx,offset heap_p2
	jmp	gc1

allow_prefetch_for_athlon:
	test	qword ptr flags,4096
	jne	no_prefetch_flag

	xor	rax,rax
	cpuid
	test	rax,rax
	jz	disable_prefetch_flag

 ifdef LINUX
	cmp	rbx,'A'+('u'*0x100)+('t'*0x10000)+('h'*0x1000000)
	jne	disable_prefetch_flag
	cmp	rdx,'e'+('n'*0x100)+('t'*0x10000)+('i'*0x1000000)
	jne	disable_prefetch_flag
	cmp	rcx,'c'+('A'*0x100)+('M'*0x10000)+('D'*0x1000000)
	jne	disable_prefetch_flag
 else
	cmp	rbx,'A'+('u' shl 8)+('t' shl 16)+('h' shl 24)
	jne	disable_prefetch_flag
	cmp	rdx,'e'+('n' shl 8)+('t' shl 16)+('i' shl 24)
	jne	disable_prefetch_flag
	cmp	rcx,'c'+('A' shl 8)+('M' shl 16)+('D' shl 24)
	jne	disable_prefetch_flag
 endif

;	mov	rax,1
;	cpuid
;	and	rax,0f00h
;	cmp	rax,600h
;	je	keep_prefetch_flag

	ret

disable_prefetch_flag:
	and	qword ptr flags,-4097
keep_prefetch_flag:
no_prefetch_flag:
	ret

out_of_memory_4_3:
out_of_memory_4_2:
out_of_memory_4_1:
out_of_memory_4:
	call	add_garbage_collect_time
	
	mov	rbp,offset out_of_memory_string_4
	jmp	print_error

zero_bit_vector:
	xor	rdx,rdx 
	test	al,1
	je	zero_bits1_1
	mov	dword ptr [rbp],edx 
	add	rbp,4
zero_bits1_1:
	shr	rax,1

	mov	rbx,rax 
	shr	rax,1
	test	bl,1
	je	zero_bits1_5

	sub	rbp,8
	jmp	zero_bits1_2

zero_bits1_4:
	mov	dword ptr [rbp],edx 
	mov	dword ptr 4[rbp],edx 
zero_bits1_2:
	mov	dword ptr 8[rbp],edx 
	mov	dword ptr 12[rbp],edx 
	add	rbp,16
zero_bits1_5:
	sub	rax,1
	jae	zero_bits1_4
	ret

reorder:
	push	rsi 
	push	rbp 

	mov	rbp,rax 
	shl	rbp,3
	mov	rsi,rbx 
	shl	rsi,3
	add	rcx,rsi 
	sub	rdx,rbp 

	push	rsi 
	push	rbp 
	push	rbx 
	push	rax 
	jmp	st_reorder_lp

reorder_lp:
	mov	rbp,qword ptr [rcx]
	mov	rsi,qword ptr (-8)[rdx]
	mov	qword ptr (-8)[rdx],rbp 
	sub	rdx,8
	mov	qword ptr [rcx],rsi 
	add	rcx,8
	
	dec	rax
	jne	next_b_in_element
	mov	rax,qword ptr [rsp]
	add	rcx,qword ptr 24[rsp]
next_b_in_element:
	dec	rbx 
	jne	next_a_in_element
	mov	rbx,qword ptr 8[rsp]
	sub	rdx,qword ptr 16[rsp]
next_a_in_element:
st_reorder_lp:
	cmp	rdx,rcx 
	ja	reorder_lp

	pop	rax 
	pop	rbx 
	add	rsp,16
	pop	rbp 
	pop	rsi 
	ret

;
;	the sliding compacting garbage collector
;

compacting_collector:
; zero all mark bits

	mov	rax,qword ptr heap_p3
	neg	rax
	mov	qword ptr neg_heap_p3,rax 

	mov	qword ptr stack_top,rsi

	mov	rdi,qword ptr heap_vector

	test	byte ptr flags,64
	je	no_mark4

	cmp	qword ptr zero_bits_before_mark,0
	je	no_zero_bits

	mov	qword ptr zero_bits_before_mark,0

no_mark4:
	mov	rbp,rdi 
	mov	rax,qword ptr heap_size_65
	add	rax,3
	shr	rax,2

	xor	rbx,rbx 

	test	al,1
	je	zero_bits_1
	mov	dword ptr [rbp],ebx 
	add	rbp,4
zero_bits_1:
	mov	rcx,rax 
	shr	rax,2

	test	cl,2
	je	zero_bits_5

	sub	rbp,8
	jmp	zero_bits_2

zero_bits_4:
	mov	dword ptr [rbp],ebx 
	mov	dword ptr 4[rbp],ebx 
zero_bits_2:
	mov	dword ptr 8[rbp],ebx 
	mov	dword ptr 12[rbp],ebx 
	add	rbp,16
zero_bits_5:
	sub	rax,1
	jnc	zero_bits_4

	test	byte ptr flags,64
	je	no_mark5

no_zero_bits:
	mov	rax,qword ptr n_last_heap_free_bytes
	mov	rbx,qword ptr n_free_words_after_mark
	shl	rbx,3

	mov	rbp,rbx 
	shl	rbp,3
	add	rbp,rbx 
	shr	rbp,2

	cmp	rax,rbp 
	jg	compact_gc

	mov	rbx,qword ptr bit_vector_size
	shl	rbx,3

	sub	rax,rbx 
	neg	rax

	imul	qword ptr heap_size_multiple
	shrd	rax,rdx,7
	shr	rdx,7
	jne	no_smaller_heap
	
	cmp	rax,rbx 
	jae	no_smaller_heap
	
	cmp	rbx,8000
	jbe	no_smaller_heap
	
	jmp	compact_gc
no_smaller_heap:
	test	qword ptr flags,4096
	jne	pmark

	include	amark.asm

	include	amark_prefetch.asm

compact_gc:
	mov	qword ptr zero_bits_before_mark,1
	mov	qword ptr n_last_heap_free_bytes,0
	mov	qword ptr n_free_words_after_mark,1000

no_mark5:

	include	acompact.asm

	mov	rsi,qword ptr stack_top

	mov	rbx,qword ptr heap_size_65
	shl	rbx,6
	add	rbx,qword ptr heap_p3

	mov	qword ptr heap_end_after_gc,rbx 

	sub	rbx,rdi
	shr	rbx,3

	sub	rbx,qword ptr n_allocated_words
	mov	r15,rbx
	jc	out_of_memory_4_1

	mov	rax,rbx
	shl	rax,2
	add	rax,rbx
	shl	rax,4
	cmp	rax,qword ptr heap_size
	jc	out_of_memory_4_2

 	test	byte ptr flags,64
	je	no_mark_6

	mov	rax,qword ptr neg_heap_p3
	add	rax,rdi 
	mov	rbx,qword ptr n_allocated_words
	lea	rax,[rax+rbx*8]

	mov	rbx,qword ptr heap_size_65
	shl	rbx,6
	
	imul	qword ptr heap_size_multiple
	shrd	rax,rdx,8
	shr	rdx,8
	jne	no_small_heap2

	and	rax,-4

	cmp	rax,8000
	jae	not_too_small2
	mov	rax,8000
not_too_small2:
	mov	rcx,rbx 
	sub	rcx,rax 
	jb	no_small_heap2
	
	sub	qword ptr heap_end_after_gc,rcx 
	shr	rcx,3
	sub	r15,rcx

	mov	rbx,rax

no_small_heap2:
	shr	rbx,3
	mov	qword ptr bit_vector_size,rbx 

no_mark_6:
	jmp	no_copy_garbage_collection

no_copy_garbage_collection:
	call	add_compact_garbage_collect_time

	mov	rax,rdi
	sub	rax,qword ptr heap_p3

	add	qword ptr total_compact_gc_bytes,rax 

	mov	rax,rdi 
	sub	rax,qword ptr heap_p3
	mov	rbx,qword ptr n_allocated_words
	lea	rax,[rax+rbx*8]

	lea	rcx,heap_use_after_compact_gc_string_1
	jmp	end_garbage_collect

	public	clean_exception_handler_

clean_exception_handler_:

	jmp	clean_exception_handler_

	mov	rax,qword ptr [rcx]
	cmp	dword ptr [rax],0c00000fdh
	je  	stack_overflow_exception

	cmp	dword ptr [rax],80000001h
	je  	guard_page_or_access_violation_exception

	cmp	dword ptr [rax] ,0c0000005h
	je  	guard_page_or_access_violation_exception

no_stack_overflow_exception:
	mov	rax,0
	ret

guard_page_or_access_violation_exception:
	mov	rax,qword ptr 16[rax]
	and	rax,-4096
	cmp	qword ptr a_stack_guard_page,rax
	jne 	no_stack_overflow_exception
	
	cmp	qword ptr a_stack_guard_page,0
	je  	no_stack_overflow_exception

stack_overflow_exception:
	mov	rax,qword ptr 8[rcx]
	mov	qword ptr (0F8h)[rax],offset stack_overflow

	mov	rax,-1
	ret

stack_overflow:
	call	add_execute_time

	mov	rbp,offset stack_overflow_string
	jmp	print_error

IO_error:
	mov	rbp,rsp
	and	rsp,-16

	mov	rbx,rcx
 ifdef LINUX
	lea	rdi,IO_error_string
 else
	sub	rsp,32
	lea	rcx,IO_error_string
 endif
	call	ew_print_string

 ifdef LINUX
	mov	rdi,rbx
 else
	mov	rcx,rbx
 endif
	call	ew_print_string

 ifdef LINUX
	lea	rdi,new_line_string
 else
	lea	rcx,new_line_string
 endif
	call	ew_print_string

	mov	rsp,rbp

	jmp	halt

print_error:
 ifdef LINUX
	mov	rdi,rbp
 else
	mov	rcx,rbp 
 endif
	mov	rbp,rsp
	and	rsp,-16
	call	ew_print_string
	mov	rsp,rbp

halt:
	mov	rsp,halt_sp

 ifdef PROFILE
	call	write_profile_stack
 endif

	mov	qword ptr execution_aborted,1

	cmp	qword ptr dll_initisialised,0
 ifdef LINUX
	je	exit_
 else
	je	exit
 endif
 ifdef LINUX
	cmp	dword ptr return_code,0
 else
	cmp	qword ptr return_code,0
 endif
	jne	return_code_set
 ifdef LINUX
	mov	dword ptr return_code,-1
 else
	mov	qword ptr return_code,-1
 endif
return_code_set:
 ifdef LINUX
	mov	edi,dword ptr return_code
	and	rsp,-16
	call	exit
 else
	push	qword ptr return_code
	call	(ExitProcess)
 endif
	jmp	return_code_set

e__system__eaind:
__eaind:
eval_fill:
	mov	[rsi],rcx 
	add	rsi,8
	mov	rcx,rdx 
	call	qword ptr [rdx]
	mov	rdx,rcx 
	mov	rcx,(-8)[rsi]
	sub	rsi,8
	
	mov	rbp,[rdx]
	mov	[rcx],rbp 
	mov	rbp,8[rdx]
	mov	8[rcx],rbp 
	mov	rbp,16[rdx]
	mov	16[rcx],rbp 
	ret

	align	(1 shl 2) 
	lea	rax,e__system__eaind
	jmp	rax
 ifdef LINUX
; pc relative lea instruction is one byte longer
	db	0,0
 else
	db	0,0,0
 endif
	dd	e__system__dind
	dd	-2
e__system__nind:
__indirection:
	mov	rdx,8[rcx]
	mov	rax,[rdx]
	test	al,2

	je	eval_fill2

	mov	[rcx],rax 
	mov	rbp,8[rdx]
	mov	8[rcx],rbp 
	mov	rbp,16[rdx]
	mov	16[rcx],rbp 
	ret

eval_fill2:
	lea	r9,__cycle__in__spine
	mov	qword ptr [rcx],r9
	mov	qword ptr [rsi],rcx 

	test	byte ptr flags,64
	je	__cycle__in__spine	

	add	rsi,8
	mov	rcx,rdx 
	call	rax 
	mov	rdx,rcx
	mov	rcx,qword ptr (-8)[rsi]
	sub	rsi,8
	
	mov	rbp,[rdx]
	mov	[rcx],rbp
	mov	rbp,8[rdx]
	mov	8[rcx],rbp
	mov	rbp,16[rdx]
	mov	16[rcx],rbp 
	ret

 ifdef PROFILE
	call	profile_n
	mov	rbp,rax
 endif
eval_upd_0:
	mov	qword ptr [rdx],offset __indirection
	mov	8[rdx],rcx 
	jmp	rbp

 ifdef PROFILE
	call	profile_n
	mov	rbp,rax
 endif
eval_upd_1:
	mov	qword ptr [rdx],offset __indirection
	mov	rax,8[rdx]
	mov	8[rdx],rcx 
	mov	rdx,rax 
	jmp	rbp

 ifdef PROFILE
	call	profile_n
	mov	rbp,rax
 endif
eval_upd_2:
	mov	qword ptr [rdx],offset __indirection
	mov	r8,8[rdx]
	mov	8[rdx],rcx
	mov	rdx,16[rdx]
	jmp	rbp 

 ifdef PROFILE
	call	profile_n
	mov	rbp,rax
 endif
eval_upd_3:
	mov	qword ptr [rdx],offset __indirection
	mov	r8,8[rdx]
	mov	8[rdx],rcx
	mov	[rsi],rcx
	mov	rcx,24[rdx]
	add	rsi,8
	mov	rdx,16[rdx]
	jmp	rbp

 ifdef PROFILE
	call	profile_n
	mov	rbp,rax
 endif
eval_upd_4:
	mov	qword ptr [rdx],offset __indirection
	mov	r8,8[rdx]
	mov	8[rdx],rcx 
	mov	[rsi],rcx 
	mov	rbx,32[rdx]
	mov	8[rsi],rbx 
	mov	rcx,24[rdx]
	add	rsi,16
	mov	rdx,16[rdx]
	jmp	rbp

 ifdef PROFILE
	call	profile_n
	mov	rbp,rax
 endif
eval_upd_5:
	mov	qword ptr [rdx],offset __indirection
	mov	r8,8[rdx]
	mov	[rsi],rcx 
	mov	8[rdx],rcx 
	mov	rbx,40[rdx]
	mov	8[rsi],rbx 
	mov	rbx,32[rdx]
	mov	16[rsi],rbx 
	mov	rcx,24[rdx]
	add	rsi,24
	mov	rdx,16[rdx]
	jmp	rbp

 ifdef PROFILE
	call	profile_n
	mov	rbp,rax
 endif
eval_upd_6:
	mov	qword ptr [rdx],offset __indirection
	mov	r8,8[rdx]
	mov	[rsi],rcx 
	mov	8[rdx],rcx 
	mov	rbx,48[rdx]
	mov	8[rsi],rbx
	mov	rbx,40[rdx]
	mov	16[rsi],rbx 
	mov	rbx,32[rdx]
	mov	24[rsi],rbx 
	mov	rcx,24[rdx]
	add	rsi,32
	mov	rdx,16[rdx]
	jmp	rbp 

 ifdef PROFILE
	call	profile_n
	mov	rbp,rax
 endif
eval_upd_7:
	mov	rax,0
	mov	rbx,40
eval_upd_n:
	mov	qword ptr [rdx],offset __indirection
	mov	r8,8[rdx]
	mov	[rsi],rcx 
	mov	8[rdx],rcx 
	add	rdx,rbx 
	mov	rbx,16[rdx ]
	mov	8[rsi],rbx 
	mov	rbx,8[rdx]
	mov	16[rsi],rbx 
	mov	rbx,[rdx]
	mov	24[rsi],rbx 
	add	rsi,32

eval_upd_n_lp:
	mov	rbx,(-8)[rdx]
	sub	rdx,8
	mov	[rsi],rbx 
	add	rsi,8
	sub	rax,1
	jnc	eval_upd_n_lp

	mov	rcx,(-8)[rdx]
	mov	rdx,(-16)[rdx ]
	jmp	rbp 

 ifdef PROFILE
	call	profile_n
	mov	rbp,rax
 endif
eval_upd_8:
	mov	rax,1
	mov	rbx,48
	jmp	eval_upd_n

 ifdef PROFILE
	call	profile_n
	mov	rbp,rax
 endif
eval_upd_9:
	mov	rax,2
	mov	rbx,56
	jmp	eval_upd_n

 ifdef PROFILE
	call	profile_n
	mov	rbp,rax
 endif
eval_upd_10:
	mov	rax,3
	mov	rbx,64
	jmp	eval_upd_n

 ifdef PROFILE
	call	profile_n
	mov	rbp,rax
 endif
eval_upd_11:
	mov	rax,4
	mov	rbx,72
	jmp	eval_upd_n

 ifdef PROFILE
	call	profile_n
	mov	rbp,rax
 endif
eval_upd_12:
	mov	rax,5
	mov	rbx,80
	jmp	eval_upd_n

 ifdef PROFILE
	call	profile_n
	mov	rbp,rax
 endif
eval_upd_13:
	mov	rax,6
	mov	rbx,88
	jmp	eval_upd_n

 ifdef PROFILE
	call	profile_n
	mov	rbp,rax
 endif
eval_upd_14:
	mov	rax,7
	mov	rbx,96
	jmp	eval_upd_n

 ifdef PROFILE
	call	profile_n
	mov	rbp,rax
 endif
eval_upd_15:
	mov	rax,8
	mov	rbx,104
	jmp	eval_upd_n

 ifdef PROFILE
	call	profile_n
	mov	rbp,rax
 endif
eval_upd_16:
	mov	rax,9
	mov	rbx,112
	jmp	eval_upd_n

 ifdef PROFILE
	call	profile_n
	mov	rbp,rax
 endif
eval_upd_17:
	mov	rax,10
	mov	rbx,120
	jmp	eval_upd_n

 ifdef PROFILE
	call	profile_n
	mov	rbp,rax
 endif
eval_upd_18:
	mov	rax,11
	mov	rbx,128
	jmp	eval_upd_n

 ifdef PROFILE
	call	profile_n
	mov	rbp,rax
 endif
eval_upd_19:
	mov	rax,12
	mov	rbx,136
	jmp	eval_upd_n

 ifdef PROFILE
	call	profile_n
	mov	rbp,rax
 endif
eval_upd_20:
	mov	rax,13
	mov	rbx,144
	jmp	eval_upd_n

 ifdef PROFILE
	call	profile_n
	mov	rbp,rax
 endif
eval_upd_21:
	mov	rax,14
	mov	rbx,152
	jmp	eval_upd_n

 ifdef PROFILE
	call	profile_n
	mov	rbp,rax
 endif
eval_upd_22:
	mov	rax,15
	mov	rbx,160
	jmp	eval_upd_n

 ifdef PROFILE
	call	profile_n
	mov	rbp,rax
 endif
eval_upd_23:
	mov	rax,16
	mov	rbx,168
	jmp	eval_upd_n

 ifdef PROFILE
	call	profile_n
	mov	rbp,rax
 endif
eval_upd_24:
	mov	rax,17
	mov	rbx,176
	jmp	eval_upd_n

 ifdef PROFILE
	call	profile_n
	mov	rbp,rax
 endif
eval_upd_25:
	mov	rax,18
	mov	rbx,184
	jmp	eval_upd_n

 ifdef PROFILE
	call	profile_n
	mov	rbp,rax
 endif
eval_upd_26:
	mov	rax,19
	mov	rbx,192
	jmp	eval_upd_n

 ifdef PROFILE
	call	profile_n
	mov	rbp,rax
 endif
eval_upd_27:
	mov	rax,20
	mov	rbx,200
	jmp	eval_upd_n

 ifdef PROFILE
	call	profile_n
	mov	rbp,rax
 endif
eval_upd_28:
	mov	rax,21
	mov	rbx,208
	jmp	eval_upd_n

 ifdef PROFILE
	call	profile_n
	mov	rbp,rax
 endif
eval_upd_29:
	mov	rax,22
	mov	rbx,216
	jmp	eval_upd_n

 ifdef PROFILE
	call	profile_n
	mov	rbp,rax
 endif
eval_upd_30:
	mov	rax,23
	mov	rbx,224
	jmp	eval_upd_n

 ifdef PROFILE
	call	profile_n
	mov	rbp,rax
 endif
eval_upd_31:
	mov	rax,24
	mov	rbx,232
	jmp	eval_upd_n

 ifdef PROFILE
	call	profile_n
	mov	rbp,rax
 endif
eval_upd_32:
	mov	rax,25
	mov	rbx,240
	jmp	eval_upd_n

;
;	STRINGS
;

catAC:
	mov	rax,8[rcx]
	mov	rbx,8[rdx]
	lea	rbp,16+7[rax+rbx]
	shr	rbp,3
	sub	r15,rbp
	jl	gc_3
gc_r_3:
	add	rcx,16
	add	rdx,16

; fill_node

	mov	r8,rdi
	mov	qword ptr [rdi],offset __STRING__+2

; store length

	lea	rbp,[rax+rbx]
	mov	8[rdi],rbp 
	add	rdi,16

; copy string 1

	lea	rbp,7[rbx]
	shr	rbp,3
	add	rbx,rdi 

	xchg	rcx,rbp 
	xchg	rsi,rdx 
	cld
	rep movsq
	mov	rsi,rdx 
	mov	rcx,rbp 

	mov	rdi,rbx 

; copy_string 2

cat_string_6:
	mov	rbp,rax 
	shr	rbp,3
	je	cat_string_9

cat_string_7:
	mov	rbx,[rcx]
	add	rcx,8
	mov	[rdi],rbx 
	add	rdi,8
	dec	rbp 
	jne	cat_string_7
	
cat_string_9:
	test	al,4
	je	cat_string_10
	mov	ebx,dword ptr [rcx]
	add	rcx,4
	mov	dword ptr [rdi],ebx 
	add	rdi,4
cat_string_10:
	test	al,2
	je	cat_string_11
	mov	bx,word ptr [rcx]
	add	rcx,2
	mov	word ptr [rdi],bx 
	add	rdi,2
cat_string_11:
	test	al,1
	je	cat_string_12
	mov	bl,byte ptr [rcx]
	mov	byte ptr [rdi],bl 
	inc	rdi
cat_string_12:

	mov	rcx,r8
; align heap pointer
	add	rdi,7
	and	rdi,-8
	ret

gc_3:	call	collect_2
	jmp	gc_r_3

empty_string:
	mov	rcx,offset zero_length_string
	ret

sliceAC:
	mov	rbp,8[rcx]
	test	rbx,rbx 
	jns	slice_string_1
	xor	rbx,rbx 
slice_string_1:
	cmp	rbx,rbp 
	jge	empty_string
	cmp	rax,rbx 
	jl	empty_string
	inc	rax 
	cmp	rax,rbp 
	jle	slice_string_2
	mov	rax,rbp 
slice_string_2:
	sub	rax,rbx 

	lea	rbp,(16+7)[rax]
	shr	rbp,3

	sub	r15,rbp
	jl	gc_4
r_gc_4:
	sub	rbp,2
	lea	rdx,16[rcx+rbx]

	mov	qword ptr [rdi],offset __STRING__+2
	mov	8[rdi],rax 

; copy part of string
	mov	rcx,rbp 
	mov	rbp,rdi 
	add	rdi,16

	xchg	rsi,rdx 
	cld
	rep movsq
	mov	rsi,rdx 
	mov	rcx,rbp 
	ret

gc_4:
	mov	rbp,rdx 
	call	collect_1
	lea	rbp,(16+7)[rax]
	shr	rbp,3
	jmp	r_gc_4

updateAC:
	mov	rbp,8[rcx]
	cmp	rbx,rbp 
	jae	update_string_error

	add	rbp,16+7
	shr	rbp,3

	sub	r15,rbp
	jl	gc_5
r_gc_5:
	mov	rbp,8[rcx]
	add	rbp,7
	shr	rbp,3

	mov	rdx,rcx 
	mov	r8,rdi 
	mov	qword ptr [rdi],offset __STRING__+2
	mov	rcx,8[rdx]
	add	rdx,16
	mov	8[rdi],rcx 
	add	rdi,16

	add	rbx,rdi

	mov	rcx,rbp 
	xchg	rsi,rdx 
	cld
	rep movsq
	mov	rsi,rdx 

	mov	byte ptr [rbx],al 
	mov	rcx,r8 
	ret

gc_5:	call	collect_1
	jmp	r_gc_5

update_string_error:
	mov	rbp,offset high_index_string
	test	rax,rax 
	jns	update_string_error_2
	mov	rbp,offset low_index_string
update_string_error_2:
	jmp	print_error

eqAC:
	mov	rax,8[rcx]
	cmp	rax,8[rdx]
	jne	equal_string_ne
	add	rcx,16
	add	rdx,16
	mov	rbx,rax 
	and	rbx,7
	shr	rax,3
	je	equal_string_d
equal_string_1:
	mov	rbp,[rcx]
	cmp	rbp,[rdx]
	jne	equal_string_ne
	add	rcx,8
	add	rdx,8
	dec	rax
	jne	equal_string_1
equal_string_d:
	test	bl,4
	je	equal_string_w
	mov	eax,dword ptr [rcx]
	cmp	eax,dword ptr [rdx]
	jne	equal_string_ne
	add	rcx,4
	add	rdx,4
equal_string_w:
	test	bl,2
	je	equal_string_b
	mov	ax,word ptr [rcx]
	cmp	ax,word ptr [rdx]
	jne	equal_string_ne
	add	rcx,2
	add	rdx,2
equal_string_b:
	test	bl,1
	je	equal_string_eq
	mov	bl,byte ptr [rcx]
	cmp	bl,byte ptr [rdx]
	jne	equal_string_ne
equal_string_eq:
	mov	rax,1
	ret
equal_string_ne:
	xor	rax,rax 
	ret

cmpAC:
	mov	rbx,8[rcx]
	mov	rbp,8[rdx]
	add	rcx,16
	add	rdx,16
	cmp	rbp,rbx 
	jb	cmp_string_less
	ja	cmp_string_more
	xor	rax,rax 
	jmp	cmp_string_chars
cmp_string_more:
	mov	rax,1
	jmp	cmp_string_chars
cmp_string_less:
	mov	rax,-1
	mov	rbx,rbp 
	jmp	cmp_string_chars

cmp_string_1:
	mov	rbp,[rdx]
	cmp	rbp,[rcx]
	jne	cmp_string_ne_q
	add	rdx,8
	add	rcx,8
cmp_string_chars:
	sub	rbx,8
	jnc	cmp_string_1
cmp_string_d:
	test	bl,4
	je	cmp_string_w
	mov	ebp,dword ptr [rdx]
	cmp	ebp,dword ptr [rcx]
	jne	cmp_string_ne_d
	add	rdx,4
	add	rcx,4
cmp_string_w:
	test	bl,2
	je	cmp_string_b
	mov	bpl,byte ptr [rdx]
	cmp	bpl,byte ptr [rcx]
	jne	cmp_string_ne
	mov	bpl,byte ptr 1[rdx]
	cmp	bpl,byte ptr 1[rcx]
	jne	cmp_string_ne
	add	rdx,2
	add	rcx,2
cmp_string_b:
	test	bl,1
	je	cmp_string_eq
	mov	bl,byte ptr [rdx]
	cmp	bl,byte ptr [rcx]
	jne	cmp_string_ne
cmp_string_eq:
	ret
cmp_string_ne_d:
	mov	r10d,[rcx]
	bswap	ebp
	bswap	r10d
	cmp	ebp,r10d
	jmp	cmp_string_ne
cmp_string_ne_q:
	mov	r10,[rcx]
	bswap	rbp
	bswap	r10
	cmp	rbp,r10
cmp_string_ne:
	ja	cmp_string_r1
	mov	rax,-1
	ret
cmp_string_r1:
	mov	rax,1
	ret

string_to_string_node:
	mov	rax,qword ptr [rcx]
	add	rcx,8

	lea	rbx,16+7[rax]
	shr	rbx,3

	sub	r15,rbx
	jl	string_to_string_node_gc

string_to_string_node_r:
	sub	rbx,2
	mov	qword ptr [rdi],offset __STRING__+2
	mov	qword ptr 8[rdi],rax 
	mov	rbp,rdi
	add	rdi,16
	jmp	string_to_string_node_4
	
string_to_string_node_2:
	mov	rax,qword ptr [rcx]
	add	rcx,8
	mov	qword ptr [rdi],rax 
	add	rdi,8
string_to_string_node_4:
	sub	rbx,1
	jge	string_to_string_node_2

	mov	rcx,rbp 
	ret

string_to_string_node_gc:
	push	rcx
	call	collect_0
	pop	rcx
	jmp	string_to_string_node_r

	align	(1 shl 2)
	dd	3
_c3:	jmp	__cycle__in__spine
	align	(1 shl 2)

	dd	4
_c4:	jmp	__cycle__in__spine
	align	(1 shl 2)
	dd	5
_c5:	jmp	__cycle__in__spine
	align	(1 shl 2)
	dd	6
_c6:	jmp	__cycle__in__spine
	align	(1 shl 2)
	dd	7
_c7:	jmp	__cycle__in__spine
	align	(1 shl 2)
	dd	8
_c8:	jmp	__cycle__in__spine
	align	(1 shl 2)
	dd	9
_c9:	jmp	__cycle__in__spine
	align	(1 shl 2)
	dd	10
_c10:	jmp	__cycle__in__spine
	align	(1 shl 2)
	dd	11
_c11:	jmp	__cycle__in__spine
	align	(1 shl 2)
	dd	12
_c12:	jmp	__cycle__in__spine
	align	(1 shl 2)
	dd	13
_c13:	jmp	__cycle__in__spine
	align	(1 shl 2)
	dd	14
_c14:	jmp	__cycle__in__spine
	align	(1 shl 2)
	dd	15
_c15:	jmp	__cycle__in__spine
	align	(1 shl 2)
	dd	16
_c16:	jmp	__cycle__in__spine
	align	(1 shl 2)
	dd	17
_c17:	jmp	__cycle__in__spine
	align	(1 shl 2)
	dd	18
_c18:	jmp	__cycle__in__spine
	align	(1 shl 2)
	dd	19
_c19:	jmp	__cycle__in__spine
	align	(1 shl 2)
	dd	20
_c20:	jmp	__cycle__in__spine
	align	(1 shl 2)
	dd	21
_c21:	jmp	__cycle__in__spine
	align	(1 shl 2)
	dd	22
_c22:	jmp	__cycle__in__spine
	align	(1 shl 2)
	dd	23
_c23:	jmp	__cycle__in__spine
	align	(1 shl 2)
	dd	24
_c24:	jmp	__cycle__in__spine
	align	(1 shl 2)
	dd	25
_c25:	jmp	__cycle__in__spine
	align	(1 shl 2)
	dd	26
_c26:	jmp	__cycle__in__spine
	align	(1 shl 2)
	dd	27
_c27:	jmp	__cycle__in__spine
	align	(1 shl 2)
	dd	28
_c28:	jmp	__cycle__in__spine
	align	(1 shl 2)
	dd	29
_c29:	jmp	__cycle__in__spine
	align	(1 shl 2)
	dd	30
_c30:	jmp	__cycle__in__spine
	align	(1 shl 2)
	dd	31
_c31:	jmp	__cycle__in__spine
	align	(1 shl 2)
	dd	32
_c32:	jmp	__cycle__in__spine

;
;	ARRAYS
;

_create_arrayB:
	mov	rbx,rax 
	add	rax,24+7
	shr	rax,3
	sub	r15,rax
	jge	no_collect_4574
	call	collect_0
no_collect_4574:
	mov	rcx,rdi
	mov	qword ptr [rdi],offset __ARRAY__+2
	mov	qword ptr 8[rdi],rbx 
	mov	qword ptr 16[rdi],offset BOOL+2
	lea	rdi,[rdi+rax*8]
	ret

_create_arrayC:
	mov	rbx,rax
	add	rax,16+7
	shr	rax,3
	sub	r15,rax
	jge	no_collect_4573
	call	collect_0
no_collect_4573:
	mov	rcx,rdi 
	mov	qword ptr [rdi],offset __STRING__+2
	mov	qword ptr 8[rdi],rbx 
	lea	rdi,[rdi+rax*8]
	ret

_create_arrayI:
	lea	rbp,3[rax]
	sub	r15,rbp
	jge	no_collect_4572
	call	collect_0
no_collect_4572:
	mov	rcx,rdi
	lea	rbp,__ARRAY__+2
	mov	qword ptr [rdi],rbp
	mov	qword ptr 8[rdi],rax
	lea	rbp,dINT+2
	mov	qword ptr 16[rdi],rbp
	lea	rdi,24[rdi+rax*8]
	ret

_create_arrayR:
	lea	rbp,3[rax]
	sub	r15,rbp
	jge	no_collect_4580
	call	collect_0
no_collect_4580:
	mov	rcx,rdi
	mov	qword ptr [rdi],offset __ARRAY__+2
	mov	qword ptr 8[rdi],rax 
	mov	qword ptr 16[rdi],offset REAL+2
	lea	rdi,24[rdi+rax*8]
	ret

; rax : number of elements, rbx: element descriptor
; r10 : element size, r11 : element a size, rcx :a_element-> rcx : array

_create_r_array:
	mov	rbp,rax
	imul	rbp,r10
	add	rbp,3
	sub	r15,rbp
	jge	no_collect_4586
	call	collect_1
no_collect_4586:
	mov	qword ptr [rdi],offset __ARRAY__+2
	mov	rdx,rcx
	mov	qword ptr 8[rdi],rax
	mov	rcx,rdi 
	mov	qword ptr 16[rdi],rbx
	add	rdi,24

	test	r11,r11
	je	_create_r_array_0
	sub	r11,2
	jc	_create_r_array_1
	je	_create_r_array_2
	sub	r11,2
	jc	_create_r_array_3
	je	_create_r_array_4
	jmp	_create_r_array_5

_create_r_array_0:
	imul	r10,rax
	lea	rdi,[rdi+r10*8]
	ret

_create_r_array_1:
	shl	r10,3
	jmp	_st_fillr1_array
_fillr1_array:
	mov	qword ptr [rdi],rdx
	add	rdi,r10 
_st_fillr1_array:
	sub	rax,1
	jnc	_fillr1_array
	ret

_create_r_array_2:
	shl	r10,3
	jmp	_st_fillr2_array
_fillr2_array:
	mov	qword ptr [rdi],rdx
	mov	qword ptr 8[rdi],rdx
	add	rdi,r10 
_st_fillr2_array:
	sub	rax,1
	jnc	_fillr2_array
	ret

_create_r_array_3:
	shl	r10,3
	jmp	_st_fillr3_array
_fillr3_array:
	mov	qword ptr [rdi],rdx
	mov	qword ptr 8[rdi],rdx
	mov	qword ptr 16[rdi],rdx
	add	rdi,r10 
_st_fillr3_array:
	sub	rax,1
	jnc	_fillr3_array
	ret

_create_r_array_4:
	shl	r10,3
	jmp	_st_fillr4_array
_fillr4_array:
	mov	qword ptr [rdi],rdx
	mov	qword ptr 8[rdi],rdx
	mov	qword ptr 16[rdi],rdx
	mov	qword ptr 24[rdi],rdx
	add	rdi,r10 
_st_fillr4_array:
	sub	rax,1
	jnc	_fillr4_array
	ret

_create_r_array_5:
	sub	r10,4
	sub	r10,r11
	sub	r11,1
	shl	r10,3
	jmp	_st_fillr5_array

_fillr5_array:
	mov	qword ptr [rdi],rdx
	mov	qword ptr 8[rdi],rdx
	mov	qword ptr 16[rdi],rdx
	mov	qword ptr 24[rdi],rdx
	add	rdi,32

	mov	rbx,r11
_copy_elem_5_lp:
	mov	qword ptr [rdi],rdx
	add	rdi,8
	sub	rbx,1
	jnc	_copy_elem_5_lp

	add	rdi,r10 
_st_fillr5_array:
	sub	rax,1
	jnc	_fillr5_array
	
	ret

create_arrayB:
	mov	r10,rbx
	add	rbx,24+7
	shr	rbx,3
	sub	r15,rbx
	jge	no_collect_4575
	call	collect_0
no_collect_4575:
	mov	rbp,rax
	sub	rbx,3
	shl	rbp,8
	or	rax,rbp
	mov	rbp,rax
	shl	rbp,16
	or	rax,rbp
	mov	rbp,rax 
	shl	rbp,32
	or	rax,rbp
	mov	rcx,rdi
	mov	qword ptr [rdi],offset __ARRAY__+2
	mov	qword ptr 8[rdi],r10
	mov	qword ptr 16[rdi],offset BOOL+2
	add	rdi,24
	jmp	create_arrayBCI

create_arrayC:
	mov	r10,rbx
	add	rbx,16+7
	shr	rbx,3
	sub	r15,rbx
	jge	no_collect_4578
	call	collect_0
no_collect_4578:
	mov	rbp,rax
	sub	rbx,2
	shl	rbp,8
	or	rax,rbp
	mov	rbp,rax
	shl	rbp,16
	or	rax,rbp
	mov	rbp,rax
	shl	rbp,32
	or	rax,rbp
	mov	rcx,rdi 
	mov	qword ptr [rdi],offset __STRING__+2
	mov	qword ptr 8[rdi],r10
	add	rdi,16
	jmp	create_arrayBCI

create_arrayI:
	lea	rbp,3[rbx]
	sub	r15,rbp
	jge	no_collect_4577
	call	collect_0
no_collect_4577:
	mov	rcx,rdi 
	lea	rbp,__ARRAY__+2
	mov	qword ptr [rdi],rbp
	mov	qword ptr 8[rdi],rbx 
	lea	rbp,dINT+2
	mov	qword ptr 16[rdi],rbp
	add	rdi,24
create_arrayBCI:
	mov	rdx,rbx
	shr	rbx,1
	test	dl,1
	je	st_filli_array

	mov	qword ptr [rdi],rax 
	add	rdi,8
	jmp	st_filli_array

filli_array:
	mov	qword ptr [rdi],rax 
	mov	qword ptr 8[rdi],rax 
	add	rdi,16
st_filli_array:
	sub	rbx,1
	jnc	filli_array

	ret

create_arrayR:
	movsd	qword ptr (-8)[rsp],xmm0
	lea	rbp,3[rax]

	mov	rbx,qword ptr (-8)[rsp]

	sub	r15,rbp
	jge	no_collect_4579
	call	collect_0
no_collect_4579:
	mov	rcx,rdi 
	mov	qword ptr [rdi],offset __ARRAY__+2
	mov	qword ptr 8[rdi],rax
	mov	qword ptr 16[rdi],offset REAL+2
	add	rdi,24
	jmp	st_fillr_array
fillr_array:
	mov	qword ptr [rdi],rbx 
	add	rdi,8
st_fillr_array:
	sub	rax,1
	jnc	fillr_array

	ret

create_array:
	lea	rbp,3[rax]
	sub	r15,rbp
	jge	no_collect_4576
	call	collect_1
no_collect_4576:
	mov	rbx,rcx 
	mov	rcx,rdi
	mov	qword ptr [rdi],offset __ARRAY__+2
	mov	qword ptr 8[rdi],rax 
	mov	qword ptr 16[rdi],0
	add	rdi,24

	jmp	fillr1_array




; in rax: number of elements, rbx: element descriptor
; r10 : element size, r11 : element a size -> rcx : array

create_R_array:
	sub	r10,2
	jc	create_R_array_1
	je	create_R_array_2
	sub	r10,2
	jc	create_R_array_3
	je	create_R_array_4
	jmp	create_R_array_5

create_R_array_1:
	lea	rbp,3[rax]
	sub	r15,rbp
	jge	no_collect_4581
	call	collect_0
no_collect_4581:
	mov	rcx,rdi
	mov	qword ptr [rdi],offset __ARRAY__+2
	mov	qword ptr 8[rdi],rax 
	mov	qword ptr 16[rdi],rbx 
	add	rdi,24

	test	r11,r11
	je	r_array_1_b

	mov	rbx,qword ptr (-8)[rsi]
	jmp	fillr1_array

r_array_1_b:
	mov	rbx,qword ptr 8[rsp]

fillr1_array:
	mov	rdx,rax 
	shr	rax,1
	test	dl,1
	je	st_fillr1_array_1

	mov	qword ptr [rdi],rbx
	add	rdi,8
	jmp	st_fillr1_array_1

fillr1_array_lp:
	mov	qword ptr [rdi],rbx 
	mov	qword ptr 8[rdi],rbx 
	add	rdi,16
st_fillr1_array_1:
	sub	rax,1
	jnc	fillr1_array_lp

	ret

create_R_array_2:
	lea	rbp,3[rax*2]
	sub	r15,rbp
	jge	no_collect_4582
	call	collect_0
no_collect_4582:
	mov	rcx,rdi 
	mov	qword ptr [rdi],offset __ARRAY__+2
	mov	qword ptr 8[rdi],rax 
	mov	qword ptr 16[rdi],rbx 
	add	rdi,24

	sub	r11,1
	jc	r_array_2_bb
	je	r_array_2_ab
r_array_2_aa:
	mov	rbx,qword ptr (-8)[rsi]
	mov	rbp,qword ptr (-16)[rsi]
	jmp	st_fillr2_array
r_array_2_ab:
	mov	rbx,qword ptr (-8)[rsi]
	mov	rbp,qword ptr 8[rsp]
	jmp	st_fillr2_array
r_array_2_bb:
	mov	rbx,qword ptr 8[rsp]
	mov	rbp,qword ptr 16[rsp]
	jmp	st_fillr2_array

fillr2_array_1:
	mov	qword ptr [rdi],rbx 
	mov	qword ptr 8[rdi],rbp 
	add	rdi,16
st_fillr2_array:
	sub	rax,1
	jnc	fillr2_array_1

	ret

create_R_array_3:
	lea	rbp,3[rax+rax*2]
	sub	r15,rbp
	jge	no_collect_4583
	call	collect_0
no_collect_4583:
	mov	rcx,rdi
	mov	qword ptr [rdi],offset __ARRAY__+2
	mov	qword ptr 8[rdi],rax 
	mov	qword ptr 16[rdi],rbx 
	add	rdi,24

	pop	rdx 
	mov	r12,rsp 

	test	r11,r11 
	je	r_array_3
	
	lea	r13,0[r11*8]
	mov	rbp,rsi
	sub	rbp,r13

	sub	r11,1

copy_a_to_b_lp3:
	push	[rbp]
	add	rbp,8
	sub	r11,1
	jnc	copy_a_to_b_lp3

r_array_3:
	mov	rbx,qword ptr [rsp]
	mov	r13,qword ptr 8[rsp]
	mov	rbp,qword ptr 16[rsp]
	
	mov	rsp,r12
	push	rdx

	jmp	st_fillr3_array

fillr3_array_1:
	mov	qword ptr [rdi],rbx 
	mov	qword ptr 8[rdi],r13
	mov	qword ptr 16[rdi],rbp 
	add	rdi,24
st_fillr3_array:
	sub	rax,1
	jnc	fillr3_array_1

	ret

create_R_array_4:
	lea	rbp,3[rax+4]
	sub	r15,rbp
	jge	no_collect_4584
	call	collect_0
no_collect_4584:
	mov	rcx,rdi 
	mov	qword ptr [rdi],offset __ARRAY__+2
	mov	qword ptr 8[rdi],rax 
	mov	qword ptr 16[rdi],rbx 
	add	rdi,24

	pop	rdx 
	mov	r12,rsp 

	test	r11,r11 
	je	r_array_4

	lea	r13,0[r11*8]
	mov	rbp,rsi
	sub	rbp,r13
	sub	r11,1

copy_a_to_b_lp4:
	push	[rbp]
	add	rbp,8
	sub	r11,1
	jnc	copy_a_to_b_lp4

r_array_4:
	mov	rbx,qword ptr [rsp]
	mov	r13,qword ptr 8[rsp]
	mov	r14,qword ptr 16[rsp]
	mov	rbp,qword ptr 24[rsp]
	
	mov	rsp,r12
	push	rdx
	
	jmp	st_fillr4_array

fillr4_array:
	mov	qword ptr [rdi],rbx 
	mov	qword ptr 8[rdi],r13 
	mov	qword ptr 16[rdi],r14 
	mov	qword ptr 24[rdi],rbp 
	add	rdi,32
st_fillr4_array:
	sub	rax,1
	jnc	fillr4_array

	ret

create_R_array_5:
	lea	r12,4[r10]
	mov	rbp,rax
	imul	rbp,r12
	add	rbp,3
	sub	r15,rbp
	jge	no_collect_4585
	call	collect_0
no_collect_4585:
	mov	qword ptr [rdi],offset __ARRAY__+2
	mov	qword ptr 8[rdi],rax
	mov	qword ptr 16[rdi],rbx
	mov	rcx,rdi
	add	rdi,24

	pop	rdx
	mov	r12,rsp 
	
	test	r11,r11 
	je	r_array_5

	lea	r13,0[r11*8]
	mov	rbp,rsi
	sub	rbp,r13
	sub	r11,1

copy_a_to_b_lp5:
	push	[rbp]
	add	rbp,8
	sub	r11,1
	jnc	copy_a_to_b_lp5

r_array_5:
	mov	r13,qword ptr [rsp]
	mov	r14,qword ptr 8[rsp]
	mov	r8,qword ptr 16[rsp]
	mov	r9,qword ptr 24[rsp]
	add	rsp,32

	sub	r10,1
	jmp	st_fillr5_array

fillr5_array_1:
	mov	qword ptr [rdi],r13 
	mov	qword ptr 8[rdi],r14

	mov	r11,rsp
	mov	rbx,r10 

	mov	qword ptr 16[rdi],r8
	mov	qword ptr 24[rdi],r9
	add	rdi,32

copy_elem_lp5:
	mov	rbp,qword ptr [r11]
	add	r11,8
	mov	qword ptr [rdi],rbp 
	add	rdi,8
	sub	rbx,1
	jnc	copy_elem_lp5

st_fillr5_array:
	sub	rax,1
	jnc	fillr5_array_1

	mov	rsp,r12
	jmp	rdx 

 ifndef NEW_DESCRIPTORS
yet_args_needed:
; for more than 4 arguments
	mov	r10,[rdx]
	movzx	rax,word ptr (-2)[r10]
	add	rax,3
	sub	r15,rax
	jl	gc_1
gc_r_1:	sub	rax,3+1+4
	mov	rbx,8[rdx]
	add	r10,8
	mov	rdx,16[rdx]
	mov	rbp,rdi
	mov	r8,[rdx]
	mov	[rdi],r8 
	mov	r8,8[rdx]
	mov	8[rdi],r8 
	mov	r8,16[rdx]
	mov	16[rdi],r8 
	add	rdx,24
	add	rdi,24

cp_a:	mov	r8,[rdx]
	add	rdx,8
	mov	[rdi],r8 
	add	rdi,8
	sub	rax,1
	jge	cp_a

	mov	[rdi],rcx 
	mov	8[rdi],r10 
	lea	rcx,8[rdi]
	mov	16[rdi],rbx 
	mov	24[rdi],rbp 
	add	rdi,32
	ret

gc_1:
	call	collect_2
	jmp	gc_r_1

yet_args_needed_0:
	sub	r15,2
	jl	gc_20
gc_r_20:
	mov	8[rdi],rcx 
	mov	rax,[rdx]
	mov	rcx,rdi
	add	rax,8
	mov	[rdi],rax 
	add	rdi,16
	ret

gc_20:
	call	collect_2
	jmp	gc_r_20

yet_args_needed_1:
	sub	r15,3
	jl	gc_21
gc_r_21:
	mov	16[rdi],rcx 
	mov	rax,[rdx]
	mov	rcx,rdi
	add	rax,8
	mov	[rdi],rax 
	mov	rbx,8[rdx]
	mov	8[rdi],rbx 
	add	rdi,24
	ret

gc_21:
	call	collect_2
	jmp	gc_r_21

yet_args_needed_2:
	sub	r15,5
	jl	gc_22
gc_r_22:
	mov	rax,[rdx]
	mov	8[rdi],rcx 
	add	rax,8
	mov	rbp,8[rdx]
	mov	16[rdi],rax 
	lea	rcx,16[rdi]
	mov	24[rdi],rbp 
	mov	rbp,16[rdx]
	mov	[rdi],rbp 
	mov	32[rdi],rdi 
	add	rdi,40
	ret

gc_22:
	call	collect_2
	jmp	gc_r_22

yet_args_needed_3:
	sub	r15,6
	jl	gc_23
gc_r_23:
	mov	rax,[rdx]
	mov	16[rdi],rcx 
	add	rax,8
	mov	rbp,8[rdx]
	mov	24[rdi],rax 
	mov	rdx,16[rdx]
	mov	32[rdi],rbp 
	mov	rbp,[rdx]
	mov	40[rdi],rdi 
	mov	[rdi],rbp 
	mov	rbp,8[rdx]
	lea	rcx,24[rdi]
	mov	8[rdi],rbp 
	add	rdi,48
	ret

gc_23:
	call	collect_2
	jmp	gc_r_23

yet_args_needed_4:
	sub	r15,7
	jl	gc_24
gc_r_24:
	mov	rax,[rdx]
	mov	24[rdi],rcx 
	add	rax,8
	mov	rbp,8[rdx]
	mov	32[rdi],rax 
	mov	rdx,16[rdx]
	mov	40[rdi],rbp 
	mov	rbp,[rdx]
	mov	48[rdi],rdi 
	mov	[rdi],rbp 
	mov	rbp,8[rdx]
	lea	rcx,32[rdi]
	mov	8[rdi],rbp 
	mov	rbp,16[rdx ]
	mov	16[rdi],rbp 
	add	rdi,56
	ret

gc_24:
	call	collect_2
	jmp	gc_r_24
 endif

repl_args_b:
	test	rax,rax 
	jle	repl_args_b_1

	dec	rax 
	je	repl_args_b_4

	mov	rdx,16[rcx]
	sub	rbx,2
	jne	repl_args_b_2

	mov	[rsi],rdx 
	add	rsi,8
	jmp	repl_args_b_4

repl_args_b_2:
	lea	rdx,[rdx+rax*8]

repl_args_b_3:
	mov	rbp,(-8)[rdx]
	sub	rdx,8
	mov	[rsi],rbp 
	add	rsi,8
	dec	rax 
	jne	repl_args_b_3

repl_args_b_4:
	mov	rbp,8[rcx]
	mov	[rsi],rbp 
	add	rsi,8
repl_args_b_1:
	ret

push_arg_b:
	cmp	rbx,2
	jb	push_arg_b_1
	jne	push_arg_b_2
	cmp	rbx,rax 
	je	push_arg_b_1
push_arg_b_2:
	mov	rcx,16[rcx]
	sub	rbx,2
push_arg_b_1:
	mov	rcx,[rcx+rbx*8]
	ret

del_args:
	mov	rbx,[rcx]
	sub	rbx,rax 
	movsx	rax,word ptr (-2)[rbx]
	sub	rax,2
	jge	del_args_2

	mov	[rdx],rbx 
	mov	rbp,8[rcx]
	mov	8[rdx],rbp 
	mov	rbp,16[rcx]
	mov	16[rdx],rbp 
	ret

del_args_2:
	jne	del_args_3

	mov	[rdx],rbx 
	mov	rbp,8[rcx]
	mov	8[rdx],rbp 
	mov	rbp,16[rcx]
	mov	rbp,[rbp]
	mov	16[rdx],rbp 
	ret

del_args_3:
	sub	r15,rax
	jl	del_args_gc
del_args_r_gc:
	mov	[rdx],rbx 
	mov	16[rdx],rdi 
	mov	rbp,8[rcx]
	mov	rcx,16[rcx]
	mov	8[rdx],rbp 

del_args_copy_args:
	mov	rbp,[rcx]
	add	rcx,8
	mov	[rdi],rbp 
	add	rdi,8
	sub	rax,1
	jg	del_args_copy_args

	ret

del_args_gc:
	call	collect_2
	jmp	del_args_r_gc

 ifdef USE_LIBM
cos_real:
	mov	rbp,rsp
	and	rsp,-16
	mov	r13,rsi
	mov	r14,rdi
	call	cos
	mov	rsp,rbp
	mov	rsi,r13
	mov	rdi,r14
	ret

sin_real:
	mov	rbp,rsp
	and	rsp,-16
	mov	r13,rsi
	mov	r14,rdi
	call	sin
	mov	rsp,rbp
	mov	rsi,r13
	mov	rdi,r14
	ret

tan_real:
	mov	rbp,rsp
	and	rsp,-16
	mov	r13,rsi
	mov	r14,rdi
	call	tan
	mov	rsp,rbp
	mov	rsi,r13
	mov	rdi,r14
	ret

atan_real:
	mov	rbp,rsp
	and	rsp,-16
	mov	r13,rsi
	mov	r14,rdi
	call	atan
	mov	rsp,rbp
	mov	rsi,r13
	mov	rdi,r14
	ret

asin_real:
acos_real:
ln_real:
log10_real:
exp_real:
pow_real:
exp2_real_:
_c_log10:
_c_pow:
_c_entier:
	int 3
	ret
 endif
	
entier_real:
	cvttsd2si rax,xmm0
	ucomisd	xmm0,qword ptr real_0_0
	jb	entier_real_m
	ret

entier_real_m:
	movsd	qword ptr (-8)[rsp],xmm0
	mov	rcx,qword ptr (-8)[rsp]
	mov	rbx,rcx
	shr rcx,52
	cmp rcx,0bffh
	jb	entier_real_m_small
	cmp	rcx,0bffh+52
	jae	entier_real_m_large
	sub	rcx,0bffh-12
	shl	rbx,cl
	je	entier_m_exact
entier_real_m_small:
	sub	rax,1
entier_real_m_large:
entier_m_exact:
	ret

r_to_i_real:
	cvtsd2si rax,xmm0
	ret

	public	getheapend

getheapend:
	lea	rbx,[rdi+r15*8]
	mov	rax,heap_end_after_gc
	ret

_TEXT	ends

	include	areals.asm

 ifdef PROFILE
  ifdef TRACE
	include	atrace.asm
  else
	include	aprofile.asm
  endif
 endif

 ifdef NEW_DESCRIPTORS
	include	aap.asm
 endif

	end

