xref: /csrg-svn/lib/libm/national/support.s (revision 26460)
1*26460Selefunt; @(#)support.s	1.1 (ucb.elefunt) 03/04/86
2*26460Selefunt;
3*26460Selefunt; IEEE recommended functions
4*26460Selefunt;
5*26460Selefunt;
6*26460Selefunt; double copysign(x,y)
7*26460Selefunt; double x,y;
8*26460Selefunt; IEEE 754 recommended function, return x*sign(y)
9*26460Selefunt; Coded by K.C. Ng in National 32k assembler, 11/9/85.
10*26460Selefunt;
11*26460Selefunt	.vers	2
12*26460Selefunt	.text
13*26460Selefunt	.align	2
14*26460Selefunt	.globl	_copysign
15*26460Selefunt_copysign:
16*26460Selefunt	movl	4(sp),f0
17*26460Selefunt	movd	8(sp),r0
18*26460Selefunt	movd	16(sp),r1
19*26460Selefunt	xord	r0,r1
20*26460Selefunt	ord	0x80000000,r1
21*26460Selefunt	cmpqd	0,r1
22*26460Selefunt	beq	end
23*26460Selefunt	negl	f0,f0
24*26460Selefuntend:	ret	0
25*26460Selefunt
26*26460Selefunt;
27*26460Selefunt; double logb(x)
28*26460Selefunt; double x;
29*26460Selefunt; IEEE p854 recommended function, return the exponent of x (return float(N)
30*26460Selefunt; such that 1 <= x*2**-N < 2, even for subnormal number.
31*26460Selefunt; Coded by K.C. Ng in National 32k assembler, 11/9/85.
32*26460Selefunt; Note: subnormal number (if implemented) will be taken care of.
33*26460Selefunt;
34*26460Selefunt	.vers	2
35*26460Selefunt	.text
36*26460Selefunt	.align	2
37*26460Selefunt	.globl	_logb
38*26460Selefunt_logb:
39*26460Selefunt;
40*26460Selefunt; extract the exponent of x
41*26460Selefunt; glossaries:	r0 = high part of x
42*26460Selefunt;		r1 = unbias exponent of x
43*26460Selefunt;		r2 = 20 (first exponent bit position)
44*26460Selefunt;
45*26460Selefunt	movd	8(sp),r0
46*26460Selefunt	movd	20,r2
47*26460Selefunt	extd	r2,r0,r1,11	; extract the exponent of x
48*26460Selefunt	cmpqd	0,r1		; if exponent bits = 0, goto L3
49*26460Selefunt	beq	L3
50*26460Selefunt	cmpd	0x7ff,r1
51*26460Selefunt	beq	L2		; if exponent bits = 0x7ff, goto L2
52*26460SelefuntL1:	subd	1023,r1		; unbias the exponent
53*26460Selefunt	movdl	r1,f0		; convert the exponent to floating value
54*26460Selefunt	ret	0
55*26460Selefunt;
56*26460Selefunt; x is INF or NaN, simply return x
57*26460Selefunt;
58*26460SelefuntL2:
59*26460Selefunt	movl	4(sp),f0	; logb(+inf)=+inf, logb(NaN)=NaN
60*26460Selefunt	ret	0
61*26460Selefunt;
62*26460Selefunt; x is 0 or subnormal
63*26460Selefunt;
64*26460SelefuntL3:
65*26460Selefunt	movl	4(sp),f0
66*26460Selefunt	cmpl	0f0,f0
67*26460Selefunt	beq	L5		; x is 0 , goto L5 (return -inf)
68*26460Selefunt;
69*26460Selefunt; Now x is subnormal
70*26460Selefunt;
71*26460Selefunt	mull	L64,f0		; scale up f0 with 2**64
72*26460Selefunt	movl	f0,tos
73*26460Selefunt	movd	tos,r0
74*26460Selefunt	movd	tos,r0		; now r0 = new high part of x
75*26460Selefunt	extd	r2,r0,r1,11	; extract the exponent of x to r1
76*26460Selefunt	subd	1087,r1		; unbias the exponent with correction
77*26460Selefunt	movdl	r1,f0		; convert the exponent to floating value
78*26460Selefunt	ret	0
79*26460Selefunt;
80*26460Selefunt; x is 0, return logb(0)= -INF
81*26460Selefunt;
82*26460SelefuntL5:
83*26460Selefunt	movl	0f1.0e300,f0
84*26460Selefunt	mull	0f-1.0e300,f0	; multiply two big numbers to get -INF
85*26460Selefunt	ret	0
86*26460SelefuntL64:	.double	0,0x43f00000	; L64=2**64
87*26460Selefunt
88*26460Selefunt;
89*26460Selefunt; double rint(x)
90*26460Selefunt; double x;
91*26460Selefunt; ... delivers integer nearest x in direction of prevailing rounding
92*26460Selefunt; ... mode
93*26460Selefunt; Coded by K.C. Ng in National 32k assembler, 11/9/85.
94*26460Selefunt; Note: subnormal number (if implemented) will be taken care of.
95*26460Selefunt;
96*26460Selefunt	.vers	2
97*26460Selefunt	.text
98*26460Selefunt	.align	2
99*26460Selefunt	.globl	_rint
100*26460Selefunt_rint:
101*26460Selefunt;
102*26460Selefunt	movd	8(sp),r0
103*26460Selefunt	movd	20,r2
104*26460Selefunt	extd	r2,r0,r1,11	; extract the exponent of x
105*26460Selefunt	cmpd	0x433,r1
106*26460Selefunt	ble	itself
107*26460Selefunt	movl	L52,f2		; f2 = L = 2**52
108*26460Selefunt	cmpqd	0,r0
109*26460Selefunt	ble	L1
110*26460Selefunt	negl	f2,f2		; f2 = s = copysign(L,x)
111*26460SelefuntL1:	addl	f2,f0		; f0 = x + s
112*26460Selefunt	subl	f2,f0		; f0 = f0 - s
113*26460Selefunt	ret	0
114*26460Selefuntitself:	movl	4(sp),f0
115*26460Selefunt	ret	0
116*26460SelefuntL52:	.double	0x0,0x43300000	; L52=2**52
117*26460Selefunt;
118*26460Selefunt; int finite(x)
119*26460Selefunt; double x;
120*26460Selefunt; IEEE 754 recommended function, return 0 if x is NaN or INF, else 0
121*26460Selefunt; Coded by K.C. Ng in National 32k assembler, 11/9/85.
122*26460Selefunt;
123*26460Selefunt	.vers	2
124*26460Selefunt	.text
125*26460Selefunt	.align	2
126*26460Selefunt	.globl	_finite
127*26460Selefunt_finite:
128*26460Selefunt	movd	4(sp),r1
129*26460Selefunt	andd	0x800fffff,r1
130*26460Selefunt	cmpd	0x7ff00000,r1
131*26460Selefunt	sned	r0		; r0=0 if exponent(x) = 0x7ff
132*26460Selefunt	ret	0
133*26460Selefunt;
134*26460Selefunt; double scalb(x,N)
135*26460Selefunt; double x; int N;
136*26460Selefunt; IEEE 754 recommended function, return x*2**N by adjusting
137*26460Selefunt; exponent of x.
138*26460Selefunt; Coded by K.C. Ng in National 32k assembler, 11/9/85.
139*26460Selefunt; Note: subnormal number (if implemented) will be taken care of
140*26460Selefunt;
141*26460Selefunt	.vers	2
142*26460Selefunt	.text
143*26460Selefunt	.align	2
144*26460Selefunt	.globl	_scalb
145*26460Selefunt_scalb:
146*26460Selefunt;
147*26460Selefunt; if x=0 return 0
148*26460Selefunt;
149*26460Selefunt	movl	4(sp),f0
150*26460Selefunt	cmpl	0f0,f0
151*26460Selefunt	beq	end		; scalb(0,N) is x itself
152*26460Selefunt;
153*26460Selefunt; extract the exponent of x
154*26460Selefunt; glossaries:	r0 = high part of x,
155*26460Selefunt;		r1 = unbias exponent of x,
156*26460Selefunt;		r2 = 20 (first exponent bit position).
157*26460Selefunt;
158*26460Selefunt	movd	8(sp),r0	; r0 = high part of x
159*26460Selefunt	movd	20,r2		; r2 = 20
160*26460Selefunt	extd	r2,r0,r1,11	; extract the exponent of x in r1
161*26460Selefunt	cmpd	0x7ff,r1
162*26460Selefunt;
163*26460Selefunt; if exponent of x is 0x7ff, then x is NaN or INF; simply return x
164*26460Selefunt;
165*26460Selefunt	beq	end
166*26460Selefunt	cmpqd	0,r1
167*26460Selefunt;
168*26460Selefunt; if exponent of x is zero, then x is subnormal; goto L19
169*26460Selefunt;
170*26460Selefunt	beq	L19
171*26460Selefunt	addd	12(sp),r1	; r1 = (exponent of x) + N
172*26460Selefunt	bfs	inof		; if integer overflows, goto inof
173*26460Selefunt	cmpqd	0,r1		; if new exponent <= 0, goto underflow
174*26460Selefunt	bge	underflow
175*26460Selefunt	cmpd	2047,r1		; if new exponent >= 2047 goto overflow
176*26460Selefunt	ble	overflow
177*26460Selefunt	insd	r2,r1,r0,11	; insert the new exponent
178*26460Selefunt	movd	r0,tos
179*26460Selefunt	movd	8(sp),tos
180*26460Selefunt	movl	tos,f0		; return x*2**N
181*26460Selefuntend:	ret	0
182*26460Selefuntinof:	bcs	underflow	; negative int overflow if Carry bit is set
183*26460Selefuntoverflow:
184*26460Selefunt	andd	0x80000000,r0	; keep the sign of x
185*26460Selefunt	ord	0x7fe00000,r0	; set x to a huge number
186*26460Selefunt	movd	r0,tos
187*26460Selefunt	movqd	0,tos
188*26460Selefunt	movl	tos,f0
189*26460Selefunt	mull	0f1.0e300,f0	; multiply two huge number to get overflow
190*26460Selefunt	ret	0
191*26460Selefuntunderflow:
192*26460Selefunt	addd	64,r1		; add 64 to exonent to see if it is subnormal
193*26460Selefunt	cmpqd	0,r1
194*26460Selefunt	bge	zero		; underflow to zero
195*26460Selefunt	insd	r2,r1,r0,11	; insert the new exponent
196*26460Selefunt	movd	r0,tos
197*26460Selefunt	movd	8(sp),tos
198*26460Selefunt	movl	tos,f0
199*26460Selefunt	mull	L30,f0		; readjust x by multiply it with 2**-64
200*26460Selefunt	ret	0
201*26460Selefuntzero:	andd	0x80000000,r0	; keep the sign of x
202*26460Selefunt	ord	0x00100000,r0	; set x to a tiny number
203*26460Selefunt	movd	r0,tos
204*26460Selefunt	movqd	0,tos
205*26460Selefunt	movl	tos,f0
206*26460Selefunt	mull	0f1.0e-300,f0	; underflow to 0  by multipling two tiny nos.
207*26460Selefunt	ret	0
208*26460SelefuntL19:		; subnormal number
209*26460Selefunt	mull	L32,f0		; scale up x by 2**64
210*26460Selefunt	movl	f0,tos
211*26460Selefunt	movd	tos,r0
212*26460Selefunt	movd	tos,r0		; get the high part of new x
213*26460Selefunt	extd	r2,r0,r1,11	; extract the exponent of x in r1
214*26460Selefunt	addd	12(sp),r1	; exponent of x + N
215*26460Selefunt	subd	64,r1		; adjust it by subtracting 64
216*26460Selefunt	cmpqd	0,r1
217*26460Selefunt	bge	underflow
218*26460Selefunt	cmpd	2047,r1
219*26460Selefunt	ble	overflow
220*26460Selefunt	insd	r2,r1,r0,11	; insert back the incremented exponent
221*26460Selefunt	movd	r0,tos
222*26460Selefunt	movd	8(sp),tos
223*26460Selefunt	movl	tos,f0
224*26460Selefuntend:	ret	0
225*26460SelefuntL30:	.double	0x0,0x3bf00000	; floating point 2**-64
226*26460SelefuntL32:	.double	0x0,0x43f00000	; floating point 2**64
227