xref: /csrg-svn/lib/libm/tahoe/support.s (revision 31840)
1*31840Szliu/*
2*31840Szliu * Copyright (c) 1987 Regents of the University of California.
3*31840Szliu *
4*31840Szliu * Use and reproduction of this software are granted  in  accordance  with
5*31840Szliu * the terms and conditions specified in  the  Berkeley  Software  License
6*31840Szliu * Agreement (in particular, this entails acknowledgement of the programs'
7*31840Szliu * source, and inclusion of this notice) with the additional understanding
8*31840Szliu * that  all  recipients  should regard themselves as participants  in  an
9*31840Szliu * ongoing  research  project and hence should  feel  obligated  to report
10*31840Szliu * their  experiences (good or bad) with these elementary function  codes,
11*31840Szliu * using "sendbug 4bsd-bugs@BERKELEY", to the authors.
12*31840Szliu */
13*31840Szliu	.data
14*31840Szliu	.align	2
15*31840Szliu_sccsid:
16*31840Szliu	.asciz	"@(#)support.s	1.1	(ucb.elefunt)	07/13/87"
17*31840Szliu/*
18*31840Szliu * copysign(x,y),
19*31840Szliu * logb(x),
20*31840Szliu * scalb(x,N),
21*31840Szliu * finite(x),
22*31840Szliu * drem(x,y),
23*31840Szliu * Coded in vax assembly language by K. C. Ng 4/9/85.
24*31840Szliu * Re-coded in tahoe assembly language by Z. Alex Liu 7/13/87.
25*31840Szliu */
26*31840Szliu/*
27*31840Szliu * double copysign(x,y)
28*31840Szliu * double x,y;
29*31840Szliu */
30*31840Szliu	.globl	_copysign
31*31840Szliu	.text
32*31840Szliu	.align	1
33*31840Szliu_copysign:
34*31840Szliu	.word	0x0004			# save r2
35*31840Szliu	movl	8(fp),r1
36*31840Szliu	movl	4(fp),r0		# r0:r1 = x
37*31840Szliu	andl3	$0x7f800000,r0,r2	# r2 = biased exponent of x
38*31840Szliu	beql	1f			# if 0 or reserved op then return x
39*31840Szliu	andl3	$0x80000000,12(fp),r2	# r2 = sign bit of y at bit-31
40*31840Szliu	andl2	$0x7fffffff,r0		# replace x by |x|
41*31840Szliu	orl2	r2,r0			# copy the sign bit of y to x
42*31840Szliu1:	ret
43*31840Szliu/*
44*31840Szliu * double logb(x)
45*31840Szliu * double x;
46*31840Szliu */
47*31840Szliu	.globl	_logb
48*31840Szliu	.text
49*31840Szliu	.align	1
50*31840Szliu_logb:
51*31840Szliu	.word	0x0000
52*31840Szliu	andl3	$0x7f800000,4(fp),r0	# r0[b23:b30] = biased exponent of x
53*31840Szliu	beql    1f
54*31840Szliu	shrl	$23,r0,r0		# r0[b0:b7] = biased exponent of x
55*31840Szliu	subl2	$129,r0			# r0 = unbiased exponent of x
56*31840Szliu	cvld	r0			# acc = unbiased exponent of x (double)
57*31840Szliu	std	r0			# r0 =  unbiased exponent of x (double)
58*31840Szliu	ret
59*31840Szliu1:	movl	8(fp),r1		# 8(fp) must be moved first
60*31840Szliu	movl	4(fp),r0		# r0:r1 = x (zero or reserved op)
61*31840Szliu	blss	2f			# simply return if reserved op
62*31840Szliu	movl	$0xfe000000,r1
63*31840Szliu	movl	$0xcfffffff,r0		# -2147483647.0
64*31840Szliu2:	ret
65*31840Szliu/*
66*31840Szliu * long finite(x)
67*31840Szliu * double x;
68*31840Szliu */
69*31840Szliu	.globl	_finite
70*31840Szliu	.text
71*31840Szliu	.align	1
72*31840Szliu_finite:
73*31840Szliu	.word	0x0000
74*31840Szliu	andl3	$0xff800000,4(fp),r0	# r0 = sign of x & its biased exponent
75*31840Szliu	cmpl	r0,$0x80000000		# is x a reserved op?
76*31840Szliu	beql	1f			# if so, return FALSE (0)
77*31840Szliu	movl	$1,r0			# else return TRUE (1)
78*31840Szliu	ret
79*31840Szliu1:	clrl	r0
80*31840Szliu	ret
81*31840Szliu/*
82*31840Szliu * double scalb(x,N)
83*31840Szliu * double x; int N;
84*31840Szliu */
85*31840Szliu	.globl	_scalb
86*31840Szliu	.set	ERANGE,34
87*31840Szliu	.text
88*31840Szliu	.align	1
89*31840Szliu_scalb:
90*31840Szliu	.word	0x000c
91*31840Szliu	movl	8(fp),r1
92*31840Szliu	movl	4(fp),r0		# r0:r1 = x (-128 <= Ex <= 126)
93*31840Szliu	andl3	$0x7f800000,r0,r3	# r3[b23:b30] = biased exponent of x
94*31840Szliu	beql	1f			# is x a 0 or a reserved operand?
95*31840Szliu	movl	12(fp),r2		# r2 = N
96*31840Szliu	cmpl	r2,$0xff		# if N >= 255
97*31840Szliu	bgeq	2f			# then the result must overflow
98*31840Szliu	cmpl	r2,$-0xff		# if N <= -255
99*31840Szliu	bleq	3f			# then the result must underflow
100*31840Szliu	shrl	$23,r3,r3		# r3[b0:b7] = biased exponent of x
101*31840Szliu	addl2	r2,r3			# r3 = biased exponent of the result
102*31840Szliu	bleq	3f			# if <= 0 then the result underflows
103*31840Szliu	cmpl	r3,$0x100		# if >= 256 then the result overflows
104*31840Szliu	bgeq	2f
105*31840Szliu	shll	$23,r3,r3		# r3[b23:b30] = biased exponent of res.
106*31840Szliu	andl2	$0x807fffff,r0
107*31840Szliu	orl2	r3,r0			# r0:r1 = x*2^N
108*31840Szliu1:	ret
109*31840Szliu2:	pushl	$ERANGE			# if the result would overflow
110*31840Szliu	callf	$8,_infnan		# and _infnan returns
111*31840Szliu	andl3	$0x80000000,4(fp),r2	# get the sign of input arg
112*31840Szliu	orl2	r2,r0			# re-attach the sign to r0:r1
113*31840Szliu	ret
114*31840Szliu3:	clrl	r1			# if the result would underflow
115*31840Szliu	clrl	r0			# then return 0
116*31840Szliu	ret
117*31840Szliu/*
118*31840Szliu * double drem(x,y)
119*31840Szliu * double x,y;
120*31840Szliu * Returns x-n*y where n=[x/y] rounded (to even in the half way case).
121*31840Szliu */
122*31840Szliu	.globl	_drem
123*31840Szliu	.set	EDOM,33
124*31840Szliu	.text
125*31840Szliu	.align	1
126*31840Szliu_drem:
127*31840Szliu	.word	0x1ffc			# save r2-r12
128*31840Szliu	movl	16(fp),r3
129*31840Szliu	movl	12(fp),r2		# r2:r3 = y
130*31840Szliu	movl	8(fp),r1
131*31840Szliu	movl	4(fp),r0		# r0:r1 = x
132*31840Szliu	andl3	$0xff800000,r0,r4
133*31840Szliu	cmpl	r4,$0x80000000		# is x a reserved operand?
134*31840Szliu	beql	1f			# if yes then propagate x and return
135*31840Szliu	andl3	$0xff800000,r2,r4
136*31840Szliu	cmpl	r4,$0x80000000		# is y a reserved operand?
137*31840Szliu	bneq	2f
138*31840Szliu	movl	r3,r1
139*31840Szliu	movl	r2,r0			# if yes then propagate y and return
140*31840Szliu1:	ret
141*31840Szliu
142*31840Szliu2:	tstl	r4			# is y a 0?
143*31840Szliu	bneq	3f
144*31840Szliu	pushl	$EDOM			# if so then generate reserved op fault
145*31840Szliu	callf	$8,_infnan
146*31840Szliu	ret
147*31840Szliu
148*31840Szliu3:	andl2	$0x7fffffff,r2		# r2:r3 = y <- |y|
149*31840Szliu	clrl	r12			# r12 = nx := 0
150*31840Szliu	cmpl	r2,$0x1c800000		# Ey ? 57
151*31840Szliu	bgtr	4f			# if Ey > 57 goto 4
152*31840Szliu	addl2	$0x1c800000,r2		# scale up y by 2**57
153*31840Szliu	movl	$0x1c800000,r12		# r12[b23:b30] = nx = 57
154*31840Szliu4:	pushl	r12			# pushed onto stack: nf := nx
155*31840Szliu	andl3	$0x80000000,r0,-(sp)	# pushed onto stack: sign of x
156*31840Szliu	andl2	$0x7fffffff,r0		# r0:r1 = x <- |x|
157*31840Szliu	movl	r3,r11			# r10:r11 = y1 = y w/ last 27 bits 0
158*31840Szliu	andl3	$0xf8000000,r10,r11	# clear last 27 bits of y1
159*31840Szliu
160*31840SzliuLoop:	cmpd2	r0,r2			# x ? y
161*31840Szliu	bleq	6f			# if x <= y goto 6
162*31840Szliu /* 					# begin argument reduction */
163*31840Szliu	movl	r3,r5
164*31840Szliu	movl	r2,r4			# r4:r5 = t = y
165*31840Szliu	movl	r11,r7
166*31840Szliu	movl	r10,r6			# r6:r7 = t1 = y1
167*31840Szliu	andl3	$0x7f800000,r0,r8	# r8[b23:b30] = Ex:biased exponent of x
168*31840Szliu	andl3	$0x7f800000,r2,r9	# r9[b23:b30] = Ey:biased exponent of y
169*31840Szliu	subl2	r9,r8			# r8[b23:b30] = Ex-Ey
170*31840Szliu	subl2	$0x0c800000,r8		# r8[b23:b30] = k = Ex-Ey-25
171*31840Szliu	blss	5f			# if k < 0 goto 5
172*31840Szliu	addl2	r8,r4			# t += k
173*31840Szliu	addl2	r8,r6			# t1 += k, scale up t and t1
174*31840Szliu5:	ldd	r0			# acc = x
175*31840Szliu	divd	r4			# acc = x/t
176*31840Szliu	cvdl	r8			# r8 = n = [x/t] truncated
177*31840Szliu	cvld	r8			# acc = dble(n)
178*31840Szliu	std	r8			# r8:r9 = dble(n)
179*31840Szliu	ldd	r4			# acc = t
180*31840Szliu	subd	r6			# acc = t-t1
181*31840Szliu	muld	r8			# acc = n*(t-t1)
182*31840Szliu	std	r4			# r4:r5 = n*(t-t1)
183*31840Szliu	ldd	r6			# acc = t1
184*31840Szliu	muld	r8			# acc = n*t1
185*31840Szliu	subd	r0			# acc = n*t1-x
186*31840Szliu	negd				# acc = x-n*t1
187*31840Szliu	subd	r4			# acc = (x-n*t1)-n*(t-t1)
188*31840Szliu	std	r0			# r0:r1 = (x-n*t1)-n*(t-t1)
189*31840Szliu	brb	Loop
190*31840Szliu
191*31840Szliu6:	movl	r12,r6			# r6 = nx
192*31840Szliu	beql	7f			# if nx == 0 goto 7
193*31840Szliu	addl2	r6,r0			# x <- x*2**57:scale x up by nx
194*31840Szliu	clrl	r12			# clear nx
195*31840Szliu	brb	Loop
196*31840Szliu
197*31840Szliu7:	movl	r3,r5
198*31840Szliu	movl	r2,r4			# r4:r5 = y
199*31840Szliu	subl2	$0x800000,r4		# r4:r5 = y/2
200*31840Szliu	cmpd2	r0,r4			# x ? y/2
201*31840Szliu	blss	9f			# if x < y/2 goto 9
202*31840Szliu	bgtr	8f			# if x > y/2 goto 8
203*31840Szliu	ldd	r8			# acc = dble(n)
204*31840Szliu	cvdl	r8			# r8 = ifix(dble(n))
205*31840Szliu	bbc	$0,r8,9f		# if the last bit is zero, goto 9
206*31840Szliu8:	ldd	r0			# acc = x
207*31840Szliu	subd	r2			# acc = x-y
208*31840Szliu	std	r0			# r0:r1 = x-y
209*31840Szliu9:	xorl2	(sp)+,r0		# x^sign (exclusive or)
210*31840Szliu	movl	(sp)+,r6		# r6 = nf
211*31840Szliu	andl3	$0x7f800000,r0,r8	# r8 = biased exponent of x
212*31840Szliu	andl2	$0x807fffff,r0		# r0 = x w/ exponent zapped
213*31840Szliu	subl2	r6,r8			# r8 = Ex-nf
214*31840Szliu	bgtr	0f			# if Ex-nf > 0 goto 0
215*31840Szliu	clrl	r8			# clear r8
216*31840Szliu	clrl	r0
217*31840Szliu	clrl	r1			# x underflows to zero
218*31840Szliu0:	orl2	r8,r0			# put r8 into x's exponent field
219*31840Szliu	ret
220