dnl  PowerPC-32 mpn_add_n and mpn_sub_n.

dnl  Copyright 2002, 2005, 2007 Free Software Foundation, Inc.

dnl  This file is part of the GNU MP Library.

dnl  The GNU MP Library is free software; you can redistribute it and/or modify
dnl  it under the terms of the GNU Lesser General Public License as published
dnl  by the Free Software Foundation; either version 3 of the License, or (at
dnl  your option) any later version.

dnl  The GNU MP Library is distributed in the hope that it will be useful, but
dnl  WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
dnl  or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
dnl  License for more details.

dnl  You should have received a copy of the GNU Lesser General Public License
dnl  along with the GNU MP Library.  If not, see http://www.gnu.org/licenses/.

include(`../config.m4')

C                cycles/limb
C 603e:              ?
C 604e:              ?		old: 3.25
C 75x (G3):          ?		old: 3.5
C 7400,7410 (G4):    3.25
C 744x,745x (G4+):   4
C power4/ppc970:     ?		old: 2.0
C power5:            ?		old: 2.5

C INPUT PARAMETERS
define(`rp',	`r3')
define(`up',	`r4')
define(`vp',	`r5')
define(`n',	`r6')
define(`cy',	`r7')

ifdef(`OPERATION_add_n', `
	define(ADCSBC,	adde)
	define(func,	mpn_add_n)
	define(func_nc,	mpn_add_nc)
	define(IFADD,	`$1')
	define(IFSUB,	`')')
ifdef(`OPERATION_sub_n', `
	define(ADCSBC,	subfe)
	define(func,	mpn_sub_n)
	define(func_nc,	mpn_sub_nc)
	define(IFADD,	`')
	define(IFSUB,	`$1')')

MULFUNC_PROLOGUE(mpn_add_n mpn_add_nc mpn_sub_n mpn_sub_nc)

ASM_START()

PROLOGUE(func_nc)
IFADD(`	addic	r0, cy, -1')		C set carry from argument
IFSUB(`	subfic	r0, cy, 0')		C set carry from argument
	b	L(ent)
EPILOGUE()

PROLOGUE(func)
IFADD(`	addic	r0, n, 0')		C clear carry
IFSUB(`	addic	r0, n, -1')		C set carry
L(ent):	andi.	r0, n, 3
	addi	r3, r3, -12
	addi	n, n, 1
	cmpwi	cr7, r0, 2
	srwi	r0, n, 2
	sub	r4, r4, r3
	sub	r5, r5, r3
	mtctr	r0
	bne	cr0, L(n00)

	lwzx	r7, r4, r3		C n = 4, 8, 12, ...
	lwzx	r8, r5, r3
	addi	r3, r3, 4
	lwzx	r9, r4, r3
	ADCSBC	r7, r8, r7
	lwzx	r10, r5, r3
	addi	r3, r3, 4
	b	L(00)

L(n00):	bge	cr7, L(n01)
	cmpwi	cr0, r0, 0		C n = 1, 5, 9, 13, ...
	lwzx	r0, r4, r3
	lwzx	r6, r5, r3
	addi	r3, r3, 4
	ADCSBC	r0, r6, r0
	ble	L(ret)
L(gt1):	lwzx	r7, r4, r3
	lwzx	r8, r5, r3
	addi	r3, r3, 4
	b	L(01)

L(n10):
	lwzx	r9, r4, r3		C n = 3, 7, 11, 15, ...
	lwzx	r10, r5, r3
	addi	r3, r3, 4
	lwzx	r11, r4, r3
	ADCSBC	r9, r10, r9
	lwzx	r12, r5, r3
	addi	r3, r3, 4
	b	L(11)

L(n01):	bne	cr7, L(n10)
	cmpwi	cr0, r0, 0		C n = 2, 6, 10, 14, ...
	lwzx	r11, r4, r3
	lwzx	r12, r5, r3
	addi	r3, r3, 4
	lwzx	r0, r4, r3
	ADCSBC	r11, r12, r11
	lwzx	r6, r5, r3
	addi	r3, r3, 4
	ble	cr0, L(end)


L(lp):	lwzx	r7, r4, r3
	ADCSBC	r0, r6, r0
	lwzx	r8, r5, r3
	stwu	r11, 4(r3)
L(01):	lwzx	r9, r4, r3
	ADCSBC	r7, r8, r7
	lwzx	r10, r5, r3
	stwu	r0, 4(r3)
L(00):	lwzx	r11, r4, r3
	ADCSBC	r9, r10, r9
	lwzx	r12, r5, r3
	stwu	r7, 4(r3)
L(11):	lwzx	r0, r4, r3
	ADCSBC	r11, r12, r11
	lwzx	r6, r5, r3
	stwu	r9, 4(r3)
	bdnz	L(lp)

L(end):	ADCSBC	r0, r6, r0
	stw	r11, 4(r3)
L(ret):	stw	r0, 8(r3)
IFADD(`	li	r3, 0	')
IFADD(`	addze	r3, r3	')
IFSUB(`	subfe	r3, r0, r0')
IFSUB(`	neg	r3, r3')
	blr
EPILOGUE()
