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) 06/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 44end: 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 72L1: 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; 78L2: 79 movl 4(sp),f0 ; logb(+inf)=+inf, logb(NaN)=NaN 80 ret 0 81; 82; x is 0 or subnormal 83; 84L3: 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; 102L5: 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) 129L1: addl f2,f0 ; f0 = x + s 130 subl f2,f0 ; f0 = f0 - s 131 ret 0 132itself: movl 4(sp),f0 133 ret 0 134L52: .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 199end: ret 0 200inof: bcs underflow ; negative int overflow if Carry bit is set 201overflow: 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 209underflow: 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 219zero: 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 226L19: ; 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 242end: ret 0 243L30: .double 0x0,0x3bf00000 ; floating point 2**-64 244L32: .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; 301L10: 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 319LOOP: 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 3341: 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 350fnad: 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 360final: 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 3711: 372 subl f2,f0 ; x = x - y 3732: 374 cmpqd 0,-40(fp) 375 beq 3f 376 divl -12(fp),f0 ; scale down the answer 3773: 378 movl f0,tos 379 xord r6,tos 380 movl tos,f0 381 movd -16(fp),r0 382 lfsr r0 ; restore the fsr 383 384end: 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; 391L2: 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 399L4: 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; 404L3: 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; 413L5: 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) 423L6: 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; 433L1: 434 movl 8(fp),f0 435 subl f0,f0 ; if x is INF, then INF-INF is NaN 436 ret 0 437L64: .double 0x0,0x43f00000 ; L64 = 2**64 438LTINY: .double 0x0,0x04000000 ; LTINY = 2**-959 439