
#define COMPACT_MARK_WITH_STACK

/ mark used nodes and pointers in argument parts and link backward pointers

	movl	heap_size_33,d0
	shl	$5,d0
	movl	d0,heap_size_32_33

#ifdef COMPACT_MARK_WITH_STACK
	lea	-8000(sp),a3
#endif
	movl	caf_list,d0
#ifdef COMPACT_MARK_WITH_STACK
	movl	a3,end_stack
#endif
	test	d0,d0
	je	end_mark_cafs

mark_cafs_lp:
	pushl	-4(d0)
#ifdef COMPACT_MARK_WITH_STACK
	lea	4(d0),a3
	movl	(d0),d0
	lea	(a3,d0,4),a0
#else
	lea	4(d0),a2
	movl	(d0),d0
	lea	(a2,d0,4),a0
#endif
	movl	a0,end_vector
	
#ifdef COMPACT_MARK_WITH_STACK
	call	rmark_stack_nodes
#else
	call	mark_stack_nodes
#endif
	
	popl	d0
	test	d0,d0
	jne	mark_cafs_lp

end_mark_cafs:
#ifdef COMPACT_MARK_WITH_STACK
	movl	stack_p,a3
#else
	movl	stack_p,a2
#endif

	movl	stack_top,a0
	movl	a0,end_vector
#ifdef COMPACT_MARK_WITH_STACK
	call	rmark_stack_nodes
#else
	call	mark_stack_nodes
#endif

#ifdef MEASURE_GC
	call	add_mark_compact_garbage_collect_time
#endif
	
	jmp	compact_heap

#ifdef COMPACT_MARK_WITH_STACK
# include "icompact_rmark.s"
# include "icompact_rmarkr.s"
#else
# include "icompact_mark.s"
#endif

/ compact the heap

compact_heap:

#ifdef FINALIZERS
	movl	$finalizer_list,a0
	movl	$free_finalizer_list,a1

	movl	(a0),a2
determine_free_finalizers_after_compact1:
	cmpl	$__Nil-4,a2
	je	end_finalizers_after_compact1

	movl	neg_heap_p3,d0
	addl	a2,d0
	movl	d0,d1
	andl	$31*4,d0
	shrl	$7,d1
	movl	bit_set_table(d0),a3
	testl	(a4,d1,4),a3
	je	finalizer_not_used_after_compact1

	movl	(a2),d0
	movl	a2,a3
	jmp	finalizer_find_descriptor

finalizer_find_descriptor_lp:
	andl	$-4,d0
	movl	d0,a3
	movl	(d0),d0
finalizer_find_descriptor:
	test	$1,d0
	jne	finalizer_find_descriptor_lp

	movl	$e____system__kFinalizerGCTemp+2,(a3)

	cmpl	a0,a2
	ja	finalizer_no_reverse

	movl	(a2),d0
	leal	1(a0),a3
	movl	a3,(a2)
	movl	d0,(a0)

finalizer_no_reverse:
	lea	4(a2),a0
	movl	4(a2),a2
	jmp	determine_free_finalizers_after_compact1

finalizer_not_used_after_compact1:
	movl	$e____system__kFinalizerGCTemp+2,(a2)

	movl	a2,(a1)
	lea	4(a2),a1

	movl	4(a2),a2
	movl	a2,(a0)

	jmp	determine_free_finalizers_after_compact1

end_finalizers_after_compact1:
	movl	a2,(a1)	

	movl	finalizer_list,a0
	cmpl	$__Nil-4,a0
	je	finalizer_list_empty
	testl	$3,a0
	jne	finalizer_list_already_reversed
	movl	(a0),d0
	movl	$finalizer_list+1,(a0)
	movl	d0,finalizer_list
finalizer_list_already_reversed:
finalizer_list_empty:

# ifdef COMPACT_MARK_WITH_STACK
	movl	$free_finalizer_list,a3
	cmpl	$__Nil-4,(a3)
# else
	movl	$free_finalizer_list,a2
	cmpl	$__Nil-4,(a2)
# endif
	je	free_finalizer_list_empty

	movl	$free_finalizer_list+4,end_vector
# ifdef COMPACT_MARK_WITH_STACK
	call	rmark_stack_nodes
# else
	call	mark_stack_nodes
# endif
free_finalizer_list_empty:
#endif

	movl	heap_size_33,d0
	movl	d0,d1
	shl	$5,d1
#ifdef SHARE_CHAR_INT
	addl	heap_p3,d1
#endif
	movl	d1,end_heap_p3

	addl	$3,d0
	shr	$2,d0
	
	movl	heap_vector,a0

	lea	4(a0),d1
	negl	d1
	movl	d1,neg_heap_vector_plus_4

	movl	heap_p3,a4
	xorl	a3,a3
	jmp	skip_zeros

/ d0,a0,a2: free
find_non_zero_long:
	movl	vector_counter,d0
	movl	vector_p,a0
skip_zeros:
	subl	$1,d0
	jc	end_copy
	movl	(a0),a3
	addl	$4,a0
	testl	a3,a3
	je	skip_zeros
/ a2: free
end_skip_zeros:
	movl	neg_heap_vector_plus_4,a2
	movl	d0,vector_counter

	addl	a0,a2
	movl	a0,vector_p

	shl	$5,a2
	addl	heap_p3,a2

#ifdef NO_BIT_INSTRUCTIONS
bsf_and_copy_nodes:
	movl	a3,d0
	movl	a3,a0
	andl	$0xff,d0
	jne	found_bit1
	andl	$0xff00,a0
	jne	found_bit2
	movl	a3,d0
	movl	a3,a0
	andl	$0xff0000,d0
	jne	found_bit3
	shrl	$24,a0
	movzbl	first_one_bit_table(,a0,1),d1
	addl	$24,d1
	jmp	copy_nodes

found_bit3:
	shrl	$16,d0
	movzbl	first_one_bit_table(,d0,1),d1
	addl	$16,d1
	jmp	copy_nodes

found_bit2:
	shrl	$8,a0
	movzbl	first_one_bit_table(,a0,1),d1
	addl	$8,d1
	jmp	copy_nodes

found_bit1:	
	movzbl	first_one_bit_table(,d0,1),d1
#else
	bsf	a3,d1
#endif

copy_nodes:
	movl	(a2,d1,4),d0
#ifdef NO_BIT_INSTRUCTIONS
	andl	bit_clear_table(,d1,4),a3
#else
	btr	d1,a3
#endif
	leal	4(a2,d1,4),a0
	dec	d0

	test	$2,d0
	je	begin_update_list_2

	movl	-10(d0),d1
	subl	$2,d0

	test	$1,d1
	je	end_list_2
find_descriptor_2:
	andl	$-4,d1
	movl	(d1),d1
	test	$1,d1
	jne	find_descriptor_2

end_list_2:
	movl	d1,a1
	movzwl	-2(d1),d1
	cmpl	$256,d1
	jb	no_record_arguments

	movzwl	-2+2(a1),a1
	subl	$2,a1
	jae	copy_record_arguments_aa

	subl	$256+3,d1

copy_record_arguments_all_b:
	pushl	d1
	movl	heap_vector,d1

update_up_list_1r:
	movl	d0,a1
	addl	neg_heap_p3,d0

#ifdef NO_BIT_INSTRUCTIONS
	push	a0
	movl	d0,a0

	shrl	$7,d0
	andl	$31*4,a0

	movl	bit_set_table(,a0,1),a0
	movl	(d1,d0,4),d0

	andl	a0,d0

	pop	a0
	je	copy_argument_part_1r
#else
	shrl	$2,d0
	bt	d0,(d1)
	jnc	copy_argument_part_1r
#endif
	movl	(a1),d0
	movl	a4,(a1)
	subl	$3,d0
	jmp	update_up_list_1r

copy_argument_part_1r:
	movl	(a1),d0
	movl	a4,(a1)
	movl	d0,(a4)
	addl	$4,a4

	movl	neg_heap_p3,d0
	addl	a0,d0
	shr	$2,d0
	
	mov	d0,d1
	andl	$31,d1
	cmp	$1,d1
	jae	bit_in_this_word

	movl	vector_counter,d0
	movl	vector_p,a1
	dec	d0
	movl	(a1),a3
	addl	$4,a1

	movl	neg_heap_vector_plus_4,a2
	addl	a1,a2
	shl	$5,a2
	addl	heap_p3,a2

	movl	a1,vector_p
	movl	d0,vector_counter

bit_in_this_word:
#ifdef NO_BIT_INSTRUCTIONS
	andl	bit_clear_table(,d1,4),a3
#else
	btr	d1,a3
#endif
	popl	d1

copy_b_record_argument_part_arguments:
	movl	(a0),d0
	addl	$4,a0
	movl	d0,(a4)
	addl	$4,a4
	subl	$1,d1
	jnc	copy_b_record_argument_part_arguments

#ifdef NO_BIT_INSTRUCTIONS
	test	a3,a3
	jne	bsf_and_copy_nodes
#else
	bsf	a3,d1
	jne	copy_nodes
#endif
	jmp	find_non_zero_long

copy_record_arguments_aa:
	subl	$256+2,d1
	subl	a1,d1
	
	pushl	d1
	pushl	a1

update_up_list_2r:
	movl	d0,a1
	movl	(a1),d0
	movl	$3,d1
	andl	d0,d1
	subl	$3,d1
	jne	copy_argument_part_2r

	movl	a4,(a1)
	subl	$3,d0
	jmp	update_up_list_2r

copy_argument_part_2r:
	movl	a4,(a1)
	cmpl	a0,d0
	jb	copy_record_argument_2
#ifdef SHARE_CHAR_INT
	cmpl	end_heap_p3,d0
	jae	copy_record_argument_2
#endif
	movl	d0,a1
	movl	(a1),d0
	lea	1(a4),d1
	movl	d1,(a1)
copy_record_argument_2:
	movl	d0,(a4)
	addl	$4,a4

	popl	d1
	subl	$1,d1
	jc	no_pointers_in_record

copy_record_pointers:
	movl	(a0),a1
	addl	$4,a0
	cmpl	a0,a1
	jb	copy_record_pointers_2
#ifdef SHARE_CHAR_INT
	cmpl	end_heap_p3,a1
	jae	copy_record_pointers_2
#endif
	movl	(a1),d0
	inc	a4
	movl	a4,(a1)
	dec	a4
	movl	d0,a1
copy_record_pointers_2:
	movl	a1,(a4)
	addl	$4,a4
	subl	$1,d1
	jnc	copy_record_pointers

no_pointers_in_record:
	popl	d1
	
	subl	$1,d1
	jc	no_non_pointers_in_record

copy_non_pointers_in_record:
	movl	(a0),d0
	addl	$4,a0
	movl	d0,(a4)
	addl	$4,a4
	subl	$1,d1
	jnc	copy_non_pointers_in_record

no_non_pointers_in_record:
#ifdef NO_BIT_INSTRUCTIONS
	test	a3,a3
	jne	bsf_and_copy_nodes
#else
	bsf	a3,d1
	jne	copy_nodes
#endif
	jmp	find_non_zero_long

no_record_arguments:
	subl	$3,d1
update_up_list_2:
	movl	d0,a1
	movl	(d0),d0
	inc	d0
	movl	a4,(a1)
	testb	$3,d0b
	jne	copy_argument_part_2

	subl	$4,d0
	jmp	update_up_list_2

copy_argument_part_2:
	dec	d0
	cmpl	a0,d0
	jc	copy_arguments_1
#ifdef SHARE_CHAR_INT
	cmpl	end_heap_p3,d0
	jnc	copy_arguments_1
#endif
	movl	d0,a1
	movl	(d0),d0
	inc	a4
	movl	a4,(a1)
	dec	a4
copy_arguments_1:
	movl	d0,(a4)
	addl	$4,a4

copy_argument_part_arguments:
	movl	(a0),a1
	addl	$4,a0
	cmpl	a0,a1
	jc	copy_arguments_2
#ifdef SHARE_CHAR_INT
	cmpl	end_heap_p3,a1
	jnc	copy_arguments_2
#endif
	movl	(a1),d0
	inc	a4
	movl	a4,(a1)
	dec	a4
	movl	d0,a1
copy_arguments_2:
	movl	a1,(a4)
	addl	$4,a4
	subl	$1,d1
	jnc	copy_argument_part_arguments

#ifdef NO_BIT_INSTRUCTIONS
	test	a3,a3
	jne	bsf_and_copy_nodes
#else
	bsf	a3,d1
	jne	copy_nodes
#endif
	jmp	find_non_zero_long

update_list_2_:
	dec	d0
update_list_2:
	movl	a4,(a1)
begin_update_list_2:
	movl	d0,a1
	movl	(d0),d0
update_list__2:
	test	$1,d0
	jz	end_update_list_2
	test	$2,d0
	jz	update_list_2_
	lea	-3(d0),a1
	movl	-3(d0),d0
	jmp	update_list__2

end_update_list_2:
	movl	a4,(a1)

	movl	d0,(a4)
	addl	$4,a4

	testb	$2,d0b
	je	move_lazy_node

	movzwl	-2(d0),d1
	testl	d1,d1
	je	move_hnf_0

	cmp	$256,d1
	jae	move_record

	subl	$2,d1
	jc	move_hnf_1
	je	move_hnf_2

move_hnf_3:
	movl	(a0),a1
	addl	$4,a0
	cmpl	a0,a1
	jc	move_hnf_3_1
#ifdef SHARE_CHAR_INT
	cmpl	end_heap_p3,a1
	jnc	move_hnf_3_1
#endif
	lea	1(a4),d0
	movl	(a1),d1
	movl	d0,(a1)
	movl	d1,a1
move_hnf_3_1:
	movl	a1,(a4)
	
	movl	(a0),a1
	addl	$4,a0
	cmpl	a0,a1
	jc	move_hnf_3_2
#ifdef SHARE_CHAR_INT
	cmpl	end_heap_p3,a1
	jnc	move_hnf_3_2
#endif
	lea	4+2+1(a4),d0
	movl	(a1),d1
	movl	d0,(a1)
	movl	d1,a1
move_hnf_3_2:
	movl	a1,4(a4)
	addl	$8,a4

#ifdef NO_BIT_INSTRUCTIONS
	test	a3,a3
	jne	bsf_and_copy_nodes
#else
	bsf	a3,d1
	jne	copy_nodes
#endif
	jmp	find_non_zero_long

move_hnf_2:
	movl	(a0),a1
	addl	$4,a0
	cmpl	a0,a1
	jc	move_hnf_2_1
#ifdef SHARE_CHAR_INT
	cmpl	end_heap_p3,a1
	jnc	move_hnf_2_1
#endif
	lea	1(a4),d0
	movl	(a1),d1
	movl	d0,(a1)
	movl	d1,a1
move_hnf_2_1:
	movl	a1,(a4)
	
	movl	(a0),a1
	addl	$4,a0
	cmpl	a0,a1
	jc	move_hnf_2_2
#ifdef SHARE_CHAR_INT
	cmpl	end_heap_p3,a1
	jnc	move_hnf_2_2
#endif
	lea	4+1(a4),d0
	movl	(a1),d1
	movl	d0,(a1)
	movl	d1,a1
move_hnf_2_2:
	movl	a1,4(a4)
	addl	$8,a4

#ifdef NO_BIT_INSTRUCTIONS
	test	a3,a3
	jne	bsf_and_copy_nodes
#else
	bsf	a3,d1
	jne	copy_nodes
#endif
	jmp	find_non_zero_long

move_hnf_1:
	movl	(a0),a1
	addl	$4,a0
	cmpl	a0,a1
	jc	move_hnf_1_
#ifdef SHARE_CHAR_INT
	cmpl	end_heap_p3,a1
	jnc	move_hnf_1_
#endif
	lea	1(a4),d0
	movl	(a1),d1
	movl	d0,(a1)
	movl	d1,a1
move_hnf_1_:
	movl	a1,(a4)
	addl	$4,a4

#ifdef NO_BIT_INSTRUCTIONS
	test	a3,a3
	jne	bsf_and_copy_nodes
#else
	bsf	a3,d1
	jne	copy_nodes
#endif
	jmp	find_non_zero_long

move_record:
	subl	$258,d1
	jb	move_record_1
	je	move_record_2

move_record_3:
	movzwl	-2+2(d0),d1
	subl	$1,d1
	ja	move_hnf_3

	movl	(a0),a1
	lea	4(a0),a0
	jb	move_record_3_1b

move_record_3_1a:
	cmpl	a0,a1
	jb	move_record_3_1b
#ifdef SHARE_CHAR_INT
	cmpl	end_heap_p3,a1
	jae	move_record_3_1b
#endif
	lea	1(a4),d0
	movl	(a1),d1
	movl	d0,(a1)
	movl	d1,a1
move_record_3_1b:
	movl	a1,(a4)
	addl	$4,a4

	movl	(a0),a1
	addl	$4,a0
	cmpl	a0,a1
	jb	move_record_3_2
#ifdef SHARE_CHAR_INT
	cmpl	end_heap_p3,a1
	jae	move_record_3_2
#endif
	movl	neg_heap_p3,d0
#ifdef NO_BIT_INSTRUCTIONS
	pushl	a2
#endif
	addl	a1,d0

#ifdef NO_BIT_INSTRUCTIONS
	movl	heap_vector,d1
	addl	$4,d0
	movl	d0,a2
	andl	$31*4,a2
	shrl	$7,d0
	movl	bit_set_table(a2),a2
	testl	(d1,d0,4),a2
	je	not_linked_record_argument_part_3_b
#else
	shr	$2,d0
	inc	d0

	movl	heap_vector,d1
	bts	d0,(d1)
	jnc	not_linked_record_argument_part_3_b
#endif

	movl	neg_heap_p3,d0
	addl	a4,d0

#ifdef NO_BIT_INSTRUCTIONS
	movl	d0,a2
	andl	$31*4,a2
	shrl	$7,d0
	movl	bit_set_table(a2),a2
	orl	a2,(d1,d0,4)
	popl	a2
#else
	shr	$2,d0
	bts	d0,(d1)
#endif
	jmp	linked_record_argument_part_3_b

not_linked_record_argument_part_3_b:
#ifdef NO_BIT_INSTRUCTIONS
	orl	a2,(d1,d0,4)
#endif
	movl	neg_heap_p3,d0
	addl	a4,d0

#ifdef NO_BIT_INSTRUCTIONS
	movl	d0,a2
	andl	$31*4,a2
	shrl	$7,d0
	movl	bit_clear_table(a2),a2
	andl	a2,(d1,d0,4)
	popl	a2
#else
	shr	$2,d0
	btr	d0,(d1)
#endif

linked_record_argument_part_3_b:
	movl	(a1),d1
	lea	2+1(a4),d0
	movl	d0,(a1)
	movl	d1,a1
move_record_3_2:
	movl	a1,(a4)
	addl	$4,a4

	movl	neg_heap_p3,d1
	addl	a0,d1
	shr	$2,d1
	dec	d1
	andl	$31,d1
	cmp	$2,d1
	jb	bit_in_next_word
	
#ifdef NO_BIT_INSTRUCTIONS
	andl	bit_clear_table(,d1,4),a3
#else
	btr	d1,a3
#endif

#ifdef NO_BIT_INSTRUCTIONS
	test	a3,a3
	jne	bsf_and_copy_nodes
#else
	bsf	a3,d1
	jne	copy_nodes
#endif
	jmp	find_non_zero_long
	
bit_in_next_word:
	movl	vector_counter,d0
	movl	vector_p,a0
	dec	d0
	movl	(a0),a3
	addl	$4,a0

#ifdef NO_BIT_INSTRUCTIONS
	andl	bit_clear_table(,d1,4),a3
#else
	btr	d1,a3
#endif
	testl	a3,a3
	je	skip_zeros
	jmp	end_skip_zeros

move_record_2:
	cmpw	$1,-2+2(d0)
	ja	move_hnf_2
	jb	move_real_or_file

move_record_2_ab:
	movl	(a0),a1
	addl	$4,a0
	cmpl	a0,a1
	jb	move_record_2_1
#ifdef SHARE_CHAR_INT
	cmpl	end_heap_p3,a1
	jae	move_record_2_1
#endif
	lea	1(a4),d0
	movl	(a1),d1
	movl	d0,(a1)
	movl	d1,a1
move_record_2_1:
	movl	a1,(a4)
	movl	(a0),d1
	addl	$4,a0
	movl	d1,4(a4)
	addl	$8,a4

#ifdef NO_BIT_INSTRUCTIONS
	test	a3,a3
	jne	bsf_and_copy_nodes
#else
	bsf	a3,d1
	jne	copy_nodes
#endif
	jmp	find_non_zero_long

move_record_1:
	movzwl	-2+2(d0),d1
	test	d1,d1
	jne	move_hnf_1
	jmp	move_int_bool_or_char

move_real_or_file:
	movl	(a0),d0
	addl	$4,a0
	movl	d0,(a4)
	addl	$4,a4
move_int_bool_or_char:
	movl	(a0),d0
	addl	$4,a0
	movl	d0,(a4)
	addl	$4,a4
copy_normal_hnf_0:
#ifdef NO_BIT_INSTRUCTIONS
	test	a3,a3
	jne	bsf_and_copy_nodes
#else
	bsf	a3,d1
	jne	copy_nodes
#endif
	jmp	find_non_zero_long

move_hnf_0:
	cmpl	$INT+2,d0
	jb	move_real_file_string_or_array
	cmpl	$CHAR+2,d0
	jbe	move_int_bool_or_char
#ifdef DLL
move_normal_hnf_0:
#endif

#ifdef NO_BIT_INSTRUCTIONS
	test	a3,a3
	jne	bsf_and_copy_nodes
#else
	bsf	a3,d1
	jne	copy_nodes
#endif
	jmp	find_non_zero_long

move_real_file_string_or_array:
	cmpl	$__STRING__+2,d0
	ja	move_real_or_file
	jne	move_array

	movl	(a0),d0
	addl	$3,d0
	shr	$2,d0

cp_s_arg_lp3:
	movl	(a0),d1
	addl	$4,a0
	movl	d1,(a4)
	addl	$4,a4
	subl	$1,d0
	jnc	cp_s_arg_lp3

#ifdef NO_BIT_INSTRUCTIONS
	test	a3,a3
	jne	bsf_and_copy_nodes
#else
	bsf	a3,d1
	jne	copy_nodes
#endif
	jmp	find_non_zero_long

move_array:
#ifdef DLL
	cmpl	$__ARRAY__+2,d0
	jb	move_normal_hnf_0
#endif
#ifdef NO_BIT_INSTRUCTIONS
	test	a3,a3
	jne	bsf_and_end_array_bit
#else
	bsf	a3,d1
	jne	end_array_bit
#endif
	pushl	a0

	movl	vector_counter,d0
	movl	vector_p,a0

skip_zeros_a:
	subl	$1,d0
	movl	(a0),a3
	addl	$4,a0
	testl	a3,a3
	je	skip_zeros_a

	movl	neg_heap_vector_plus_4,a2
	addl	a0,a2
	movl	d0,vector_counter

	shl	$5,a2
	movl	a0,vector_p

	addl	heap_p3,a2
	popl	a0

#ifdef NO_BIT_INSTRUCTIONS
bsf_and_end_array_bit:
	movl	a3,d0
	movl	a3,a1
	andl	$0xff,d0
	jne	a_found_bit1
	andl	$0xff00,a1
	jne	a_found_bit2
	movl	a3,d0
	movl	a3,a1
	andl	$0xff0000,d0
	jne	a_found_bit3
	shrl	$24,a1
	movzbl	first_one_bit_table(,a1,1),d1
	addl	$24,d1
	jmp	end_array_bit
a_found_bit3:
	shrl	$16,d0
	movzbl	first_one_bit_table(,d0,1),d1
	addl	$16,d1
	jmp	end_array_bit
a_found_bit2:
	shrl	$8,a1
	movzbl	first_one_bit_table(,a1,1),d1
	addl	$8,d1
	jmp	end_array_bit
a_found_bit1:
	movzbl	first_one_bit_table(,d0,1),d1

#else
	bsf	a3,d1
#endif

end_array_bit:
#ifdef NO_BIT_INSTRUCTIONS
	andl	bit_clear_table(,d1,4),a3
#else
	btr	d1,a3
#endif
	leal	(a2,d1,4),d1

	cmpl	d1,a0
	jne	move_a_array

move_b_array:
	movl	(a0),a1
	movl	a1,(a4)
	movl	4(a0),d1
	addl	$4,a0
	movzwl	-2(d1),d0
	addl	$4,a4
	test	d0,d0
	je	move_strict_basic_array

	subl	$256,d0
	imull	d0,a1
	movl	a1,d0
	jmp	cp_s_arg_lp3

move_strict_basic_array:
	movl	a1,d0
	cmpl	$INT+2,d1
	je	cp_s_arg_lp3

	cmpl	$BOOL+2,d1
	je	move_bool_array

	addl	d0,d0
	jmp	cp_s_arg_lp3

move_bool_array:
	addl	$3,d0
	shr	$2,d0
	jmp	cp_s_arg_lp3

move_a_array:
	movl	d1,a1
	subl	a0,d1
	shr	$2,d1

	pushl	a3

	subl	$1,d1
	jb	end_array

	movl	(a0),a3
	movl	-4(a1),d0
	movl	a3,-4(a1)
	movl	d0,(a4)
	movl	(a1),d0
	movl	4(a0),a3
	addl	$8,a0
	movl	a3,(a1)
	movl	d0,4(a4)
	addl	$8,a4
	test	d0,d0
	je	st_move_array_lp

	movzwl	-2+2(d0),a3
	movzwl	-2(d0),d0
	subl	$256,d0
	cmpl	a3,d0
	je	st_move_array_lp

move_array_ab:
	pushl	a0

	movl	-8(a4),a1
	movl	a3,d1
	imull	d0,a1
	shl	$2,a1

	subl	d1,d0
	addl	a0,a1
	call	reorder

	popl	a0
	subl	$1,d1
	subl	$1,d0

	pushl	d1
	pushl	d0
	pushl	-8(a4)
	jmp	st_move_array_lp_ab

move_array_ab_lp1:
	movl	8(sp),d0
move_array_ab_a_elements:
	movl	(a0),d1
	addl	$4,a0
	cmpl	a0,d1
	jb	move_array_element_ab
#ifdef SHARE_CHAR_INT
	cmpl	end_heap_p3,d1
	jnc	move_array_element_ab
#endif
	movl	d1,a1
	movl	(a1),d1
	inc	a4
	movl	a4,(a1)
	dec	a4
move_array_element_ab:
	movl	d1,(a4)
	addl	$4,a4
	subl	$1,d0
	jnc	move_array_ab_a_elements

	movl	4(sp),d0
move_array_ab_b_elements:
	movl	(a0),d1
	addl	$4,a0
	movl	d1,(a4)
	addl	$4,a4
	subl	$1,d0
	jnc	move_array_ab_b_elements

st_move_array_lp_ab:
	subl	$1,(sp)
	jnc	move_array_ab_lp1

	addl	$12,sp
	jmp	end_array	

move_array_lp1:
	movl	(a0),d0
	addl	$4,a0
	addl	$4,a4
	cmpl	a0,d0
	jb	move_array_element
#ifdef SHARE_CHAR_INT
	cmpl	end_heap_p3,d0
	jnc	move_array_element
#endif
	movl	(d0),a3
	movl	d0,a1
	movl	a3,-4(a4)
	leal	-4+1(a4),d0
	movl	d0,(a1)

	subl	$1,d1
	jnc	move_array_lp1

	jmp	end_array

move_array_element:
	movl	d0,-4(a4)
st_move_array_lp:
	subl	$1,d1
	jnc	move_array_lp1

end_array:
	popl	a3

#ifdef NO_BIT_INSTRUCTIONS
	test	a3,a3
	jne	bsf_and_copy_nodes
#else
	bsf	a3,d1
	jne	copy_nodes
#endif
	jmp	find_non_zero_long

move_lazy_node:
	movl	d0,a1
	movl	-4(a1),d1
	test	d1,d1
	je	move_lazy_node_0

	subl	$1,d1
	jle	move_lazy_node_1

	cmpl	$256,d1
	jge	move_closure_with_unboxed_arguments

move_lazy_node_arguments:
	movl	(a0),a1
	addl	$4,a0
	cmpl	a0,a1
	jc	move_lazy_node_arguments_
#ifdef SHARE_CHAR_INT
	cmpl	end_heap_p3,a1
	jnc	move_lazy_node_arguments_
#endif
	movl	(a1),d0
	movl	d0,(a4)
	lea	1(a4),d0
	addl	$4,a4
	movl	d0,(a1)
	subl	$1,d1
	jnc	move_lazy_node_arguments

#ifdef NO_BIT_INSTRUCTIONS
	test	a3,a3
	jne	bsf_and_copy_nodes
#else
	bsf	a3,d1
	jne	copy_nodes
#endif
	jmp	find_non_zero_long

move_lazy_node_arguments_:
	movl	a1,(a4)
	addl	$4,a4
	subl	$1,d1
	jnc	move_lazy_node_arguments
	
#ifdef NO_BIT_INSTRUCTIONS
	test	a3,a3
	jne	bsf_and_copy_nodes
#else
	bsf	a3,d1
	jne	copy_nodes
#endif
	jmp	find_non_zero_long

move_lazy_node_1:
	movl	(a0),a1
	addl	$4,a0
	cmpl	a0,a1
	jc	move_lazy_node_1_
#ifdef SHARE_CHAR_INT
	cmpl	end_heap_p3,a1
	jnc	move_lazy_node_1_
#endif
	lea	1(a4),d0
	movl	(a1),d1
	movl	d0,(a1)
	movl	d1,a1
move_lazy_node_1_:
	movl	a1,(a4)
	addl	$8,a4

#ifdef NO_BIT_INSTRUCTIONS
	test	a3,a3
	jne	bsf_and_copy_nodes
#else
	bsf	a3,d1
	jne	copy_nodes
#endif
	jmp	find_non_zero_long

move_lazy_node_0:
	addl	$8,a4

#ifdef NO_BIT_INSTRUCTIONS
	test	a3,a3
	jne	bsf_and_copy_nodes
#else
	bsf	a3,d1
	jne	copy_nodes
#endif
	jmp	find_non_zero_long

move_closure_with_unboxed_arguments:
	je	move_closure_with_unboxed_arguments_1
	addl	$1,d1
	movl	d1,d0
	andl	$255,d1
	shrl	$8,d0
	subl	d0,d1
	je	move_non_pointers_of_closure

	pushl	d0

move_closure_with_unboxed_arguments_lp:
	movl	(a0),a1
	addl	$4,a0
	cmpl	a0,a1
	jc	move_closure_with_unboxed_arguments_
#ifdef SHARE_CHAR_INT
	cmpl	end_heap_p3,a1
	jnc	move_closure_with_unboxed_arguments_
#endif
	movl	(a1),d0
	movl	d0,(a4)
	lea	1(a4),d0
	addl	$4,a4
	movl	d0,(a1)
	subl	$1,d1
	jne	move_closure_with_unboxed_arguments_lp

	popl	d0
	jmp	move_non_pointers_of_closure

move_closure_with_unboxed_arguments_:
	movl	a1,(a4)
	addl	$4,a4
	subl	$1,d1
	jne	move_closure_with_unboxed_arguments_lp

	popl	d0

move_non_pointers_of_closure:
	movl	(a0),d1
	addl	$4,a0
	movl	d1,(a4)
	addl	$4,a4
	subl	$1,d0
	jne	move_non_pointers_of_closure

#ifdef NO_BIT_INSTRUCTIONS
	test	a3,a3
	jne	bsf_and_copy_nodes
#else
	bsf	a3,d1
	jne	copy_nodes
#endif
	jmp	find_non_zero_long

move_closure_with_unboxed_arguments_1:
	movl	(a0),d0
	movl	d0,(a4)
	addl	$8,a4
# ifdef NO_BIT_INSTRUCTIONS
	test	a3,a3
	jne	bsf_and_copy_nodes
# else
	bsf	a3,d1
	jne	copy_nodes
# endif
	jmp	find_non_zero_long	

end_copy:

#ifdef FINALIZERS
	movl	finalizer_list,a0

restore_finalizer_descriptors:
	cmpl	$__Nil-4,a0
	je	end_restore_finalizer_descriptors

	movl	$e____system__kFinalizer+2,(a0)
	movl	4(a0),a0
	jmp	restore_finalizer_descriptors

end_restore_finalizer_descriptors:
#endif
