|
|
1.1 ! root 1: ; Copyright (c) 1985 Regents of the University of California. ! 2: ; All rights reserved. ! 3: ; ! 4: ; Redistribution and use in source and binary forms are permitted ! 5: ; provided that the above copyright notice and this paragraph are ! 6: ; duplicated in all such forms and that any documentation, ! 7: ; advertising materials, and other materials related to such ! 8: ; distribution and use acknowledge that the software was developed ! 9: ; by the University of California, Berkeley. The name of the ! 10: ; University may not be used to endorse or promote products derived ! 11: ; from this software without specific prior written permission. ! 12: ; THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR ! 13: ; IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED ! 14: ; WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. ! 15: ; ! 16: ; All recipients should regard themselves as participants in an ongoing ! 17: ; research project and hence should feel obligated to report their ! 18: ; experiences (good or bad) with these elementary function codes, using ! 19: ; the sendbug(8) program, to the authors. ! 20: ; ! 21: ; @(#)support.s 5.3 (Berkeley) 6/30/88 ! 22: ; ! 23: ! 24: ; IEEE recommended functions ! 25: ; ! 26: ; double copysign(x,y) ! 27: ; double x,y; ! 28: ; IEEE 754 recommended function, return x*sign(y) ! 29: ; Coded by K.C. Ng in National 32k assembler, 11/9/85. ! 30: ; ! 31: .vers 2 ! 32: .text ! 33: .align 2 ! 34: .globl _copysign ! 35: _copysign: ! 36: movl 4(sp),f0 ! 37: movd 8(sp),r0 ! 38: movd 16(sp),r1 ! 39: xord r0,r1 ! 40: andd 0x80000000,r1 ! 41: cmpqd 0,r1 ! 42: beq end ! 43: negl f0,f0 ! 44: end: ret 0 ! 45: ! 46: ; ! 47: ; double logb(x) ! 48: ; double x; ! 49: ; IEEE p854 recommended function, return the exponent of x (return float(N) ! 50: ; such that 1 <= x*2**-N < 2, even for subnormal number. ! 51: ; Coded by K.C. Ng in National 32k assembler, 11/9/85. ! 52: ; Note: subnormal number (if implemented) will be taken care of. ! 53: ; ! 54: .vers 2 ! 55: .text ! 56: .align 2 ! 57: .globl _logb ! 58: _logb: ! 59: ; ! 60: ; extract the exponent of x ! 61: ; glossaries: r0 = high part of x ! 62: ; r1 = unbias exponent of x ! 63: ; r2 = 20 (first exponent bit position) ! 64: ; ! 65: movd 8(sp),r0 ! 66: movd 20,r2 ! 67: extd r2,r0,r1,11 ; extract the exponent of x ! 68: cmpqd 0,r1 ; if exponent bits = 0, goto L3 ! 69: beq L3 ! 70: cmpd 0x7ff,r1 ! 71: beq L2 ; if exponent bits = 0x7ff, goto L2 ! 72: L1: subd 1023,r1 ; unbias the exponent ! 73: movdl r1,f0 ; convert the exponent to floating value ! 74: ret 0 ! 75: ; ! 76: ; x is INF or NaN, simply return x ! 77: ; ! 78: L2: ! 79: movl 4(sp),f0 ; logb(+inf)=+inf, logb(NaN)=NaN ! 80: ret 0 ! 81: ; ! 82: ; x is 0 or subnormal ! 83: ; ! 84: L3: ! 85: movl 4(sp),f0 ! 86: cmpl 0f0,f0 ! 87: beq L5 ; x is 0 , goto L5 (return -inf) ! 88: ; ! 89: ; Now x is subnormal ! 90: ; ! 91: mull L64,f0 ; scale up f0 with 2**64 ! 92: movl f0,tos ! 93: movd tos,r0 ! 94: movd tos,r0 ; now r0 = new high part of x ! 95: extd r2,r0,r1,11 ; extract the exponent of x to r1 ! 96: subd 1087,r1 ; unbias the exponent with correction ! 97: movdl r1,f0 ; convert the exponent to floating value ! 98: ret 0 ! 99: ; ! 100: ; x is 0, return logb(0)= -INF ! 101: ; ! 102: L5: ! 103: movl 0f1.0e300,f0 ! 104: mull 0f-1.0e300,f0 ; multiply two big numbers to get -INF ! 105: ret 0 ! 106: ; ! 107: ; double rint(x) ! 108: ; double x; ! 109: ; ... delivers integer nearest x in direction of prevailing rounding ! 110: ; ... mode ! 111: ; Coded by K.C. Ng in National 32k assembler, 11/9/85. ! 112: ; Note: subnormal number (if implemented) will be taken care of. ! 113: ; ! 114: .vers 2 ! 115: .text ! 116: .align 2 ! 117: .globl _rint ! 118: _rint: ! 119: ; ! 120: movd 8(sp),r0 ! 121: movd 20,r2 ! 122: extd r2,r0,r1,11 ; extract the exponent of x ! 123: cmpd 0x433,r1 ! 124: ble itself ! 125: movl L52,f2 ; f2 = L = 2**52 ! 126: cmpqd 0,r0 ! 127: ble L1 ! 128: negl f2,f2 ; f2 = s = copysign(L,x) ! 129: L1: addl f2,f0 ; f0 = x + s ! 130: subl f2,f0 ; f0 = f0 - s ! 131: ret 0 ! 132: itself: movl 4(sp),f0 ! 133: ret 0 ! 134: L52: .double 0x0,0x43300000 ; L52=2**52 ! 135: ; ! 136: ; int finite(x) ! 137: ; double x; ! 138: ; IEEE 754 recommended function, return 0 if x is NaN or INF, else 0 ! 139: ; Coded by K.C. Ng in National 32k assembler, 11/9/85. ! 140: ; ! 141: .vers 2 ! 142: .text ! 143: .align 2 ! 144: .globl _finite ! 145: _finite: ! 146: movd 4(sp),r1 ! 147: andd 0x800fffff,r1 ! 148: cmpd 0x7ff00000,r1 ! 149: sned r0 ; r0=0 if exponent(x) = 0x7ff ! 150: ret 0 ! 151: ; ! 152: ; double scalb(x,N) ! 153: ; double x; int N; ! 154: ; IEEE 754 recommended function, return x*2**N by adjusting ! 155: ; exponent of x. ! 156: ; Coded by K.C. Ng in National 32k assembler, 11/9/85. ! 157: ; Note: subnormal number (if implemented) will be taken care of ! 158: ; ! 159: .vers 2 ! 160: .text ! 161: .align 2 ! 162: .globl _scalb ! 163: _scalb: ! 164: ; ! 165: ; if x=0 return 0 ! 166: ; ! 167: movl 4(sp),f0 ! 168: cmpl 0f0,f0 ! 169: beq end ; scalb(0,N) is x itself ! 170: ; ! 171: ; extract the exponent of x ! 172: ; glossaries: r0 = high part of x, ! 173: ; r1 = unbias exponent of x, ! 174: ; r2 = 20 (first exponent bit position). ! 175: ; ! 176: movd 8(sp),r0 ; r0 = high part of x ! 177: movd 20,r2 ; r2 = 20 ! 178: extd r2,r0,r1,11 ; extract the exponent of x in r1 ! 179: cmpd 0x7ff,r1 ! 180: ; ! 181: ; if exponent of x is 0x7ff, then x is NaN or INF; simply return x ! 182: ; ! 183: beq end ! 184: cmpqd 0,r1 ! 185: ; ! 186: ; if exponent of x is zero, then x is subnormal; goto L19 ! 187: ; ! 188: beq L19 ! 189: addd 12(sp),r1 ; r1 = (exponent of x) + N ! 190: bfs inof ; if integer overflows, goto inof ! 191: cmpqd 0,r1 ; if new exponent <= 0, goto underflow ! 192: bge underflow ! 193: cmpd 2047,r1 ; if new exponent >= 2047 goto overflow ! 194: ble overflow ! 195: insd r2,r1,r0,11 ; insert the new exponent ! 196: movd r0,tos ! 197: movd 8(sp),tos ! 198: movl tos,f0 ; return x*2**N ! 199: end: ret 0 ! 200: inof: bcs underflow ; negative int overflow if Carry bit is set ! 201: overflow: ! 202: andd 0x80000000,r0 ; keep the sign of x ! 203: ord 0x7fe00000,r0 ; set x to a huge number ! 204: movd r0,tos ! 205: movqd 0,tos ! 206: movl tos,f0 ! 207: mull 0f1.0e300,f0 ; multiply two huge number to get overflow ! 208: ret 0 ! 209: underflow: ! 210: addd 64,r1 ; add 64 to exonent to see if it is subnormal ! 211: cmpqd 0,r1 ! 212: bge zero ; underflow to zero ! 213: insd r2,r1,r0,11 ; insert the new exponent ! 214: movd r0,tos ! 215: movd 8(sp),tos ! 216: movl tos,f0 ! 217: mull L30,f0 ; readjust x by multiply it with 2**-64 ! 218: ret 0 ! 219: zero: andd 0x80000000,r0 ; keep the sign of x ! 220: ord 0x00100000,r0 ; set x to a tiny number ! 221: movd r0,tos ! 222: movqd 0,tos ! 223: movl tos,f0 ! 224: mull 0f1.0e-300,f0 ; underflow to 0 by multipling two tiny nos. ! 225: ret 0 ! 226: L19: ; subnormal number ! 227: mull L32,f0 ; scale up x by 2**64 ! 228: movl f0,tos ! 229: movd tos,r0 ! 230: movd tos,r0 ; get the high part of new x ! 231: extd r2,r0,r1,11 ; extract the exponent of x in r1 ! 232: addd 12(sp),r1 ; exponent of x + N ! 233: subd 64,r1 ; adjust it by subtracting 64 ! 234: cmpqd 0,r1 ! 235: bge underflow ! 236: cmpd 2047,r1 ! 237: ble overflow ! 238: insd r2,r1,r0,11 ; insert back the incremented exponent ! 239: movd r0,tos ! 240: movd 8(sp),tos ! 241: movl tos,f0 ! 242: end: ret 0 ! 243: L30: .double 0x0,0x3bf00000 ; floating point 2**-64 ! 244: L32: .double 0x0,0x43f00000 ; floating point 2**64 ! 245: ; ! 246: ; double drem(x,y) ! 247: ; double x,y; ! 248: ; IEEE double remainder function, return x-n*y, where n=x/y rounded to ! 249: ; nearest integer (half way case goes to even). Result exact. ! 250: ; Coded by K.C. Ng in National 32k assembly, 11/19/85. ! 251: ; ! 252: .vers 2 ! 253: .text ! 254: .align 2 ! 255: .globl _drem ! 256: _drem: ! 257: ; ! 258: ; glossaries: ! 259: ; r2 = high part of x ! 260: ; r3 = exponent of x ! 261: ; r4 = high part of y ! 262: ; r5 = exponent of y ! 263: ; r6 = sign of x ! 264: ; r7 = constant 0x7ff00000 ! 265: ; ! 266: ; 16(fp) : y ! 267: ; 8(fp) : x ! 268: ; -12(fp) : adjustment on y when y is subnormal ! 269: ; -16(fp) : fsr ! 270: ; -20(fp) : nx ! 271: ; -28(fp) : t ! 272: ; -36(fp) : t1 ! 273: ; -40(fp) : nf ! 274: ; ! 275: ; ! 276: enter [r3,r4,r5,r6,r7],40 ! 277: movl f6,tos ! 278: movl f4,tos ! 279: movl 0f0,-12(fp) ! 280: movd 0,-20(fp) ! 281: movd 0,-40(fp) ! 282: movd 0x7ff00000,r7 ; initialize r7=0x7ff00000 ! 283: movd 12(fp),r2 ; r2 = high(x) ! 284: movd r2,r3 ! 285: andd r7,r3 ; r3 = xexp ! 286: cmpd r7,r3 ! 287: ; if x is NaN or INF goto L1 ! 288: beq L1 ! 289: movd 20(fp),r4 ! 290: bicd [31],r4 ; r4 = high part of |y| ! 291: movd r4,20(fp) ; y = |y| ! 292: movd r4,r5 ! 293: andd r7,r5 ; r5 = yexp ! 294: cmpd r7,r5 ! 295: beq L2 ; if y is NaN or INF goto L2 ! 296: cmpd 0x04000000,r5 ; ! 297: bgt L3 ; if y is tiny goto L3 ! 298: ; ! 299: ; now y != 0 , x is finite ! 300: ; ! 301: L10: ! 302: movd r2,r6 ! 303: andd 0x80000000,r6 ; r6 = sign(x) ! 304: bicd [31],r2 ; x <- |x| ! 305: sfsr r1 ! 306: movd r1,-16(fp) ; save fsr in -16(fp) ! 307: bicd [5],r1 ! 308: lfsr r1 ; disable inexact interupt ! 309: movd 16(fp),r0 ; r0 = low part of y ! 310: movd r0,r1 ; r1 = r0 = low part of y ! 311: andd 0xf8000000,r1 ; mask off the lsb 27 bits of y ! 312: ! 313: movd r2,12(fp) ; update x to |x| ! 314: movd r0,-28(fp) ; ! 315: movd r4,-24(fp) ; t = y ! 316: movd r4,-32(fp) ; ! 317: movd r1,-36(fp) ; t1 = y with trialing 27 zeros ! 318: movd 0x01900000,r1 ; r1 = 25 in exponent field ! 319: LOOP: ! 320: movl 8(fp),f0 ; f0 = x ! 321: movl 16(fp),f2 ; f2 = y ! 322: cmpl f0,f2 ! 323: ble fnad ; goto fnad (final adjustment) if x <= y ! 324: movd r4,-32(fp) ! 325: movd r3,r0 ! 326: subd r5,r0 ; xexp - yexp ! 327: subd r1,r0 ; r0 = xexp - yexp - m25 ! 328: cmpqd 0,r0 ; r0 > 0 ? ! 329: bge 1f ! 330: addd r4,r0 ; scale up (high) y ! 331: movd r0,-24(fp) ; scale up t ! 332: movl -28(fp),f2 ; t ! 333: movd r0,-32(fp) ; scale up t1 ! 334: 1: ! 335: movl -36(fp),f4 ; t1 ! 336: movl f0,f6 ! 337: divl f2,f6 ; f6 = x/t ! 338: floorld f6,r0 ; r0 = [x/t] ! 339: movdl r0,f6 ; f6 = n ! 340: subl f4,f2 ; t = t - t1 (tail of t1) ! 341: mull f6,f4 ; f4 = n*t1 ...exact ! 342: subl f4,f0 ; x = x - n*t1 ! 343: mull f6,f2 ; n*(t-t1) ...exact ! 344: subl f2,f0 ; x = x - n*(t-t1) ! 345: ; update xexp ! 346: movl f0,8(fp) ! 347: movd 12(fp),r3 ! 348: andd r7,r3 ! 349: jump LOOP ! 350: fnad: ! 351: cmpqd 0,-20(fp) ; 0 = nx? ! 352: beq final ! 353: mull -12(fp),8(fp) ; scale up x the same amount as y ! 354: movd 0,-20(fp) ! 355: movd 12(fp),r2 ! 356: movd r2,r3 ! 357: andd r7,r3 ; update exponent of x ! 358: jump LOOP ! 359: ! 360: final: ! 361: movl 16(fp),f2 ; f2 = y (f0=x, r0=n) ! 362: subd 0x100000,r4 ; high y /2 ! 363: movd r4,-24(fp) ! 364: movl -28(fp),f4 ; f4 = y/2 ! 365: cmpl f0,f4 ; x > y/2 ? ! 366: bgt 1f ! 367: bne 2f ! 368: andd 1,r0 ; n is odd or even ! 369: cmpqd 0,r0 ! 370: beq 2f ! 371: 1: ! 372: subl f2,f0 ; x = x - y ! 373: 2: ! 374: cmpqd 0,-40(fp) ! 375: beq 3f ! 376: divl -12(fp),f0 ; scale down the answer ! 377: 3: ! 378: movl f0,tos ! 379: xord r6,tos ! 380: movl tos,f0 ! 381: movd -16(fp),r0 ! 382: lfsr r0 ; restore the fsr ! 383: ! 384: end: movl tos,f4 ! 385: movl tos,f6 ! 386: exit [r3,r4,r5,r6,r7] ! 387: ret 0 ! 388: ; ! 389: ; y is NaN or INF ! 390: ; ! 391: L2: ! 392: movd 16(fp),r0 ; r0 = low part of y ! 393: andd 0xfffff,r4 ; r4 = high part of y & 0x000fffff ! 394: ord r4,r0 ! 395: cmpqd 0,r0 ! 396: beq L4 ! 397: movl 16(fp),f0 ; y is NaN, return y ! 398: jump end ! 399: L4: movl 8(fp),f0 ; y is inf, return x ! 400: jump end ! 401: ; ! 402: ; exponent of y is less than 64, y may be zero or subnormal ! 403: ; ! 404: L3: ! 405: movl 16(fp),f0 ! 406: cmpl 0f0,f0 ! 407: bne L5 ! 408: divl f0,f0 ; y is 0, return NaN by doing 0/0 ! 409: jump end ! 410: ; ! 411: ; subnormal y or tiny y ! 412: ; ! 413: L5: ! 414: movd 0x04000000,-20(fp) ; nx = 64 in exponent field ! 415: movl L64,f2 ! 416: movl f2,-12(fp) ! 417: mull f2,f0 ! 418: cmpl f0,LTINY ! 419: bgt L6 ! 420: mull f2,f0 ! 421: addd 0x04000000,-20(fp) ; nx = nx + 64 in exponent field ! 422: mull f2,-12(fp) ! 423: L6: ! 424: movd -20(fp),-40(fp) ! 425: movl f0,16(fp) ! 426: movd 20(fp),r4 ! 427: movd r4,r5 ! 428: andd r7,r5 ; exponent of new y ! 429: jump L10 ! 430: ; ! 431: ; x is NaN or INF, return x-x ! 432: ; ! 433: L1: ! 434: movl 8(fp),f0 ! 435: subl f0,f0 ; if x is INF, then INF-INF is NaN ! 436: ret 0 ! 437: L64: .double 0x0,0x43f00000 ; L64 = 2**64 ! 438: LTINY: .double 0x0,0x04000000 ; LTINY = 2**-959
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.