%if 0

Extensions for lDebug call macros

Copyright (C) 2008-2024 E. C. Masloch

Usage of the works is permitted provided that this
instrument is retained with the works, so that any entity
that uses the works is notified of this instrument.

DISCLAIMER: THE WORKS ARE WITHOUT WARRANTY.

%endif

%ifndef ELDCALL_MAC
%define ELDCALL_MAC 1

%include "lmacros3.mac"
%include "nasmhash.mac"
%include "elddata.mac"

%assign ELDLINKER 0

[section relocatedzero nobits vstart=0]
relocatedzero:
__SECT__

	numdef HOUDINI, 1
	numdef HOUDINI_CONDITIONAL, 1

%imacro houdini 0.nolist
%if _HOUDINI
 %if _HOUDINI_CONDITIONAL
reloc	testopt [ss:relocateddata], 100h
linkdatarelocation options7, -3
	jz %%skip
 %endif
reloc	testopt [ss:relocateddata], 100h
linkdatarelocation internalflags6, -3
	jz %%skip
	int3
%%skip:
%endif
%endmacro

%define ELDCALL_CODE_RELOCATIONS ""
%define ELDCALL_LINKER_CODE_RELOCATIONS ""
%define ELDCALL_CODE_RELOCATIONS_OPTIONAL ""
%define ELDCALL_LINKER_CODE_RELOCATIONS_OPTIONAL ""
%define ELDCALL_CODE_NAMES db ""
%define ELDCALL_CODE_DETECTION none, none
%assign ELDCALL_OPTIONAL_STATUS 0		; not any seen yet
%assign ELDCALL_PMREQUIRED_STATUS 0		; not any seen yet
%assign ELDCALL_NEXT_STATUS 0			; not any seen yet
%assign ELDCALL_NEXT_ENTRY -1

	%imacro extcall 1-3.nolist required, single
%ifidni _CURRENT_SECTION_TYPE, DATA
 %error "ELD call cannot be used in ELD data block"
%endif
%assign %%entry $ + _CURRENT_SECTION %+ FIXUP
%ifidni %2, required
 %assign %%optional 0
%elifidni %2, optional
 %assign %%optional 100h
 %if ELDCALL_OPTIONAL_STATUS == 0
  %assign ELDCALL_OPTIONAL_STATUS 1
 %elif ELDCALL_OPTIONAL_STATUS == 1
 %else
  %error Optional code link not allowed here
 %endif
%elifidni %2, PM required
 %assign %%optional 300h
 %assign ELDCALL_PMREQUIRED_STATUS 1
 %if ELDCALL_OPTIONAL_STATUS == 0
  %assign ELDCALL_OPTIONAL_STATUS 1
 %elif ELDCALL_OPTIONAL_STATUS == 1
 %else
  %error Optional code link not allowed here
 %endif
%else
 %fatal Unknown optional keyword
%endif
%ifidni %3, single
 %if ELDCALL_NEXT_STATUS == 1		; after next ?
  %error Unexpected single code link after next code link
 %elif ELDCALL_NEXT_STATUS == 2		; after last ?
  %assign ELDCALL_NEXT_STATUS 3		; note single with next/last present
 %endif
 %assign %%next 0
%elifidni %3, next
 %if ELDCALL_NEXT_STATUS == 0		; no next/last yet ?
  %assign ELDCALL_NEXT_STATUS 1		; in next
 %elif ELDCALL_NEXT_STATUS == 2		; after last ?
  %assign ELDCALL_NEXT_STATUS 1		; in next
 %elif ELDCALL_NEXT_STATUS == 3		; after single ?
  %assign ELDCALL_NEXT_STATUS 1		; in next
 %elif ELDCALL_NEXT_STATUS == 1		; repeated next ?
  %if ELDCALL_NEXT_ENTRY != %%entry
   %error Unexpected next code link
  %endif
 %else
  %error Next code link not allowed here
 %endif
 %ifn %%optional
  %error Next code link only valid as optional or PM required
 %endif
 %assign %%next 400h
 %assign ELDCALL_NEXT_ENTRY %%entry
%elifidni %3, last
 %if ELDCALL_NEXT_STATUS == 0		; no next/last yet ?
  %error Next last code link not allowed here
 %elif ELDCALL_NEXT_STATUS == 2		; after last ?
  %error Next last code link not allowed here
 %elif ELDCALL_NEXT_STATUS == 3		; after single ?
  %error Next last code link not allowed here
 %elif ELDCALL_NEXT_STATUS == 1		; after next ?
  %if ELDCALL_NEXT_ENTRY != %%entry
   %error Unexpected next code link
  %endif
  %assign ELDCALL_NEXT_STATUS 2		; note now after last
 %else
  %error Next code link not allowed here
 %endif
 %assign %%next 800h
 %assign ELDCALL_NEXT_ENTRY -1
 %assign ELDCALL_NEXT_SECTION -1
%else
 %fatal Unknown next keyword
%endif
%if %%next != 400h
%if 0
[warning -reloc-rel-word]
	call near relocatedzero
[warning +reloc-rel-word]
%else
	db 0E8h
reloc	dw relocatedzero
	eldstrictcheck
%endif
	jmp strict short %%skipparameter
	dw 0
%%skipparameter:
%endif
%if ELDLINKER
 %xdefine ELDCALL_LINKER_CODE_RELOCATIONS ELDCALL_LINKER_CODE_RELOCATIONS, %%entry, %%name
 %xdefine ELDCALL_LINKER_CODE_RELOCATIONS_OPTIONAL ELDCALL_LINKER_CODE_RELOCATIONS_OPTIONAL, 1 + %%optional + %%next, %%entry, %%name
%else
 %xdefine ELDCALL_CODE_RELOCATIONS ELDCALL_CODE_RELOCATIONS, %%entry, %%name
 %xdefine ELDCALL_CODE_RELOCATIONS_OPTIONAL ELDCALL_CODE_RELOCATIONS_OPTIONAL, 1 + %%optional + %%next, %%entry, %%name
%endif
%defstr %%string %1
%strlen %%length %%string
%if %%length > 64
	; Could be increased, but mustn't exceed 127 bytes
	;  because flag 80h is used to mark optional links
	;  that failed to be matched.
 %error Too long link name: %1
%endif
%define ELDCALL_CODE_CHECK %1
	linkcode_detect ELDCALL_CODE_DETECTION
%if ELDCALL_CODE_NEW
 %xdefine ELDCALL_CODE_DETECTION ELDCALL_CODE_DETECTION, %1, %%name
	hashdef HASH, %%string
%xdefine ELDCALL_CODE_NAMES \
	ELDCALL_CODE_NAMES, %%name:, dw _HASH, {counted %%string}
%else
 %%name equ ELDCALL_CODE_DUPLICATE
%endif
	%endmacro

	%imacro linkcode_detect 2-*.nolist
%assign ELDCALL_CODE_NEW 1
%rep (%0 - 2) / 2
 %rotate 2
 %ifidni %1, ELDCALL_CODE_CHECK
  %assign ELDCALL_CODE_NEW 0
  %xdefine ELDCALL_CODE_DUPLICATE %2
  %exitrep
 %endif
%endrep
	%endmacro


%define ELDCALL_CALLCALL_LIST none
%define ELDCALL_CALLCALL_PROCESSED_PRIOR ""

	%imacro extcallcall 1.nolist
	call %1
%xdefine ELDCALL_CALLCALL_LIST ELDCALL_CALLCALL_LIST, %1
	%endmacro

%assign ELDCALLCALL_DUMPED 0

	%imacro eldcall_dump_callcall 1-*.nolist
%xdefine ELDCALL_CALLCALL_PROCESSED ELDCALL_CALLCALL_PROCESSED_PRIOR
 %rep %0 - 1
  %rotate 1
  %define ELDCALL_CHECK %1
	eldcall_callcall_detect ELDCALL_CALLCALL_PROCESSED
  %if ELDCALL_NEW
   %xdefine ELDCALL_CALLCALL_PROCESSED ELDCALL_CALLCALL_PROCESSED, %1
	align 8, nop
%1:
	extcall %1
	retn
  %endif
 %endrep
%assign ELDCALLCALL_DUMPED 1
%define ELDCALL_CALLCALL_LIST none
	%endmacro

	%imacro eldcall_new_callcall 0.nolist
%if ELDCALLCALL_DUMPED
 %xdefine ELDCALL_CALLCALL_PROCESSED_PRIOR \
  ELDCALL_CALLCALL_PROCESSED_PRIOR, ELDCALL_CALLCALL_PROCESSED
 %assign ELDCALLCALL_DUMPED 0
 %define ELDCALL_CALLCALL_LIST none
%endif
	%endmacro

	%imacro eldcall_callcall_detect 1-*.nolist
%assign ELDCALL_NEW 1
%rep %0
 %ifidni %1, ELDCALL_CHECK
  %assign ELDCALL_NEW 0
  %exitrep
 %endif
 %rotate 1
%endrep
	%endmacro

	%imacro eldcall_dump_names 1-*.nolist
%rep %0
	%1
 %rotate 1
%endrep
	%endmacro

; eldcall_dump_callcall ELDCALL_CALLCALL_LIST
; if using optional code links:
;  dw ELDCALL_LINKER_CODE_RELOCATIONS_OPTIONAL, 0
;  dw ELDCALL_CODE_RELOCATIONS_OPTIONAL, 0
; if not using optional code links:
;  dw ELDCALL_LINKER_CODE_RELOCATIONS, 0, 0
;  dw ELDCALL_CODE_RELOCATIONS, 0, 0
; eldcall_dump_names ELDCALL_CODE_NAMES

%endif
