;       SCCSID = @(#)byte.asm	6.1 90/11/18
;	SCCSID = @(#)byte.asm      13.3 90/01/25
;***	BYTE - perform byte move/fill/compare/scan operations
;
;	BYTE_COPY (pchSrc, pchDst, cch)
;	BYTE_COPY_DN (pchSrc, pchDst, cch)
;	BYTE_FILL (pchDst, ch, cch)

.286

.MODEL MEDIUM, PASCAL

ifdef MEDIUM_MODEL
CALLTYPE    equ <far>
else
CALLTYPE    equ <near>
endif

.data

IRP SEG,<_TEXT,_BTXT>

.CODE SEG


;**	BYTE_COPY - copy data from source to destination
;
;	Caller must be aware that we only copy UP.  No overlap detection
;	is provided.
;
;	Returns pointer to next destination

public	BYTE_COPY&SEG
BYTE_COPY&SEG   proc CALLTYPE   uses ds si di, \
pchSrc:dword, pchDst:dword, cch:word

	lds	si,pchSrc
	les	di,pchDst
	mov	cx,cch

;	(ds:si) = source address
;	(es:di) = destination address
;	(cx) = number of bytes to move

        cmp     cx,9        ; Small copy ?.
        jbe     bc1         ; Yes - do simple rep movsb.
        mov     ax,di
        neg     ax          ; d1d0 = count to quad-align.
        and     ax,3        ; Is dst quad-aligned ?
; ax = number of bytes remainnig after round off to quad-aligned.
        jz      bc0         ; Yes.
        sub     cx,ax       ; cx must be > 9.
; dst is not quad-aligned, enough to copy to make it quad-aligned.
        xchg    ax,cx       ; cx = # of bytes to copy to make quad-aligned.
    rep movsb
        mov     cx,ax       ; cx = reminder of byte count.
bc0:
        mov     ax,cx       ; set ax in case we took a jump to bc0.
        shr     cx,2        ; cx = reminder of dword count.
        and     ax,3        ; ax = reminder byte count after dword move.
.386
    rep movsd
.286
        mov     cx,ax       ; cx = Remaining byte count.
bc1:
    rep movsb

;	(es:di) = pointer to next place to store

	mov	dx,es
	mov	ax,di

	ret

BYTE_COPY&SEG   endp


;**	BYTE_COPY_DN - copy data from source to destination
;
;	Caller must be aware that we only copy DOWN.  No overlap detection
;	is provided.  Pointers must point to the end location of the copy
;	(i.e. the high memory location)
;
;	Returns pointer to next destination

public	BYTE_COPY_DN&SEG
BYTE_COPY_DN&SEG	    proc   CALLTYPE   uses ds si di, \
pchSrc:dword, pchDst:dword, cch:word

	lds	si,pchSrc
	les	di,pchDst
	mov	cx,cch

;	(ds:si) = source address
;	(es:di) = destination address
;	(cx) = number of bytes to move

	std                 ; set direction flag so we decrement ptrs
        cmp     cx,11       ; Small copy ?.
        jbe     bcd1        ; Yes - do simple rep movsb.
        mov     ax,di
        inc     ax          ; copy down, quad-aligned when d1d0==11.
        and     ax,3        ; Is dst quad-aligned ?
; ax = number of bytes remainnig after round off to quad-aligned.
        jz      bcd0        ; Yes.
        sub     cx,ax       ; cx must be > 9.
; dst is not quad-aligned, enough to copy to make it quad-aligned.
        xchg    ax,cx       ; cx = # of bytes to copy to make quad-aligned.
    rep movsb
        mov     cx,ax       ; cx = reminder of byte count.
bcd0:
        mov     ax,cx       ; set ax in case we took a jump to bcd0.
        shr     cx,2        ; cx = reminder of dword count.
        and     ax,3        ; ax = reminder byte count after dword move.
        sub     si,3        ; Because of byte ordering in a dword
        sub     di,3        ; Because of byte ordering in a dword
.386
    rep movsd
.286
        mov     cx,ax       ; cx = Remaining byte count.
        add     si,3        ; Bumped by remainder since not moving dwords
        add     di,3        ; Bumped by remainder since not moving dwords
bcd1:
    rep movsb

	cld                 ; restore direction

;	(es:di) = pointer to next place to store

	mov	dx,es
	mov	ax,di

	ret
BYTE_COPY_DN&SEG	    endp



;**	BYTE_FILL - fill a region with a particular byte pattern
;
;	Returns pointer to next destination

public BYTE_FILL&SEG

BYTE_FILL&SEG   proc  CALLTYPE    uses di, pchDst:dword, b:word, cch:word

	les	di,pchDst
	mov	ax,b
	mov	cx,cch

        cmp     cx,9        ; Small fill ?.
        jbe     bf1         ; Yes - do simple rep stosb.
        mov     bx,di
        neg     bx          ; d1d0 = count to quad-align.
        and     bx,3        ; Is dst quad-aligned ?
        jz      bf0         ; Yes.
        sub     cx,bx       ; cx must be > 9.
; dst is not quad-aligned, enough to copy to make it quad-aligned.
        xchg    bx,cx       ; cx = # of bytes to copy to make quad-aligned.
    rep stosb
        mov     cx,ax       ; cx = reminder of byte count.
bf0:
        mov     bx,cx       ; set bx in case we took a jump to bf0.
        shr     cx,2        ; cx = reminder of dword count.
        and     bx,3        ; bx = reminder byte count after dword move.
	mov	ah,al
        mov     dx,ax
.386
        shl     edx,16
        shld    eax,edx,16  ; eax = Byte pattern to fill.
    rep stosd
.286
        mov     cx,bx       ; cx = Remaining byte count.
bf1:
    rep stosb

;	(es:di) = pointer to next place to store

	mov	dx,es
	mov	ax,di

	ret
BYTE_FILL&SEG   endp

ENDM
end
