
; Public Domain

loop_free_data:
.outer:
	xor si, si
.inner:
	mov bx, [relocated(extdata_used)]
linkdatarelocation extdata_used
	add bx, [relocated(extdata)]
linkdatarelocation extdata
	cmp si, [relocated(extseg_used)]
linkdatarelocation extseg_used		; behind last instance ?
	jae .end			; yes -->
	cmp word [es:si + eldiStartCode], si
	jne .error			; start matches itself ?
	testopt [es:si + eldiFlags], eldifResident
	jnz .next			; is free ?
	mov dx, word [es:si + eldiEndData]
	mov ax, dx
	sub ax, word [es:si + eldiStartData]
					; = length of block
	jc .error			; block must not be negative size -->
					; ZR if empty range
	jnz @F				; not empty -->
					; special zeroing handling
	test dx, dx			; is it already zero ?
	jz .next			; yes -->
	jmp @FF				; zero it and re-loop outer -->
@@:
	cmp dx, bx			; end > last data ?
	ja .error			; yes, error -->
	jne .next			; end == last data ?
@@:					; yes, free it
	cmp ax, word [relocated(extdata_used)]
linkdatarelocation extdata_used
	ja .error
	sub word [relocated(extdata_used)], ax
linkdatarelocation extdata_used		; subtract size of block (or 0)
	xor ax, ax
	mov word [es:si + eldiStartData], ax
	mov word [es:si + eldiEndData], ax
					; reset the block data
	jmp .outer			; restart search for trailing data

.next:
	mov dx, si
	add dx, ELD_INSTANCE_size
	mov si, word [es:si + eldiEndCode]
	cmp si, dx
	jb .error
	jmp .inner

.end:


loop_free_code:
.outer:
	mov dx, -1			; remember no candidate
	xor si, si			; -> start of ext seg
.inner:
	cmp si, [relocated(extseg_used)]
linkdatarelocation extseg_used		; behind last instance ?
	jae .end_inner			; yes -->
	cmp word [es:si + eldiStartCode], si
	jne .error			; start matches itself ?
	testopt [es:si + eldiFlags], eldifResident
	jnz .next_not_free		; is free ?
	mov dx, si			; -> candidate free block
	cmp byte [es:si + eldiStartData], 0
	jne .next_data_used		; is free ?
	cmp byte [es:si + eldiEndData], 0
	jne .next_data_used		; is free ?
	xor cx, cx			; remember candidate has no data
	jmp .next

.next_data_used:
	mov cx, 1			; remember candidate has data
	jmp .next

.next_not_free:
	mov dx, -1			; remember no candidate (used block)
.next:
	mov ax, si
	add ax, ELD_INSTANCE_size
	mov si, word [es:si + eldiEndCode]
	cmp si, ax
	jb .error
	jmp .inner

.end_inner:
	cmp dx, -1			; last ELD instance is free ?
	je .end				; no -->
	xor bx, bx			; if to not keep ELD instance, = 0
	jcxz .free			; no data ? then use bx = 0 -->
	mov bl, 32			; need to keep ELD instance, = 32
.free:
	mov si, dx			; -> instance to free/resize
	mov ax, word [es:si + eldiEndCode]
	cmp ax, [relocated(extseg_used)] ; validity check
linkdatarelocation extseg_used
	jne .error
	mov dx, word [es:si + eldiStartCode]
	sub ax, dx			; size of entire instance
	add dx, bx			; start of instance + how much to keep
	mov word [es:si + eldiEndCode], dx
					; enter into instance's end
	sub ax, bx			; size to discard
	sub word [relocated(extseg_used)], ax ; do discard it
linkdatarelocation extseg_used
	test bx, bx			; only resized ?
	jz .outer			; no, go back try to free new last block

.end:
