.data .asciz "@(#)Fadds.s 1.1 86/02/03 Copyr 1985 Sun Micro" .even .text | Copyright (c) 1985 by Sun Microsystems, Inc. #include "fpcrtdefs.h" /* * ieee single floating run-time support * copyright 1981, Richard E. James III * translated to SUN idiom 14 March 1983 rt */ /* single floating addition and subtraction */ /* * entry conditions: * first argument in d0 * second argument in d1 * exit conditions: * result (4 bytes) in d0 * * register conventions: * d0 operand 1 * d1 operand 2/sum * d2 sign of operand 1 * d3 sign of operand 2 * d4 exponent of operand 1 * d5 exponent of operand 2 * d6 difference of exponents * d7 reserved for sticky */ SAVEMASK = 0x3f00 | registers d2-d7 RESTMASK = 0xfc NSAVED = 6*4 | 6 registers * sizeof(register) RTENTRY(Fsubs) bchg #31,d1 jra adding RTENTRY(Fadds) adding: | save registers and load operands into registers moveml #SAVEMASK,sp@- | registers d2-d7 | extract signs asll #1,d0 | sign ->c scs d2 | c -> d4 asll #1,d1 scs d3 | compare and exchange to put larger in d0 cmpl d1,d0 blss 1$ exg d0,d1 exg d2,d3 | extract exponents 1$: roll #8,d1 roll #8,d0 clrl d5 movb d1,d5 | larger exp clrw d4 movb d0,d4 | smaller exp bnes 3$ | not zero or denormalized | smaller is 0 or is denormalized tstl d0 | if smaller == 0 jeq signofzero | then use larger (sign of 0-0 unpredictable) tstb d5 | larger exponent bnes 4$ | not gu | both are denormalized cmpb d3,d2 | compare signs bnes 2$ addl d0,d1 addxb d1,d1 | incr exp to 1 if overflow jra asbuild 2$: subl d0,d1 | subtract jne asbuild jra cancel | neither is denormalized 3$: movb #1,d0 | clear exp and rorl #1,d0 4$: movb #1,d1 | ... clr hidden bit rorl #1,d1 cmpb #0xff,d5 jeq ovfl | inf or nan | align smaller movw d5,d6 subw d4,d6 | difference of exponents cmpw #16,d6 bges bigshift | Branch if shift 26 or more places. check8: cmpw #8,d6 blts shortshift | exit when <8 *s tstb d0 beqs shift8 | Branch if no bits to be lost. bset #8,d0 | Sticky bit on. shift8: subqw #8,d6 lsrl #8,d0 | align bra check8 | loop bigshift: cmpw #26,d6 bges greatshift | Branch if only sticky left. tstw d0 beqs 1$ bset #16,d0 | Set sticky bit. 1$: clrw d0 swap d0 subw #16,d6 bras check8 greatshift: moveq #1,d0 | Here's a sticky bit. bras addorsub shortshift: movb d0,d7 lsrl d6,d0 | finish align cmpw #2,d6 bges stickit | Branch if shift >=2 so whole byte sticky. andb #1,d7 | Shift = 0 or 1 so only lsb sticks. stickit: tstb d7 beqs addorsub | Branch if no bits to stick. bset #0,d0 | Set a sticky bit on. addorsub: cmpb d3,d2 | cmp signs bnes diff | decide whether to add or subtract | add them addl d0,d1 | sum bccs endas | no carry here roxrl #1,d1 | pull in overflow *s addqw #1,d5 cmpw #0xff,d5 blts endas | no ofl bras a_geninf signofzero: | Set proper sign of zero. cmpb d2,d3 beqs usel | If signs are equal, use d3. tstl d1 bnes usel | Branch if not zero. clrb d3 | Sign if positive otherwise. bras usel | subtract them diff: subl d0,d1 bmis endas | if normalized beqs cancel | result == 0 9$: asll #1,d1 | normalize dbmi d5,9$ | dec exponent subqw #1,d5 bgts endas | not gu beqs 10$ clrw d5 lsrl #1,d1 | grad und 10$: lsrl #1,d1 endas: | round (NOT FULLY STANDARD) addl #0x80,d1 | round bccs testeven | round did not cause mantissa to ofl roxrl #1,d1 addqw #1,d5 cmpw #0xff,d5 beqs a_geninf | round caused exp to overflow bras rebuild testeven: | Test if ambiguous case. tstb d1 bnes rebuild | Branch if not ambiguous. bclr #8,d1 | Force round to even. rebuild: | rebuild answer lsll #1,d1 | toss hidden usel: movb d5,d1 | insert exponent asbuild:rorl #8,d1 roxrb #1,d3 roxrl #1,d1 | apply sign | d1 now has answer movl d1,d0 asexit: moveml sp@+,#RESTMASK RET | EXCEPTION CASES ovfl: | largest exponent = 255 lsll #1,d1 tstl d1 | larger mantissa bnes usel | larger == nan cmpb d4,d5 | exps bnes usel | larger == inf | AFFINE MODE ASSUMED IN THIS IMPLEMENTATION cmpb d3,d2 | signs beqs usel | inf+inf = inf |gennan: movl #0x7f800001,d0 bras asexit | complete cancellation cancel: clrl d0 | result == 0 | need minus 0 for (-0)+(-0), round to -inf bras asexit | result overflows: a_geninf:movl #0xff,d1 bras asbuild /* * ieee single floating compare * copyright 1981, Richard E. James III * translated to SUN idiom 29 March 1983 rt */ /* * entry conditions: * first argument in d0 * second argument in d1 * exit conditions: * result in condition code * d0/d1 trashed * * register conventions: * d0 operand 1 * d1 operand 2 * d2 scratch */ NSAVED = 4 CODE = NSAVED RTENTRY(Fcmps) #ifdef PROF unlk a6 | don't get in the way of the cc. #endif subqw #2,sp | save space for condition code return movl d2,sp@- | save register movl d1,d2 andl d0,d2 | compare signs bpls 1$ exg d0,d1 | both minus 1$: cmpl d1,d0 | main compare bgts 1f blts 2f movw #FEQ,sp@(CODE) bras 3f 1: movw #FGT,sp@(CODE) bras 3f 2: movw #FLT,sp@(CODE) 3: lsll #1,d0 lsll #1,d1 cmpl d1,d0 bccs 2$ exg d0,d1 | find larger 2$: cmpl #0xff000000,d0 blss 3$ | nan movw #FUN,sp@(CODE) | c for unordered 3$: tstl d0 bnes 4$ movw #FEQ,sp@(CODE) | -0 == 0 | result is in sp@(CODE) 4$: | restore saved register and go movl sp@+,d2 rtr