1*61308Sbostic; Copyright (c) 1985, 1993 2*61308Sbostic; The Regents of the University of California. All rights reserved. 334129Sbostic; 445304Sbostic; %sccs.include.redist.semicolon% 534129Sbostic; 6*61308Sbostic; @(#)support.s 8.1 (Berkeley) 06/04/93 734129Sbostic; 834129Sbostic 926460Selefunt; IEEE recommended functions 1026460Selefunt; 1126460Selefunt; double copysign(x,y) 1226460Selefunt; double x,y; 1326460Selefunt; IEEE 754 recommended function, return x*sign(y) 1426460Selefunt; Coded by K.C. Ng in National 32k assembler, 11/9/85. 1526460Selefunt; 1626460Selefunt .vers 2 1726460Selefunt .text 1826460Selefunt .align 2 1926460Selefunt .globl _copysign 2026460Selefunt_copysign: 2126460Selefunt movl 4(sp),f0 2226460Selefunt movd 8(sp),r0 2326460Selefunt movd 16(sp),r1 2426460Selefunt xord r0,r1 2526907Selefunt andd 0x80000000,r1 2626460Selefunt cmpqd 0,r1 2726460Selefunt beq end 2826460Selefunt negl f0,f0 2926460Selefuntend: ret 0 3026460Selefunt 3126460Selefunt; 3226460Selefunt; double logb(x) 3326460Selefunt; double x; 3426460Selefunt; IEEE p854 recommended function, return the exponent of x (return float(N) 3526460Selefunt; such that 1 <= x*2**-N < 2, even for subnormal number. 3626460Selefunt; Coded by K.C. Ng in National 32k assembler, 11/9/85. 3726460Selefunt; Note: subnormal number (if implemented) will be taken care of. 3826460Selefunt; 3926460Selefunt .vers 2 4026460Selefunt .text 4126460Selefunt .align 2 4226460Selefunt .globl _logb 4326460Selefunt_logb: 4426460Selefunt; 4526460Selefunt; extract the exponent of x 4626460Selefunt; glossaries: r0 = high part of x 4726460Selefunt; r1 = unbias exponent of x 4826460Selefunt; r2 = 20 (first exponent bit position) 4926460Selefunt; 5026460Selefunt movd 8(sp),r0 5126460Selefunt movd 20,r2 5226460Selefunt extd r2,r0,r1,11 ; extract the exponent of x 5326460Selefunt cmpqd 0,r1 ; if exponent bits = 0, goto L3 5426460Selefunt beq L3 5526460Selefunt cmpd 0x7ff,r1 5626460Selefunt beq L2 ; if exponent bits = 0x7ff, goto L2 5726460SelefuntL1: subd 1023,r1 ; unbias the exponent 5826460Selefunt movdl r1,f0 ; convert the exponent to floating value 5926460Selefunt ret 0 6026460Selefunt; 6126460Selefunt; x is INF or NaN, simply return x 6226460Selefunt; 6326460SelefuntL2: 6426460Selefunt movl 4(sp),f0 ; logb(+inf)=+inf, logb(NaN)=NaN 6526460Selefunt ret 0 6626460Selefunt; 6726460Selefunt; x is 0 or subnormal 6826460Selefunt; 6926460SelefuntL3: 7026460Selefunt movl 4(sp),f0 7126460Selefunt cmpl 0f0,f0 7226460Selefunt beq L5 ; x is 0 , goto L5 (return -inf) 7326460Selefunt; 7426460Selefunt; Now x is subnormal 7526460Selefunt; 7626460Selefunt mull L64,f0 ; scale up f0 with 2**64 7726460Selefunt movl f0,tos 7826460Selefunt movd tos,r0 7926460Selefunt movd tos,r0 ; now r0 = new high part of x 8026460Selefunt extd r2,r0,r1,11 ; extract the exponent of x to r1 8126460Selefunt subd 1087,r1 ; unbias the exponent with correction 8226460Selefunt movdl r1,f0 ; convert the exponent to floating value 8326460Selefunt ret 0 8426460Selefunt; 8526460Selefunt; x is 0, return logb(0)= -INF 8626460Selefunt; 8726460SelefuntL5: 8826460Selefunt movl 0f1.0e300,f0 8926460Selefunt mull 0f-1.0e300,f0 ; multiply two big numbers to get -INF 9026460Selefunt ret 0 9126460Selefunt; 9226460Selefunt; double rint(x) 9326460Selefunt; double x; 9426460Selefunt; ... delivers integer nearest x in direction of prevailing rounding 9526460Selefunt; ... mode 9626460Selefunt; Coded by K.C. Ng in National 32k assembler, 11/9/85. 9726460Selefunt; Note: subnormal number (if implemented) will be taken care of. 9826460Selefunt; 9926460Selefunt .vers 2 10026460Selefunt .text 10126460Selefunt .align 2 10226460Selefunt .globl _rint 10326460Selefunt_rint: 10426460Selefunt; 10526460Selefunt movd 8(sp),r0 10626460Selefunt movd 20,r2 10726460Selefunt extd r2,r0,r1,11 ; extract the exponent of x 10826460Selefunt cmpd 0x433,r1 10926460Selefunt ble itself 11026460Selefunt movl L52,f2 ; f2 = L = 2**52 11126460Selefunt cmpqd 0,r0 11226460Selefunt ble L1 11326460Selefunt negl f2,f2 ; f2 = s = copysign(L,x) 11426460SelefuntL1: addl f2,f0 ; f0 = x + s 11526460Selefunt subl f2,f0 ; f0 = f0 - s 11626460Selefunt ret 0 11726460Selefuntitself: movl 4(sp),f0 11826460Selefunt ret 0 11926460SelefuntL52: .double 0x0,0x43300000 ; L52=2**52 12026460Selefunt; 12126460Selefunt; int finite(x) 12226460Selefunt; double x; 12326460Selefunt; IEEE 754 recommended function, return 0 if x is NaN or INF, else 0 12426460Selefunt; Coded by K.C. Ng in National 32k assembler, 11/9/85. 12526460Selefunt; 12626460Selefunt .vers 2 12726460Selefunt .text 12826460Selefunt .align 2 12926460Selefunt .globl _finite 13026460Selefunt_finite: 13126460Selefunt movd 4(sp),r1 13226460Selefunt andd 0x800fffff,r1 13326460Selefunt cmpd 0x7ff00000,r1 13426460Selefunt sned r0 ; r0=0 if exponent(x) = 0x7ff 13526460Selefunt ret 0 13626460Selefunt; 13726460Selefunt; double scalb(x,N) 13826460Selefunt; double x; int N; 13926460Selefunt; IEEE 754 recommended function, return x*2**N by adjusting 14026460Selefunt; exponent of x. 14126460Selefunt; Coded by K.C. Ng in National 32k assembler, 11/9/85. 14226460Selefunt; Note: subnormal number (if implemented) will be taken care of 14326460Selefunt; 14426460Selefunt .vers 2 14526460Selefunt .text 14626460Selefunt .align 2 14726460Selefunt .globl _scalb 14826460Selefunt_scalb: 14926460Selefunt; 15026460Selefunt; if x=0 return 0 15126460Selefunt; 15226460Selefunt movl 4(sp),f0 15326460Selefunt cmpl 0f0,f0 15426460Selefunt beq end ; scalb(0,N) is x itself 15526460Selefunt; 15626460Selefunt; extract the exponent of x 15726460Selefunt; glossaries: r0 = high part of x, 15826460Selefunt; r1 = unbias exponent of x, 15926460Selefunt; r2 = 20 (first exponent bit position). 16026460Selefunt; 16126460Selefunt movd 8(sp),r0 ; r0 = high part of x 16226460Selefunt movd 20,r2 ; r2 = 20 16326460Selefunt extd r2,r0,r1,11 ; extract the exponent of x in r1 16426460Selefunt cmpd 0x7ff,r1 16526460Selefunt; 16626460Selefunt; if exponent of x is 0x7ff, then x is NaN or INF; simply return x 16726460Selefunt; 16826460Selefunt beq end 16926460Selefunt cmpqd 0,r1 17026460Selefunt; 17126460Selefunt; if exponent of x is zero, then x is subnormal; goto L19 17226460Selefunt; 17326460Selefunt beq L19 17426460Selefunt addd 12(sp),r1 ; r1 = (exponent of x) + N 17526460Selefunt bfs inof ; if integer overflows, goto inof 17626460Selefunt cmpqd 0,r1 ; if new exponent <= 0, goto underflow 17726460Selefunt bge underflow 17826460Selefunt cmpd 2047,r1 ; if new exponent >= 2047 goto overflow 17926460Selefunt ble overflow 18026460Selefunt insd r2,r1,r0,11 ; insert the new exponent 18126460Selefunt movd r0,tos 18226460Selefunt movd 8(sp),tos 18326460Selefunt movl tos,f0 ; return x*2**N 18426460Selefuntend: ret 0 18526460Selefuntinof: bcs underflow ; negative int overflow if Carry bit is set 18626460Selefuntoverflow: 18726460Selefunt andd 0x80000000,r0 ; keep the sign of x 18826460Selefunt ord 0x7fe00000,r0 ; set x to a huge number 18926460Selefunt movd r0,tos 19026460Selefunt movqd 0,tos 19126460Selefunt movl tos,f0 19226460Selefunt mull 0f1.0e300,f0 ; multiply two huge number to get overflow 19326460Selefunt ret 0 19426460Selefuntunderflow: 19526460Selefunt addd 64,r1 ; add 64 to exonent to see if it is subnormal 19626460Selefunt cmpqd 0,r1 19726460Selefunt bge zero ; underflow to zero 19826460Selefunt insd r2,r1,r0,11 ; insert the new exponent 19926460Selefunt movd r0,tos 20026460Selefunt movd 8(sp),tos 20126460Selefunt movl tos,f0 20226460Selefunt mull L30,f0 ; readjust x by multiply it with 2**-64 20326460Selefunt ret 0 20426460Selefuntzero: andd 0x80000000,r0 ; keep the sign of x 20526460Selefunt ord 0x00100000,r0 ; set x to a tiny number 20626460Selefunt movd r0,tos 20726460Selefunt movqd 0,tos 20826460Selefunt movl tos,f0 20926460Selefunt mull 0f1.0e-300,f0 ; underflow to 0 by multipling two tiny nos. 21026460Selefunt ret 0 21126460SelefuntL19: ; subnormal number 21226460Selefunt mull L32,f0 ; scale up x by 2**64 21326460Selefunt movl f0,tos 21426460Selefunt movd tos,r0 21526460Selefunt movd tos,r0 ; get the high part of new x 21626460Selefunt extd r2,r0,r1,11 ; extract the exponent of x in r1 21726460Selefunt addd 12(sp),r1 ; exponent of x + N 21826460Selefunt subd 64,r1 ; adjust it by subtracting 64 21926460Selefunt cmpqd 0,r1 22026460Selefunt bge underflow 22126460Selefunt cmpd 2047,r1 22226460Selefunt ble overflow 22326460Selefunt insd r2,r1,r0,11 ; insert back the incremented exponent 22426460Selefunt movd r0,tos 22526460Selefunt movd 8(sp),tos 22626460Selefunt movl tos,f0 22726460Selefuntend: ret 0 22826460SelefuntL30: .double 0x0,0x3bf00000 ; floating point 2**-64 22926460SelefuntL32: .double 0x0,0x43f00000 ; floating point 2**64 23031848Szliu; 23131848Szliu; double drem(x,y) 23231848Szliu; double x,y; 23331848Szliu; IEEE double remainder function, return x-n*y, where n=x/y rounded to 23431848Szliu; nearest integer (half way case goes to even). Result exact. 23531848Szliu; Coded by K.C. Ng in National 32k assembly, 11/19/85. 23631848Szliu; 23731848Szliu .vers 2 23831848Szliu .text 23931848Szliu .align 2 24031848Szliu .globl _drem 24131848Szliu_drem: 24231848Szliu; 24331848Szliu; glossaries: 24431848Szliu; r2 = high part of x 24531848Szliu; r3 = exponent of x 24631848Szliu; r4 = high part of y 24731848Szliu; r5 = exponent of y 24831848Szliu; r6 = sign of x 24931848Szliu; r7 = constant 0x7ff00000 25031848Szliu; 25131848Szliu; 16(fp) : y 25231848Szliu; 8(fp) : x 25331848Szliu; -12(fp) : adjustment on y when y is subnormal 25431848Szliu; -16(fp) : fsr 25531848Szliu; -20(fp) : nx 25631848Szliu; -28(fp) : t 25731848Szliu; -36(fp) : t1 25831848Szliu; -40(fp) : nf 25931848Szliu; 26031848Szliu; 26131848Szliu enter [r3,r4,r5,r6,r7],40 26231848Szliu movl f6,tos 26331848Szliu movl f4,tos 26431848Szliu movl 0f0,-12(fp) 26531848Szliu movd 0,-20(fp) 26631848Szliu movd 0,-40(fp) 26731848Szliu movd 0x7ff00000,r7 ; initialize r7=0x7ff00000 26831848Szliu movd 12(fp),r2 ; r2 = high(x) 26931848Szliu movd r2,r3 27031848Szliu andd r7,r3 ; r3 = xexp 27131848Szliu cmpd r7,r3 27231848Szliu; if x is NaN or INF goto L1 27331848Szliu beq L1 27431848Szliu movd 20(fp),r4 27531848Szliu bicd [31],r4 ; r4 = high part of |y| 27631848Szliu movd r4,20(fp) ; y = |y| 27731848Szliu movd r4,r5 27831848Szliu andd r7,r5 ; r5 = yexp 27931848Szliu cmpd r7,r5 28031848Szliu beq L2 ; if y is NaN or INF goto L2 28131848Szliu cmpd 0x04000000,r5 ; 28231848Szliu bgt L3 ; if y is tiny goto L3 28331848Szliu; 28431848Szliu; now y != 0 , x is finite 28531848Szliu; 28631848SzliuL10: 28731848Szliu movd r2,r6 28831848Szliu andd 0x80000000,r6 ; r6 = sign(x) 28931848Szliu bicd [31],r2 ; x <- |x| 29031848Szliu sfsr r1 29131848Szliu movd r1,-16(fp) ; save fsr in -16(fp) 29231848Szliu bicd [5],r1 29331848Szliu lfsr r1 ; disable inexact interupt 29431848Szliu movd 16(fp),r0 ; r0 = low part of y 29531848Szliu movd r0,r1 ; r1 = r0 = low part of y 29631848Szliu andd 0xf8000000,r1 ; mask off the lsb 27 bits of y 29731848Szliu 29831848Szliu movd r2,12(fp) ; update x to |x| 29931848Szliu movd r0,-28(fp) ; 30031848Szliu movd r4,-24(fp) ; t = y 30131848Szliu movd r4,-32(fp) ; 30231848Szliu movd r1,-36(fp) ; t1 = y with trialing 27 zeros 30331848Szliu movd 0x01900000,r1 ; r1 = 25 in exponent field 30431848SzliuLOOP: 30531848Szliu movl 8(fp),f0 ; f0 = x 30631848Szliu movl 16(fp),f2 ; f2 = y 30731848Szliu cmpl f0,f2 30831848Szliu ble fnad ; goto fnad (final adjustment) if x <= y 30931848Szliu movd r4,-32(fp) 31031848Szliu movd r3,r0 31131848Szliu subd r5,r0 ; xexp - yexp 31231848Szliu subd r1,r0 ; r0 = xexp - yexp - m25 31331848Szliu cmpqd 0,r0 ; r0 > 0 ? 31431848Szliu bge 1f 31531848Szliu addd r4,r0 ; scale up (high) y 31631848Szliu movd r0,-24(fp) ; scale up t 31731848Szliu movl -28(fp),f2 ; t 31831848Szliu movd r0,-32(fp) ; scale up t1 31931848Szliu1: 32031848Szliu movl -36(fp),f4 ; t1 32131848Szliu movl f0,f6 32231848Szliu divl f2,f6 ; f6 = x/t 32331848Szliu floorld f6,r0 ; r0 = [x/t] 32431848Szliu movdl r0,f6 ; f6 = n 32531848Szliu subl f4,f2 ; t = t - t1 (tail of t1) 32631848Szliu mull f6,f4 ; f4 = n*t1 ...exact 32731848Szliu subl f4,f0 ; x = x - n*t1 32831848Szliu mull f6,f2 ; n*(t-t1) ...exact 32931848Szliu subl f2,f0 ; x = x - n*(t-t1) 33031848Szliu; update xexp 33131848Szliu movl f0,8(fp) 33231848Szliu movd 12(fp),r3 33331848Szliu andd r7,r3 33431848Szliu jump LOOP 33531848Szliufnad: 33631848Szliu cmpqd 0,-20(fp) ; 0 = nx? 33731848Szliu beq final 33831848Szliu mull -12(fp),8(fp) ; scale up x the same amount as y 33931848Szliu movd 0,-20(fp) 34031848Szliu movd 12(fp),r2 34131848Szliu movd r2,r3 34231848Szliu andd r7,r3 ; update exponent of x 34331848Szliu jump LOOP 34431848Szliu 34531848Szliufinal: 34631848Szliu movl 16(fp),f2 ; f2 = y (f0=x, r0=n) 34731848Szliu subd 0x100000,r4 ; high y /2 34831848Szliu movd r4,-24(fp) 34931848Szliu movl -28(fp),f4 ; f4 = y/2 35031848Szliu cmpl f0,f4 ; x > y/2 ? 35131848Szliu bgt 1f 35231848Szliu bne 2f 35331848Szliu andd 1,r0 ; n is odd or even 35431848Szliu cmpqd 0,r0 35531848Szliu beq 2f 35631848Szliu1: 35731848Szliu subl f2,f0 ; x = x - y 35831848Szliu2: 35931848Szliu cmpqd 0,-40(fp) 36031848Szliu beq 3f 36131848Szliu divl -12(fp),f0 ; scale down the answer 36231848Szliu3: 36331848Szliu movl f0,tos 36431848Szliu xord r6,tos 36531848Szliu movl tos,f0 36631848Szliu movd -16(fp),r0 36731848Szliu lfsr r0 ; restore the fsr 36831848Szliu 36931848Szliuend: movl tos,f4 37031848Szliu movl tos,f6 37131848Szliu exit [r3,r4,r5,r6,r7] 37231848Szliu ret 0 37331848Szliu; 37431848Szliu; y is NaN or INF 37531848Szliu; 37631848SzliuL2: 37731848Szliu movd 16(fp),r0 ; r0 = low part of y 37831848Szliu andd 0xfffff,r4 ; r4 = high part of y & 0x000fffff 37931848Szliu ord r4,r0 38031848Szliu cmpqd 0,r0 38131848Szliu beq L4 38231848Szliu movl 16(fp),f0 ; y is NaN, return y 38331848Szliu jump end 38431848SzliuL4: movl 8(fp),f0 ; y is inf, return x 38531848Szliu jump end 38631848Szliu; 38731848Szliu; exponent of y is less than 64, y may be zero or subnormal 38831848Szliu; 38931848SzliuL3: 39031848Szliu movl 16(fp),f0 39131848Szliu cmpl 0f0,f0 39231848Szliu bne L5 39331848Szliu divl f0,f0 ; y is 0, return NaN by doing 0/0 39431848Szliu jump end 39531848Szliu; 39631848Szliu; subnormal y or tiny y 39731848Szliu; 39831848SzliuL5: 39931848Szliu movd 0x04000000,-20(fp) ; nx = 64 in exponent field 40031848Szliu movl L64,f2 40131848Szliu movl f2,-12(fp) 40231848Szliu mull f2,f0 40331848Szliu cmpl f0,LTINY 40431848Szliu bgt L6 40531848Szliu mull f2,f0 40631848Szliu addd 0x04000000,-20(fp) ; nx = nx + 64 in exponent field 40731848Szliu mull f2,-12(fp) 40831848SzliuL6: 40931848Szliu movd -20(fp),-40(fp) 41031848Szliu movl f0,16(fp) 41131848Szliu movd 20(fp),r4 41231848Szliu movd r4,r5 41331848Szliu andd r7,r5 ; exponent of new y 41431848Szliu jump L10 41531848Szliu; 41631848Szliu; x is NaN or INF, return x-x 41731848Szliu; 41831848SzliuL1: 41931848Szliu movl 8(fp),f0 42031848Szliu subl f0,f0 ; if x is INF, then INF-INF is NaN 42131848Szliu ret 0 42231848SzliuL64: .double 0x0,0x43f00000 ; L64 = 2**64 42331848SzliuLTINY: .double 0x0,0x04000000 ; LTINY = 2**-959 424