********************************************************************
; BORROWED FROM SUPLIB32 (C) Mathew Dillon
; these are optimized byte operation routines
; TABS to 4
; Assemble with genam (devpac) 3 or similar
; 680x0 compatible routines
********************************************************************
		OPT		o+			;optimize
		OPT		l+			;link

		xdef	_dbcmp	    ; compare two blocks of memory
		xdef	_dbmov		; optimized proc'r move
		xdef	_dbset		; Set a block of memory to (byte val)
		xdef	_dbzero		; Zero a block of memory

********************************************************************
_dbcmp	;   BCMP(src:a0, dst:a1, len:d0)
********************************************************************
		tst.l		d0
		beq.s		db_csucc
		cmp.w		D0,D0							;set Z bit
		bra.s		db_c2
db_c1	cmp.b		(A0)+,(A1)+
db_c2	dbne		D0,db_c1
		bne.s		db_cfail
		sub.l		#$10000,D0						;handle > 32Kb
		bcc.s		db_c1
db_csucc
		moveq.l 	#1,D0
		rts
db_cfail
		moveq.l 	#0,D0
		rts


********************************************************************
_dbmov	;   BMOV(src:a0, dst:a1, len:d0)
********************************************************************
		cmp.l		A0,A1							;direction ?
		beq			db_mend
		bls.s		db_mup
; COPY DESCENDING
db_mdown
		adda.l		D0,A0							;descending copy
		adda.l		D0,A1
		move.w		A0,D1							;CHECK WORD ALIGNED
		btst.l		#0,D1
		bne.s		db_mdown1
		move.w		A1,D1
		btst.l		#0,D1
		bne.s		db_mdown1
		cmp.l		#259,D0 						;chosen by calculation.
		blo.s		db_mdown8

		move.l		D0,D1							;overhead for bmd44: ~360
		divu.w		#44,D1
		bvs.s		db_mdown8						;too big (> 2,883,540)
		movem.l		D2-D7/A2-A6,-(sp)				;use D2-D7/A2-A6 (11 regs)
		moveq.l		#11*4,D0
		bra.s		db_md44b
db_md44a
		sub.l		D0,A0							;8 total 214/44bytes
		movem.l		(A0),D2-D7/A2-A6				;12 + 8*11  4.86 cycles/byte
		movem.l		D2-D7/A2-A6,-(A1)				; 8 + 8*11
db_md44b
		dbf.w		D1,db_md44a						;10
		swap		D1								;D0<15:7> already contain 0
		move.w		D1,D0							;D0 = remainder
		movem.l		(sp)+,D2-D7/A2-A6
db_mdown8
		move.w		D0,D1							;D1<2:0> = #bytes left later
		lsr.l		#3,D0							;divide by 8
		bra.s		db_md8b
db_md8a	move.l		-(A0),-(A1)						;20 total 50/8bytes
		move.l		-(A0),-(A1)						;20 = 6.25 cycles/byte
db_md8b	dbf.w		D0,db_md8a						;10
		sub.l		#$10000,D0
		bcc.s		db_md8a
		move.w		D1,D0							;D0 = 0 to 7 bytes
		and.l		#7,D0
		bne.s		db_mdown1
		rts
db_md1a	
		move.b		-(A0),-(A1)						;12 total 22/byte
db_mdown1
db_md1b	dbf.w		D0,db_md1a						;10
		sub.l		#$10000,D0
		bcc.s		db_md1a
		rts
; COPY ASCENDING
db_mup	move.w		A0,D1							;CHECK WORD ALIGNED
		btst.l		#0,D1
		bne.s		db_mup1
		move.w		A1,D1
		btst.l		#0,D1
		bne.s		db_mup1
		cmp.l		#259,D0							;chosen by calculation
		blo.s		db_mup8
		move.l		D0,D1							;overhead for bmu44: ~360
		divu		#44,D1
		bvs.s		db_mup8							;too big (> 2,883,540)
		movem.l		D2-D7/A2-A6,-(sp)				;use D2-D7/A2-A6 (11 regs)
		moveq.l		#11*4,D0
		bra.s		db_mu44b
db_mu44a
		movem.l 	(A0)+,D2-D7/A2-A6				;12 + 8*11 214/44bytes
		movem.l 	D2-D7/A2-A6,(A1)				;8  + 8*11  4.86 cycles/byte
		add.l		D0,A1							;8
db_mu44b
		dbf.w		D1,db_mu44a						;10
		swap		D1								;D0<15:7> already contain 0
		move.w		D1,D0							;D0 = remainder
		movem.l		(sp)+,D2-D7/A2-A6
db_mup8	move.w		D0,D1							;D1<2:0> = #bytes left later
		lsr.l		#3,D0							;divide by 8
		bra.s		db_mu8b
db_mu8a	move.l		(A0)+,(A1)+						;20 total 50/8bytes
		move.l		(A0)+,(A1)+						;20 = 6.25 cycles/byte
db_mu8b	dbf.w		D0,db_mu8a						;10
		sub.l		#$10000,D0
		bcc.s		db_mu8a
		move.w		D1,D0							;D0 = 0 to 7 bytes
		and.l		#7,D0
		bne.s		db_mup1
		rts
db_mu1a	move.b		(A0)+,(A1)+
db_mup1
db_mu1b	dbf.w		D0,db_mu1a
		sub.l		#$10000,D0
		bcc.s		db_mu1a
db_mend	rts




********************************************************************
_dbzero:	;   BZERO(buffer:a0, len)
********************************************************************
		moveq.l		#0,D1
********************************************************************
_dbset:	;   BSET(buffer:a0, len:d0, byte:d1)
********************************************************************
db_z0
		add.l		D0,A0							;start at end of address
		cmp.l		#40,D0							;unscientifically chosen
		bls.s		db_s2
		bra.s		db_s10
db_s1	move.b		D1,-(A0)
db_s2	dbf.w		D0,db_s1						;any count < 65536
		rts
; at least 2 bytes in count (D0)
db_s10	movem.l		D2-D7/A2-A6,-(sp)				;ant count > 4
		move.l		A0,D2
		btst.l		#0,D2							;is it aligned?
		beq.s		db_s22
		move.b		D1,-(A0)						;no, copy one byte
		subq.l		#1,D0
db_s22	andi.l		#$FF,D1							;expand data D1.B -> D2-D7/A1-A6
		move.l		D1,D2							;D1 000000xx   D2 000000xx
		asl.w		#8,D2							;				  0000xx00
		or.w		D2,D1							;	0000xxxx
		move.w		D1,D2							;	0000xxxx      0000xxxx
		swap		D2								;	0000xxxx      xxxx0000
		or.l		D1,D2							;D2.L
		move.l		D2,D3
		move.l		D2,D4
		move.l		D2,D5
		move.l		D2,D6
		move.l		D2,D7
		move.l		D2,A1
		move.l		D2,A2
		move.l		D2,A3
		move.l		D2,A4
		move.l		D2,A5
		move.l		D2,A6							;D2-D7/A1-A6 (12 registers)
		moveq.l		#12*4,D1						;bytes per transfer (48)
db_s30	sub.l		D1,D0							;pre subtract
		bmi.s		db_s40
db_s31	movem.l		D2-D7/A1-A6,-(A0)
		sub.l		D1,D0
		bpl.s		db_s31
db_s40	add.w		D1,D0							;less than 48 bytes remaining
		move.w		#4,D1							;by 4's
		sub.w		D1,D0
		bmi.s		db_s50
db_s41	move.l		D2,-(A0)
		sub.w		D1,D0
		bpl.s		db_s41
db_s50	add.w		D1,D0
		bra.s		db_s52
db_s51	move.b		D2,-(A0)						;by 1's
db_s52	dbf.w		D0,db_s51
		movem.l		(sp)+,D2-D7/A2-A6
		rts

