/*
* bnialpha.s - DEC Alpha 64-bit math primitives. These use 64-bit words
* unless otherwise noted.
*
* Copyright (C) 1995-1997 Pretty Good Privacy, Inc. All rights reserved.
*
* $Id: bnialpha.s,v 1.4.2.1 1997/06/07 09:49:36 mhw Exp $
*
* The DEC assembler apparently does some instruction scheduling,
* but I tried to do some of my own, and tries to spread things
* out over the register file to give the assembler more room
* to schedule things.
*
* Alpha OSF/1 register usage conventions:
* r0 - v0 - Temp, holds integer return value
* r1..r8 - t0..t7 - Temp, trashed by procedure call
* r9..r14 - s0..s5 - Saved across procedure calls
* r15 - s6/FP - Frame pointer, saved across procedure calls
* r16..r21 - a0..a5 - Argument registers, all trashed by procedure call
* r22..r25 - t8..t11 - Temp, trashed by procedure call
* r26	- ra - Return address
* r27	- t12/pv - Procedure value, trashed by procedure call
* r28		- at	- Assembler temp, trashed by procedure call
* r29		- gp	- Global pointer
* r30		- sp	- Stack pointer
* r31		- zero	- hardwired to zero
*/
			.text
			.align	4
		.globl	bniMulN1_64
/* I have no idea what the '2' at the end of the .ent line means. */
	.ent	bniMulN1_64 2
/*
* Arguments: $16 = out, $17 = in, $18 = len<32>, $19 = k
* Other registers: $0 = carry word, $1 = product low,
* $2 = product high, $3 = input word
*/
bniMulN1_64:
			ldq	$3,0($17)		/* Load first word of input */
			subl	 $18,1,$18
			mulq	 $3,$19,$1		/* Do low half of first multiply */
			umulh	$3,$19,$0		/* Do second half of first multiply */
			stq	$1,0($16)
			beq	$18,m64_done
m64_loop:
			ldq	$3,8($17)
			addq	 $17,8,$17
			mulq	 $3,$19,$1		/* Do bottom half of multiply */
			subl	 $18,1,$18
			umulh	$3,$19,$2		/* Do top half of multiply */
			addq	 $0,$1,$1		/* Add carry word from previous multiply */
			stq	$1,8($16)
			cmpult	$1,$0,$0		/* Compute carry bit from add */
			addq	 $16,8,$16
			addq	 $2,$0,$0		/* Add carry bit to carry word */

beq	 $18,m64_done

			ldq	$3,8($17)
			addq	 $17,8,$17
			mulq	 $3,$19,$1		/* Do bottom half of multiply */
			subl	 $18,1,$18
			umulh	$3,$19,$2		/* Do top half of multiply */
			addq	 $0,$1,$1		/* Add carry word from previous multiply */
			stq	$1,8($16)
			cmpult	$1,$0,$0		/* Compute carry bit from add */
			addq	 $16,8,$16
			addq	 $2,$0,$0		/* Add carry bit to carry word */

			bne	$18,m64_loop
m64_done:
		stq	$0,8($16)			/* Store last word of result */
		ret	$31,($26),1
/* The '1' in the hint field means procedure return - software convention */
			.end bniMulN1_64


			.text
			.align	4
			.globl	bniMulAdd1_64
			.ent	 bniMulAdd1_64 2
/*
* Arguments: $16 = out, $17 = in, $18 = len<32>, $19 = k
* Other registers: $0 = product high, $1 = product low,
* $2 = product high temp, $3 = input word, $4 = output word
* $5 = carry bit from add to out
*/
bniMulAdd1_64:
			ldq	$3,0($17)		/* Load first word of input */
			subl	 $18,1,$18
			mulq	 $3,$19,$1		/* Do low half of first multiply */
			ldq	$4,0($16)		/* Load first word of output */
			umulh	$3,$19,$2		/* Do second half of first multiply */
			addq	 $4,$1,$4
			cmpult	$4,$1,$5		/* Compute borrow bit from subtract */
			stq	$4,0($16)
			addq	 $5,$2,$0		/* Add carry bit to high word */
			beq	$18,ma64_done
ma64_loop:
			ldq	$3,8($17)		/* Load next word of input */
			addq	 $17,8,$17
			ldq	$4,8($16)		/* Load next word of output */
			mulq	 $3,$19,$1		/* Do bottom half of multiply */
			subl	 $18,1,$18
			addq	 $0,$1,$1		/* Add carry word from previous multiply */
			umulh	$3,$19,$2		/* Do top half of multiply */
			cmpult	$1,$0,$0		/* Compute carry bit from add */
			addq	 $4,$1,$4		/* Add product to loaded word */
			cmpult	$4,$1,$5		/* Compute carry bit from add */
			stq	$4,8($16)
			addq	 $5,$0,$5		/* Add carry bits together */
			addq	 $16,8,$16
			addq	 $5,$2,$0		/* Add carry bits to carry word */

			beq	$18,ma64_done

		ldq	$3,8($17)		/* Load next word of input */
		addq	$17,8,$17
		ldq	$4,8($16)		/* Load next word of output */
		mulq	$3,$19,$1		/* Do bottom half of multiply */
		subl	$18,1,$18
		addq	$0,$1,$1		/* Add carry word from previous multiply */
		umulh	 $3,$19,$2		/* Do top half of multiply */
		cmpult	$1,$0,$0		/* Compute carry bit from add */
		addq	$4,$1,$4		/* Add product to loaded word */
		cmpult	$4,$1,$5		/* Compute carry bit from add */
		stq	$4,8($16)
		addq	$5,$0,$5		/* Add carry bits together */
		addq	$16,8,$16
		addq	$5,$2,$0		/* Add carry bits to carry word */

			bne	$18,ma64_loop
ma64_done:
			ret	$31,($26),1
			.end bniMulAdd1_64


.text
.align	4
.globl	bniMulSub1_64
.ent	bniMulSub1_64 2
/*
* Arguments: $16 = out, $17 = in, $18 = len<32>, $19 = k
* Other registers: $0 = carry word, $1 = product low,
* $2 = product high temp, $3 = input word, $4 = output word
* $5 = borrow bit from subtract
*/
bniMulSub1_64:
			ldq	$3,0($17)		/* Load first word of input */
			subl	 $18,1,$18
			mulq	 $3,$19,$1		/* Do low half of first multiply */
			ldq	$4,0($16)		/* Load first word of output */
			umulh	$3,$19,$2		/* Do second half of first multiply */
			cmpult	$4,$1,$5		/* Compute borrow bit from subtract */
			subq	 $4,$1,$4
			addq	 $5,$2,$0		/* Add carry bit to high word */
			stq	$4,0($16)
			beq	$18,ms64_done
ms64_loop:
			ldq	$3,8($17)		/* Load next word of input */
			addq	 $17,8,$17
			ldq	$4,8($16)		/* Load next word of output */
			mulq	 $3,$19,$1		/* Do bottom half of multiply */
			subl	 $18,1,$18
			addq	 $0,$1,$1		/* Add carry word from previous multiply */
			umulh	$3,$19,$2		/* Do top half of multiply */
			cmpult	$1,$0,$0		/* Compute carry bit from add */
			cmpult	$4,$1,$5		/* Compute borrow bit from subtract */
			subq	 $4,$1,$4
			addq	 $5,$0,$5		/* Add carry bits together */
			stq	$4,8($16)
			addq	 $5,$2,$0		/* Add carry bits to carry word */
			addq	 $16,8,$16

			beq	$18,ms64_done

			ldq	$3,8($17)		/* Load next word of input */
			addq	 $17,8,$17
			ldq	$4,8($16)		/* Load next word of output */
			mulq	 $3,$19,$1		/* Do bottom half of multiply */
			subl	 $18,1,$18
			addq	 $0,$1,$1		/* Add carry word from previous multiply */
			umulh	$3,$19,$2		/* Do top half of multiply */
			cmpult	$1,$0,$0		/* Compute carry bit from add */
			cmpult	$4,$1,$5		/* Compute borrow bit from subtract */
			subq	 $4,$1,$4
			addq	 $5,$0,$5		/* Add carry bits together */
			stq	$4,8($16)
			addq	 $5,$2,$0		/* Add carry bits to carry word */
			addq	 $16,8,$16

			bne	$18,ms64_loop
ms64_done:
	ret	$31,($26),1
	.end bniMulSub1_64
