/*  host3210.S -- Host-dependent optimized subroutines for AIS-3210
 *  copyright (c)
 *	Daniel Steinberg
 *	February, 1984
 *
 *	AIS/UNIX-System V.2  code format
 *
 */
	.file	"host3210.S"

#include "3200config.h"

	.text

/*  blk_to (from, to, bcnt)
 *	in:	from		ptr to source buffer
 *	in:	to		ptr to destination buffer (in host)
 *	in:	bcnt		number of bytes to transfer
 *	return:	(NONE)
 *	thrown:	(NONE)
 *
 *	Copies the source to destination buffer, using only byte and word
 *	transfers, maintaining even alignment of the destination buffer.
 *	This means that no word accesses to odd addresses are permitted to
 *	the destination buffer.
 */
	.globl	_blk_to
_blk_to:
	enter	[r3],$0		/* Save r3 working register */
	movd	8(fp),r1	/* Get 'from' source ptr */
	movd	12(fp),r2	/* Get 'to' destination ptr */
	tbitd	$0,r2		/* Set F-bit if odd destination address */
	br	align		/* and merge with blk_from() below */


/*  blk_from (from, to, bcnt)
 *	in:	from		ptr to source buffer (in host)
 *	in:	to		ptr to destination buffer
 *	in:	bcnt		number of bytes to transfer
 *	return:	(NONE)
 *	thrown:	(NONE)
 *
 *	Copies the source to destination buffer, using only byte and word
 *	transfers, maintaining even alignment of the source buffer.
 *	This means that no word accesses to odd addresses are permitted from
 *	the source buffer.
 */
	.globl	_blk_from
_blk_from:
	enter	[r3],$0		/* Save r3 working register */
	movd	8(fp),r1	/* Get 'from' source ptr */
	movd	12(fp),r2	/* Get 'to' destination ptr */
	tbitd	$0,r1		/* Set F-bit if odd source address */
align:
		/*** TEMPORARY ***/
	movqb	$HOST_MEMENABLE,@(UART_MAPENABLE + U_SETOUT)	/* enable */

	movd	16(fp),r0	/* Get 'bcnt' transfer size */
	bfc	alignd		/* Skip if host buffer is word-aligned */
	movb	0(r1),0(r2)	/* Copy one byte to even the score */
	addqd	$-1,r0		/* Adjust the byte count */

alignd:
	movzbd	$16,r3		/* Maximum number of bytes in a Move Multiple */
	subd	r3,r0		/* Enough room for a block move? */
	bcs	mvlast		/* No....skip to final moves */
movmul:
	movmw	0(r1),0(r2),$8	/* Move 8 words from source to destination */
	addd	r3,r1		/* Adjust pointers */
	addd	r3,r2
	subd	r3,r0		/* Adjust byte count */
	bcc	movmul		/* and loop */

mvlast:
	addd	r3,r0		/* Re-adjust from previous subtract */
	movd	r0,r3		/* Copy last count */
	lshd	$-1,r0		/* Convert byte count to word count */
	cmpqd	$0,r0		/* Anything left to do? */
	beq	lstbyt		/* Nothing but the final byte, if any */
	movsw			/* Copy r0 words from r1 to r2 */
lstbyt:
	tbitd	$0,r3		/* Odd remainder byte count? */
	bfc	done		/* No....block is moved */
	movb	0(r1),0(r2)	/* Yes...move the last character */
done:
		/*** TEMPORARY ***/
	movqb	$HOST_MEMENABLE,@(UART_MAPENABLE + U_CLROUT)	/* disable */

	exit	[r3]		/* Restore working register */
	ret	$0		/* And return to caller */
