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