	TITLE	bits

	.386p

_TEXT	SEGMENT  DWORD PUBLIC use32 'CODE'
_TEXT	ENDS

_TEXT	SEGMENT
	ASSUME	CS: _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(pdst, psrc, doff, soff, n)
; u_char *pdst	/* EAX */
; u_char *psrc;	/* EDX */
; int doff;	/* EBX */
; int soff;	/* ECX */
; int n;	/* on the stack */
buf	equ	-130
n	equ	8


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

; setbits(pdst, psrc, doff, soff, n)
;	psrc and soff are ignored.
setbits_:
	mov	edx,-1	; set src to ones

; setmem is called with DX containing the value to set.
setmem:
	push	ebp
	mov	ebp,esp
	push	edi
	mov	edi,eax		; pdst
	mov	eax,edx		; value
	mov	edx,ebx		; doff
	shr	edx,3
	add	edi,edx		; pdst += doff >> 3
	mov	edx,n[ebp]	; get bits to set
	and	ebx,7		; doff &= 7
	jz	short sm_3	; if doff == 0
	mov	ecx,ebx		; soff = doff
	not	ch		; ch = 0xff
	shr	ch,cl		; mask = 0xff >> doff
	neg	bl		; -doff
	and	bl,7		; 8 - doff
	sub	edx,ebx		; test n and (8 - doff)
	ja	short sm_1		; if (n > 8 - doff) then branch
	je	short sm_2		; if (n = 8 - doff) then branch
	neg	dl		; al = 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,[edi]	; ~mask & *pdst
	or	al,ch		; (data & mask) | (*pdst & ~mask)
	stosb
	jmp	short sm_exit
sm_1:
	and	al,ch
	not	ch
	and	ch,[edi]
	or	al,ch		; (*pdst & ~mask) | (data & mask)
	stosb
	mov	al,ah		; restore set value
sm_3:
	mov	ecx,edx		; n
	shrd	ebx,ecx,5	; convert to dwords
	shr	ecx,5
	rep	stosd
	shld	ecx,ebx,2	; get last 0-3 bytes
	rep	stosb
	mov	cl,dl
	and	cl,7		; how many bits left??
	jz	short sm_exit		; were done
	not	ch		; ch = 0xff
	shr	ch,cl		; 0xff >> bits left
	mov	ah,[edi]
	and	ah,ch		; *pdst & ~mask
	not	ch
	and	al,ch		; data & mask
	or	al,ah		; (data & mask) | (*pdst & ~mask)
	stosb
sm_exit:
	pop	edi
	pop	ebp

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

; invertbits(psrc, pdst, soff, doff, n)
;	psrc and soff are ignored.
invertbits_:
	push	ebp
	mov	ebp,esp
	push	esi
	mov	esi,eax		; pdst
	mov	ecx,ebx		; doff
	shr	ebx,3
	add	esi,ebx		;
	mov	edx,n[ebp]	; get bits to set
	and	ecx,7		; doff &= 7
	jecxz	short ib_5		; if doff == 0
	mov	ebx,ecx
	not	ch		; ch = 0xff
	shr	ch,cl		; mask = 0xff >> doff
	neg	bl		; -doff
	and	ebx,7		; 8 - doff
	sub	edx,ebx		; test n and (8 - doff)
	ja	short ib_1	; if (n > 8 - doff) then branch
	je	short 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	[esi],ch
	jmp	short ib_exit
ib_1:
	xor	[esi],ch
	inc	esi
ib_5:
	mov	eax,-1		; make all ones
	mov	ecx,edx
	shr	ecx,4		; convert to words
	jz	short ib_3
ib_loop:
	xor	[esi],ax
	add	esi,2
	loop	ib_loop
ib_3:
	mov	cl,dl
	test	cl,8
	jz	short ib_4
	xor	[esi],al
	inc	esi
ib_4:
	and	cl,7		; how many bits left??
	jz	ib_exit		; were done
	shr	al,cl		; 0xff >> bits left
	not	al
	xor	[esi],al
ib_exit:
	pop	esi
	pop	ebp
	ret	4

; orInvertedbits(psrc, pdst, soff, doff, n)
;	*pdst = *pdst | ~*psrc
orInvertedbits_:
	push	ebp
	mov	ebp,esp
	add	esp,buf-2
	push	esi
	push	edi
	call	do_common
	jecxz	short oI_6		; if (doff == 0)
	mov	ebx,ecx		; save doff
	not	ch		; ch = 0xff
	shr	ch,cl		; mask = 0xff >> doff
	neg	bl		; bh = 0
	and	bl,7		; 8 - doff
	sub	edx,ebx		; test n and (8 - doff)
	lodsb
	not	al
	ja	short oI_2		; if (n > 8 - doff) then branch
	je	short 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	[edi],al
	jmp	short oI_exit
oI_2:
	and	al,ch
	or	[edi],al
	inc	edi		; point to next one
oI_6:
	mov	ecx,edx
	shr	ecx,4		; convert to words
	jecxz	short oI_4
oI_loop:
	lodsw
	not	eax
	or	[edi],ax
	add	edi,2
	loop	oI_loop
oI_4:
	mov	cl,dl		; n
	test	cl,8		; ch = 0
	jz	short oI_5
	lodsb
	not	al
	or	[edi],al
	inc	edi
oI_5:
	and	cl,7		; how many bits left??
	jz	short oI_exit		; we're done
	not	ch		; ch = 0xff
	shr	ch,cl		; 0xff >> bits left
	or	ch,[esi]
	not	ch
	or	[edi],ch
oI_exit:
	pop	edi
	pop	esi
	leave
	ret	4

; orReversebits(psrc, pdst, soff, doff, n)
;	*pdst = ~*pdst | *psrc
orReversebits_:
	push	ebp
	mov	ebp,esp
	add	esp,buf-2
	push	esi
	push	edi
	call	do_common
	jecxz	short oR_6		; if (doff == 0)
	mov	ebx,ecx		; save doff
	not	ch		; ch = 0xff
	shr	ch,cl		; mask = 0xff >> doff
	neg	bl		; bh = 0
	and	bl,7		; 8 - doff
	sub	edx,ebx		; test n and (8 - doff)
	lodsb
	ja	short oR_2		; if (n > 8 - doff) then branch
	je	short 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,[edi]
	or	al,ch
	stosb
	jmp	short oR_exit
oR_2:
	and	al,ch
	xor	ch,[edi]
	or	al,ch
	stosb
oR_6:
	mov	ecx,edx
	shr	ecx,4		; convert to words
	jecxz	short oR_4
oR_loop:
	lodsw
	mov	bx,[edi]
	not	ebx
	or	eax,ebx
	stosw
	loop	oR_loop
oR_4:
	mov	cl,dl		; n
	test	cl,8		; ch = 0
	jz	short oR_5
	lodsb
	mov	ah,[edi]
	not	ah
	or	al,ah
	stosb
oR_5:
	and	cl,7		; how many bits left??
	jz	short oR_exit		; we're done
	not	ch		; ch = 0xff
	shr	ch,cl		; 0xff >> bits left
	lodsb
	not	ch
	and	al,ch		; mask
	xor	ch,[edi]
	or	al,ch
	stosb
oR_exit:
	pop	edi
	pop	esi
	leave
	ret	4

; andReversebits(psrc, pdst, soff, doff, n)
;	*pdst = ~*pdst & *psrc
andReversebits_:
	push	ebp
	mov	ebp,esp
	add	esp,buf-2
	push	esi
	push	edi
	call	do_common
	jecxz	short aR_6		; if (doff == 0)
	mov	ebx,ecx		; save doff
	not	ch		; ch = 0xff
	shr	ch,cl		; mask = 0xff >> doff
	neg	bl		; bh = 0
	and	bl,7		; 8 - doff
	sub	edx,ebx		; test n and (8 - doff)
	lodsb
	ja	short aR_2		; if (n > 8 - doff) then branch
	je	short 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,[edi]	; ~*pdst & mask
	not	ch
	or	al,ch
	and	al,ah
	stosb
	jmp	short aR_exit
aR_2:
	mov	ah,ch
	xor	ah,[edi]	; ~*pdst & mask
	not	ch
	or	al,ch
	and	al,ah
	stosb
aR_6:
	mov	ecx,edx
	shr	ecx,4		; convert to words
	jecxz	short aR_4
aR_loop:
	lodsw
	mov	bx,[edi]
	not	ebx
	and	eax,ebx
	stosw
	loop	aR_loop
aR_4:
	mov	cl,dl		; n
	test	cl,8		; ch = 0
	jz	short aR_5
	lodsb
	mov	ah,[edi]
	not	ah
	and	al,ah
	stosb
aR_5:
	and	cl,7		; how many bits left??
	jz	short aR_exit		; we're done
	not	ch		; ch = 0xff
	shr	ch,cl		; 0xff >> bits left
	lodsb
	or	al,ch
	not	ch
	xor	ch,[edi]
	and	al,ch		; mask
	stosb
aR_exit:
	pop	edi
	pop	esi
	leave
	ret	4

; nandbits(pdst, psrc, doff, soff, n)
;	*pdst = ~(*pdst & *psrc)
nandbits_:
	push	ebp
	mov	ebp,esp
	add	esp,buf-2
	push	esi
	push	edi
	call	do_common
	jecxz	short n_6		; if (doff == 0)
	mov	ebx,ecx		; save doff
	not	ch		; ch = 0xff
	shr	ch,cl		; mask = 0xff >> doff
	neg	bl		; bh = 0
	and	bl,7		; 8 - doff
	sub	edx,ebx		; test n and (8 - doff)
	lodsb
	ja	short n_2		; if (n > 8 - doff) then branch
	je	short 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,[edi]
	not	ch
	or	al,ch
	not	al
	or	al,ah
	stosb
	jmp	short n_exit
n_2:
	mov	ah,ch		; mask
	xor	ah,[edi]	; mask ^ dst
	not	ch		; ~mask
	or	al,ch		; src | ~mask
	not	al		; ~src & mask
	or	al,ah		; (~src & mask) | (mask ^ dst)
	stosb			; or ((~src | ~dst) & mask) | (dst & ~mask)
n_6:
	mov	ecx,edx
	shr	ecx,4		; convert to words
	jecxz	short n_4
n_loop:
	lodsw
	and	ax,[edi]
	not	eax
	stosw
	loop	n_loop
n_4:
	mov	cl,dl		; n
	test	cl,8		; ch = 0
	jz	short n_5
	lodsb
	and	al,[edi]
	not	al
	stosb
n_5:
	and	cl,7		; how many bits left??
	jz	short 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,[edi]
	or	al,ch
	stosb
n_exit:
	pop	edi
	pop	esi
	leave
	ret	4

; norbits(psrc, pdst, soff, doff, n)
;	*pdst = ~(*pdst | *psrc)
norbits_:
	push	ebp
	mov	ebp,esp
	add	esp,buf-2
	push	esi
	push	edi
	call	do_common
	jecxz	short no_6		; if (doff == 0)
	mov	ebx,ecx		; save doff
	not	ch		; ch = 0xff
	shr	ch,cl		; mask = 0xff >> doff
	neg	bl		; bh = 0
	and	bl,7		; 8 - doff
	sub	edx,ebx		; test n and (8 - doff)
	lodsb
	not	al
	ja	short no_2		; if (n > 8 - doff) then branch
	je	short 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,[edi]
	not	ch
	or	al,ch
	and	al,ah
	stosb
	jmp	short no_exit
no_2:
	mov	ah,ch
	xor	ah,[edi]
	not	ch
	or	al,ch
	and	al,ah
	stosb
no_6:
	mov	ecx,edx
	shr	ecx,4		; convert to words
	jecxz	short no_4
no_loop:
	lodsw
	or	ax,[edi]
	not	eax
	stosw
	loop	no_loop
no_4:
	mov	cl,dl		; n
	test	cl,8		; ch = 0
	jz	short no_5
	lodsb
	or	al,[edi]
	not	al
	stosb
no_5:
	and	cl,7		; how many bits left??
	jz	short 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,[edi]
	and	al,ch
	stosb
no_exit:
	pop	edi
	pop	esi
	leave
	ret	4

; orbits(psrc, pdst, soff, doff, n)
;	*pdst = *pdst & *psrc
orbits_:
	push	ebp
	mov	ebp,esp
	add	esp,buf-2
	push	esi
	push	edi
	call	do_common
	jecxz	short o_6		; if (doff == 0)
	mov	ebx,ecx		; save doff
	not	ch		; ch = 0xff
	shr	ch,cl		; mask = 0xff >> doff
	neg	bl		; bh = 0
	and	bl,7		; 8 - doff
	sub	edx,ebx		; test n and (8 - doff)
	lodsb
	ja	short o_2		; if (n > 8 - doff) then branch
	je	short 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	[edi],al
	jmp	short o_exit
o_2:
	and	al,ch
	or	[edi],al
	inc	edi		; point to next one
o_6:
	mov	ecx,edx
	shr	ecx,4		; convert to words
	jecxz	short o_4
o_loop:
	lodsw
	or	[edi],ax
	add	edi,2
	loop	o_loop
o_4:
	mov	cl,dl		; n
	test	cl,8		; ch = 0
	jz	short o_5
	lodsb
	or	[edi],al
	inc	edi
o_5:
	and	cl,7		; how many bits left??
	jz	short o_exit		; we're done
	not	ch		; ch = 0xff
	shr	ch,cl		; 0xff >> bits left
	lodsb
	not	ch
	and	al,ch		; mask
	or	[edi],al
o_exit:
	pop	edi
	pop	esi
	leave
	ret	4

; andbits(psrc, pdst, soff, doff, n)
;	*pdst = *pdst & *psrc
andbits_:
	push	ebp
	mov	ebp,esp
	add	esp,buf-2
	push	esi
	push	edi
	call	do_common
	jecxz	short a_6		; if (doff == 0)
	mov	ebx,ecx		; save doff
	not	ch		; ch = 0xff
	shr	ch,cl		; mask = 0xff >> doff
	neg	bl		; bh = 0
	and	bl,7		; 8 - doff
	sub	edx,ebx		; test n and (8 - doff)
	lodsb
	ja	short a_2		; if (n > 8 - doff) then branch
	je	short 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	[edi],al
	jmp	short a_exit
a_2:
	not	ch
	or	al,ch
	and	[edi],al
	inc	edi		; point to next one
a_6:
	mov	ecx,edx
	shr	ecx,4		; convert to words
	jecxz	short a_4
a_loop:
	lodsw
	and	[edi],ax
	add	edi,2
	loop	a_loop
a_4:
	mov	cl,dl		; n
	test	cl,8		; ch = 0
	jz	short a_5
	lodsb
	and	[edi],al
	inc	edi
a_5:
	and	cl,7		; how many bits left??
	jz	short a_exit		; we're done
	not	ch		; ch = 0xff
	shr	ch,cl		; 0xff >> bits left
	lodsb
	or	al,ch		; mask
	and	[edi],al
a_exit:
	pop	edi
	pop	esi
	leave
	ret	4

; andInvertedbits(psrc, pdst, soff, doff, n)
;	*pdst = *pdst & ~*psrc
andInvertedbits_:
	push	ebp
	mov	ebp,esp
	add	esp,buf-2
	push	esi
	push	edi
	call	do_common
	jecxz	short aI_6		; if (doff == 0)
	mov	ebx,ecx		; save doff
	not	ch		; ch = 0xff
	shr	ch,cl		; mask = 0xff >> doff
	neg	bl		; bh = 0
	and	bl,7		; 8 - doff
	sub	edx,ebx		; test n and (8 - doff)
	lodsb
	not	al
	ja	short aI_2		; if (n > 8 - doff) then branch
	je	short 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	[edi],al
	jmp	short aI_exit
aI_2:
	not	ch
	or	al,ch
	and	[edi],al
	inc	edi		; point to next one
aI_6:
	mov	ecx,edx
	shr	ecx,4		; convert to words
	jecxz	short aI_4
aI_loop:
	lodsw
	not	eax
	and	[edi],ax
	add	edi,2
	loop	aI_loop
aI_4:
	mov	cl,dl		; n
	test	cl,8		; ch = 0
	jz	short aI_5
	lodsb
	not	al
	and	[edi],al
	inc	edi
aI_5:
	and	cl,7		; how many bits left??
	jz	short aI_exit		; we're done
	not	ch		; ch = 0xff
	shr	ch,cl		; 0xff >> bits left
	lodsb
	not	al
	or	al,ch		; mask
	and	[edi],al
aI_exit:
	pop	edi
	pop	esi
	leave
	ret	4

; 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	ebp
	mov	ebp,esp
	add	esp,buf-2
	push	esi
	push	edi
	call	do_common
	jecxz	short cI_6		; if (doff == 0)
	mov	ebx,ecx		; save doff
	not	ch		; ch = 0xff
	shr	ch,cl		; mask = 0xff >> doff
	neg	bl		; bh = 0
	and	bl,7
	sub	edx,ebx		; test n and (8 - doff)
	lodsb
	not	al
	ja	short cI_2		; if (n > 8 - doff) then branch
	je	short 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,[edi]
	or	al,ch
	stosb
	jmp	short cI_exit
cI_2:
	and	al,ch
	not	ch
	and	ch,[edi]
	or	al,ch
	stosb
cI_6:
	mov	ecx,edx
	shr	ecx,4		; convert to words
	jecxz	short cI_7
cI_8:
	lodsw
	not	eax
	stosw
	loop	cI_8
cI_7:
	mov	cl,dl
	test	cl,8
	jz	short cI_9
	lodsb
	not	al
	stosb
cI_9:
	and	cl,7		; how many bits left??
	jz	short cI_exit		; we're done
	not	ch		; ch = 0xff
	shr	ch,cl		; 0xff >> bits left
	mov	al,[edi]
	and	al,ch		; mask & *pdst
	or	ch,[esi]		; mask | *psrc
	not	ch		; ~mask & ~*psrc
	or	al,ch		; (mask & *pdst) | (~mask & ~*psrc)
	stosb
cI_exit:
	pop	edi
	pop	esi
	leave
	ret	4

; 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	ebp
	mov	ebp,esp
	add	esp,buf-2
	push	esi
	push	edi
	call	do_common
	jecxz	short c_6		; if (doff == 0)
	mov	ebx,ecx		; save doff
	not	ch		; ch = 0xff
	shr	ch,cl		; mask = 0xff >> doff
	neg	bl		; bh = 0
	and	bl,7
	sub	edx,ebx		; test n and (8 - doff)
	lodsb
	ja	short c_2		; if (n > 8 - doff) then branch
	je	short 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,[edi]
	or	al,ch
	stosb
	jmp	short c_exit
c_2:
	and	al,ch
	not	ch
	and	ch,[edi]
	or	al,ch
	stosb
c_6:
	mov	ecx,edx
	shrd	ebx,ecx,5	; convert to dwords
	shr	ecx,5
	rep	movsd
	shld	ecx,ebx,2	; get bytes back from edx
	rep	movsb
	mov	cl,dl		; n
	and	cl,7		; how many bits left??
	jz	short c_exit		; we're done
	not	ch		; ch = 0xff
	shr	ch,cl		; 0xff >> bits left
	mov	al,[edi]
	and	al,ch
	not	ch
	and	ch,[esi]
	or	al,ch
	stosb
c_exit:
	pop	edi
	pop	esi
	leave
	ret	4

; 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	ebp
	mov	ebp,esp
	add	esp,buf-2
	push	esi
	push	edi
	call	do_common
	jecxz	short x_6		; if (doff == 0)
	mov	ebx,ecx		; save doff
	not	ch		; ch = 0xff
	shr	ch,cl		; mask = 0xff >> doff
	neg	bl		; bh = 0
	and	bl,7
	sub	edx,ebx		; test n and (8 - doff)
	lodsb
	ja	short x_2		; if (n > 8 - doff) then branch
	je	short 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	[edi],al
	jmp	short x_exit
x_2:
	and	al,ch
	xor	[edi],al
	inc	edi
x_6:
	mov	ecx,edx
	shr	ecx,4		; convert to words
	jecxz	short x_4
x_loop:
	lodsw
	xor	[edi],ax
	add	edi,2
	loop	x_loop
x_4:
	mov	cl,dl		; ch = 0
	test	cl,8
	jz	short x_5
	lodsb
	xor	[edi],al
	inc	edi
x_5:
	and	cl,7
	jz	short x_exit		; we're done
	not	ch		; ch = 0xff
	shr	ch,cl		; 0xff >> bits left
	not	ch
	and	ch,[esi]
	xor	[edi],ch
x_exit:
	pop	edi
	pop	esi
	leave
	ret	4

; 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	ebp
	mov	ebp,esp
	add	esp,buf-2
	push	esi
	push	edi
	call	do_common
	jecxz	short e_6		; if (doff == 0)
	mov	ebx,ecx		; save doff
	not	ch		; ch = 0xff
	shr	ch,cl		; mask = 0xff >> doff
	neg	bl		; bh = 0
	and	bl,7
	sub	edx,ebx		; test n and (8 - doff)
	lodsb
	not	al
	ja	short e_2		; if (n > 8 - doff) then branch
	je	short 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	[edi],al
	jmp	short e_exit
e_2:
	and	al,ch
	xor	[edi],al
	inc	edi
e_6:
	mov	ecx,edx
	shr	ecx,4		; convert to words
	jecxz	short e_4
e_loop:
	lodsw
	not	eax
	xor	[edi],ax
	add	edi,2
	loop	e_loop
e_4:
	mov	cl,dl		; ch = 0
	test	cl,8
	jz	short e_5
	lodsb
	not	al
	xor	[edi],al
	inc	edi
e_5:
	and	cl,7
	jz	short e_exit		; we're done
	not	ch		; ch = 0xff
	shr	ch,cl		; 0xff >> bits left
	or	ch,[esi]
	not	ch
	xor	[edi],ch
e_exit:
	pop	edi
	pop	esi
	leave
	ret	4
BITS	ENDP

; called with arguments of function
; shift the bits and return:
;	ESI:	psrc (this could be the buffer if we had to shift)
;	EDI:	pdst
;	ECX:	doff
;	EDX:	n
; After we do the shift, soff is not needed.

do_common	PROC NEAR
	mov	edi,eax		; pdst
	mov	esi,edx		; psrc

	mov	edx,ecx		; soff
	shr	ecx,3
	add	esi,ecx		; psrc += soff >> 3
	and	edx,7		; soff &= 7

	mov	ecx,ebx		; doff
	shr	ecx,3
	add	edi,ecx		; pdst += doff >> 3
	and	ebx,7		; now we only need doff & 7

	mov	ecx,ebx		; doff
	sub	ecx,edx		; doff-soff
	jz	short dc_1		; bits to shift == 0

	push	edi		; save pdst

	lea	edi,buf[ebp]
; the number of bytes to copy is always (soff + n + 7) >> 3 no matter which
; direction we are copying.
	ja	short dc_right
	and	cl,7		; left shift
	dec	edi		; skip first byte
dc_right:
	add	edx,n[ebp]	; count = n + soff
	add	edx,7		; make sure it is at byte values
	shr	edx,3		; convert to bytes
	jz	short dc_2	; This can't happen
	sub	ah,ah		; clear the high byte
dc_right_loop:
	lodsb			; get byte
	mov	ch,al		; save it
	shr	eax,cl
	stosb			; and save it
	mov	ah,ch		; setup for next byte
	dec	edx
	jnz	short dc_right_loop

	shr	eax,cl		; get trailing part of last byte
	stosb

dc_2:
	lea	esi,buf[ebp]	; buffer is source

	pop	edi		; restore pdst
dc_1:
	mov	edx,n[ebp]	; get bits to set
	mov	ecx,ebx		; restore doff
	ret
do_common	ENDP
_TEXT	ENDS
	END
