	TITLE	bits

	.286p

IBM_TEXT	SEGMENT  WORD PUBLIC 'CODE'
IBM_TEXT	ENDS
IBM_TEXT	SEGMENT
	ASSUME	CS: IBM_TEXT


	public	_clearbits, _andbits, _andReversebits, _copybits
	public	_andInvertedbits, _noopbits, _xorbits, _orbits
	public	_norbits, _equivbits, _invertbits, _orReversebits
	public	_copyInvertedbits, _orInvertedbits, _nandbits, _setbits

;	All routines are called with the following information
; XXXbits(psrc, pdst, soff, doff, n)
; u_char *psrc, *pdst;	/* byte pointers to src and dst memory */
; int soff, doff;	/* offset into src and dst 0 <= soff,doff <= 7 */
; int n;		/* number of bits to copy */
buf	equ	-130
psrc	equ	4
pdst	equ	8
soff	equ	12
doff	equ	14
n	equ	16


BITS	PROC	NEAR
; clearbits(psrc, pdst, soff, doff, n)
;	psrc and soff are ignored.
_clearbits:
	sub	ax,ax		; set it to zero
	jmp	short setmem

; setbits(psrc, pdst, soff, doff, n)
;	psrc and soff are ignored.
_setbits:
	mov	ax,0ffffh	; set it to ones

; setmem is called with AX containing the value to set.
setmem:
	push	bp
	mov	bp,sp
	push	es
	push	di
	les	di,pdst[bp]
	mov	cx,doff[bp]
	mov	bx,cx
	shr	bx,3
	add	di,bx
	mov	dx,n[bp]	; get bits to set
	and	cx,7
	jcxz	sm_3		; if doff == 0
	mov	bx,cx		; doff
	not	ch		; ch = 0xff
	shr	ch,cl		; mask = 0xff >> doff
	neg	bl		; -doff
	and	bl,7		; 8 - doff
	sub	dx,bx		; test n and (8 - doff)
	ja	sm_1		; if (n > 8 - doff) then branch
	je	sm_2		; if (n = 8 - doff) then branch
	neg	dl		; dl = 8 - n - doff
	mov	cl,dl		; 8 - doff - n
	shl	dh,cl		; dh = 0xff << 8 - doff - n
	and	ch,dh		; ch = mask
sm_2:				; set less than one byte
	and	al,ch		; data & mask
	not	ch		; ~mask
	and	ch,es:[di]	; ~mask & *pdst
	or	al,ch		; (data & mask) | (*pdst & ~mask)
	stosb
	jmp	short sm_exit
sm_1:
	and	al,ch
	not	ch
	and	ch,es:[di]
	or	al,ch		; (*pdst & ~mask) | (data & mask)
	stosb
	mov	al,ah		; restore set value
sm_3:
	mov	cx,dx
	shr	cx,4		; convert to words
	rep	stosw
	adc	cx,cx		; get last byte
	rep	stosb
	mov	cl,dl
	and	cl,7		; how many bits left??
	jz	sm_exit		; were done
	not	ch		; ch = 0xff
	shr	ch,cl		; 0xff >> bits left
	mov	ah,es:[di]
	and	ah,ch		; *pdst & ~mask
	not	ch
	and	al,ch		; data & mask
	or	al,ah		; (data & mask) | (*pdst & ~mask)
	stosb
sm_exit:
	pop	di
	pop	es
	pop	bp

; noopbits(psrc, pdst, soff, doff, n)
;	everything is ignored
_noopbits:
	ret

; invertbits(psrc, pdst, soff, doff, n)
;	psrc and soff are ignored.
_invertbits:
	push	bp
	mov	bp,sp
	push	ds
	push	si
	lds	si,pdst[bp]
	mov	cx,doff[bp]
	mov	bx,cx
	shr	bx,3
	add	si,bx
	mov	dx,n[bp]	; get bits to set
	and	cx,7
	jcxz	ib_5		; if doff == 0
	mov	bx,cx
	not	ch		; ch = 0xff
	shr	ch,cl		; mask = 0xff >> doff
	neg	bl		; -doff
	and	bl,7		; 8 - doff
	sub	dx,bx		; test n and (8 - doff)
	ja	ib_1		; if (n > 8 - doff) then branch
	je	ib_2		; if (n = 8 - doff) then branch
	neg	dl		; dl = 8 - n - doff
	mov	cl,dl		; 8 - doff - n
	shl	dh,cl		; dh = 0xff << 8 - doff - n
	and	ch,dh		; ch = mask
ib_2:
	xor	[si],ch
	jmp	short ib_exit
ib_1:
	xor	[si],ch
	inc	si
ib_5:
	mov	ax,0ffffh	; make all ones
	mov	cx,dx
	shr	cx,4		; convert to words
	jcxz	ib_3
ib_loop:
	xor	[si],ax
	add	si,2
	loop	ib_loop
ib_3:
	mov	cl,dl
	test	cl,8
	jz	ib_4
	xor	[si],al
	inc	si
ib_4:
	and	cl,7		; how many bits left??
	jz	ib_exit		; were done
	shr	al,cl		; 0xff >> bits left
	not	al
	xor	[si],al
ib_exit:
	pop	si
	pop	ds
	pop	bp
	ret

; orInvertedbits(psrc, pdst, soff, doff, n)
;	*pdst = *pdst | ~*psrc
_orInvertedbits:
	push	bp
	mov	bp,sp
	add	sp,buf-2
	push	ds
	push	es
	push	si
	push	di
	call	do_common
	jcxz	oI_6		; if (doff == 0)
	mov	bx,cx		; save doff
	not	ch		; ch = 0xff
	shr	ch,cl		; mask = 0xff >> doff
	neg	bl		; bh = 0
	and	bl,7		; 8 - doff
	sub	dx,bx		; test n and (8 - doff)
	lodsb
	not	al
	ja	oI_2		; if (n > 8 - doff) then branch
	je	oI_3		; if (n < 8 - doff) then branch
	neg	dl		; dl = 8 - n - doff; dh = 0xff
	mov	cl,dl		; 8 - doff - n
	shl	dh,cl		; dh = 0xff << 8 - doff - n
	and	ch,dh		; ch = mask
oI_3:
	and	al,ch
	or	es:[di],al
	jmp	short oI_exit
oI_2:
	and	al,ch
	or	es:[di],al
	inc	di		; point to next one
oI_6:
	mov	cx,dx
	shr	cx,4		; convert to words
	jcxz	oI_4
oI_loop:
	lodsw
	not	ax
	or	es:[di],ax
	add	di,2
	loop	oI_loop
oI_4:
	mov	cl,dl		; n
	test	cl,8		; ch = 0
	jz	oI_5
	lodsb
	not	al
	or	es:[di],al
	inc	di
oI_5:
	and	cl,7		; how many bits left??
	jz	oI_exit		; we're done
	not	ch		; ch = 0xff
	shr	ch,cl		; 0xff >> bits left
	or	ch,[si]
	not	ch
	or	es:[di],ch
oI_exit:
	pop	di
	pop	si
	pop	es
	pop	ds
	leave
	ret

; orReversebits(psrc, pdst, soff, doff, n)
;	*pdst = ~*pdst | *psrc
_orReversebits:
	push	bp
	mov	bp,sp
	add	sp,buf-2
	push	ds
	push	es
	push	si
	push	di
	call	do_common
	jcxz	oR_6		; if (doff == 0)
	mov	bx,cx		; save doff
	not	ch		; ch = 0xff
	shr	ch,cl		; mask = 0xff >> doff
	neg	bl		; bh = 0
	and	bl,7		; 8 - doff
	sub	dx,bx		; test n and (8 - doff)
	lodsb
	ja	oR_2		; if (n > 8 - doff) then branch
	je	oR_3		; if (n < 8 - doff) then branch
	neg	dl		; dl = 8 - n - doff; dh = 0xff
	mov	cl,dl		; 8 - doff - n
	shl	dh,cl		; dh = 0xff << 8 - doff - n
	and	ch,dh		; ch = mask
oR_3:
	and	al,ch
	xor	ch,es:[di]
	or	al,ch
	stosb
	jmp	short oR_exit
oR_2:
	and	al,ch
	xor	ch,es:[di]
	or	al,ch
	stosb
oR_6:
	mov	cx,dx
	shr	cx,4		; convert to words
	jcxz	oR_4
oR_loop:
	lodsw
	mov	bx,es:[di]
	not	bx
	or	ax,bx
	stosw
	loop	oR_loop
oR_4:
	mov	cl,dl		; n
	test	cl,8		; ch = 0
	jz	oR_5
	lodsb
	mov	ah,es:[di]
	not	ah
	or	al,ah
	stosb
oR_5:
	and	cl,7		; how many bits left??
	jz	oR_exit		; we're done
	not	ch		; ch = 0xff
	shr	ch,cl		; 0xff >> bits left
	lodsb
	not	ch
	and	al,ch		; mask
	xor	ch,es:[di]
	or	al,ch
	stosb
oR_exit:
	pop	di
	pop	si
	pop	es
	pop	ds
	leave
	ret

; andReversebits(psrc, pdst, soff, doff, n)
;	*pdst = ~*pdst & *psrc
_andReversebits:
	push	bp
	mov	bp,sp
	add	sp,buf-2
	push	ds
	push	es
	push	si
	push	di
	call	do_common
	jcxz	aR_6		; if (doff == 0)
	mov	bx,cx		; save doff
	not	ch		; ch = 0xff
	shr	ch,cl		; mask = 0xff >> doff
	neg	bl		; bh = 0
	and	bl,7		; 8 - doff
	sub	dx,bx		; test n and (8 - doff)
	lodsb
	ja	aR_2		; if (n > 8 - doff) then branch
	je	aR_3		; if (n < 8 - doff) then branch
	neg	dl		; dl = 8 - n - doff; dh = 0xff
	mov	cl,dl		; 8 - doff - n
	shl	dh,cl		; dh = 0xff << 8 - doff - n
	and	ch,dh		; ch = mask
aR_3:
	mov	ah,ch
	xor	ah,es:[di]	; ~*pdst & mask
	not	ch
	or	al,ch
	and	al,ah
	stosb
	jmp	short aR_exit
aR_2:
	mov	ah,ch
	xor	ah,es:[di]	; ~*pdst & mask
	not	ch
	or	al,ch
	and	al,ah
	stosb
aR_6:
	mov	cx,dx
	shr	cx,4		; convert to words
	jcxz	aR_4
aR_loop:
	lodsw
	mov	bx,es:[di]
	not	bx
	and	ax,bx
	stosw
	loop	aR_loop
aR_4:
	mov	cl,dl		; n
	test	cl,8		; ch = 0
	jz	aR_5
	lodsb
	mov	ah,es:[di]
	not	ah
	and	al,ah
	stosb
aR_5:
	and	cl,7		; how many bits left??
	jz	aR_exit		; we're done
	not	ch		; ch = 0xff
	shr	ch,cl		; 0xff >> bits left
	lodsb
	or	al,ch
	not	ch
	xor	ch,es:[di]
	and	al,ch		; mask
	stosb
aR_exit:
	pop	di
	pop	si
	pop	es
	pop	ds
	leave
	ret

; nandbits(psrc, pdst, soff, doff, n)
;	*pdst = ~(*pdst & *psrc)
_nandbits:
	push	bp
	mov	bp,sp
	add	sp,buf-2
	push	ds
	push	es
	push	si
	push	di
	call	do_common
	jcxz	n_6		; if (doff == 0)
	mov	bx,cx		; save doff
	not	ch		; ch = 0xff
	shr	ch,cl		; mask = 0xff >> doff
	neg	bl		; bh = 0
	and	bl,7		; 8 - doff
	sub	dx,bx		; test n and (8 - doff)
	lodsb
	ja	n_2		; if (n > 8 - doff) then branch
	je	n_3		; if (n < 8 - doff) then branch
	neg	dl		; dl = 8 - n - doff; dh = 0xff
	mov	cl,dl		; 8 - doff - n
	shl	dh,cl		; dh = 0xff << 8 - doff - n
	and	ch,dh		; ch = mask
n_3:
	mov	ah,ch
	xor	ah,es:[di]
	not	ch
	or	al,ch
	not	al
	or	al,ah
	stosb
	jmp	short n_exit
n_2:
	mov	ah,ch
	xor	ah,es:[di]
	not	ch
	or	al,ch
	not	al
	or	al,ch
	stosb
n_6:
	mov	cx,dx
	shr	cx,4		; convert to words
	jcxz	n_4
n_loop:
	lodsw
	and	ax,es:[di]
	not	ax
	stosw
	loop	n_loop
n_4:
	mov	cl,dl		; n
	test	cl,8		; ch = 0
	jz	n_5
	lodsb
	and	al,es:[di]
	not	al
	stosb
n_5:
	and	cl,7		; how many bits left??
	jz	n_exit		; we're done
	not	ch		; ch = 0xff
	shr	ch,cl		; 0xff >> bits left
	lodsb
	or	al,ch		; mask
	not	al
	not	ch
	xor	ch,es:[di]
	or	al,ch
	stosb
n_exit:
	pop	di
	pop	si
	pop	es
	pop	ds
	leave
	ret

; norbits(psrc, pdst, soff, doff, n)
;	*pdst = ~(*pdst | *psrc)
_norbits:
	push	bp
	mov	bp,sp
	add	sp,buf-2
	push	ds
	push	es
	push	si
	push	di
	call	do_common
	jcxz	no_6		; if (doff == 0)
	mov	bx,cx		; save doff
	not	ch		; ch = 0xff
	shr	ch,cl		; mask = 0xff >> doff
	neg	bl		; bh = 0
	and	bl,7		; 8 - doff
	sub	dx,bx		; test n and (8 - doff)
	lodsb
	not	al
	ja	no_2		; if (n > 8 - doff) then branch
	je	no_3		; if (n < 8 - doff) then branch
	neg	dl		; dl = 8 - n - doff; dh = 0xff
	mov	cl,dl		; 8 - doff - n
	shl	dh,cl		; dh = 0xff << 8 - doff - n
	and	ch,dh		; ch = mask
no_3:
	mov	ah,ch
	xor	ah,es:[di]
	not	ch
	or	al,ch
	and	al,ah
	stosb
	jmp	short no_exit
no_2:
	mov	ah,ch
	xor	ah,es:[di]
	not	ch
	or	al,ch
	and	al,ah
	stosb
no_6:
	mov	cx,dx
	shr	cx,4		; convert to words
	jcxz	no_4
no_loop:
	lodsw
	or	ax,es:[di]
	not	ax
	stosw
	loop	no_loop
no_4:
	mov	cl,dl		; n
	test	cl,8		; ch = 0
	jz	no_5
	lodsb
	or	al,es:[di]
	not	al
	stosb
no_5:
	and	cl,7		; how many bits left??
	jz	no_exit		; we're done
	not	ch		; ch = 0xff
	shr	ch,cl		; 0xff >> bits left
	lodsb
	not	al
	or	al,ch
	not	ch
	xor	ch,es:[di]
	and	al,ch
	stosb
no_exit:
	pop	di
	pop	si
	pop	es
	pop	ds
	leave
	ret

; orbits(psrc, pdst, soff, doff, n)
;	*pdst = *pdst & *psrc
_orbits:
	push	bp
	mov	bp,sp
	add	sp,buf-2
	push	ds
	push	es
	push	si
	push	di
	call	do_common
	jcxz	o_6		; if (doff == 0)
	mov	bx,cx		; save doff
	not	ch		; ch = 0xff
	shr	ch,cl		; mask = 0xff >> doff
	neg	bl		; bh = 0
	and	bl,7		; 8 - doff
	sub	dx,bx		; test n and (8 - doff)
	lodsb
	ja	o_2		; if (n > 8 - doff) then branch
	je	o_3		; if (n < 8 - doff) then branch
	neg	dl		; dl = 8 - n - doff; dh = 0xff
	mov	cl,dl		; 8 - doff - n
	shl	dh,cl		; dh = 0xff << 8 - doff - n
	and	ch,dh		; ch = mask
o_3:
	and	al,ch
	or	es:[di],al
	jmp	short o_exit
o_2:
	and	al,ch
	or	es:[di],al
	inc	di		; point to next one
o_6:
	mov	cx,dx
	shr	cx,4		; convert to words
	jcxz	o_4
o_loop:
	lodsw
	or	es:[di],ax
	add	di,2
	loop	o_loop
o_4:
	mov	cl,dl		; n
	test	cl,8		; ch = 0
	jz	o_5
	lodsb
	or	es:[di],al
	inc	di
o_5:
	and	cl,7		; how many bits left??
	jz	o_exit		; we're done
	not	ch		; ch = 0xff
	shr	ch,cl		; 0xff >> bits left
	lodsb
	not	ch
	and	al,ch		; mask
	or	es:[di],al
o_exit:
	pop	di
	pop	si
	pop	es
	pop	ds
	leave
	ret

; andbits(psrc, pdst, soff, doff, n)
;	*pdst = *pdst & *psrc
_andbits:
	push	bp
	mov	bp,sp
	add	sp,buf-2
	push	ds
	push	es
	push	si
	push	di
	call	do_common
	jcxz	a_6		; if (doff == 0)
	mov	bx,cx		; save doff
	not	ch		; ch = 0xff
	shr	ch,cl		; mask = 0xff >> doff
	neg	bl		; bh = 0
	and	bl,7		; 8 - doff
	sub	dx,bx		; test n and (8 - doff)
	lodsb
	ja	a_2		; if (n > 8 - doff) then branch
	je	a_3		; if (n < 8 - doff) then branch
	neg	dl		; dl = 8 - n - doff; dh = 0xff
	mov	cl,dl		; 8 - doff - n
	shl	dh,cl		; dh = 0xff << 8 - doff - n
	and	ch,dh		; ch = mask
a_3:
	not	ch
	or	al,ch
	and	es:[di],al
	jmp	short a_exit
a_2:
	not	ch
	or	al,ch
	and	es:[di],al
	inc	di		; point to next one
a_6:
	mov	cx,dx
	shr	cx,4		; convert to words
	jcxz	a_4
a_loop:
	lodsw
	and	es:[di],ax
	add	di,2
	loop	a_loop
a_4:
	mov	cl,dl		; n
	test	cl,8		; ch = 0
	jz	a_5
	lodsb
	and	es:[di],al
	inc	di
a_5:
	and	cl,7		; how many bits left??
	jz	a_exit		; we're done
	not	ch		; ch = 0xff
	shr	ch,cl		; 0xff >> bits left
	lodsb
	or	al,ch		; mask
	and	es:[di],al
a_exit:
	pop	di
	pop	si
	pop	es
	pop	ds
	leave
	ret

; andInvertedbits(psrc, pdst, soff, doff, n)
;	*pdst = *pdst & ~*psrc
_andInvertedbits:
	push	bp
	mov	bp,sp
	add	sp,buf-2
	push	ds
	push	es
	push	si
	push	di
	call	do_common
	jcxz	aI_6		; if (doff == 0)
	mov	bx,cx		; save doff
	not	ch		; ch = 0xff
	shr	ch,cl		; mask = 0xff >> doff
	neg	bl		; bh = 0
	and	bl,7		; 8 - doff
	sub	dx,bx		; test n and (8 - doff)
	lodsb
	not	al
	ja	aI_2		; if (n > 8 - doff) then branch
	je	aI_3		; if (n < 8 - doff) then branch
	neg	dl		; dl = 8 - n - doff; dh = 0xff
	mov	cl,dl		; 8 - doff - n
	shl	dh,cl		; dh = 0xff << 8 - doff - n
	and	ch,dh		; ch = mask
aI_3:
	not	ch
	or	al,ch
	and	es:[di],al
	jmp	short aI_exit
aI_2:
	not	ch
	or	al,ch
	and	es:[di],al
	inc	di		; point to next one
aI_6:
	mov	cx,dx
	shr	cx,4		; convert to words
	jcxz	aI_4
aI_loop:
	lodsw
	not	ax
	and	es:[di],ax
	add	di,2
	loop	aI_loop
aI_4:
	mov	cl,dl		; n
	test	cl,8		; ch = 0
	jz	aI_5
	lodsb
	not	al
	and	es:[di],al
	inc	di
aI_5:
	and	cl,7		; how many bits left??
	jz	aI_exit		; we're done
	not	ch		; ch = 0xff
	shr	ch,cl		; 0xff >> bits left
	lodsb
	not	al
	or	al,ch		; mask
	and	es:[di],al
aI_exit:
	pop	di
	pop	si
	pop	es
	pop	ds
	leave
	ret

; copyInvertedbits(psrc, pdst, soff, doff, n)
;	*pdst = ~*psrc
; u_char *psrc, *pdst;	/* byte pointers to src and dst memory */
; int soff, doff;	/* offset into src and dst 0 <= soff,doff <= 7 */
; int n;		/* number of bits to copy */

_copyInvertedbits:
	push	bp
	mov	bp,sp
	add	sp,buf-2
	push	ds
	push	es
	push	si
	push	di
	call	do_common
	jcxz	cI_6		; if (doff == 0)
	mov	bx,cx		; save doff
	not	ch		; ch = 0xff
	shr	ch,cl		; mask = 0xff >> doff
	neg	bl		; bh = 0
	and	bl,7
	sub	dx,bx		; test n and (8 - doff)
	lodsb
	not	al
	ja	cI_2		; if (n > 8 - doff) then branch
	je	cI_3		; if (n < 8 - doff) then branch
	neg	dl		; dl = 8 - n - doff; dh = 0xff
	mov	cl,dl		; 8 - doff - n
	shl	dh,cl		; dh = 0xff << 8 - doff - n
	and	ch,dh		; ch = mask
cI_3:
	and	al,ch
	not	ch
	and	ch,es:[di]
	or	al,ch
	stosb
	jmp	short cI_exit
cI_2:
	and	al,ch
	not	ch
	and	ch,es:[di]
	or	al,ch
	stosb
cI_6:
	mov	cx,dx
	shr	cx,4		; convert to words
	jcxz	cI_7
cI_8:
	lodsw
	not	ax
	stosw
	loop	cI_8
cI_7:
	mov	cl,dl
	test	cl,8
	jz	cI_9
	lodsb
	not	al
	stosb
cI_9:
	and	cl,7		; how many bits left??
	jz	cI_exit		; we're done
	not	ch		; ch = 0xff
	shr	ch,cl		; 0xff >> bits left
	mov	al,es:[di]
	and	al,ch		; mask & *pdst
	or	ch,[si]		; mask | *psrc
	not	ch		; ~mask & ~*psrc
	or	al,ch		; (mask & *pdst) | (~mask & ~*psrc)
	stosb
cI_exit:
	pop	di
	pop	si
	pop	es
	pop	ds
	leave
	ret

; copybits(psrc, pdst, soff, doff, n)
;	*pdst = *psrc
; u_char *psrc, *pdst;	/* byte pointers to src and dst memory */
; int soff, doff;	/* offset into src and dst 0 <= soff,doff <= 7 */
; int n;		/* number of bits to copy */

_copybits:
	push	bp
	mov	bp,sp
	add	sp,buf-2
	push	ds
	push	es
	push	si
	push	di
	call	do_common
	jcxz	c_6		; if (doff == 0)
	mov	bx,cx		; save doff
	not	ch		; ch = 0xff
	shr	ch,cl		; mask = 0xff >> doff
	neg	bl		; bh = 0
	and	bl,7
	sub	dx,bx		; test n and (8 - doff)
	lodsb
	ja	c_2		; if (n > 8 - doff) then branch
	je	c_3		; if (n < 8 - doff) then branch
	neg	dl		; dl = 8 - n - doff; dh = 0xff
	mov	cl,dl		; 8 - doff - n
	shl	dh,cl		; dh = 0xff << 8 - doff - n
	and	ch,dh		; ch = mask
c_3:
	and	al,ch
	not	ch
	and	ch,es:[di]
	or	al,ch
	stosb
	jmp	short c_exit
c_2:
	and	al,ch
	not	ch
	and	ch,es:[di]
	or	al,ch
	stosb
c_6:
	mov	cx,dx
	shr	cx,4		; convert to words
	rep	movsw
	adc	cx,cx
	rep	movsb
	mov	cl,dl		; n
	and	cl,7		; how many bits left??
	jz	c_exit		; we're done
	not	ch		; ch = 0xff
	shr	ch,cl		; 0xff >> bits left
	mov	al,es:[di]
	and	al,ch
	not	ch
	and	ch,[si]
	or	al,ch
	stosb
c_exit:
	pop	di
	pop	si
	pop	es
	pop	ds
	leave
	ret

; xorbits(psrc, pdst, soff, doff, n)
;	*pdst = *pdst ^ *psrc
; u_char *psrc, *pdst;	/* byte pointers to src and dst memory */
; int soff, doff;	/* offset into src and dst 0 <= soff,doff <= 7 */
; int n;		/* number of bits to copy */

_xorbits:
	push	bp
	mov	bp,sp
	add	sp,buf-2
	push	ds
	push	es
	push	si
	push	di
	call	do_common
	jcxz	x_6		; if (doff == 0)
	mov	bx,cx		; save doff
	not	ch		; ch = 0xff
	shr	ch,cl		; mask = 0xff >> doff
	neg	bl		; bh = 0
	and	bl,7
	sub	dx,bx		; test n and (8 - doff)
	lodsb
	ja	x_2		; if (n > 8 - doff) then branch
	je	x_3		; if (n = 8 - doff) then branch
	neg	dl		; dl = 8 - n - doff; dh = 0xff
	mov	cl,dl		; 8 - doff - n
	shl	dh,cl		; dh = 0xff << 8 - doff - n
	and	ch,dh		; ch = mask
x_3:
	and	al,ch
	xor	es:[di],al
	jmp	short x_exit
x_2:
	and	al,ch
	xor	es:[di],al
	inc	di
x_6:
	mov	cx,dx
	shr	cx,4		; convert to words
	jcxz	x_4
x_loop:
	lodsw
	xor	es:[di],ax
	add	di,2
	loop	x_loop
x_4:
	mov	cl,dl		; ch = 0
	test	cl,8
	jz	x_5
	lodsb
	xor	es:[di],al
	inc	di
x_5:
	and	cl,7
	jz	x_exit		; we're done
	not	ch		; ch = 0xff
	shr	ch,cl		; 0xff >> bits left
	not	ch
	and	ch,[si]
	xor	es:[di],ch
x_exit:
	pop	di
	pop	si
	pop	es
	pop	ds
	leave
	ret

; equivbits(psrc, pdst, soff, doff, n)
;	*pdst = *pdst ^ ~*psrc
; u_char *psrc, *pdst;	/* byte pointers to src and dst memory */
; int soff, doff;	/* offset into src and dst 0 <= soff,doff <= 7 */
; int n;		/* number of bits to copy */

_equivbits:
	push	bp
	mov	bp,sp
	add	sp,buf-2
	push	ds
	push	es
	push	si
	push	di
	call	do_common
	jcxz	e_6		; if (doff == 0)
	mov	bx,cx		; save doff
	not	ch		; ch = 0xff
	shr	ch,cl		; mask = 0xff >> doff
	neg	bl		; bh = 0
	and	bl,7
	sub	dx,bx		; test n and (8 - doff)
	lodsb
	not	al
	ja	e_2		; if (n > 8 - doff) then branch
	je	e_3		; if (n < 8 - doff) then branch
	neg	dl		; dl = 8 - n - doff; dh = 0xff
	mov	cl,dl		; 8 - doff - n
	shl	dh,cl		; dh = 0xff << 8 - doff - n
	and	ch,dh		; ch = mask
e_3:
	and	al,ch
	xor	es:[di],al
	jmp	short e_exit
e_2:
	and	al,ch
	xor	es:[di],al
	inc	di
e_6:
	mov	cx,dx
	shr	cx,4		; convert to words
	jcxz	e_4
e_loop:
	lodsw
	not	ax
	xor	es:[di],ax
	add	di,2
	loop	e_loop
e_4:
	mov	cl,dl		; ch = 0
	test	cl,8
	jz	e_5
	lodsb
	not	al
	xor	es:[di],al
	inc	di
e_5:
	and	cl,7
	jz	e_exit		; we're done
	not	ch		; ch = 0xff
	shr	ch,cl		; 0xff >> bits left
	or	ch,[si]
	not	ch
	xor	es:[di],ch
e_exit:
	pop	di
	pop	si
	pop	es
	pop	ds
	leave
	ret
BITS	ENDP

do_common	PROC NEAR
	mov	bx,doff[bp]
	mov	cx,bx		; save in cx
	and	cx,7
	mov	doff[bp],cx
	shr	bx,3

	mov	ax,soff[bp]
	mov	dx,ax
	and	dx,7
;	mov	soff[bp],dx
	shr	ax,3
	lds	si,psrc[bp]
	add	si,ax

	sub	cx,dx		; doff-soff
	jz	dc_1		; bits to shift == 0
	mov	ax,ss
	mov	es,ax		; setup dest
	lea	di,buf[bp]
	mov	dx,doff[bp]
	ja	dc_right
	and	cl,7		; right shift
	dec	di		; skip first byte
	add	dx,8		; add one more byte
dc_right:
	add	dx,n[bp]	; count = n + doff
	add	dx,7		; make sure it is at byte values
	shr	dx,3		; convert to bytes
	sub	ah,ah		; clear the high byte
dc_right_loop:
	lodsb			; get byte
	mov	ch,al		; save it in bl
	shr	ax,cl
	stosb			; and save it
	mov	ah,ch		; setup for next byte
	dec	dx
	jnz	dc_right_loop

	mov	ax,ss
	mov	ds,ax		; setup psrc
	lea	si,buf[bp]
dc_1:
	les	di,pdst[bp]
	add	di,bx
	mov	dx,n[bp]	; get bits to set
	mov	cx,doff[bp]
	ret
do_common	ENDP
IBM_TEXT	ENDS
	END
