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