	INCLUDE	inc.i
	
; void bcopy(void *src, void *dst, long cnt)
;	handle overlap (both ways), odd/even alignment etc
;	++jrb	bammi@dsrgsun.ces.cwru.edu
;
	CODE
	IF		_REGARG
	xdef	@bcopy
	xdef	@_bcopy
	ELSE
	xdef	_bcopy
	xdef	__bcopy
	ENDC
	
	IFEQ	_REGARG
_bcopy:
__bcopy:
	move.l	4(sp),a0	; src -> a0
	move.l	8(sp),a1	; dst -> a1
	move.l	12(sp),d0	; cnt -> d0
	ELSE
@bcopy:
@_bcopy:
	tst.l	d0
	ENDC
	ble	return		; cnt <= 0
	move.l	d2,-(sp)	; save d2

	; check overlap
	move.l	a0,d1		; (abs(src - dst)) < cnt =>  overlap
	sub.l	a1,d1
	bge	L1
	neg.l	d1
L1:	cmp.l	d1,d0
	bgt	overlap

	; check for odd src or dst
	move.w	a0,d1
	move.w	a1,d2
	eor.b	d1,d2
	btst	#0,d2
	bne	oddeven
	btst	#0,d1
	beq	eveneven
	move.b	(a0)+,(a1)+	; odd  odd
	subq.l	#1,d0		; now even even 

eveneven:			; may want long alignment for 020/030 etc
	move.l	d0,d1
	and.b	#$1c,d1		; 4 bytes/copy  32 bytes max/iter
	lsr.l	#1,d1		; calc index into loop (each move.l == 2bytes)
	neg.l	d1		;  
	add.l	#18,d1		; 16 + 2 bytes for jmp ext word - d1 == index
	jmp	0(pc,d1)	;  dive into loop at appro spot
loop1:
	move.l	(a0)+,(a1)+
	move.l	(a0)+,(a1)+
	move.l	(a0)+,(a1)+
	move.l	(a0)+,(a1)+

	move.l	(a0)+,(a1)+
	move.l	(a0)+,(a1)+
	move.l	(a0)+,(a1)+
	move.l	(a0)+,(a1)+

	sub.l	#32,d0
	bge	loop1

	btst	#1,d0
	beq	L4
	move.w	(a0)+,(a1)+	; residual word
L4:	btst	#0,d0
	beq	ret
	move.b	(a0),(a1)		; residual byte

ret:	move.l	(sp)+,d2
return:	rts

oddeven:
upcopy:				; byte-by-byte forward
	subq.l	#1,d0
	blt	ret
	move.b	(a0)+,(a1)+
	bra	upcopy

overlap:
	cmp.l	a0,a1
	bmi	upcopy		; (src > dst) go do byte/byte forward copy
	add.l	d0,a0		; otherwise backwards copy
	add.l	d0,a1		; note we use predec so 1 is not sub from addr

downcopy:			; byte-by-byte backward
	subq.l	#1,d0
	blt	ret
	move.b	-(a0),-(a1)
	bra	downcopy
	end
