xref: /csrg-svn/lib/libm/national/support.s (revision 26907)
1*26907Selefunt; @(#)support.s	1.2 (ucb.elefunt) 03/18/86
226460Selefunt;
326460Selefunt; IEEE recommended functions
426460Selefunt;
526460Selefunt;
626460Selefunt; double copysign(x,y)
726460Selefunt; double x,y;
826460Selefunt; IEEE 754 recommended function, return x*sign(y)
926460Selefunt; Coded by K.C. Ng in National 32k assembler, 11/9/85.
1026460Selefunt;
1126460Selefunt	.vers	2
1226460Selefunt	.text
1326460Selefunt	.align	2
1426460Selefunt	.globl	_copysign
1526460Selefunt_copysign:
1626460Selefunt	movl	4(sp),f0
1726460Selefunt	movd	8(sp),r0
1826460Selefunt	movd	16(sp),r1
1926460Selefunt	xord	r0,r1
20*26907Selefunt	andd	0x80000000,r1
2126460Selefunt	cmpqd	0,r1
2226460Selefunt	beq	end
2326460Selefunt	negl	f0,f0
2426460Selefuntend:	ret	0
2526460Selefunt
2626460Selefunt;
2726460Selefunt; double logb(x)
2826460Selefunt; double x;
2926460Selefunt; IEEE p854 recommended function, return the exponent of x (return float(N)
3026460Selefunt; such that 1 <= x*2**-N < 2, even for subnormal number.
3126460Selefunt; Coded by K.C. Ng in National 32k assembler, 11/9/85.
3226460Selefunt; Note: subnormal number (if implemented) will be taken care of.
3326460Selefunt;
3426460Selefunt	.vers	2
3526460Selefunt	.text
3626460Selefunt	.align	2
3726460Selefunt	.globl	_logb
3826460Selefunt_logb:
3926460Selefunt;
4026460Selefunt; extract the exponent of x
4126460Selefunt; glossaries:	r0 = high part of x
4226460Selefunt;		r1 = unbias exponent of x
4326460Selefunt;		r2 = 20 (first exponent bit position)
4426460Selefunt;
4526460Selefunt	movd	8(sp),r0
4626460Selefunt	movd	20,r2
4726460Selefunt	extd	r2,r0,r1,11	; extract the exponent of x
4826460Selefunt	cmpqd	0,r1		; if exponent bits = 0, goto L3
4926460Selefunt	beq	L3
5026460Selefunt	cmpd	0x7ff,r1
5126460Selefunt	beq	L2		; if exponent bits = 0x7ff, goto L2
5226460SelefuntL1:	subd	1023,r1		; unbias the exponent
5326460Selefunt	movdl	r1,f0		; convert the exponent to floating value
5426460Selefunt	ret	0
5526460Selefunt;
5626460Selefunt; x is INF or NaN, simply return x
5726460Selefunt;
5826460SelefuntL2:
5926460Selefunt	movl	4(sp),f0	; logb(+inf)=+inf, logb(NaN)=NaN
6026460Selefunt	ret	0
6126460Selefunt;
6226460Selefunt; x is 0 or subnormal
6326460Selefunt;
6426460SelefuntL3:
6526460Selefunt	movl	4(sp),f0
6626460Selefunt	cmpl	0f0,f0
6726460Selefunt	beq	L5		; x is 0 , goto L5 (return -inf)
6826460Selefunt;
6926460Selefunt; Now x is subnormal
7026460Selefunt;
7126460Selefunt	mull	L64,f0		; scale up f0 with 2**64
7226460Selefunt	movl	f0,tos
7326460Selefunt	movd	tos,r0
7426460Selefunt	movd	tos,r0		; now r0 = new high part of x
7526460Selefunt	extd	r2,r0,r1,11	; extract the exponent of x to r1
7626460Selefunt	subd	1087,r1		; unbias the exponent with correction
7726460Selefunt	movdl	r1,f0		; convert the exponent to floating value
7826460Selefunt	ret	0
7926460Selefunt;
8026460Selefunt; x is 0, return logb(0)= -INF
8126460Selefunt;
8226460SelefuntL5:
8326460Selefunt	movl	0f1.0e300,f0
8426460Selefunt	mull	0f-1.0e300,f0	; multiply two big numbers to get -INF
8526460Selefunt	ret	0
8626460SelefuntL64:	.double	0,0x43f00000	; L64=2**64
8726460Selefunt
8826460Selefunt;
8926460Selefunt; double rint(x)
9026460Selefunt; double x;
9126460Selefunt; ... delivers integer nearest x in direction of prevailing rounding
9226460Selefunt; ... mode
9326460Selefunt; Coded by K.C. Ng in National 32k assembler, 11/9/85.
9426460Selefunt; Note: subnormal number (if implemented) will be taken care of.
9526460Selefunt;
9626460Selefunt	.vers	2
9726460Selefunt	.text
9826460Selefunt	.align	2
9926460Selefunt	.globl	_rint
10026460Selefunt_rint:
10126460Selefunt;
10226460Selefunt	movd	8(sp),r0
10326460Selefunt	movd	20,r2
10426460Selefunt	extd	r2,r0,r1,11	; extract the exponent of x
10526460Selefunt	cmpd	0x433,r1
10626460Selefunt	ble	itself
10726460Selefunt	movl	L52,f2		; f2 = L = 2**52
10826460Selefunt	cmpqd	0,r0
10926460Selefunt	ble	L1
11026460Selefunt	negl	f2,f2		; f2 = s = copysign(L,x)
11126460SelefuntL1:	addl	f2,f0		; f0 = x + s
11226460Selefunt	subl	f2,f0		; f0 = f0 - s
11326460Selefunt	ret	0
11426460Selefuntitself:	movl	4(sp),f0
11526460Selefunt	ret	0
11626460SelefuntL52:	.double	0x0,0x43300000	; L52=2**52
11726460Selefunt;
11826460Selefunt; int finite(x)
11926460Selefunt; double x;
12026460Selefunt; IEEE 754 recommended function, return 0 if x is NaN or INF, else 0
12126460Selefunt; Coded by K.C. Ng in National 32k assembler, 11/9/85.
12226460Selefunt;
12326460Selefunt	.vers	2
12426460Selefunt	.text
12526460Selefunt	.align	2
12626460Selefunt	.globl	_finite
12726460Selefunt_finite:
12826460Selefunt	movd	4(sp),r1
12926460Selefunt	andd	0x800fffff,r1
13026460Selefunt	cmpd	0x7ff00000,r1
13126460Selefunt	sned	r0		; r0=0 if exponent(x) = 0x7ff
13226460Selefunt	ret	0
13326460Selefunt;
13426460Selefunt; double scalb(x,N)
13526460Selefunt; double x; int N;
13626460Selefunt; IEEE 754 recommended function, return x*2**N by adjusting
13726460Selefunt; exponent of x.
13826460Selefunt; Coded by K.C. Ng in National 32k assembler, 11/9/85.
13926460Selefunt; Note: subnormal number (if implemented) will be taken care of
14026460Selefunt;
14126460Selefunt	.vers	2
14226460Selefunt	.text
14326460Selefunt	.align	2
14426460Selefunt	.globl	_scalb
14526460Selefunt_scalb:
14626460Selefunt;
14726460Selefunt; if x=0 return 0
14826460Selefunt;
14926460Selefunt	movl	4(sp),f0
15026460Selefunt	cmpl	0f0,f0
15126460Selefunt	beq	end		; scalb(0,N) is x itself
15226460Selefunt;
15326460Selefunt; extract the exponent of x
15426460Selefunt; glossaries:	r0 = high part of x,
15526460Selefunt;		r1 = unbias exponent of x,
15626460Selefunt;		r2 = 20 (first exponent bit position).
15726460Selefunt;
15826460Selefunt	movd	8(sp),r0	; r0 = high part of x
15926460Selefunt	movd	20,r2		; r2 = 20
16026460Selefunt	extd	r2,r0,r1,11	; extract the exponent of x in r1
16126460Selefunt	cmpd	0x7ff,r1
16226460Selefunt;
16326460Selefunt; if exponent of x is 0x7ff, then x is NaN or INF; simply return x
16426460Selefunt;
16526460Selefunt	beq	end
16626460Selefunt	cmpqd	0,r1
16726460Selefunt;
16826460Selefunt; if exponent of x is zero, then x is subnormal; goto L19
16926460Selefunt;
17026460Selefunt	beq	L19
17126460Selefunt	addd	12(sp),r1	; r1 = (exponent of x) + N
17226460Selefunt	bfs	inof		; if integer overflows, goto inof
17326460Selefunt	cmpqd	0,r1		; if new exponent <= 0, goto underflow
17426460Selefunt	bge	underflow
17526460Selefunt	cmpd	2047,r1		; if new exponent >= 2047 goto overflow
17626460Selefunt	ble	overflow
17726460Selefunt	insd	r2,r1,r0,11	; insert the new exponent
17826460Selefunt	movd	r0,tos
17926460Selefunt	movd	8(sp),tos
18026460Selefunt	movl	tos,f0		; return x*2**N
18126460Selefuntend:	ret	0
18226460Selefuntinof:	bcs	underflow	; negative int overflow if Carry bit is set
18326460Selefuntoverflow:
18426460Selefunt	andd	0x80000000,r0	; keep the sign of x
18526460Selefunt	ord	0x7fe00000,r0	; set x to a huge number
18626460Selefunt	movd	r0,tos
18726460Selefunt	movqd	0,tos
18826460Selefunt	movl	tos,f0
18926460Selefunt	mull	0f1.0e300,f0	; multiply two huge number to get overflow
19026460Selefunt	ret	0
19126460Selefuntunderflow:
19226460Selefunt	addd	64,r1		; add 64 to exonent to see if it is subnormal
19326460Selefunt	cmpqd	0,r1
19426460Selefunt	bge	zero		; underflow to zero
19526460Selefunt	insd	r2,r1,r0,11	; insert the new exponent
19626460Selefunt	movd	r0,tos
19726460Selefunt	movd	8(sp),tos
19826460Selefunt	movl	tos,f0
19926460Selefunt	mull	L30,f0		; readjust x by multiply it with 2**-64
20026460Selefunt	ret	0
20126460Selefuntzero:	andd	0x80000000,r0	; keep the sign of x
20226460Selefunt	ord	0x00100000,r0	; set x to a tiny number
20326460Selefunt	movd	r0,tos
20426460Selefunt	movqd	0,tos
20526460Selefunt	movl	tos,f0
20626460Selefunt	mull	0f1.0e-300,f0	; underflow to 0  by multipling two tiny nos.
20726460Selefunt	ret	0
20826460SelefuntL19:		; subnormal number
20926460Selefunt	mull	L32,f0		; scale up x by 2**64
21026460Selefunt	movl	f0,tos
21126460Selefunt	movd	tos,r0
21226460Selefunt	movd	tos,r0		; get the high part of new x
21326460Selefunt	extd	r2,r0,r1,11	; extract the exponent of x in r1
21426460Selefunt	addd	12(sp),r1	; exponent of x + N
21526460Selefunt	subd	64,r1		; adjust it by subtracting 64
21626460Selefunt	cmpqd	0,r1
21726460Selefunt	bge	underflow
21826460Selefunt	cmpd	2047,r1
21926460Selefunt	ble	overflow
22026460Selefunt	insd	r2,r1,r0,11	; insert back the incremented exponent
22126460Selefunt	movd	r0,tos
22226460Selefunt	movd	8(sp),tos
22326460Selefunt	movl	tos,f0
22426460Selefuntend:	ret	0
22526460SelefuntL30:	.double	0x0,0x3bf00000	; floating point 2**-64
22626460SelefuntL32:	.double	0x0,0x43f00000	; floating point 2**64
227