Annotation of researchv9/libc/sun/Faddd.s, revision 1.1.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.