📄 support.s
字号:
; Copyright (c) 1985, 1993; The Regents of the University of California. All rights reserved.;; Redistribution and use in source and binary forms, with or without; modification, are permitted provided that the following conditions; are met:; 1. Redistributions of source code must retain the above copyright; notice, this list of conditions and the following disclaimer.; 2. Redistributions in binary form must reproduce the above copyright; notice, this list of conditions and the following disclaimer in the; documentation and/or other materials provided with the distribution.; 3. All advertising materials mentioning features or use of this software; must display the following acknowledgement:; This product includes software developed by the University of; California, Berkeley and its contributors.; 4. Neither the name of the University nor the names of its contributors; may be used to endorse or promote products derived from this software; without specific prior written permission.;; THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND; ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE; IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE; ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE; FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL; DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS; OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION); HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT; LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY; OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF; SUCH DAMAGE.;; @(#)support.s 8.1 (Berkeley) 6/4/93;; IEEE recommended functions; ; double copysign(x,y); double x,y;; IEEE 754 recommended function, return x*sign(y); Coded by K.C. Ng in National 32k assembler, 11/9/85.; .vers 2 .text .align 2 .globl _copysign_copysign: movl 4(sp),f0 movd 8(sp),r0 movd 16(sp),r1 xord r0,r1 andd 0x80000000,r1 cmpqd 0,r1 beq end negl f0,f0end: ret 0; ; double logb(x); double x;; IEEE p854 recommended function, return the exponent of x (return float(N) ; such that 1 <= x*2**-N < 2, even for subnormal number.; Coded by K.C. Ng in National 32k assembler, 11/9/85.; Note: subnormal number (if implemented) will be taken care of. ; .vers 2 .text .align 2 .globl _logb_logb:;; extract the exponent of x; glossaries: r0 = high part of x; r1 = unbias exponent of x; r2 = 20 (first exponent bit position); movd 8(sp),r0 movd 20,r2 extd r2,r0,r1,11 ; extract the exponent of x cmpqd 0,r1 ; if exponent bits = 0, goto L3 beq L3 cmpd 0x7ff,r1 beq L2 ; if exponent bits = 0x7ff, goto L2L1: subd 1023,r1 ; unbias the exponent movdl r1,f0 ; convert the exponent to floating value ret 0;; x is INF or NaN, simply return x;L2: movl 4(sp),f0 ; logb(+inf)=+inf, logb(NaN)=NaN ret 0;; x is 0 or subnormal;L3: movl 4(sp),f0 cmpl 0f0,f0 beq L5 ; x is 0 , goto L5 (return -inf);; Now x is subnormal; mull L64,f0 ; scale up f0 with 2**64 movl f0,tos movd tos,r0 movd tos,r0 ; now r0 = new high part of x extd r2,r0,r1,11 ; extract the exponent of x to r1 subd 1087,r1 ; unbias the exponent with correction movdl r1,f0 ; convert the exponent to floating value ret 0;; x is 0, return logb(0)= -INF;L5: movl 0f1.0e300,f0 mull 0f-1.0e300,f0 ; multiply two big numbers to get -INF ret 0; ; double rint(x); double x;; ... delivers integer nearest x in direction of prevailing rounding; ... mode; Coded by K.C. Ng in National 32k assembler, 11/9/85.; Note: subnormal number (if implemented) will be taken care of. ; .vers 2 .text .align 2 .globl _rint_rint:; movd 8(sp),r0 movd 20,r2 extd r2,r0,r1,11 ; extract the exponent of x cmpd 0x433,r1 ble itself movl L52,f2 ; f2 = L = 2**52 cmpqd 0,r0 ble L1 negl f2,f2 ; f2 = s = copysign(L,x)L1: addl f2,f0 ; f0 = x + s subl f2,f0 ; f0 = f0 - s ret 0itself: movl 4(sp),f0 ret 0L52: .double 0x0,0x43300000 ; L52=2**52; ; int finite(x); double x;; IEEE 754 recommended function, return 0 if x is NaN or INF, else 0; Coded by K.C. Ng in National 32k assembler, 11/9/85.; .vers 2 .text .align 2 .globl _finite_finite: movd 4(sp),r1 andd 0x800fffff,r1 cmpd 0x7ff00000,r1 sned r0 ; r0=0 if exponent(x) = 0x7ff ret 0; ; double scalb(x,N); double x; int N;; IEEE 754 recommended function, return x*2**N by adjusting ; exponent of x.; Coded by K.C. Ng in National 32k assembler, 11/9/85. ; Note: subnormal number (if implemented) will be taken care of ; .vers 2 .text .align 2 .globl _scalb_scalb:;; if x=0 return 0; movl 4(sp),f0 cmpl 0f0,f0 beq end ; scalb(0,N) is x itself;; extract the exponent of x; glossaries: r0 = high part of x, ; r1 = unbias exponent of x,; r2 = 20 (first exponent bit position).; movd 8(sp),r0 ; r0 = high part of x movd 20,r2 ; r2 = 20 extd r2,r0,r1,11 ; extract the exponent of x in r1 cmpd 0x7ff,r1 ;; if exponent of x is 0x7ff, then x is NaN or INF; simply return x ; beq end cmpqd 0,r1;; if exponent of x is zero, then x is subnormal; goto L19; beq L19 addd 12(sp),r1 ; r1 = (exponent of x) + N bfs inof ; if integer overflows, goto inof cmpqd 0,r1 ; if new exponent <= 0, goto underflow bge underflow cmpd 2047,r1 ; if new exponent >= 2047 goto overflow ble overflow insd r2,r1,r0,11 ; insert the new exponent movd r0,tos movd 8(sp),tos movl tos,f0 ; return x*2**Nend: ret 0inof: bcs underflow ; negative int overflow if Carry bit is setoverflow: andd 0x80000000,r0 ; keep the sign of x ord 0x7fe00000,r0 ; set x to a huge number movd r0,tos movqd 0,tos movl tos,f0 mull 0f1.0e300,f0 ; multiply two huge number to get overflow ret 0underflow: addd 64,r1 ; add 64 to exonent to see if it is subnormal cmpqd 0,r1 bge zero ; underflow to zero insd r2,r1,r0,11 ; insert the new exponent movd r0,tos movd 8(sp),tos movl tos,f0 mull L30,f0 ; readjust x by multiply it with 2**-64 ret 0zero: andd 0x80000000,r0 ; keep the sign of x ord 0x00100000,r0 ; set x to a tiny number movd r0,tos movqd 0,tos movl tos,f0 mull 0f1.0e-300,f0 ; underflow to 0 by multipling two tiny nos. ret 0L19: ; subnormal number mull L32,f0 ; scale up x by 2**64 movl f0,tos movd tos,r0 movd tos,r0 ; get the high part of new x extd r2,r0,r1,11 ; extract the exponent of x in r1 addd 12(sp),r1 ; exponent of x + N subd 64,r1 ; adjust it by subtracting 64 cmpqd 0,r1 bge underflow cmpd 2047,r1 ble overflow insd r2,r1,r0,11 ; insert back the incremented exponent movd r0,tos movd 8(sp),tos movl tos,f0end: ret 0L30: .double 0x0,0x3bf00000 ; floating point 2**-64L32: .double 0x0,0x43f00000 ; floating point 2**64; ; double drem(x,y); double x,y;; IEEE double remainder function, return x-n*y, where n=x/y rounded to ; nearest integer (half way case goes to even). Result exact.; Coded by K.C. Ng in National 32k assembly, 11/19/85.; .vers 2 .text .align 2 .globl _drem_drem:;; glossaries: ; r2 = high part of x; r3 = exponent of x; r4 = high part of y; r5 = exponent of y; r6 = sign of x; r7 = constant 0x7ff00000;; 16(fp) : y; 8(fp) : x; -12(fp) : adjustment on y when y is subnormal; -16(fp) : fsr; -20(fp) : nx; -28(fp) : t; -36(fp) : t1; -40(fp) : nf; ; enter [r3,r4,r5,r6,r7],40 movl f6,tos movl f4,tos movl 0f0,-12(fp) movd 0,-20(fp) movd 0,-40(fp) movd 0x7ff00000,r7 ; initialize r7=0x7ff00000 movd 12(fp),r2 ; r2 = high(x) movd r2,r3 andd r7,r3 ; r3 = xexp cmpd r7,r3; if x is NaN or INF goto L1 beq L1 movd 20(fp),r4 bicd [31],r4 ; r4 = high part of |y| movd r4,20(fp) ; y = |y| movd r4,r5 andd r7,r5 ; r5 = yexp cmpd r7,r5 beq L2 ; if y is NaN or INF goto L2 cmpd 0x04000000,r5 ; bgt L3 ; if y is tiny goto L3;; now y != 0 , x is finite;L10: movd r2,r6 andd 0x80000000,r6 ; r6 = sign(x) bicd [31],r2 ; x <- |x| sfsr r1 movd r1,-16(fp) ; save fsr in -16(fp) bicd [5],r1 lfsr r1 ; disable inexact interupt movd 16(fp),r0 ; r0 = low part of y movd r0,r1 ; r1 = r0 = low part of y andd 0xf8000000,r1 ; mask off the lsb 27 bits of y movd r2,12(fp) ; update x to |x| movd r0,-28(fp) ; movd r4,-24(fp) ; t = y movd r4,-32(fp) ; movd r1,-36(fp) ; t1 = y with trialing 27 zeros movd 0x01900000,r1 ; r1 = 25 in exponent fieldLOOP: movl 8(fp),f0 ; f0 = x movl 16(fp),f2 ; f2 = y cmpl f0,f2 ble fnad ; goto fnad (final adjustment) if x <= y movd r4,-32(fp) movd r3,r0 subd r5,r0 ; xexp - yexp subd r1,r0 ; r0 = xexp - yexp - m25 cmpqd 0,r0 ; r0 > 0 ? bge 1f addd r4,r0 ; scale up (high) y movd r0,-24(fp) ; scale up t movl -28(fp),f2 ; t movd r0,-32(fp) ; scale up t11: movl -36(fp),f4 ; t1 movl f0,f6 divl f2,f6 ; f6 = x/t floorld f6,r0 ; r0 = [x/t] movdl r0,f6 ; f6 = n subl f4,f2 ; t = t - t1 (tail of t1) mull f6,f4 ; f4 = n*t1 ...exact subl f4,f0 ; x = x - n*t1 mull f6,f2 ; n*(t-t1) ...exact subl f2,f0 ; x = x - n*(t-t1); update xexp movl f0,8(fp) movd 12(fp),r3 andd r7,r3 jump LOOPfnad: cmpqd 0,-20(fp) ; 0 = nx? beq final mull -12(fp),8(fp) ; scale up x the same amount as y movd 0,-20(fp) movd 12(fp),r2 movd r2,r3 andd r7,r3 ; update exponent of x jump LOOPfinal: movl 16(fp),f2 ; f2 = y (f0=x, r0=n) subd 0x100000,r4 ; high y /2 movd r4,-24(fp) movl -28(fp),f4 ; f4 = y/2 cmpl f0,f4 ; x > y/2 ? bgt 1f bne 2f andd 1,r0 ; n is odd or even cmpqd 0,r0 beq 2f1: subl f2,f0 ; x = x - y2: cmpqd 0,-40(fp) beq 3f divl -12(fp),f0 ; scale down the answer3: movl f0,tos xord r6,tos movl tos,f0 movd -16(fp),r0 lfsr r0 ; restore the fsrend: movl tos,f4 movl tos,f6 exit [r3,r4,r5,r6,r7] ret 0;; y is NaN or INF;L2: movd 16(fp),r0 ; r0 = low part of y andd 0xfffff,r4 ; r4 = high part of y & 0x000fffff ord r4,r0 cmpqd 0,r0 beq L4 movl 16(fp),f0 ; y is NaN, return y jump endL4: movl 8(fp),f0 ; y is inf, return x jump end;; exponent of y is less than 64, y may be zero or subnormal;L3: movl 16(fp),f0 cmpl 0f0,f0 bne L5 divl f0,f0 ; y is 0, return NaN by doing 0/0 jump end;; subnormal y or tiny y;L5: movd 0x04000000,-20(fp) ; nx = 64 in exponent field movl L64,f2 movl f2,-12(fp) mull f2,f0 cmpl f0,LTINY bgt L6 mull f2,f0 addd 0x04000000,-20(fp) ; nx = nx + 64 in exponent field mull f2,-12(fp)L6: movd -20(fp),-40(fp) movl f0,16(fp) movd 20(fp),r4 movd r4,r5 andd r7,r5 ; exponent of new y jump L10;; x is NaN or INF, return x-x;L1: movl 8(fp),f0 subl f0,f0 ; if x is INF, then INF-INF is NaN ret 0L64: .double 0x0,0x43f00000 ; L64 = 2**64LTINY: .double 0x0,0x04000000 ; LTINY = 2**-959
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -