Annotation of researchv9/libc/sun/Faddd.s, revision 1.1

1.1     ! root        1:        .data
        !             2:        .asciz  "@(#)Faddd.s 1.1 86/02/03 Copyr 1985 Sun Micro"
        !             3:        .even
        !             4:        .text
        !             5: 
        !             6: |      Copyright (c) 1985 by Sun Microsystems, Inc.
        !             7: 
        !             8: #include "fpcrtdefs.h"
        !             9: 
        !            10: /*
        !            11:  *     double-precision floating math run-time support
        !            12:  *
        !            13:  *     copyright 1981, 1982 Richard E. James III
        !            14:  *     translated to SUN idiom 10/11 March 1983 rt
        !            15:  *     parameter passing re-done 22 July 1983 rt
        !            16:  */
        !            17: 
        !            18: ARG2PTR = a0
        !            19: 
        !            20: /*
        !            21:  * extract exponents from two double-precision numbers.
        !            22:  *
        !            23:  * input:
        !            24:  *     d0/d1 one operand
        !            25:  *     d2/d3 other operand
        !            26:  *
        !            27:  * output:
        !            28:  *     d0/d1 mantissa, waiting for hidden bit to be turned on
        !            29:  *     d2/d3 other mantissa, likewise
        !            30:  *     d6      exponent from d2/d3
        !            31:  *     d7      exponent for d0/d1
        !            32:  *
        !            33:  * destroys d4
        !            34:  */
        !            35: 
        !            36: ENTER(d_exte)
        !            37:        moveq   #11,d4  | size of exponent
        !            38:        roll    d4,d0
        !            39:        roll    d4,d2
        !            40:        roll    d4,d1
        !            41:        roll    d4,d3
        !            42:        movl    #0x7ff,d6
        !            43:        movl    d6,d7
        !            44:        andl    d2,d6
        !            45:        eorl    d6,d2
        !            46:        movl    d7,d4
        !            47:        andl    d3,d4
        !            48:        eorl    d4,d3
        !            49:        lsrl    #1,d2
        !            50:        orl     d4,d2
        !            51:        | end transformation of larger
        !            52:        movl    d7,d4
        !            53:        andl    d0,d7
        !            54:        eorl    d7,d0
        !            55:        andl    d1,d4
        !            56:        eorl    d4,d1
        !            57:        lsrl    #1,d0
        !            58:        orl     d4,d0
        !            59:        | end transformation of smaller
        !            60:        rts
        !            61: 
        !            62: /*
        !            63:  *     ieee double floating compare
        !            64:  *     copyright 1981, Richard E. James III
        !            65:  *     translated to SUN idiom 30 March 1983 rt
        !            66:  */
        !            67: 
        !            68: /*
        !            69:  *     entry conditions:
        !            70:  *         first argument in d0/d1
        !            71:  *         second argument on stack
        !            72:  *     exit conditions:
        !            73:  *         result in cc -- carry flag set if either a NAN
        !            74:  *     problems:
        !            75:  *         unordered cases (e.e.: projective infinities and NANs)
        !            76:  *         produce random results.
        !            77:  *         A NAN, however, does compare not equal to anything.
        !            78:  *
        !            79:  *     register conventions:
        !            80:  *         d0/d1       first operand
        !            81:  *         d2/d3       second operand
        !            82:  *         d4          scratch
        !            83:  */
        !            84:        SAVEMASK = 0x3800       | registers d2-d4
        !            85:        RESTMASK = 0x1c
        !            86:        NSAVED   = 3*4          | 6 registers * sizeof(register)
        !            87:        CODE     = NSAVED
        !            88: 
        !            89: RTENTRY(Fcmpd)
        !            90:        subqw   #2,sp   | save room for result
        !            91: |      save registers and load operands into registers
        !            92:        moveml  #SAVEMASK,sp@-
        !            93:        movl    ARG2PTR@+,d2
        !            94:        movl    ARG2PTR@ ,d3
        !            95:        | we are now set up.
        !            96:        movl    d2,d4
        !            97:        andl    d0,d4           | compare signs
        !            98:        bpls    nbothmi
        !            99:        exg     d0,d2           | both minus
        !           100:        exg     d1,d3
        !           101: nbothmi:cmpl   d2,d0           | main compare
        !           102:        bnes    gotcmp          | got the answer
        !           103:        movl    d1,d4
        !           104:        subl    d3,d4           | compare lowers
        !           105:        beqs    gotcmp          | entirely equal
        !           106:        roxrl   #1,d4
        !           107:        andb    #0xa,cc         | clear z, in case differ by 1 ulp
        !           108: gotcmp:        andb    #0xe,cc         | clear carry
        !           109:         bgts    1f
        !           110:         blts    2f
        !           111:         movw    #FEQ,sp@(CODE)
        !           112:         bras    3f
        !           113: 1:
        !           114:         movw    #FGT,sp@(CODE)
        !           115:         bras    3f
        !           116: 2:
        !           117:         movw    #FLT,sp@(CODE)
        !           118: 3:
        !           119:        lsll    #1,d0
        !           120:        lsll    #1,d2
        !           121:        cmpl    d2,d0
        !           122:        bccs    4$
        !           123:        exg     d0,d2           | find larger in magnitude
        !           124: 4$:    cmpl    #0xffe00000,d0
        !           125:        blss    6$              | no nan
        !           126:        movw    #FUN,sp@(CODE)  | c, nz
        !           127:        bras    8$              | one was a nan
        !           128: 6$:    orl     d1,d0
        !           129:        orl     d2,d0
        !           130:        orl     d3,d0
        !           131:        bnes    8$
        !           132:        movw    #FEQ,sp@(CODE)  | -0 == 0
        !           133:        | done, now go
        !           134: 8$:    moveml  sp@+,#RESTMASK  | put back saved registers
        !           135:        movw    sp@+,cc         | install condition code
        !           136:        RET
        !           137: 
        !           138: 
        !           139: /*
        !           140:  *     ieee double floating add
        !           141:  *     copyright 1981, Richard E. James III
        !           142:  *     translated to SUN idiom 10 March 1983 rt
        !           143:  */
        !           144: 
        !           145: /*
        !           146:  *     entry conditions:
        !           147:  *         first argument in d0/d1
        !           148:  *         second argument on stack
        !           149:  *     exit conditions:
        !           150:  *         result (8 bytes) in d0/d1
        !           151:  *
        !           152:  *     register conventions:
        !           153:  *         d0/d1       smaller operand (d0=most significant)
        !           154:  *         d2/d3       larger operand
        !           155:  *         d4          11 or mask of 11 bits
        !           156:  *         d5          signs: sign of .w = sign of answer
        !           157:  *                            sign of .b = comparison of signs
        !           158:  *         d6          exponent of larger
        !           159:  *         d7          exponent of smaller
        !           160:  */
        !           161:        SAVEMASK = 0x3f00       | registers d2-d7
        !           162:        RESTMASK = 0xfc
        !           163:        NSAVED   = 6*4          | 6 registers * sizeof(register)
        !           164: 
        !           165: RTENTRY(Fsubd)
        !           166: |      save registers and load operands into registers
        !           167:        moveml  #SAVEMASK,sp@-  | registers d2-d7
        !           168:        movl    ARG2PTR@+,d2
        !           169:        movl    ARG2PTR@ ,d3
        !           170:        bchg    #31,d2
        !           171:        jra     adding
        !           172: RTENTRY(Faddd)
        !           173: |      save registers and load operands into registers
        !           174:        moveml  #SAVEMASK,sp@-  | registers d2-d7
        !           175:        movl    ARG2PTR@+,d2
        !           176:        movl    ARG2PTR@ ,d3
        !           177: adding:
        !           178:        | extract signs
        !           179:        asll    #1,d0   | sign ->c
        !           180:        scs     d4      | c -> d4
        !           181:        asll    #1,d2
        !           182:        scs     d5
        !           183:        | compare and exchange to put larger in d0/d1
        !           184:        cmpl    d2,d0
        !           185:        blss    1$
        !           186:        exg     d0,d2
        !           187:        exg     d1,d3
        !           188:        exg     d4,d5
        !           189: 1$:    extw    d5      | sign of larger
        !           190:        eorb    d4,d5   | comparison of signs
        !           191:        | extract exponents
        !           192:        jbsr    d_exte  | larger ->d2/d3,d6; smaller ->d0/d1,d7
        !           193:        tstw    d7
        !           194:        bnes    2$      | not zero or denormalized
        !           195:        | here, smaller is zero or is denormalized
        !           196:        movl    d0,d4
        !           197:        orl     d1,d4
        !           198:        jeq     signofzero | if smaller == 0 use larger
        !           199:        | (sign of 0-0 unpredictable)
        !           200:        lsll    #1,d1
        !           201:        roxll   #1,d0
        !           202:        tstw    d6      | larger exp
        !           203:        bnes    3$      | not gradual underflow
        !           204:        lsll    #1,d3
        !           205:        roxll   #1,d2
        !           206:        bras    addorsub | both gradual-underflow, no hidden or align needed
        !           207: 2$:    bset    #31,d0  | add hidden bit
        !           208: 3$:    cmpw    #0x7ff,d6
        !           209:        jeq     a_ovfl  | inf/nan
        !           210:        bset    #31,d2
        !           211:        | align smaller
        !           212:        | shift-by-eight loop
        !           213:        subw    d6,d7
        !           214:        negw    d7      | d7 = difference of exponents
        !           215:        cmpw    #16,d7
        !           216:        jge     rsge16  | Branch if shift of 16 or more.
        !           217: rs015:                 | Right shift 0..15.
        !           218:        subqw   #8,d7
        !           219:        blts    5$      | exit loop when difference <8
        !           220:        
        !           221:        tstb    d1
        !           222:        beqs    99$     | Branch if no bits to lose in shift.
        !           223:        bset    #8,d1   | Turn on the sticky bit if any bits will be lost.
        !           224: 99$:
        !           225:        movb    d0,d1   | shift eight bits down
        !           226:        rorl    #8,d1
        !           227:        lsrl    #8,d0
        !           228:        bras    rs015
        !           229: 5$:    addqw   #7,d7
        !           230:        bmis    addorsub
        !           231:        tstb    d1
        !           232:        beqs    98$
        !           233:        bset    #8,d1   | Turn on sticky bit.
        !           234: 98$:
        !           235: 6$:    lsrl    #1,d0
        !           236:        roxrl   #1,d1
        !           237:        dbra    d7,6$   | final  part of alignment
        !           238: addorsub:
        !           239:        | decide whether to add or subtract
        !           240:        tstb    d5      | compare signs
        !           241:        bmis    diff
        !           242:        | add them
        !           243:        addl    d1,d3   | sum
        !           244:        addxl   d0,d2
        !           245:        bccs    endas   | no c, ok
        !           246:        roxrl   #1,d2
        !           247:        roxrl   #1,d3
        !           248:        addqw   #1,d6
        !           249:        cmpw    #0x7ff,d6
        !           250:        blts    endas   | no overflow
        !           251:        jra     a_geninf
        !           252:        
        !           253: rsge16:                        | Right shift 16 or more.
        !           254:        cmpw    #32,d7
        !           255:        blts    rs1631  | Branch if shift is 16..31.
        !           256:        cmpw    #64,d7
        !           257:        blts    rs3263  | Branch if shift is 32..63.
        !           258:        clrl    d0      | Top will be zero.
        !           259:        moveq   #1,d1   | Bottom will be sticky.
        !           260:        bras    addorsub
        !           261: rs3263:                        | Shift 32.
        !           262:        tstl    d1
        !           263:        beqs    1$
        !           264:        bset    #0,d0   | Sticky bit on.
        !           265: 1$:
        !           266:        movl    d0,d1
        !           267:        clrl    d0
        !           268:        subw    #32,d7
        !           269:        cmpw    #16,d7
        !           270:        blts    rs015   | Branch if shift < 16.
        !           271: rs1631:                        | Shift 16.
        !           272:        tstw    d1      
        !           273:        beq     2$      | Branch if no bits in D.
        !           274:        bset    #16,d1  | Turn on sticky bit in C.
        !           275: 2$:
        !           276:        clrw    d1      | d1 gets Cs,0.
        !           277:        movw    d0,d1   | d1 gets Cs,B.
        !           278:        swap    d1      | d1 gets B,Cs.
        !           279:        clrw    d0      | d0 gets A,0.
        !           280:        swap    d0      | d0 gets 0,A.
        !           281:        subw    #16,d7
        !           282:        jra     rs015
        !           283:        
        !           284: 
        !           285:                | subtract then
        !           286: diff:  subl    d1,d3   | subtract lowers
        !           287:        subxl   d0,d2   | subtract uppers
        !           288:        bccs    9$
        !           289:        | cancelled down into 2nd word, but got wrong sign
        !           290:        notw    d5      | flip result sign
        !           291:        negl    d3
        !           292:        negxl   d2      | negate value
        !           293: 9$:    bnes    subrenorm | Branch if result nonzero.
        !           294:        tstl    d3
        !           295:        bnes    subrenorm | Branch if result nonzero.
        !           296:        clrw    d5      | Exact zero result has positive sign.
        !           297: subrenorm:             | Renormalize result after cancellation.        
        !           298:        jbsr    d_norm  
        !           299:        | rejoin, round
        !           300: endas: jbsr    d_rcp   | round, check, and pack
        !           301: assgn: lslw    #1,d5   | get sign
        !           302:        roxrl   #1,d2   | put in sign
        !           303: 
        !           304:        | answer is now in d2/d3: put in d0/d1
        !           305:        movl    d2,d0
        !           306:        movl    d3,d1
        !           307: asexit:        | restore registers and split
        !           308:        moveml  sp@+,#RESTMASK
        !           309:        RET
        !           310: 
        !           311: | EXCEPTION CASES
        !           312: signofzero:            | Set up proper sign for exact zero.
        !           313:        tstb    d5
        !           314:        beqs    useln   | Branch if signs equal: either will do.
        !           315:        tstw    d6
        !           316:        bnes    useln   | Branch if not zero or subnormal.
        !           317:        tstl    d2
        !           318:        bnes    useln   | Branch if subnormal.
        !           319:        tstl    d3
        !           320:        bnes    useln   | Branch if subnormal.
        !           321:        clrw    d5      | Signs unequal so set positive.
        !           322: 
        !           323: useln: tstw    d6
        !           324:        beqs    usel    | Branch if subnormal: don't set i bit.
        !           325:        bset    #31,d2  | Set i bit of normal number. 
        !           326: usel:  jbsr    d_usel  | use the larger
        !           327:        bras    assgn
        !           328: 
        !           329: | larger exponent = 1-23
        !           330: a_ovfl:        movl    d2,d4   | larger mantissa
        !           331:        orl     d3,d4
        !           332:        bnes    usel    | larger = nan, use it
        !           333:        cmpw    d6,d7   | exps
        !           334:        bnes    usel    | larger=inf and smaller=number
        !           335:        | (need nan...)
        !           336:        tstb    d5      | comparison of signs
        !           337:        bpls    usel    | inf+inf=inf; inf-inf=nan
        !           338:        movl    #0x7ff00001,d0  | NAN
        !           339:        clrl    d1
        !           340:        bras asexit
        !           341: | result overflows
        !           342: a_geninf:
        !           343:        movl    #0xffe00000,d2
        !           344:        clrl    d3
        !           345:        bras    assgn
        !           346: 
        !           347: /*
        !           348:  * subroutine for unpacking one operand, and normalizing a denormalized number
        !           349:  * input:
        !           350:  *     d0/d1   number
        !           351:  * output:
        !           352:  *     d0/d1   mantissa
        !           353:  *     d7.w    exponent
        !           354:  *     z       on iff mantissa is zero_
        !           355:  *
        !           356:  * unchanged:
        !           357:  *     d4      bottom = 0xf77
        !           358:  */
        !           359: 
        !           360: unp:   movl    d0,d7   | start getting exp
        !           361:        andl    #0xfffff,d0     | clear out sign and exp
        !           362:        swap    d7
        !           363:        lsrw    #(16-1-11),d7
        !           364:        andw    d4,d7   | expondnt
        !           365:        bnes    3$      | normal number
        !           366:        | denormalized number or zero:
        !           367:        tstl    d0      | upper
        !           368:        bnes    1$
        !           369:        tstl    d1      | lower
        !           370:        beqs    3$      |zero
        !           371: 1$:    addqw   #1,d7
        !           372: 2$:    subql   #1,d7
        !           373:        lsll    #1,d1
        !           374:        roxll   #1,d0   | normalize
        !           375:        btst    #20,d0
        !           376:        beqs    2$      | loop until normalized
        !           377: 3$:    rts

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.