xref: /csrg-svn/lib/libm/tahoe/cabs.s (revision 34128)
1*34128Sbostic#
232004Szliu# Copyright (c) 1987 Regents of the University of California.
3*34128Sbostic# All rights reserved.
432004Szliu#
5*34128Sbostic# Redistribution and use in source and binary forms are permitted
6*34128Sbostic# provided that this notice is preserved and that due credit is given
7*34128Sbostic# to the University of California at Berkeley. The name of the University
8*34128Sbostic# may not be used to endorse or promote products derived from this
9*34128Sbostic# software without specific prior written permission. This software
10*34128Sbostic# is provided ``as is'' without express or implied warranty.
11*34128Sbostic#
12*34128Sbostic# All recipients should regard themselves as participants in an ongoing
13*34128Sbostic# research project and hence should feel obligated to report their
14*34128Sbostic# experiences (good or bad) with these elementary function codes, using
15*34128Sbostic# the sendbug(8) program, to the authors.
16*34128Sbostic#
17*34128Sbostic#	@(#)cabs.s	5.3 (Berkeley) 04/29/88
18*34128Sbostic#
1932004Szliu	.data
2032004Szliu	.align	2
2132004Szliu_sccsid:
22*34128Sbostic.asciz	"@(#)cabs.s	5.3	5.3	(ucb.elefunt)	04/29/88"
2332004Szliu
2432004Szliu# double precision complex absolute value
2532004Szliu# CABS by W. Kahan, 9/7/80.
2632004Szliu# Revised for reserved operands by E. LeBlanc, 8/18/82
2732004Szliu# argument for complex absolute value by reference, *4(fp)
2832004Szliu# argument for cabs and hypot (C fcns) by value, 4(fp)
2932004Szliu# output is in r0:r1
3032004Szliu
3132004Szliu	.text
3232004Szliu	.align	2
3332004Szliu	.globl  _cabs
3432004Szliu	.globl  _hypot
3532004Szliu	.globl	_z_abs
3632004Szliu
3732004Szliu#	entry for c functions cabs and hypot
3832004Szliu_cabs:
3932004Szliu_hypot:
4032004Szliu	.word	0x807c		# save r2-r6, enable floating overflow
4132004Szliu	movl	16(fp),r3
4232004Szliu	movl	12(fp),r2	# r2:3 = y
4332004Szliu	movl	8(fp),r1
4432004Szliu	movl	4(fp),r0	# r0:1 = x
4532004Szliu	brb	1f
4632004Szliu#	entry for Fortran use, call by:   d = abs(z)
4732004Szliu_z_abs:
4832004Szliu	.word	0x807c		# save r2-r6, enable floating overflow
4932004Szliu	movl	4(fp),r4	# indirect addressing is necessary here
5032004Szliu	movl	12(r4),r3	#
5132004Szliu	movl	8(r4),r2	# r2:3 = y
5232004Szliu	movl	4(r4),r1	#
5332004Szliu	movl	(r4),r0		# r0:1 = x
5432004Szliu1:	andl3	$0xff800000,r0,r4	# r4 has signed biased exp of x
5532004Szliu	cmpl	$0x80000000,r4
5632004Szliu	beql	2f		# x is a reserved operand, so return it
5732004Szliu	andl3	$0xff800000,r2,r5	# r5 has signed biased exp of y
5832004Szliu	cmpl	$0x80000000,r5
5932004Szliu	bneq	3f		# y isn't a reserved operand
6032004Szliu	movl	r3,r1
6132004Szliu	movl	r2,r0		# return y if it's reserved
6232004Szliu2:	ret
6332004Szliu
6432004Szliu3:	callf	$4,regs_set	# r0:1 = dsqrt(x^2+y^2)/2^r6
6532004Szliu	addl2	r6,r0		# unscaled cdabs in r0:1
6632004Szliu	jvc	2b		# unless it overflows
6732004Szliu	subl2	$0x800000,r0	# halve r0 to get meaningful overflow
6832004Szliu	ldd	r0
6932004Szliu	addd	r0		# overflow; r0 is half of true abs value
7032004Szliu	ret
7132004Szliu
7232004Szliuregs_set:
7332004Szliu	.word	0x0000
7432004Szliu	andl2	$0x7fffffff,r0	# r0:r1 = dabs(x)
7532004Szliu	andl2	$0x7fffffff,r2	# r2:r3 = dabs(y)
7632004Szliu	cmpl	r0,r2
7732004Szliu	bgeq	4f
7832004Szliu	movl	r1,r5
7932004Szliu	movl	r0,r4
8032004Szliu	movl	r3,r1
8132004Szliu	movl	r2,r0
8232004Szliu	movl	r5,r3
8332004Szliu	movl	r4,r2		# force y's exp <= x's exp
8432004Szliu4:	andl3	$0xff800000,r0,r6	# r6 = exponent(x) + bias(129)
8532004Szliu	beql	5f		# if x = y = 0 then cdabs(x,y) = 0
8632004Szliu	subl2	$0x47800000,r6	# r6 = exponent(x) - 14
8732004Szliu	subl2	r6,r0		# 2^14 <= scaled x < 2^15
8832004Szliu	bitl	$0xff800000,r2
8932004Szliu	beql	5f		# if y = 0 return dabs(x)
9032004Szliu	subl2	r6,r2
9132004Szliu	cmpl	$0x37800000,r2	# if scaled y < 2^-18
9232004Szliu	bgtr	5f		#   return dabs(x)
9332004Szliu	ldd	r0
9432004Szliu	muld	r0
9532004Szliu	std	r0		# r0:1 = scaled x^2
9632004Szliu	ldd	r2
9732004Szliu	muld	r2		# acc = scaled y^2
9832004Szliu	addd	r0
9932004Szliu	std	r0
10032004Szliu	pushl	r1
10132004Szliu	pushl	r0
10232004Szliu	callf	$12,_sqrt	# r0:1 = dsqrt(x^2+y^2)/2^r6
10332004Szliu5:	ret
104