
; Public Domain

%include "lmacros3.mac"
%include "eld.mac"
%include "eldcall.mac"
%include "elddata.mac"

	cpu 8086

	addsection RELOCATEDDATA, nobits vstart=_ELD_RELOC_VSTART
relocateddata:

	addsection HEADER, start=0

		; ELD executable header
	istruc ELD_HEADER
at eldhSignature,	db "ELD1"
			db 0,0,0
			db 26
at eldhCodeOffset,	dd CODEOFFSET
at eldhCodeImageLength,	dw code_size
at eldhCodeAllocLength,	dw 0
at eldhDataOffset,	dd DATAOFFSET
at eldhDataImageLength,	dw data_size
at eldhDataAllocLength,	dw total_data_size - data_size
at eldhCodeEntrypoint,	dw linker - code
at eldhReserved
	iend


	align 16, db 0

CODEOFFSET equ $ - $$
	addsection CODE, follows=HEADER vstart=_ELD_CODE_VSTART
%define CODEFIXUP - code + 0
code:
		; ELD instance header
	istruc ELD_INSTANCE
at eldiStartCode
at eldiEndCode
at eldiStartData
at eldiEndData
at eldiIdentifier,	fill 8, 32, db "ELDTEST"
	iend

start:
	push ss
	pop es
	lodsb
	extcallcall getexpression
	extcallcall chkeol
	push bx
	push dx

	call get_es_ext
	setopt [es:code + eldiFlags], eldifResident
internalcoderelocation -3		; mark block as resident

	push word [relocateddata]
linkdatarelocation ext_inject_handler
	push word [relocateddata]
linkdatarelocation savesp
	push word [relocateddata]
linkdatarelocation throwsp
	mov word [eld_sp], sp
internaldatarelocation
	mov word [relocateddata], sp
linkdatarelocation savesp
	mov word [relocateddata], sp
linkdatarelocation throwsp

	mov word [relocateddata], .inject
linkdatarelocation ext_inject_handler, -4
internalcoderelocation
	extcallcall cmd3

.inject:
	mov di, relocateddata + 1
linkdatarelocation line_in
	push di
	mov si, inject
internaldatarelocation
	mov cx, inject_size
	rep movsb
	pop si
	inc si
	extcall skipwhite

	mov word [relocateddata], .return
linkdatarelocation ext_inject_handler, -4
internalcoderelocation
	extcall cmd3_injected

.return:
	mov sp, word [eld_sp]
internaldatarelocation
	pop word [relocateddata]
linkdatarelocation throwsp
	pop word [relocateddata]
linkdatarelocation savesp
	pop word [relocateddata]
linkdatarelocation ext_inject_handler
	call get_es_ext
	clropt [es:code + eldiFlags], eldifResident
internalcoderelocation -3		; mark block as free
	 push ss
	 pop es
	pop ax
	pop dx
	mov di, relocateddata
linkdatarelocation line_out
	xchg dx, ax
	extcallcall hexword
	xchg dx, ax
	mov byte [di], '_'
	inc di
	extcallcall hexword
	extcallcall putsline_crlf

end:
	call get_es_ext
	mov ax, word [cs:code + eldiEndData]
internalcoderelocation			; ax -> our data end
	mov bx, 32			; prepare to keep 32 Bytes
	push ax
	sub ax, [relocateddata]		; ax = index into data behind our end
linkdatarelocation extdata
	cmp word [relocateddata], ax	; are we last ?
linkdatarelocation extdata_used
	pop ax
	jne @F				; no, keep >= 32 Bytes of instance -->
	xor bx, bx			; remember to free instance completely
	sub ax, word [cs:code + eldiStartData]
internalcoderelocation			; get our length
	sub word [relocateddata], ax	; subtract from use counter
linkdatarelocation extdata_used
	xor ax, ax			; zero out our data references
					;  (in case we keep the instance)
	mov word [es:code + eldiStartData], ax
internalcoderelocation
	mov word [es:code + eldiEndData], ax
internalcoderelocation
@@:

	mov dx, word [cs:code + eldiStartCode]
internalcoderelocation
	add dx, bx			; -> behind to keep (= start if no data)
	mov ax, word [cs:code + eldiEndCode]
internalcoderelocation
	cmp word [relocateddata], ax	; at end ?
linkdatarelocation extseg_used
	jne @F				; no, keep block as is -->
	mov word [es:code + eldiEndCode], dx
internalcoderelocation			; modify end to -> behind to keep
	sub ax, word [cs:code + eldiStartCode]
internalcoderelocation			; = original length
	sub ax, bx			; = how much to free
	sub word [relocateddata], ax	; subtract from use counter
linkdatarelocation extseg_used
@@:

	extcallcall cmd3


get_es_ext:
	mov es, word [relocateddata]
linkdatarelocation extdssel
	extcall ispm
	jz @F
	mov es, word [relocateddata]
linkdatarelocation extseg
@@:
	retn


DATAOFFSET equ CODEOFFSET + code_size
	addsection DATA, follows=CODE vstart=_ELD_DATA_VSTART
%define DATAFIXUP - datastart + 0
datastart:

inject:
	counted "rvm"
	db 13
	endarea inject


uinit_data:

	align 16, db 0
data_size equ $ - datastart

	absolute uinit_data
	alignb 2
eld_sp:
	resw 1

	alignb 16
uinit_data_end:

total_data_size equ $ - datastart
%assign _DATA_SIZE total_data_size

	usesection CODE

%include "eldlink.asm"

	align 16
code_size equ $ - code
