
%if 0

lDebug S commands (search, sleep)

Copyright (C) 1995-2003 Paul Vojta
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


	usesection lDEBUG_CODE

..@sss_access_start:

		; S command - search for a string of bytes.
sss:
 %ifn ELD
	dec si
	dec si			; -> at 'S'
	mov dx, msg.sleep
	call isstring?		; check for "SLEEP"
	je sleepcmd
	inc si			; skip 'S'
	lodsb			; load next
 %endif

%if _SREVERSE
reloc	clropt [relocated(internalflags3)], dif3_sss_is_reverse
linkdatarelocation internalflags3, -3
%endif

reloc	mov bx, word [relocated(reg_ds)]	; get search range
linkdatarelocation reg_ds
	_386_PM_o32		; xor ecx, ecx
	xor cx, cx
	extcallcall getrangeX	; get address range into BX:(E)DX..BX:(E)CX
	extcallcall skipcomm0
	_386_PM_o32		; push edx
	push dx
	_386_PM_o32		; push ecx
	push cx
	push bx

reloc	mov byte [relocated(sss_silent_count_used)], 0
linkdatarelocation sss_silent_count_used, -3
%if ELD
reloc	mov byte [tagbuffer], 0	; clear caps and wild flags for scasb
internaldatarelocation -3
reloc	mov byte [sss_range_used], 0
internaldatarelocation -3
reloc2	mov word [sss_repe_cmpsb_for_range], do_repe_cmpsb
internaldatarelocation -4
internalcoderelocation
%endif

%if _SREVERSE
reloc	mov dx, msg.reverse
internaldatarelocation
	dec si
	extcallcall isstring?
	jne @F

reloc	setopt [relocated(internalflags3)], dif3_sss_is_reverse
linkdatarelocation internalflags3, -3
	extcallcall skipcomma
	dec si
@@:
%else
	dec si
%endif

reloc	mov dx, msg.silent
internaldatarelocation
	extcallcall isstring?
	jne @F
	extcallcall skipequals
	extcallcall getdword
reloc	mov word [relocated(sss_silent_count)], dx
linkdatarelocation sss_silent_count
reloc	mov word [relocated(sss_silent_count) + 2], bx
linkdatarelocation sss_silent_count
reloc	not byte [relocated(sss_silent_count_used)]
linkdatarelocation sss_silent_count_used
	extcallcall skipcomm0
	dec si
@@:

reloc	mov dx, msg.range
internaldatarelocation
	extcallcall isstring?
	lodsb
	jne .notrange

%if ELD
	extcallcall skipcomm0
	dec si
reloc	mov dx, msg.caps
internaldatarelocation
	extcallcall isstring?
	lodsb
	jne .notrangecaps
	extcallcall skipcomm0

reloc	or byte [tagbuffer], 2	; set caps flag for scasb
internaldatarelocation -3
reloc2	mov word [sss_repe_cmpsb_for_range], do_repe_cmpsb_caps
internaldatarelocation -4
internalcoderelocation
.notrangecaps:
%endif

reloc	mov bx, word [relocated(reg_ds)]	; get search range
linkdatarelocation reg_ds
	xor cx, cx
	extcallcall getrangeX	; try to get second range
	push si
	extcallcall chkeol	; and insure end-of-line
				; successful if it returned
	_386_PM_o32		; mov esi, edx
	mov si, dx		; bx:esi-> source string
	_386_PM_o32		; sub ecx, edx
	sub cx, dx		; ecx = count - 1
%if ELD
reloc	not byte [sss_range_used]
internaldatarelocation
%endif
	jmp short .setesedi

.notrange:
%if ELD
	call getstr_sss		; get string of bytes
%else
	nearcall getstr
%endif
	push si
reloc	sub di, strict word relocated(line_out)
				; di = number of bytes to look for
linkdatarelocation line_out
	jz error
	mov cx, di
	dec di			;     minus one
reloc	mov si, relocated(line_out)
linkdatarelocation line_out
	push di

%if _SWHILEBUFFER && ! ELD
 %if _WHILEBUFFSIZE < 264
  %error WHILE buffer not large enough for search pattern
 %endif
	testopt [internalflags], tt_while
	jnz .use_auxbuff
	mov di, while_buffer
	push di
	rep movsb
	pop si
_386_PM	movzx esi, si
	jmp .use_whilebuffer
%endif

%if 1 && ELD
	cmp cx, patternbuffer.size
	ja error
reloc	mov di, patternbuffer
internaldatarelocation
	push di
	rep movsb
	pop si
_386_PM	movzx esi, si
	; jmp .use_whilebuffer
%else
.use_auxbuff:
	extcallcall guard_auxbuff
reloc	mov es, word [relocated(auxbuff_segorsel)]
linkdatarelocation auxbuff_segorsel
	xor di, di
	rep movsb		; move to auxbuff
	_386_PM_o32	; xor esi, esi
	xor si, si
%endif
.use_whilebuffer:
	mov bx, es		; bx:esi -> auxbuff
	pop cx
_386_PM	movzx ecx, cx		; ecx = count - 1
.setesedi:
%if _SCOUNT || ELD
	push bx
	extcall count_store, optional
	pop bx
%endif
	push ss
	pop es
reloc	mov di, relocated(search_results)
linkdatarelocation search_results
	push cx
%if ELD
	houdini
reloc	mov cx, relocated(search_results_amount)
linkdatarelocation search_results_amount
reloc	mov ax, relocated(0)
linkdatarelocation build_option_PM
	test ax, ax
	jz @F
	mov ax, cx
@@:
	add cx, cx		; times 2
	add cx, ax		; PM: times 3, else: times 2
%elif _PM
	mov cx, (6 * search_results_amount) >> 1
%else
	mov cx, (4 * search_results_amount) >> 1
%endif
	xor ax, ax
reloc	mov word [relocated(sscounter)], ax
linkdatarelocation sscounter
reloc	mov word [relocated(sscounter) + 2], ax
linkdatarelocation sscounter
	rep stosw
	pop cx

 %if ELD
reloc	test byte [tagbuffer + 0], 3
internaldatarelocation -3
	jz .simple
.difficult:
reloc	mov ax, difficult_scasb
internalcoderelocation
reloc	mov di, difficult_repne_scasb
internalcoderelocation
	jmp @F

.simple:
reloc	mov ax, do_scasb
internalcoderelocation
reloc	mov di, do_repne_scasb
internalcoderelocation
@@:
reloc	mov word [sss_scasb], ax
internaldatarelocation
reloc	mov word [sss_repne_scasb], di
internaldatarelocation

reloc	rol byte [sss_range_used], 1
internaldatarelocation
	jc .simple_match
	xor ax, ax
reloc	mov di, tagbuffer
internaldatarelocation
	push cx
	mov cx, words(tagbuffer.size)
	repe scasw
	pop cx
	je .simple_match

.difficult_match:
reloc2	mov word [sss_repe_cmpsb], difficult_repe_cmpsb
internaldatarelocation -4
internalcoderelocation
	jmp @F

.simple_match:
reloc	mov ax, word [sss_repe_cmpsb_for_range]
internaldatarelocation
reloc	mov word [sss_repe_cmpsb], ax
internaldatarelocation
@@:
 %endif
	extcall prephack	; set up for the interrupt vector hack
	extcallcall dohack
	mov ds, bx
	pop di			; original si
	pop es
 %if ELD
reloc	mov ax, relocated(0)
linkdatarelocation build_option_PM
	test ax, ax
	jz @F
 %endif
	_386_PM_jmpn .386init	; 386 -->
@@:
.init:
 %if ELD
	_386_PM_o32		; pop ebx
	pop bx
	_386_PM_o32		; pop edx
	pop dx
 %else
	pop bx
	pop dx
 %endif
.init_popped:
	sub bx, dx		; bx = number of bytes in search range minus one
	sub bx, cx		; = number of possible positions of string minus 1
	jb .error_unhack_di
	mov di, dx
	mov dx, cx
	mov cx, bx

		; ds:si-> search string, length (dx+1)
		; es:di-> data to search in, (cx+1) bytes
%if _SREVERSE
reloc	testopt [ss:relocated(internalflags3)], dif3_sss_is_reverse
linkdatarelocation internalflags3, -3
	jnz .reverse
%endif
.loop:
	or al, 1		; NZ (iff cx==0, repne scasb doesn't change ZF)
	push si
	lodsb			; first character in al
 %if ELD
_386_PM	clc
reloc	call near [ss:sss_repne_scasb]
internaldatarelocation
 %else
	repne scasb		; look for first byte
 %endif
	je .foundbyte
 %if ELD
_386_PM	clc
reloc	call near [ss:sss_scasb]
internaldatarelocation
 %else
	scasb			; count in cx was cnt-1
 %endif
	jne .done
.found_last_byte:
	call .handle_found_byte
	jmp .done

.foundbyte:
	call .handle_found_byte
	pop si
	jmp .loop		; cx = 0 if one to search,
				;  cx = 1 if two to search, etc

%if _SREVERSE
.reverse:
	add di, cx		; -> last position to check
.reverseloop:
	or al, 1		; NZ (iff cx==0, repne scasb doesn't change ZF)
	push si
	lodsb			; first character in al
	std			; no AMD erratum workaround needed
 %if ELD
_386_PM	clc
reloc	call near [ss:sss_repne_scasb]
internaldatarelocation
 %else
	repne scasb		; look for first byte
 %endif
	je .reversefoundbyte
 %if ELD
_386_PM	clc
reloc	call near [ss:sss_scasb]
internaldatarelocation
 %else
	scasb			; count in cx was cnt-1
 %endif
	jne .done
.reversefound_last_byte:
	cld
	add di, 2
	cmp al, al		; ZR for case if dx = 0
	call .handle_found_byte
	sub di, 2
	jmp .done

.reversefoundbyte:
	cld
	add di, 2
	cmp al, al		; ZR for case if dx = 0
	call .handle_found_byte
	sub di, 2
	pop si
	jmp .reverseloop	; cx = 0 if one to search,
				;  cx = 1 if two to search, etc
%endif

.done:
	pop si			; discard
.commondone:
	cld
	push ss
	pop ds
	extcallcall unhack
reloc	mov di, relocated(line_out)
linkdatarelocation line_out

reloc	mov ax, word [relocated(sscounter) + 2]
linkdatarelocation sscounter
	test ax, ax
	jz .nohighcounter
	extcallcall hexword
.nohighcounter:

reloc	mov ax, word [relocated(sscounter)]
linkdatarelocation sscounter
	extcallcall hexword
	extcallcall putsline
reloc	mov dx, msg.matches
internaldatarelocation
%if ELD
	extcallcall putsz
	retn
%else
	jmp putsz
%endif


		; INP:	ZR
.handle_found_byte:
	push cx
	push di
	mov cx, dx
 %if ELD
_386_PM	clc
reloc	call near [ss:sss_repe_cmpsb]
internaldatarelocation
 %else
	repe cmpsb		; compare string behind first byte
 %endif
		; If we're searching for a single-byte value then
		;  dx is equal to zero here. In that case cx gets
		;  the value zero and then repe cmpsb does not
		;  alter ZF, meaning it will stay ZR (as noted for
		;  the comment INP section).
	pop di
	je .display		; if equal
.next:
	pop cx
	retn

.display:
	mov bx, es
	push di
	push ds
	push es
	 push ss
	 pop ds
	extcallcall unhack	; undo the interrupt vector hack and restore es
	push di
reloc	cmp word [relocated(sscounter) + 2], strict byte 0
linkdatarelocation sscounter, -3
	jne @F
reloc	mov di, word [relocated(sscounter)]
linkdatarelocation sscounter
reloc	cmp di, strict word relocated(search_results_amount)
linkdatarelocation search_results_amount
	jae @F
%if ELD && _PM
reloc	mov ax, relocated(0)
linkdatarelocation build_option_PM
	add di, di		; times 2
	test ax, ax		; PM build ?
	jz .idxnotpm		; no --> (ax == zero)
	mov ax, di		; = times 2
.idxnotpm:
	add di, di		; times 4
	add di, ax		; _PM: times 4 + times 2 = times 6, else: times 4
%elif _PM
	add di, di		; times 2
	mov ax, di		; = times 2
	add di, di		; times 4
	add di, ax		; times 4 + times 2 = times 6
%else
	add di, di		; times 2
	add di, di		; times 4
%endif
reloc	add di, strict word relocated(search_results)
linkdatarelocation search_results

	pop ax
	push ax
	dec ax
	stosw
%if _PM
 %if ELD
reloc	mov ax, relocated(0)
linkdatarelocation build_option_PM
	test ax, ax
	jz .storenotpm
 %endif
	xor ax, ax
	stosw
.storenotpm:
%endif
	mov ax, bx
	stosw

@@:
reloc	add word [relocated(sscounter)], strict byte 1
linkdatarelocation sscounter, -3
reloc	adc word [relocated(sscounter) + 2], strict byte 0
linkdatarelocation sscounter, -3
reloc	rol byte [relocated(sss_silent_count_used)], 1
linkdatarelocation sss_silent_count_used
	jnc @F
reloc	mov ax, word [relocated(sss_silent_count)]
linkdatarelocation sss_silent_count
reloc	or ax, word [relocated(sss_silent_count) + 2]
linkdatarelocation sss_silent_count
	pop ax
	push dx
	jz .nodisplay
	pop dx
	push ax
reloc	sub word [relocated(sss_silent_count)], strict byte 1
linkdatarelocation sss_silent_count, -3
reloc	sbb word [relocated(sss_silent_count) + 2], strict byte 0
linkdatarelocation sss_silent_count, -3
@@:
	mov ax, bx
reloc	mov di, relocated(line_out)
linkdatarelocation line_out
	extcallcall hexword	; 4 (segment)
	mov al, ':'
	stosb			; +1=5
	pop ax
	dec ax
	extcallcall hexword
%if _SDUMP
reloc	testopt [relocated(options)], ss_no_dump
linkdatarelocation options, -3
	jnz .no_dump
	stc
	adc ax, dx		; -> behind result
	jbe .noresult		; end of segment
	mov si, ax		; cannot be zero

%if _SDUMPDISPLACEMENT
_386_PM	movzx edx, dx
	call sss_calculate_displacement

	mov bx, di
	add bx, ax
	add bx, ax
	add bx, ax
%else
	mov ax, 32<<8|32
	stosw
	lea bx, [di+3*16]
%endif

	mov cx, si		; cannot be zero
	neg cx			; cannot be zero
%if _SDUMPDISPLACEMENT
	cmp cx, ax
%else
	cmp cx, byte 16
%endif
	jbe .cxdone
%if _SDUMPDISPLACEMENT
	mov cx, ax
%else
	mov cx, 16
%endif
.cxdone:			; cx cannot be zero
	 pop ds
	 push ds		; restore search's segment
%if _SDUMPDISPLACEMENT
	push ax
%endif
	push cx
.disploop:
	lodsb
	extcallcall dd_store
	mov al, 32
	stosb
	loop .disploop
	pop cx
%if _SDUMPDISPLACEMENT
	pop ax
%endif
	 push ss
	 pop ds
	neg cx
%if _SDUMPDISPLACEMENT
	add cx, ax
%else
	add cx, byte 16
%endif
	jz .noblanks
.loopblanks:
	mov ax, 32<<8|32
	stosw
	stosb
	loop .loopblanks
.noblanks:
	mov byte [di-(1+(8*3))], '-'
	mov di, bx
.noresult:
.no_dump:
%endif	; _SDUMP
	push dx
	extcallcall putsline_crlf
.nodisplay:
	extcallcall dohack
	pop dx
	pop es
	pop ds
	pop di
	jmp .next


.error_unhack_di:
	push ss
	pop ds
	extcallcall unhack
	mov si, di
	jmp error


%if _PM
	subcpu 386

.386init:
	pop ebx
	pop edx
	extcallcall ispm
	jnz .init_popped	; not PM -->
	sub ebx, edx		; ebx = number of bytes in search range minus one
	sub ebx, ecx		; = number of possible positions of string minus 1
	jb .error_unhack_di
	mov edi, edx
	mov edx, ecx
	mov ecx, ebx

		; ds:esi-> search string, length (edx+1)
		; es:edi-> data to search in, (ecx+1) bytes
		; Although 386+ RM still uses 64 KiB segments, it allows
		; us to use the 32-bit addressing variant of the string
		; instructions as long as we never access any byte above
		; the 64 KiB limit. (Even if the index register contains
		; 00010000h after an instruction executed.)
%if _SREVERSE
reloc	testopt [ss:relocated(internalflags3)], dif3_sss_is_reverse
linkdatarelocation internalflags3, -3
	jnz .386reverse
%endif
.386loop:
	or al, 1		; NZ (iff cx==0, repne scasb doesn't change ZF)
	push esi
	a32 lodsb		; first character in al
 %if ELD
_386_PM	stc
reloc	call near [ss:sss_repne_scasb]
internaldatarelocation
 %else
	a32 repne scasb		; look for first byte
 %endif
	je .386foundbyte
 %if ELD
_386_PM	stc
reloc	call near [ss:sss_scasb]
internaldatarelocation
 %else
	a32 scasb		; count in ecx was cnt-1
 %endif
	jne .386done
.386found_last_byte:
	call .386handle_found_byte
	jmp .386done

.386foundbyte:
	call .386handle_found_byte
	pop esi
	jmp .386loop		; ecx = 0 if one to search,
				;  ecx = 1 if two to search, etc

%if _SREVERSE
.386reverse:
	add edi, ecx		; -> last position to check
.386reverseloop:
	or al, 1		; NZ (iff cx==0, repne scasb doesn't change ZF)
	push esi
	a32 lodsb		; first character in al
	std			; no AMD erratum workaround needed
 %if ELD
_386_PM	stc
reloc	call near [ss:sss_repne_scasb]
internaldatarelocation
 %else
	a32 repne scasb		; look for first byte
 %endif
	je .386reversefoundbyte
 %if ELD
_386_PM	stc
reloc	call near [ss:sss_scasb]
internaldatarelocation
 %else
	a32 scasb		; count in ecx was cnt-1
 %endif
	jne .386done
.386reversefound_last_byte:
	cld
	add edi, 2
	cmp al, al		; ZR for case if edx = 0
	call .386handle_found_byte
	sub edi, 2
	jmp .386done

.386reversefoundbyte:
	cld
	add edi, 2
	cmp al, al		; ZR for case if edx = 0
	call .386handle_found_byte
	sub edi, 2
	pop esi
	jmp .386reverseloop	; ecx = 0 if one to search,
				;  ecx = 1 if two to search, etc
%endif

.386done:
	pop esi			; discard
	jmp .commondone


		; INP:	ZR
.386handle_found_byte:
	push ecx
	push edi
	mov ecx, edx
 %if ELD
_386_PM	stc
reloc	call near [ss:sss_repe_cmpsb]
internaldatarelocation
 %else
	a32 repe cmpsb		; compare string behind first byte
 %endif
		; If we're searching for a single-byte value then
		;  edx is equal to zero here. In that case ecx gets
		;  the value zero and then a32 repe cmpsb does not
		;  alter ZF, meaning it will stay ZR (as noted for
		;  the comment INP section).
	pop edi
	je .386display		; if equal
.386next:
	pop ecx
	retn

.386display:
	mov bx, es
	push edi
	push ds
	push es
	 push ss
	 pop ds
	extcallcall unhack	; undo the interrupt vector hack and restore es
	push edi
reloc	mov edi, dword [relocated(sscounter)]
linkdatarelocation sscounter
reloc	cmp edi, strict dword relocated(search_results_amount)
linkdatarelocation search_results_amount, -4	; low word of the dword !
	jae @F
	add di, di		; * 2
	mov ax, di
	add di, di		; * 4
	add di, ax		; * 4 + * 2 = * 6
reloc	add di, relocated(search_results)
linkdatarelocation search_results
	pop eax
	push eax
	dec eax
	stosd
	mov ax, bx
	stosw

@@:
reloc	inc dword [relocated(sscounter)]
linkdatarelocation sscounter
reloc	rol byte [relocated(sss_silent_count_used)], 1
linkdatarelocation sss_silent_count_used
	jnc @F
reloc	cmp dword [relocated(sss_silent_count)], strict byte 0
linkdatarelocation sss_silent_count, -3
	pop eax
	push dx
	je .386nodisplay
	pop dx
	push eax
reloc	sub word [relocated(sss_silent_count)], strict byte 1
linkdatarelocation sss_silent_count, -3
reloc	sbb word [relocated(sss_silent_count) + 2], strict byte 0
linkdatarelocation sss_silent_count, -3
@@:
	mov ax, bx
reloc	mov di, relocated(line_out)
linkdatarelocation line_out
	extcallcall hexword	; 4 (segment)
	mov al, ':'
	stosb			; +1=5
	pop eax
	dec eax
	extcallcall test_high_limit
	jz .noa32
	extcall hexword_high, PM required
.noa32:
	extcallcall hexword
%if _SDUMP
reloc	testopt [relocated(options)], ss_no_dump
linkdatarelocation options, -3
	jnz .386_no_dump
	stc
	adc eax, edx		; -> behind result
	jbe .386noresult	; end of segment
	mov esi, eax
		; esi is at most 10000h in a 64 KiB segment.
		;  The jcxz at .386cxdone will branch if si = 0,
		;  which is only possible if esi = 10000h.
		; esi is never zero here.

%if _SDUMPDISPLACEMENT
	call sss_calculate_displacement
%else
	mov ax, 32<<8|32
	stosw
%endif

	pop bx			; get search selector
	push bx
	extcallcall test_high_limit
	jnz .386_high_limit

.386_low_limit:
	mov cx, si		; 0 if at end of 64 KiB limit, else nonzero
	neg cx			; 0 if at end of 64 KiB limit, else nonzero
%if _SDUMPDISPLACEMENT
	cmp cx, ax
%else
	cmp cx, byte 16		; below or equal maximum dump length ?
%endif
	jmp @F

.386_high_limit:
	mov ecx, esi		; cannot be 0
	neg ecx			; cannot be 0
%if _SDUMPDISPLACEMENT
	movzx eax, ax
	cmp ecx, eax
%else
	cmp ecx, byte 16	; below or equal maximum dump length ?
%endif
@@:
	jbe .386cxdone		; (e)cx <= maximum dump length, use cx
%if _SDUMPDISPLACEMENT
	mov cx, ax
%else
	mov cx, 16		; reset cx (ecxh is not used)
%endif
.386cxdone:
	jcxz .386noresult	; if at end of 64 KiB limit -->
		; (The displacement is already written here. Oh well.)
%if _SDUMPDISPLACEMENT
	mov bx, di
	add bx, ax
	add bx, ax
	add bx, ax
%else
	lea bx, [di+3*16]
%endif
	 pop ds
	 push ds		; restore search's segment
%if _SDUMPDISPLACEMENT
	push ax
%endif
	push cx
.386disploop:
	a32 lodsb
	extcallcall dd_store
	mov al, 32
	stosb
	loop .386disploop
	pop cx
%if _SDUMPDISPLACEMENT
	pop ax
%endif
	 push ss
	 pop ds
	neg cx
%if _SDUMPDISPLACEMENT
	add cx, ax
%else
	add cx, byte 16
%endif
	jz .386noblanks
.386loopblanks:
	mov ax, 32<<8|32
	stosw
	stosb
	loop .386loopblanks
.386noblanks:
	mov byte [di-(1+(8*3))], '-'
	mov di, bx
.386noresult:
.386_no_dump:
%endif	; _SDUMP
	push dx
	extcallcall putsline_crlf
.386nodisplay:
	extcallcall dohack
	pop dx
	pop es
	pop ds
	pop edi
	jmp .386next

subcpureset
%endif	; _PM


%if _SDUMPDISPLACEMENT

		; INP:	(e)dx = length of pattern - 1
		;	es:di -> where to write, within line_out
		;	di <= line_out + 13
		;	di >= line_out + 9
		; OUT:	bx = table offset
		;	ax = how many bytes to dump (13 .. 16)
		; CHG:	-
sss_calculate_displacement:

	xor bx, bx
	_386_PM_o32
	inc dx			; = pattern length (can overflow)
_386_PM	mov bl, 6		; dword needed
_386_PM	test edx, 0FF00_0000h
_386_PM	jnz @F
_386_PM	mov bl, 4		; 3byte needed
_386_PM	test edx, 0FF_0000h
_386_PM	jnz @F
	mov bl, 2		; word needed
	test dh, dh
	jnz @F
	mov bl, 0		; byte needed
@@:

	mov ax, " +"
	stosw			; common prefix
	_386_PM_o32
	mov ax, dx
reloc	call near [word sss_displacement_write_table + bx]
internaldatarelocation
				; write displacement number
	_386_PM_o32
	dec dx			; restore

	mov ax, 32 | 32 << 8
	stosw			; write blanks
	mov ax, di
reloc	sub ax, strict word relocated(line_out)
linkdatarelocation line_out	; = length written so far (<= 25, >= 15)
	neg ax			; minus length written so far (>= -25, <= -15)
	add ax, 79		; 79 minus length written so far
				;  = how many columns remaining (>= 54, <= 64)
	shr ax, 1
	shr ax, 1		; divide by 4 (>= 13, <= 16)
				;  = how many bytes can be dumped
	retn


	usesection lDEBUG_DATA_ENTRY
	align 2, db 0
sss_displacement_write_table:
reloc	dw .byte
internalcoderelocation
reloc	dw .word
internalcoderelocation
 %if _PM && ! _ONLYNON386
reloc	dw .3byte
internalcoderelocation
reloc	dw .dword
internalcoderelocation
 %endif

	usesection lDEBUG_CODE

 %if ELD
.byte:
	extcallcall hexbyte
	retn
.word:
	extcallcall hexword
	retn
  %if _PM && ! _ONLYNON386
.3byte:
 subcpu 386
	ror eax, 16
	extcallcall hexbyte
	rol eax, 16
 subcpureset
	jmp .word
.dword:
	extcall hexdword, PM required
	retn
  %endif
 %else
.byte: equ hexbyte
.word: equ hexword
  %if _PM && ! _ONLYNON386
.3byte:
 subcpu 386
	ror eax, 16
	call hexbyte
	rol eax, 16
 subcpureset
	jmp .word
.dword: equ hexdword
  %endif
 %endif
%endif

%if ELD
do_repne_scasb:
_386_PM	jc do_repne_scasb_a32
	repne scasb
	retn

do_scasb:
_386_PM	jc do_scasb_a32
	scasb
	retn

do_repe_cmpsb:
_386_PM	jc do_repe_cmpsb_a32
	repe cmpsb
	retn

do_repe_cmpsb_caps:
_386_PM	jc do_repe_cmpsb_caps_a32
	jcxz .retn
.loop:
	lodsb
	mov bh, 2		; caps flag
	call difficult_scasb_a16
	loope .loop
.retn:
	retn

difficult_repe_cmpsb:
_386_PM	jc difficult_repe_cmpsb_a32
	jcxz .retn
	lframe
	lenter
	xor bx, bx
	 push bx		; ?idx = 0
	lvar word, idx
	mov bl, 2		; skip initial tag
.loop:
	push cx
	mov cx, bx		; cl = how many tags to skip times 2
	mov bx, word [bp + ?idx]; + tagbuffer -> current tag byte
reloc	mov ch, byte [ss:word tagbuffer + bx]
internaldatarelocation		; get current tag byte
	shr ch, cl		; shift down tag to bit 0 and 1
	add cl, 2		; next tag
	cmp cl, 8		; need to increment ?idx ?
	jb @F			; no -->
	mov cl, 0		; reset for next iteration
	inc word [bp + ?idx]	; point at next tag byte
@@:
	mov bx, cx		; bl = shift count for next tag,
				; bh bit 0 and 1 = tag
	pop cx
	lodsb
	push bx			; preserve shift count
	call difficult_scasb_a16
	pop bx
	loope .loop
	lleave
.retn:
	retn


difficult_repne_scasb:
reloc	mov bh, byte [ss:tagbuffer]
internaldatarelocation
_386_PM	jc difficult_repne_scasb_a32
	jcxz .ret
.loop:
	call difficult_scasb_a16
	loopne .loop
.ret:
	retn

difficult_scasb:
reloc	mov bh, byte [ss:tagbuffer]
internaldatarelocation
_386_PM	jc difficult_scasb_a32
difficult_scasb_a16:
	test bh, 1
	jnz .wild
	test bh, 2
	jnz .caps
	scasb
	retn

.caps:
	push di
	scasb
	je .ret_stack		; ZR
	cmp al, 'A'
	jb .ret_stack		; NZ
	cmp al, 'Z'
	jbe .toggle
	cmp al, 'a'
	jb .ret_stack		; NZ
	cmp al, 'z'
	ja .ret_stack		; NZ
.toggle:
	pop di
	xor al, 32		; try other caps status
	scasb
	retn

.ret_stack:
	pop bx
	retn

.wild:
	scasb
	cmp al, al
	retn


 %if _PM
	subcpu 386
do_repne_scasb_a32:
	repne

do_scasb_a32:
	a32 scasb
	retn

do_repe_cmpsb_a32:
	a32 repe cmpsb
	retn

do_repe_cmpsb_caps_a32:
	jecxz .retn
.loop:
	a32 lodsb
	mov bh, 2		; caps flag
	call difficult_scasb_a32
	loope .loop, ecx
.retn:
	retn

difficult_repe_cmpsb_a32:
	jecxz .retn
	lframe
	lenter
	xor bx, bx
	 push bx		; ?idx = 0
	lvar word, idx
	mov bl, 2		; skip initial tag
.loop:
	push cx
	mov cx, bx		; cl = how many tags to skip times 2
	mov bx, word [bp + ?idx]; + tagbuffer -> current tag byte
reloc	mov ch, byte [ss:word tagbuffer + bx]
internaldatarelocation		; get current tag byte
	shr ch, cl		; shift down tag to bit 0 and 1
	add cl, 2		; next tag
	cmp cl, 8		; need to increment ?idx ?
	jb @F			; no -->
	mov cl, 0		; reset for next iteration
	inc word [bp + ?idx]	; point at next tag byte
@@:
	mov bx, cx		; bl = shift count for next tag,
				; bh bit 0 and 1 = tag
	pop cx
	a32 lodsb
	push bx			; preserve shift count
	call difficult_scasb_a32
	pop bx
	loope .loop, ecx
	lleave
.retn:
	retn


difficult_repne_scasb_a32:
	jecxz .ret
.loop:
	call difficult_scasb_a32
	loopne .loop, ecx
.ret:
	retn

difficult_scasb_a32:
	test bh, 1
	jnz .wild
	test bh, 2
	jnz .caps
	a32 scasb
	retn

.caps:
	push edi
	a32 scasb
	je .ret_stack		; ZR
	cmp al, 'A'
	jb .ret_stack		; NZ
	cmp al, 'Z'
	jbe .toggle
	cmp al, 'a'
	jb .ret_stack		; NZ
	cmp al, 'z'
	ja .ret_stack		; NZ
.toggle:
	pop edi
	xor al, 32		; try other caps status
	a32 scasb
	retn

.ret_stack:
	pop ebx
	retn

.wild:
	a32 scasb
	cmp al, al
	retn

	subcpureset
 %endif
%endif

..@sss_access_end:
