xref: /csrg-svn/lib/libm/tahoe/support.s (revision 42658)
134128Sbostic/*
231840Szliu * Copyright (c) 1987 Regents of the University of California.
334128Sbostic * All rights reserved.
434128Sbostic *
5*42658Sbostic * %sccs.include.redist.c%
634128Sbostic *
734128Sbostic * All recipients should regard themselves as participants in an ongoing
834128Sbostic * research project and hence should feel obligated to report their
934128Sbostic * experiences (good or bad) with these elementary function codes, using
1034128Sbostic * the sendbug(8) program, to the authors.
1131840Szliu */
1231840Szliu	.data
1331840Szliu	.align	2
1431840Szliu_sccsid:
15*42658Sbostic	.asciz	"@(#)support.s	5.5	(ucb.elefunt)	06/01/90"
1631840Szliu/*
1731840Szliu * copysign(x,y),
1831840Szliu * logb(x),
1931840Szliu * scalb(x,N),
2031840Szliu * finite(x),
2131840Szliu * drem(x,y),
2231840Szliu * Coded in vax assembly language by K. C. Ng 4/9/85.
2331840Szliu * Re-coded in tahoe assembly language by Z. Alex Liu 7/13/87.
2431840Szliu */
2531840Szliu/*
2631840Szliu * double copysign(x,y)
2731840Szliu * double x,y;
2831840Szliu */
2931840Szliu	.globl	_copysign
3031840Szliu	.text
3131842Szliu	.align	2
3231840Szliu_copysign:
3331840Szliu	.word	0x0004			# save r2
3431840Szliu	movl	8(fp),r1
3531840Szliu	movl	4(fp),r0		# r0:r1 = x
3631840Szliu	andl3	$0x7f800000,r0,r2	# r2 = biased exponent of x
3731840Szliu	beql	1f			# if 0 or reserved op then return x
3831840Szliu	andl3	$0x80000000,12(fp),r2	# r2 = sign bit of y at bit-31
3931840Szliu	andl2	$0x7fffffff,r0		# replace x by |x|
4031840Szliu	orl2	r2,r0			# copy the sign bit of y to x
4131840Szliu1:	ret
4231840Szliu/*
4331840Szliu * double logb(x)
4431840Szliu * double x;
4531840Szliu */
4631840Szliu	.globl	_logb
4731840Szliu	.text
4831842Szliu	.align	2
4931840Szliu_logb:
5031842Szliu	.word	0x0000			# save nothing
5131840Szliu	andl3	$0x7f800000,4(fp),r0	# r0[b23:b30] = biased exponent of x
5231840Szliu	beql    1f
5331840Szliu	shrl	$23,r0,r0		# r0[b0:b7] = biased exponent of x
5431840Szliu	subl2	$129,r0			# r0 = unbiased exponent of x
5531840Szliu	cvld	r0			# acc = unbiased exponent of x (double)
5631840Szliu	std	r0			# r0 =  unbiased exponent of x (double)
5731840Szliu	ret
5831840Szliu1:	movl	8(fp),r1		# 8(fp) must be moved first
5931840Szliu	movl	4(fp),r0		# r0:r1 = x (zero or reserved op)
6031840Szliu	blss	2f			# simply return if reserved op
6131840Szliu	movl	$0xfe000000,r1
6231840Szliu	movl	$0xcfffffff,r0		# -2147483647.0
6331840Szliu2:	ret
6431840Szliu/*
6531840Szliu * long finite(x)
6631840Szliu * double x;
6731840Szliu */
6831840Szliu	.globl	_finite
6931840Szliu	.text
7031842Szliu	.align	2
7131840Szliu_finite:
7231842Szliu	.word	0x0000			# save nothing
7331840Szliu	andl3	$0xff800000,4(fp),r0	# r0 = sign of x & its biased exponent
7431840Szliu	cmpl	r0,$0x80000000		# is x a reserved op?
7531840Szliu	beql	1f			# if so, return FALSE (0)
7631840Szliu	movl	$1,r0			# else return TRUE (1)
7731840Szliu	ret
7831840Szliu1:	clrl	r0
7931840Szliu	ret
8031840Szliu/*
8131840Szliu * double scalb(x,N)
8231840Szliu * double x; int N;
8331840Szliu */
8431840Szliu	.globl	_scalb
8531840Szliu	.set	ERANGE,34
8631840Szliu	.text
8731842Szliu	.align	2
8831840Szliu_scalb:
8931842Szliu	.word	0x000c			# save r2-r3
9031840Szliu	movl	8(fp),r1
9131840Szliu	movl	4(fp),r0		# r0:r1 = x (-128 <= Ex <= 126)
9231840Szliu	andl3	$0x7f800000,r0,r3	# r3[b23:b30] = biased exponent of x
9331840Szliu	beql	1f			# is x a 0 or a reserved operand?
9431840Szliu	movl	12(fp),r2		# r2 = N
9531840Szliu	cmpl	r2,$0xff		# if N >= 255
9631840Szliu	bgeq	2f			# then the result must overflow
9731840Szliu	cmpl	r2,$-0xff		# if N <= -255
9831840Szliu	bleq	3f			# then the result must underflow
9931840Szliu	shrl	$23,r3,r3		# r3[b0:b7] = biased exponent of x
10031840Szliu	addl2	r2,r3			# r3 = biased exponent of the result
10131840Szliu	bleq	3f			# if <= 0 then the result underflows
10231840Szliu	cmpl	r3,$0x100		# if >= 256 then the result overflows
10331840Szliu	bgeq	2f
10431840Szliu	shll	$23,r3,r3		# r3[b23:b30] = biased exponent of res.
10531840Szliu	andl2	$0x807fffff,r0
10631840Szliu	orl2	r3,r0			# r0:r1 = x*2^N
10731840Szliu1:	ret
10831840Szliu2:	pushl	$ERANGE			# if the result would overflow
10931840Szliu	callf	$8,_infnan		# and _infnan returns
11031840Szliu	andl3	$0x80000000,4(fp),r2	# get the sign of input arg
11131840Szliu	orl2	r2,r0			# re-attach the sign to r0:r1
11231840Szliu	ret
11331840Szliu3:	clrl	r1			# if the result would underflow
11431840Szliu	clrl	r0			# then return 0
11531840Szliu	ret
11631840Szliu/*
11731840Szliu * double drem(x,y)
11831840Szliu * double x,y;
11931840Szliu * Returns x-n*y where n=[x/y] rounded (to even in the half way case).
12031840Szliu */
12131840Szliu	.globl	_drem
12231840Szliu	.set	EDOM,33
12331840Szliu	.text
12431842Szliu	.align	2
12531840Szliu_drem:
12631840Szliu	.word	0x1ffc			# save r2-r12
12731840Szliu	movl	16(fp),r3
12831840Szliu	movl	12(fp),r2		# r2:r3 = y
12931840Szliu	movl	8(fp),r1
13031840Szliu	movl	4(fp),r0		# r0:r1 = x
13131840Szliu	andl3	$0xff800000,r0,r4
13231840Szliu	cmpl	r4,$0x80000000		# is x a reserved operand?
13331840Szliu	beql	1f			# if yes then propagate x and return
13431840Szliu	andl3	$0xff800000,r2,r4
13531840Szliu	cmpl	r4,$0x80000000		# is y a reserved operand?
13631840Szliu	bneq	2f
13731840Szliu	movl	r3,r1
13831840Szliu	movl	r2,r0			# if yes then propagate y and return
13931840Szliu1:	ret
14031840Szliu
14131840Szliu2:	tstl	r4			# is y a 0?
14231840Szliu	bneq	3f
14331840Szliu	pushl	$EDOM			# if so then generate reserved op fault
14431840Szliu	callf	$8,_infnan
14531840Szliu	ret
14631840Szliu
14731840Szliu3:	andl2	$0x7fffffff,r2		# r2:r3 = y <- |y|
14831840Szliu	clrl	r12			# r12 = nx := 0
14931840Szliu	cmpl	r2,$0x1c800000		# Ey ? 57
15031840Szliu	bgtr	4f			# if Ey > 57 goto 4
15131840Szliu	addl2	$0x1c800000,r2		# scale up y by 2**57
15231840Szliu	movl	$0x1c800000,r12		# r12[b23:b30] = nx = 57
15331840Szliu4:	pushl	r12			# pushed onto stack: nf := nx
15431840Szliu	andl3	$0x80000000,r0,-(sp)	# pushed onto stack: sign of x
15531840Szliu	andl2	$0x7fffffff,r0		# r0:r1 = x <- |x|
15631840Szliu	movl	r3,r11			# r10:r11 = y1 = y w/ last 27 bits 0
15731840Szliu	andl3	$0xf8000000,r10,r11	# clear last 27 bits of y1
15831840Szliu
15931840SzliuLoop:	cmpd2	r0,r2			# x ? y
16031840Szliu	bleq	6f			# if x <= y goto 6
16131840Szliu /* 					# begin argument reduction */
16231840Szliu	movl	r3,r5
16331840Szliu	movl	r2,r4			# r4:r5 = t = y
16431840Szliu	movl	r11,r7
16531840Szliu	movl	r10,r6			# r6:r7 = t1 = y1
16631840Szliu	andl3	$0x7f800000,r0,r8	# r8[b23:b30] = Ex:biased exponent of x
16731840Szliu	andl3	$0x7f800000,r2,r9	# r9[b23:b30] = Ey:biased exponent of y
16831840Szliu	subl2	r9,r8			# r8[b23:b30] = Ex-Ey
16931840Szliu	subl2	$0x0c800000,r8		# r8[b23:b30] = k = Ex-Ey-25
17031840Szliu	blss	5f			# if k < 0 goto 5
17131840Szliu	addl2	r8,r4			# t += k
17231840Szliu	addl2	r8,r6			# t1 += k, scale up t and t1
17331840Szliu5:	ldd	r0			# acc = x
17431840Szliu	divd	r4			# acc = x/t
17531840Szliu	cvdl	r8			# r8 = n = [x/t] truncated
17631840Szliu	cvld	r8			# acc = dble(n)
17731840Szliu	std	r8			# r8:r9 = dble(n)
17831840Szliu	ldd	r4			# acc = t
17931840Szliu	subd	r6			# acc = t-t1
18031840Szliu	muld	r8			# acc = n*(t-t1)
18131840Szliu	std	r4			# r4:r5 = n*(t-t1)
18231840Szliu	ldd	r6			# acc = t1
18331840Szliu	muld	r8			# acc = n*t1
18431840Szliu	subd	r0			# acc = n*t1-x
18531840Szliu	negd				# acc = x-n*t1
18631840Szliu	subd	r4			# acc = (x-n*t1)-n*(t-t1)
18731840Szliu	std	r0			# r0:r1 = (x-n*t1)-n*(t-t1)
18831840Szliu	brb	Loop
18931840Szliu
19031840Szliu6:	movl	r12,r6			# r6 = nx
19131840Szliu	beql	7f			# if nx == 0 goto 7
19231840Szliu	addl2	r6,r0			# x <- x*2**57:scale x up by nx
19331840Szliu	clrl	r12			# clear nx
19431840Szliu	brb	Loop
19531840Szliu
19631840Szliu7:	movl	r3,r5
19731840Szliu	movl	r2,r4			# r4:r5 = y
19831840Szliu	subl2	$0x800000,r4		# r4:r5 = y/2
19931840Szliu	cmpd2	r0,r4			# x ? y/2
20031840Szliu	blss	9f			# if x < y/2 goto 9
20131840Szliu	bgtr	8f			# if x > y/2 goto 8
20231840Szliu	ldd	r8			# acc = dble(n)
20331840Szliu	cvdl	r8			# r8 = ifix(dble(n))
20431840Szliu	bbc	$0,r8,9f		# if the last bit is zero, goto 9
20531840Szliu8:	ldd	r0			# acc = x
20631840Szliu	subd	r2			# acc = x-y
20731840Szliu	std	r0			# r0:r1 = x-y
20831840Szliu9:	xorl2	(sp)+,r0		# x^sign (exclusive or)
20931840Szliu	movl	(sp)+,r6		# r6 = nf
21031840Szliu	andl3	$0x7f800000,r0,r8	# r8 = biased exponent of x
21131840Szliu	andl2	$0x807fffff,r0		# r0 = x w/ exponent zapped
21231840Szliu	subl2	r6,r8			# r8 = Ex-nf
21331840Szliu	bgtr	0f			# if Ex-nf > 0 goto 0
21431840Szliu	clrl	r8			# clear r8
21531840Szliu	clrl	r0
21631840Szliu	clrl	r1			# x underflows to zero
21731840Szliu0:	orl2	r8,r0			# put r8 into x's exponent field
21831840Szliu	ret
219